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