MythTV  master
mythmusic.cpp
Go to the documentation of this file.
1 // C++ headers
2 #include <cstdlib>
3 #include <sys/stat.h>
4 #include <sys/types.h>
5 #include <unistd.h>
6 
7 // Qt headers
8 #include <QApplication>
9 #include <QDir>
10 #include <QScopedPointer>
11 
12 // MythTV headers
13 #include <libmythbase/compat.h>
14 #include <libmythbase/lcddevice.h>
16 #include <libmythbase/mythdb.h>
17 #include <libmythbase/mythdbcon.h>
19 #include <libmythbase/mythplugin.h>
21 #include <libmythbase/mythversion.h>
22 #include <libmythmetadata/metaio.h>
26 #include <libmythui/mediamonitor.h>
29 #include <libmythui/mythuihelper.h>
30 
31 // MythMusic headers
32 #include "cddecoder.h"
33 #include "config.h"
34 #include "decoder.h"
35 #include "generalsettings.h"
36 #include "importmusic.h"
37 #include "importsettings.h"
38 #include "mainvisual.h"
39 #include "musicdata.h"
40 #include "musicdbcheck.h"
41 #include "musicplayer.h"
42 #include "playersettings.h"
43 #include "playlistcontainer.h"
44 #include "playlisteditorview.h"
45 #include "playlistview.h"
46 #include "ratingsettings.h"
47 #include "streamview.h"
48 #include "visualizationsettings.h"
49 
50 #ifdef HAVE_CDIO
51 #include "cdrip.h"
52 #endif
53 
54 #if defined HAVE_CDIO
55 
58 static QString chooseCD(void)
59 {
60  if (!gCDdevice.isEmpty())
61  return gCDdevice;
62 
63 #ifdef Q_OS_DARWIN
65 #endif
66 
68 }
69 #endif
70 
72 static bool checkStorageGroup(void)
73 {
74  // get a list of hosts with a directory defined for the 'Music' storage group
75  QStringList hostList;
77  QString sql = "SELECT DISTINCT hostname "
78  "FROM storagegroup "
79  "WHERE groupname = 'Music'";
80  if (!query.exec(sql) || !query.isActive())
81  MythDB::DBError("checkStorageGroup get host list", query);
82  else
83  {
84  while(query.next())
85  {
86  hostList.append(query.value(0).toString());
87  }
88  }
89 
90  if (hostList.isEmpty())
91  {
92  ShowOkPopup(QCoreApplication::translate("(MythMusicMain)",
93  "No directories found in the 'Music' storage group. "
94  "Please run mythtv-setup on the backend machine to add one."));
95  return false;
96  }
97 
98  // get a list of hosts with a directory defined for the 'MusicArt' storage group
99  hostList.clear();
100  sql = "SELECT DISTINCT hostname "
101  "FROM storagegroup "
102  "WHERE groupname = 'MusicArt'";
103  if (!query.exec(sql) || !query.isActive())
104  MythDB::DBError("checkStorageGroup get host list", query);
105  else
106  {
107  while(query.next())
108  {
109  hostList.append(query.value(0).toString());
110  }
111  }
112 
113  if (hostList.isEmpty())
114  {
115  ShowOkPopup(QCoreApplication::translate("(MythMusicMain)",
116  "No directories found in the 'MusicArt' storage group. "
117  "Please run mythtv-setup on the backend machine to add one."));
118  return false;
119  }
120 
121  return true;
122 }
123 
125 static bool checkMusicAvailable(void)
126 {
127  MSqlQuery count_query(MSqlQuery::InitCon());
128  bool foundMusic = false;
129  if (count_query.exec("SELECT COUNT(*) FROM music_songs;"))
130  {
131  if(count_query.next() &&
132  0 != count_query.value(0).toInt())
133  {
134  foundMusic = true;
135  }
136  }
137 
138  if (!foundMusic)
139  {
140  ShowOkPopup(QCoreApplication::translate("(MythMusicMain)",
141  "No music has been found.\n"
142  "Please select 'Scan For New Music' "
143  "to perform a scan for music."));
144  }
145 
146  return foundMusic;
147 }
148 
149 static void startPlayback(void)
150 {
152  return;
153 
155 
157 
158  auto *view = new PlaylistView(mainStack, nullptr);
159 
160  if (view->Create())
161  mainStack->AddScreen(view);
162  else
163  delete view;
164 }
165 
166 static void startStreamPlayback(void)
167 {
169 
171 
172  auto *view = new StreamView(mainStack, nullptr);
173 
174  if (view->Create())
175  mainStack->AddScreen(view);
176  else
177  delete view;
178 }
179 
180 static void startDatabaseTree(void)
181 {
183  return;
184 
186 
188 
189  QString lastView = gCoreContext->GetSetting("MusicPlaylistEditorView", "tree");
190  auto *view = new PlaylistEditorView(mainStack, nullptr, lastView);
191 
192  if (view->Create())
193  mainStack->AddScreen(view);
194  else
195  delete view;
196 }
197 
198 static void startRipper(void)
199 {
200 #if defined HAVE_CDIO
201  if (!checkStorageGroup())
202  return;
203 
205 
207 
208  auto *rip = new Ripper(mainStack, chooseCD());
209 
210  if (rip->Create())
211  {
212  mainStack->AddScreen(rip);
213  QObject::connect(rip, &Ripper::ripFinished,
215  Qt::QueuedConnection);
216  }
217  else
218  {
219  delete rip;
220  }
221 
222 #else
223  ShowOkPopup(QCoreApplication::translate("(MythMusicMain)",
224  "MythMusic hasn't been built with libcdio "
225  "support so ripping CDs is not possible"));
226 #endif
227 }
228 
229 static void runScan(void)
230 {
231  if (!checkStorageGroup())
232  return;
233 
234  LOG(VB_GENERAL, LOG_INFO, "Scanning for music files");
235 
237 }
238 
239 static void startImport(void)
240 {
241  if (!checkStorageGroup())
242  return;
243 
245 
247 
248  auto *import = new ImportMusicDialog(mainStack);
249 
250  if (import->Create())
251  {
252  mainStack->AddScreen(import);
253  QObject::connect(import, &ImportMusicDialog::importFinished,
255  Qt::QueuedConnection);
256  }
257  else
258  {
259  delete import;
260  }
261 }
262 
263 // these point to the the mainmenu callback if found
264 static void (*m_callback)(void *, QString &) = nullptr;
265 static void *m_callbackdata = nullptr;
266 
267 static void MusicCallback([[maybe_unused]] void *data, QString &selection)
268 {
269  QString sel = selection.toLower();
270  if (sel == "music_create_playlist")
272  else if (sel == "music_play")
273  startPlayback();
274  else if (sel == "stream_play")
276  else if (sel == "music_rip")
277  {
278  startRipper();
279  }
280  else if (sel == "music_import")
281  {
282  startImport();
283  }
284  else if (sel == "settings_scan")
285  {
286  runScan();
287  }
288  else if (sel == "settings_general")
289  {
291  auto *gs = new GeneralSettings(mainStack, "general settings");
292 
293  if (gs->Create())
294  mainStack->AddScreen(gs);
295  else
296  delete gs;
297  }
298  else if (sel == "settings_player")
299  {
301  auto *ps = new PlayerSettings(mainStack, "player settings");
302 
303  if (ps->Create())
304  mainStack->AddScreen(ps);
305  else
306  delete ps;
307  }
308  else if (sel == "settings_rating")
309  {
311  auto *rs = new RatingSettings(mainStack, "rating settings");
312 
313  if (rs->Create())
314  mainStack->AddScreen(rs);
315  else
316  delete rs;
317  }
318  else if (sel == "settings_visualization")
319  {
320 
322  auto *vs = new VisualizationSettings(mainStack, "visualization settings");
323 
324  if (vs->Create())
325  mainStack->AddScreen(vs);
326  else
327  delete vs;
328  }
329  else if (sel == "settings_import")
330  {
332  auto *is = new ImportSettings(mainStack, "import settings");
333 
334  if (is->Create())
335  mainStack->AddScreen(is);
336  else
337  delete is;
338  }
339  else
340  {
341  // if we have found the mainmenu callback
342  // pass the selection on to it
343  if (m_callback && m_callbackdata)
344  m_callback(m_callbackdata, selection);
345  }
346 }
347 
348 static int runMenu(const QString& which_menu)
349 {
350  QString themedir = GetMythUI()->GetThemeDir();
351 
352  // find the 'mainmenu' MythThemedMenu so we can use the callback from it
353  MythThemedMenu *mainMenu = nullptr;
354  QObject *parentObject = GetMythMainWindow()->GetMainStack()->GetTopScreen();
355 
356  while (parentObject)
357  {
358  auto *menu = qobject_cast<MythThemedMenu *>(parentObject);
359 
360  if (menu && menu->objectName() == "mainmenu")
361  {
362  mainMenu = menu;
363  break;
364  }
365 
366  parentObject = parentObject->parent();
367  }
368 
369  auto *diag = new MythThemedMenu(themedir, which_menu,
370  GetMythMainWindow()->GetMainStack(),
371  "music menu");
372 
373  // save the callback from the main menu
374  if (mainMenu)
375  mainMenu->getCallback(&m_callback, &m_callbackdata);
376 
377  diag->setCallback(MusicCallback, nullptr);
378  diag->setKillable();
379 
380  if (diag->foundTheme())
381  {
382  if (LCD *lcd = LCD::Get())
383  {
384  lcd->switchToTime();
385  }
387  return 0;
388  }
389  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find menu %1 or theme %2")
390  .arg(which_menu, themedir));
391  delete diag;
392  return -1;
393 }
394 
395 static void runMusicPlayback(void)
396 {
397  GetMythUI()->AddCurrentLocation("playmusic");
398  startPlayback();
400 }
401 
402 static void runMusicStreamPlayback(void)
403 {
404  GetMythUI()->AddCurrentLocation("streammusic");
407 }
408 
409 static void runMusicSelection(void)
410 {
411  GetMythUI()->AddCurrentLocation("musicplaylists");
414 }
415 
416 static void runRipCD(void)
417 {
419 
420 #if defined HAVE_CDIO
422 
423  auto *rip = new Ripper(mainStack, chooseCD());
424 
425  if (rip->Create())
426  mainStack->AddScreen(rip);
427  else
428  {
429  delete rip;
430  return;
431  }
432 
433  QObject::connect(rip, &Ripper::ripFinished,
435  Qt::QueuedConnection);
436 #endif
437 }
438 
439 static void showMiniPlayer(void)
440 {
441  if (!gMusicData->m_all_music)
442  return;
443 
444  // only show the miniplayer if there isn't already a client attached
445  if (!gPlayer->hasClient())
447 }
448 
449 static QStringList GetMusicFilter()
450 {
451  QString filt = MetaIO::kValidFileExtensions;
452  filt.replace(".", "*.");
453  return filt.split('|');
454 }
455 
456 static QStringList BuildFileList(const QString &dir, const QStringList &filters)
457 {
458  QStringList ret;
459 
460  QDir d(dir);
461  if (!d.exists())
462  return ret;
463 
464  d.setNameFilters(filters);
465  d.setFilter(QDir::Files | QDir::AllDirs |
466  QDir::NoSymLinks | QDir::Readable |
467  QDir::NoDotAndDotDot);
468  d.setSorting(QDir::Name | QDir::DirsLast);
469 
470  QFileInfoList list = d.entryInfoList();
471  if (list.isEmpty())
472  return ret;
473 
474  for (const auto & fi : std::as_const(list))
475  {
476  if (fi.isDir())
477  {
478  ret += BuildFileList(fi.absoluteFilePath(), filters);
479  QCoreApplication::processEvents();
480  }
481  else
482  {
483  ret << fi.absoluteFilePath();
484  }
485  }
486  return ret;
487 }
488 
489 static void handleMedia(MythMediaDevice *cd, bool forcePlayback)
490 {
491  static QString s_mountPath;
492 
493  if (!cd)
494  return;
495 
496  if (MEDIASTAT_MOUNTED != cd->getStatus())
497  {
498  if (s_mountPath != cd->getMountPath())
499  return;
500 
501  LOG(VB_MEDIA, LOG_INFO, QString(
502  "MythMusic: '%1' unmounted, clearing data").arg(cd->getVolumeID()));
503 
506  {
507  // Now playing a track which is no longer available so stop playback
508  gPlayer->stop(true);
509  }
510 
511  // device is not usable so remove any existing CD tracks
513  {
516  }
517 
518  gPlayer->activePlaylistChanged(-1, false);
520 
521  return;
522  }
523 
524  LOG(VB_MEDIA, LOG_NOTICE, QString("MythMusic: '%1' mounted on '%2'")
525  .arg(cd->getVolumeID(), cd->getMountPath()) );
526 
527  s_mountPath.clear();
528 
529  // don't show the music screen if AutoPlayCD is off
530  if (!forcePlayback && !gCoreContext->GetBoolSetting("AutoPlayCD", false))
531  return;
532 
535 
536  // remove any existing CD tracks
539 
541 
542  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
543 
544  QString message = QCoreApplication::translate("(MythMusicMain)",
545  "Searching for music files...");
546  auto *busy = new MythUIBusyDialog( message, popupStack, "musicscanbusydialog");
547  if (busy->Create())
548  popupStack->AddScreen(busy, false);
549  else
550  {
551  delete busy;
552  busy = nullptr;
553  }
554 
555  // Search for music files
556  QStringList trackList = BuildFileList(cd->getMountPath(), GetMusicFilter());
557  LOG(VB_MEDIA, LOG_INFO, QString("MythMusic: %1 music files found")
558  .arg(trackList.count()));
559 
560  if (busy)
561  busy->Close();
562 
563  if (trackList.isEmpty())
564  return;
565 
566  message = QCoreApplication::translate("(MythMusicMain)", "Loading music tracks");
567  auto *progress = new MythUIProgressDialog( message, popupStack,
568  "scalingprogressdialog");
569  if (progress->Create())
570  {
571  popupStack->AddScreen(progress, false);
572  progress->SetTotal(trackList.count());
573  }
574  else
575  {
576  delete progress;
577  progress = nullptr;
578  }
579 
580  // Read track metadata and add to all_music
581  int track = 0;
582  for (const auto & file : std::as_const(trackList))
583  {
584  QScopedPointer<MusicMetadata> meta(MetaIO::readMetadata(file));
585  if (meta)
586  {
587  meta->setTrack(++track);
589  }
590  if (progress)
591  {
592  progress->SetProgress(track);
593  QCoreApplication::processEvents();
594  }
595  }
596  LOG(VB_MEDIA, LOG_INFO, QString("MythMusic: %1 tracks scanned").arg(track));
597 
598  if (progress)
599  progress->Close();
600 
601  // Remove all tracks from the playlist
603 
604  // Create list of new tracks
605  QList<int> songList;
606  const int tracks = gMusicData->m_all_music->getCDTrackCount();
607  for (track = 1; track <= tracks; track++)
608  {
610  if (mdata)
611  songList.append(mdata->ID());
612  }
613  if (songList.isEmpty())
614  return;
615 
616  s_mountPath = cd->getMountPath();
617 
618  // Add new tracks to playlist
620  songList, true, PL_REPLACE, 0);
622 
623  // if there is no music screen showing then show the Playlist view
624  if (!gPlayer->hasClient())
625  {
626  // make sure we start playing from the first track
627  gCoreContext->SaveSetting("MusicBookmark", 0);
628  gCoreContext->SaveSetting("MusicBookmarkPosition", 0);
629 
631  }
632 }
633 
634 #ifdef HAVE_CDIO
635 static void handleCDMedia(MythMediaDevice *cd, bool forcePlayback)
636 {
637 
638  if (!cd)
639  return;
640 
641  LOG(VB_MEDIA, LOG_NOTICE, "Got a CD media changed event");
642 
643  QString newDevice;
644 
645  // save the device if valid
646  if (cd->isUsable())
647  {
648 #ifdef Q_OS_DARWIN
649  newDevice = cd->getMountPath();
650 #else
651  newDevice = cd->getDevicePath();
652 #endif
653 
654  gCDdevice = newDevice;
655  LOG(VB_MEDIA, LOG_INFO, "MythMusic: Storing CD device " + gCDdevice);
656  }
657  else
658  {
659  LOG(VB_MEDIA, LOG_INFO, "Device is not usable clearing cd data");
660 
663  {
664  // we was playing a cd track which is no longer available so stop playback
665  // TODO should check the playing track is from the ejected drive if more than one is available
666  gPlayer->stop(true);
667  }
668 
669  // device is not usable so remove any existing CD tracks
670  if (gMusicData->m_all_music)
671  {
674  }
675 
676  gPlayer->activePlaylistChanged(-1, false);
678 
679  return;
680  }
681 
684 
685  // wait for the music and playlists to load
688  {
689  QCoreApplication::processEvents();
690  usleep(50000);
691  }
692 
693  // remove any existing CD tracks
696 
697  // find any new cd tracks
698  auto *decoder = new CdDecoder("cda", nullptr, nullptr);
699  decoder->setDevice(newDevice);
700 
701  int tracks = decoder->getNumTracks();
702  bool setTitle = false;
703 
704  for (int trackNo = 1; trackNo <= tracks; trackNo++)
705  {
706  MusicMetadata *track = decoder->getMetadata(trackNo);
707  if (track)
708  {
710 
711  if (!setTitle)
712  {
713 
714  QString parenttitle = " ";
715  if (track->FormatArtist().length() > 0)
716  {
717  parenttitle += track->FormatArtist();
718  parenttitle += " ~ ";
719  }
720 
721  if (track->Album().length() > 0)
722  parenttitle += track->Album();
723  else
724  {
725  parenttitle = " " + QCoreApplication::translate("(MythMusicMain)",
726  "Unknown");
727  LOG(VB_GENERAL, LOG_INFO, "Couldn't find your "
728  " CD. It may not be in the freedb database.\n"
729  " More likely, however, is that you need to delete\n"
730  " ~/.cddb and ~/.cdserverrc and restart MythMusic.");
731  }
732 
733  gMusicData->m_all_music->setCDTitle(parenttitle);
734  setTitle = true;
735  }
736 
737  delete track;
738  }
739  }
740 
742 
743  delete decoder;
744 
745  // if the AutoPlayCD setting is set we remove all the existing tracks
746  // from the playlist and replace them with the new CD tracks found
747  if (forcePlayback || gCoreContext->GetBoolSetting("AutoPlayCD", false))
748  {
750 
751  QList<int> songList;
752 
753  for (int x = 1; x <= gMusicData->m_all_music->getCDTrackCount(); x++)
754  {
756  if (mdata)
757  songList.append((mdata)->ID());
758  }
759 
760  if (!songList.isEmpty())
761  {
763  songList, true, PL_REPLACE, 0);
765  }
766  }
767  else
768  {
769  // don't show the music screen if AutoPlayCD is off
770  return;
771  }
772 
773  // if there is no music screen showing show the Playlist view
774  if (!gPlayer->hasClient())
775  {
776  // make sure we start playing from the first track
777  gCoreContext->SaveSetting("MusicBookmark", 0);
778  gCoreContext->SaveSetting("MusicBookmarkPosition", 0);
779 
781  }
782 }
783 #else
784 static void handleCDMedia([[maybe_unused]] MythMediaDevice *cd, [[maybe_unused]] bool forcePlayback)
785 {
786  LOG(VB_GENERAL, LOG_NOTICE, "MythMusic got a media changed event"
787  "but cdio support is not compiled in");
788 }
789 #endif
790 
791 static void setupKeys(void)
792 {
793  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Play music"),
794  "", "", runMusicPlayback);
795  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Select music playlists"),
796  "", "", runMusicSelection);
797  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Play radio stream"),
798  "", "", runMusicStreamPlayback);
799  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Rip CD"),
800  "", "", runRipCD);
801  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Scan music"),
802  "", "", runScan);
803  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Show Music Miniplayer"),
804  "", "", showMiniPlayer, false);
805 
806  REG_KEY("Music", "NEXTTRACK", QT_TRANSLATE_NOOP("MythControls",
807  "Move to the next track"), ">,.,Z,End,Media Next");
808  REG_KEY("Music", "PREVTRACK", QT_TRANSLATE_NOOP("MythControls",
809  "Move to the previous track"), ",,<,Q,Home,Media Previous");
810  REG_KEY("Music", "FFWD", QT_TRANSLATE_NOOP("MythControls",
811  "Fast forward"), "PgDown,Ctrl+F,Media Fast Forward");
812  REG_KEY("Music", "RWND", QT_TRANSLATE_NOOP("MythControls",
813  "Rewind"), "PgUp,Ctrl+B,Media Rewind");
814  REG_KEY("Music", "PAUSE", QT_TRANSLATE_NOOP("MythControls",
815  "Pause/Start playback"), "P,Media Play");
816  REG_KEY("Music", "PLAY", QT_TRANSLATE_NOOP("MythControls",
817  "Start playback"), "");
818  REG_KEY("Music", "STOP", QT_TRANSLATE_NOOP("MythControls",
819  "Stop playback"), "O,Media Stop");
820  REG_KEY("Music", "VOLUMEDOWN", QT_TRANSLATE_NOOP("MythControls",
821  "Volume down"), "[,{,F10,Volume Down");
822  REG_KEY("Music", "VOLUMEUP", QT_TRANSLATE_NOOP("MythControls",
823  "Volume up"), "],},F11,Volume Up");
824  REG_KEY("Music", "MUTE", QT_TRANSLATE_NOOP("MythControls",
825  "Mute"), "|,\\,F9,Volume Mute");
826  REG_KEY("Music", "TOGGLEUPMIX",QT_TRANSLATE_NOOP("MythControls",
827  "Toggle audio upmixer"), "Ctrl+U");
828  REG_KEY("Music", "CYCLEVIS", QT_TRANSLATE_NOOP("MythControls",
829  "Cycle visualizer mode"), "6");
830  REG_KEY("Music", "BLANKSCR", QT_TRANSLATE_NOOP("MythControls",
831  "Blank screen"), "5");
832  REG_KEY("Music", "THMBUP", QT_TRANSLATE_NOOP("MythControls",
833  "Increase rating"), "9");
834  REG_KEY("Music", "THMBDOWN", QT_TRANSLATE_NOOP("MythControls",
835  "Decrease rating"), "7");
836  REG_KEY("Music", "REFRESH", QT_TRANSLATE_NOOP("MythControls",
837  "Refresh music tree"), "8");
838  REG_KEY("Music", "SPEEDUP", QT_TRANSLATE_NOOP("MythControls",
839  "Increase Play Speed"), "W,3");
840  REG_KEY("Music", "SPEEDDOWN", QT_TRANSLATE_NOOP("MythControls",
841  "Decrease Play Speed"), "X,1");
842  REG_KEY("Music", "MARK", QT_TRANSLATE_NOOP("MythControls",
843  "Toggle track selection"), "T");
844  REG_KEY("Music", "TOGGLESHUFFLE", QT_TRANSLATE_NOOP("MythControls",
845  "Toggle shuffle mode"), "");
846  REG_KEY("Music", "TOGGLEREPEAT", QT_TRANSLATE_NOOP("MythControls",
847  "Toggle repeat mode"), "");
848  REG_KEY("Music", "TOGGLELAST", QT_TRANSLATE_NOOP("MythControls",
849  "Switch to previous radio stream"), "");
850 
851  // switch to view key bindings
852  REG_KEY("Music", "SWITCHTOPLAYLIST", QT_TRANSLATE_NOOP("MythControls",
853  "Switch to the current playlist view"), "");
854  REG_KEY("Music", "SWITCHTOPLAYLISTEDITORTREE", QT_TRANSLATE_NOOP("MythControls",
855  "Switch to the playlist editor tree view"), "");
856  REG_KEY("Music", "SWITCHTOPLAYLISTEDITORGALLERY", QT_TRANSLATE_NOOP("MythControls",
857  "Switch to the playlist editor gallery view"), "");
858  REG_KEY("Music", "SWITCHTOSEARCH", QT_TRANSLATE_NOOP("MythControls",
859  "Switch to the search view"), "");
860  REG_KEY("Music", "SWITCHTOVISUALISER", QT_TRANSLATE_NOOP("MythControls",
861  "Switch to the fullscreen visualiser view"), "");
862  REG_KEY("Music", "SWITCHTORADIO", QT_TRANSLATE_NOOP("MythControls",
863  "Switch to the radio stream view"), "");
864 
865  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
866  "MythMusic Media Handler 1/2"), "", handleCDMedia,
867  MEDIATYPE_AUDIO | MEDIATYPE_MIXED, QString());
868  QString filt = MetaIO::kValidFileExtensions;
869  filt.replace('|',',');
870  filt.remove('.');
871  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
872  "MythMusic Media Handler 2/2"), "", handleMedia,
873  MEDIATYPE_MMUSIC, filt);
874 }
875 
876 int mythplugin_init(const char *libversion)
877 {
878  if (!MythCoreContext::TestPluginVersion("mythmusic", libversion,
879  MYTH_BINARY_VERSION))
880  return -1;
881 
883  bool upgraded = UpgradeMusicDatabaseSchema();
885 
886  if (!upgraded)
887  {
888  LOG(VB_GENERAL, LOG_ERR,
889  "Couldn't upgrade music database schema, exiting.");
890  return -1;
891  }
892 
893  setupKeys();
894 
895  gPlayer = new MusicPlayer(nullptr);
896  gMusicData = new MusicData();
897 
898  return 0;
899 }
900 
901 
902 int mythplugin_run(void)
903 {
904  return runMenu("musicmenu.xml");
905 }
906 
908 {
909  return runMenu("music_settings.xml");
910 }
911 
913 {
914  gPlayer->stop(true);
915 
916  // TODO these should be saved when they are changed
917  // Automagically save all playlists and metadata (ratings) that have changed
919  {
921  }
922 
924  {
926  }
927 
928  delete gPlayer;
929 
930  delete gMusicData;
931 }
MythMediaDevice::isUsable
bool isUsable() const
Is this device "ready", for a plugin to access?
Definition: mythmedia.h:84
MythMediaDevice::getMountPath
const QString & getMountPath() const
Definition: mythmedia.h:58
themedir
static QString themedir
Definition: mythdirs.cpp:23
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:215
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:317
generalsettings.h
playlistcontainer.h
m_callback
static void(* m_callback)(void *, QString &)
Definition: mythmusic.cpp:264
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:38
runMenu
static int runMenu(const QString &which_menu)
Definition: mythmusic.cpp:348
MythUILocation::RemoveCurrentLocation
QString RemoveCurrentLocation()
Definition: mythuilocation.cpp:12
MusicPlayer::setCurrentTrackPos
bool setCurrentTrackPos(int pos)
Definition: musicplayer.cpp:1064
REG_KEY
static void REG_KEY(const QString &Context, const QString &Action, const QString &Description, const QString &Key)
Definition: mythmainwindow.h:175
ImportSettings
Definition: importsettings.h:11
mythplugin_run
int mythplugin_run(void)
Definition: mythmusic.cpp:902
mythdb.h
ImportMusicDialog::importFinished
void importFinished(void)
MusicMetadata::FormatArtist
QString FormatArtist()
Definition: musicmetadata.cpp:954
PlaylistEditorView
Definition: playlisteditorview.h:65
VisualizationSettings
Definition: visualizationsettings.h:9
startDatabaseTree
static void startDatabaseTree(void)
Definition: mythmusic.cpp:180
progress
bool progress
Definition: mythcommflag.cpp:60
mythplugin.h
MEDIATYPE_MIXED
@ MEDIATYPE_MIXED
Definition: mythmedia.h:27
Playlist::removeAllCDTracks
void removeAllCDTracks(void)
Definition: playlist.cpp:97
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
MythScreenStack
Definition: mythscreenstack.h:16
mythdbcon.h
mythplugin_init
int mythplugin_init(const char *libversion)
Definition: mythmusic.cpp:876
handleMedia
static void handleMedia(MythMediaDevice *cd, bool forcePlayback)
Definition: mythmusic.cpp:489
MusicMetadata::ID
IdType ID() const
Definition: musicmetadata.h:217
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
MythMediaDevice::getDevicePath
const QString & getDevicePath() const
Definition: mythmedia.h:61
MusicData::m_initialized
bool m_initialized
Definition: musicdata.h:54
MusicPlayer::isPlaying
bool isPlaying(void) const
Definition: musicplayer.h:109
MythMediaDevice::getStatus
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
AllMusic::setCDTitle
void setCDTitle(const QString &a_title)
Definition: musicmetadata.h:440
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
playlisteditorview.h
MusicMetadata
Definition: musicmetadata.h:80
startRipper
static void startRipper(void)
Definition: mythmusic.cpp:198
MythCoreContext::TestPluginVersion
static bool TestPluginVersion(const QString &name, const QString &libversion, const QString &pluginversion)
Definition: mythcorecontext.cpp:2089
build_compdb.file
file
Definition: build_compdb.py:55
checkStorageGroup
static bool checkStorageGroup(void)
checks we have at least one music directory in the 'Music' storage group
Definition: mythmusic.cpp:72
playlistview.h
mediamonitor.h
PlaylistView
Definition: playlistview.h:17
LCD::Get
static LCD * Get(void)
Definition: lcddevice.cpp:69
musicutils.h
mythprogressdialog.h
Ripper::ripFinished
void ripFinished(void)
m_callbackdata
static void * m_callbackdata
Definition: mythmusic.cpp:265
startImport
static void startImport(void)
Definition: mythmusic.cpp:239
AllMusic::getCDMetadata
MusicMetadata * getCDMetadata(int m_the_track)
Definition: musicmetadata.cpp:1721
musicfilescanner.h
gCDdevice
QString gCDdevice
Definition: musicplayer.cpp:39
PlaylistContainer::getActive
Playlist * getActive(void)
Definition: playlistcontainer.h:47
cddecoder.h
MusicPlayer::getCurrentMetadata
MusicMetadata * getCurrentMetadata(void)
get the metadata for the current track in the playlist
Definition: musicplayer.cpp:1189
startPlayback
static void startPlayback(void)
Definition: mythmusic.cpp:149
runScan
static void runScan(void)
Definition: mythmusic.cpp:229
runMusicPlayback
static void runMusicPlayback(void)
Definition: mythmusic.cpp:395
handleCDMedia
static void handleCDMedia([[maybe_unused]] MythMediaDevice *cd, [[maybe_unused]] bool forcePlayback)
Definition: mythmusic.cpp:784
MusicCallback
static void MusicCallback([[maybe_unused]] void *data, QString &selection)
Definition: mythmusic.cpp:267
ratingsettings.h
BuildFileList
static QStringList BuildFileList(const QString &dir, const QStringList &filters)
Definition: mythmusic.cpp:456
mythlogging.h
CdDecoder
Definition: cddecoder.h:24
AllMusic::doneLoading
bool doneLoading() const
Definition: musicmetadata.h:443
REG_MEDIA_HANDLER
static void REG_MEDIA_HANDLER(const QString &destination, const QString &description, MediaCallback callback, int mediaType, const QString &extensions)
Definition: mediamonitor.h:140
StreamView
Definition: streamview.h:18
GetMusicFilter
static QStringList GetMusicFilter()
Definition: mythmusic.cpp:449
MusicData::reloadMusic
void reloadMusic(void) const
reload music after a scan, rip or import
Definition: musicdata.cpp:61
runMusicStreamPlayback
static void runMusicStreamPlayback(void)
Definition: mythmusic.cpp:402
MythUIProgressDialog
Definition: mythprogressdialog.h:59
cdrip.h
menu
static MythThemedMenu * menu
Definition: mythtv-setup.cpp:58
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
MythUIThemeHelper::GetThemeDir
QString GetThemeDir()
Definition: mythuithemehelper.cpp:141
compat.h
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
AllMusic::cleanOutThreads
bool cleanOutThreads()
Definition: musicmetadata.cpp:1459
AllMusic::addCDTrack
void addCDTrack(const MusicMetadata &the_track)
Definition: musicmetadata.cpp:1704
AllMusic::getCDTrackCount
int getCDTrackCount(void) const
Definition: musicmetadata.h:441
MEDIASTAT_MOUNTED
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
MythUIBusyDialog
Definition: mythprogressdialog.h:36
setupKeys
static void setupKeys(void)
Definition: mythmusic.cpp:791
checkMusicAvailable
static bool checkMusicAvailable(void)
checks we have some tracks available
Definition: mythmusic.cpp:125
MusicData
Definition: musicdata.h:35
Ripper
Definition: cdrip.h:95
GeneralSettings
Definition: globalsettings.h:133
MusicPlayer::hasClient
bool hasClient(void)
Definition: musicplayer.h:112
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
mythplugin_destroy
void mythplugin_destroy(void)
Definition: mythmusic.cpp:912
MEDIATYPE_MMUSIC
@ MEDIATYPE_MMUSIC
Definition: mythmedia.h:31
MusicPlayer::showMiniPlayer
void showMiniPlayer(void) const
Definition: musicplayer.cpp:1149
MusicPlayer
Definition: musicplayer.h:61
mythpluginapi.h
musicdata.h
runMusicSelection
static void runMusicSelection(void)
Definition: mythmusic.cpp:409
MusicMetadata::Album
QString Album() const
Definition: musicmetadata.h:149
gMusicData
MusicData * gMusicData
Definition: musicdata.cpp:23
streamview.h
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:912
PlaylistContainer::cleanOutThreads
bool cleanOutThreads()
Definition: playlistcontainer.cpp:298
mythuihelper.h
MusicMetadata::isCDTrack
bool isCDTrack(void) const
Definition: musicmetadata.h:221
UpgradeMusicDatabaseSchema
bool UpgradeMusicDatabaseSchema(void)
Definition: musicdbcheck.cpp:26
ImportMusicDialog
Definition: importmusic.h:60
MEDIATYPE_AUDIO
@ MEDIATYPE_AUDIO
Definition: mythmedia.h:28
MusicData::loadMusic
void loadMusic(void) const
Definition: musicdata.cpp:102
MythThemedMenu::getCallback
void getCallback(void(**lcallback)(void *, QString &), void **data)
Get the themed menus callback function and data for that function.
Definition: myththemedmenu.cpp:151
MusicPlayer::activePlaylistChanged
void activePlaylistChanged(int trackID, bool deleted)
Definition: musicplayer.cpp:1458
mythcorecontext.h
PlaylistContainer::save
void save()
Definition: playlistcontainer.cpp:169
metaio.h
RatingSettings
Definition: ratingsettings.h:9
AllMusic::clearCDData
void clearCDData(void)
Definition: musicmetadata.cpp:1689
musicdbcheck.h
importmusic.h
startStreamPlayback
static void startStreamPlayback(void)
Definition: mythmusic.cpp:166
AllMusic::save
void save()
Check each MusicMetadata entry and save those that have changed (ratings, etc.)
Definition: musicmetadata.cpp:1679
REG_JUMP
static void REG_JUMP(const QString &Destination, const QString &Description, const QString &Key, void(*Callback)(void))
Definition: mythmainwindow.h:188
mainvisual.h
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
visualizationsettings.h
REG_JUMPEX
static void REG_JUMPEX(const QString &Destination, const QString &Description, const QString &Key, void(*Callback)(void), bool ExitToMain)
Definition: mythmainwindow.h:202
MythCoreContext::ActivateSettingsCache
void ActivateSettingsCache(bool activate=true)
Definition: mythcorecontext.cpp:839
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:322
MusicData::m_all_music
AllMusic * m_all_music
Definition: musicdata.h:52
PL_REPLACE
@ PL_REPLACE
Definition: playlist.h:24
MusicPlayer::sendCDChangedEvent
void sendCDChangedEvent(void)
Definition: musicplayer.cpp:1393
MythThemedMenu
Themed menu class, used for main menus in MythTV frontend.
Definition: myththemedmenu.h:57
MythMediaDevice
Definition: mythmedia.h:48
runRipCD
static void runRipCD(void)
Definition: mythmusic.cpp:416
myththemedmenu.h
Playlist::removeAllTracks
void removeAllTracks(void)
Definition: playlist.cpp:89
MusicPlayer::stop
void stop(bool stopAll=false)
Definition: musicplayer.cpp:250
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
PlaylistContainer::doneLoading
bool doneLoading() const
Definition: playlistcontainer.h:67
MythUILocation::AddCurrentLocation
void AddCurrentLocation(const QString &Location)
Definition: mythuilocation.cpp:5
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:887
lcddevice.h
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:64
Playlist::fillSonglistFromList
int fillSonglistFromList(const QList< int > &songList, bool removeDuplicates, InsertPLOption insertOption, int currentTrackID)
Definition: playlist.cpp:785
showMiniPlayer
static void showMiniPlayer(void)
Definition: mythmusic.cpp:439
MetaIO::kValidFileExtensions
static const QString kValidFileExtensions
Definition: metaio.h:160
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
mythplugin_config
int mythplugin_config(void)
Definition: mythmusic.cpp:907
MetaIO::readMetadata
static MusicMetadata * readMetadata(const QString &filename)
Read the metadata from filename directly.
Definition: metaio.cpp:62
MusicData::scanMusic
static void scanMusic(void)
Definition: musicdata.cpp:51
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:566
playersettings.h
MythMediaDevice::getVolumeID
const QString & getVolumeID() const
Definition: mythmedia.h:72
musicmetadata.h
LCD
Definition: lcddevice.h:169
MediaMonitor::defaultCDdevice
static QString defaultCDdevice()
CDDevice, user-selected drive, or /dev/cdrom.
Definition: mediamonitor.cpp:887
decoder.h
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:904
MediaMonitor::GetMountPath
static QString GetMountPath(const QString &devPath)
If the device is being monitored, return its mountpoint.
Definition: mediamonitor.cpp:552
musicplayer.h
MythScreenStack::GetTopScreen
virtual MythScreenType * GetTopScreen(void) const
Definition: mythscreenstack.cpp:182
importsettings.h
PlayerSettings
Definition: videoplayersettings.h:11