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
17 #include <libmythui/mythuivideo.h>
18 
19 // mythmusic
20 #include "constants.h"
21 #include "mainvisual.h"
22 #include "musicplayer.h"
23 #include "visualize.h"
24 
25 // fast inlines
26 #include "inlines.h"
27 
28 
30 // MainVisual
31 
33  : QObject(nullptr), m_visualizerVideo(visualizer)
34 {
35  setObjectName("MainVisual");
36 
37  for (const VisFactory* pVisFactory = VisFactory::VisFactories();
38  pVisFactory; pVisFactory = pVisFactory->next())
39  {
40  pVisFactory->plugins(&m_visualizers);
41  }
42  m_visualizers.sort();
43 
44  m_currentVisualizer = gCoreContext->GetNumSetting("MusicLastVisualizer", 0);
45 
46  resize(m_visualizerVideo->GetArea().size());
47 
48  m_updateTimer = new QTimer(this);
49  m_updateTimer->setInterval(1000 / m_fps);
50  m_updateTimer->setSingleShot(true);
52 }
53 
55 {
56  m_updateTimer->stop();
57  delete m_updateTimer;
58 
59  delete m_vis;
60 
61  while (!m_nodes.empty())
62  delete m_nodes.takeLast();
63 
64  gCoreContext->SaveSetting("MusicLastVisualizer", m_currentVisualizer);
65 }
66 
67 void MainVisual::stop(void)
68 {
69  m_updateTimer->stop();
70 
71  if (m_vis)
72  {
73  delete m_vis;
74  m_vis = nullptr;
75  }
76 }
77 
78 void MainVisual::setVisual(const QString &name)
79 {
80  m_updateTimer->stop();
81 
82  int index = m_visualizers.indexOf(name);
83 
84  if (index == -1)
85  {
86  LOG(VB_GENERAL, LOG_ERR, QString("MainVisual: visualizer %1 not found!").arg(name));
87  return;
88  }
89 
90  m_currentVisualizer = index;
91 
93 
94  QString visName;
95  QString pluginName;
96 
97  if (name.contains("-"))
98  {
99  visName = name.section('-', 0, 0);
100  pluginName = name.section('-', 1, 1);
101  }
102  else
103  {
104  visName = name;
105  pluginName.clear();
106  }
107 
108  if (m_vis)
109  {
110  delete m_vis;
111  m_vis = nullptr;
112  }
113 
114  for (const VisFactory* pVisFactory = VisFactory::VisFactories();
115  pVisFactory; pVisFactory = pVisFactory->next())
116  {
117  if (pVisFactory->name() == visName)
118  {
119  m_vis = pVisFactory->create(this, pluginName);
123 
124  QMutexLocker locker(mutex());
125  prepare();
126 
127  break;
128  }
129  }
130 
131  // force an update
132  m_updateTimer->start(1000 / m_fps);
133 }
134 
135 // Caller holds mutex() lock
137 {
138  while (!m_nodes.empty())
139  delete m_nodes.takeLast();
140 }
141 
142 // This is called via : mythtv/libs/libmyth/output.cpp :: OutputListeners::dispatchVisual
143 // from : mythtv/libs/libmyth/audio/audiooutputbase.cpp :: AudioOutputBase::AddData
144 // Caller holds mutex() lock
145 void MainVisual::add(const void *buffer, unsigned long b_len,
146  std::chrono::milliseconds timecode,
147  int source_channels, int bits_per_sample)
148 {
149  unsigned long len = b_len;
150  short *l = nullptr;
151  short *r = nullptr;
152  bool s32le = false;
153 
154  // 24 bit samples are stored as s32le in the buffer.
155  // 32 bit samples are stored as float. Flag the difference.
156  if (bits_per_sample == 24)
157  {
158  s32le = true;
159  bits_per_sample = 32;
160  }
161 
162  // len is length of buffer in fully converted samples
163  len /= source_channels;
164  len /= (bits_per_sample / 8);
165 
166  len = std::min(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  {
203  len = 0;
204  }
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  std::chrono::milliseconds timestamp = gPlayer->getOutput()->GetAudiotime();
216  while (m_nodes.size() > 1)
217  {
218  // LOG(VB_PLAYBACK, LOG_DEBUG,
219  // QString("\tMV %1 first > %2 timestamp").
220  // arg(m_nodes.first()->m_offset.count()).arg(timestamp.count()));
221  if (m_nodes.first()->m_offset >= timestamp + 5s)
222  {
223  // REW seek: drain buffer and start over
224  }
225  else if (m_nodes.first()->m_offset > timestamp)
226  {
227  break; // at current time
228  }
229 
230  if (m_vis)
231  m_vis->processUndisplayed(m_nodes.first());
232 
233  delete m_nodes.first();
234  m_nodes.removeFirst();
235  }
236 
237  if (!m_nodes.isEmpty())
238  node = m_nodes.first();
239  }
240 
241  bool stop = true;
242  if (m_vis)
243  stop = m_vis->process(node);
244 
245  if (m_vis && !stop)
246  {
247  QPainter p(&m_pixmap);
250  }
251 
252  if (m_playing && !stop)
253  m_updateTimer->start();
254 }
255 
256 void MainVisual::resize(const QSize size)
257 {
258  m_pixmap = QPixmap(size);
260 
261  if (m_vis)
262  m_vis->resize(size);
263 }
264 
265 void MainVisual::customEvent(QEvent *event)
266 {
267  if ((event->type() == OutputEvent::kPlaying) ||
268  (event->type() == OutputEvent::kInfo) ||
269  (event->type() == OutputEvent::kBuffering) ||
270  (event->type() == OutputEvent::kPaused))
271  {
272  m_playing = true;
273  if (!m_updateTimer->isActive())
274  m_updateTimer->start();
275  }
276  else if ((event->type() == OutputEvent::kStopped) ||
277  (event->type() == OutputEvent::kError))
278  {
279  m_playing = false;
280  }
281 }
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:54
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:37
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:102
mono16_from_monopcmfloat
static void mono16_from_monopcmfloat(short *l, float *s, long cnt)
Definition: inlines.h:167
mythuivideo.h
VisualNode
Definition: videovisual.h:25
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:265
MainVisual::m_fps
int m_fps
Definition: mainvisual.h:73
MainVisual::prepare
void prepare(void) override
Definition: mainvisual.cpp:136
MainVisual::setVisual
void setVisual(const QString &name)
Definition: mainvisual.cpp:78
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
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:256
VisualBase::getDesiredFPS
virtual int getDesiredFPS(void)
Definition: visualize.h:81
MainVisual::timeout
void timeout()
Definition: mainvisual.cpp:209
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:55
MythUIVideo::UpdateFrame
void UpdateFrame(MythImage *image)
Definition: mythuivideo.cpp:52
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:916
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:67
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
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:145
OutputEvent::kBuffering
static const Type kBuffering
Definition: output.h:64
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:885
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:32
OutputEvent::kPaused
static const Type kPaused
Definition: output.h:66
musicplayer.h