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