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 <algorithm>
9 #include <cmath>
10 #include <cstdio>
11 #include <iostream>
12 
13 // Qt
14 #include <QPainter>
15 
16 // MythTV
19 #include <libmythui/mythuivideo.h>
20 
21 // mythmusic
22 #include "constants.h"
23 #include "mainvisual.h"
24 #include "musicplayer.h"
25 #include "visualize.h"
26 
27 // fast inlines
28 #include "inlines.h"
29 
30 
32 // MainVisual
33 
35  : QObject(nullptr), m_visualizerVideo(visualizer)
36 {
37  setObjectName("MainVisual");
38 
39  for (const VisFactory* pVisFactory = VisFactory::VisFactories();
40  pVisFactory; pVisFactory = pVisFactory->next())
41  {
42  pVisFactory->plugins(&m_visualizers);
43  }
44  m_visualizers.sort();
45 
46  m_currentVisualizer = gCoreContext->GetNumSetting("MusicLastVisualizer", 0);
47 
48  resize(m_visualizerVideo->GetArea().size());
49 
50  m_updateTimer = new QTimer(this);
51  m_updateTimer->setInterval(1000 / m_fps);
52  m_updateTimer->setSingleShot(true);
54 }
55 
57 {
58  m_updateTimer->stop();
59  delete m_updateTimer;
60 
61  delete m_vis;
62 
63  while (!m_nodes.empty())
64  delete m_nodes.takeLast();
65 
66  gCoreContext->SaveSetting("MusicLastVisualizer", m_currentVisualizer);
67 }
68 
69 void MainVisual::stop(void)
70 {
71  m_updateTimer->stop();
72 
73  if (m_vis)
74  {
75  delete m_vis;
76  m_vis = nullptr;
77  }
78 }
79 
80 void MainVisual::setVisual(const QString &name)
81 {
82  m_updateTimer->stop();
83 
84  int index = m_visualizers.indexOf(name);
85 
86  if (index == -1)
87  {
88  LOG(VB_GENERAL, LOG_ERR, QString("MainVisual: visualizer %1 not found!").arg(name));
89  return;
90  }
91 
92  m_currentVisualizer = index;
93 
95 
96  QString visName;
97  QString 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,
148  std::chrono::milliseconds timecode,
149  int source_channels, int bits_per_sample)
150 {
151  unsigned long len = b_len;
152  short *l = nullptr;
153  short *r = nullptr;
154  bool s32le = false;
155 
156  // 24 bit samples are stored as s32le in the buffer.
157  // 32 bit samples are stored as float. Flag the difference.
158  if (bits_per_sample == 24)
159  {
160  s32le = true;
161  bits_per_sample = 32;
162  }
163 
164  // len is length of buffer in fully converted samples
165  len /= source_channels;
166  len /= (bits_per_sample / 8);
167 
168  len = std::min(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  {
205  len = 0;
206  }
207 
208  m_nodes.append(new VisualNode(l, r, len, timecode));
209 }
210 
212 {
213  VisualNode *node = nullptr;
214  if (m_playing && gPlayer->getOutput())
215  {
216  QMutexLocker locker(mutex());
217  std::chrono::milliseconds timestamp = gPlayer->getOutput()->GetAudiotime();
218  while (m_nodes.size() > 1)
219  {
220  // LOG(VB_PLAYBACK, LOG_DEBUG,
221  // QString("\tMV %1 first > %2 timestamp").
222  // arg(m_nodes.first()->m_offset.count()).arg(timestamp.count()));
223  if (m_nodes.first()->m_offset >= timestamp + 5s)
224  {
225  // REW seek: drain buffer and start over
226  }
227  else if (m_nodes.first()->m_offset > timestamp)
228  {
229  break; // at current time
230  }
231 
232  if (m_vis)
233  m_vis->processUndisplayed(m_nodes.first());
234 
235  delete m_nodes.first();
236  m_nodes.removeFirst();
237  }
238 
239  if (!m_nodes.isEmpty())
240  node = m_nodes.first();
241  }
242 
243  bool stop = true;
244  if (m_vis)
245  stop = m_vis->process(node);
246 
247  if (m_vis && !stop)
248  {
249  QPainter p(&m_pixmap);
252  }
253 
254  if (m_playing && !stop)
255  m_updateTimer->start();
256 }
257 
258 void MainVisual::resize(const QSize size)
259 {
260  m_pixmap = QPixmap(size);
262 
263  if (m_vis)
264  m_vis->resize(size);
265 }
266 
267 void MainVisual::customEvent(QEvent *event)
268 {
269  if ((event->type() == OutputEvent::kPlaying) ||
270  (event->type() == OutputEvent::kInfo) ||
271  (event->type() == OutputEvent::kBuffering) ||
272  (event->type() == OutputEvent::kPaused))
273  {
274  m_playing = true;
275  if (!m_updateTimer->isActive())
276  m_updateTimer->start();
277  }
278  else if ((event->type() == OutputEvent::kStopped) ||
279  (event->type() == OutputEvent::kError))
280  {
281  m_playing = false;
282  }
283 }
mono16_from_monopcm8
static void mono16_from_monopcm8(short *l, const uchar *c, long cnt)
Definition: videovisualdefs.h:142
MusicPlayer::getOutput
AudioOutput * getOutput(void)
Definition: musicplayer.h:128
MainVisual::~MainVisual
~MainVisual() override
Definition: mainvisual.cpp:56
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:38
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:101
mono16_from_monopcmfloat
static void mono16_from_monopcmfloat(short *l, float *s, long cnt)
Definition: inlines.h:167
mythuivideo.h
VisualNode
Definition: videovisual.h:24
VisualBase::getDesiredSamples
virtual unsigned long getDesiredSamples(void)
Definition: visualize.h:83
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MainVisual::customEvent
void customEvent(QEvent *event) override
Definition: mainvisual.cpp:267
MainVisual::m_fps
int m_fps
Definition: mainvisual.h:73
MainVisual::prepare
void prepare(void) override
Definition: mainvisual.cpp:138
MainVisual::setVisual
void setVisual(const QString &name)
Definition: mainvisual.cpp:80
MythUIType::GetArea
virtual MythRect GetArea(void) const
If the object has a minimum area defined, return it, other wise return the default area.
Definition: mythuitype.cpp:885
MainVisual::m_samples
unsigned long m_samples
Definition: mainvisual.h:74
MainVisual::m_playing
bool m_playing
Definition: mainvisual.h:72
VisualBase::resize
virtual void resize(const QSize &size)=0
OutputEvent::kStopped
static const Type kStopped
Definition: output.h:67
mythlogging.h
mono16_from_monopcm16
static void mono16_from_monopcm16(short *l, const short *s, long cnt)
Definition: videovisualdefs.h:171
hardwareprofile.config.p
p
Definition: config.py:33
OutputEvent::kInfo
static const Type kInfo
Definition: output.h:65
stereo16_from_stereopcmfloat
static void stereo16_from_stereopcmfloat(short *l, short *r, float *s, long cnt)
Definition: inlines.h:94
MythTV::Visual::mutex
QMutex * mutex()
Definition: visual.h:26
VisFactory
Definition: visualize.h:91
stereo16_from_stereopcm16
static void stereo16_from_stereopcm16(short *l, short *r, const short *s, long cnt)
Definition: videovisualdefs.h:104
MainVisual::resize
void resize(QSize size)
Definition: mainvisual.cpp:258
VisualBase::getDesiredFPS
virtual int getDesiredFPS(void)
Definition: visualize.h:81
MainVisual::timeout
void timeout()
Definition: mainvisual.cpp:211
VisualBase::draw
virtual bool draw(QPainter *, const QColor &)=0
inlines.h
visualize.h
VisFactory::VisFactories
static const VisFactory * VisFactories()
Definition: visualize.h:102
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MythUIVideo::UpdateFrame
void UpdateFrame(MythImage *image)
Definition: mythuivideo.cpp:49
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:918
AudioOutput::GetAudiotime
virtual std::chrono::milliseconds GetAudiotime(void)=0
VisualBase::process
virtual bool process(VisualNode *node)=0
MainVisual::m_visualizerVideo
MythUIVideo * m_visualizerVideo
Definition: mainvisual.h:66
OutputEvent::kPlaying
static const Type kPlaying
Definition: output.h:63
MainVisual::stop
void stop(void)
Definition: mainvisual.cpp:69
VisualBase::processUndisplayed
virtual bool processUndisplayed(VisualNode *)
Definition: visualize.h:73
stereo16_from_stereopcm8
static void stereo16_from_stereopcm8(short *l, short *r, const uchar *c, long cnt)
Definition: videovisualdefs.h:66
MainVisual::m_currentVisualizer
int m_currentVisualizer
Definition: mainvisual.h:68
mono16_from_monopcm32
static void mono16_from_monopcm32(short *l, int *s, long cnt)
Definition: inlines.h:158
MythUIVideo
Video widget, displays raw image data.
Definition: mythuivideo.h:14
mythcorecontext.h
OutputEvent::kError
static const Type kError
Definition: output.h:68
constants.h
mainvisual.h
stereo16_from_stereopcm32
static void stereo16_from_stereopcm32(short *l, short *r, int *s, long cnt)
Definition: inlines.h:82
MythUIVideo::GetBackgroundColor
QColor GetBackgroundColor(void)
Definition: mythuivideo.h:23
MainVisual::add
void add(const void *buffer, unsigned long b_len, std::chrono::milliseconds timecode, int source_channel, int bits_per_sample) override
Definition: mainvisual.cpp:147
OutputEvent::kBuffering
static const Type kBuffering
Definition: output.h:64
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:887
MainVisual::m_updateTimer
QTimer * m_updateTimer
Definition: mainvisual.h:75
MainVisual::m_nodes
QList< VisualNode * > m_nodes
Definition: mainvisual.h:71
VisFactory::next
const VisFactory * next() const
Definition: visualize.h:98
MainVisual::m_visualizers
QStringList m_visualizers
Definition: mainvisual.h:67
MainVisual::m_vis
VisualBase * m_vis
Definition: mainvisual.h:69
MainVisual::m_pixmap
QPixmap m_pixmap
Definition: mainvisual.h:70
MainVisual::MainVisual
MainVisual(MythUIVideo *visualizer)
Definition: mainvisual.cpp:34
OutputEvent::kPaused
static const Type kPaused
Definition: output.h:66
musicplayer.h