MythTV  master
musicplayer.cpp
Go to the documentation of this file.
1 // ANSI C includes
2 #include <cstdlib>
3 
4 // qt
5 #include <QApplication>
6 #include <QDir>
7 #include <QFile>
8 #include <QList>
9 #include <QWidget>
10 
11 // mythtv
13 #include <libmyth/mythcontext.h>
15 #include <libmythbase/mythdb.h>
16 #include <libmythmetadata/metaio.h>
20 #include <libmythui/mythuihelper.h>
21 
22 // mythmusic
23 #include "config.h"
24 #include "constants.h"
25 #include "decoder.h"
26 #include "decoderhandler.h"
27 #include "mainvisual.h"
28 #include "miniplayer.h"
29 #include "musicdata.h"
30 #include "musicplayer.h"
31 #include "playlistcontainer.h"
32 
33 #ifdef HAVE_CDIO
34 #include "cddecoder.h"
35 #endif
36 
37 MusicPlayer *gPlayer = nullptr;
38 QString gCDdevice = "";
39 
41 
42 const QEvent::Type MusicPlayerEvent::kTrackChangeEvent = (QEvent::Type) QEvent::registerEventType();
43 const QEvent::Type MusicPlayerEvent::kVolumeChangeEvent = (QEvent::Type) QEvent::registerEventType();
44 const QEvent::Type MusicPlayerEvent::kTrackAddedEvent = (QEvent::Type) QEvent::registerEventType();
45 const QEvent::Type MusicPlayerEvent::kTrackRemovedEvent = (QEvent::Type) QEvent::registerEventType();
46 const QEvent::Type MusicPlayerEvent::kTrackUnavailableEvent = (QEvent::Type) QEvent::registerEventType();
47 const QEvent::Type MusicPlayerEvent::kAllTracksRemovedEvent = (QEvent::Type) QEvent::registerEventType();
48 const QEvent::Type MusicPlayerEvent::kMetadataChangedEvent = (QEvent::Type) QEvent::registerEventType();
49 const QEvent::Type MusicPlayerEvent::kTrackStatsChangedEvent = (QEvent::Type) QEvent::registerEventType();
50 const QEvent::Type MusicPlayerEvent::kAlbumArtChangedEvent = (QEvent::Type) QEvent::registerEventType();
51 const QEvent::Type MusicPlayerEvent::kCDChangedEvent = (QEvent::Type) QEvent::registerEventType();
52 const QEvent::Type MusicPlayerEvent::kPlaylistChangedEvent = (QEvent::Type) QEvent::registerEventType();
53 const QEvent::Type MusicPlayerEvent::kPlayedTracksChangedEvent = (QEvent::Type) QEvent::registerEventType();
54 
55 MusicPlayer::MusicPlayer(QObject *parent)
56  :QObject(parent)
57 {
58  setObjectName("MusicPlayer");
59 
60  QString playmode = gCoreContext->GetSetting("PlayMode", "none");
61  if (playmode.toLower() == "random")
63  else if (playmode.toLower() == "intelligent")
65  else if (playmode.toLower() == "album")
67  else if (playmode.toLower() == "artist")
69  else
71 
72  QString repeatmode = gCoreContext->GetSetting("RepeatMode", "all");
73  if (repeatmode.toLower() == "track")
75  else if (repeatmode.toLower() == "all")
77  else
79 
80  loadSettings();
81 
86 }
87 
89 {
90  if (!hasClient())
91  savePosition();
92 
95 
96  QMap<QString, int>::Iterator i;
97  for (i = m_notificationMap.begin(); i != m_notificationMap.end(); i++)
98  GetNotificationCenter()->UnRegister(this, (*i));
99 
100  m_notificationMap.clear();
101 
102  stop(true);
103 
104  if (m_decoderHandler)
105  {
107  m_decoderHandler->deleteLater();
108  m_decoderHandler = nullptr;
109  }
110 
111  if (m_oneshotMetadata)
112  {
113  delete m_oneshotMetadata;
114  m_oneshotMetadata = nullptr;
115  }
116 
117  while (!m_playedList.empty())
118  {
119  delete m_playedList.back();
120  m_playedList.pop_back();
121  }
122 
124  gCoreContext->SaveSetting("PlayMode", "intelligent");
125  else if (m_shuffleMode == SHUFFLE_RANDOM)
126  gCoreContext->SaveSetting("PlayMode", "random");
127  else if (m_shuffleMode == SHUFFLE_ALBUM)
128  gCoreContext->SaveSetting("PlayMode", "album");
129  else if (m_shuffleMode == SHUFFLE_ARTIST)
130  gCoreContext->SaveSetting("PlayMode", "artist");
131  else
132  gCoreContext->SaveSetting("PlayMode", "none");
133 
134  if (m_repeatMode == REPEAT_TRACK)
135  gCoreContext->SaveSetting("RepeatMode", "track");
136  else if (m_repeatMode == REPEAT_ALL)
137  gCoreContext->SaveSetting("RepeatMode", "all");
138  else
139  gCoreContext->SaveSetting("RepeatMode", "none");
140 
141  gCoreContext->SaveSetting("MusicAutoShowPlayer",
142  (m_autoShowPlayer ? "1" : "0"));
143 }
144 
145 void MusicPlayer::addListener(QObject *listener)
146 {
147  if (listener && m_output)
148  m_output->addListener(listener);
149 
150  if (listener && getDecoder())
151  getDecoder()->addListener(listener);
152 
153  if (listener && m_decoderHandler)
154  m_decoderHandler->addListener(listener);
155 
156  MythObservable::addListener(listener);
157 
159 }
160 
161 void MusicPlayer::removeListener(QObject *listener)
162 {
163  if (listener && m_output)
164  m_output->removeListener(listener);
165 
166  if (listener && getDecoder())
167  getDecoder()->removeListener(listener);
168 
169  if (listener && m_decoderHandler)
170  m_decoderHandler->removeListener(listener);
171 
173 
175 }
176 
178 {
179  if (visual && !m_visualisers.contains(visual))
180  {
181  if (m_output)
182  {
183  m_output->addListener(visual);
184  m_output->addVisual(visual);
185  }
186 
187  m_visualisers.insert(visual);
188  }
189 }
190 
192 {
193  if (visual)
194  {
195  if (m_output)
196  {
197  m_output->removeListener(visual);
198  m_output->removeVisual(visual);
199  }
200 
201  m_visualisers.remove(visual);
202  }
203 }
204 
206 {
207  if (m_playMode == PLAYMODE_RADIO)
208  return m_resumeModeRadio;
210  return m_resumeModeEditor;
211  return m_resumeModePlayback;
212 }
213 
215 {
219 
220  m_lastplayDelay = gCoreContext->GetDurSetting<std::chrono::seconds>("MusicLastPlayDelay", LASTPLAY_DELAY);
221  m_autoShowPlayer = (gCoreContext->GetNumSetting("MusicAutoShowPlayer", 1) > 0);
222 
223 }
224 
225 void MusicPlayer::setPlayNow(bool PlayNow)
226 {
227  gCoreContext->SaveBoolSetting("MusicPreferPlayNow", PlayNow);
228 }
230 {
231  return gCoreContext->GetBoolSetting("MusicPreferPlayNow", false);
232 }
233 
234 // this stops playing the playlist and plays the file pointed to by mdata
236 {
237  if (m_oneshotMetadata)
238  {
239  delete m_oneshotMetadata;
240  m_oneshotMetadata = nullptr;
241  }
242 
244  *m_oneshotMetadata = mdata;
245 
246  play();
247 }
248 
249 void MusicPlayer::stop(bool stopAll)
250 {
251  stopDecoder();
252 
253  if (m_output)
254  {
255  if (m_output->IsPaused())
256  pause();
257  m_output->Reset();
258  }
259 
260  if (m_oneshotMetadata)
261  {
262  delete m_oneshotMetadata;
263  m_oneshotMetadata = nullptr;
264  }
265 
266  m_isPlaying = false;
267 
268  if (stopAll && getDecoder())
269  {
270  getDecoder()->removeListener(this);
271 
272  // remove any listeners from the decoder
273  {
274  QMutexLocker locker(m_lock);
275  // NOLINTNEXTLINE(modernize-loop-convert)
276  for (auto it = m_listeners.begin(); it != m_listeners.end() ; ++it)
277  getDecoder()->removeListener(*it);
278  }
279  }
280 
281  if (stopAll && m_output)
282  {
283  m_output->removeListener(this);
284  delete m_output;
285  m_output = nullptr;
286  }
287 
288  // because we don't actually stop the audio output we have to fake a Stopped
289  // event so any listeners can act on it
291  dispatch(oe);
292 
294 
296 }
297 
299 {
300  if (m_output)
301  {
304  }
305  // wake up threads
306  Decoder *decoder = getDecoder();
307  if (decoder)
308  {
309  decoder->lock();
310  decoder->cond()->wakeAll();
311  decoder->unlock();
312  }
313 
315 }
316 
318 {
319  stopDecoder();
320 
322  if (!meta)
323  return;
324 
325  if (meta->Filename() == METADATA_INVALID_FILENAME)
326  {
327  // put an upper limit on the number of consecutive track unavailable errors
328  if (m_errorCount >= 1000)
329  {
330  ShowOkPopup(tr("Got too many track unavailable errors. Maybe the host with the music on is off-line?"));
331  stop(true);
332  m_errorCount = 0;
333  return;
334  }
335 
336  if (m_errorCount < 5)
337  {
338  MythErrorNotification n(tr("Track Unavailable"), tr("MythMusic"), QString("Cannot find file '%1'").arg(meta->Filename(false)));
340  }
341 
342  m_errorCount++;
343 
344  sendTrackUnavailableEvent(meta->ID());
345  next();
346  return;
347  }
348 
349  // Notify others that we are about to play
351 
352  if (!m_output)
353  {
354  if (!openOutputDevice())
355  return;
356  }
357 
358  if (!getDecoderHandler())
360 
361  getDecoderHandler()->start(meta);
362 
364 }
365 
367 {
368  if (getDecoderHandler())
369  getDecoderHandler()->stop();
370 }
371 
373 {
374  QString adevice;
375  QString pdevice;
376 
377  adevice = gCoreContext->GetSetting("MusicAudioDevice", "default");
378  if (adevice == "default" || adevice.isEmpty())
379  adevice = gCoreContext->GetSetting("AudioOutputDevice");
380  else
381  adevice = gCoreContext->GetSetting("MusicAudioDevice");
382 
383  pdevice = gCoreContext->GetBoolSetting("PassThruDeviceOverride", false) ?
384  gCoreContext->GetSetting("PassThruOutputDevice") : "auto";
385 
387  adevice, pdevice, FORMAT_S16, 2, AV_CODEC_ID_NONE, 44100,
388  AUDIOOUTPUT_MUSIC, true, false,
389  gCoreContext->GetNumSetting("MusicDefaultUpmix", 0) + 1);
390 
391  if (!m_output)
392  {
393  LOG(VB_GENERAL, LOG_ERR,
394  QString("MusicPlayer: Cannot open audio output device: %1").arg(adevice));
395 
396  return false;
397  }
398 
399  if (!m_output->GetError().isEmpty())
400  {
401  LOG(VB_GENERAL, LOG_ERR,
402  QString("MusicPlayer: Cannot open audio output device: %1").arg(adevice));
403  LOG(VB_GENERAL, LOG_ERR,
404  QString("Error was: %1").arg(m_output->GetError()));
405 
406  delete m_output;
407  m_output = nullptr;
408 
409  return false;
410  }
411 
412  m_output->setBufferSize(256 * 1024);
413 
414  m_output->addListener(this);
415 
416  // add any visuals to the audio output
417  // NOLINTNEXTLINE(modernize-loop-convert)
418  for (auto it = m_visualisers.begin(); it != m_visualisers.end() ; ++it)
420 
421  // add any listeners to the audio output
422  QMutexLocker locker(m_lock);
423  // NOLINTNEXTLINE(modernize-loop-convert)
424  for (auto it = m_listeners.begin(); it != m_listeners.end() ; ++it)
425  m_output->addListener(*it);
426 
427  return true;
428 }
429 
431 {
432  int currentTrack = m_currentTrack;
433 
434  if (!getCurrentPlaylist())
435  return;
436 
437  if (m_oneshotMetadata)
438  {
439  delete m_oneshotMetadata;
440  m_oneshotMetadata = nullptr;
441  }
442  else
443  currentTrack++;
444 
445  if (currentTrack >= getCurrentPlaylist()->getTrackCount())
446  {
447  if (m_repeatMode == REPEAT_ALL)
448  {
449  // start playing again from first track
450  currentTrack = 0;
451  }
452  else
453  {
454  stop();
455  return;
456  }
457  }
458 
459  changeCurrentTrack(currentTrack);
460 
461  if (getCurrentMetadata())
462  play();
463  else
464  stop();
465 }
466 
468 {
469  int currentTrack = m_currentTrack;
470 
471  if (!getCurrentPlaylist())
472  return;
473 
474  if (m_oneshotMetadata)
475  {
476  delete m_oneshotMetadata;
477  m_oneshotMetadata = nullptr;
478  }
479  else
480  currentTrack--;
481 
482  if (currentTrack >= 0)
483  {
484  changeCurrentTrack(currentTrack);
485 
486  if (getCurrentMetadata())
487  play();
488  else
489  return;//stop();
490  }
491  else
492  {
493  // FIXME take repeat mode into account
494  return; //stop();
495  }
496 }
497 
499 {
500  if (!getCurrentPlaylist())
501  return;
502 
503  if (m_oneshotMetadata)
504  {
505  delete m_oneshotMetadata;
506  m_oneshotMetadata = nullptr;
507  stop(true);
508  return;
509  }
510 
511  if (m_repeatMode == REPEAT_TRACK)
512  {
513  play();
514  return;
515  }
516  if (!m_decoderHandler->next())
517  next();
518 
519  // if we don't already have a gui attached show the miniplayer if configured to do so
521  {
522  MythScreenStack *popupStack =
523  GetMythMainWindow()->GetStack("popup stack");
524 
525  auto *miniplayer = new MiniPlayer(popupStack);
526 
527  if (miniplayer->Create())
528  popupStack->AddScreen(miniplayer);
529  else
530  delete miniplayer;
531  }
532 }
533 
535 {
537  {
538  play();
539 
540  m_wasPlaying = false;
541  }
542 }
543 
545 {
546  if (m_output)
547  {
549 
550  savePosition();
551  stop(true);
552  }
553 }
554 
555 void MusicPlayer::customEvent(QEvent *event)
556 {
557  // handle decoderHandler events
558  if (event->type() == DecoderHandlerEvent::kReady)
559  {
560  m_errorCount = 0;
562  }
563  else if (event->type() == DecoderHandlerEvent::kMeta)
564  {
565  auto *dhe = dynamic_cast<DecoderHandlerEvent*>(event);
566  if (!dhe)
567  return;
568 
569  auto *mdata = new MusicMetadata(*dhe->getMetadata());
570 
572 
573  if (getCurrentMetadata())
574  {
575  mdata->setID(getCurrentMetadata()->ID());
576  mdata->setHostname(gCoreContext->GetMasterHostName());
577  mdata->setTrack(m_playedList.count() + 1);
578  mdata->setBroadcaster(getCurrentMetadata()->Broadcaster());
579  mdata->setChannel(getCurrentMetadata()->Channel());
580 
581  getCurrentMetadata()->setTitle(mdata->Title());
582  getCurrentMetadata()->setArtist(mdata->Artist());
583  getCurrentMetadata()->setAlbum(mdata->Album());
584  getCurrentMetadata()->setTrack(mdata->Track());
585  }
586 
587  m_playedList.append(mdata);
588 
590  {
591  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
592 
593  auto *miniplayer = new MiniPlayer(popupStack);
594 
595  if (miniplayer->Create())
596  popupStack->AddScreen(miniplayer);
597  else
598  delete miniplayer;
599  }
600 
601  // tell any listeners we've added a new track to the played list
603  dispatch(me);
604  }
605  // handle MythEvent events
606  else if (event->type() == MythEvent::kMythEventMessage)
607  {
608  auto *me = dynamic_cast<MythEvent*>(event);
609  if (!me)
610  return;
611 
612  if (me->Message().left(13) == "MUSIC_COMMAND")
613  {
614  QStringList list = me->Message().simplified().split(' ');
615 
616  if (list.size() >= 3 && list[1] == gCoreContext->GetHostName())
617  {
618  if (list[2] == "PLAY")
619  play();
620  else if (list[2] == "STOP")
621  stop();
622  else if (list[2] == "PAUSE")
623  pause();
624  else if (list[2] == "SET_VOLUME")
625  {
626  if (list.size() > 3)
627  {
628  int volume = list[3].toInt();
629  if (volume >= 0 && volume <= 100)
630  setVolume(volume);
631  }
632  }
633  else if (list[2] == "GET_VOLUME")
634  {
635  QString message = QString("MUSIC_CONTROL ANSWER %1 %2")
636  .arg(gCoreContext->GetHostName()).arg(getVolume());
637  MythEvent me2(message);
638  gCoreContext->dispatch(me2);
639  }
640  else if (list[2] == "PLAY_FILE")
641  {
642  int start = me->Message().indexOf("'");
643  int end = me->Message().lastIndexOf("'");
644 
645  if (start != -1 && end != -1 && start != end)
646  {
647  QString filename = me->Message().mid(start + 1, end - start - 1);
648  MusicMetadata mdata;
649  mdata.setFilename(filename);
650  playFile(mdata);
651  }
652  else
653  {
654  LOG(VB_GENERAL, LOG_ERR,
655  QString("MusicPlayer: got invalid MUSIC_COMMAND "
656  "PLAY_FILE - %1").arg(me->Message()));
657  }
658  }
659  else if (list[2] == "PLAY_URL")
660  {
661  if (list.size() == 4)
662  {
663  QString filename = list[3];
664  MusicMetadata mdata;
665  mdata.setFilename(filename);
666  playFile(mdata);
667  }
668  else
669  {
670  LOG(VB_GENERAL, LOG_ERR,
671  QString("MusicPlayer: got invalid MUSIC_COMMAND "
672  "PLAY_URL - %1").arg(me->Message()));
673  }
674  }
675  else if (list[2] == "PLAY_TRACK")
676  {
677  if (list.size() == 4)
678  {
679  int trackID = list[3].toInt();
680  MusicMetadata *mdata = gMusicData->m_all_music->getMetadata(trackID);
681  if (mdata)
682  playFile(*mdata);
683  }
684  else
685  {
686  LOG(VB_GENERAL, LOG_ERR,
687  QString("MusicPlayer: got invalid MUSIC_COMMAND "
688  "PLAY_TRACK - %1").arg(me->Message()));
689  }
690  }
691  else if (list[2] == "GET_METADATA")
692  {
693  QString mdataStr;
695  if (mdata)
696  mdataStr = QString("%1 by %2 from %3").arg(mdata->Title(), mdata->Artist(), mdata->Album());
697  else
698  mdataStr = "Unknown Track2";
699 
700  QString message = QString("MUSIC_CONTROL ANSWER %1 %2")
701  .arg(gCoreContext->GetHostName(), mdataStr);
702  MythEvent me2(message);
703  gCoreContext->dispatch(me2);
704  }
705  else if (list[2] == "GET_STATUS")
706  {
707  QString statusStr = "STOPPED";
708 
709  if (gPlayer->isPlaying())
710  statusStr = "PLAYING";
711  else if (gPlayer->isPaused())
712  statusStr = "PAUSED";
713 
714  QString message = QString("MUSIC_CONTROL ANSWER %1 %2")
715  .arg(gCoreContext->GetHostName(), statusStr);
716  MythEvent me2(message);
717  gCoreContext->dispatch(me2);
718  }
719  }
720  else
721  {
722  LOG(VB_GENERAL, LOG_ERR,
723  QString("MusicPlayer: got unknown/invalid MUSIC_COMMAND "
724  "- %1").arg(me->Message()));
725  }
726  }
727  else if (me->Message().startsWith("MUSIC_SETTINGS_CHANGED"))
728  {
729  loadSettings();
730  }
731  else if (me->Message().startsWith("MUSIC_METADATA_CHANGED"))
732  {
734  {
735  QStringList list = me->Message().simplified().split(' ');
736  if (list.size() == 2)
737  {
738  int songID = list[1].toInt();
739  MusicMetadata *mdata = gMusicData->m_all_music->getMetadata(songID);
740 
741  if (mdata)
742  {
743  mdata->reloadMetadata();
744 
745  // tell any listeners the metadata has changed for this track
746  sendMetadataChangedEvent(songID);
747  }
748  }
749  }
750  }
751  else if (me->Message().startsWith("MUSIC_SCANNER_STARTED"))
752  {
753  QStringList list = me->Message().simplified().split(' ');
754  if (list.size() == 2)
755  {
756  QString host = list[1];
757  int id = getNotificationID(host);
758  sendNotification(id,
759  tr("A music file scan has started on %1").arg(host),
760  tr("Music File Scanner"),
761  tr("This may take a while I'll give a shout when finished"));
762  }
763  }
764  else if (me->Message().startsWith("MUSIC_SCANNER_FINISHED"))
765  {
766  QStringList list = me->Message().simplified().split(' ');
767  if (list.size() == 6)
768  {
769  QString host = list[1];
770  int id = getNotificationID(host);
771  int totalTracks = list[2].toInt();
772  int newTracks = list[3].toInt();
773  int totalCoverart = list[4].toInt();
774  int newCoverart = list[5].toInt();
775 
776  QString summary = QString("Total Tracks: %2, new tracks: %3,\nTotal Coverart: %4, New CoverArt %5")
777  .arg(totalTracks).arg(newTracks).arg(totalCoverart).arg(newCoverart);
778  sendNotification(id,
779  tr("A music file scan has finished on %1").arg(host),
780  tr("Music File Scanner"), summary);
781 
783  }
784  }
785  else if (me->Message().startsWith("MUSIC_SCANNER_ERROR"))
786  {
787  QStringList list = me->Message().simplified().split(' ');
788  if (list.size() == 3)
789  {
790  QString host = list[1];
791  QString error = list[2];
792  int id = getNotificationID(host);
793 
794  if (error == "Already_Running")
795  {
796  sendNotification(id, tr(""),
797  tr("Music File Scanner"),
798  tr("Can't run the music file scanner because it is already running on %1").arg(host));
799  }
800  else if (error == "Stalled")
801  {
802  sendNotification(id, tr(""),
803  tr("Music File Scanner"),
804  tr("The music file scanner has been running for more than 60 minutes on %1.\nResetting and trying again")
805  .arg(host));
806  }
807  }
808  }
809  }
810 
811  if (event->type() == OutputEvent::kError)
812  {
813  auto *aoe = dynamic_cast<OutputEvent *>(event);
814 
815  if (!aoe)
816  return;
817 
818  LOG(VB_GENERAL, LOG_ERR, QString("Audio Output Error: %1").arg(*aoe->errorMessage()));
819 
820  MythErrorNotification n(tr("Audio Output Error"), tr("MythMusic"), *aoe->errorMessage());
822 
823  m_errorCount++;
824 
825  if (m_errorCount <= 5)
826  nextAuto();
827  else
828  {
829  m_errorCount = 0;
830  stop(true);
831  }
832  }
833  else if (event->type() == DecoderEvent::kError)
834  {
835  auto *dxe = dynamic_cast<DecoderEvent *>(event);
836 
837  if (!dxe)
838  return;
839 
840  LOG(VB_GENERAL, LOG_ERR, QString("Decoder Error: %2").arg(*dxe->errorMessage()));
841 
842  MythErrorNotification n(tr("Decoder Error"), tr("MythMusic"), *dxe->errorMessage());
844 
845  m_errorCount++;
846 
847  if (m_playMode != PLAYMODE_RADIO && m_errorCount <= 5)
848  nextAuto();
849  else
850  {
851  m_errorCount = 0;
852  stop(true);
853  }
854  }
855  else if (event->type() == DecoderHandlerEvent::kError)
856  {
857  auto *dhe = dynamic_cast<DecoderHandlerEvent*>(event);
858 
859  if (!dhe)
860  return;
861 
862  LOG(VB_GENERAL, LOG_ERR, QString("Decoder Handler Error - %1").arg(*dhe->getMessage()));
863 
864  MythErrorNotification n(tr("Decoder Handler Error"), tr("MythMusic"), *dhe->getMessage());
866 
867  m_errorCount++;
868 
869  if (m_errorCount <= 5)
870  nextAuto();
871  else
872  {
873  m_errorCount = 0;
874  stop(true);
875  }
876  }
877  else if (event->type() == OutputEvent::kInfo)
878  {
879  auto *oe = dynamic_cast<OutputEvent*>(event);
880 
881  if (!oe)
882  return;
883 
884  if (m_playMode != PLAYMODE_RADIO)
885  m_currentTime = oe->elapsedSeconds();
886  else
887  m_currentTime = oe->elapsedSeconds() - m_lastTrackStart;
888 
890  {
891  // we update the lastplay and playcount after playing
892  // for m_lastplayDelay seconds or half the total track time
893  if ((getCurrentMetadata() &&
894  m_currentTime > duration_cast<std::chrono::seconds>(getCurrentMetadata()->Length()) / 2) ||
896  {
897  updateLastplay();
898  }
899  }
900 
901  // update the current tracks time in the last played list
902  if (m_playMode == PLAYMODE_RADIO)
903  {
904  if (!m_playedList.isEmpty() && m_currentTime > 0s)
905  {
906  m_playedList.last()->setLength(m_currentTime);
907  // this will update any track lengths displayed on screen
909  }
910  }
911  }
912  else if (event->type() == DecoderEvent::kFinished)
913  {
914  if (m_oneshotMetadata)
915  {
916  delete m_oneshotMetadata;
917  m_oneshotMetadata = nullptr;
918  stop(true);
919  }
920  else
921  {
922  auto metadataSecs = duration_cast<std::chrono::seconds>(getCurrentMetadata()->Length());
924  m_currentTime != metadataSecs)
925  {
926  LOG(VB_GENERAL, LOG_NOTICE, QString("MusicPlayer: Updating track length was %1s, should be %2s")
927  .arg(metadataSecs.count()).arg(m_currentTime.count()));
928 
931 
932  // this will update any track lengths displayed on screen
934 
935  // this will force the playlist stats to update
937  dispatch(me);
938  }
939 
940  nextAuto();
941  }
942  }
943  else if (event->type() == DecoderEvent::kStopped)
944  {
945  }
946  else if (event->type() == DecoderHandlerEvent::kBufferStatus)
947  {
948  auto *dhe = dynamic_cast<DecoderHandlerEvent*>(event);
949  if (!dhe)
950  return;
951 
953  }
954 
955  QObject::customEvent(event);
956 }
957 
958 void MusicPlayer::getBufferStatus(int *bufferAvailable, int *bufferSize) const
959 {
960  *bufferAvailable = m_bufferAvailable;
961  *bufferSize = m_bufferSize;
962 }
963 
965 {
966  if (m_playMode == mode)
967  return;
968 
969  savePosition();
970 
971  m_playMode = mode;
972 
973  loadPlaylist();
974 }
975 
977 {
978  if (m_playMode == PLAYMODE_RADIO)
979  {
981  {
982  int bookmark = gCoreContext->GetNumSetting("MusicRadioBookmark", 0);
983  if (bookmark < 0 || bookmark >= getCurrentPlaylist()->getTrackCount())
984  bookmark = 0;
985 
986  m_currentTrack = bookmark;
987  }
988  else
989  m_currentTrack = 0;
990 
992  }
993  else
994  {
996  {
997  int bookmark = gCoreContext->GetNumSetting("MusicBookmark", 0);
998  if (bookmark < 0 || bookmark >= getCurrentPlaylist()->getTrackCount())
999  bookmark = 0;
1000 
1001  m_currentTrack = bookmark;
1002  }
1003  else
1004  m_currentTrack = 0;
1005  }
1006 }
1007 
1009 {
1011 
1012  // create the radio playlist
1016 
1017  for (int x = 0; x < list->count(); x++)
1018  {
1019  MusicMetadata *mdata = list->at(x);
1020  gMusicData->m_all_playlists->getStreamPlaylist()->addTrack(mdata->ID(), false);
1021 
1022  if (mdata->ID() == id)
1023  m_currentTrack = x;
1024  }
1025 
1027 }
1028 
1029 void MusicPlayer::moveTrackUpDown(bool moveUp, int whichTrack)
1030 {
1031  if (!getCurrentPlaylist())
1032  return;
1033 
1034  if (moveUp && whichTrack <= 0)
1035  return;
1036 
1037  if (!moveUp && whichTrack >= getCurrentPlaylist()->getTrackCount() - 1)
1038  return;
1039 
1041 
1042  getCurrentPlaylist()->moveTrackUpDown(moveUp, whichTrack);
1043 
1045 }
1046 
1048 {
1049  changeCurrentTrack(pos);
1050 
1051  if (!getCurrentMetadata())
1052  {
1053  stop();
1054  return false;
1055  }
1056 
1057  play();
1058 
1059  return true;
1060 }
1061 
1063 {
1064  // can't save a bookmark if we don't know what we are playing
1065  if (!getCurrentMetadata())
1066  return;
1067 
1068  if (m_playMode == PLAYMODE_RADIO)
1069  {
1070  gCoreContext->SaveSetting("MusicRadioBookmark", getCurrentMetadata()->ID());
1071  }
1072  else
1073  {
1074  gCoreContext->SaveSetting("MusicBookmark", getCurrentMetadata()->ID());
1075  gCoreContext->SaveDurSetting("MusicBookmarkPosition", m_currentTime);
1076  }
1077 }
1078 
1080 {
1081  // if we are switching views we don't wont to restore the position
1082  if (!m_allowRestorePos)
1083  return;
1084 
1085  m_currentTrack = 0;
1086  uint id = -1;
1087 
1089  {
1090  if (m_playMode == PLAYMODE_RADIO)
1091  id = gCoreContext->GetNumSetting("MusicRadioBookmark", 0);
1092  else
1093  id = gCoreContext->GetNumSetting("MusicBookmark", 0);
1094  }
1095 
1096  if (getCurrentPlaylist())
1097  {
1098  for (int x = 0; x < getCurrentPlaylist()->getTrackCount(); x++)
1099  {
1100  if (getCurrentPlaylist()->getSongAt(x) &&
1101  getCurrentPlaylist()->getSongAt(x)->ID() == id)
1102  {
1103  m_currentTrack = x;
1104  break;
1105  }
1106  }
1107  }
1108 
1109  if (getCurrentMetadata())
1110  {
1112  play();
1113 
1115  seek(gCoreContext->GetDurSetting<std::chrono::seconds>("MusicBookmarkPosition", 0s));
1116  }
1117 }
1118 
1119 void MusicPlayer::seek(std::chrono::seconds pos)
1120 {
1121  if (m_output)
1122  {
1123  Decoder *decoder = getDecoder();
1124  if (decoder && decoder->isRunning())
1125  decoder->seek(pos.count());
1126 
1127  m_output->SetTimecode(pos);
1128  }
1129 }
1130 
1132 {
1133  if (m_canShowPlayer)
1134  {
1135  MythScreenStack *popupStack =
1136  GetMythMainWindow()->GetStack("popup stack");
1137 
1138  auto *miniplayer = new MiniPlayer(popupStack);
1139 
1140  if (miniplayer->Create())
1141  popupStack->AddScreen(miniplayer);
1142  else
1143  delete miniplayer;
1144  }
1145 }
1146 
1149 {
1150  if (!getCurrentPlaylist())
1151  return;
1152 
1153  // check to see if we need to save the current tracks volatile metadata (playcount, last played etc)
1155 
1156  m_currentTrack = trackNo;
1157 
1158  // sanity check the current track
1159  if (m_currentTrack < 0 || m_currentTrack >= getCurrentPlaylist()->getTrackCount())
1160  {
1161  LOG(VB_GENERAL, LOG_ERR,
1162  QString("MusicPlayer: asked to set the current track to an invalid track no. %1")
1163  .arg(trackNo));
1164  m_currentTrack = -1;
1165  return;
1166  }
1167 }
1168 
1171 {
1172  if (m_oneshotMetadata)
1173  return m_oneshotMetadata;
1174 
1175  if (!getCurrentPlaylist() || !getCurrentPlaylist()->getSongAt(m_currentTrack))
1176  return nullptr;
1177 
1179 }
1180 
1183 {
1184  if (m_playMode == PLAYMODE_RADIO)
1185  return nullptr;
1186 
1187  if (m_oneshotMetadata)
1188  return getCurrentMetadata();
1189 
1190  if (!getCurrentPlaylist() || !getCurrentPlaylist()->getSongAt(m_currentTrack))
1191  return nullptr;
1192 
1193  if (m_repeatMode == REPEAT_TRACK)
1194  return getCurrentMetadata();
1195 
1196  // if we are not playing the last track then just return the next track
1197  if (m_currentTrack < getCurrentPlaylist()->getTrackCount() - 1)
1199 
1200  // if we are playing the last track then we need to take the
1201  // repeat mode into account
1202  if (m_repeatMode == REPEAT_ALL)
1203  return getCurrentPlaylist()->getSongAt(0);
1204  return nullptr;
1205 }
1206 
1208 {
1209  switch (m_repeatMode)
1210  {
1211  case REPEAT_OFF:
1213  break;
1214  case REPEAT_TRACK:
1216  break;
1217  case REPEAT_ALL:
1218  default:
1220  break;
1221  }
1222 
1223  return m_repeatMode;
1224 }
1225 
1227 {
1228  switch (m_shuffleMode)
1229  {
1230  case SHUFFLE_OFF:
1232  break;
1233  case SHUFFLE_RANDOM:
1235  break;
1236  case SHUFFLE_INTELLIGENT:
1238  break;
1239  case SHUFFLE_ALBUM:
1241  break;
1242  case SHUFFLE_ARTIST:
1243  default:
1245  break;
1246  }
1247 
1249 
1250  return m_shuffleMode;
1251 }
1252 
1254 {
1255  int curTrackID = -1;
1256  if (getCurrentMetadata())
1257  curTrackID = getCurrentMetadata()->ID();
1258 
1259  // only save the mode if we are playing tracks
1260  if (m_playMode != PLAYMODE_RADIO)
1261  m_shuffleMode = mode;
1262 
1263  if (!getCurrentPlaylist())
1264  return;
1265 
1267 
1268  if (curTrackID != -1)
1269  {
1270  for (int x = 0; x < getCurrentPlaylist()->getTrackCount(); x++)
1271  {
1273  if (mdata && mdata->ID() == (MusicMetadata::IdType) curTrackID)
1274  {
1275  m_currentTrack = x;
1276  break;
1277  }
1278  }
1279  }
1280 }
1281 
1283 {
1285  {
1288  }
1289 
1290  m_updatedLastplay = true;
1291 }
1292 
1294 {
1296  {
1297  if (getCurrentMetadata()->hasChanged())
1298  {
1300 
1301  // only write the last played, playcount & rating to the tag if it's enabled by the user
1302  if (GetMythDB()->GetNumSetting("AllowTagWriting", 0) == 1)
1303  {
1304  QStringList strList;
1305  strList << QString("MUSIC_TAG_UPDATE_VOLATILE")
1307  << QString::number(getCurrentMetadata()->ID())
1308  << QString::number(getCurrentMetadata()->Rating())
1309  << QString::number(getCurrentMetadata()->Playcount())
1310  << getCurrentMetadata()->LastPlay().toString(Qt::ISODate);
1311  auto *thread = new SendStringListThread(strList);
1312  MThreadPool::globalInstance()->start(thread, "UpdateVolatile");
1313  }
1314 
1316  }
1317  }
1318 }
1319 
1320 void MusicPlayer::setSpeed(float newspeed)
1321 {
1322  if (m_output)
1323  {
1324  m_playSpeed = newspeed;
1326  }
1327 }
1328 
1330 {
1331  m_playSpeed += 0.05F;
1333 }
1334 
1336 {
1337  m_playSpeed -= 0.05F;
1339 }
1340 
1342 {
1344  dispatch(me);
1345 }
1346 
1348 {
1350  dispatch(me);
1351 }
1352 
1354 {
1356  dispatch(me);
1357 }
1358 
1360 {
1362  dispatch(me);
1363 }
1364 
1366 {
1368  dispatch(me);
1369 }
1370 
1372 {
1374  dispatch(me);
1375 }
1376 
1378 {
1379  if (getOutput())
1380  {
1383  }
1384 }
1385 
1387 {
1388  if (getOutput())
1389  {
1392  }
1393 }
1394 
1395 void MusicPlayer::setVolume(int volume)
1396 {
1397  if (getOutput())
1398  {
1399  getOutput()->SetCurrentVolume(volume);
1401  }
1402 }
1403 
1405 {
1406  if (m_output)
1407  return m_output->GetCurrentVolume();
1408  return 0;
1409 }
1410 
1412 {
1413  if (m_output)
1414  {
1415  m_output->ToggleMute();
1417  }
1418 }
1419 
1421 {
1422  if (m_output)
1423  return m_output->GetMuteState();
1424  return kMuteOff;
1425 }
1426 
1427 void MusicPlayer::toMap(InfoMap &map) const
1428 {
1429  map["volumemute"] = isMuted() ? tr("%1% (Muted)", "Zero Audio Volume").arg(getVolume()) :
1430  QString("%1%").arg(getVolume());
1431  map["volume"] = QString("%1").arg(getVolume());
1432  map["volumepercent"] = QString("%1%").arg(getVolume());
1433  map["mute"] = isMuted() ? tr("Muted") : "";
1434 }
1435 
1436 void MusicPlayer::activePlaylistChanged(int trackID, bool deleted)
1437 {
1438  if (trackID == -1)
1439  {
1440  if (deleted)
1441  {
1443  dispatch(me);
1444  }
1445  else
1446  {
1448  dispatch(me);
1449  }
1450  }
1451  else
1452  {
1453  if (deleted)
1454  {
1456  dispatch(me);
1457  }
1458  else
1459  {
1461  dispatch(me);
1462  }
1463  }
1464 
1465  // if we don't have any tracks to play stop here
1466  if (!getCurrentPlaylist() || getCurrentPlaylist()->getTrackCount() == 0)
1467  {
1468  m_currentTrack = -1;
1469  if (isPlaying())
1470  stop(true);
1471  return;
1472  }
1473 
1474  int trackPos = -1;
1475 
1476  // make sure the current playing track is still valid
1477  if (isPlaying() && getDecoderHandler())
1478  {
1479  for (int x = 0; x < getCurrentPlaylist()->getTrackCount(); x++)
1480  {
1482  {
1483  trackPos = x;
1484  break;
1485  }
1486  }
1487  }
1488 
1489  if (trackPos != m_currentTrack)
1490  m_currentTrack = trackPos;
1491 
1492  if (!getCurrentMetadata())
1493  {
1494  m_currentTrack = -1;
1495  stop(true);
1496  }
1497 }
1498 
1499 void MusicPlayer::playlistChanged(int playlistID)
1500 {
1502  dispatch(me);
1503 }
1504 
1506 {
1509 
1510  // add any listeners to the decoderHandler
1511  {
1512  QMutexLocker locker(m_lock);
1513  // NOLINTNEXTLINE(modernize-loop-convert)
1514  for (auto it = m_listeners.begin(); it != m_listeners.end() ; ++it)
1516  }
1517 }
1518 
1520 {
1521  Decoder *decoder = getDecoder();
1522  if (!decoder)
1523  return;
1524 
1525  LOG(VB_PLAYBACK, LOG_INFO, QString ("decoder handler is ready, decoding %1")
1526  .arg(decoder->getURL()));
1527 
1528 #ifdef HAVE_CDIO
1529  auto *cddecoder = dynamic_cast<CdDecoder*>(decoder);
1530  if (cddecoder)
1531  cddecoder->setDevice(gCDdevice);
1532 #endif
1533 
1534  // Decoder thread can't be running while being initialized
1535  if (decoder->isRunning())
1536  {
1537  decoder->stop();
1538  decoder->wait();
1539  }
1540 
1541  decoder->setOutput(m_output);
1542  //decoder-> setBlockSize(2 * 1024);
1543  decoder->addListener(this);
1544 
1545  // add any listeners to the decoder
1546  {
1547  QMutexLocker locker(m_lock);
1548  // NOLINTNEXTLINE(modernize-loop-convert)
1549  for (auto it = m_listeners.begin(); it != m_listeners.end() ; ++it)
1550  decoder->addListener(*it);
1551  }
1552 
1553  m_currentTime = 0s;
1554  m_lastTrackStart = 0s;
1555 
1556  // NOLINTNEXTLINE(modernize-loop-convert)
1557  for (auto it = m_visualisers.begin(); it != m_visualisers.end() ; ++it)
1558  {
1559  //m_output->addVisual((MythTV::Visual*)(*it));
1560  //(*it)->setDecoder(decoder);
1561  //m_visual->setOutput(m_output);
1562  }
1563 
1564  if (decoder->initialize())
1565  {
1566  if (m_output)
1568 
1569  decoder->start();
1570 
1572  gCoreContext->GetDurSetting<std::chrono::seconds>("MusicBookmarkPosition", 0s) > 0s)
1573  {
1574  seek(gCoreContext->GetDurSetting<std::chrono::seconds>("MusicBookmarkPosition", 0s));
1575  gCoreContext->SaveDurSetting("MusicBookmarkPosition", 0s);
1576  }
1577 
1578  m_isPlaying = true;
1579  m_updatedLastplay = false;
1580  }
1581  else
1582  {
1583  LOG(VB_PLAYBACK, LOG_ERR, QString("Cannot initialise decoder for %1")
1584  .arg(decoder->getURL()));
1585  return;
1586  }
1587 
1588  // tell any listeners we've started playing a new track
1590  dispatch(me);
1591 }
1592 
1593 void MusicPlayer::removeTrack(int trackID)
1594 {
1595  MusicMetadata *mdata = gMusicData->m_all_music->getMetadata(trackID);
1596  if (mdata)
1597  {
1598  int trackPos = getCurrentPlaylist()->getTrackPosition(mdata->ID());
1599  if (m_currentTrack > 0 && m_currentTrack >= trackPos)
1600  m_currentTrack--;
1601 
1602  getCurrentPlaylist()->removeTrack(trackID);
1603  }
1604 }
1605 
1606 void MusicPlayer::addTrack(int trackID, bool updateUI)
1607 {
1608  getCurrentPlaylist()->addTrack(trackID, updateUI);
1609 }
1610 
1612 {
1614  return nullptr;
1615 
1616  if (m_playMode == PLAYMODE_RADIO)
1617  {
1619  }
1621 }
1622 
1624 {
1625  return gMusicData->m_all_streams->getStreams();
1626 }
1627 
1629 {
1630  if (m_notificationMap.find(hostname) == m_notificationMap.end())
1631  m_notificationMap.insert(hostname, GetNotificationCenter()->Register(this));
1632 
1633  return m_notificationMap[hostname];
1634 }
1635 
1636 void MusicPlayer::sendNotification(int notificationID, const QString &title, const QString &author, const QString &desc)
1637 {
1638  QString image = "musicscanner.png";
1639  if (!GetMythUI()->FindThemeFile(image))
1640  LOG(VB_GENERAL, LOG_ERR, "MusicPlayer: sendNotification failed to find the 'musicscanner.png' image");
1641 
1642  DMAP map;
1643  map["asar"] = title;
1644  map["minm"] = author;
1645  map["asal"] = desc;
1646 
1647  auto *n = new MythImageNotification(MythNotification::kInfo, image, map);
1648 
1649  n->SetId(notificationID);
1650  n->SetParent(this);
1651  n->SetDuration(5s);
1652  n->SetFullScreen(false);
1654  delete n;
1655 }
MusicPlayer::addVisual
void addVisual(MainVisual *visual)
Definition: musicplayer.cpp:177
AudioOutput::GetError
QString GetError(void) const
Definition: audiooutput.h:148
OutputListeners::addVisual
void addVisual(MythTV::Visual *v)
Definition: output.cpp:35
MusicPlayer::StopPlayback
void StopPlayback(void)
Definition: musicplayer.cpp:544
MusicPlayer::PLAYMODE_TRACKSEDITOR
@ PLAYMODE_TRACKSEDITOR
Definition: musicplayer.h:72
VolumeBase::SetCurrentVolume
virtual void SetCurrentVolume(int value)
Definition: volumebase.cpp:123
MusicPlayer::toggleMute
void toggleMute(void)
Definition: musicplayer.cpp:1411
MusicPlayer::openOutputDevice
bool openOutputDevice(void)
Definition: musicplayer.cpp:372
MusicPlayer::SHUFFLE_INTELLIGENT
@ SHUFFLE_INTELLIGENT
Definition: musicplayer.h:177
MusicPlayer::m_bufferAvailable
int m_bufferAvailable
Definition: musicplayer.h:259
MusicPlayer::getDecoder
Decoder * getDecoder(void)
Definition: musicplayer.h:126
MusicPlayer::StartPlayback
void StartPlayback(void)
Definition: musicplayer.cpp:534
playlistcontainer.h
MusicPlayer::getOutput
AudioOutput * getOutput(void)
Definition: musicplayer.h:128
MusicMetadata::Title
QString Title() const
Definition: musicmetadata.h:162
Channel
Definition: channel.h:36
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:37
Playlist::getSongAt
MusicMetadata * getSongAt(int pos) const
Definition: playlist.cpp:1085
MusicMetadata::Filename
QString Filename(bool find=true)
Definition: musicmetadata.cpp:962
MusicPlayer::m_notificationMap
QMap< QString, int > m_notificationMap
Definition: musicplayer.h:254
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
MythCoreContext::GetMasterHostName
QString GetMasterHostName(void)
Definition: mythcorecontext.cpp:807
MusicMetadata::incPlayCount
void incPlayCount()
Definition: musicmetadata.cpp:1194
MusicPlayer::m_bufferSize
int m_bufferSize
Definition: musicplayer.h:260
MusicPlayer::setCurrentTrackPos
bool setCurrentTrackPos(int pos)
Definition: musicplayer.cpp:1047
MusicPlayer::RESUME_OFF
@ RESUME_OFF
Definition: musicplayer.h:184
MythEvent::kMythEventMessage
static const Type kMythEventMessage
Definition: mythevent.h:79
error
static void error(const char *str,...)
Definition: vbi.cpp:36
FORMAT_S16
@ FORMAT_S16
Definition: audiooutputsettings.h:27
MusicPlayer::setVolume
void setVolume(int volume)
Definition: musicplayer.cpp:1395
MusicPlayer::toMap
void toMap(InfoMap &infoMap) const
Definition: musicplayer.cpp:1427
mythdb.h
VolumeBase::AdjustCurrentVolume
virtual void AdjustCurrentVolume(int change)
Definition: volumebase.cpp:132
MusicPlayer::sendNotification
void sendNotification(int notificationID, const QString &title, const QString &author, const QString &desc)
Definition: musicplayer.cpp:1636
MusicPlayer::RESUME_TRACK
@ RESUME_TRACK
Definition: musicplayer.h:186
VolumeBase::GetCurrentVolume
virtual uint GetCurrentVolume(void) const
Definition: volumebase.cpp:118
MusicPlayer::getResumeMode
ResumeMode getResumeMode(void)
Definition: musicplayer.cpp:205
OutputEvent
Definition: output.h:31
MythObservable::m_lock
QMutex * m_lock
Definition: mythobservable.h:29
MusicPlayer::loadPlaylist
void loadPlaylist(void)
Definition: musicplayer.cpp:976
MusicPlayerEvent
Definition: musicplayer.h:20
AudioOutput::Reset
virtual void Reset(void)=0
MusicPlayer::loadStreamPlaylist
void loadStreamPlaylist(void)
Definition: musicplayer.cpp:1008
decoderhandler.h
Playlist::enableSaves
void enableSaves(void)
Definition: playlist.h:103
MThread::wait
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
Definition: mthread.cpp:300
MythCoreContext::emitTVPlaybackStopped
void emitTVPlaybackStopped(void)
Definition: mythcorecontext.h:291
Playlist::shuffleTracks
void shuffleTracks(MusicPlayer::ShuffleMode mode)
Definition: playlist.cpp:154
MusicPlayer::decVolume
void decVolume(void)
Definition: musicplayer.cpp:1386
Playlist
Definition: playlist.h:45
MusicMetadata::setTrack
void setTrack(int ltrack)
Definition: musicmetadata.h:200
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
MusicPlayer::getPlayNow
static bool getPlayNow(void)
Definition: musicplayer.cpp:229
mythdialogbox.h
MythScreenStack
Definition: mythscreenstack.h:16
MusicPlayer::setShuffleMode
void setShuffleMode(ShuffleMode mode)
Definition: musicplayer.cpp:1253
MusicMetadata::ID
IdType ID() const
Definition: musicmetadata.h:218
MusicMetadata::setAlbum
void setAlbum(const QString &lalbum, const QString &lalbum_sort=nullptr)
Definition: musicmetadata.h:152
MusicData::m_initialized
bool m_initialized
Definition: musicdata.h:58
MusicPlayer::isPlaying
bool isPlaying(void) const
Definition: musicplayer.h:109
MusicPlayer::MusicPlayer
MusicPlayer(QObject *parent)
Definition: musicplayer.cpp:55
MusicPlayer::m_playMode
PlayMode m_playMode
Definition: musicplayer.h:233
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MusicPlayer::m_lastplayDelay
std::chrono::seconds m_lastplayDelay
Definition: musicplayer.h:242
MusicPlayer::m_resumeModePlayback
ResumeMode m_resumeModePlayback
Definition: musicplayer.h:246
MusicMetadata
Definition: musicmetadata.h:80
MusicPlayerEvent::kMetadataChangedEvent
static const Type kMetadataChangedEvent
Definition: musicplayer.h:45
MusicPlayer::getStreamList
static StreamList * getStreamList(void)
Definition: musicplayer.cpp:1623
MusicPlayer::getMuteState
MuteState getMuteState(void) const
Definition: musicplayer.cpp:1420
GetMythDB
MythDB * GetMythDB(void)
Definition: mythdb.cpp:50
MusicPlayer::getCurrentPlaylist
Playlist * getCurrentPlaylist(void)
Definition: musicplayer.cpp:1611
MythObservable::dispatch
void dispatch(const MythEvent &event)
Dispatch an event to all listeners.
Definition: mythobservable.cpp:73
MythCoreContext::SaveDurSetting
std::enable_if_t< std::chrono::__is_duration< T >::value, void > SaveDurSetting(const QString &key, T newValue)
Definition: mythcorecontext.h:155
MusicPlayer::removeListener
void removeListener(QObject *listener)
Definition: musicplayer.cpp:161
DecoderHandler::next
bool next(void)
Definition: decoderhandler.cpp:137
OutputListeners::removeVisual
void removeVisual(MythTV::Visual *v)
Definition: output.cpp:42
MusicMetadata::persist
void persist(void)
Definition: musicmetadata.cpp:175
MusicMetadata::Artist
QString Artist() const
Definition: musicmetadata.h:126
MusicPlayer::setPlayMode
void setPlayMode(PlayMode mode)
Definition: musicplayer.cpp:964
MusicPlayer::pause
void pause(void)
Definition: musicplayer.cpp:298
MusicPlayer::updateVolatileMetadata
void updateVolatileMetadata(void)
Definition: musicplayer.cpp:1293
Decoder::cond
QWaitCondition * cond()
Definition: decoder.h:89
MythImageNotification
Definition: mythnotification.h:131
MusicPlayer::m_decoderHandler
DecoderHandler * m_decoderHandler
Definition: musicplayer.h:229
MythObservable::m_listeners
QSet< QObject * > m_listeners
Definition: mythobservable.h:30
musicutils.h
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
MusicPlayerEvent::kAllTracksRemovedEvent
static const Type kAllTracksRemovedEvent
Definition: musicplayer.h:44
AudioOutput::OpenAudio
static AudioOutput * OpenAudio(const QString &main_device, const QString &passthru_device, AudioFormat format, int channels, AVCodecID codec, int samplerate, AudioOutputSource source, bool set_initial_vol, bool passthru, int upmixer_startup=0, AudioOutputSettings *custom=nullptr)
Definition: audiooutput.cpp:56
MusicPlayer::changeCurrentTrack
void changeCurrentTrack(int trackNo)
change the current track to the given track
Definition: musicplayer.cpp:1148
gCDdevice
QString gCDdevice
Definition: musicplayer.cpp:38
MusicPlayer::m_resumeModeRadio
ResumeMode m_resumeModeRadio
Definition: musicplayer.h:248
MuteState
MuteState
Definition: volumebase.h:6
PlaylistContainer::getActive
Playlist * getActive(void)
Definition: playlistcontainer.h:47
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
MusicPlayer::sendTrackStatsChangedEvent
void sendTrackStatsChangedEvent(int trackID)
Definition: musicplayer.cpp:1353
cddecoder.h
MythObservable::addListener
void addListener(QObject *listener)
Add a listener to the observable.
Definition: mythobservable.cpp:38
MusicPlayer::ResumeMode
ResumeMode
Definition: musicplayer.h:183
MusicPlayerEvent::kPlayedTracksChangedEvent
static const Type kPlayedTracksChangedEvent
Definition: musicplayer.h:50
MusicPlayer::getCurrentMetadata
MusicMetadata * getCurrentMetadata(void)
get the metadata for the current track in the playlist
Definition: musicplayer.cpp:1170
MusicPlayer::getNotificationID
int getNotificationID(const QString &hostname)
Definition: musicplayer.cpp:1628
MythTV::Visual
Definition: visual.h:16
DecoderHandler
Class for starting stream decoding.
Definition: decoderhandler.h:77
MythCoreContext::UnregisterForPlayback
void UnregisterForPlayback(QObject *sender)
Definition: mythcorecontext.cpp:1958
MusicPlayer::SHUFFLE_OFF
@ SHUFFLE_OFF
Definition: musicplayer.h:175
OutputEvent::kStopped
static const Type kStopped
Definition: output.h:67
MusicPlayer::toggleRepeatMode
RepeatMode toggleRepeatMode(void)
Definition: musicplayer.cpp:1207
DecoderHandlerEvent
Events sent by the DecoderHandler and it's helper classes.
Definition: decoderhandler.h:25
Decoder
Definition: decoder.h:70
MusicPlayer::m_lastTrackStart
std::chrono::seconds m_lastTrackStart
Definition: musicplayer.h:258
AUDIOOUTPUT_MUSIC
@ AUDIOOUTPUT_MUSIC
Definition: audiosettings.h:24
MusicPlayer::removeVisual
void removeVisual(MainVisual *visual)
Definition: musicplayer.cpp:191
DecoderHandlerEvent::getBufferStatus
void getBufferStatus(int *available, int *maxSize) const
Definition: decoderhandler.cpp:61
MusicPlayer::incVolume
void incVolume(void)
Definition: musicplayer.cpp:1377
AudioOutput::Pause
virtual void Pause(bool paused)=0
CdDecoder
Definition: cddecoder.h:24
METADATA_INVALID_FILENAME
static constexpr const char * METADATA_INVALID_FILENAME
Definition: musicmetadata.h:73
Decoder::unlock
virtual void unlock(void)
Definition: decoder.h:86
VolumeBase::ToggleMute
virtual void ToggleMute(void)
Definition: volumebase.cpp:144
MusicMetadata::setLength
void setLength(T llength)
Definition: musicmetadata.h:207
MusicData::reloadMusic
void reloadMusic(void) const
reload music after a scan, rip or import
Definition: musicdata.cpp:58
MusicPlayer::toggleShuffleMode
ShuffleMode toggleShuffleMode(void)
Definition: musicplayer.cpp:1226
MusicPlayerEvent::kTrackChangeEvent
static const Type kTrackChangeEvent
Definition: musicplayer.h:39
MusicPlayer::m_currentTrack
int m_currentTrack
Definition: musicplayer.h:223
Playlist::removeTrack
void removeTrack(MusicMetadata::IdType trackID)
Definition: playlist.cpp:116
MusicPlayer::m_wasPlaying
bool m_wasPlaying
Definition: musicplayer.h:238
DecoderEvent
Definition: decoder.h:29
OutputEvent::kInfo
static const Type kInfo
Definition: output.h:65
OutputListeners::setBufferSize
void setBufferSize(unsigned int sz)
Definition: output.h:114
MythCoreContext::GetDurSetting
std::enable_if_t< std::chrono::__is_duration< T >::value, T > GetDurSetting(const QString &key, T defaultval=T::zero())
Definition: mythcorecontext.h:168
MusicData::m_all_streams
AllStream * m_all_streams
Definition: musicdata.h:57
AllStream::getStreams
StreamList * getStreams(void)
Definition: musicmetadata.h:489
PlaylistContainer::getStreamPlaylist
Playlist * getStreamPlaylist(void)
Definition: playlistcontainer.h:50
MusicPlayer::setupDecoderHandler
void setupDecoderHandler(void)
Definition: musicplayer.cpp:1505
MusicPlayer::PlayMode
PlayMode
Definition: musicplayer.h:69
MusicMetadata::setTitle
void setTitle(const QString &ltitle, const QString &ltitle_sort=nullptr)
Definition: musicmetadata.h:164
MusicPlayer::m_output
AudioOutput * m_output
Definition: musicplayer.h:228
MusicPlayer::nextAuto
void nextAuto(void)
Definition: musicplayer.cpp:498
Playlist::getTrackCount
int getTrackCount(void)
Definition: playlist.h:82
MythErrorNotification
Definition: mythnotification.h:198
MusicPlayer::REPEAT_TRACK
@ REPEAT_TRACK
Definition: musicplayer.h:170
MusicPlayerEvent::kTrackStatsChangedEvent
static const Type kTrackStatsChangedEvent
Definition: musicplayer.h:46
VolumeBase::GetMuteState
virtual MuteState GetMuteState(void) const
Definition: volumebase.cpp:150
MusicPlayer::sendTrackUnavailableEvent
void sendTrackUnavailableEvent(int trackID)
Definition: musicplayer.cpp:1365
SendStringListThread
send a message to the master BE without blocking the UI thread
Definition: musicdata.h:22
Decoder::stop
virtual void stop()=0
Playlist::addTrack
void addTrack(MusicMetadata::IdType trackID, bool update_display)
Given a tracks ID, add that track to this playlist.
Definition: playlist.cpp:62
MusicPlayer::stopDecoder
void stopDecoder(void)
Definition: musicplayer.cpp:366
MusicPlayer::m_shuffleMode
ShuffleMode m_shuffleMode
Definition: musicplayer.h:244
MusicPlayer::incSpeed
void incSpeed()
Definition: musicplayer.cpp:1329
MusicPlayer::RESUME_FIRST
@ RESUME_FIRST
Definition: musicplayer.h:185
Playlist::disableSaves
void disableSaves(void)
whether any changes should be saved to the DB
Definition: playlist.h:102
MythCoreContext::RegisterForPlayback
void RegisterForPlayback(QObject *sender, PlaybackStartCb method)
Definition: mythcorecontext.cpp:1937
MusicPlayer::m_autoShowPlayer
bool m_autoShowPlayer
Definition: musicplayer.h:237
MusicPlayer::SHUFFLE_ARTIST
@ SHUFFLE_ARTIST
Definition: musicplayer.h:179
MusicPlayer::savePosition
void savePosition(void)
Definition: musicplayer.cpp:1062
MusicMetadata::setFilename
void setFilename(const QString &lfilename)
Definition: musicmetadata.cpp:956
kMuteOff
@ kMuteOff
Definition: volumebase.h:7
MythObservable::hasListeners
bool hasListeners(void)
Definition: mythobservable.h:23
Decoder::getURL
QString getURL(void) const
Definition: decoder.h:91
MusicPlayer::playlistChanged
void playlistChanged(int playlistID)
Definition: musicplayer.cpp:1499
MusicPlayer::sendMetadataChangedEvent
void sendMetadataChangedEvent(int trackID)
Definition: musicplayer.cpp:1347
MusicPlayer::hasClient
bool hasClient(void)
Definition: musicplayer.h:112
DecoderEvent::kStopped
static const Type kStopped
Definition: decoder.h:46
AllMusic::getMetadata
MusicMetadata * getMetadata(int an_id)
Definition: musicmetadata.cpp:1634
uint
unsigned int uint
Definition: compat.h:81
MusicPlayer::removeTrack
void removeTrack(int trackID)
Definition: musicplayer.cpp:1593
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
MusicData::m_all_playlists
PlaylistContainer * m_all_playlists
Definition: musicdata.h:55
MusicPlayer::next
void next(void)
Definition: musicplayer.cpp:430
MusicPlayer::isPaused
bool isPaused(void)
Definition: musicplayer.h:110
CdDecoder::setDevice
void setDevice(const QString &dev)
Definition: cddecoder.cpp:104
MusicPlayer::m_allowRestorePos
bool m_allowRestorePos
Definition: musicplayer.h:240
MusicPlayer::updateLastplay
void updateLastplay(void)
Definition: musicplayer.cpp:1282
MusicPlayer::showMiniPlayer
void showMiniPlayer(void) const
Definition: musicplayer.cpp:1131
MusicPlayer
Definition: musicplayer.h:61
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:912
DecoderHandlerEvent::kMeta
static const Type kMeta
Definition: decoderhandler.h:47
musicdata.h
MythCoreContext::TVPlaybackAborted
void TVPlaybackAborted(void)
MusicPlayer::m_updatedLastplay
bool m_updatedLastplay
Definition: musicplayer.h:239
MusicPlayer::SHUFFLE_RANDOM
@ SHUFFLE_RANDOM
Definition: musicplayer.h:176
StreamList
QList< MusicMetadata * > StreamList
Definition: musicmetadata.h:474
MusicMetadata::Album
QString Album() const
Definition: musicmetadata.h:150
gMusicData
MusicData * gMusicData
Definition: musicdata.cpp:21
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:906
Playlist::moveTrackUpDown
void moveTrackUpDown(bool flag, int where_its_at)
Definition: playlist.cpp:127
DecoderHandler::start
void start(MusicMetadata *mdata)
Definition: decoderhandler.cpp:74
MusicPlayerEvent::kTrackUnavailableEvent
static const Type kTrackUnavailableEvent
Definition: musicplayer.h:43
MusicMetadata::IdType
uint32_t IdType
Definition: musicmetadata.h:86
MusicPlayer::getNextMetadata
MusicMetadata * getNextMetadata(void)
get the metadata for the next track in the playlist
Definition: musicplayer.cpp:1182
mthreadpool.h
mythuihelper.h
MusicPlayerEvent::kCDChangedEvent
static const Type kCDChangedEvent
Definition: musicplayer.h:48
MainVisual
Definition: mainvisual.h:34
MusicPlayer::decoderHandlerReady
void decoderHandlerReady(void)
Definition: musicplayer.cpp:1519
MusicPlayer::previous
void previous(void)
Definition: musicplayer.cpp:467
Decoder::initialize
virtual bool initialize()=0
MusicPlayer::m_visualisers
QSet< QObject * > m_visualisers
Definition: musicplayer.h:231
MythCoreContext::InWantingPlayback
bool InWantingPlayback(void)
Returns true if a client has requested playback.
Definition: mythcorecontext.cpp:2055
MusicMetadata::reloadMetadata
void reloadMetadata(void)
Definition: musicmetadata.cpp:428
MusicMetadata::dumpToDatabase
void dumpToDatabase(void)
Definition: musicmetadata.cpp:668
MusicPlayer::getDecoderHandler
DecoderHandler * getDecoderHandler(void)
Definition: musicplayer.h:127
MythNotification::kInfo
static const Type kInfo
Definition: mythnotification.h:34
MusicPlayer::decSpeed
void decSpeed()
Definition: musicplayer.cpp:1335
MusicMetadata::setArtist
void setArtist(const QString &lartist, const QString &lartist_sort=nullptr)
Definition: musicmetadata.h:128
MusicPlayer::activePlaylistChanged
void activePlaylistChanged(int trackID, bool deleted)
Definition: musicplayer.cpp:1436
MusicMetadata::Hostname
QString Hostname(void)
Definition: musicmetadata.h:230
MusicPlayer::m_canShowPlayer
bool m_canShowPlayer
Definition: musicplayer.h:236
MusicPlayer::setSpeed
void setSpeed(float speed)
Definition: musicplayer.cpp:1320
DecoderEvent::kFinished
static const Type kFinished
Definition: decoder.h:47
MusicPlayer::setRepeatMode
void setRepeatMode(RepeatMode mode)
Definition: musicplayer.h:192
MusicPlayer::m_repeatMode
RepeatMode m_repeatMode
Definition: musicplayer.h:245
MusicPlayer::REPEAT_OFF
@ REPEAT_OFF
Definition: musicplayer.h:169
metaio.h
OutputEvent::kError
static const Type kError
Definition: output.h:68
MusicPlayer::RepeatMode
RepeatMode
Definition: musicplayer.h:168
MusicPlayer::addTrack
void addTrack(int trackID, bool updateUI)
Definition: musicplayer.cpp:1606
MusicPlayer::SHUFFLE_ALBUM
@ SHUFFLE_ALBUM
Definition: musicplayer.h:178
AudioOutput::SetStretchFactor
virtual void SetStretchFactor(float factor)
Definition: audiooutput.cpp:248
constants.h
DecoderHandlerEvent::kError
static const Type kError
Definition: decoderhandler.h:51
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
MusicMetadata::LastPlay
QDateTime LastPlay() const
Definition: musicmetadata.h:244
audiooutput.h
Decoder::setOutput
void setOutput(AudioOutput *o)
Definition: decoder.cpp:45
MusicPlayer::m_playedList
QList< MusicMetadata * > m_playedList
Definition: musicplayer.h:257
DecoderHandler::getMetadata
MusicMetadata & getMetadata()
Definition: decoderhandler.h:102
MusicPlayer::customEvent
void customEvent(QEvent *event) override
Definition: musicplayer.cpp:555
DecoderHandlerEvent::kBufferStatus
static const Type kBufferStatus
Definition: decoderhandler.h:48
DecoderHandlerEvent::kReady
static const Type kReady
Definition: decoderhandler.h:46
MiniPlayer
Definition: miniplayer.h:12
MusicPlayer::isMuted
bool isMuted(void) const
Definition: musicplayer.h:89
GetNotificationCenter
MythNotificationCenter * GetNotificationCenter(void)
Definition: mythmainwindow.cpp:124
mythcontext.h
miniplayer.h
MythNotificationCenter::UnRegister
void UnRegister(void *from, int id, bool closeimemdiately=false)
Unregister the client.
Definition: mythnotificationcenter.cpp:1373
MusicPlayer::m_resumeModeEditor
ResumeMode m_resumeModeEditor
Definition: musicplayer.h:247
MusicPlayer::sendVolumeChangedEvent
void sendVolumeChangedEvent(void)
Definition: musicplayer.cpp:1341
mainvisual.h
MusicPlayer::~MusicPlayer
~MusicPlayer(void) override
Definition: musicplayer.cpp:88
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
MThread::isRunning
bool isRunning(void) const
Definition: mthread.cpp:263
Playlist::getTrackPosition
int getTrackPosition(MusicMetadata::IdType trackID)
Definition: playlist.h:90
MusicPlayer::loadSettings
void loadSettings(void)
Definition: musicplayer.cpp:214
MusicPlayer::PLAYMODE_RADIO
@ PLAYMODE_RADIO
Definition: musicplayer.h:73
MusicPlayerEvent::kTrackRemovedEvent
static const Type kTrackRemovedEvent
Definition: musicplayer.h:42
MusicPlayer::sendAlbumArtChangedEvent
void sendAlbumArtChangedEvent(int trackID)
Definition: musicplayer.cpp:1359
MusicPlayer::m_oneshotMetadata
MusicMetadata * m_oneshotMetadata
Definition: musicplayer.h:226
MusicPlayer::play
void play(void)
Definition: musicplayer.cpp:317
MusicPlayer::restorePosition
void restorePosition(void)
Definition: musicplayer.cpp:1079
MusicMetadata::setLastPlay
void setLastPlay()
Definition: musicmetadata.cpp:1188
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:323
MythCoreContext::WantingPlayback
void WantingPlayback(QObject *sender)
All the objects that have registered using MythCoreContext::RegisterForPlayback but sender will be ca...
Definition: mythcorecontext.cpp:1977
MusicData::m_all_music
AllMusic * m_all_music
Definition: musicdata.h:56
MusicPlayer::sendCDChangedEvent
void sendCDChangedEvent(void)
Definition: musicplayer.cpp:1371
MusicPlayerEvent::kTrackAddedEvent
static const Type kTrackAddedEvent
Definition: musicplayer.h:41
MusicPlayer::seek
void seek(std::chrono::seconds pos)
Definition: musicplayer.cpp:1119
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:838
DecoderHandler::stop
void stop(void)
Definition: decoderhandler.cpp:175
MusicPlayer::playFile
void playFile(const MusicMetadata &mdata)
Definition: musicplayer.cpp:235
MusicPlayerEvent::kVolumeChangeEvent
static const Type kVolumeChangeEvent
Definition: musicplayer.h:40
Decoder::lock
virtual void lock(void)
Definition: decoder.h:85
MusicPlayer::m_isPlaying
bool m_isPlaying
Definition: musicplayer.h:234
Playlist::removeAllTracks
void removeAllTracks(void)
Definition: playlist.cpp:86
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
MusicPlayer::stop
void stop(bool stopAll=false)
Definition: musicplayer.cpp:249
MusicPlayer::m_errorCount
int m_errorCount
Definition: musicplayer.h:262
MusicPlayer::m_playSpeed
float m_playSpeed
Definition: musicplayer.h:250
MythCoreContext::TVPlaybackStopped
void TVPlaybackStopped(void)
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:881
DMAP
QMap< QString, QString > DMAP
Definition: mythnotification.h:26
MusicPlayer::getBufferStatus
void getBufferStatus(int *bufferAvailable, int *bufferSize) const
Definition: musicplayer.cpp:958
MusicPlayer::setPlayNow
static void setPlayNow(bool PlayNow)
whether we prefer Play Now over Add Tracks
Definition: musicplayer.cpp:225
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:66
build_compdb.filename
filename
Definition: build_compdb.py:21
Decoder::seek
virtual void seek(double)=0
MThreadPool::globalInstance
static MThreadPool * globalInstance(void)
Definition: mthreadpool.cpp:307
mythmainwindow.h
MusicPlayer::getVolume
uint getVolume(void) const
Definition: musicplayer.cpp:1404
LASTPLAY_DELAY
static constexpr std::chrono::seconds LASTPLAY_DELAY
Definition: musicplayer.h:14
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
MusicPlayer::m_currentTime
std::chrono::seconds m_currentTime
Definition: musicplayer.h:224
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1719
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:562
MusicPlayerEvent::kPlaylistChangedEvent
static const Type kPlaylistChangedEvent
Definition: musicplayer.h:49
DecoderEvent::kError
static const Type kError
Definition: decoder.h:48
MythObservable::removeListener
void removeListener(QObject *listener)
Remove a listener to the observable.
Definition: mythobservable.cpp:55
AudioOutput::PauseUntilBuffered
virtual void PauseUntilBuffered(void)=0
MusicPlayer::m_isAutoplay
bool m_isAutoplay
Definition: musicplayer.h:235
MythCoreContext::SaveBoolSetting
void SaveBoolSetting(const QString &key, bool newValue)
Definition: mythcorecontext.h:160
AudioOutput::IsPaused
virtual bool IsPaused(void) const =0
MThreadPool::start
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Definition: mthreadpool.cpp:342
MusicPlayer::addListener
void addListener(QObject *listener)
Definition: musicplayer.cpp:145
MusicPlayer::RESUME_EXACT
@ RESUME_EXACT
Definition: musicplayer.h:187
decoder.h
MusicPlayer::ShuffleMode
ShuffleMode
Definition: musicplayer.h:174
MythMainWindow::PauseIdleTimer
void PauseIdleTimer(bool Pause)
Pause the idle timeout timer.
Definition: mythmainwindow.cpp:2154
AudioOutput::SetTimecode
virtual void SetTimecode(std::chrono::milliseconds timecode)=0
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:898
MusicPlayerEvent::kAlbumArtChangedEvent
static const Type kAlbumArtChangedEvent
Definition: musicplayer.h:47
musicplayer.h
MusicPlayer::REPEAT_ALL
@ REPEAT_ALL
Definition: musicplayer.h:171
MythNotificationCenter::Queue
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
Definition: mythnotificationcenter.cpp:1349
MusicPlayer::moveTrackUpDown
void moveTrackUpDown(bool moveUp, int whichTrack)
Definition: musicplayer.cpp:1029