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, pluginName;
98 
99  if (name.contains("-"))
100  {
101  visName = name.section('-', 0, 0);
102  pluginName = name.section('-', 1, 1);
103  }
104  else
105  {
106  visName = name;
107  pluginName.clear();
108  }
109 
110  if (m_vis)
111  {
112  delete m_vis;
113  m_vis = nullptr;
114  }
115 
116  for (const VisFactory* pVisFactory = VisFactory::VisFactories();
117  pVisFactory; pVisFactory = pVisFactory->next())
118  {
119  if (pVisFactory->name() == visName)
120  {
121  m_vis = pVisFactory->create(this, pluginName);
125 
126  QMutexLocker locker(mutex());
127  prepare();
128 
129  break;
130  }
131  }
132 
133  // force an update
134  m_updateTimer->start(1000 / m_fps);
135 }
136 
137 // Caller holds mutex() lock
139 {
140  while (!m_nodes.empty())
141  delete m_nodes.takeLast();
142 }
143 
144 // This is called via : mythtv/libs/libmyth/output.cpp :: OutputListeners::dispatchVisual
145 // from : mythtv/libs/libmyth/audio/audiooutputbase.cpp :: AudioOutputBase::AddData
146 // Caller holds mutex() lock
147 void MainVisual::add(const void *buffer, unsigned long b_len, unsigned long timecode, int source_channels, int bits_per_sample)
148 {
149  unsigned long len = b_len;
150  short *l = nullptr, *r = nullptr;
151  bool s32le = false;
152 
153  // 24 bit samples are stored as s32le in the buffer.
154  // 32 bit samples are stored as float. Flag the difference.
155  if (bits_per_sample == 24)
156  {
157  s32le = true;
158  bits_per_sample = 32;
159  }
160 
161  // len is length of buffer in fully converted samples
162  len /= source_channels;
163  len /= (bits_per_sample / 8);
164 
165  if (len > m_samples)
166  len = m_samples;
167 
168  int cnt = len;
169 
170  if (source_channels == 2)
171  {
172  l = new short[len];
173  r = new short[len];
174 
175  if (bits_per_sample == 8)
176  stereo16_from_stereopcm8(l, r, (uchar *) buffer, cnt);
177  else if (bits_per_sample == 16)
178  stereo16_from_stereopcm16(l, r, (short *) buffer, cnt);
179  else if (s32le)
180  stereo16_from_stereopcm32(l, r, (int *) buffer, cnt);
181  else if (bits_per_sample == 32)
182  stereo16_from_stereopcmfloat(l, r, (float *) buffer, cnt);
183  else
184  len = 0;
185  }
186  else if (source_channels == 1)
187  {
188  l = new short[len];
189 
190  if (bits_per_sample == 8)
191  mono16_from_monopcm8(l, (uchar *) buffer, cnt);
192  else if (bits_per_sample == 16)
193  mono16_from_monopcm16(l, (short *) buffer, cnt);
194  else if (s32le)
195  mono16_from_monopcm32(l, (int *) buffer, cnt);
196  else if (bits_per_sample == 32)
197  mono16_from_monopcmfloat(l, (float *) buffer, cnt);
198  else
199  len = 0;
200  }
201  else
202  len = 0;
203 
204  m_nodes.append(new VisualNode(l, r, len, timecode));
205 }
206 
208 {
209  VisualNode *node = nullptr;
210  if (m_playing && gPlayer->getOutput())
211  {
212  QMutexLocker locker(mutex());
213  int64_t timestamp = gPlayer->getOutput()->GetAudiotime();
214  while (m_nodes.size() > 1)
215  {
216  if ((int64_t)m_nodes.first()->m_offset > timestamp)
217  break;
218 
219  if (m_vis)
220  m_vis->processUndisplayed(node);
221 
222  delete m_nodes.first();
223  m_nodes.removeFirst();
224  }
225 
226  if (!m_nodes.isEmpty())
227  node = m_nodes.first();
228  }
229 
230  bool stop = true;
231  if (m_vis)
232  stop = m_vis->process(node);
233 
234  if (m_vis && !stop)
235  {
236  QPainter p(&m_pixmap);
239  }
240 
241  if (m_playing && !stop)
242  m_updateTimer->start();
243 }
244 
245 void MainVisual::resize(const QSize &size)
246 {
247  m_pixmap = QPixmap(size);
249 
250  if (m_vis)
251  m_vis->resize(size);
252 }
253 
254 void MainVisual::customEvent(QEvent *event)
255 {
256  if ((event->type() == OutputEvent::Playing) ||
257  (event->type() == OutputEvent::Info) ||
258  (event->type() == OutputEvent::Buffering) ||
259  (event->type() == OutputEvent::Paused))
260  {
261  m_playing = true;
262  if (!m_updateTimer->isActive())
263  m_updateTimer->start();
264  }
265  else if ((event->type() == OutputEvent::Stopped) ||
266  (event->type() == OutputEvent::Error))
267  {
268  m_playing = false;
269  }
270 }
static Type Info
Definition: output.h:63
static void mono16_from_monopcm16(short *l, short *s, long cnt)
MusicPlayer * gPlayer
Definition: musicplayer.cpp:35
void stop(void)
Definition: mainvisual.cpp:70
MythUIVideo * m_visualizerVideo
Definition: mainvisual.h:64
static Type Error
Definition: output.h:66
static Type Playing
Definition: output.h:61
void SaveSetting(const QString &key, int newValue)
void customEvent(QEvent *) override
Definition: mainvisual.cpp:254
static const VisFactory * VisFactories()
Definition: visualize.h:110
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
const VisFactory * next() const
Definition: visualize.h:106
QList< VisualNode * > m_nodes
Definition: mainvisual.h:69
QPixmap m_pixmap
Definition: mainvisual.h:68
static Type Buffering
Definition: output.h:62
virtual int64_t GetAudiotime(void)=0
unsigned char r
Definition: ParseText.cpp:329
int m_currentVisualizer
Definition: mainvisual.h:66
MainVisual(MythUIVideo *visualizer)
Definition: mainvisual.cpp:35
virtual unsigned long getDesiredSamples(void)
Definition: visualize.h:93
QTimer * m_updateTimer
Definition: mainvisual.h:73
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:863
VisualBase * m_vis
Definition: mainvisual.h:67
Video widget, displays raw image data.
Definition: mythuivideo.h:14
void resize(const QSize &size)
Definition: mainvisual.cpp:245
const char * name
Definition: ParseText.cpp:328
void add(const void *, unsigned long, unsigned long, int, int) override
Definition: mainvisual.cpp:147
QStringList m_visualizers
Definition: mainvisual.h:65
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)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
static void stereo16_from_stereopcm8(short *l, short *r, uchar *c, long cnt)
QMutex * mutex()
Definition: visual.h:25
static void mono16_from_monopcm32(short *l, int *s, long cnt)
Definition: inlines.h:160
static void mono16_from_monopcm8(short *l, uchar *c, long cnt)
void prepare(void) override
Definition: mainvisual.cpp:138
virtual void resize(const QSize &size)=0
void UpdateFrame(MythImage *image)
Definition: mythuivideo.cpp:52
static void stereo16_from_stereopcm16(short *l, short *r, short *s, long cnt)
unsigned long m_samples
Definition: mainvisual.h:72
virtual bool draw(QPainter *, const QColor &)=0
bool m_playing
Definition: mainvisual.h:70
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:207
virtual ~MainVisual()
Definition: mainvisual.cpp:57
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