MythTV  0.26-pre
main.cpp
Go to the documentation of this file.
00001 // POSIX headers
00002 #include <sys/types.h>
00003 #include <sys/stat.h>
00004 #include <stdlib.h>
00005 #include <unistd.h>
00006 
00007 // Qt headers
00008 #include <QDir>
00009 #include <QApplication>
00010 #include <QRegExp>
00011 
00012 // MythTV headers
00013 #include <mythcontext.h>
00014 #include <mythplugin.h>
00015 #include <mythmediamonitor.h>
00016 #include <mythdbcon.h>
00017 #include <mythdb.h>
00018 #include <mythpluginapi.h>
00019 #include <mythversion.h>
00020 #include <myththemedmenu.h>
00021 #include <compat.h>
00022 #include <mythuihelper.h>
00023 #include <mythprogressdialog.h>
00024 #include <lcddevice.h>
00025 
00026 // MythMusic headers
00027 #include "decoder.h"
00028 #include "metadata.h"
00029 #include "playlisteditorview.h"
00030 #include "playlistview.h"
00031 #include "playlistcontainer.h"
00032 #include "dbcheck.h"
00033 #include "filescanner.h"
00034 #include "musicplayer.h"
00035 #include "config.h"
00036 #include "mainvisual.h"
00037 #include "generalsettings.h"
00038 #include "playersettings.h"
00039 #include "visualizationsettings.h"
00040 #include "importsettings.h"
00041 #include "ratingsettings.h"
00042 #include "importmusic.h"
00043 
00044 #ifdef HAVE_CDIO
00045 #include "cdrip.h"
00046 #endif
00047 
00048 
00049 // This stores the last MythMediaDevice that was detected:
00050 QString gCDdevice;
00051 
00055 static QString chooseCD(void)
00056 {
00057     if (gCDdevice.length())
00058         return gCDdevice;
00059 
00060 #ifdef Q_OS_MAC
00061     return MediaMonitor::GetMountPath(MediaMonitor::defaultCDdevice());
00062 #endif
00063 
00064     return MediaMonitor::defaultCDdevice();
00065 }
00066 
00067 static void SavePending(int pending)
00068 {
00069     //  Temporary Hack until mythmusic
00070     //  has a proper settings/setup
00071 
00072     MSqlQuery query(MSqlQuery::InitCon());
00073     query.prepare("SELECT * FROM settings "
00074                   "WHERE value = :LASTPUSH "
00075                   "AND hostname = :HOST ;");
00076     query.bindValue(":LASTPUSH", "LastMusicPlaylistPush");
00077     query.bindValue(":HOST", gCoreContext->GetHostName());
00078 
00079     if (query.exec() && query.size() == 0)
00080     {
00081         //  first run from this host / recent version
00082         query.prepare("INSERT INTO settings (value,data,hostname) VALUES "
00083                          "(:LASTPUSH, :DATA, :HOST );");
00084         query.bindValue(":LASTPUSH", "LastMusicPlaylistPush");
00085         query.bindValue(":DATA", pending);
00086         query.bindValue(":HOST", gCoreContext->GetHostName());
00087 
00088         if (!query.exec())
00089             MythDB::DBError("SavePending - inserting LastMusicPlaylistPush",
00090                             query);
00091     }
00092     else if (query.size() == 1)
00093     {
00094         //  ah, just right
00095         query.prepare("UPDATE settings SET data = :DATA "
00096                          "WHERE value = :LASTPUSH "
00097                          "AND hostname = :HOST ;");
00098         query.bindValue(":DATA", pending);
00099         query.bindValue(":LASTPUSH", "LastMusicPlaylistPush");
00100         query.bindValue(":HOST", gCoreContext->GetHostName());
00101 
00102         if (!query.exec())
00103             MythDB::DBError("SavePending - updating LastMusicPlaylistPush",
00104                             query);
00105     }
00106     else
00107     {
00108         //  correct thor's diabolical plot to
00109         //  consume all table space
00110 
00111         query.prepare("DELETE FROM settings WHERE "
00112                          "WHERE value = :LASTPUSH "
00113                          "AND hostname = :HOST ;");
00114         query.bindValue(":LASTPUSH", "LastMusicPlaylistPush");
00115         query.bindValue(":HOST", gCoreContext->GetHostName());
00116         if (!query.exec())
00117             MythDB::DBError("SavePending - deleting LastMusicPlaylistPush",
00118                             query);
00119 
00120         query.prepare("INSERT INTO settings (value,data,hostname) VALUES "
00121                          "(:LASTPUSH, :DATA, :HOST );");
00122         query.bindValue(":LASTPUSH", "LastMusicPlaylistPush");
00123         query.bindValue(":DATA", pending);
00124         query.bindValue(":HOST", gCoreContext->GetHostName());
00125 
00126         if (!query.exec())
00127             MythDB::DBError("SavePending - inserting LastMusicPlaylistPush (2)",
00128                             query);
00129     }
00130 }
00131 
00132 static void loadMusic()
00133 {
00134     // only do this once
00135     if (gMusicData->initialized)
00136         return;
00137 
00138     MSqlQuery count_query(MSqlQuery::InitCon());
00139 
00140     bool musicdata_exists = false;
00141     if (count_query.exec("SELECT COUNT(*) FROM music_songs;"))
00142     {
00143         if(count_query.next() &&
00144             0 != count_query.value(0).toInt())
00145         {
00146             musicdata_exists = true;
00147         }
00148     }
00149 
00150     QString startdir = gCoreContext->GetSetting("MusicLocation");
00151     startdir = QDir::cleanPath(startdir);
00152     if (!startdir.isEmpty() && !startdir.endsWith("/"))
00153         startdir += "/";
00154 
00155     gMusicData->musicDir = startdir;
00156 
00157     Decoder::SetLocationFormatUseTags();
00158 
00159     // Only search music files if a directory was specified & there
00160     // is no data in the database yet (first run).  Otherwise, user
00161     // can choose "Setup" option from the menu to force it.
00162     if (!gMusicData->musicDir.isEmpty() && !musicdata_exists)
00163     {
00164         FileScanner *fscan = new FileScanner();
00165         fscan->SearchDir(startdir);
00166         delete fscan;
00167     }
00168 
00169     MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
00170     QString message = QObject::tr("Loading Music. Please wait ...");
00171 
00172     MythUIBusyDialog *busy = new MythUIBusyDialog(message, popupStack,
00173                                                   "musicscanbusydialog");
00174     if (busy->Create())
00175         popupStack->AddScreen(busy, false);
00176     else
00177         busy = NULL;
00178 
00179     // Set the various track formatting modes
00180     Metadata::setArtistAndTrackFormats();
00181 
00182     AllMusic *all_music = new AllMusic();
00183 
00184     //  Load all playlists into RAM (once!)
00185     PlaylistContainer *all_playlists = new PlaylistContainer(
00186             all_music, gCoreContext->GetHostName());
00187 
00188     gMusicData->all_playlists = all_playlists;
00189     gMusicData->all_music = all_music;
00190     gMusicData->initialized = true;
00191 
00192     while (!gMusicData->all_playlists->doneLoading() || !gMusicData->all_music->doneLoading())
00193     {
00194         qApp->processEvents();
00195         usleep(50000);
00196     }
00197     gMusicData->all_playlists->postLoad();
00198 
00199     gPlayer->loadPlaylist();
00200 
00201     if (busy)
00202         busy->Close();
00203 
00204 }
00205 
00206 static void startPlayback(void)
00207 {
00208     loadMusic();
00209 
00210     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00211 
00212     PlaylistView *view = new PlaylistView(mainStack);
00213 
00214     if (view->Create())
00215         mainStack->AddScreen(view);
00216     else
00217         delete view;
00218 }
00219 
00220 static void startDatabaseTree(void)
00221 {
00222     loadMusic();
00223 
00224     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00225 
00226     QString lastView = gCoreContext->GetSetting("MusicPlaylistEditorView", "tree");
00227     PlaylistEditorView *view = new PlaylistEditorView(mainStack, lastView);
00228 
00229     if (view->Create())
00230         mainStack->AddScreen(view);
00231     else
00232         delete view;
00233 }
00234 
00235 static void startRipper(void)
00236 {
00237     loadMusic();
00238 
00239 #if defined HAVE_CDIO
00240     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00241 
00242     Ripper *rip = new Ripper(mainStack, chooseCD());
00243 
00244     if (rip->Create())
00245     {
00246         mainStack->AddScreen(rip);
00247         QObject::connect(rip, SIGNAL(ripFinished()),
00248                      gMusicData, SLOT(reloadMusic()),
00249                      Qt::QueuedConnection);
00250     }
00251     else
00252         delete rip;
00253 #endif
00254 }
00255 
00256 static void runScan(void)
00257 {
00258     // maybe we haven't loaded the music yet in which case we wont have a valid music dir set
00259     if (gMusicData->musicDir.isEmpty())
00260     {
00261         QString startdir = gCoreContext->GetSetting("MusicLocation");
00262         startdir = QDir::cleanPath(startdir);
00263         if (!startdir.isEmpty() && !startdir.endsWith("/"))
00264             startdir += "/";
00265 
00266         gMusicData->musicDir = startdir;
00267     }
00268 
00269     // if we still don't have a valid start dir warn the user and give up
00270     if (gMusicData->musicDir.isEmpty())
00271     {
00272         ShowOkPopup(QObject::tr("You need to tell me where to find your music on the "
00273                                 "'General Settings' page of MythMusic's settings pages."));
00274        return;
00275     }
00276 
00277     if (!QFile::exists(gMusicData->musicDir))
00278     {
00279         ShowOkPopup(QObject::tr("Can't find your music directory. Have you set it correctly on the "
00280                                 "'General Settings' page of MythMusic's settings pages?"));
00281        return;
00282     }
00283 
00284     LOG(VB_GENERAL, LOG_INFO, QString("Scanning '%1' for music files").arg(gMusicData->musicDir));
00285 
00286     FileScanner *fscan = new FileScanner();
00287     fscan->SearchDir(gMusicData->musicDir);
00288 
00289     // save anything that may have changed
00290     if (gMusicData->all_music && gMusicData->all_music->cleanOutThreads())
00291         gMusicData->all_music->save();
00292 
00293     if (gMusicData->all_playlists && gMusicData->all_playlists->cleanOutThreads())
00294     {
00295         gMusicData->all_playlists->save();
00296         int x = gMusicData->all_playlists->getPending();
00297         SavePending(x);
00298     }
00299 
00300     // force a complete reload of the tracks and playlists
00301     gPlayer->stop(true);
00302     delete gMusicData;
00303 
00304     gMusicData = new MusicData;
00305     loadMusic();
00306 
00307     delete fscan;
00308 }
00309 
00310 static void startImport(void)
00311 {
00312     loadMusic();
00313 
00314     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00315 
00316     ImportMusicDialog *import = new ImportMusicDialog(mainStack);
00317 
00318     if (import->Create())
00319     {
00320         mainStack->AddScreen(import);
00321         QObject::connect(import, SIGNAL(importFinished()),
00322                 gMusicData, SLOT(reloadMusic()),
00323                 Qt::QueuedConnection);
00324     }
00325     else
00326         delete import;
00327 }
00328 
00329 static void MusicCallback(void *data, QString &selection)
00330 {
00331     (void) data;
00332 
00333     QString sel = selection.toLower();
00334     if (sel == "music_create_playlist")
00335         startDatabaseTree();
00336     else if (sel == "music_play")
00337         startPlayback();
00338     else if (sel == "music_rip")
00339     {
00340         startRipper();
00341     }
00342     else if (sel == "music_import")
00343     {
00344         startImport();
00345     }
00346     else if (sel == "settings_scan")
00347     {
00348         runScan();
00349     }
00350     else if (sel == "settings_general")
00351      {
00352         MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00353         GeneralSettings *gs = new GeneralSettings(mainStack, "general settings");
00354 
00355         if (gs->Create())
00356             mainStack->AddScreen(gs);
00357         else
00358             delete gs;
00359     }
00360     else if (sel == "settings_player")
00361     {
00362         MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00363         PlayerSettings *ps = new PlayerSettings(mainStack, "player settings");
00364 
00365         if (ps->Create())
00366             mainStack->AddScreen(ps);
00367         else
00368             delete ps;
00369     }
00370     else if (sel == "settings_rating")
00371     {
00372         MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00373         RatingSettings *rs = new RatingSettings(mainStack, "rating settings");
00374 
00375         if (rs->Create())
00376             mainStack->AddScreen(rs);
00377         else
00378             delete rs;
00379     }
00380     else if (sel == "settings_visualization")
00381     {
00382 
00383        MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00384        VisualizationSettings *vs = new VisualizationSettings(mainStack, "visualization settings");
00385 
00386        if (vs->Create())
00387            mainStack->AddScreen(vs);
00388         else
00389             delete vs;
00390     }
00391     else if (sel == "settings_import")
00392     {
00393         MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00394         ImportSettings *is = new ImportSettings(mainStack, "import settings");
00395 
00396         if (is->Create())
00397             mainStack->AddScreen(is);
00398         else
00399             delete is;
00400     }
00401 }
00402 
00403 static int runMenu(QString which_menu)
00404 {
00405     QString themedir = GetMythUI()->GetThemeDir();
00406 
00407     MythThemedMenu *diag = new MythThemedMenu(
00408         themedir, which_menu, GetMythMainWindow()->GetMainStack(),
00409         "music menu");
00410 
00411     diag->setCallback(MusicCallback, NULL);
00412     diag->setKillable();
00413 
00414     if (diag->foundTheme())
00415     {
00416         if (LCD *lcd = LCD::Get())
00417         {
00418             lcd->switchToTime();
00419         }
00420         GetMythMainWindow()->GetMainStack()->AddScreen(diag);
00421         return 0;
00422     }
00423     else
00424     {
00425         LOG(VB_GENERAL, LOG_ERR, QString("Couldn't find menu %1 or theme %2")
00426                               .arg(which_menu).arg(themedir));
00427         delete diag;
00428         return -1;
00429     }
00430 }
00431 
00432 static void runMusicPlayback(void)
00433 {
00434     GetMythUI()->AddCurrentLocation("playmusic");
00435     startPlayback();
00436     GetMythUI()->RemoveCurrentLocation();
00437 }
00438 
00439 static void runMusicSelection(void)
00440 {
00441     GetMythUI()->AddCurrentLocation("musicplaylists");
00442     startDatabaseTree();
00443     GetMythUI()->RemoveCurrentLocation();
00444 }
00445 
00446 static void runRipCD(void)
00447 {
00448     loadMusic();
00449 
00450 #if defined HAVE_CDIO
00451     MythScreenStack *mainStack = GetMythMainWindow()->GetMainStack();
00452 
00453     Ripper *rip = new Ripper(mainStack, chooseCD());
00454 
00455     if (rip->Create())
00456         mainStack->AddScreen(rip);
00457     else
00458         delete rip;
00459 
00460     QObject::connect(rip, SIGNAL(ripFinished()),
00461                      gMusicData, SLOT(reloadMusic()),
00462                      Qt::QueuedConnection);
00463 #endif
00464 }
00465 
00466 static void showMiniPlayer(void)
00467 {
00468     if (!gMusicData->all_music)
00469         return;
00470 
00471     // only show the miniplayer if there isn't already a client attached
00472     if (!gPlayer->hasClient())
00473         gPlayer->showMiniPlayer();
00474 }
00475 
00476 #ifdef FIXME  // the only call is likewise commented out and needs fixing
00477 static void handleMedia(MythMediaDevice *cd)
00478 {
00479     // if the music player is already playing ignore the event
00480     if (gPlayer->isPlaying())
00481     {
00482         LOG(VB_GENERAL, LOG_NOTICE, "Got a media changed event but ignoring since "
00483                                       "the music player is already playing");
00484         return;
00485     }
00486     else
00487          LOG(VB_GENERAL, LOG_NOTICE, "Got a media changed event");
00488 
00489     // Note that we should deal with other disks that may contain music.
00490     // e.g. MEDIATYPE_MMUSIC or MEDIATYPE_MIXED
00491 
00492     if (!cd)
00493         return;
00494 
00495     if (cd->isUsable())
00496     {
00497         QString newDevice;
00498 
00499 #ifdef Q_OS_MAC
00500         newDevice = cd->getMountPath();
00501 #else
00502         newDevice = cd->getDevicePath();
00503 #endif
00504 
00505         if (gCDdevice.length() && gCDdevice != newDevice)
00506         {
00507             // In the case of multiple audio CDs, clear the old stored device
00508             // so the user has to choose (via MediaMonitor::defaultCDdevice())
00509 
00510             gCDdevice = QString::null;
00511             LOG(VB_MEDIA, LOG_INFO, "MythMusic: Forgetting existing CD");
00512         }
00513         else
00514         {
00515             gCDdevice = newDevice;
00516             LOG(VB_MEDIA, LOG_INFO,
00517                 "MythMusic: Storing CD device " + gCDdevice);
00518         }
00519     }
00520     else
00521     {
00522         gCDdevice = QString::null;
00523         return;
00524     }
00525 
00526     GetMythMainWindow()->JumpTo("Main Menu");
00527 
00528     if (gCoreContext->GetNumSetting("AutoPlayCD", 0))
00529     {
00530         // Empty the playlist to ensure CD is played first
00531         if (gMusicData->all_music)
00532             gMusicData->all_music->clearCDData();
00533         if (gMusicData->all_playlists)
00534             gMusicData->all_playlists->clearCDList();
00535 
00536         runMusicPlayback();
00537     }
00538     else
00539         mythplugin_run();
00540 }
00541 #endif
00542 
00543 static void setupKeys(void)
00544 {
00545     REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Play music"),
00546         "", "", runMusicPlayback);
00547     REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Select music playlists"),
00548         "", "", runMusicSelection);
00549     REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Rip CD"),
00550         "", "", runRipCD);
00551     REG_JUMP(QT_TRANSLATE_NOOP("MythControls", "Scan music"),
00552         "", "", runScan);
00553     REG_JUMPEX(QT_TRANSLATE_NOOP("MythControls", "Show Music Miniplayer"),
00554         "", "", showMiniPlayer, false);
00555 
00556     REG_KEY("Music", "NEXTTRACK",  QT_TRANSLATE_NOOP("MythControls",
00557         "Move to the next track"),     ">,.,Z,End");
00558     REG_KEY("Music", "PREVTRACK",  QT_TRANSLATE_NOOP("MythControls",
00559         "Move to the previous track"), ",,<,Q,Home");
00560     REG_KEY("Music", "FFWD",       QT_TRANSLATE_NOOP("MythControls",
00561         "Fast forward"),               "PgDown");
00562     REG_KEY("Music", "RWND",       QT_TRANSLATE_NOOP("MythControls",
00563         "Rewind"),                     "PgUp");
00564     REG_KEY("Music", "PAUSE",      QT_TRANSLATE_NOOP("MythControls",
00565         "Pause/Start playback"),       "P");
00566     REG_KEY("Music", "PLAY",       QT_TRANSLATE_NOOP("MythControls",
00567         "Start playback"),             "");
00568     REG_KEY("Music", "STOP",       QT_TRANSLATE_NOOP("MythControls",
00569         "Stop playback"),              "O");
00570     REG_KEY("Music", "VOLUMEDOWN", QT_TRANSLATE_NOOP("MythControls",
00571         "Volume down"),       "[,{,F10,Volume Down");
00572     REG_KEY("Music", "VOLUMEUP",   QT_TRANSLATE_NOOP("MythControls",
00573         "Volume up"),         "],},F11,Volume Up");
00574     REG_KEY("Music", "MUTE",       QT_TRANSLATE_NOOP("MythControls",
00575         "Mute"),              "|,\\,F9,Volume Mute");
00576     REG_KEY("Music", "TOGGLEUPMIX",QT_TRANSLATE_NOOP("MythControls",
00577         "Toggle audio upmixer"),    "Ctrl+U");
00578     REG_KEY("Music", "CYCLEVIS",   QT_TRANSLATE_NOOP("MythControls",
00579         "Cycle visualizer mode"),      "6");
00580     REG_KEY("Music", "BLANKSCR",   QT_TRANSLATE_NOOP("MythControls",
00581         "Blank screen"),               "5");
00582     REG_KEY("Music", "THMBUP",     QT_TRANSLATE_NOOP("MythControls",
00583         "Increase rating"),            "9");
00584     REG_KEY("Music", "THMBDOWN",   QT_TRANSLATE_NOOP("MythControls",
00585         "Decrease rating"),            "7");
00586     REG_KEY("Music", "REFRESH",    QT_TRANSLATE_NOOP("MythControls",
00587         "Refresh music tree"),         "8");
00588     REG_KEY("Music", "SPEEDUP",    QT_TRANSLATE_NOOP("MythControls",
00589         "Increase Play Speed"),   "W");
00590     REG_KEY("Music", "SPEEDDOWN",  QT_TRANSLATE_NOOP("MythControls",
00591         "Decrease Play Speed"),   "X");
00592     REG_KEY("Music", "MARK",       QT_TRANSLATE_NOOP("MythControls",
00593         "Toggle track selection"), "T");
00594     REG_KEY("Music", "TOGGLESHUFFLE", QT_TRANSLATE_NOOP("MythControls",
00595         "Toggle shuffle mode"),    "");
00596     REG_KEY("Music", "TOGGLEREPEAT",  QT_TRANSLATE_NOOP("MythControls",
00597         "Toggle repeat mode"),     "");
00598 
00599     // switch to view key bindings
00600     REG_KEY("Music", "SWITCHTOPLAYLIST",              QT_TRANSLATE_NOOP("MythControls",
00601         "Switch to the current playlist view"), "");
00602     REG_KEY("Music", "SWITCHTOPLAYLISTEDITORTREE",    QT_TRANSLATE_NOOP("MythControls",
00603         "Switch to the playlist editor tree view"), "");
00604     REG_KEY("Music", "SWITCHTOPLAYLISTEDITORGALLERY", QT_TRANSLATE_NOOP("MythControls",
00605         "Switch to the playlist editor gallery view"), "");
00606     REG_KEY("Music", "SWITCHTOSEARCH",                QT_TRANSLATE_NOOP("MythControls",
00607         "Switch to the search view"), "");
00608     REG_KEY("Music", "SWITCHTOVISUALISER",            QT_TRANSLATE_NOOP("MythControls",
00609         "Switch to the fullscreen visualiser view"), "");
00610 
00611 
00612 #ifdef FIXME
00613 // FIXME need to find a way to stop the media monitor jumping to the main menu before
00614 // calling the handler
00615     REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
00616         "MythMusic Media Handler 1/2"), "", "", handleMedia,
00617         MEDIATYPE_AUDIO | MEDIATYPE_MIXED, QString::null);
00618     REG_MEDIA_HANDLER(QT_TRANSLATE_NOOP("MythControls",
00619         "MythMusic Media Handler 2/2"), "", "", handleMedia,
00620         MEDIATYPE_MMUSIC, "mp3,mp2,ogg,oga,flac,wma,wav,ac3,"
00621                           "oma,omg,atp,ra,dts,aac,m4a,aa3,tta,"
00622                           "mka,aiff,swa,wv");
00623 #endif
00624 }
00625 
00626 int mythplugin_init(const char *libversion)
00627 {
00628     if (!gContext->TestPopupVersion("mythmusic", libversion,
00629                                     MYTH_BINARY_VERSION))
00630         return -1;
00631 
00632     gCoreContext->ActivateSettingsCache(false);
00633     bool upgraded = UpgradeMusicDatabaseSchema();
00634     gCoreContext->ActivateSettingsCache(true);
00635 
00636     if (!upgraded)
00637     {
00638         LOG(VB_GENERAL, LOG_ERR,
00639             "Couldn't upgrade music database schema, exiting.");
00640         return -1;
00641     }
00642 
00643     setupKeys();
00644 
00645     Decoder::SetLocationFormatUseTags();
00646 
00647     gPlayer = new MusicPlayer(NULL, chooseCD());
00648     gMusicData = new MusicData();
00649 
00650     return 0;
00651 }
00652 
00653 
00654 int mythplugin_run(void)
00655 {
00656     return runMenu("musicmenu.xml");
00657 }
00658 
00659 int mythplugin_config(void)
00660 {
00661     Decoder::SetLocationFormatUseTags();
00662 
00663     return runMenu("music_settings.xml");
00664 }
00665 
00666 void mythplugin_destroy(void)
00667 {
00668     gPlayer->stop(true);
00669 
00670     // TODO these should be saved when they are changed
00671     // Automagically save all playlists and metadata (ratings) that have changed
00672     if (gMusicData->all_music && gMusicData->all_music->cleanOutThreads())
00673     {
00674         gMusicData->all_music->save();
00675     }
00676 
00677     if (gMusicData->all_playlists && gMusicData->all_playlists->cleanOutThreads())
00678     {
00679         gMusicData->all_playlists->save();
00680         int x = gMusicData->all_playlists->getPending();
00681         SavePending(x);
00682     }
00683 
00684     delete gPlayer;
00685 
00686     delete gMusicData;
00687 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends