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  if (len > m_samples)
167  len = m_samples;
168 
169  int cnt = len;
170 
171  if (source_channels == 2)
172  {
173  l = new short[len];
174  r = new short[len];
175 
176  if (bits_per_sample == 8)
177  stereo16_from_stereopcm8(l, r, (uchar *) buffer, cnt);
178  else if (bits_per_sample == 16)
179  stereo16_from_stereopcm16(l, r, (short *) buffer, cnt);
180  else if (s32le)
181  stereo16_from_stereopcm32(l, r, (int *) buffer, cnt);
182  else if (bits_per_sample == 32)
183  stereo16_from_stereopcmfloat(l, r, (float *) buffer, cnt);
184  else
185  len = 0;
186  }
187  else if (source_channels == 1)
188  {
189  l = new short[len];
190 
191  if (bits_per_sample == 8)
192  mono16_from_monopcm8(l, (uchar *) buffer, cnt);
193  else if (bits_per_sample == 16)
194  mono16_from_monopcm16(l, (short *) buffer, cnt);
195  else if (s32le)
196  mono16_from_monopcm32(l, (int *) buffer, cnt);
197  else if (bits_per_sample == 32)
198  mono16_from_monopcmfloat(l, (float *) buffer, cnt);
199  else
200  len = 0;
201  }
202  else
203  len = 0;
204 
205  m_nodes.append(new VisualNode(l, r, len, timecode));
206 }
207 
209 {
210  VisualNode *node = nullptr;
211  if (m_playing && gPlayer->getOutput())
212  {
213  QMutexLocker locker(mutex());
214  std::chrono::milliseconds timestamp = gPlayer->getOutput()->GetAudiotime();
215  while (m_nodes.size() > 1)
216  {
217  // LOG(VB_PLAYBACK, LOG_DEBUG,
218  // QString("\tMV %1 first > %2 timestamp").
219  // arg(m_nodes.first()->m_offset.count()).arg(timestamp.count()));
220  if (m_nodes.first()->m_offset >= timestamp + 5s)
221  {
222  // REW seek: drain buffer and start over
223  }
224  else if (m_nodes.first()->m_offset > timestamp)
225  break; // at current time
226 
227  if (m_vis)
228  m_vis->processUndisplayed(m_nodes.first());
229 
230  delete m_nodes.first();
231  m_nodes.removeFirst();
232  }
233 
234  if (!m_nodes.isEmpty())
235  node = m_nodes.first();
236  }
237 
238  bool stop = true;
239  if (m_vis)
240  stop = m_vis->process(node);
241 
242  if (m_vis && !stop)
243  {
244  QPainter p(&m_pixmap);
247  }
248 
249  if (m_playing && !stop)
250  m_updateTimer->start();
251 }
252 
253 void MainVisual::resize(const QSize size)
254 {
255  m_pixmap = QPixmap(size);
257 
258  if (m_vis)
259  m_vis->resize(size);
260 }
261 
262 void MainVisual::customEvent(QEvent *event)
263 {
264  if ((event->type() == OutputEvent::kPlaying) ||
265  (event->type() == OutputEvent::kInfo) ||
266  (event->type() == OutputEvent::kBuffering) ||
267  (event->type() == OutputEvent::kPaused))
268  {
269  m_playing = true;
270  if (!m_updateTimer->isActive())
271  m_updateTimer->start();
272  }
273  else if ((event->type() == OutputEvent::kStopped) ||
274  (event->type() == OutputEvent::kError))
275  {
276  m_playing = false;
277  }
278 }
mono16_from_monopcm8
static void mono16_from_monopcm8(short *l, const uchar *c, long cnt)
Definition: videovisualdefs.h:143
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:84
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MainVisual::customEvent
void customEvent(QEvent *event) override
Definition: mainvisual.cpp:262
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:886
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:172
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:92
stereo16_from_stereopcm16
static void stereo16_from_stereopcm16(short *l, short *r, const short *s, long cnt)
Definition: videovisualdefs.h:105
MainVisual::resize
void resize(QSize size)
Definition: mainvisual.cpp:253
VisualBase::getDesiredFPS
virtual int getDesiredFPS(void)
Definition: visualize.h:82
MainVisual::timeout
void timeout()
Definition: mainvisual.cpp:208
VisualBase::draw
virtual bool draw(QPainter *, const QColor &)=0
inlines.h
visualize.h
VisFactory::VisFactories
static const VisFactory * VisFactories()
Definition: visualize.h:101
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:912
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:74
stereo16_from_stereopcm8
static void stereo16_from_stereopcm8(short *l, short *r, const uchar *c, long cnt)
Definition: videovisualdefs.h:67
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:881
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:97
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