Ticket #4222: 4222-v3.patch
File 4222-v3.patch, 75.1 KB (added by , 16 years ago) |
---|
-
mythmusic/playbackbox.cpp
27 27 #include "mainvisual.h" 28 28 #include "smartplaylist.h" 29 29 #include "search.h" 30 #include "musicplayer.h" 30 31 31 32 PlaybackBoxMusic::PlaybackBoxMusic(MythMainWindow *parent, QString window_name, 32 33 QString theme_filename, … … 37 38 : MythThemedDialog(parent, window_name, theme_filename, name) 38 39 { 39 40 // A few internal variable defaults 40 41 input = NULL;42 output = NULL;43 decoder = NULL;44 41 mainvisual = NULL; 45 42 visual_mode_timer = NULL; 46 43 lcd_update_timer = NULL; 47 44 waiting_for_playlists_timer = NULL; 48 45 speed_scroll_timer = NULL; 49 playlist_tree = NULL;50 46 playlist_popup = NULL; 51 47 progress = NULL; 52 48 53 isplaying = false; 49 gPlayer->setListener(this); 50 54 51 tree_is_done = false; 55 52 first_playlist_check = true; 56 53 outputBufferSize = 256; … … 112 109 this, SLOT(hideVolume())); 113 110 } 114 111 115 // Figure out the shuffle mode112 setShuffleMode(gPlayer->getShuffleMode()); 116 113 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 else127 setShuffleMode(SHUFFLE_OFF);128 129 114 QString resumestring = gContext->GetSetting("ResumeMode", "off"); 130 115 if (resumestring.lower() == "off") 131 116 resumemode = RESUME_OFF; … … 134 119 else 135 120 resumemode = RESUME_EXACT; 136 121 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()); 144 123 145 124 // Set some button values 146 125 … … 170 149 // Set please wait on the LCD 171 150 QPtrList<LCDTextItem> textItems; 172 151 textItems.setAutoDelete(true); 173 152 174 153 textItems.append(new LCDTextItem(1, ALIGN_CENTERED, "Please Wait", 175 154 "Generic")); 176 155 lcd->switchToGeneric(&textItems); … … 196 175 mainvisual->setGeometry(screenwidth + 10, screenheight + 10, 160, 160); 197 176 mainvisual->show(); 198 177 178 gPlayer->setVisual(mainvisual); 179 199 180 fullscreen_blank = false; 200 181 201 182 visual_modes = QStringList::split(';', gContext->GetSetting("VisualMode")); … … 240 221 { 241 222 savePosition(currentTime); 242 223 243 stopAll();244 245 if (output)246 {247 delete output;248 output = NULL;249 }250 251 224 if (progress) 252 225 { 253 226 progress->Close(); … … 262 235 delete cd_reader_thread; 263 236 } 264 237 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) 269 240 gContext->SaveSetting("PlayMode", "intelligent"); 270 else if (shufflemode == SHUFFLE_RANDOM)241 else if (shufflemode == MusicPlayer::SHUFFLE_RANDOM) 271 242 gContext->SaveSetting("PlayMode", "random"); 272 else if (shufflemode == SHUFFLE_ALBUM)243 else if (shufflemode == MusicPlayer::SHUFFLE_ALBUM) 273 244 gContext->SaveSetting("PlayMode", "album"); 274 else if (shufflemode == SHUFFLE_ARTIST)245 else if (shufflemode == MusicPlayer::SHUFFLE_ARTIST) 275 246 gContext->SaveSetting("PlayMode", "artist"); 276 247 else 277 248 gContext->SaveSetting("PlayMode", "none"); 278 249 279 if (repeatmode == REPEAT_TRACK) 250 MusicPlayer::RepeatMode repeatmode = gPlayer->getRepeatMode(); 251 if (repeatmode == MusicPlayer::REPEAT_TRACK) 280 252 gContext->SaveSetting("RepeatMode", "track"); 281 else if (repeatmode == REPEAT_ALL)253 else if (repeatmode == MusicPlayer::REPEAT_ALL) 282 254 gContext->SaveSetting("RepeatMode", "all"); 283 255 else 284 256 gContext->SaveSetting("RepeatMode", "none"); 257 285 258 if (class LCD *lcd = LCD::Get()) 286 259 lcd->switchToTime(); 287 260 } … … 304 277 resetTimer(); 305 278 306 279 QStringList actions; 307 gContext->GetMainWindow()->TranslateKeyPress("Music", e, actions );280 gContext->GetMainWindow()->TranslateKeyPress("Music", e, actions, false); 308 281 309 282 int scrollAmt = 1; 310 283 … … 343 316 } 344 317 else if (action == "PAUSE") 345 318 { 346 if ( isplaying)319 if (gPlayer->isPlaying()) 347 320 { 348 321 if (pause_button) 349 322 pause_button->push(); … … 371 344 stop_button->push(); 372 345 else 373 346 stop(); 374 375 347 currentTime = 0; 376 348 } 377 349 else if (action == "THMBUP") … … 427 399 bannerToggle(curMeta); 428 400 else 429 401 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 } 430 427 else 431 428 handled = false; 432 429 } … … 541 538 music_tree_list->incSearchStart(); 542 539 else if (action == "INCSEARCHNEXT") 543 540 music_tree_list->incSearchNext(); 544 else545 handled = false;546 541 } 547 542 } 548 543 else … … 565 560 handled = false; 566 561 } 567 562 } 568 569 if (!handled)570 MythThemedDialog::keyPressEvent(e);571 563 } 572 564 573 565 void PlaybackBoxMusic::handlePush(QString buttonname) … … 949 941 if (cd_reader_thread->getLock()->locked()) 950 942 return; 951 943 952 if (!scan_for_cd) { 944 if (!scan_for_cd) 945 { 953 946 cd_watcher->stop(); 954 947 delete cd_watcher; 955 948 cd_watcher = NULL; … … 1062 1055 GenericTree *node = music_tree_list->getCurrentNode(); 1063 1056 curMeta = all_music->getMetadata(node->getInt()); 1064 1057 1065 setShuffleMode( shufflemode);1058 setShuffleMode(gPlayer->getShuffleMode()); 1066 1059 1067 1060 music_tree_list->refresh(); 1068 1061 … … 1104 1097 branches_to_current_node.append(1); // We're on a playlist (not "My Music") 1105 1098 branches_to_current_node.append(0); // Active play Queue 1106 1099 1107 if (resumemode > RESUME_OFF) 1108 restorePosition(); 1100 if (gPlayer->isPlaying()) 1101 { 1102 restorePosition(gPlayer->getRouteToCurrent()); 1103 } 1109 1104 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 } 1111 1111 1112 1112 music_tree_list->refresh(); 1113 1113 if (show_whole_tree) … … 1162 1162 1163 1163 void PlaybackBoxMusic::changeVolume(bool up_or_down) 1164 1164 { 1165 if (volume_control && output)1165 if (volume_control && gPlayer->getOutput()) 1166 1166 { 1167 1167 if (up_or_down) 1168 output->AdjustCurrentVolume(2);1168 gPlayer->getOutput()->AdjustCurrentVolume(2); 1169 1169 else 1170 output->AdjustCurrentVolume(-2);1170 gPlayer->getOutput()->AdjustCurrentVolume(-2); 1171 1171 showVolume(true); 1172 1172 } 1173 1173 } 1174 1174 1175 1175 void PlaybackBoxMusic::toggleMute() 1176 1176 { 1177 if (volume_control && output)1177 if (volume_control && gPlayer->getOutput()) 1178 1178 { 1179 output->ToggleMute();1179 gPlayer->getOutput()->ToggleMute(); 1180 1180 showVolume(true); 1181 1181 } 1182 1182 } … … 1184 1184 void PlaybackBoxMusic::showProgressBar() 1185 1185 { 1186 1186 1187 if (progress_bar) {1188 1187 if (progress_bar) 1188 { 1189 1189 progress_bar->SetTotal(maxTime); 1190 1190 progress_bar->SetUsed(currentTime); 1191 1191 } … … 1194 1194 void PlaybackBoxMusic::showVolume(bool on_or_off) 1195 1195 { 1196 1196 float volume_level; 1197 if (volume_control && output)1197 if (volume_control && gPlayer->getOutput()) 1198 1198 { 1199 1199 if (volume_status) 1200 1200 { 1201 1201 if (on_or_off) 1202 1202 { 1203 volume_status->SetUsed( output->GetCurrentVolume());1203 volume_status->SetUsed(gPlayer->getOutput()->GetCurrentVolume()); 1204 1204 volume_status->SetOrder(0); 1205 1205 volume_status->refresh(); 1206 1206 volume_display_timer->changeInterval(2000); 1207 1207 if (class LCD *lcd = LCD::Get()) 1208 1208 lcd->switchToVolume("Music"); 1209 1209 1210 if ( output->GetMute())1210 if (gPlayer->getOutput()->GetMute()) 1211 1211 volume_level = 0.0; 1212 1212 else 1213 volume_level = (float) output->GetCurrentVolume() /1213 volume_level = (float)gPlayer->getOutput()->GetCurrentVolume() / 1214 1214 (float)100; 1215 1215 1216 1216 if (class LCD *lcd = LCD::Get()) … … 1239 1239 1240 1240 void PlaybackBoxMusic::play() 1241 1241 { 1242 if (gPlayer->isPlaying()) 1243 gPlayer->stop(); 1242 1244 1243 if (isplaying)1244 stop();1245 1246 1245 if (curMeta) 1247 1246 playfile = curMeta->Filename(); 1248 1247 else … … 1252 1251 return; 1253 1252 } 1254 1253 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()) 1262 1255 { 1263 pause();1256 gPlayer->pause(); 1264 1257 return; 1265 1258 } 1266 1259 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); 1281 1262 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 else1299 {1300 decoder->setInput(input);1301 decoder->setFilename(sourcename);1302 decoder->setOutput(output);1303 }1304 1305 1263 currentTime = 0; 1306 1264 1307 mainvisual->setDecoder( decoder);1308 mainvisual->setOutput( output);1265 mainvisual->setDecoder(gPlayer->getDecoder()); 1266 mainvisual->setOutput(gPlayer->getOutput()); 1309 1267 mainvisual->setMetadata(curMeta); 1310 1268 1311 if ( decoder->initialize())1269 if (!gPlayer->isPlaying()) 1312 1270 { 1313 if (output) 1271 if (resumemode == RESUME_EXACT && 1272 gContext->GetNumSetting("MusicBookmarkPosition", 0) > 0) 1314 1273 { 1315 output->Reset();1316 }1317 1318 decoder->start();1319 1320 if (resumemode == RESUME_EXACT && gContext->GetNumSetting("MusicBookmarkPosition", 0) > 0)1321 {1322 1274 seek(gContext->GetNumSetting("MusicBookmarkPosition", 0)); 1323 1275 gContext->SaveSetting("MusicBookmarkPosition", 0); 1324 1276 } 1325 1326 bannerEnable(curMeta, show_album_art);1327 isplaying = true;1328 curMeta->setLastPlay();1329 curMeta->incPlayCount();1330 1277 } 1278 1279 bannerEnable(curMeta, show_album_art); 1331 1280 } 1332 1281 1333 1282 void PlaybackBoxMusic::visEnable() 1334 1283 { 1335 if (!visualizer_status != 2 && isplaying)1284 if (!visualizer_status != 2 && gPlayer->isPlaying()) 1336 1285 { 1337 1286 setUpdatesEnabled(false); 1338 1287 mainvisual->setGeometry(0, 0, screenwidth, screenheight); … … 1410 1359 void PlaybackBoxMusic::setTrackOnLCD(Metadata *mdata) 1411 1360 { 1412 1361 LCD *lcd = LCD::Get(); 1413 if (!lcd )1362 if (!lcd || !mdata) 1414 1363 return; 1415 1364 1416 1365 // Set the Artist and Tract on the LCD … … 1421 1370 1422 1371 void PlaybackBoxMusic::pause(void) 1423 1372 { 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(); 1437 1374 } 1438 1375 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 1455 1376 void PlaybackBoxMusic::stop(void) 1456 1377 { 1457 stopDecoder();1378 gPlayer->stop(); 1458 1379 1459 if (output)1460 {1461 if (output->GetPause())1462 {1463 pause();1464 }1465 output->Reset();1466 }1467 1468 1380 mainvisual->setDecoder(0); 1469 1381 mainvisual->setOutput(0); 1470 1382 mainvisual->deleteMetadata(); 1471 1383 1472 delete input;1473 input = 0;1474 1475 1384 QString time_string = getTimeString(maxTime, 0); 1476 1385 1477 1386 if (time_text) 1478 1387 time_text->SetText(time_string); 1479 1388 if (info_text) 1480 1389 info_text->SetText(""); 1481 1482 isplaying = false;1483 1390 } 1484 1391 1485 1392 void PlaybackBoxMusic::stopAll() … … 1489 1396 lcd->switchToTime(); 1490 1397 } 1491 1398 1492 stop(); 1399 mainvisual->setDecoder(0); 1400 mainvisual->setOutput(0); 1401 mainvisual->deleteMetadata(); 1493 1402 1494 if (decoder) 1495 { 1496 decoder->removeListener(this); 1497 decoder = 0; 1498 } 1403 gPlayer->stop(true); 1499 1404 } 1500 1405 1501 1406 void PlaybackBoxMusic::previous() 1502 1407 { 1503 if ( repeatmode ==REPEAT_ALL)1408 if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_ALL) 1504 1409 { 1505 1410 if (music_tree_list->prevActive(true, show_whole_tree)) 1506 1411 music_tree_list->activate(); … … 1517 1422 1518 1423 void PlaybackBoxMusic::next() 1519 1424 { 1520 if ( repeatmode ==REPEAT_ALL)1425 if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_ALL) 1521 1426 { 1522 1427 // Grab the next track after this one. First flag is to wrap around 1523 1428 // to the beginning of the list. Second decides if we will traverse up … … 1541 1446 1542 1447 void PlaybackBoxMusic::nextAuto() 1543 1448 { 1544 stopDecoder(); 1545 1546 isplaying = false; 1547 1548 if (repeatmode == REPEAT_TRACK) 1449 if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_TRACK) 1549 1450 play(); 1550 1451 else 1551 1452 next(); … … 1569 1470 1570 1471 void PlaybackBoxMusic::seek(int pos) 1571 1472 { 1572 if ( output)1473 if (gPlayer->getOutput()) 1573 1474 { 1574 output->Reset();1575 output->SetTimecode(pos*1000);1475 gPlayer->getOutput()->Reset(); 1476 gPlayer->getOutput()->SetTimecode(pos*1000); 1576 1477 1577 if ( decoder && decoder->running())1478 if (gPlayer->getDecoder() && gPlayer->getDecoder()->running()) 1578 1479 { 1579 decoder->lock();1580 decoder->seek(pos);1480 gPlayer->getDecoder()->lock(); 1481 gPlayer->getDecoder()->seek(pos); 1581 1482 1582 1483 if (mainvisual) 1583 1484 { … … 1586 1487 mainvisual->mutex()->unlock(); 1587 1488 } 1588 1489 1589 decoder->unlock();1490 gPlayer->getDecoder()->unlock(); 1590 1491 } 1591 1492 1592 if (! isplaying)1493 if (!gPlayer->isPlaying()) 1593 1494 { 1594 1495 currentTime = pos; 1595 1496 if (time_text) … … 1614 1515 } 1615 1516 } 1616 1517 1617 void PlaybackBoxMusic::setShuffleMode( unsigned intmode)1518 void PlaybackBoxMusic::setShuffleMode(MusicPlayer::ShuffleMode mode) 1618 1519 { 1619 shufflemode = mode;1520 MusicPlayer::ShuffleMode shufflemode = mode; 1620 1521 QString state; 1621 1522 1622 1523 switch (shufflemode) 1623 1524 { 1624 case SHUFFLE_INTELLIGENT:1525 case MusicPlayer::SHUFFLE_INTELLIGENT: 1625 1526 state = tr("Smart"); 1626 1527 if (class LCD *lcd = LCD::Get()) 1627 1528 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_SMART); 1628 1529 break; 1629 case SHUFFLE_RANDOM:1530 case MusicPlayer::SHUFFLE_RANDOM: 1630 1531 state = tr("Rand"); 1631 1532 if (class LCD *lcd = LCD::Get()) 1632 1533 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_RAND); 1633 1534 break; 1634 case SHUFFLE_ALBUM:1535 case MusicPlayer::SHUFFLE_ALBUM: 1635 1536 state = tr("Album"); 1636 1537 if (class LCD *lcd = LCD::Get()) 1637 1538 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ALBUM); 1638 1539 break; 1639 case SHUFFLE_ARTIST:1540 case MusicPlayer::SHUFFLE_ARTIST: 1640 1541 state = tr("Artist"); 1641 1542 if (class LCD *lcd = LCD::Get()) 1642 1543 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ARTIST); … … 1663 1564 1664 1565 bannerEnable(QString("%1: %2").arg(tr("Shuffle")).arg(state), 4000); 1665 1566 1666 if (!shufflemode == SHUFFLE_OFF)1567 if (!shufflemode == MusicPlayer::SHUFFLE_OFF) 1667 1568 music_tree_list->scrambleParents(true); 1668 1569 else 1669 1570 music_tree_list->scrambleParents(true); … … 1675 1576 music_tree_list->setVisualOrdering(1); 1676 1577 music_tree_list->refresh(); 1677 1578 1678 if ( isplaying)1579 if (gPlayer->isPlaying()) 1679 1580 setTrackOnLCD(curMeta); 1680 1581 } 1681 1582 1682 1583 void PlaybackBoxMusic::toggleShuffle(void) 1683 1584 { 1684 setShuffleMode( ++shufflemode % MAX_SHUFFLE_MODES);1585 setShuffleMode(gPlayer->toggleShuffleMode()); 1685 1586 } 1686 1587 1687 1588 void PlaybackBoxMusic::increaseRating() … … 1713 1614 } 1714 1615 } 1715 1616 1716 void PlaybackBoxMusic::setRepeatMode( unsigned intmode)1617 void PlaybackBoxMusic::setRepeatMode(MusicPlayer::RepeatMode mode) 1717 1618 { 1718 repeatmode = mode;1619 MusicPlayer::RepeatMode repeatmode = mode; 1719 1620 QString state; 1720 1621 1721 1622 switch (repeatmode) 1722 1623 { 1723 case REPEAT_ALL:1624 case MusicPlayer::REPEAT_ALL: 1724 1625 state = tr("All"); 1725 1626 if (class LCD *lcd = LCD::Get()) 1726 1627 lcd->setMusicRepeat (LCD::MUSIC_REPEAT_ALL); 1727 1628 break; 1728 case REPEAT_TRACK:1629 case MusicPlayer::REPEAT_TRACK: 1729 1630 state = tr("Track"); 1730 1631 if (class LCD *lcd = LCD::Get()) 1731 1632 lcd->setMusicRepeat (LCD::MUSIC_REPEAT_TRACK); … … 1787 1688 gContext->SaveSetting("MusicBookmarkPosition", position); 1788 1689 } 1789 1690 1790 void PlaybackBoxMusic::restorePosition( )1691 void PlaybackBoxMusic::restorePosition(const QString &position) 1791 1692 { 1792 1693 QValueList <int> branches_to_current_node; 1793 QString s = gContext->GetSetting("MusicBookmark", "");1794 1694 1795 if ( s!= "")1695 if (position != "") 1796 1696 { 1797 QStringList list = QStringList::split(",", s);1697 QStringList list = QStringList::split(",", position); 1798 1698 1799 1699 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) 1800 1700 branches_to_current_node.append((*it).toInt()); … … 1810 1710 { 1811 1711 if (music_tree_list->tryToSetActive(branches_to_current_node)) 1812 1712 { 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(); 1814 1739 return; 1815 1740 } 1816 1741 } … … 1820 1745 //we're in show all tree mode - try to restore the position 1821 1746 if (music_tree_list->tryToSetActive(branches_to_current_node)) 1822 1747 { 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 1824 1775 return; 1825 1776 } 1826 1777 } … … 1835 1786 1836 1787 void PlaybackBoxMusic::toggleRepeat() 1837 1788 { 1838 setRepeatMode( ++repeatmode % MAX_REPEAT_MODES);1789 setRepeatMode(gPlayer->toggleRepeatMode()); 1839 1790 } 1840 1791 1841 1792 void PlaybackBoxMusic::constructPlaylistTree() 1842 1793 { 1794 GenericTree *playlist_tree = gPlayer->getPlaylistTree(); 1795 1843 1796 if (playlist_tree) 1844 1797 delete playlist_tree; 1845 1798 … … 1919 1872 cd_watcher->start(1000); 1920 1873 } 1921 1874 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 1935 1875 void PlaybackBoxMusic::customEvent(QCustomEvent *event) 1936 1876 { 1937 1877 switch ((int)event->type()) … … 2061 2001 break; 2062 2002 } 2063 2003 } 2004 //cout << "status string: " << statusString << endl; 2064 2005 2065 2006 QWidget::customEvent(event); 2066 2007 } … … 2095 2036 setTrackOnLCD(mdata); 2096 2037 } 2097 2038 2098 void PlaybackBoxMusic::openOutputDevice(void)2099 {2100 QString adevice;2101 2102 if (gContext->GetSetting("MusicAudioDevice") == "default")2103 adevice = gContext->GetSetting("AudioOutputDevice");2104 else2105 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 2118 2039 void PlaybackBoxMusic::handleTreeListSignals(int node_int, IntVector *attributes) 2119 2040 { 2120 2041 if (attributes->size() < 4) … … 2146 2067 } 2147 2068 } 2148 2069 2070 GenericTree *node = music_tree_list->getCurrentNode(); 2071 if (node && node->childCount() > 0) 2072 return; 2073 2149 2074 if (attributes->at(0) == 1) 2150 2075 { 2151 2076 // It's a track … … 2164 2089 ratings_image->setRepeat(curMeta->Rating()); 2165 2090 } 2166 2091 2167 if (output && output->GetPause()) 2168 stop(); 2169 2092 if (gPlayer->getOutput() && gPlayer->getOutput()->GetPause()) 2093 { 2094 gPlayer->stop(); 2095 } 2170 2096 if (m_pushedButton && m_pushedButton->Name() == "play_button") 2171 2097 { 2172 2098 // Play button already pushed, so don't push it again. … … 2349 2275 2350 2276 // only give the user a choice of the track to play if shuffle mode is off 2351 2277 MythComboBox *playCombo = NULL; 2352 if ( shufflemode ==SHUFFLE_OFF)2278 if (gPlayer->getShuffleMode() == MusicPlayer::SHUFFLE_OFF) 2353 2279 { 2354 2280 playCombo = new MythComboBox(false, popup, "play_combo" ); 2355 2281 playCombo->insertItem(tr("Continue playing current track")); … … 2358 2284 playCombo->setBackgroundOrigin(ParentOrigin); 2359 2285 popup->addWidget(playCombo); 2360 2286 } 2361 2287 2362 2288 MythCheckBox *dupsCheck = new MythCheckBox(popup); 2363 2289 dupsCheck->setText(tr("Remove Duplicates")); 2364 2290 dupsCheck->setChecked(false); … … 2388 2314 2389 2315 // if shuffle mode != SHUFFLE_OFF we always try to continue playing 2390 2316 // the current track 2391 if ( shufflemode ==SHUFFLE_OFF)2317 if (gPlayer->getShuffleMode() == MusicPlayer::SHUFFLE_OFF) 2392 2318 { 2393 2319 switch (playCombo->currentItem()) 2394 2320 { -
mythmusic/mythmusic.pro
39 39 HEADERS += goom/mmx.h goom/mathtools.h goom/tentacle3d.h goom/v3d.h 40 40 HEADERS += editmetadata.h smartplaylist.h search.h genres.h 41 41 HEADERS += treebuilders.h importmusic.h directoryfinder.h 42 HEADERS += filescanner.h libvisualplugin.h 42 HEADERS += filescanner.h libvisualplugin.h musicplayer.h miniplayer.h 43 43 44 44 SOURCES += cddecoder.cpp cdrip.cpp decoder.cpp 45 45 SOURCES += flacdecoder.cpp flacencoder.cpp maddecoder.cpp main.cpp … … 55 55 SOURCES += goom/zoom_filter_mmx.c goom/zoom_filter_xmmx.c goom/mythgoom.cpp 56 56 SOURCES += avfdecoder.cpp editmetadata.cpp smartplaylist.cpp search.cpp 57 57 SOURCES += treebuilders.cpp importmusic.cpp directoryfinder.cpp 58 SOURCES += filescanner.cpp libvisualplugin.cpp 58 SOURCES += filescanner.cpp libvisualplugin.cpp musicplayer.cpp miniplayer.cpp 59 59 60 60 macx { 61 61 SOURCES -= cddecoder.cpp … … 67 67 #QMAKE_LFLAGS += -flat_namespace -undefined suppress 68 68 QMAKE_LFLAGS += -flat_namespace -undefined error 69 69 } 70 -
mythmusic/music-ui.xml
1792 1792 </container> 1793 1793 </window> 1794 1794 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 1795 1871 </mythuitheme> -
mythmusic/miniplayer.cpp
1 #include <iostream> 2 using 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 20 MiniPlayer::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 49 MiniPlayer::~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 63 void MiniPlayer::showPlayer(int showTime) 64 { 65 m_displayTimer->start(showTime * 1000, true); 66 exec(); 67 } 68 69 void MiniPlayer::timerTimeout(void) 70 { 71 done(Accepted); 72 } 73 74 void 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 136 void MiniPlayer::show() 137 { 138 grabKeyboard(); 139 140 MythDialog::show(); 141 } 142 143 void MiniPlayer::hide() 144 { 145 releaseKeyboard(); 146 147 MythDialog::hide(); 148 } 149 150 void 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 263 void 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 360 QString 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 392 void 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 422 void MiniPlayer::seekforward(void) 423 { 424 int nextTime = m_currTime + 5; 425 if (nextTime > m_maxTime) 426 nextTime = m_maxTime; 427 seek(nextTime); 428 } 429 430 void MiniPlayer::seekback(void) 431 { 432 int nextTime = m_currTime - 5; 433 if (nextTime < 0) 434 nextTime = 0; 435 seek(nextTime); 436 } 437 438 void 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 477 void 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 491 void 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 505 void 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 520 void 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 561 void 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 592 void 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
725 725 return image; 726 726 } 727 727 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 730 Metadata *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 728 802 MetadataLoadingThread::MetadataLoadingThread(AllMusic *parent_ptr) 729 803 { 730 804 parent = parent_ptr; -
mythmusic/metadata.h
183 183 static QString GetStartdir() { return m_startdir; } 184 184 185 185 static QStringList fillFieldList(QString field); 186 static Metadata *getMetadataFromID(int id); 186 187 187 188 QImage getAlbumArt(ImageType type); 188 189 -
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 11 class Decoder; 12 class AudioOutput; 13 class MainVisual; 14 15 class 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 114 extern MPUBLIC MusicPlayer *gPlayer; 115 116 #endif -
mythmusic/main.cpp
29 29 #include "dbcheck.h" 30 30 #include "importmusic.h" 31 31 #include "filescanner.h" 32 #include "musicplayer.h" 32 33 #include "config.h" 33 34 34 35 // System header (relies on config.h define) … … 151 152 pbb->exec(); 152 153 qApp->lock(); 153 154 154 pbb->stop();155 156 155 qApp->processEvents(); 157 156 158 157 delete pbb; … … 313 312 void runMusicSelection(void); 314 313 void runRipCD(void); 315 314 void runScan(void); 315 void showMiniPlayer(void); 316 316 317 318 317 void handleMedia(MythMediaDevice *cd) 319 318 { 320 319 // Note that we should deal with other disks that may contain music. … … 365 364 REG_JUMP("Select music playlists", "", "", runMusicSelection); 366 365 REG_JUMP("Rip CD", "", "", runRipCD); 367 366 REG_JUMP("Scan music", "", "", runScan); 367 REG_JUMPEX("Show Miniplayer", "", "", showMiniPlayer, false); 368 368 369 369 REG_KEY("Music", "DELETE", "Delete track from playlist", "D"); 370 370 REG_KEY("Music", "NEXTTRACK", "Move to the next track", ">,.,Z,End"); … … 423 423 424 424 Decoder::SetLocationFormatUseTags(); 425 425 426 gPlayer = new MusicPlayer(NULL, chooseCD()); 427 426 428 return 0; 427 429 } 428 430 … … 530 532 return 0; 531 533 } 532 534 535 void mythplugin_destroy(void) 536 { 537 delete gPlayer; 538 } 539 533 540 void runMusicPlayback(void) 534 541 { 535 542 MusicData mdata; … … 585 592 586 593 postMusic(&mdata); 587 594 } 595 596 void 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 7 using 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 27 MusicPlayer *gPlayer = NULL; 28 29 //////////////////////////////////////////////////////////////// 30 31 MusicPlayer::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 69 MusicPlayer::~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 84 void 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 103 void 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 120 void MusicPlayer::playFile(const Metadata &meta) 121 { 122 playFile(meta.Filename()); 123 } 124 125 void MusicPlayer::playFile(const QString &filename) 126 { 127 m_currentFile = filename; 128 play(); 129 } 130 131 void 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 178 void 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 194 void 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 274 void 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 302 void 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 329 void 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 365 void 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 387 void 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 409 void 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 458 QString 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 498 QString 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 515 void MusicPlayer::showMiniPlayer(void) 516 { 517 MiniPlayer *popup = new MiniPlayer(gContext->GetMainWindow(), this); 518 popup->exec(); 519 popup->deleteLater(); 520 popup = NULL; 521 } 522 523 Metadata *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 536 MusicPlayer::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 557 MusicPlayer::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
1 1 #ifndef PLAYBACKBOX_H_ 2 2 #define PLAYBACKBOX_H_ 3 3 4 // qt 4 5 #include <qtimer.h> 5 6 #include <qmutex.h> 6 7 #include <qvaluevector.h> 7 8 9 // mythtv 8 10 #include <mythtv/mythwidgets.h> 9 11 #include <mythtv/dialogbox.h> 10 12 #include <mythtv/audiooutput.h> 11 13 14 // mythmusic 12 15 #include "mainvisual.h" 13 16 #include "metadata.h" 14 17 #include "playlist.h" 15 18 #include "editmetadata.h" 16 19 #include "databasebox.h" 20 #include "musicplayer.h" 17 21 18 22 class Output; 19 23 class Decoder; … … 33 37 34 38 ~PlaybackBoxMusic(void); 35 39 36 void closeEvent(QCloseEvent *);37 40 void customEvent(QCustomEvent *); 38 void showEvent(QShowEvent *);39 41 void keyPressEvent(QKeyEvent *e); 40 42 void constructPlaylistTree(); 41 43 … … 44 46 public slots: 45 47 46 48 void play(); 47 void pause();48 49 void stop(); 50 void pause(); 49 51 void stopDecoder(); 50 52 void previous(); 51 53 void next(); … … 53 55 void seekback(); 54 56 void seek(int); 55 57 void stopAll(); 56 void setShuffleMode( unsigned intmode);58 void setShuffleMode(MusicPlayer::ShuffleMode mode); 57 59 void toggleShuffle(); 58 60 void increaseRating(); 59 61 void decreaseRating(); 60 void setRepeatMode( unsigned intmode);62 void setRepeatMode(MusicPlayer::RepeatMode mode); 61 63 void toggleRepeat(); 62 64 void editPlaylist(); 63 65 void nextAuto(); … … 109 111 void updatePlaylistFromCD(void); 110 112 void setTrackOnLCD(Metadata *mdata); 111 113 void updateTrackInfo(Metadata *mdata); 112 void openOutputDevice(void);113 114 void postUpdate(); 114 115 void playFirstTrack(); 115 116 void bannerEnable(QString text, int millis); 116 117 void bannerEnable(Metadata *mdata, bool fullScreen = false); 117 118 void bannerToggle(Metadata *mdata); 118 119 void savePosition(uint position); 119 void restorePosition( void);120 void restorePosition(const QString &position); 120 121 void pushButton(UIPushButtonType *button); 121 122 QString getTimeString(int exTime, int maxTime); 122 123 123 QIODevice *input;124 AudioOutput *output;125 Decoder *decoder;126 127 124 QString playfile; 128 125 QString statusString; 129 126 QString curSmartPlaylistCategory; 130 127 QString curSmartPlaylistName; 131 128 132 enum RepeatMode133 { REPEAT_OFF = 0,134 REPEAT_TRACK,135 REPEAT_ALL,136 MAX_REPEAT_MODES137 };138 enum ShuffleMode139 { SHUFFLE_OFF = 0,140 SHUFFLE_RANDOM,141 SHUFFLE_INTELLIGENT,142 SHUFFLE_ALBUM,143 SHUFFLE_ARTIST,144 MAX_SHUFFLE_MODES145 };146 129 enum ResumeMode 147 130 { RESUME_OFF, 148 131 RESUME_TRACK, … … 158 141 159 142 Metadata *curMeta; 160 143 161 162 unsigned int shufflemode;163 unsigned int repeatmode;164 144 unsigned int resumemode; 165 145 166 bool isplaying;167 168 146 bool menufilters; 169 147 170 148 ReadCDThread *cd_reader_thread; … … 195 173 QTimer *waiting_for_playlists_timer; 196 174 QTimer *volume_display_timer; 197 175 198 GenericTree *playlist_tree;199 200 176 bool cycle_visualizer; 201 177 bool random_visualizer; 202 178 bool show_album_art; -
mythmusic/mainvisual.cpp
217 217 218 218 VisualNode *node = 0; 219 219 220 if (playing && output()) { 220 if (playing && output()) 221 { 221 222 long synctime = output()->GetAudiotime(); 222 223 mutex()->lock(); 223 224 VisualNode *prev = 0; 224 while ((node = nodes.first())) { 225 while ((node = nodes.first())) 226 { 225 227 if (node->offset > synctime) 226 228 break; 227 228 229 delete prev; 229 230 nodes.removeFirst(); 230 231 prev = node; 231 232 } 232 233 mutex()->unlock(); 233 node = prev; 234 node = prev; 234 235 } 235 236 236 237 bool stop = TRUE; … … 276 277 switch (event->type()) 277 278 { 278 279 case OutputEvent::Playing: 279 playing = TRUE;280 // fall through intended281 282 280 case OutputEvent::Info: 283 281 case OutputEvent::Buffering: 284 282 case OutputEvent::Paused: 283 playing = TRUE; 284 285 285 if (! timer->isActive()) 286 286 timer->start(1000 / fps); 287 288 287 break; 289 288 290 289 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 8 class MusicPlayer; 9 class QTimer; 10 class Metadata; 11 12 /// Preferred position to place popup miniplayer. 13 enum PlayerPosition 14 { 15 MP_POSTOPDIALOG, 16 MP_POSBOTTOMDIALOG, 17 MP_POSCENTERDIALOG 18 }; 19 20 class 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