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>
16#include <libmythbase/mythdb.h>
21#include <libmythbase/mythversion.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"
49
50#ifdef HAVE_CDIO
51#include "cdrip.h"
52#endif
53
54#if defined HAVE_CDIO
58static QString chooseCD(void)
59{
60 if (!gCDdevice.isEmpty())
61 return gCDdevice;
62
63#ifdef Q_OS_DARWIN
65#endif
66
68}
69#endif
70
72static 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
125static 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
149static 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
166static 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
180static 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
198static 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
229static void runScan(void)
230{
231 if (!checkStorageGroup())
232 return;
233
234 LOG(VB_GENERAL, LOG_INFO, "Scanning for music files");
235
237}
238
239static 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
264static void (*m_callback)(void *, QString &) = nullptr;
265static void *m_callbackdata = nullptr;
266
267static 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")
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
344 m_callback(m_callbackdata, selection);
345 }
346}
347
348static 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)
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
395static void runMusicPlayback(void)
396{
397 GetMythUI()->AddCurrentLocation("playmusic");
400}
401
402static void runMusicStreamPlayback(void)
403{
404 GetMythUI()->AddCurrentLocation("streammusic");
407}
408
409static void runMusicSelection(void)
410{
411 GetMythUI()->AddCurrentLocation("musicplaylists");
414}
415
416static 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
439static void showMiniPlayer(void)
440{
442 return;
443
444 // only show the miniplayer if there isn't already a client attached
445 if (!gPlayer->hasClient())
447}
448
449static QStringList GetMusicFilter()
450{
451 QString filt = MetaIO::kValidFileExtensions;
452 filt.replace(".", "*.");
453 return filt.split('|');
454}
455
456static 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
489static 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
635static 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
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
784static 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
791static 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
876int 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
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}
MusicMetadata * getCDMetadata(int m_the_track)
void addCDTrack(const MusicMetadata &the_track)
int getCDTrackCount(void) const
void clearCDData(void)
bool cleanOutThreads()
void save()
Check each MusicMetadata entry and save those that have changed (ratings, etc.)
void setCDTitle(const QString &a_title)
bool doneLoading() const
void importFinished(void)
Definition: lcddevice.h:170
static LCD * Get(void)
Definition: lcddevice.cpp:69
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
QVariant value(int i) const
Definition: mythdbcon.h:204
bool isActive(void) const
Definition: mythdbcon.h:215
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
static QString defaultCDdevice()
CDDevice, user-selected drive, or /dev/cdrom.
static QString GetMountPath(const QString &devPath)
If the device is being monitored, return its mountpoint.
static const QString kValidFileExtensions
Definition: metaio.h:160
static MusicMetadata * readMetadata(const QString &filename)
Read the metadata from filename directly.
Definition: metaio.cpp:62
static void scanMusic(void)
Definition: musicdata.cpp:51
bool m_initialized
Definition: musicdata.h:54
void reloadMusic(void) const
reload music after a scan, rip or import
Definition: musicdata.cpp:61
AllMusic * m_all_music
Definition: musicdata.h:52
void loadMusic(void) const
Definition: musicdata.cpp:102
PlaylistContainer * m_all_playlists
Definition: musicdata.h:51
bool isCDTrack(void) const
QString FormatArtist()
IdType ID() const
QString Album() const
MusicMetadata * getCurrentMetadata(void)
get the metadata for the current track in the playlist
void showMiniPlayer(void) const
void stop(bool stopAll=false)
void activePlaylistChanged(int trackID, bool deleted)
void sendCDChangedEvent(void)
bool isPlaying(void) const
Definition: musicplayer.h:109
bool setCurrentTrackPos(int pos)
bool hasClient(void)
Definition: musicplayer.h:112
void ActivateSettingsCache(bool activate=true)
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
static bool TestPluginVersion(const QString &name, const QString &libversion, const QString &pluginversion)
bool GetBoolSetting(const QString &key, bool defaultval=false)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
MythScreenStack * GetMainStack()
MythScreenStack * GetStack(const QString &Stackname)
const QString & getMountPath() const
Definition: mythmedia.h:58
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
bool isUsable() const
Is this device "ready", for a plugin to access?
Definition: mythmedia.h:84
const QString & getDevicePath() const
Definition: mythmedia.h:61
const QString & getVolumeID() const
Definition: mythmedia.h:72
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
virtual MythScreenType * GetTopScreen(void) const
Themed menu class, used for main menus in MythTV frontend.
void getCallback(void(**lcallback)(void *, QString &), void **data)
Get the themed menus callback function and data for that function.
QString RemoveCurrentLocation()
void AddCurrentLocation(const QString &Location)
bool doneLoading() const
Playlist * getActive(void)
void removeAllCDTracks(void)
Definition: playlist.cpp:97
void removeAllTracks(void)
Definition: playlist.cpp:89
int fillSonglistFromList(const QList< int > &songList, bool removeDuplicates, InsertPLOption insertOption, int currentTrackID)
Definition: playlist.cpp:785
Definition: cdrip.h:96
void ripFinished(void)
static const iso6937table * d
static void REG_MEDIA_HANDLER(const QString &destination, const QString &description, MediaCallback callback, int mediaType, const QString &extensions)
Definition: mediamonitor.h:141
MusicData * gMusicData
Definition: musicdata.cpp:23
bool UpgradeMusicDatabaseSchema(void)
MusicPlayer * gPlayer
Definition: musicplayer.cpp:38
QString gCDdevice
Definition: musicplayer.cpp:39
bool progress
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
static QString themedir
Definition: mythdirs.cpp:23
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythMainWindow * GetMythMainWindow(void)
static void REG_JUMPEX(const QString &Destination, const QString &Description, const QString &Key, void(*Callback)(void), bool ExitToMain)
static void REG_JUMP(const QString &Destination, const QString &Description, const QString &Key, void(*Callback)(void))
static void REG_KEY(const QString &Context, const QString &Action, const QString &Description, const QString &Key)
@ MEDIATYPE_MIXED
Definition: mythmedia.h:27
@ MEDIATYPE_AUDIO
Definition: mythmedia.h:28
@ MEDIATYPE_MMUSIC
Definition: mythmedia.h:31
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
static void handleMedia(MythMediaDevice *cd, bool forcePlayback)
Definition: mythmusic.cpp:489
static void startStreamPlayback(void)
Definition: mythmusic.cpp:166
static void showMiniPlayer(void)
Definition: mythmusic.cpp:439
int mythplugin_config(void)
Definition: mythmusic.cpp:907
static QStringList BuildFileList(const QString &dir, const QStringList &filters)
Definition: mythmusic.cpp:456
static void runScan(void)
Definition: mythmusic.cpp:229
static void(* m_callback)(void *, QString &)
Definition: mythmusic.cpp:264
static void runMusicStreamPlayback(void)
Definition: mythmusic.cpp:402
void mythplugin_destroy(void)
Definition: mythmusic.cpp:912
static void startPlayback(void)
Definition: mythmusic.cpp:149
static void startRipper(void)
Definition: mythmusic.cpp:198
static void startImport(void)
Definition: mythmusic.cpp:239
static void startDatabaseTree(void)
Definition: mythmusic.cpp:180
static void runRipCD(void)
Definition: mythmusic.cpp:416
static void handleCDMedia(MythMediaDevice *cd, bool forcePlayback)
Definition: mythmusic.cpp:784
static void runMusicPlayback(void)
Definition: mythmusic.cpp:395
static void setupKeys(void)
Definition: mythmusic.cpp:791
static int runMenu(const QString &which_menu)
Definition: mythmusic.cpp:348
static void MusicCallback(void *data, QString &selection)
Definition: mythmusic.cpp:267
static bool checkStorageGroup(void)
checks we have at least one music directory in the 'Music' storage group
Definition: mythmusic.cpp:72
static void runMusicSelection(void)
Definition: mythmusic.cpp:409
int mythplugin_run(void)
Definition: mythmusic.cpp:902
static bool checkMusicAvailable(void)
checks we have some tracks available
Definition: mythmusic.cpp:125
static QStringList GetMusicFilter()
Definition: mythmusic.cpp:449
int mythplugin_init(const char *libversion)
Definition: mythmusic.cpp:876
static void * m_callbackdata
Definition: mythmusic.cpp:265
static MythThemedMenu * menu
MythUIHelper * GetMythUI()
@ PL_REPLACE
Definition: playlist.h:24