MythTV  master
mythplugins/mythmusic/mythmusic/main.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 <QDir>
9 #include <QApplication>
10 #include <QRegExp>
11 #include <QScopedPointer>
12 
13 // MythTV headers
14 #include <mythcontext.h>
15 #include <mythplugin.h>
16 #include <mythmediamonitor.h>
17 #include <mythdbcon.h>
18 #include <mythdb.h>
19 #include <mythpluginapi.h>
20 #include <mythversion.h>
21 #include <myththemedmenu.h>
22 #include <compat.h>
23 #include <mythuihelper.h>
24 #include <mythprogressdialog.h>
25 #include <lcddevice.h>
26 #include <musicmetadata.h>
27 #include <musicutils.h>
28 #include <musicfilescanner.h>
29 
30 // MythMusic headers
31 #include "musicdata.h"
32 #include "decoder.h"
33 #include "cddecoder.h"
34 #include "playlisteditorview.h"
35 #include "playlistview.h"
36 #include "streamview.h"
37 #include "playlistcontainer.h"
38 #include "musicdbcheck.h"
39 #include "musicplayer.h"
40 #include "config.h"
41 #include "mainvisual.h"
42 #include "generalsettings.h"
43 #include "playersettings.h"
44 #include "visualizationsettings.h"
45 #include "importsettings.h"
46 #include "ratingsettings.h"
47 #include "importmusic.h"
48 #include "metaio.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_MAC
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, SIGNAL(ripFinished()),
214  gMusicData, SLOT(reloadMusic()),
215  Qt::QueuedConnection);
216  }
217  else
218  delete rip;
219 
220 #else
221  ShowOkPopup(QCoreApplication::translate("(MythMusicMain)",
222  "MythMusic hasn't been built with libcdio "
223  "support so ripping CDs is not possible"));
224 #endif
225 }
226 
227 static void runScan(void)
228 {
229  if (!checkStorageGroup())
230  return;
231 
232  LOG(VB_GENERAL, LOG_INFO, "Scanning for music files");
233 
235 }
236 
237 static void startImport(void)
238 {
239  if (!checkStorageGroup())
240  return;
241 
243 
245 
246  auto *import = new ImportMusicDialog(mainStack);
247 
248  if (import->Create())
249  {
250  mainStack->AddScreen(import);
251  QObject::connect(import, SIGNAL(importFinished()),
252  gMusicData, SLOT(reloadMusic()),
253  Qt::QueuedConnection);
254  }
255  else
256  delete import;
257 }
258 
259 // these point to the the mainmenu callback if found
260 static void (*m_callback)(void *, QString &) = nullptr;
261 static void *m_callbackdata = nullptr;
262 
263 static void MusicCallback(void *data, QString &selection)
264 {
265  (void) data;
266 
267  QString sel = selection.toLower();
268  if (sel == "music_create_playlist")
270  else if (sel == "music_play")
271  startPlayback();
272  else if (sel == "stream_play")
274  else if (sel == "music_rip")
275  {
276  startRipper();
277  }
278  else if (sel == "music_import")
279  {
280  startImport();
281  }
282  else if (sel == "settings_scan")
283  {
284  runScan();
285  }
286  else if (sel == "settings_general")
287  {
289  auto *gs = new GeneralSettings(mainStack, "general settings");
290 
291  if (gs->Create())
292  mainStack->AddScreen(gs);
293  else
294  delete gs;
295  }
296  else if (sel == "settings_player")
297  {
299  auto *ps = new PlayerSettings(mainStack, "player settings");
300 
301  if (ps->Create())
302  mainStack->AddScreen(ps);
303  else
304  delete ps;
305  }
306  else if (sel == "settings_rating")
307  {
309  auto *rs = new RatingSettings(mainStack, "rating settings");
310 
311  if (rs->Create())
312  mainStack->AddScreen(rs);
313  else
314  delete rs;
315  }
316  else if (sel == "settings_visualization")
317  {
318 
320  auto *vs = new VisualizationSettings(mainStack, "visualization settings");
321 
322  if (vs->Create())
323  mainStack->AddScreen(vs);
324  else
325  delete vs;
326  }
327  else if (sel == "settings_import")
328  {
330  auto *is = new ImportSettings(mainStack, "import settings");
331 
332  if (is->Create())
333  mainStack->AddScreen(is);
334  else
335  delete is;
336  }
337  else
338  {
339  // if we have found the mainmenu callback
340  // pass the selection on to it
341  if (m_callback && m_callbackdata)
342  m_callback(m_callbackdata, selection);
343  }
344 }
345 
346 static int runMenu(const QString& which_menu)
347 {
348  QString themedir = GetMythUI()->GetThemeDir();
349 
350  // find the 'mainmenu' MythThemedMenu so we can use the callback from it
351  MythThemedMenu *mainMenu = nullptr;
352  QObject *parentObject = GetMythMainWindow()->GetMainStack()->GetTopScreen();
353 
354  while (parentObject)
355  {
356  auto *menu = qobject_cast<MythThemedMenu *>(parentObject);
357 
358  if (menu && menu->objectName() == "mainmenu")
359  {
360  mainMenu = menu;
361  break;
362  }
363 
364  parentObject = parentObject->parent();
365  }
366 
367  auto *diag = new MythThemedMenu(themedir, which_menu,
368  GetMythMainWindow()->GetMainStack(),
369  "music menu");
370 
371  // save the callback from the main menu
372  if (mainMenu)
373  mainMenu->getCallback(&m_callback, &m_callbackdata);
374 
375  diag->setCallback(MusicCallback, nullptr);
376  diag->setKillable();
377 
378  if (diag->foundTheme())
379  {
380  if (LCD *lcd = LCD::Get())
381  {
382  lcd->switchToTime();
383  }
385  return 0;
386  }
387  LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find menu %1 or theme %2")
388  .arg(which_menu).arg(themedir));
389  delete diag;
390  return -1;
391 }
392 
393 static void runMusicPlayback(void)
394 {
395  GetMythUI()->AddCurrentLocation("playmusic");
396  startPlayback();
398 }
399 
400 static void runMusicStreamPlayback(void)
401 {
402  GetMythUI()->AddCurrentLocation("streammusic");
405 }
406 
407 static void runMusicSelection(void)
408 {
409  GetMythUI()->AddCurrentLocation("musicplaylists");
412 }
413 
414 static void runRipCD(void)
415 {
417 
418 #if defined HAVE_CDIO
420 
421  auto *rip = new Ripper(mainStack, chooseCD());
422 
423  if (rip->Create())
424  mainStack->AddScreen(rip);
425  else
426  {
427  delete rip;
428  return;
429  }
430 
431  QObject::connect(rip, SIGNAL(ripFinished()),
432  gMusicData, SLOT(reloadMusic()),
433  Qt::QueuedConnection);
434 #endif
435 }
436 
437 static void showMiniPlayer(void)
438 {
439  if (!gMusicData->m_all_music)
440  return;
441 
442  // only show the miniplayer if there isn't already a client attached
443  if (!gPlayer->hasClient())
445 }
446 
447 static QStringList GetMusicFilter()
448 {
449  QString filt = MetaIO::kValidFileExtensions;
450  filt.replace(".", "*.");
451  return filt.split('|');
452 }
453 
454 static QStringList BuildFileList(const QString &dir, const QStringList &filters)
455 {
456  QStringList ret;
457 
458  QDir d(dir);
459  if (!d.exists())
460  return ret;
461 
462  d.setNameFilters(filters);
463  d.setFilter(QDir::Files | QDir::AllDirs |
464  QDir::NoSymLinks | QDir::Readable |
465  QDir::NoDotAndDotDot);
466  d.setSorting(QDir::Name | QDir::DirsLast);
467 
468  QFileInfoList list = d.entryInfoList();
469  if (list.isEmpty())
470  return ret;
471 
472  for (const auto & fi : qAsConst(list))
473  {
474  if (fi.isDir())
475  {
476  ret += BuildFileList(fi.absoluteFilePath(), filters);
477  QCoreApplication::processEvents();
478  }
479  else
480  {
481  ret << fi.absoluteFilePath();
482  }
483  }
484  return ret;
485 }
486 
487 static void handleMedia(MythMediaDevice *cd)
488 {
489  static QString s_mountPath;
490 
491  if (!cd)
492  return;
493 
494  if (MEDIASTAT_MOUNTED != cd->getStatus())
495  {
496  if (s_mountPath != cd->getMountPath())
497  return;
498 
499  LOG(VB_MEDIA, LOG_INFO, QString(
500  "MythMusic: '%1' unmounted, clearing data").arg(cd->getVolumeID()));
501 
504  {
505  // Now playing a track which is no longer available so stop playback
506  gPlayer->stop(true);
507  }
508 
509  // device is not usable so remove any existing CD tracks
511  {
514  }
515 
516  gPlayer->activePlaylistChanged(-1, false);
518 
519  return;
520  }
521 
522  LOG(VB_MEDIA, LOG_NOTICE, QString("MythMusic: '%1' mounted on '%2'")
523  .arg(cd->getVolumeID()).arg(cd->getMountPath()) );
524 
525  s_mountPath.clear();
526 
527  // don't show the music screen if AutoPlayCD is off
528  if (!gCoreContext->GetBoolSetting("AutoPlayCD", false))
529  return;
530 
533 
534  // remove any existing CD tracks
537 
539 
540  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
541 
542  QString message = QCoreApplication::translate("(MythMusicMain)",
543  "Searching for music files...");
544  auto *busy = new MythUIBusyDialog( message, popupStack, "musicscanbusydialog");
545  if (busy->Create())
546  popupStack->AddScreen(busy, false);
547  else
548  {
549  delete busy;
550  busy = nullptr;
551  }
552 
553  // Search for music files
554  QStringList trackList = BuildFileList(cd->getMountPath(), GetMusicFilter());
555  LOG(VB_MEDIA, LOG_INFO, QString("MythMusic: %1 music files found")
556  .arg(trackList.count()));
557 
558  if (busy)
559  busy->Close();
560 
561  if (trackList.isEmpty())
562  return;
563 
564  message = QCoreApplication::translate("(MythMusicMain)", "Loading music tracks");
565  auto *progress = new MythUIProgressDialog( message, popupStack,
566  "scalingprogressdialog");
567  if (progress->Create())
568  {
569  popupStack->AddScreen(progress, false);
570  progress->SetTotal(trackList.count());
571  }
572  else
573  {
574  delete progress;
575  progress = nullptr;
576  }
577 
578  // Read track metadata and add to all_music
579  int track = 0;
580  for (const auto & file : qAsConst(trackList))
581  {
582  QScopedPointer<MusicMetadata> meta(MetaIO::readMetadata(file));
583  if (meta)
584  {
585  meta->setTrack(++track);
587  }
588  if (progress)
589  {
590  progress->SetProgress(track);
591  QCoreApplication::processEvents();
592  }
593  }
594  LOG(VB_MEDIA, LOG_INFO, QString("MythMusic: %1 tracks scanned").arg(track));
595 
596  if (progress)
597  progress->Close();
598 
599  // Remove all tracks from the playlist
601 
602  // Create list of new tracks
603  QList<int> songList;
604  const int tracks = gMusicData->m_all_music->getCDTrackCount();
605  for (track = 1; track <= tracks; track++)
606  {
608  if (mdata)
609  songList.append(mdata->ID());
610  }
611  if (songList.isEmpty())
612  return;
613 
614  s_mountPath = cd->getMountPath();
615 
616  // Add new tracks to playlist
618  songList, true, PL_REPLACE, 0);
620 
621  // if there is no music screen showing then show the Playlist view
622  if (!gPlayer->hasClient())
623  {
624  // make sure we start playing from the first track
625  gCoreContext->SaveSetting("MusicBookmark", 0);
626  gCoreContext->SaveSetting("MusicBookmarkPosition", 0);
627 
629  }
630 }
631 
632 #ifdef HAVE_CDIO
633 static void handleCDMedia(MythMediaDevice *cd)
634 {
635 
636  if (!cd)
637  return;
638 
639  LOG(VB_MEDIA, LOG_NOTICE, "Got a CD media changed event");
640 
641  QString newDevice;
642 
643  // save the device if valid
644  if (cd->isUsable())
645  {
646 #ifdef Q_OS_MAC
647  newDevice = cd->getMountPath();
648 #else
649  newDevice = cd->getDevicePath();
650 #endif
651 
652  gCDdevice = newDevice;
653  LOG(VB_MEDIA, LOG_INFO, "MythMusic: Storing CD device " + gCDdevice);
654  }
655  else
656  {
657  LOG(VB_MEDIA, LOG_INFO, "Device is not usable clearing cd data");
658 
661  {
662  // we was playing a cd track which is no longer available so stop playback
663  // TODO should check the playing track is from the ejected drive if more than one is available
664  gPlayer->stop(true);
665  }
666 
667  // device is not usable so remove any existing CD tracks
668  if (gMusicData->m_all_music)
669  {
672  }
673 
674  gPlayer->activePlaylistChanged(-1, false);
676 
677  return;
678  }
679 
682 
683  // wait for the music and playlists to load
686  {
687  QCoreApplication::processEvents();
688  usleep(50000);
689  }
690 
691  // remove any existing CD tracks
694 
695  // find any new cd tracks
696  auto *decoder = new CdDecoder("cda", nullptr, nullptr);
697  decoder->setDevice(newDevice);
698 
699  int tracks = decoder->getNumTracks();
700  bool setTitle = false;
701 
702  for (int trackNo = 1; trackNo <= tracks; trackNo++)
703  {
704  MusicMetadata *track = decoder->getMetadata(trackNo);
705  if (track)
706  {
708 
709  if (!setTitle)
710  {
711 
712  QString parenttitle = " ";
713  if (track->FormatArtist().length() > 0)
714  {
715  parenttitle += track->FormatArtist();
716  parenttitle += " ~ ";
717  }
718 
719  if (track->Album().length() > 0)
720  parenttitle += track->Album();
721  else
722  {
723  parenttitle = " " + QCoreApplication::translate("(MythMusicMain)",
724  "Unknown");
725  LOG(VB_GENERAL, LOG_INFO, "Couldn't find your "
726  " CD. It may not be in the freedb database.\n"
727  " More likely, however, is that you need to delete\n"
728  " ~/.cddb and ~/.cdserverrc and restart MythMusic.");
729  }
730 
731  gMusicData->m_all_music->setCDTitle(parenttitle);
732  setTitle = true;
733  }
734 
735  delete track;
736  }
737  }
738 
740 
741  delete decoder;
742 
743  // if the AutoPlayCD setting is set we remove all the existing tracks
744  // from the playlist and replace them with the new CD tracks found
745  if (gCoreContext->GetBoolSetting("AutoPlayCD", false))
746  {
748 
749  QList<int> songList;
750 
751  for (int x = 1; x <= gMusicData->m_all_music->getCDTrackCount(); x++)
752  {
754  if (mdata)
755  songList.append((mdata)->ID());
756  }
757 
758  if (!songList.isEmpty())
759  {
761  songList, true, PL_REPLACE, 0);
763  }
764  }
765  else
766  {
767  // don't show the music screen if AutoPlayCD is off
768  return;
769  }
770 
771  // if there is no music screen showing show the Playlist view
772  if (!gPlayer->hasClient())
773  {
774  // make sure we start playing from the first track
775  gCoreContext->SaveSetting("MusicBookmark", 0);
776  gCoreContext->SaveSetting("MusicBookmarkPosition", 0);
777 
779  }
780 }
781 #else
783 {
784  LOG(VB_GENERAL, LOG_NOTICE, "MythMusic got a media changed event"
785  "but cdio support is not compiled in");
786 }
787 #endif
788 
789 static void setupKeys(void)
790 {
791  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Play music"),
792  "", "", runMusicPlayback);
793  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Select music playlists"),
794  "", "", runMusicSelection);
795  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Play radio stream"),
796  "", "", runMusicStreamPlayback);
797  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Rip CD"),
798  "", "", runRipCD);
799  REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Scan music"),
800  "", "", runScan);
801  REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Show Music Miniplayer"),
802  "", "", showMiniPlayer, false);
803 
804  REG_KEY("Music", "NEXTTRACK", QT_TRANSLATE_NOOP("MythControls",
805  "Move to the next track"), ">,.,Z,End");
806  REG_KEY("Music", "PREVTRACK", QT_TRANSLATE_NOOP("MythControls",
807  "Move to the previous track"), ",,<,Q,Home");
808  REG_KEY("Music", "FFWD", QT_TRANSLATE_NOOP("MythControls",
809  "Fast forward"), "PgDown");
810  REG_KEY("Music", "RWND", QT_TRANSLATE_NOOP("MythControls",
811  "Rewind"), "PgUp");
812  REG_KEY("Music", "PAUSE", QT_TRANSLATE_NOOP("MythControls",
813  "Pause/Start playback"), "P");
814  REG_KEY("Music", "PLAY", QT_TRANSLATE_NOOP("MythControls",
815  "Start playback"), "");
816  REG_KEY("Music", "STOP", QT_TRANSLATE_NOOP("MythControls",
817  "Stop playback"), "O");
818  REG_KEY("Music", "VOLUMEDOWN", QT_TRANSLATE_NOOP("MythControls",
819  "Volume down"), "[,{,F10,Volume Down");
820  REG_KEY("Music", "VOLUMEUP", QT_TRANSLATE_NOOP("MythControls",
821  "Volume up"), "],},F11,Volume Up");
822  REG_KEY("Music", "MUTE", QT_TRANSLATE_NOOP("MythControls",
823  "Mute"), "|,\\,F9,Volume Mute");
824  REG_KEY("Music", "TOGGLEUPMIX",QT_TRANSLATE_NOOP("MythControls",
825  "Toggle audio upmixer"), "Ctrl+U");
826  REG_KEY("Music", "CYCLEVIS", QT_TRANSLATE_NOOP("MythControls",
827  "Cycle visualizer mode"), "6");
828  REG_KEY("Music", "BLANKSCR", QT_TRANSLATE_NOOP("MythControls",
829  "Blank screen"), "5");
830  REG_KEY("Music", "THMBUP", QT_TRANSLATE_NOOP("MythControls",
831  "Increase rating"), "9");
832  REG_KEY("Music", "THMBDOWN", QT_TRANSLATE_NOOP("MythControls",
833  "Decrease rating"), "7");
834  REG_KEY("Music", "REFRESH", QT_TRANSLATE_NOOP("MythControls",
835  "Refresh music tree"), "8");
836  REG_KEY("Music", "SPEEDUP", QT_TRANSLATE_NOOP("MythControls",
837  "Increase Play Speed"), "W");
838  REG_KEY("Music", "SPEEDDOWN", QT_TRANSLATE_NOOP("MythControls",
839  "Decrease Play Speed"), "X");
840  REG_KEY("Music", "MARK", QT_TRANSLATE_NOOP("MythControls",
841  "Toggle track selection"), "T");
842  REG_KEY("Music", "TOGGLESHUFFLE", QT_TRANSLATE_NOOP("MythControls",
843  "Toggle shuffle mode"), "");
844  REG_KEY("Music", "TOGGLEREPEAT", QT_TRANSLATE_NOOP("MythControls",
845  "Toggle repeat mode"), "");
846  REG_KEY("Music", "TOGGLELAST", QT_TRANSLATE_NOOP("MythControls",
847  "Switch to previous radio stream"), "");
848 
849  // switch to view key bindings
850  REG_KEY("Music", "SWITCHTOPLAYLIST", QT_TRANSLATE_NOOP("MythControls",
851  "Switch to the current playlist view"), "");
852  REG_KEY("Music", "SWITCHTOPLAYLISTEDITORTREE", QT_TRANSLATE_NOOP("MythControls",
853  "Switch to the playlist editor tree view"), "");
854  REG_KEY("Music", "SWITCHTOPLAYLISTEDITORGALLERY", QT_TRANSLATE_NOOP("MythControls",
855  "Switch to the playlist editor gallery view"), "");
856  REG_KEY("Music", "SWITCHTOSEARCH", QT_TRANSLATE_NOOP("MythControls",
857  "Switch to the search view"), "");
858  REG_KEY("Music", "SWITCHTOVISUALISER", QT_TRANSLATE_NOOP("MythControls",
859  "Switch to the fullscreen visualiser view"), "");
860  REG_KEY("Music", "SWITCHTORADIO", QT_TRANSLATE_NOOP("MythControls",
861  "Switch to the radio stream view"), "");
862 
863  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
864  "MythMusic Media Handler 1/2"), "", handleCDMedia,
865  MEDIATYPE_AUDIO | MEDIATYPE_MIXED, QString());
866  QString filt = MetaIO::kValidFileExtensions;
867  filt.replace('|',',');
868  filt.remove('.');
869  REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
870  "MythMusic Media Handler 2/2"), "", handleMedia,
871  MEDIATYPE_MMUSIC, filt);
872 }
873 
874 int mythplugin_init(const char *libversion)
875 {
876  if (!MythCoreContext::TestPluginVersion("mythmusic", libversion,
878  return -1;
879 
881  bool upgraded = UpgradeMusicDatabaseSchema();
883 
884  if (!upgraded)
885  {
886  LOG(VB_GENERAL, LOG_ERR,
887  "Couldn't upgrade music database schema, exiting.");
888  return -1;
889  }
890 
891  setupKeys();
892 
893  gPlayer = new MusicPlayer(nullptr);
894  gMusicData = new MusicData();
895 
896  return 0;
897 }
898 
899 
900 int mythplugin_run(void)
901 {
902  return runMenu("musicmenu.xml");
903 }
904 
906 {
907  return runMenu("music_settings.xml");
908 }
909 
911 {
912  gPlayer->stop(true);
913 
914  // TODO these should be saved when they are changed
915  // Automagically save all playlists and metadata (ratings) that have changed
917  {
919  }
920 
922  {
924  }
925 
926  delete gPlayer;
927 
928  delete gMusicData;
929 }
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
mythplugin_config
int mythplugin_config(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:905
themedir
static QString themedir
Definition: mythdirs.cpp:21
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:204
MEDIATYPE_MIXED
@ MEDIATYPE_MIXED
Definition: mythmedia.h:27
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:304
generalsettings.h
playlistcontainer.h
startDatabaseTree
static void startDatabaseTree(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:180
PL_REPLACE
@ PL_REPLACE
Definition: playlist.h:24
gPlayer
MusicPlayer * gPlayer
Definition: musicplayer.cpp:35
MusicPlayer::setCurrentTrackPos
bool setCurrentTrackPos(int pos)
Definition: musicplayer.cpp:1034
handleCDMedia
static void handleCDMedia(MythMediaDevice *)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:782
ImportSettings
Definition: importsettings.h:12
MythUIHelper::RemoveCurrentLocation
QString RemoveCurrentLocation(void)
Definition: mythuihelper.cpp:1432
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:551
mythdb.h
MusicMetadata::FormatArtist
QString FormatArtist()
Definition: musicmetadata.cpp:945
PlaylistEditorView
Definition: playlisteditorview.h:65
VisualizationSettings
Definition: visualizationsettings.h:10
mythplugin.h
BuildFileList
static QStringList BuildFileList(const QString &dir, const QStringList &filters)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:454
progress
bool progress
Definition: mythtv/programs/mythcommflag/main.cpp:74
setupKeys
static void setupKeys(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:789
Playlist::removeAllCDTracks
void removeAllCDTracks(void)
Definition: playlist.cpp:95
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
MythScreenStack
Definition: mythscreenstack.h:16
arg
arg(title).arg(filename).arg(doDelete))
mythdbcon.h
mythmediamonitor.h
startRipper
static void startRipper(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:198
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:603
MythMediaDevice::getDevicePath
const QString & getDevicePath() const
Definition: mythmedia.h:61
MusicData::m_initialized
bool m_initialized
Definition: musicdata.h:57
MusicPlayer::isPlaying
bool isPlaying(void) const
Definition: musicplayer.h:102
MythMediaDevice::getStatus
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
MEDIATYPE_MMUSIC
@ MEDIATYPE_MMUSIC
Definition: mythmedia.h:31
AllMusic::setCDTitle
void setCDTitle(const QString &a_title)
Definition: musicmetadata.h:440
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
playlisteditorview.h
MusicMetadata
Definition: musicmetadata.h:81
MythCoreContext::TestPluginVersion
static bool TestPluginVersion(const QString &name, const QString &libversion, const QString &pluginversion)
Definition: mythcorecontext.cpp:2059
MEDIASTAT_MOUNTED
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
build_compdb.file
file
Definition: build_compdb.py:55
playlistview.h
runRipCD
static void runRipCD(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:414
runMusicSelection
static void runMusicSelection(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:407
mythplugin_destroy
void mythplugin_destroy(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:910
menu
static MythThemedMenu * menu
Definition: mythtv/programs/mythtv-setup/main.cpp:55
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &stackname)
Definition: mythmainwindow.cpp:309
PlaylistView
Definition: playlistview.h:18
LCD::Get
static LCD * Get(void)
Definition: lcddevice.cpp:64
musicutils.h
mythprogressdialog.h
AllMusic::getCDMetadata
MusicMetadata * getCDMetadata(int m_the_track)
Definition: musicmetadata.cpp:1705
musicfilescanner.h
mythversion.h
gCDdevice
QString gCDdevice
Definition: musicplayer.cpp:36
PlaylistContainer::getActive
Playlist * getActive(void)
Definition: playlistcontainer.h:45
cddecoder.h
MusicPlayer::getCurrentMetadata
MusicMetadata * getCurrentMetadata(void)
get the metadata for the current track in the playlist
Definition: musicplayer.cpp:1157
ratingsettings.h
REG_KEY
#define REG_KEY(a, b, c, d)
Definition: mythmainwindow.h:17
runMusicPlayback
static void runMusicPlayback(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:393
CdDecoder
Definition: cddecoder.h:27
AllMusic::doneLoading
bool doneLoading() const
Definition: musicmetadata.h:443
StreamView
Definition: streamview.h:20
MythUIProgressDialog
Definition: mythprogressdialog.h:60
startImport
static void startImport(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:237
cdrip.h
MusicCallback
static void MusicCallback(void *data, QString &selection)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:263
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
compat.h
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
AllMusic::cleanOutThreads
bool cleanOutThreads()
Definition: musicmetadata.cpp:1443
handleMedia
static void handleMedia(MythMediaDevice *cd)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:487
startStreamPlayback
static void startStreamPlayback(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:166
AllMusic::addCDTrack
void addCDTrack(const MusicMetadata &the_track)
Definition: musicmetadata.cpp:1688
AllMusic::getCDTrackCount
int getCDTrackCount(void) const
Definition: musicmetadata.h:441
REG_JUMP
#define REG_JUMP(a, b, c, d)
Definition: mythmainwindow.h:19
MythUIBusyDialog
Definition: mythprogressdialog.h:37
MEDIATYPE_AUDIO
@ MEDIATYPE_AUDIO
Definition: mythmedia.h:28
MusicData
Definition: musicdata.h:39
Ripper
Definition: cdrip.h:96
GeneralSettings
Definition: globalsettings.h:119
MusicPlayer::hasClient
bool hasClient(void)
Definition: musicplayer.h:105
runMusicStreamPlayback
static void runMusicStreamPlayback(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:400
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:54
MusicPlayer::showMiniPlayer
void showMiniPlayer(void) const
Definition: musicplayer.cpp:1118
MusicPlayer
Definition: musicplayer.h:55
REG_MEDIA_HANDLER
#define REG_MEDIA_HANDLER(a, b, c, d, e)
Definition: mythmediamonitor.h:135
mythpluginapi.h
musicdata.h
MusicMetadata::Album
QString Album() const
Definition: musicmetadata.h:150
gMusicData
MusicData * gMusicData
Definition: musicdata.cpp:20
streamview.h
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:924
PlaylistContainer::cleanOutThreads
bool cleanOutThreads()
Definition: playlistcontainer.cpp:302
mythuihelper.h
MusicMetadata::isCDTrack
bool isCDTrack(void) const
Definition: musicmetadata.h:221
startPlayback
static void startPlayback(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:149
MYTH_BINARY_VERSION
#define MYTH_BINARY_VERSION
Update this whenever the plug-in ABI changes.
Definition: mythversion.h:15
UpgradeMusicDatabaseSchema
bool UpgradeMusicDatabaseSchema(void)
Definition: musicdbcheck.cpp:21
ImportMusicDialog
Definition: importmusic.h:59
MusicData::loadMusic
void loadMusic(void) const
Definition: musicdata.cpp:98
MythThemedMenu::getCallback
void getCallback(void(**lcallback)(void *, QString &), void **data)
Get the themed menus callback function and data for that function.
Definition: myththemedmenu.cpp:150
GetMusicFilter
static QStringList GetMusicFilter()
Definition: mythplugins/mythmusic/mythmusic/main.cpp:447
MusicPlayer::activePlaylistChanged
void activePlaylistChanged(int trackID, bool deleted)
Definition: musicplayer.cpp:1423
PlaylistContainer::save
void save()
Definition: playlistcontainer.cpp:170
dir
QDir dir
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1177
metaio.h
RatingSettings
Definition: ratingsettings.h:10
MythUIHelper::AddCurrentLocation
void AddCurrentLocation(const QString &location)
Definition: mythuihelper.cpp:1424
AllMusic::clearCDData
void clearCDData(void)
Definition: musicmetadata.cpp:1673
checkMusicAvailable
static bool checkMusicAvailable(void)
checks we have some tracks available
Definition: mythplugins/mythmusic/mythmusic/main.cpp:125
musicdbcheck.h
MythUIHelper::GetThemeDir
QString GetThemeDir(void)
Definition: mythuihelper.cpp:1058
importmusic.h
AllMusic::save
void save()
Check each MusicMetadata entry and save those that have changed (ratings, etc.)
Definition: musicmetadata.cpp:1663
mythcontext.h
mainvisual.h
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:107
runScan
static void runScan(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:227
visualizationsettings.h
MythCoreContext::ActivateSettingsCache
void ActivateSettingsCache(bool activate=true)
Definition: mythcorecontext.cpp:851
REG_JUMPEX
#define REG_JUMPEX(a, b, c, d, e)
Definition: mythmainwindow.h:21
MusicData::m_all_music
AllMusic * m_all_music
Definition: musicdata.h:55
MusicPlayer::sendCDChangedEvent
void sendCDChangedEvent(void)
Definition: musicplayer.cpp:1358
MythThemedMenu
Themed menu class, used for main menus in MythTV frontend.
Definition: myththemedmenu.h:58
MythMediaDevice
Definition: mythmedia.h:49
myththemedmenu.h
m_callbackdata
static void * m_callbackdata
Definition: mythplugins/mythmusic/mythmusic/main.cpp:261
Playlist::removeAllTracks
void removeAllTracks(void)
Definition: playlist.cpp:87
MusicPlayer::stop
void stop(bool stopAll=false)
Definition: musicplayer.cpp:237
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
PlaylistContainer::doneLoading
bool doneLoading() const
Definition: playlistcontainer.h:65
Playlist::fillSonglistFromList
void fillSonglistFromList(const QList< int > &songList, bool removeDuplicates, InsertPLOption insertOption, int currentTrackID)
Definition: playlist.cpp:783
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:899
mythplugin_run
int mythplugin_run(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:900
lcddevice.h
GetMythUI
MythUIHelper * GetMythUI()
Definition: mythuihelper.cpp:81
showMiniPlayer
static void showMiniPlayer(void)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:437
MetaIO::kValidFileExtensions
static const QString kValidFileExtensions
Definition: metaio.h:173
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:49
query
MSqlQuery query(MSqlQuery::InitCon())
MetaIO::readMetadata
static MusicMetadata * readMetadata(const QString &filename)
Read the metadata from filename directly.
Definition: metaio.cpp:63
MusicData::scanMusic
static void scanMusic(void)
Definition: musicdata.cpp:47
playersettings.h
MythMediaDevice::getVolumeID
const QString & getVolumeID() const
Definition: mythmedia.h:72
musicmetadata.h
mythplugin_init
int mythplugin_init(const char *libversion)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:874
m_callback
static void(* m_callback)(void *, QString &)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:260
LCD
Definition: lcddevice.h:170
checkStorageGroup
static bool checkStorageGroup(void)
checks we have at least one music directory in the 'Music' storage group
Definition: mythplugins/mythmusic/mythmusic/main.cpp:72
MediaMonitor::defaultCDdevice
static QString defaultCDdevice()
CDDevice, user-selected drive, or /dev/cdrom.
Definition: mythmediamonitor.cpp:907
decoder.h
runMenu
static int runMenu(const QString &which_menu)
Definition: mythplugins/mythmusic/mythmusic/main.cpp:346
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:916
MediaMonitor::GetMountPath
static QString GetMountPath(const QString &devPath)
If the device is being monitored, return its mountpoint.
Definition: mythmediamonitor.cpp:573
musicplayer.h
MythScreenStack::GetTopScreen
virtual MythScreenType * GetTopScreen(void) const
Definition: mythscreenstack.cpp:179
importsettings.h
PlayerSettings
Definition: videoplayersettings.h:12