MythTV  master
mainvisual.cpp
Go to the documentation of this file.
1 // Copyright (c) 2000-2001 Brad Hughes <bhughes@trolltech.com>
2 //
3 // Use, modification and distribution is allowed without limitation,
4 // warranty, or liability of any kind.
5 //
6 
7 // C
8 #include <cmath>
9 #include <cstdio>
10 
11 // C++
12 #include <algorithm>
13 #include <iostream>
14 using namespace std;
15 
16 // Qt
17 #include <QPainter>
18 
19 // mythtv
20 #include <mythuivideo.h>
21 
22 // mythmusic
23 #include "visualize.h"
24 #include "mainvisual.h"
25 #include "constants.h"
26 #include "musicplayer.h"
27 
28 // fast inlines
29 #include "inlines.h"
30 
31 
33 // MainVisual
34 
36  : QObject(nullptr), m_visualizerVideo(visualizer)
37 {
38  setObjectName("MainVisual");
39 
40  for (const VisFactory* pVisFactory = VisFactory::VisFactories();
41  pVisFactory; pVisFactory = pVisFactory->next())
42  {
43  pVisFactory->plugins(&m_visualizers);
44  }
45  m_visualizers.sort();
46 
47  m_currentVisualizer = gCoreContext->GetNumSetting("MusicLastVisualizer", 0);
48 
49  resize(m_visualizerVideo->GetArea().size());
50 
51  m_updateTimer = new QTimer(this);
52  m_updateTimer->setInterval(1000 / m_fps);
53  m_updateTimer->setSingleShot(true);
54  connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(timeout()));
55 }
56 
58 {
59  m_updateTimer->stop();
60  delete m_updateTimer;
61 
62  delete m_vis;
63 
64  while (!m_nodes.empty())
65  delete m_nodes.takeLast();
66 
67  gCoreContext->SaveSetting("MusicLastVisualizer", m_currentVisualizer);
68 }
69 
70 void MainVisual::stop(void)
71 {
72  m_updateTimer->stop();
73 
74  if (m_vis)
75  {
76  delete m_vis;
77  m_vis = nullptr;
78  }
79 }
80 
81 void MainVisual::setVisual(const QString &name)
82 {
83  m_updateTimer->stop();
84 
85  int index = m_visualizers.indexOf(name);
86 
87  if (index == -1)
88  {
89  LOG(VB_GENERAL, LOG_ERR, QString("MainVisual: visualizer %1 not found!").arg(name));
90  return;
91  }
92 
93  m_currentVisualizer = index;
94 
96 
97  QString visName;
98  QString pluginName;
99 
100  if (name.contains("-"))
101  {
102  visName = name.section('-', 0, 0);
103  pluginName = name.section('-', 1, 1);
104  }
105  else
106  {
107  visName = name;
108  pluginName.clear();
109  }
110 
111  if (m_vis)
112  {
113  delete m_vis;
114  m_vis = nullptr;
115  }
116 
117  for (const VisFactory* pVisFactory = VisFactory::VisFactories();
118  pVisFactory; pVisFactory = pVisFactory->next())
119  {
120  if (pVisFactory->name() == visName)
121  {
122  m_vis = pVisFactory->create(this, pluginName);
126 
127  QMutexLocker locker(mutex());
128  prepare();
129 
130  break;
131  }
132  }
133 
134  // force an update
135  m_updateTimer->start(1000 / m_fps);
136 }
137 
138 // Caller holds mutex() lock
140 {
141  while (!m_nodes.empty())
142  delete m_nodes.takeLast();
143 }
144 
145 // This is called via : mythtv/libs/libmyth/output.cpp :: OutputListeners::dispatchVisual
146 // from : mythtv/libs/libmyth/audio/audiooutputbase.cpp :: AudioOutputBase::AddData
147 // Caller holds mutex() lock
148 void MainVisual::add(const void *buffer, unsigned long b_len, unsigned long timecode, int source_channels, int bits_per_sample)
149 {
150  unsigned long len = b_len;
151  short *l = nullptr;
152  short *r = nullptr;
153  bool s32le = false;
154 
155  // 24 bit samples are stored as s32le in the buffer.
156  // 32 bit samples are stored as float. Flag the difference.
157  if (bits_per_sample == 24)
158  {
159  s32le = true;
160  bits_per_sample = 32;
161  }
162 
163  // len is length of buffer in fully converted samples
164  len /= source_channels;
165  len /= (bits_per_sample / 8);
166 
167  if (len > m_samples)
168  len = m_samples;
169 
170  int cnt = len;
171 
172  if (source_channels == 2)
173  {
174  l = new short[len];
175  r = new short[len];
176 
177  if (bits_per_sample == 8)
178  stereo16_from_stereopcm8(l, r, (uchar *) buffer, cnt);
179  else if (bits_per_sample == 16)
180  stereo16_from_stereopcm16(l, r, (short *) buffer, cnt);
181  else if (s32le)
182  stereo16_from_stereopcm32(l, r, (int *) buffer, cnt);
183  else if (bits_per_sample == 32)
184  stereo16_from_stereopcmfloat(l, r, (float *) buffer, cnt);
185  else
186  len = 0;
187  }
188  else if (source_channels == 1)
189  {
190  l = new short[len];
191 
192  if (bits_per_sample == 8)
193  mono16_from_monopcm8(l, (uchar *) buffer, cnt);
194  else if (bits_per_sample == 16)
195  mono16_from_monopcm16(l, (short *) buffer, cnt);
196  else if (s32le)
197  mono16_from_monopcm32(l, (int *) buffer, cnt);
198  else if (bits_per_sample == 32)
199  mono16_from_monopcmfloat(l, (float *) buffer, cnt);
200  else
201  len = 0;
202  }
203  else
204  len = 0;
205 
206  m_nodes.append(new VisualNode(l, r, len, timecode));
207 }
208 
210 {
211  VisualNode *node = nullptr;
212  if (m_playing && gPlayer->getOutput())
213  {
214  QMutexLocker locker(mutex());
215  int64_t timestamp = gPlayer->getOutput()->GetAudiotime();
216  while (m_nodes.size() > 1)
217  {
218  if ((int64_t)m_nodes.first()->m_offset > timestamp)
219  break;
220 
221  if (m_vis)
222  m_vis->processUndisplayed(node);
223 
224  delete m_nodes.first();
225  m_nodes.removeFirst();
226  }
227 
228  if (!m_nodes.isEmpty())
229  node = m_nodes.first();
230  }
231 
232  bool stop = true;
233  if (m_vis)
234  stop = m_vis->process(node);
235 
236  if (m_vis && !stop)
237  {
238  QPainter p(&m_pixmap);
241  }
242 
243  if (m_playing && !stop)
244  m_updateTimer->start();
245 }
246 
247 void MainVisual::resize(const QSize &size)
248 {
249  m_pixmap = QPixmap(size);
251 
252  if (m_vis)
253  m_vis->resize(size);
254 }
255 
256 void MainVisual::customEvent(QEvent *event)
257 {
258  if ((event->type() == OutputEvent::Playing) ||
259  (event->type() == OutputEvent::Info) ||
260  (event->type() == OutputEvent::Buffering) ||
261  (event->type() == OutputEvent::Paused))
262  {
263  m_playing = true;
264  if (!m_updateTimer->isActive())
265  m_updateTimer->start();
266  }
267  else if ((event->type() == OutputEvent::Stopped) ||
268  (event->type() == OutputEvent::Error))
269  {
270  m_playing = false;
271  }
272 }
static Type Info
Definition: output.h:63
MusicPlayer * gPlayer
Definition: musicplayer.cpp:35
void stop(void)
Definition: mainvisual.cpp:70
MythUIVideo * m_visualizerVideo
Definition: mainvisual.h:65
static Type Error
Definition: output.h:66
static Type Playing
Definition: output.h:61
void SaveSetting(const QString &key, int newValue)
static const VisFactory * VisFactories()
Definition: visualize.h:110
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void add(const void *buffer, unsigned long b_len, unsigned long timecode, int source_channel, int bits_per_sample) override
Definition: mainvisual.cpp:148
const VisFactory * next() const
Definition: visualize.h:106
QList< VisualNode * > m_nodes
Definition: mainvisual.h:70
QPixmap m_pixmap
Definition: mainvisual.h:69
static Type Buffering
Definition: output.h:62
virtual int64_t GetAudiotime(void)=0
int m_currentVisualizer
Definition: mainvisual.h:67
~MainVisual() override
Definition: mainvisual.cpp:57
MainVisual(MythUIVideo *visualizer)
Definition: mainvisual.cpp:35
virtual unsigned long getDesiredSamples(void)
Definition: visualize.h:93
QTimer * m_updateTimer
Definition: mainvisual.h:74
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:864
VisualBase * m_vis
Definition: mainvisual.h:68
static void mono16_from_monopcm8(short *l, const uchar *c, long cnt)
Video widget, displays raw image data.
Definition: mythuivideo.h:14
void resize(const QSize &size)
Definition: mainvisual.cpp:247
QStringList m_visualizers
Definition: mainvisual.h:66
static void stereo16_from_stereopcmfloat(short *l, short *r, float *s, long cnt)
Definition: inlines.h:96
static void stereo16_from_stereopcm32(short *l, short *r, int *s, long cnt)
Definition: inlines.h:84
int GetNumSetting(const QString &key, int defaultval=0)
static void stereo16_from_stereopcm8(short *l, short *r, const uchar *c, long cnt)
static void stereo16_from_stereopcm16(short *l, short *r, const short *s, long cnt)
QMutex * mutex()
Definition: visual.h:25
static void mono16_from_monopcm32(short *l, int *s, long cnt)
Definition: inlines.h:160
void prepare(void) override
Definition: mainvisual.cpp:139
virtual void resize(const QSize &size)=0
void UpdateFrame(MythImage *image)
Definition: mythuivideo.cpp:52
static void mono16_from_monopcm16(short *l, const short *s, long cnt)
unsigned long m_samples
Definition: mainvisual.h:73
virtual bool draw(QPainter *, const QColor &)=0
void customEvent(QEvent *event) override
Definition: mainvisual.cpp:256
bool m_playing
Definition: mainvisual.h:71
virtual int getDesiredFPS(void)
Definition: visualize.h:91
AudioOutput * getOutput(void)
Definition: musicplayer.h:117
virtual bool process(VisualNode *node)=0
static void mono16_from_monopcmfloat(short *l, float *s, long cnt)
Definition: inlines.h:169
void setVisual(const QString &name)
Definition: mainvisual.cpp:81
void timeout()
Definition: mainvisual.cpp:209
static Type Paused
Definition: output.h:64
virtual bool processUndisplayed(VisualNode *)
Definition: visualize.h:83
static Type Stopped
Definition: output.h:65
QColor GetBackgroundColor(void)
Definition: mythuivideo.h:23
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:41