Ticket #4222: 4222-v3.patch

File 4222-v3.patch, 75.1 KB (added by paulh, 16 years ago)

Updated patch (requires mythtv >= r14969 to be installed)

  • mythmusic/playbackbox.cpp

     
    2727#include "mainvisual.h"
    2828#include "smartplaylist.h"
    2929#include "search.h"
     30#include "musicplayer.h"
    3031
    3132PlaybackBoxMusic::PlaybackBoxMusic(MythMainWindow *parent, QString window_name,
    3233                                   QString theme_filename,
     
    3738                : MythThemedDialog(parent, window_name, theme_filename, name)
    3839{
    3940    //  A few internal variable defaults
    40  
    41     input = NULL;
    42     output = NULL;
    43     decoder = NULL;
    4441    mainvisual = NULL;
    4542    visual_mode_timer = NULL;
    4643    lcd_update_timer = NULL;
    4744    waiting_for_playlists_timer = NULL;
    4845    speed_scroll_timer = NULL;
    49     playlist_tree = NULL;
    5046    playlist_popup = NULL;
    5147    progress = NULL;
    5248
    53     isplaying = false;
     49    gPlayer->setListener(this);
     50
    5451    tree_is_done = false;
    5552    first_playlist_check = true;
    5653    outputBufferSize = 256;
     
    112109                this, SLOT(hideVolume()));
    113110    }
    114111
    115     // Figure out the shuffle mode
     112    setShuffleMode(gPlayer->getShuffleMode());
    116113
    117     QString playmode = gContext->GetSetting("PlayMode", "none");
    118     if (playmode.lower() == "random")
    119         setShuffleMode(SHUFFLE_RANDOM);
    120     else if (playmode.lower() == "intelligent")
    121         setShuffleMode(SHUFFLE_INTELLIGENT);
    122     else if (playmode.lower() == "album")
    123         setShuffleMode(SHUFFLE_ALBUM);
    124     else if (playmode.lower() == "artist")
    125         setShuffleMode(SHUFFLE_ARTIST);
    126     else
    127         setShuffleMode(SHUFFLE_OFF);
    128 
    129114    QString resumestring = gContext->GetSetting("ResumeMode", "off");
    130115    if (resumestring.lower() == "off")
    131116        resumemode = RESUME_OFF;
     
    134119    else
    135120        resumemode = RESUME_EXACT;
    136121
    137     QString repeatmode = gContext->GetSetting("RepeatMode", "all");
    138     if (repeatmode.lower() == "track")
    139         setRepeatMode(REPEAT_TRACK);
    140     else if (repeatmode.lower() == "all")
    141         setRepeatMode(REPEAT_ALL);
    142     else
    143         setRepeatMode(REPEAT_OFF);
     122    setRepeatMode(gPlayer->getRepeatMode());
    144123
    145124    // Set some button values
    146125
     
    170149        // Set please wait on the LCD
    171150        QPtrList<LCDTextItem> textItems;
    172151        textItems.setAutoDelete(true);
    173        
     152
    174153        textItems.append(new LCDTextItem(1, ALIGN_CENTERED, "Please Wait",
    175154                         "Generic"));
    176155        lcd->switchToGeneric(&textItems);
     
    196175        mainvisual->setGeometry(screenwidth + 10, screenheight + 10, 160, 160);
    197176    mainvisual->show();
    198177
     178    gPlayer->setVisual(mainvisual);
     179
    199180    fullscreen_blank = false;
    200181
    201182    visual_modes = QStringList::split(';', gContext->GetSetting("VisualMode"));
     
    240221{
    241222    savePosition(currentTime);
    242223
    243     stopAll();
    244 
    245     if (output)
    246     {
    247         delete output;
    248         output = NULL;
    249     }
    250 
    251224    if (progress)
    252225    {
    253226        progress->Close();
     
    262235        delete cd_reader_thread;
    263236    }
    264237
    265     if (playlist_tree)
    266         delete playlist_tree;
    267 
    268     if (shufflemode == SHUFFLE_INTELLIGENT)
     238    MusicPlayer::ShuffleMode shufflemode = gPlayer->getShuffleMode();
     239    if (shufflemode == MusicPlayer::SHUFFLE_INTELLIGENT)
    269240        gContext->SaveSetting("PlayMode", "intelligent");
    270     else if (shufflemode == SHUFFLE_RANDOM)
     241    else if (shufflemode == MusicPlayer::SHUFFLE_RANDOM)
    271242        gContext->SaveSetting("PlayMode", "random");
    272     else if (shufflemode == SHUFFLE_ALBUM)
     243    else if (shufflemode == MusicPlayer::SHUFFLE_ALBUM)
    273244        gContext->SaveSetting("PlayMode", "album");
    274     else if (shufflemode == SHUFFLE_ARTIST)
     245    else if (shufflemode == MusicPlayer::SHUFFLE_ARTIST)
    275246        gContext->SaveSetting("PlayMode", "artist");
    276247    else
    277248        gContext->SaveSetting("PlayMode", "none");
    278249
    279     if (repeatmode == REPEAT_TRACK)
     250    MusicPlayer::RepeatMode repeatmode = gPlayer->getRepeatMode();
     251    if (repeatmode == MusicPlayer::REPEAT_TRACK)
    280252        gContext->SaveSetting("RepeatMode", "track");
    281     else if (repeatmode == REPEAT_ALL)
     253    else if (repeatmode == MusicPlayer::REPEAT_ALL)
    282254        gContext->SaveSetting("RepeatMode", "all");
    283255    else
    284256        gContext->SaveSetting("RepeatMode", "none");
     257
    285258    if (class LCD *lcd = LCD::Get())
    286259        lcd->switchToTime();
    287260}
     
    304277    resetTimer();
    305278
    306279    QStringList actions;
    307     gContext->GetMainWindow()->TranslateKeyPress("Music", e, actions);
     280    gContext->GetMainWindow()->TranslateKeyPress("Music", e, actions, false);
    308281
    309282    int scrollAmt = 1;
    310283
     
    343316        }
    344317        else if (action == "PAUSE")
    345318        {
    346             if (isplaying)
     319            if (gPlayer->isPlaying())
    347320            {
    348321                if (pause_button)
    349322                    pause_button->push();
     
    371344                stop_button->push();
    372345            else
    373346                stop();
    374 
    375347            currentTime = 0;
    376348        }
    377349        else if (action == "THMBUP")
     
    427399                bannerToggle(curMeta);
    428400            else
    429401                showEditMetadataDialog();
     402        else if (action == "ESCAPE" && visualizer_status != 2)
     403        {
     404            DialogBox *dialog = new DialogBox(gContext->GetMainWindow(),
     405                             tr("Exiting Music Player\n"
     406                             "Do you want to continue playing in the background?"));
     407            dialog->AddButton("No - Exit, Stop Playing");
     408            dialog->AddButton("Yes - Exit, Continue Playing");
     409            dialog->AddButton("Cancel");
     410            int res = dialog->exec();
     411            dialog->deleteLater();
     412
     413            if (res == kDialogCodeButton0)
     414            {
     415                stopAll();
     416                done(kDialogCodeAccepted);
     417            }
     418            else if (res == kDialogCodeButton1)
     419            {
     420                gPlayer->setListener(NULL);
     421                gPlayer->setVisual(NULL);
     422                done(kDialogCodeAccepted);
     423            }
     424            else
     425                handled = true;
     426        }
    430427        else
    431428            handled = false;
    432429    }
     
    541538                music_tree_list->incSearchStart();
    542539            else if (action == "INCSEARCHNEXT")
    543540                music_tree_list->incSearchNext();
    544             else
    545                 handled = false;
    546541        }
    547542    }
    548543    else
     
    565560                handled = false;
    566561        }
    567562    }
    568 
    569     if (!handled)
    570         MythThemedDialog::keyPressEvent(e);
    571563}
    572564
    573565void PlaybackBoxMusic::handlePush(QString buttonname)
     
    949941    if (cd_reader_thread->getLock()->locked())
    950942        return;
    951943
    952     if (!scan_for_cd) {
     944    if (!scan_for_cd)
     945    {
    953946        cd_watcher->stop();
    954947        delete cd_watcher;
    955948        cd_watcher = NULL;
     
    10621055        GenericTree *node = music_tree_list->getCurrentNode();
    10631056        curMeta = all_music->getMetadata(node->getInt());
    10641057
    1065         setShuffleMode(shufflemode);
     1058        setShuffleMode(gPlayer->getShuffleMode());
    10661059
    10671060        music_tree_list->refresh();
    10681061
     
    11041097                branches_to_current_node.append(1); //  We're on a playlist (not "My Music")
    11051098                branches_to_current_node.append(0); //  Active play Queue
    11061099
    1107                 if (resumemode > RESUME_OFF)
    1108                     restorePosition();
     1100                if (gPlayer->isPlaying())
     1101                {
     1102                    restorePosition(gPlayer->getRouteToCurrent());
     1103                }
    11091104                else
    1110                     music_tree_list->moveToNodesFirstChild(branches_to_current_node);
     1105                {
     1106                    if (resumemode > RESUME_OFF)
     1107                        restorePosition(gContext->GetSetting("MusicBookmark", ""));
     1108                    else
     1109                        music_tree_list->moveToNodesFirstChild(branches_to_current_node);
     1110                }
    11111111
    11121112                music_tree_list->refresh();
    11131113                if (show_whole_tree)
     
    11621162
    11631163void PlaybackBoxMusic::changeVolume(bool up_or_down)
    11641164{
    1165     if (volume_control && output)
     1165    if (volume_control && gPlayer->getOutput())
    11661166    {
    11671167        if (up_or_down)
    1168             output->AdjustCurrentVolume(2);
     1168            gPlayer->getOutput()->AdjustCurrentVolume(2);
    11691169        else
    1170             output->AdjustCurrentVolume(-2);
     1170            gPlayer->getOutput()->AdjustCurrentVolume(-2);
    11711171        showVolume(true);
    11721172    }
    11731173}
    11741174
    11751175void PlaybackBoxMusic::toggleMute()
    11761176{
    1177     if (volume_control && output)
     1177    if (volume_control && gPlayer->getOutput())
    11781178    {
    1179         output->ToggleMute();
     1179        gPlayer->getOutput()->ToggleMute();
    11801180        showVolume(true);
    11811181    }
    11821182}
     
    11841184void PlaybackBoxMusic::showProgressBar()
    11851185{
    11861186
    1187     if (progress_bar) {
    1188 
     1187    if (progress_bar)
     1188    {
    11891189             progress_bar->SetTotal(maxTime);
    11901190             progress_bar->SetUsed(currentTime);
    11911191    }
     
    11941194void PlaybackBoxMusic::showVolume(bool on_or_off)
    11951195{
    11961196    float volume_level;
    1197     if (volume_control && output)
     1197    if (volume_control && gPlayer->getOutput())
    11981198    {
    11991199        if (volume_status)
    12001200        {
    12011201            if (on_or_off)
    12021202            {
    1203                 volume_status->SetUsed(output->GetCurrentVolume());
     1203                volume_status->SetUsed(gPlayer->getOutput()->GetCurrentVolume());
    12041204                volume_status->SetOrder(0);
    12051205                volume_status->refresh();
    12061206                volume_display_timer->changeInterval(2000);
    12071207                if (class LCD *lcd = LCD::Get())
    12081208                    lcd->switchToVolume("Music");
    12091209
    1210                 if (output->GetMute())
     1210                if (gPlayer->getOutput()->GetMute())
    12111211                    volume_level = 0.0;
    12121212                else
    1213                     volume_level = (float)output->GetCurrentVolume() /
     1213                    volume_level = (float)gPlayer->getOutput()->GetCurrentVolume() /
    12141214                                   (float)100;
    12151215
    12161216                if (class LCD *lcd = LCD::Get())
     
    12391239
    12401240void PlaybackBoxMusic::play()
    12411241{
     1242    if (gPlayer->isPlaying())
     1243        gPlayer->stop();
    12421244
    1243     if (isplaying)
    1244         stop();
    1245 
    12461245    if (curMeta)
    12471246        playfile = curMeta->Filename();
    12481247    else
     
    12521251        return;
    12531252    }
    12541253
    1255     QUrl sourceurl(playfile);
    1256     QString sourcename(playfile);
    1257 
    1258     if (!output)
    1259         openOutputDevice();
    1260 
    1261     if (output->GetPause())
     1254    if (gPlayer->getOutput() && gPlayer->getOutput()->GetPause())
    12621255    {
    1263         pause();
     1256        gPlayer->pause();
    12641257        return;
    12651258    }
    12661259
    1267     if (!sourceurl.isLocalFile())
    1268     {
    1269         StreamInput streaminput(sourceurl);
    1270         streaminput.setup();
    1271         input = streaminput.socket();
    1272     }
    1273     else
    1274         input = new QFile(playfile);
    1275    
    1276     if (decoder && !decoder->factory()->supports(sourcename))
    1277     {
    1278         decoder->removeListener(this);
    1279         decoder = 0;
    1280     }
     1260    gPlayer->setCurrentNode(music_tree_list->getCurrentNode());
     1261    gPlayer->playFile(playfile);
    12811262
    1282     if (!decoder)
    1283     {
    1284         decoder = Decoder::create(sourcename, input, output);
    1285 
    1286         if (!decoder)
    1287         {
    1288             printf("mythmusic: unsupported fileformat\n");
    1289             stopAll();
    1290             return;
    1291         }
    1292         if (sourcename.contains("cda") == 1)
    1293             dynamic_cast<CdDecoder*>(decoder)->setDevice(m_CDdevice);
    1294 
    1295         decoder->setBlockSize(globalBlockSize);
    1296         decoder->addListener(this);
    1297     }
    1298     else
    1299     {
    1300         decoder->setInput(input);
    1301         decoder->setFilename(sourcename);
    1302         decoder->setOutput(output);
    1303     }
    1304 
    13051263    currentTime = 0;
    13061264
    1307     mainvisual->setDecoder(decoder);
    1308     mainvisual->setOutput(output);
     1265    mainvisual->setDecoder(gPlayer->getDecoder());
     1266    mainvisual->setOutput(gPlayer->getOutput());
    13091267    mainvisual->setMetadata(curMeta);
    13101268
    1311     if (decoder->initialize())
     1269    if (!gPlayer->isPlaying())
    13121270    {
    1313         if (output)
     1271        if (resumemode == RESUME_EXACT &&
     1272                gContext->GetNumSetting("MusicBookmarkPosition", 0) > 0)
    13141273        {
    1315             output->Reset();
    1316         }
    1317 
    1318         decoder->start();
    1319 
    1320         if (resumemode == RESUME_EXACT && gContext->GetNumSetting("MusicBookmarkPosition", 0) > 0)
    1321         {
    13221274            seek(gContext->GetNumSetting("MusicBookmarkPosition", 0));
    13231275            gContext->SaveSetting("MusicBookmarkPosition", 0);
    13241276        }
    1325 
    1326         bannerEnable(curMeta, show_album_art);
    1327         isplaying = true;
    1328         curMeta->setLastPlay();
    1329         curMeta->incPlayCount();
    13301277    }
     1278
     1279    bannerEnable(curMeta, show_album_art);
    13311280}
    13321281
    13331282void PlaybackBoxMusic::visEnable()
    13341283{
    1335     if (!visualizer_status != 2 && isplaying)
     1284    if (!visualizer_status != 2 && gPlayer->isPlaying())
    13361285    {
    13371286        setUpdatesEnabled(false);
    13381287        mainvisual->setGeometry(0, 0, screenwidth, screenheight);
     
    14101359void PlaybackBoxMusic::setTrackOnLCD(Metadata *mdata)
    14111360{
    14121361    LCD *lcd = LCD::Get();
    1413     if (!lcd)
     1362    if (!lcd || !mdata)
    14141363        return;
    14151364
    14161365    // Set the Artist and Tract on the LCD
     
    14211370
    14221371void PlaybackBoxMusic::pause(void)
    14231372{
    1424     if (output)
    1425     {
    1426         isplaying = !isplaying;
    1427         output->Pause(!isplaying); //Note pause doesn't take effect instantly
    1428     }
    1429     // wake up threads
    1430     if (decoder)
    1431     {
    1432         decoder->lock();
    1433         decoder->cond()->wakeAll();
    1434         decoder->unlock();
    1435     }
    1436 
     1373    gPlayer->pause();
    14371374}
    14381375
    1439 void PlaybackBoxMusic::stopDecoder(void)
    1440 {
    1441     if (decoder && decoder->running())
    1442         decoder->stop();
    1443 
    1444     if (decoder)
    1445     {
    1446         decoder->lock();
    1447         decoder->cond()->wakeAll();
    1448         decoder->unlock();
    1449     }
    1450 
    1451     if (decoder)
    1452         decoder->wait();
    1453 }
    1454 
    14551376void PlaybackBoxMusic::stop(void)
    14561377{
    1457     stopDecoder();
     1378    gPlayer->stop();
    14581379
    1459     if (output)
    1460     {
    1461         if (output->GetPause())
    1462         {
    1463             pause();
    1464         }
    1465         output->Reset();
    1466     }
    1467 
    14681380    mainvisual->setDecoder(0);
    14691381    mainvisual->setOutput(0);
    14701382    mainvisual->deleteMetadata();
    14711383
    1472     delete input;
    1473     input = 0;
    1474 
    14751384    QString time_string = getTimeString(maxTime, 0);
    14761385
    14771386    if (time_text)
    14781387        time_text->SetText(time_string);
    14791388    if (info_text)
    14801389        info_text->SetText("");
    1481 
    1482     isplaying = false;
    14831390}
    14841391
    14851392void PlaybackBoxMusic::stopAll()
     
    14891396        lcd->switchToTime();
    14901397    }
    14911398
    1492     stop();
     1399    mainvisual->setDecoder(0);
     1400    mainvisual->setOutput(0);
     1401    mainvisual->deleteMetadata();
    14931402
    1494     if (decoder)
    1495     {
    1496         decoder->removeListener(this);
    1497         decoder = 0;
    1498     }
     1403    gPlayer->stop(true);
    14991404}
    15001405
    15011406void PlaybackBoxMusic::previous()
    15021407{
    1503     if (repeatmode == REPEAT_ALL)
     1408    if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_ALL)
    15041409    {
    15051410        if (music_tree_list->prevActive(true, show_whole_tree))
    15061411            music_tree_list->activate();
     
    15171422
    15181423void PlaybackBoxMusic::next()
    15191424{
    1520     if (repeatmode == REPEAT_ALL)
     1425    if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_ALL)
    15211426    {
    15221427        // Grab the next track after this one. First flag is to wrap around
    15231428        // to the beginning of the list. Second decides if we will traverse up
     
    15411446
    15421447void PlaybackBoxMusic::nextAuto()
    15431448{
    1544     stopDecoder();
    1545 
    1546     isplaying = false;
    1547 
    1548     if (repeatmode == REPEAT_TRACK)
     1449    if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_TRACK)
    15491450        play();
    15501451    else
    15511452        next();
     
    15691470
    15701471void PlaybackBoxMusic::seek(int pos)
    15711472{
    1572     if (output)
     1473    if (gPlayer->getOutput())
    15731474    {
    1574         output->Reset();
    1575         output->SetTimecode(pos*1000);
     1475        gPlayer->getOutput()->Reset();
     1476        gPlayer->getOutput()->SetTimecode(pos*1000);
    15761477
    1577         if (decoder && decoder->running())
     1478        if (gPlayer->getDecoder() && gPlayer->getDecoder()->running())
    15781479        {
    1579             decoder->lock();
    1580             decoder->seek(pos);
     1480            gPlayer->getDecoder()->lock();
     1481            gPlayer->getDecoder()->seek(pos);
    15811482
    15821483            if (mainvisual)
    15831484            {
     
    15861487                mainvisual->mutex()->unlock();
    15871488            }
    15881489
    1589             decoder->unlock();
     1490            gPlayer->getDecoder()->unlock();
    15901491        }
    15911492
    1592         if (!isplaying)
     1493        if (!gPlayer->isPlaying())
    15931494        {
    15941495            currentTime = pos;
    15951496            if (time_text)
     
    16141515    }
    16151516}
    16161517
    1617 void PlaybackBoxMusic::setShuffleMode(unsigned int mode)
     1518void PlaybackBoxMusic::setShuffleMode(MusicPlayer::ShuffleMode mode)
    16181519{
    1619     shufflemode = mode;
     1520    MusicPlayer::ShuffleMode shufflemode = mode;
    16201521    QString state;
    16211522
    16221523    switch (shufflemode)
    16231524    {
    1624         case SHUFFLE_INTELLIGENT:
     1525        case MusicPlayer::SHUFFLE_INTELLIGENT:
    16251526            state = tr("Smart");
    16261527            if (class LCD *lcd = LCD::Get())
    16271528                lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_SMART);
    16281529            break;
    1629         case SHUFFLE_RANDOM:
     1530        case MusicPlayer::SHUFFLE_RANDOM:
    16301531            state = tr("Rand");
    16311532            if (class LCD *lcd = LCD::Get())
    16321533                lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_RAND);
    16331534            break;
    1634         case SHUFFLE_ALBUM:
     1535        case MusicPlayer::SHUFFLE_ALBUM:
    16351536            state = tr("Album");
    16361537            if (class LCD *lcd = LCD::Get())
    16371538                lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ALBUM);
    16381539            break;
    1639         case SHUFFLE_ARTIST:
     1540        case MusicPlayer::SHUFFLE_ARTIST:
    16401541            state = tr("Artist");
    16411542            if (class LCD *lcd = LCD::Get())
    16421543                lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ARTIST);
     
    16631564
    16641565    bannerEnable(QString("%1: %2").arg(tr("Shuffle")).arg(state), 4000);
    16651566
    1666     if (!shufflemode == SHUFFLE_OFF)
     1567    if (!shufflemode == MusicPlayer::SHUFFLE_OFF)
    16671568        music_tree_list->scrambleParents(true);
    16681569    else
    16691570        music_tree_list->scrambleParents(true);
     
    16751576        music_tree_list->setVisualOrdering(1);
    16761577    music_tree_list->refresh();
    16771578
    1678     if (isplaying)
     1579    if (gPlayer->isPlaying())
    16791580        setTrackOnLCD(curMeta);
    16801581}
    16811582
    16821583void PlaybackBoxMusic::toggleShuffle(void)
    16831584{
    1684     setShuffleMode(++shufflemode % MAX_SHUFFLE_MODES);
     1585    setShuffleMode(gPlayer->toggleShuffleMode());
    16851586}
    16861587
    16871588void PlaybackBoxMusic::increaseRating()
     
    17131614    }
    17141615}
    17151616
    1716 void PlaybackBoxMusic::setRepeatMode(unsigned int mode)
     1617void PlaybackBoxMusic::setRepeatMode(MusicPlayer::RepeatMode mode)
    17171618{
    1718     repeatmode = mode;
     1619    MusicPlayer::RepeatMode repeatmode = mode;
    17191620    QString state;
    17201621
    17211622    switch (repeatmode)
    17221623    {
    1723         case REPEAT_ALL:
     1624        case MusicPlayer::REPEAT_ALL:
    17241625            state = tr("All");
    17251626            if (class LCD *lcd = LCD::Get())
    17261627                lcd->setMusicRepeat (LCD::MUSIC_REPEAT_ALL);
    17271628            break;
    1728         case REPEAT_TRACK:
     1629        case MusicPlayer::REPEAT_TRACK:
    17291630            state = tr("Track");
    17301631            if (class LCD *lcd = LCD::Get())
    17311632                lcd->setMusicRepeat (LCD::MUSIC_REPEAT_TRACK);
     
    17871688    gContext->SaveSetting("MusicBookmarkPosition", position);
    17881689}
    17891690
    1790 void PlaybackBoxMusic::restorePosition()
     1691void PlaybackBoxMusic::restorePosition(const QString &position)
    17911692{
    17921693    QValueList <int> branches_to_current_node;
    1793     QString s = gContext->GetSetting("MusicBookmark", "");
    17941694
    1795     if (s != "")
     1695    if (position != "")
    17961696    {
    1797         QStringList list = QStringList::split(",", s);
     1697        QStringList list = QStringList::split(",", position);
    17981698
    17991699        for (QStringList::Iterator it = list.begin(); it != list.end(); ++it)
    18001700            branches_to_current_node.append((*it).toInt());
     
    18101710            {
    18111711                if (music_tree_list->tryToSetActive(branches_to_current_node))
    18121712                {
    1813                     music_tree_list->select();
     1713                    if (gPlayer->isPlaying())
     1714                    {
     1715                        GenericTree *node = music_tree_list->getCurrentNode();
     1716                        if (node)
     1717                        {
     1718                            curMeta = all_music->getMetadata(node->getInt());
     1719                            updateTrackInfo(curMeta);
     1720
     1721                            maxTime = curMeta->Length() / 1000;
     1722
     1723                            QString time_string = getTimeString(maxTime, 0);
     1724
     1725                            if (showrating)
     1726                            {
     1727                                if (ratings_image)
     1728                                    ratings_image->setRepeat(curMeta->Rating());
     1729                            }
     1730
     1731                            mainvisual->setDecoder(gPlayer->getDecoder());
     1732                            mainvisual->setOutput(gPlayer->getOutput());
     1733                            mainvisual->setMetadata(curMeta);
     1734                            bannerEnable(curMeta, show_album_art);
     1735                        }
     1736                    }
     1737                    else
     1738                        music_tree_list->select();
    18141739                    return;
    18151740                }
    18161741            }
     
    18201745            //we're in show all tree mode - try to restore the position
    18211746            if (music_tree_list->tryToSetActive(branches_to_current_node))
    18221747            {
    1823                 music_tree_list->select();
     1748                if (gPlayer->isPlaying())
     1749                {
     1750                    GenericTree *node = music_tree_list->getCurrentNode();
     1751                    if (node)
     1752                    {
     1753                        curMeta = all_music->getMetadata(node->getInt());
     1754                        updateTrackInfo(curMeta);
     1755
     1756                        maxTime = curMeta->Length() / 1000;
     1757
     1758                        QString time_string = getTimeString(maxTime, 0);
     1759
     1760                        if (showrating)
     1761                        {
     1762                            if (ratings_image)
     1763                                ratings_image->setRepeat(curMeta->Rating());
     1764                        }
     1765
     1766                        mainvisual->setDecoder(gPlayer->getDecoder());
     1767                        mainvisual->setOutput(gPlayer->getOutput());
     1768                        mainvisual->setMetadata(curMeta);
     1769                        bannerEnable(curMeta, show_album_art);
     1770                    }
     1771                }
     1772                else
     1773                    music_tree_list->select();
     1774
    18241775                return;
    18251776            }
    18261777        }
     
    18351786
    18361787void PlaybackBoxMusic::toggleRepeat()
    18371788{
    1838     setRepeatMode(++repeatmode % MAX_REPEAT_MODES);
     1789    setRepeatMode(gPlayer->toggleRepeatMode());
    18391790}
    18401791
    18411792void PlaybackBoxMusic::constructPlaylistTree()
    18421793{
     1794    GenericTree *playlist_tree = gPlayer->getPlaylistTree();
     1795
    18431796    if (playlist_tree)
    18441797        delete playlist_tree;
    18451798
     
    19191872        cd_watcher->start(1000);
    19201873}
    19211874
    1922 void PlaybackBoxMusic::closeEvent(QCloseEvent *event)
    1923 {
    1924     stopAll();
    1925 
    1926     hide();
    1927     event->accept();
    1928 }
    1929 
    1930 void PlaybackBoxMusic::showEvent(QShowEvent *event)
    1931 {
    1932     QWidget::showEvent(event);
    1933 }
    1934 
    19351875void PlaybackBoxMusic::customEvent(QCustomEvent *event)
    19361876{
    19371877    switch ((int)event->type())
     
    20612001            break;
    20622002        }
    20632003    }
     2004    //cout << "status string: " << statusString << endl;
    20642005
    20652006    QWidget::customEvent(event);
    20662007}
     
    20952036    setTrackOnLCD(mdata);
    20962037}
    20972038
    2098 void PlaybackBoxMusic::openOutputDevice(void)
    2099 {
    2100     QString adevice;
    2101 
    2102     if (gContext->GetSetting("MusicAudioDevice") == "default")
    2103         adevice = gContext->GetSetting("AudioOutputDevice");
    2104     else
    2105         adevice = gContext->GetSetting("MusicAudioDevice");
    2106 
    2107     // TODO: Error checking that device is opened correctly!
    2108     output = AudioOutput::OpenAudio(adevice, "default", 16, 2, 44100,
    2109                                     AUDIOOUTPUT_MUSIC, true,
    2110                                     false /* AC3/DTS pass through */);
    2111     output->setBufferSize(outputBufferSize * 1024);
    2112     output->SetBlocking(false);
    2113     output->addListener(this);
    2114     output->addListener(mainvisual);
    2115     output->addVisual(mainvisual);   
    2116 }
    2117 
    21182039void PlaybackBoxMusic::handleTreeListSignals(int node_int, IntVector *attributes)
    21192040{
    21202041    if (attributes->size() < 4)
     
    21462067        }
    21472068    }
    21482069
     2070    GenericTree *node = music_tree_list->getCurrentNode();
     2071    if (node && node->childCount() > 0)
     2072        return;
     2073
    21492074    if (attributes->at(0) == 1)
    21502075    {
    21512076        //  It's a track
     
    21642089                ratings_image->setRepeat(curMeta->Rating());
    21652090        }
    21662091
    2167         if (output && output->GetPause())
    2168             stop();
    2169 
     2092        if (gPlayer->getOutput() && gPlayer->getOutput()->GetPause())
     2093        {
     2094            gPlayer->stop();
     2095        }
    21702096        if (m_pushedButton && m_pushedButton->Name() == "play_button")
    21712097        {
    21722098            // Play button already pushed, so don't push it again.
     
    23492275
    23502276    // only give the user a choice of the track to play if shuffle mode is off
    23512277    MythComboBox *playCombo = NULL;
    2352     if (shufflemode == SHUFFLE_OFF)
     2278    if (gPlayer->getShuffleMode() == MusicPlayer::SHUFFLE_OFF)
    23532279    {
    23542280        playCombo = new MythComboBox(false, popup, "play_combo" );
    23552281        playCombo->insertItem(tr("Continue playing current track"));
     
    23582284        playCombo->setBackgroundOrigin(ParentOrigin);
    23592285        popup->addWidget(playCombo);
    23602286    }
    2361    
     2287
    23622288    MythCheckBox *dupsCheck = new MythCheckBox(popup);
    23632289    dupsCheck->setText(tr("Remove Duplicates"));
    23642290    dupsCheck->setChecked(false);
     
    23882314
    23892315    // if shuffle mode != SHUFFLE_OFF we always try to continue playing
    23902316    // the current track
    2391     if (shufflemode == SHUFFLE_OFF)
     2317    if (gPlayer->getShuffleMode() == MusicPlayer::SHUFFLE_OFF)
    23922318    {
    23932319        switch (playCombo->currentItem())
    23942320        {
  • mythmusic/mythmusic.pro

     
    3939HEADERS += goom/mmx.h goom/mathtools.h goom/tentacle3d.h goom/v3d.h
    4040HEADERS += editmetadata.h smartplaylist.h search.h genres.h
    4141HEADERS += treebuilders.h importmusic.h directoryfinder.h
    42 HEADERS += filescanner.h libvisualplugin.h
     42HEADERS += filescanner.h libvisualplugin.h musicplayer.h miniplayer.h
    4343
    4444SOURCES += cddecoder.cpp cdrip.cpp decoder.cpp
    4545SOURCES += flacdecoder.cpp flacencoder.cpp maddecoder.cpp main.cpp
     
    5555SOURCES += goom/zoom_filter_mmx.c goom/zoom_filter_xmmx.c goom/mythgoom.cpp
    5656SOURCES += avfdecoder.cpp editmetadata.cpp smartplaylist.cpp search.cpp
    5757SOURCES += treebuilders.cpp importmusic.cpp directoryfinder.cpp
    58 SOURCES += filescanner.cpp libvisualplugin.cpp
     58SOURCES += filescanner.cpp libvisualplugin.cpp musicplayer.cpp miniplayer.cpp
    5959
    6060macx {
    6161    SOURCES -= cddecoder.cpp
     
    6767    #QMAKE_LFLAGS += -flat_namespace -undefined suppress
    6868    QMAKE_LFLAGS += -flat_namespace -undefined error
    6969}
     70
  • mythmusic/music-ui.xml

     
    17921792       </container>
    17931793   </window>
    17941794
     1795   <window name="miniplayer">
     1796
     1797    <font name="currenttitle" face="Arial">
     1798        <color>#ffffff</color>
     1799        <size>20</size>
     1800        <bold>yes</bold>
     1801    </font>
     1802
     1803    <font name="currentartist" face="Arial">
     1804        <color>#ffffff</color>
     1805        <size>16</size>
     1806        <bold>yes</bold>
     1807    </font>
     1808
     1809    <font name="infotext" face="Arial">
     1810        <color>#ffffff</color>
     1811        <size>12</size>
     1812        <bold>yes</bold>
     1813    </font>
     1814
     1815    <container name="player_container">
     1816        <area>0,0,590,170</area>
     1817        <image name="track_info_background" draworder="0" fleximage="no">
     1818            <filename>miniplayer_background.png</filename>
     1819            <position>10,10</position>
     1820        </image>
     1821
     1822        <image name="mm_blackhole_border" draworder="0" fleximage="no">
     1823            <filename>mm_blackhole_border.png</filename>
     1824            <position>20,20</position>
     1825        </image>
     1826
     1827        <textarea name="title_text" draworder="1" align="left">
     1828            <font>currenttitle</font>
     1829            <area>160,15,415,34</area>
     1830            <cutdown>yes</cutdown>
     1831        </textarea>
     1832
     1833        <textarea name="artist_text" draworder="1" align="left">
     1834            <font>currentartist</font>
     1835            <area>160,50,415,25</area>
     1836            <cutdown>yes</cutdown>
     1837        </textarea>
     1838
     1839        <textarea name="album_text" draworder="1" align="left">
     1840            <font>currentartist</font>
     1841            <area>160,73,415,25</area>
     1842            <cutdown>yes</cutdown>
     1843        </textarea>
     1844
     1845        <repeatedimage name="ratings_image" draworder="1" fleximage="no">
     1846            <filename>mm_rating.png</filename>
     1847            <position>160,105</position>
     1848            <orientation>LeftToRight</orientation>
     1849        </repeatedimage>
     1850
     1851        <textarea name="info_text" draworder="1" align="left">
     1852            <font>infotext</font>
     1853            <area>160,129,250,25</area>
     1854        </textarea>
     1855
     1856        <textarea name="time_text" draworder="1" align="right">
     1857            <font>currentartist</font>
     1858            <area>375,125,185,25</area>
     1859        </textarea>
     1860
     1861        <image name="cover_image" draworder="2">
     1862            <filename>mm_nothumb.png</filename>
     1863            <position>22,22</position>
     1864            <staticsize>122,124</staticsize>
     1865        </image>
     1866
     1867    </container>
     1868
     1869  </window>
     1870
    17951871</mythuitheme>
  • mythmusic/miniplayer.cpp

     
     1#include <iostream>
     2using namespace std;
     3
     4// qt
     5#include <qpixmap.h>
     6#include <qimage.h>
     7#include <qapplication.h>
     8
     9// mythtv
     10#include <mythtv/mythcontext.h>
     11#include <mythtv/mythdialogs.h>
     12#include <mythtv/uitypes.h>
     13#include <mythtv/lcddevice.h>
     14
     15// mythmusic
     16#include "miniplayer.h"
     17#include "musicplayer.h"
     18#include "decoder.h"
     19
     20MiniPlayer::MiniPlayer(MythMainWindow *parent,
     21                    MusicPlayer *parentPlayer,
     22                    const char *name,
     23                    bool setsize)
     24            : MythThemedDialog(parent, name, setsize)
     25{
     26    setFrameStyle(QFrame::Panel | QFrame::Raised);
     27    setLineWidth(1);
     28    m_parentPlayer = parentPlayer;
     29
     30    m_displayTimer = new QTimer(this);
     31    connect(m_displayTimer, SIGNAL(timeout()), this, SLOT(timerTimeout()));
     32
     33    m_infoTimer = new QTimer(this);
     34    connect(m_infoTimer, SIGNAL(timeout()), this, SLOT(showInfoTimeout()));
     35
     36    wireupTheme();
     37
     38    gPlayer->setListener(this);
     39
     40    if (gPlayer->isPlaying() && gPlayer->getCurrentMetadata())
     41    {
     42        m_maxTime = gPlayer->getCurrentMetadata()->Length() / 1000;
     43        updateTrackInfo(gPlayer->getCurrentMetadata());
     44    }
     45
     46    m_showingInfo = false;
     47}
     48
     49MiniPlayer::~MiniPlayer(void)
     50{
     51    gPlayer->setListener(NULL);
     52
     53    m_displayTimer->deleteLater();
     54    m_displayTimer = NULL;
     55
     56    m_infoTimer->deleteLater();
     57    m_infoTimer = NULL;
     58
     59    if (class LCD *lcd = LCD::Get())
     60        lcd->switchToTime ();
     61}
     62
     63void MiniPlayer::showPlayer(int showTime)
     64{
     65    m_displayTimer->start(showTime * 1000, true);
     66    exec();
     67}
     68
     69void MiniPlayer::timerTimeout(void)
     70{
     71    done(Accepted);
     72}
     73
     74void MiniPlayer::wireupTheme(void)
     75{
     76    QString theme_file = QString("music-");
     77
     78    if (!loadThemedWindow("miniplayer", theme_file))
     79    {
     80        VERBOSE(VB_GENERAL, "MiniPlayer: cannot load theme!");
     81        done(0);
     82        return;
     83    }
     84
     85    // get dialog size from player_container area
     86    LayerSet *container = getContainer("player_container");
     87
     88    if (!container)
     89    {
     90        cerr << "MiniPlayer: cannot find the 'player_container'"
     91                " in your theme" << endl;
     92        done(0);
     93        return;
     94    }
     95
     96    m_popupWidth = container->GetAreaRect().width();
     97    m_popupHeight = container->GetAreaRect().height();
     98    setFixedSize(QSize(m_popupWidth, m_popupHeight));
     99
     100    int xbase, width, ybase, height;
     101    float wmult, hmult;
     102    gContext->GetScreenSettings(xbase, width, wmult, ybase, height, hmult);
     103    QRect tlwg = QRect(0, 0, width, height);
     104
     105    QPoint newpos;
     106
     107    PlayerPosition preferredPos = MP_POSTOPDIALOG;
     108
     109    if (preferredPos == MP_POSTOPDIALOG)
     110    {
     111        newpos = QPoint(tlwg.width() / 2 - m_popupWidth / 2, 5);
     112        this->move(newpos);
     113    }
     114    else if (preferredPos == MP_POSBOTTOMDIALOG)
     115    {
     116        newpos = QPoint(tlwg.width() / 2 - m_popupWidth / 2,
     117                        tlwg.height() - 5 - m_popupHeight);
     118        this->move(newpos);
     119    }
     120    else if (preferredPos == MP_POSCENTERDIALOG)
     121    {
     122        newpos = QPoint(tlwg.width() / 2 - m_popupWidth / 2,
     123                        tlwg.height() / 2 - m_popupHeight / 2);
     124        this->move(newpos);
     125    }
     126
     127    m_titleText = getUITextType("title_text");
     128    m_artistText = getUITextType("artist_text");
     129    m_timeText = getUITextType("time_text");
     130    m_infoText = getUITextType("info_text");
     131    m_albumText = getUITextType("album_text");
     132    m_ratingsImage = getUIRepeatedImageType("ratings_image");
     133    m_coverImage = getUIImageType("cover_image");
     134}
     135
     136void MiniPlayer::show()
     137{
     138    grabKeyboard();
     139
     140    MythDialog::show();
     141}
     142
     143void MiniPlayer::hide()
     144{
     145    releaseKeyboard();
     146
     147    MythDialog::hide();
     148}
     149
     150void MiniPlayer::keyPressEvent(QKeyEvent *e)
     151{
     152    bool handled = false;
     153    QStringList actions;
     154    if (gContext->GetMainWindow()->TranslateKeyPress("Music", e, actions, false))
     155    {
     156        for (unsigned int i = 0; i < actions.size() && !handled; i++)
     157        {
     158            QString action = actions[i];
     159            handled = true;
     160            if (action == "ESCAPE")
     161                done(0);
     162            else if (action == "SELECT")
     163                    m_displayTimer->stop();
     164            else if (action == "NEXTTRACK")
     165            {
     166                gPlayer->next();
     167            }
     168            else if (action == "PREVTRACK")
     169            {
     170                gPlayer->previous();
     171            }
     172            else if (action == "FFWD")
     173            {
     174                seekforward();
     175            }
     176            else if (action == "RWND")
     177            {
     178                seekback();
     179            }
     180            else if (action == "PAUSE")
     181            {
     182                if (gPlayer->isPlaying())
     183                    gPlayer->pause();
     184                else
     185                {
     186                    if (gPlayer->isPlaying())
     187                        gPlayer->stop();
     188
     189                    if (gPlayer->getOutput() && gPlayer->getOutput()->GetPause())
     190                    {
     191                        gPlayer->pause();
     192                        return;
     193                    }
     194
     195                    gPlayer->play();
     196                }
     197            }
     198            else if (action == "STOP")
     199            {
     200                gPlayer->stop();
     201
     202                QString time_string = getTimeString(m_maxTime, 0);
     203
     204                if (m_timeText)
     205                    m_timeText->SetText(time_string);
     206                if (m_infoText)
     207                    m_infoText->SetText("");
     208            }
     209            else if (action == "VOLUMEDOWN")
     210            {
     211                if (gPlayer->getOutput())
     212                {
     213                    gPlayer->getOutput()->AdjustCurrentVolume(-2);
     214                    showVolume();
     215                }
     216            }
     217            else if (action == "VOLUMEUP")
     218            {
     219                if (gPlayer->getOutput())
     220                {
     221                    gPlayer->getOutput()->AdjustCurrentVolume(2);
     222                    showVolume();
     223                }
     224            }
     225            else if (action == "MUTE")
     226            {
     227                if (gPlayer->getOutput())
     228                {
     229                    gPlayer->getOutput()->ToggleMute();
     230
     231                    if (m_infoText)
     232                    {
     233                        m_showingInfo = true;
     234                        if (gPlayer->getOutput()->GetMute())
     235                            m_infoText->SetText(tr("Mute: On"));
     236                        else
     237                            m_infoText->SetText(tr("Mute: Off"));
     238
     239                        m_infoTimer->start(5000, true);
     240                    }
     241                }
     242            }
     243            else if (action == "THMBUP")
     244                increaseRating();
     245            else if (action == "THMBDOWN")
     246                decreaseRating();
     247            else if (action == "1")
     248            {
     249                gPlayer->toggleShuffleMode();
     250                showShuffleMode();
     251            }
     252            else if (action == "2")
     253            {
     254                gPlayer->toggleRepeatMode();
     255                showRepeatMode();
     256            }
     257            else
     258                handled = false;
     259        }
     260    }
     261}
     262
     263void MiniPlayer::customEvent(QCustomEvent *event)
     264{
     265
     266    switch ((int)event->type())
     267    {
     268        case OutputEvent::Playing:
     269        {
     270            if (gPlayer->getCurrentMetadata())
     271            {
     272                m_maxTime = gPlayer->getCurrentMetadata()->Length() / 1000;
     273                updateTrackInfo(gPlayer->getCurrentMetadata());
     274            }
     275            break;
     276        }
     277
     278        case OutputEvent::Buffering:
     279        {
     280            break;
     281        }
     282
     283        case OutputEvent::Paused:
     284        {
     285            break;
     286        }
     287
     288        case OutputEvent::Info:
     289       {
     290            OutputEvent *oe = (OutputEvent *) event;
     291
     292            int rs;
     293            m_currTime = rs = oe->elapsedSeconds();
     294
     295            QString time_string = getTimeString(rs, m_maxTime);
     296
     297            QString info_string;
     298
     299            //  Hack around for cd bitrates
     300            if (oe->bitrate() < 2000)
     301            {
     302                info_string.sprintf("%d "+tr("kbps")+ "   %.1f "+ tr("kHz")+ "   %s "+ tr("ch"),
     303                                   oe->bitrate(), float(oe->frequency()) / 1000.0,
     304                                   oe->channels() > 1 ? "2" : "1");
     305            }
     306            else
     307            {
     308                info_string.sprintf("%.1f "+ tr("kHz")+ "   %s "+ tr("ch"),
     309                                   float(oe->frequency()) / 1000.0,
     310                                   oe->channels() > 1 ? "2" : "1");
     311            }
     312
     313            if (m_timeText)
     314                m_timeText->SetText(time_string);
     315            if (m_infoText && !m_showingInfo)
     316                m_infoText->SetText(info_string);
     317
     318            if (gPlayer->getCurrentMetadata())
     319            {
     320                if (class LCD *lcd = LCD::Get())
     321                {
     322                    float percent_heard = m_maxTime <=0 ? 0.0 :
     323                            ((float)rs / (float)gPlayer->getCurrentMetadata()->Length()) * 1000.0;
     324
     325                    QString lcd_time_string = time_string;
     326
     327                    // if the string is longer than the LCD width, remove all spaces
     328                    if (time_string.length() > lcd->getLCDWidth())
     329                        lcd_time_string.remove(' ');
     330
     331                    lcd->setMusicProgress(lcd_time_string, percent_heard);
     332                }
     333            }
     334            break;
     335        }
     336        case OutputEvent::Error:
     337        {
     338            break;
     339        }
     340        case DecoderEvent::Stopped:
     341        {
     342            break;
     343        }
     344        case DecoderEvent::Finished:
     345        {
     346            if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_TRACK)
     347               gPlayer->play();
     348            else
     349                gPlayer->next();
     350            break;
     351        }
     352        case DecoderEvent::Error:
     353        {
     354            break;
     355        }
     356    }
     357    QObject::customEvent(event);
     358}
     359
     360QString MiniPlayer::getTimeString(int exTime, int maxTime)
     361{
     362    QString time_string;
     363
     364    int eh = exTime / 3600;
     365    int em = (exTime / 60) % 60;
     366    int es = exTime % 60;
     367
     368    int maxh = maxTime / 3600;
     369    int maxm = (maxTime / 60) % 60;
     370    int maxs = maxTime % 60;
     371
     372    if (maxTime <= 0)
     373    {
     374        if (eh > 0)
     375            time_string.sprintf("%d:%02d:%02d", eh, em, es);
     376        else
     377            time_string.sprintf("%02d:%02d", em, es);
     378    }
     379    else
     380    {
     381        if (maxh > 0)
     382            time_string.sprintf("%d:%02d:%02d / %02d:%02d:%02d", eh, em,
     383                    es, maxh, maxm, maxs);
     384        else
     385            time_string.sprintf("%02d:%02d / %02d:%02d", em, es, maxm,
     386                    maxs);
     387    }
     388
     389    return time_string;
     390}
     391
     392void MiniPlayer::updateTrackInfo(Metadata *mdata)
     393{
     394    if (m_titleText)
     395        m_titleText->SetText(mdata->FormatTitle());
     396    if (m_artistText)
     397        m_artistText->SetText(mdata->FormatArtist());
     398    if (m_albumText)
     399        m_albumText->SetText(mdata->Album());
     400    if (m_ratingsImage)
     401        m_ratingsImage->setRepeat(mdata->Rating());
     402
     403    if (m_coverImage)
     404    {
     405        QImage image = gPlayer->getCurrentMetadata()->getAlbumArt(IT_FRONTCOVER);
     406        if (!image.isNull())
     407            m_coverImage->SetImage(
     408                    QPixmap(image.smoothScale(m_coverImage->GetSize(true))));
     409        m_coverImage->refresh();
     410    }
     411
     412    LCD *lcd = LCD::Get();
     413    if (lcd)
     414    {
     415        // Set the Artist and Track on the LCD
     416        lcd->switchToMusic(mdata->Artist(),
     417                       mdata->Album(),
     418                       mdata->Title());
     419    }
     420}
     421
     422void MiniPlayer::seekforward(void)
     423{
     424    int nextTime = m_currTime + 5;
     425    if (nextTime > m_maxTime)
     426        nextTime = m_maxTime;
     427    seek(nextTime);
     428}
     429
     430void MiniPlayer::seekback(void)
     431{
     432    int nextTime = m_currTime - 5;
     433    if (nextTime < 0)
     434        nextTime = 0;
     435    seek(nextTime);
     436}
     437
     438void MiniPlayer::seek(int pos)
     439{
     440    if (gPlayer->getOutput())
     441    {
     442        gPlayer->getOutput()->Reset();
     443        gPlayer->getOutput()->SetTimecode(pos*1000);
     444
     445        if (gPlayer->getDecoder() && gPlayer->getDecoder()->running())
     446        {
     447            gPlayer->getDecoder()->lock();
     448            gPlayer->getDecoder()->seek(pos);
     449            gPlayer->getDecoder()->unlock();
     450        }
     451
     452        if (!gPlayer->isPlaying())
     453        {
     454            m_currTime = pos;
     455            if (m_timeText)
     456                m_timeText->SetText(getTimeString(pos, m_maxTime));
     457
     458            //showProgressBar();
     459
     460            if (class LCD *lcd = LCD::Get())
     461            {
     462                float percent_heard = m_maxTime <= 0 ? 0.0 : ((float)pos /
     463                                      (float)m_maxTime);
     464
     465                QString lcd_time_string = getTimeString(pos, m_maxTime);
     466
     467                // if the string is longer than the LCD width, remove all spaces
     468                if (lcd_time_string.length() > lcd->getLCDWidth())
     469                    lcd_time_string.remove(' ');
     470
     471                lcd->setMusicProgress(lcd_time_string, percent_heard);
     472            }
     473        }
     474    }
     475}
     476
     477void MiniPlayer::increaseRating(void)
     478{
     479    Metadata *curMeta = gPlayer->getCurrentMetadata();
     480
     481    if (!curMeta)
     482        return;
     483
     484    if (m_ratingsImage)
     485    {
     486        curMeta->incRating();
     487        m_ratingsImage->setRepeat(curMeta->Rating());
     488    }
     489}
     490
     491void MiniPlayer::decreaseRating(void)
     492{
     493    Metadata *curMeta = gPlayer->getCurrentMetadata();
     494
     495    if (!curMeta)
     496        return;
     497
     498    if (m_ratingsImage)
     499    {
     500        curMeta->decRating();
     501        m_ratingsImage->setRepeat(curMeta->Rating());
     502    }
     503}
     504
     505void MiniPlayer::showInfoTimeout(void)
     506{
     507    m_showingInfo = false;
     508    LCD *lcd = LCD::Get();
     509    Metadata * mdata = gPlayer->getCurrentMetadata();
     510
     511    if (lcd && mdata)
     512    {
     513        // Set the Artist and Track on the LCD
     514        lcd->switchToMusic(mdata->Artist(),
     515                       mdata->Album(),
     516                       mdata->Title());
     517    }
     518}
     519
     520void MiniPlayer::showShuffleMode(void)
     521{
     522    if (m_infoText)
     523    {
     524        m_infoTimer->stop();
     525        QString msg = tr("Shuffle Mode: ");
     526        switch (gPlayer->getShuffleMode())
     527        {
     528            case MusicPlayer::SHUFFLE_INTELLIGENT:
     529                msg += tr("Smart");
     530                if (class LCD *lcd = LCD::Get())
     531                    lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_SMART);
     532                break;
     533            case MusicPlayer::SHUFFLE_RANDOM:
     534                msg += tr("Rand");
     535                if (class LCD *lcd = LCD::Get())
     536                    lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_RAND);
     537                break;
     538            case MusicPlayer::SHUFFLE_ALBUM:
     539                msg += tr("Album");
     540                if (class LCD *lcd = LCD::Get())
     541                    lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ALBUM);
     542                break;
     543            case MusicPlayer::SHUFFLE_ARTIST:
     544                msg += tr("Artist");
     545                if (class LCD *lcd = LCD::Get())
     546                    lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ARTIST);
     547                break;
     548            default:
     549                msg += tr("None");
     550                if (class LCD *lcd = LCD::Get())
     551                    lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_NONE);
     552                break;
     553        }
     554
     555        m_showingInfo = true;
     556        m_infoText->SetText(msg);
     557        m_infoTimer->start(5000, true);
     558    }
     559}
     560
     561void MiniPlayer::showRepeatMode(void)
     562{
     563    if (m_infoText)
     564    {
     565        m_infoTimer->stop();
     566        QString msg = tr("Repeat Mode: ");
     567        switch (gPlayer->getRepeatMode())
     568        {
     569            case MusicPlayer::REPEAT_ALL:
     570                msg += tr("All");
     571                if (class LCD *lcd = LCD::Get())
     572                    lcd->setMusicRepeat (LCD::MUSIC_REPEAT_ALL);
     573                break;
     574            case MusicPlayer::REPEAT_TRACK:
     575                msg += tr("Track");
     576                if (class LCD *lcd = LCD::Get())
     577                    lcd->setMusicRepeat (LCD::MUSIC_REPEAT_TRACK);
     578                break;
     579            default:
     580                msg += tr("None");
     581                if (class LCD *lcd = LCD::Get())
     582                    lcd->setMusicRepeat (LCD::MUSIC_REPEAT_NONE);
     583                break;
     584        }
     585
     586        m_showingInfo = true;
     587        m_infoText->SetText(msg);
     588        m_infoTimer->start(5000, true);
     589    }
     590}
     591
     592void MiniPlayer::showVolume(void)
     593{
     594    if (m_infoText)
     595    {
     596        m_infoTimer->stop();
     597        QString msg = tr("Volume: ");
     598        float level;
     599
     600        level = (float)gPlayer->getOutput()->GetCurrentVolume();
     601
     602        if (gPlayer->getOutput()->GetMute())
     603        {
     604            if (class LCD *lcd = LCD::Get())
     605            {
     606                lcd->switchToVolume("Music (muted)");
     607                lcd->setVolumeLevel(level / (float)100);
     608            }
     609            msg += QString::number((int) level) + "% " + tr("(muted)");
     610        }
     611        else
     612        {
     613            if (class LCD *lcd = LCD::Get())
     614            {
     615                lcd->switchToVolume("Music");
     616                lcd->setVolumeLevel(level / (float)100);
     617            }
     618            msg += QString::number((int) level) + "%";
     619        }
     620
     621        m_showingInfo = true;
     622        m_infoText->SetText(msg);
     623        m_infoTimer->start(5000, true);
     624    }
     625}
  • mythmusic/metadata.cpp

     
    725725    return image;
    726726}
    727727
     728// static function to get a matadata object given a track id
     729// it's upto the caller to delete the returned object when finished
     730Metadata *Metadata::getMetadataFromID(int id)
     731{
     732    Metadata *meta = NULL;
     733
     734    QString aquery = "SELECT music_songs.song_id, music_artists.artist_name, music_comp_artists.artist_name AS compilation_artist, "
     735                     "music_albums.album_name, music_songs.name, music_genres.genre, music_songs.year, "
     736                     "music_songs.track, music_songs.length, CONCAT_WS('/', "
     737                     "music_directories.path, music_songs.filename) AS filename, "
     738                     "music_songs.rating, music_songs.numplays, music_songs.lastplay, music_albums.compilation, "
     739                     "music_songs.format "
     740                     "FROM music_songs "
     741                     "LEFT JOIN music_directories ON music_songs.directory_id=music_directories.directory_id "
     742                     "LEFT JOIN music_artists ON music_songs.artist_id=music_artists.artist_id "
     743                     "LEFT JOIN music_albums ON music_songs.album_id=music_albums.album_id "
     744                     "LEFT JOIN music_artists AS music_comp_artists ON music_albums.artist_id=music_comp_artists.artist_id "
     745                     "LEFT JOIN music_genres ON music_songs.genre_id=music_genres.genre_id "
     746                     "WHERE music_songs.song_id = :TRACKID;";
     747
     748    QString filename, artist, album, title;
     749
     750    MSqlQuery query(MSqlQuery::InitCon());
     751    query.prepare(aquery);
     752    query.bindValue(":TRACKID", id);
     753    query.exec();
     754
     755    if (query.isActive() && query.size() > 0)
     756    {
     757        query.next();
     758        filename = QString::fromUtf8(query.value(9).toString());
     759        if (!filename.contains("://"))
     760            filename = m_startdir + filename;
     761
     762        artist = QString::fromUtf8(query.value(1).toString());
     763        if (artist.isEmpty())
     764            artist = QObject::tr("Unknown Artist");
     765
     766        album = QString::fromUtf8(query.value(3).toString());
     767        if (album.isEmpty())
     768            album = QObject::tr("Unknown Album");
     769
     770        title = QString::fromUtf8(query.value(4).toString());
     771        if (title.isEmpty())
     772            title = QObject::tr("Unknown Title");
     773
     774        meta = new Metadata(
     775            filename,
     776            artist,
     777            QString::fromUtf8(query.value(2).toString()),
     778            album,
     779            title,
     780            QString::fromUtf8(query.value(5).toString()),
     781            query.value(6).toInt(),
     782            query.value(7).toInt(),
     783            query.value(8).toInt(),
     784            query.value(0).toInt(),
     785            query.value(10).toInt(), //rating
     786            query.value(11).toInt(), //playcount
     787            query.value(12).toString(), //lastplay
     788            (query.value(13).toInt() > 0), //compilation
     789            query.value(14).toString()); //format
     790    }
     791    else
     792    {
     793         VERBOSE(VB_IMPORTANT, QString("Track %1 not found!!").arg(id));
     794         return NULL;
     795    }
     796
     797    return meta;
     798}
     799
     800//--------------------------------------------------------------------------
     801
    728802MetadataLoadingThread::MetadataLoadingThread(AllMusic *parent_ptr)
    729803{
    730804    parent = parent_ptr;
  • mythmusic/metadata.h

     
    183183    static QString GetStartdir() { return m_startdir; }
    184184
    185185    static QStringList fillFieldList(QString field);
     186    static Metadata *getMetadataFromID(int id);
    186187
    187188    QImage getAlbumArt(ImageType type);
    188189
  • mythmusic/musicplayer.h

     
     1#ifndef MUSICPLAYER_H_
     2#define MUSICPLAYER_H_
     3
     4#include <iostream>
     5
     6#include <mythtv/mythdialogs.h>
     7#include <mythtv/audiooutput.h>
     8
     9#include "metadata.h"
     10
     11class Decoder;
     12class AudioOutput;
     13class MainVisual;
     14
     15class MusicPlayer : public QObject
     16{
     17  //Q_OBJECT
     18
     19  public:
     20
     21     MusicPlayer(QObject *parent, const QString &dev);
     22    ~MusicPlayer(void);
     23
     24    void playFile(const QString &filename);
     25    void playFile(const Metadata &meta);
     26
     27    void addFile(const QString &filename) {};
     28    void addFile(const Metadata &meta) {};
     29
     30    void setListener(QObject *listener);
     31    void setVisual(MainVisual *visual);
     32    void setCDDevice(const QString &dev) { m_CDdevice = dev; }
     33
     34    void mute(void) {};
     35    void unMute(void) {};
     36    void setVolume(void) {};
     37
     38    void play(void);
     39    void stop(bool stopAll = false);
     40    void pause(void);
     41    void next(void);
     42    void previous(void);
     43
     44    void nextAuto(void);
     45
     46    bool isPlaying(void) { return m_isPlaying; }
     47    bool hasClient(void) { return (m_listener != NULL); }
     48
     49    Decoder     *getDecoder(void) { return m_decoder; }
     50    AudioOutput *getOutput(void) { return m_output; }
     51
     52    GenericTree *getPlaylistTree() { return m_playlistTree; }
     53    void         setCurrentNode(GenericTree *node) { m_currentNode = node; }
     54    QString      getRouteToCurrent(void);
     55
     56    Metadata    *getCurrentMetadata(void);
     57
     58    void showMiniPlayer(void);
     59
     60    enum RepeatMode
     61    { REPEAT_OFF = 0,
     62      REPEAT_TRACK,
     63      REPEAT_ALL,
     64      MAX_REPEAT_MODES
     65    };
     66    enum ShuffleMode
     67    { SHUFFLE_OFF = 0,
     68      SHUFFLE_RANDOM,
     69      SHUFFLE_INTELLIGENT,
     70      SHUFFLE_ALBUM,
     71      SHUFFLE_ARTIST,
     72      MAX_SHUFFLE_MODES
     73    };
     74
     75    RepeatMode getRepeatMode(void) { return m_repeatMode; }
     76    void       setRepeatMode(RepeatMode mode) { m_repeatMode = mode; }
     77    RepeatMode toggleRepeatMode(void);
     78
     79    ShuffleMode getShuffleMode(void) { return m_shuffleMode; }
     80    void        setShuffleMode(ShuffleMode mode) { m_shuffleMode = mode; }
     81    ShuffleMode toggleShuffleMode(void);
     82
     83  protected:
     84    void customEvent(QCustomEvent *event);
     85
     86  private:
     87    void stopDecoder(void);
     88    void openOutputDevice(void);
     89    QString getFilenameFromID(int id);
     90
     91    GenericTree *m_playlistTree;
     92
     93    GenericTree *m_currentNode;
     94    Metadata    *m_currentMetadata;
     95    QString      m_currentFile;
     96
     97    QIODevice   *m_input;
     98    AudioOutput *m_output;
     99    Decoder     *m_decoder;
     100
     101    QObject     *m_listener;
     102    MainVisual  *m_visual;
     103
     104    QString      m_CDdevice;
     105
     106    bool         m_isPlaying;
     107    bool         m_isAutoplay;
     108
     109    ShuffleMode  m_shuffleMode;
     110    RepeatMode   m_repeatMode;
     111};
     112
     113// This global variable contains the MusicPlayer instance for the application
     114extern MPUBLIC MusicPlayer *gPlayer;
     115
     116#endif
  • mythmusic/main.cpp

     
    2929#include "dbcheck.h"
    3030#include "importmusic.h"
    3131#include "filescanner.h"
     32#include "musicplayer.h"
    3233#include "config.h"
    3334
    3435// System header (relies on config.h define)
     
    151152    pbb->exec();
    152153    qApp->lock();
    153154
    154     pbb->stop();
    155 
    156155    qApp->processEvents();
    157156
    158157    delete pbb;
     
    313312void runMusicSelection(void);
    314313void runRipCD(void);
    315314void runScan(void);
     315void showMiniPlayer(void);
    316316
    317 
    318317void handleMedia(MythMediaDevice *cd)
    319318{
    320319    // Note that we should deal with other disks that may contain music.
     
    365364    REG_JUMP("Select music playlists", "", "", runMusicSelection);
    366365    REG_JUMP("Rip CD",                 "", "", runRipCD);
    367366    REG_JUMP("Scan music",             "", "", runScan);
     367    REG_JUMPEX("Show Miniplayer",        "", "", showMiniPlayer, false);
    368368
    369369    REG_KEY("Music", "DELETE",     "Delete track from playlist", "D");
    370370    REG_KEY("Music", "NEXTTRACK",  "Move to the next track",     ">,.,Z,End");
     
    423423
    424424    Decoder::SetLocationFormatUseTags();
    425425
     426    gPlayer = new MusicPlayer(NULL, chooseCD());
     427
    426428    return 0;
    427429}
    428430
     
    530532    return 0;
    531533}
    532534
     535void mythplugin_destroy(void)
     536{
     537    delete gPlayer;
     538}
     539
    533540void runMusicPlayback(void)
    534541{
    535542    MusicData mdata;
     
    585592
    586593    postMusic(&mdata);
    587594}
     595
     596void showMiniPlayer(void)
     597{
     598    // only show the miniplayer if there isn't already a client attached
     599    if (!gPlayer->hasClient())
     600        gPlayer->showMiniPlayer();
     601}
  • mythmusic/musicplayer.cpp

     
     1// ANSI C includes
     2#include <cstdlib>
     3
     4// C++ includes
     5#include <iostream>
     6
     7using namespace std;
     8
     9// qt
     10#include <qapplication.h>
     11#include <qurl.h>
     12#include <qwidget.h>
     13
     14// mythtv
     15#include <mythtv/mythcontext.h>
     16#include <mythtv/audiooutput.h>
     17#include <mythtv/mythdbcon.h>
     18
     19// mythmusic
     20#include "musicplayer.h"
     21#include "decoder.h"
     22#include "cddecoder.h"
     23#include "constants.h"
     24#include "mainvisual.h"
     25#include "miniplayer.h"
     26
     27MusicPlayer  *gPlayer = NULL;
     28
     29////////////////////////////////////////////////////////////////
     30
     31MusicPlayer::MusicPlayer(QObject *parent, const QString &dev)
     32    :QObject(parent)
     33{
     34    m_CDdevice = dev;
     35    m_decoder = NULL;
     36    m_input = NULL;
     37    m_output = NULL;
     38
     39    m_playlistTree = NULL;
     40    m_currentNode = NULL;
     41    m_currentMetadata = NULL;
     42
     43    m_listener = NULL;
     44    m_visual = NULL;
     45
     46    m_isAutoplay = false;
     47
     48    QString playmode = gContext->GetSetting("PlayMode", "none");
     49    if (playmode.lower() == "random")
     50        setShuffleMode(SHUFFLE_RANDOM);
     51    else if (playmode.lower() == "intelligent")
     52        setShuffleMode(SHUFFLE_INTELLIGENT);
     53    else if (playmode.lower() == "album")
     54        setShuffleMode(SHUFFLE_ALBUM);
     55    else if (playmode.lower() == "artist")
     56        setShuffleMode(SHUFFLE_ARTIST);
     57    else
     58        setShuffleMode(SHUFFLE_OFF);
     59
     60    QString repeatmode = gContext->GetSetting("RepeatMode", "all");
     61    if (repeatmode.lower() == "track")
     62        setRepeatMode(REPEAT_TRACK);
     63    else if (repeatmode.lower() == "all")
     64        setRepeatMode(REPEAT_ALL);
     65    else
     66        setRepeatMode(REPEAT_OFF);
     67}
     68
     69MusicPlayer::~MusicPlayer()
     70{
     71//    setListener(NULL);
     72//    setVisual(NULL);
     73
     74    stop(true);
     75
     76    if (m_playlistTree)
     77        delete m_playlistTree;
     78
     79    if (m_currentMetadata)
     80        delete m_currentMetadata;
     81    m_currentMetadata = NULL;
     82}
     83
     84void MusicPlayer::setListener(QObject *listener)
     85{
     86    if (m_listener && m_output)
     87        m_output->removeListener(m_listener);
     88
     89    if (m_listener && m_decoder)
     90        m_decoder->removeListener(m_listener);
     91
     92    m_listener = listener;
     93
     94    if (m_listener && m_output)
     95        m_output->addListener(m_listener);
     96
     97    if (m_listener && m_decoder)
     98        m_decoder->addListener(m_listener);
     99
     100    (listener == NULL) ? m_isAutoplay = true :  m_isAutoplay = false;
     101}
     102
     103void MusicPlayer::setVisual(MainVisual *visual)
     104{
     105    if (m_visual && m_output)
     106    {
     107        m_output->removeListener(m_visual);
     108        m_output->removeVisual(m_visual);
     109    }
     110
     111    m_visual = visual;
     112
     113    if (m_visual && m_output)
     114    {
     115        m_output->addListener(m_visual);
     116        m_output->addVisual(m_visual);
     117    }
     118}
     119
     120void MusicPlayer::playFile(const Metadata &meta)
     121{
     122    playFile(meta.Filename());
     123}
     124
     125void MusicPlayer::playFile(const QString &filename)
     126{
     127    m_currentFile = filename;
     128    play();
     129}
     130
     131void MusicPlayer::stop(bool stopAll)
     132{
     133    stopDecoder();
     134
     135    if (m_output)
     136    {
     137        if (m_output->GetPause())
     138        {
     139            pause();
     140        }
     141        m_output->Reset();
     142    }
     143
     144    if (m_input)
     145        delete m_input;
     146    m_input = NULL;
     147
     148    m_isPlaying = false;
     149
     150    if (stopAll && m_decoder)
     151    {
     152        m_decoder->removeListener(this);
     153        if (m_listener)
     154            m_decoder->removeListener(m_listener);
     155
     156        delete m_decoder;
     157        m_decoder = NULL;
     158        m_listener = NULL;
     159    }
     160
     161    if (stopAll && m_output)
     162    {
     163        m_output->removeListener(this);
     164        if (m_listener)
     165            m_output->removeListener(m_listener);
     166
     167        if (m_visual)
     168        {
     169            m_output->removeListener(m_visual);
     170            m_output->removeVisual(m_visual);
     171        }
     172        delete m_output;
     173        m_output = NULL;
     174        m_visual = NULL;
     175    }
     176}
     177
     178void MusicPlayer::pause(void)
     179{
     180    if (m_output)
     181    {
     182        m_isPlaying = !m_isPlaying;
     183        m_output->Pause(!m_isPlaying);
     184    }
     185    // wake up threads
     186    if (m_decoder)
     187    {
     188        m_decoder->lock();
     189        m_decoder->cond()->wakeAll();
     190        m_decoder->unlock();
     191    }
     192}
     193
     194void MusicPlayer::play(void)
     195{
     196    stopDecoder();
     197
     198    if (!m_output)
     199        openOutputDevice();
     200
     201    if (m_input)
     202        delete m_input;
     203
     204    m_input = new QFile(m_currentFile);
     205
     206    if (m_decoder && !m_decoder->factory()->supports(m_currentFile))
     207    {
     208        m_decoder->removeListener(this);
     209
     210        if (m_listener)
     211            m_decoder->removeListener(m_listener);
     212
     213        delete m_decoder;
     214        m_decoder = NULL;
     215    }
     216
     217    if (!m_decoder)
     218    {
     219        m_decoder = Decoder::create(m_currentFile, m_input, m_output, true);
     220        if (!m_decoder)
     221        {
     222            VERBOSE(VB_IMPORTANT, "MusicPlayer: Failed to create decoder for playback");
     223            return;
     224        }
     225
     226        if (m_currentFile.contains("cda") == 1)
     227            dynamic_cast<CdDecoder*>(m_decoder)->setDevice(m_CDdevice);
     228
     229        m_decoder->setBlockSize(2 * 1024);
     230
     231        m_decoder->addListener(this);
     232
     233        if (m_listener)
     234            m_decoder->addListener(m_listener);
     235    }
     236    else
     237    {
     238        m_decoder->setInput(m_input);
     239        m_decoder->setFilename(m_currentFile);
     240        m_decoder->setOutput(m_output);
     241    }
     242
     243    if (m_decoder->initialize())
     244    {
     245        if (m_output)
     246            m_output->Reset();
     247
     248        m_decoder->start();
     249
     250        m_isPlaying = true;
     251
     252        if (m_currentNode)
     253        {
     254            if (m_currentNode->getInt() > 0)
     255            {
     256                m_currentMetadata = Metadata::getMetadataFromID(m_currentNode->getInt());
     257                if (m_currentMetadata)
     258                {
     259                    m_currentMetadata->incPlayCount();
     260                    m_currentMetadata->setLastPlay();
     261                }
     262            }
     263            else
     264            {
     265                // CD track
     266                CdDecoder *cddecoder = dynamic_cast<CdDecoder*>(m_decoder);
     267                if (m_decoder)
     268                    m_currentMetadata = cddecoder->getMetadata(-m_currentNode->getInt());
     269            }
     270        }
     271    }
     272}
     273
     274void MusicPlayer::stopDecoder(void)
     275{
     276    if (m_decoder && m_decoder->running())
     277    {
     278        m_decoder->lock();
     279        m_decoder->stop();
     280        m_decoder->unlock();
     281    }
     282
     283    if (m_decoder)
     284    {
     285        m_decoder->lock();
     286        m_decoder->cond()->wakeAll();
     287        m_decoder->unlock();
     288    }
     289
     290    if (m_decoder)
     291        m_decoder->wait();
     292
     293    if (m_currentMetadata)
     294    {
     295        if (m_currentMetadata->hasChanged())
     296            m_currentMetadata->persist();
     297        delete m_currentMetadata;
     298    }
     299    m_currentMetadata = NULL;
     300}
     301
     302void MusicPlayer::openOutputDevice(void)
     303{
     304    QString adevice;
     305
     306    if (gContext->GetSetting("MusicAudioDevice") == "default")
     307        adevice = gContext->GetSetting("AudioOutputDevice");
     308    else
     309        adevice = gContext->GetSetting("MusicAudioDevice");
     310
     311    // TODO: Error checking that device is opened correctly!
     312    m_output = AudioOutput::OpenAudio(adevice, "default", 16, 2, 44100,
     313                                    AUDIOOUTPUT_MUSIC, true, false);
     314    m_output->setBufferSize(256 * 1024);
     315    m_output->SetBlocking(false);
     316
     317    m_output->addListener(this);
     318
     319    if (m_listener)
     320        m_output->addListener(m_listener);
     321
     322    if (m_visual)
     323    {
     324        m_output->addListener((QObject*) m_visual);
     325        m_output->addVisual(m_visual);
     326    }
     327}
     328
     329void MusicPlayer::next(void)
     330{
     331    if (!m_currentNode)
     332        return;
     333
     334    GenericTree *node = m_currentNode->nextSibling(1, ((int) m_shuffleMode) + 1);
     335    if (node)
     336    {
     337        m_currentNode = node;
     338    }
     339    else
     340    {
     341        if (m_repeatMode == REPEAT_ALL)
     342        {
     343            // start playing again from first track
     344            GenericTree *parent = m_currentNode->getParent();
     345            if (parent)
     346            {
     347                node = parent->getChildAt(0, ((int) m_shuffleMode) + 1);
     348                if (node)
     349                    m_currentNode = node;
     350                else
     351                    return; // stop()
     352            }
     353        }
     354        else
     355            return; // stop()
     356    }
     357
     358    QString filename = getFilenameFromID(node->getInt());
     359    if (!filename.isEmpty())
     360        playFile(filename);
     361    else
     362        stop();
     363}
     364
     365void MusicPlayer::previous(void)
     366{
     367    if (!m_currentNode)
     368        return;
     369
     370    GenericTree *node = m_currentNode->prevSibling(1, ((int) m_shuffleMode) + 1);
     371    if (node)
     372    {
     373        m_currentNode = node;
     374        QString filename = getFilenameFromID(node->getInt());
     375        if (!filename.isEmpty())
     376            playFile(filename);
     377        else
     378            return;//stop();
     379    }
     380    else
     381    {
     382        // FIXME take repeat mode into account
     383        return; //stop();
     384    }
     385}
     386
     387void MusicPlayer::nextAuto(void)
     388{
     389    if (!m_isAutoplay)
     390        return;
     391
     392    if (!m_currentNode)
     393        return;
     394
     395    if (m_repeatMode == REPEAT_TRACK)
     396    {
     397        play();
     398        return;
     399    }
     400    else
     401        next();
     402
     403    MiniPlayer *popup = new MiniPlayer(gContext->GetMainWindow(), this);
     404    popup->showPlayer(10);
     405    popup->deleteLater();
     406    popup = NULL;
     407}
     408
     409void MusicPlayer::customEvent(QCustomEvent *event)
     410{
     411    if (m_isAutoplay)
     412    {
     413        switch ((int)event->type())
     414        {
     415            case OutputEvent::Error:
     416            {
     417                OutputEvent *aoe = (OutputEvent *) event;
     418
     419                VERBOSE(VB_IMPORTANT, QString("Output Error - %1")
     420                        .arg(*aoe->errorMessage()));
     421                MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     422                        "Output Error:",
     423                        QString("MythMusic has encountered the following error:\n%1")
     424                                .arg(*aoe->errorMessage()));
     425                stop(true);
     426
     427                break;
     428            }
     429
     430            case DecoderEvent::Finished:
     431            {
     432                nextAuto();
     433                break;
     434            }
     435
     436            case DecoderEvent::Error:
     437            {
     438                stop(true);
     439
     440                QApplication::sendPostedEvents();
     441
     442                DecoderEvent *dxe = (DecoderEvent *) event;
     443
     444                VERBOSE(VB_IMPORTANT, QString("Decoder Error - %1")
     445                        .arg(*dxe->errorMessage()));
     446                MythPopupBox::showOkPopup(gContext->GetMainWindow(),
     447                                        "Decoder Error",
     448                                        QString("MythMusic has encountered the following error:\n%1")
     449                                        .arg(*dxe->errorMessage()));
     450                break;
     451            }
     452        }
     453    }
     454
     455    QObject::customEvent(event);
     456}
     457
     458QString MusicPlayer::getFilenameFromID(int id)
     459{
     460    QString filename = "";
     461
     462    if (id > 0)
     463    {
     464        QString aquery = "SELECT CONCAT_WS('/', "
     465                        "music_directories.path, music_songs.filename) AS filename "
     466                        "FROM music_songs "
     467                        "LEFT JOIN music_directories ON music_songs.directory_id=music_directories.directory_id "
     468                        "WHERE music_songs.song_id = :ID";
     469
     470        MSqlQuery query(MSqlQuery::InitCon());
     471        query.prepare(aquery);
     472        query.bindValue(":ID", id);
     473        if (!query.exec() || query.numRowsAffected() < 1)
     474            MythContext::DBError("get filename", query);
     475
     476        if (query.isActive() && query.size() > 0)
     477        {
     478            query.first();
     479            filename = QString::fromUtf8(query.value(0).toString());
     480            if (!filename.contains("://"))
     481                filename = Metadata::GetStartdir() + filename;
     482        }
     483    }
     484    else
     485    {
     486        // cd track
     487        CdDecoder *cddecoder = dynamic_cast<CdDecoder*>(m_decoder);
     488        if (m_decoder)
     489        {
     490            Metadata *meta = cddecoder->getMetadata(-id);
     491            if (meta)
     492                filename = meta->Filename();
     493        }
     494    }
     495    return filename;
     496}
     497
     498QString MusicPlayer::getRouteToCurrent(void)
     499{
     500    QStringList route;
     501
     502    if (m_currentNode)
     503    {
     504        GenericTree *climber = m_currentNode;
     505
     506        route.push_front(QString::number(climber->getInt()));
     507        while((climber = climber->getParent()))
     508        {
     509            route.push_front(QString::number(climber->getInt()));
     510        }
     511    }
     512    return route.join(",");
     513}
     514
     515void MusicPlayer::showMiniPlayer(void)
     516{
     517    MiniPlayer *popup = new MiniPlayer(gContext->GetMainWindow(), this);
     518    popup->exec();
     519    popup->deleteLater();
     520    popup = NULL;
     521}
     522
     523Metadata *MusicPlayer::getCurrentMetadata(void)
     524{
     525    if (!m_currentNode)
     526        return NULL;
     527
     528    if (m_currentMetadata)
     529        return m_currentMetadata;
     530
     531    m_currentMetadata = Metadata::getMetadataFromID(m_currentNode->getInt());
     532
     533    return m_currentMetadata;
     534}
     535
     536MusicPlayer::RepeatMode MusicPlayer::toggleRepeatMode(void)
     537{
     538    switch (m_repeatMode)
     539    {
     540        case REPEAT_OFF:
     541            m_repeatMode = REPEAT_TRACK;
     542            break;
     543        case REPEAT_TRACK:
     544            m_repeatMode = REPEAT_ALL;
     545            break;
     546        case REPEAT_ALL:
     547            m_repeatMode = REPEAT_OFF;
     548           break;
     549        default:
     550            m_repeatMode = REPEAT_OFF;
     551            break;
     552    }
     553
     554    return m_repeatMode;
     555}
     556
     557MusicPlayer::ShuffleMode MusicPlayer::toggleShuffleMode(void)
     558{
     559    switch (m_shuffleMode)
     560    {
     561        case SHUFFLE_OFF:
     562            m_shuffleMode = SHUFFLE_RANDOM;
     563            break;
     564        case SHUFFLE_RANDOM:
     565            m_shuffleMode = SHUFFLE_INTELLIGENT;
     566            break;
     567        case SHUFFLE_INTELLIGENT:
     568            m_shuffleMode = SHUFFLE_ALBUM;
     569           break;
     570        case SHUFFLE_ALBUM:
     571            m_shuffleMode = SHUFFLE_ARTIST;
     572           break;
     573        case SHUFFLE_ARTIST:
     574            m_shuffleMode = SHUFFLE_OFF;
     575           break;
     576        default:
     577            m_shuffleMode = SHUFFLE_OFF;
     578            break;
     579    }
     580
     581    return m_shuffleMode;
     582}
  • mythmusic/playbackbox.h

     
    11#ifndef PLAYBACKBOX_H_
    22#define PLAYBACKBOX_H_
    33
     4// qt
    45#include <qtimer.h>
    56#include <qmutex.h>
    67#include <qvaluevector.h>
    78
     9// mythtv
    810#include <mythtv/mythwidgets.h>
    911#include <mythtv/dialogbox.h>
    1012#include <mythtv/audiooutput.h>
    1113
     14// mythmusic
    1215#include "mainvisual.h"
    1316#include "metadata.h"
    1417#include "playlist.h"
    1518#include "editmetadata.h"
    1619#include "databasebox.h"
     20#include "musicplayer.h"
    1721
    1822class Output;
    1923class Decoder;
     
    3337
    3438    ~PlaybackBoxMusic(void);
    3539
    36     void closeEvent(QCloseEvent *);
    3740    void customEvent(QCustomEvent *);
    38     void showEvent(QShowEvent *);
    3941    void keyPressEvent(QKeyEvent *e);
    4042    void constructPlaylistTree();
    4143
     
    4446  public slots:
    4547
    4648    void play();
    47     void pause();
    4849    void stop();
     50    void pause();
    4951    void stopDecoder();
    5052    void previous();
    5153    void next();
     
    5355    void seekback();
    5456    void seek(int);
    5557    void stopAll();
    56     void setShuffleMode(unsigned int mode);
     58    void setShuffleMode(MusicPlayer::ShuffleMode mode);
    5759    void toggleShuffle();
    5860    void increaseRating();
    5961    void decreaseRating();
    60     void setRepeatMode(unsigned int mode);
     62    void setRepeatMode(MusicPlayer::RepeatMode mode);
    6163    void toggleRepeat();
    6264    void editPlaylist();
    6365    void nextAuto();
     
    109111    void updatePlaylistFromCD(void);
    110112    void setTrackOnLCD(Metadata *mdata);
    111113    void updateTrackInfo(Metadata *mdata);
    112     void openOutputDevice(void);
    113114    void postUpdate();
    114115    void playFirstTrack();
    115116    void bannerEnable(QString text, int millis);
    116117    void bannerEnable(Metadata *mdata, bool fullScreen = false);
    117118    void bannerToggle(Metadata *mdata);
    118119    void savePosition(uint position);
    119     void restorePosition(void);
     120    void restorePosition(const QString &position);
    120121    void pushButton(UIPushButtonType *button);
    121122    QString getTimeString(int exTime, int maxTime);
    122123
    123     QIODevice *input;
    124     AudioOutput *output;
    125     Decoder *decoder;
    126 
    127124    QString playfile;
    128125    QString statusString;
    129126    QString curSmartPlaylistCategory;
    130127    QString curSmartPlaylistName;
    131128
    132     enum RepeatMode
    133     { REPEAT_OFF = 0,
    134       REPEAT_TRACK,
    135       REPEAT_ALL,
    136       MAX_REPEAT_MODES
    137     };
    138     enum ShuffleMode
    139     { SHUFFLE_OFF = 0,
    140       SHUFFLE_RANDOM,
    141       SHUFFLE_INTELLIGENT,
    142       SHUFFLE_ALBUM,
    143       SHUFFLE_ARTIST,
    144       MAX_SHUFFLE_MODES
    145     };
    146129    enum ResumeMode
    147130    { RESUME_OFF,
    148131      RESUME_TRACK,
     
    158141
    159142    Metadata *curMeta;
    160143
    161 
    162     unsigned int shufflemode;
    163     unsigned int repeatmode;
    164144    unsigned int resumemode;
    165145
    166     bool isplaying;
    167 
    168146    bool menufilters;
    169147
    170148    ReadCDThread *cd_reader_thread;
     
    195173    QTimer  *waiting_for_playlists_timer;
    196174    QTimer  *volume_display_timer;
    197175
    198     GenericTree *playlist_tree;
    199 
    200176    bool cycle_visualizer;
    201177    bool random_visualizer;
    202178    bool show_album_art;
  • mythmusic/mainvisual.cpp

     
    217217
    218218    VisualNode *node = 0;
    219219
    220     if (playing && output()) {
     220    if (playing && output())
     221    {
    221222        long synctime = output()->GetAudiotime();
    222223        mutex()->lock();
    223224        VisualNode *prev = 0;
    224         while ((node = nodes.first())) {
     225        while ((node = nodes.first()))
     226        {
    225227            if (node->offset > synctime)
    226228                break;
    227 
    228229            delete prev;
    229230            nodes.removeFirst();
    230231            prev = node;
    231232        }
    232233        mutex()->unlock();
    233         node = prev; 
     234        node = prev;
    234235    }
    235236
    236237    bool stop = TRUE;
     
    276277    switch (event->type())
    277278    {
    278279        case OutputEvent::Playing:
    279         playing = TRUE;
    280         // fall through intended
    281 
    282280        case OutputEvent::Info:
    283281        case OutputEvent::Buffering:
    284282        case OutputEvent::Paused:
     283            playing = TRUE;
     284
    285285            if (! timer->isActive())
    286286                timer->start(1000 / fps);
    287 
    288287            break;
    289288
    290289        case OutputEvent::Stopped:
  • mythmusic/miniplayer.h

     
     1#ifndef MINIPLAYER_H_
     2#define MINIPLAYER_H_
     3
     4#include <qstring.h>
     5
     6#include "mythtv/mythdialogs.h"
     7
     8class MusicPlayer;
     9class QTimer;
     10class Metadata;
     11
     12/// Preferred position to place popup miniplayer.
     13enum PlayerPosition
     14{
     15    MP_POSTOPDIALOG,
     16    MP_POSBOTTOMDIALOG,
     17    MP_POSCENTERDIALOG
     18};
     19
     20class MPUBLIC MiniPlayer : public MythThemedDialog
     21{
     22  Q_OBJECT
     23
     24  public:
     25    MiniPlayer(MythMainWindow *parent,
     26                    MusicPlayer *parentPlayer,
     27                    const char *name = 0,
     28                    bool setsize = true);
     29    ~MiniPlayer();
     30
     31  public slots:
     32    virtual void show();
     33    virtual void hide();
     34    void timerTimeout(void);
     35    void showPlayer(int showTime);
     36    void showInfoTimeout(void);
     37
     38  protected:
     39    virtual void keyPressEvent(QKeyEvent *e);
     40    virtual void customEvent(QCustomEvent *event);
     41
     42  private:
     43    void    wireupTheme(void);
     44    QString getTimeString(int exTime, int maxTime);
     45    void    updateTrackInfo(Metadata *mdata);
     46    void    seekforward(void);
     47    void    seekback(void);
     48    void    seek(int pos);
     49    void    increaseRating(void);
     50    void    decreaseRating(void);
     51    void    showShuffleMode(void);
     52    void    showRepeatMode(void);
     53    void    showVolume(void);
     54
     55    int           m_currTime, m_maxTime;
     56
     57    MusicPlayer  *m_parentPlayer;
     58    int           m_popupWidth;
     59    int           m_popupHeight;
     60
     61    QTimer       *m_displayTimer;
     62    QTimer       *m_infoTimer;
     63
     64    bool          m_showingInfo;
     65
     66    UITextType   *m_titleText;
     67    UITextType   *m_artistText;
     68    UITextType   *m_albumText;
     69    UITextType   *m_timeText;
     70    UITextType   *m_infoText;
     71    UIImageType  *m_coverImage;
     72
     73    UITextType   *m_shufflestateText;
     74    UITextType   *m_repeatstateText;
     75
     76    UIRepeatedImageType *m_ratingsImage;
     77};
     78
     79#endif