00001 #include <iostream>
00002 using namespace std;
00003
00004
00005 #include <qpixmap.h>
00006 #include <qimage.h>
00007 #include <qapplication.h>
00008
00009
00010 #include <mythtv/mythcontext.h>
00011 #include <mythtv/mythdialogs.h>
00012 #include <mythtv/uitypes.h>
00013 #include <mythtv/lcddevice.h>
00014
00015
00016 #include "miniplayer.h"
00017 #include "musicplayer.h"
00018 #include "decoder.h"
00019
00020 MiniPlayer::MiniPlayer(MythMainWindow *parent,
00021 MusicPlayer *parentPlayer,
00022 const char *name,
00023 bool setsize)
00024 : MythThemedDialog(parent, name, setsize)
00025 {
00026 setFrameStyle(QFrame::NoFrame | QFrame::Plain);
00027 setLineWidth(1);
00028 m_parentPlayer = parentPlayer;
00029
00030 m_displayTimer = new QTimer(this);
00031 connect(m_displayTimer, SIGNAL(timeout()), this, SLOT(timerTimeout()));
00032
00033 m_infoTimer = new QTimer(this);
00034 connect(m_infoTimer, SIGNAL(timeout()), this, SLOT(showInfoTimeout()));
00035
00036 wireupTheme();
00037
00038 gPlayer->setListener(this);
00039
00040 if (gPlayer->getCurrentMetadata())
00041 {
00042 m_maxTime = gPlayer->getCurrentMetadata()->Length() / 1000;
00043 updateTrackInfo(gPlayer->getCurrentMetadata());
00044
00045 if (!gPlayer->isPlaying())
00046 {
00047 QString time_string = getTimeString(m_maxTime, 0);
00048
00049 if (m_timeText)
00050 m_timeText->SetText(time_string);
00051 if (m_infoText)
00052 m_infoText->SetText(tr("Stopped"));
00053 }
00054 }
00055
00056 m_showingInfo = false;
00057 }
00058
00059 MiniPlayer::~MiniPlayer(void)
00060 {
00061 gPlayer->setListener(NULL);
00062
00063 m_displayTimer->deleteLater();
00064 m_displayTimer = NULL;
00065
00066 m_infoTimer->deleteLater();
00067 m_infoTimer = NULL;
00068
00069 if (class LCD *lcd = LCD::Get())
00070 lcd->switchToTime ();
00071 }
00072
00073 void MiniPlayer::showPlayer(int showTime)
00074 {
00075 m_showTime = showTime;
00076 m_displayTimer->start(showTime * 1000, true);
00077 exec();
00078 }
00079
00080 void MiniPlayer::timerTimeout(void)
00081 {
00082 done(Accepted);
00083 }
00084
00085 void MiniPlayer::wireupTheme(void)
00086 {
00087 QString theme_file = QString("music-");
00088
00089 if (!loadThemedWindow("miniplayer", theme_file))
00090 {
00091 VERBOSE(VB_GENERAL, "MiniPlayer: cannot load theme!");
00092 done(0);
00093 return;
00094 }
00095
00096
00097 LayerSet *container = getContainer("player_container");
00098
00099 if (!container)
00100 {
00101 cerr << "MiniPlayer: cannot find the 'player_container'"
00102 " in your theme" << endl;
00103 done(0);
00104 return;
00105 }
00106
00107 QRect area = container->GetAreaRect();
00108
00109
00110 container->SetAreaRect(QRect(0, 0, area.width(), area.height()));
00111
00112
00113 vector<UIType *> *types = container->getAllTypes();
00114 vector<UIType *>::iterator i = types->begin();
00115 for (; i != types->end(); i++)
00116 {
00117 UIType *type = (*i);
00118 type->calculateScreenArea();
00119 }
00120
00121 setFixedSize(QSize(area.width(), area.height()));
00122
00123 QPoint pos(area.x(), area.y());
00124 this->move(pos);
00125
00126 m_titleText = getUITextType("title_text");
00127 m_artistText = getUITextType("artist_text");
00128 m_timeText = getUITextType("time_text");
00129 m_infoText = getUITextType("info_text");
00130 m_albumText = getUITextType("album_text");
00131 m_ratingsImage = getUIRepeatedImageType("ratings_image");
00132 m_coverImage = getUIImageType("cover_image");
00133 m_progressBar = getUIStatusBarType("progress_bar");
00134 m_volText = getUITextType("volume_text");
00135
00136 if (m_volText && gPlayer->getOutput())
00137 {
00138 m_volFormat = m_volText->GetText();
00139 m_volText->SetText(QString(m_volFormat)
00140 .arg((int) gPlayer->getOutput()->GetCurrentVolume()));
00141 }
00142 }
00143
00144 void MiniPlayer::show()
00145 {
00146 grabKeyboard();
00147
00148 MythDialog::show();
00149 }
00150
00151 void MiniPlayer::hide()
00152 {
00153 releaseKeyboard();
00154
00155 MythDialog::hide();
00156 }
00157
00158 void MiniPlayer::keyPressEvent(QKeyEvent *e)
00159 {
00160 bool handled = false;
00161 QStringList actions;
00162 if (gContext->GetMainWindow()->TranslateKeyPress("Music", e, actions, false))
00163 {
00164 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00165 {
00166 QString action = actions[i];
00167 handled = true;
00168 if (action == "ESCAPE")
00169 done(0);
00170 else if (action == "SELECT")
00171 m_displayTimer->stop();
00172 else if (action == "NEXTTRACK")
00173 gPlayer->next();
00174 else if (action == "PREVTRACK")
00175 gPlayer->previous();
00176 else if (action == "FFWD")
00177 seekforward();
00178 else if (action == "RWND")
00179 seekback();
00180 else if (action == "PLAY")
00181 {
00182 if (gPlayer->isPlaying())
00183 return;
00184
00185 if (gPlayer->getOutput() && gPlayer->getOutput()->GetPause())
00186 {
00187 gPlayer->pause();
00188 return;
00189 }
00190
00191 gPlayer->play();
00192 }
00193 else if (action == "PAUSE")
00194 {
00195 if (gPlayer->isPlaying())
00196 gPlayer->pause();
00197 else
00198 {
00199 if (gPlayer->isPlaying())
00200 gPlayer->stop();
00201
00202 if (gPlayer->getOutput() && gPlayer->getOutput()->GetPause())
00203 {
00204 gPlayer->pause();
00205 return;
00206 }
00207
00208 gPlayer->play();
00209 }
00210 }
00211 else if (action == "STOP")
00212 {
00213 gPlayer->stop();
00214
00215 QString time_string = getTimeString(m_maxTime, 0);
00216
00217 if (m_timeText)
00218 m_timeText->SetText(time_string);
00219 if (m_infoText)
00220 m_infoText->SetText("");
00221 }
00222 else if (action == "VOLUMEDOWN")
00223 {
00224 if (gPlayer->getOutput())
00225 {
00226 gPlayer->getOutput()->AdjustCurrentVolume(-2);
00227 showVolume();
00228 }
00229 }
00230 else if (action == "VOLUMEUP")
00231 {
00232 if (gPlayer->getOutput())
00233 {
00234 gPlayer->getOutput()->AdjustCurrentVolume(2);
00235 showVolume();
00236 }
00237 }
00238 else if (action == "MUTE")
00239 {
00240 if (gPlayer->getOutput())
00241 {
00242 gPlayer->getOutput()->ToggleMute();
00243
00244 if (m_infoText)
00245 {
00246 m_showingInfo = true;
00247 if (gPlayer->getOutput()->GetMute())
00248 m_infoText->SetText(tr("Mute: On"));
00249 else
00250 m_infoText->SetText(tr("Mute: Off"));
00251
00252 m_infoTimer->start(5000, true);
00253 }
00254
00255 if (m_volText)
00256 {
00257 if (gPlayer->getOutput()->GetMute())
00258 m_volText->SetText(QString(m_volFormat).arg(0));
00259 else
00260 m_volText->SetText(QString(m_volFormat)
00261 .arg((int) gPlayer->getOutput()->GetCurrentVolume()));
00262 }
00263 }
00264 }
00265 else if (action == "THMBUP")
00266 increaseRating();
00267 else if (action == "THMBDOWN")
00268 decreaseRating();
00269 else if (action == "SPEEDDOWN")
00270 {
00271 gPlayer->decSpeed();
00272 showSpeed();
00273 }
00274 else if (action == "SPEEDUP")
00275 {
00276 gPlayer->incSpeed();
00277 showSpeed();
00278 }
00279 else if (action == "1")
00280 {
00281 gPlayer->toggleShuffleMode();
00282 showShuffleMode();
00283 }
00284 else if (action == "2")
00285 {
00286 gPlayer->toggleRepeatMode();
00287 showRepeatMode();
00288 }
00289 else if (action == "MENU")
00290 {
00291 gPlayer->autoShowPlayer(!gPlayer->getAutoShowPlayer());
00292 showAutoMode();
00293 }
00294
00295 else
00296 handled = false;
00297 }
00298
00299
00300 if (m_displayTimer->isActive())
00301 m_displayTimer->start(m_showTime * 1000, true);
00302 }
00303 }
00304
00305 void MiniPlayer::customEvent(QCustomEvent *event)
00306 {
00307 if (isHidden())
00308 return;
00309
00310 switch ((int)event->type())
00311 {
00312 case OutputEvent::Playing:
00313 {
00314 if (gPlayer->getCurrentMetadata())
00315 {
00316 m_maxTime = gPlayer->getCurrentMetadata()->Length() / 1000;
00317 updateTrackInfo(gPlayer->getCurrentMetadata());
00318 }
00319 break;
00320 }
00321
00322 case OutputEvent::Buffering:
00323 {
00324 break;
00325 }
00326
00327 case OutputEvent::Paused:
00328 {
00329 break;
00330 }
00331
00332 case OutputEvent::Info:
00333 {
00334 OutputEvent *oe = (OutputEvent *) event;
00335
00336 int rs;
00337 m_currTime = rs = oe->elapsedSeconds();
00338
00339 QString time_string = getTimeString(rs, m_maxTime);
00340
00341 QString info_string;
00342
00343
00344 if (oe->bitrate() < 2000)
00345 {
00346 info_string.sprintf("%d "+tr("kbps")+ " %.1f "+ tr("kHz")+ " %s "+ tr("ch"),
00347 oe->bitrate(), float(oe->frequency()) / 1000.0,
00348 oe->channels() > 1 ? "2" : "1");
00349 }
00350 else
00351 {
00352 info_string.sprintf("%.1f "+ tr("kHz")+ " %s "+ tr("ch"),
00353 float(oe->frequency()) / 1000.0,
00354 oe->channels() > 1 ? "2" : "1");
00355 }
00356
00357 if (m_timeText)
00358 m_timeText->SetText(time_string);
00359 if (m_infoText && !m_showingInfo)
00360 m_infoText->SetText(info_string);
00361
00362 if (m_progressBar)
00363 {
00364 m_progressBar->SetTotal(m_maxTime);
00365 m_progressBar->SetUsed(m_currTime);
00366 }
00367
00368 if (gPlayer->getCurrentMetadata())
00369 {
00370 if (class LCD *lcd = LCD::Get())
00371 {
00372 float percent_heard = m_maxTime <=0 ? 0.0 :
00373 ((float)rs / (float)gPlayer->getCurrentMetadata()->Length()) * 1000.0;
00374
00375 QString lcd_time_string = time_string;
00376
00377
00378 if (time_string.length() > lcd->getLCDWidth())
00379 lcd_time_string.remove(' ');
00380
00381 lcd->setMusicProgress(lcd_time_string, percent_heard);
00382 }
00383 }
00384 break;
00385 }
00386 case OutputEvent::Error:
00387 {
00388 break;
00389 }
00390 case DecoderEvent::Stopped:
00391 {
00392 break;
00393 }
00394 case DecoderEvent::Finished:
00395 {
00396 if (gPlayer->getRepeatMode() == MusicPlayer::REPEAT_TRACK)
00397 gPlayer->play();
00398 else
00399 gPlayer->next();
00400 break;
00401 }
00402 case DecoderEvent::Error:
00403 {
00404 break;
00405 }
00406 }
00407 QObject::customEvent(event);
00408 }
00409
00410 QString MiniPlayer::getTimeString(int exTime, int maxTime)
00411 {
00412 QString time_string;
00413
00414 int eh = exTime / 3600;
00415 int em = (exTime / 60) % 60;
00416 int es = exTime % 60;
00417
00418 int maxh = maxTime / 3600;
00419 int maxm = (maxTime / 60) % 60;
00420 int maxs = maxTime % 60;
00421
00422 if (maxTime <= 0)
00423 {
00424 if (eh > 0)
00425 time_string.sprintf("%d:%02d:%02d", eh, em, es);
00426 else
00427 time_string.sprintf("%02d:%02d", em, es);
00428 }
00429 else
00430 {
00431 if (maxh > 0)
00432 time_string.sprintf("%d:%02d:%02d / %02d:%02d:%02d", eh, em,
00433 es, maxh, maxm, maxs);
00434 else
00435 time_string.sprintf("%02d:%02d / %02d:%02d", em, es, maxm,
00436 maxs);
00437 }
00438
00439 return time_string;
00440 }
00441
00442 void MiniPlayer::updateTrackInfo(Metadata *mdata)
00443 {
00444 if (m_titleText)
00445 m_titleText->SetText(mdata->FormatTitle());
00446 if (m_artistText)
00447 m_artistText->SetText(mdata->FormatArtist());
00448 if (m_albumText)
00449 m_albumText->SetText(mdata->Album());
00450 if (m_ratingsImage)
00451 m_ratingsImage->setRepeat(mdata->Rating());
00452
00453 if (m_coverImage)
00454 {
00455 QImage image = gPlayer->getCurrentMetadata()->getAlbumArt();
00456 if (!image.isNull())
00457 {
00458 m_coverImage->SetImage(
00459 QPixmap(image.smoothScale(m_coverImage->GetSize(true))));
00460 }
00461 else
00462 {
00463 m_coverImage->SetImage("mm_nothumb.png");
00464 m_coverImage->LoadImage();
00465 }
00466
00467 m_coverImage->refresh();
00468 }
00469
00470 LCD *lcd = LCD::Get();
00471 if (lcd)
00472 {
00473
00474 lcd->switchToMusic(mdata->Artist(),
00475 mdata->Album(),
00476 mdata->Title());
00477 }
00478 }
00479
00480 void MiniPlayer::seekforward(void)
00481 {
00482 int nextTime = m_currTime + 5;
00483 if (nextTime > m_maxTime)
00484 nextTime = m_maxTime;
00485 seek(nextTime);
00486 }
00487
00488 void MiniPlayer::seekback(void)
00489 {
00490 int nextTime = m_currTime - 5;
00491 if (nextTime < 0)
00492 nextTime = 0;
00493 seek(nextTime);
00494 }
00495
00496 void MiniPlayer::seek(int pos)
00497 {
00498 if (gPlayer->getOutput())
00499 {
00500 gPlayer->getOutput()->Reset();
00501 gPlayer->getOutput()->SetTimecode(pos*1000);
00502
00503 if (gPlayer->getDecoder() && gPlayer->getDecoder()->running())
00504 {
00505 gPlayer->getDecoder()->lock();
00506 gPlayer->getDecoder()->seek(pos);
00507 gPlayer->getDecoder()->unlock();
00508 }
00509
00510 if (!gPlayer->isPlaying())
00511 {
00512 m_currTime = pos;
00513 if (m_timeText)
00514 m_timeText->SetText(getTimeString(pos, m_maxTime));
00515
00516
00517
00518 if (class LCD *lcd = LCD::Get())
00519 {
00520 float percent_heard = m_maxTime <= 0 ? 0.0 : ((float)pos /
00521 (float)m_maxTime);
00522
00523 QString lcd_time_string = getTimeString(pos, m_maxTime);
00524
00525
00526 if (lcd_time_string.length() > lcd->getLCDWidth())
00527 lcd_time_string.remove(' ');
00528
00529 lcd->setMusicProgress(lcd_time_string, percent_heard);
00530 }
00531 }
00532 }
00533 }
00534
00535 void MiniPlayer::increaseRating(void)
00536 {
00537 Metadata *curMeta = gPlayer->getCurrentMetadata();
00538
00539 if (!curMeta)
00540 return;
00541
00542 if (m_ratingsImage)
00543 {
00544 curMeta->incRating();
00545 curMeta->persist();
00546 m_ratingsImage->setRepeat(curMeta->Rating());
00547
00548
00549 if (gMusicData->all_music)
00550 {
00551 if (gPlayer->getCurrentNode())
00552 {
00553 Metadata *mdata = gMusicData->all_music->getMetadata(gPlayer->getCurrentNode()->getInt());
00554 if (mdata)
00555 {
00556 mdata->incRating();
00557 }
00558 }
00559 }
00560 }
00561 }
00562
00563 void MiniPlayer::decreaseRating(void)
00564 {
00565 Metadata *curMeta = gPlayer->getCurrentMetadata();
00566
00567 if (!curMeta)
00568 return;
00569
00570 if (m_ratingsImage)
00571 {
00572 curMeta->decRating();
00573 curMeta->persist();
00574 m_ratingsImage->setRepeat(curMeta->Rating());
00575
00576
00577 if (gMusicData->all_music)
00578 {
00579 if (gPlayer->getCurrentNode())
00580 {
00581 Metadata *mdata = gMusicData->all_music->getMetadata(gPlayer->getCurrentNode()->getInt());
00582 if (mdata)
00583 {
00584 mdata->decRating();
00585 }
00586 }
00587 }
00588 }
00589 }
00590
00591 void MiniPlayer::showInfoTimeout(void)
00592 {
00593 m_showingInfo = false;
00594 LCD *lcd = LCD::Get();
00595 Metadata * mdata = gPlayer->getCurrentMetadata();
00596
00597 if (lcd && mdata)
00598 {
00599
00600 lcd->switchToMusic(mdata->Artist(),
00601 mdata->Album(),
00602 mdata->Title());
00603 }
00604 }
00605
00606 void MiniPlayer::showShuffleMode(void)
00607 {
00608 if (m_infoText)
00609 {
00610 m_infoTimer->stop();
00611 QString msg = tr("Shuffle Mode: ");
00612 switch (gPlayer->getShuffleMode())
00613 {
00614 case MusicPlayer::SHUFFLE_INTELLIGENT:
00615 msg += tr("Smart");
00616 if (class LCD *lcd = LCD::Get())
00617 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_SMART);
00618 break;
00619 case MusicPlayer::SHUFFLE_RANDOM:
00620 msg += tr("Rand");
00621 if (class LCD *lcd = LCD::Get())
00622 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_RAND);
00623 break;
00624 case MusicPlayer::SHUFFLE_ALBUM:
00625 msg += tr("Album");
00626 if (class LCD *lcd = LCD::Get())
00627 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ALBUM);
00628 break;
00629 case MusicPlayer::SHUFFLE_ARTIST:
00630 msg += tr("Artist");
00631 if (class LCD *lcd = LCD::Get())
00632 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_ARTIST);
00633 break;
00634 default:
00635 msg += tr("None");
00636 if (class LCD *lcd = LCD::Get())
00637 lcd->setMusicShuffle(LCD::MUSIC_SHUFFLE_NONE);
00638 break;
00639 }
00640
00641 m_showingInfo = true;
00642 m_infoText->SetText(msg);
00643 m_infoTimer->start(5000, true);
00644 }
00645 }
00646
00647 void MiniPlayer::showRepeatMode(void)
00648 {
00649 if (m_infoText)
00650 {
00651 m_infoTimer->stop();
00652 QString msg = tr("Repeat Mode: ");
00653 switch (gPlayer->getRepeatMode())
00654 {
00655 case MusicPlayer::REPEAT_ALL:
00656 msg += tr("All");
00657 if (class LCD *lcd = LCD::Get())
00658 lcd->setMusicRepeat (LCD::MUSIC_REPEAT_ALL);
00659 break;
00660 case MusicPlayer::REPEAT_TRACK:
00661 msg += tr("Track");
00662 if (class LCD *lcd = LCD::Get())
00663 lcd->setMusicRepeat (LCD::MUSIC_REPEAT_TRACK);
00664 break;
00665 default:
00666 msg += tr("None");
00667 if (class LCD *lcd = LCD::Get())
00668 lcd->setMusicRepeat (LCD::MUSIC_REPEAT_NONE);
00669 break;
00670 }
00671
00672 m_showingInfo = true;
00673 m_infoText->SetText(msg);
00674 m_infoTimer->start(5000, true);
00675 }
00676 }
00677
00678 void MiniPlayer::showAutoMode(void)
00679 {
00680 if (m_infoText)
00681 {
00682 m_infoTimer->stop();
00683 QString msg = tr("Auto Show Player: ");
00684 if (gPlayer->getAutoShowPlayer())
00685 msg += tr("On");
00686 else
00687 msg += tr("Off");
00688
00689 m_showingInfo = true;
00690 m_infoText->SetText(msg);
00691 m_infoTimer->start(5000, true);
00692 }
00693 }
00694
00695 void MiniPlayer::showVolume(void)
00696 {
00697 float level = (float)gPlayer->getOutput()->GetCurrentVolume();
00698 bool muted = gPlayer->getOutput()->GetMute();
00699
00700 if (m_infoText)
00701 {
00702 m_infoTimer->stop();
00703 QString msg = tr("Volume: ");
00704
00705 if (muted)
00706 msg += QString::number((int) level) + "% " + tr("(muted)");
00707 else
00708 msg += QString::number((int) level) + "%";
00709
00710 m_showingInfo = true;
00711 m_infoText->SetText(msg);
00712 m_infoTimer->start(5000, true);
00713 }
00714
00715 if (class LCD *lcd = LCD::Get())
00716 {
00717 if (muted)
00718 {
00719 lcd->switchToVolume("Music (muted)");
00720 lcd->setVolumeLevel(level / (float)100);
00721 }
00722 else
00723 {
00724 lcd->switchToVolume("Music");
00725 lcd->setVolumeLevel(level / (float)100);
00726 }
00727 }
00728
00729 if (m_volText)
00730 {
00731 if (muted)
00732 level = 0.0;
00733
00734 m_volText->SetText(QString(m_volFormat).arg((int) level));
00735 }
00736 }
00737
00738 void MiniPlayer::showSpeed(void)
00739 {
00740 float level = (float)gPlayer->getSpeed();
00741 QString msg = tr("Speed: ");
00742 QString param;
00743
00744 param.sprintf("x%4.2f",level);
00745 msg += param;
00746
00747 if (m_infoText)
00748 {
00749 m_infoTimer->stop();
00750 m_showingInfo = true;
00751 m_infoText->SetText(msg);
00752 m_infoTimer->start(5000, true);
00753 }
00754
00755 if (class LCD *lcd = LCD::Get())
00756 {
00757 QPtrList<LCDTextItem> textItems;
00758 textItems.setAutoDelete(true);
00759 textItems.append(new LCDTextItem(lcd->getLCDHeight() / 2, ALIGN_CENTERED,
00760 msg, "Generic", false));
00761 lcd->switchToGeneric(&textItems);
00762 }
00763 }