|
MythTV
0.26-pre
|
00001 #include <cmath> 00002 00003 #include <QPainter> 00004 00005 #include "mythconfig.h" 00006 00007 #include "playercontext.h" 00008 #include "mythplayer.h" 00009 #include "remoteencoder.h" 00010 #include "livetvchain.h" 00011 #include "ringbuffer.h" 00012 #include "playgroup.h" 00013 #include "videoouttypes.h" 00014 #include "storagegroup.h" 00015 #include "mythcorecontext.h" 00016 #include "videometadatautil.h" 00017 #include "metadataimagehelper.h" 00018 #include "mythlogging.h" 00019 #include "DVD/mythdvdplayer.h" 00020 #include "Bluray/mythbdplayer.h" 00021 00022 #define LOC QString("playCtx: ") 00023 00024 const uint PlayerContext::kSMExitTimeout = 2000; 00025 const uint PlayerContext::kMaxChannelHistory = 30; 00026 00027 PlayerContext::PlayerContext(const QString &inUseID) : 00028 recUsage(inUseID), player(NULL), playerUnsafe(false), recorder(NULL), 00029 tvchain(NULL), buffer(NULL), playingInfo(NULL), playingLen(0), 00030 nohardwaredecoders(false), last_cardid(-1), 00031 // Fast forward state 00032 ff_rew_state(0), ff_rew_index(0), ff_rew_speed(0), 00033 // Other state 00034 playingState(kState_None), 00035 errored(false), 00036 // pseudo states 00037 pseudoLiveTVRec(NULL), pseudoLiveTVState(kPseudoNormalLiveTV), 00038 // DB values 00039 fftime(0), rewtime(0), 00040 jumptime(0), ts_normal(1.0f), ts_alt(1.5f), 00041 // locks 00042 playingInfoLock(QMutex::Recursive), deletePlayerLock(QMutex::Recursive), 00043 stateLock(QMutex::Recursive), 00044 // pip 00045 pipState(kPIPOff), pipRect(0,0,0,0), parentWidget(NULL), pipLocation(0), 00046 useNullVideo(false) 00047 { 00048 lastSignalMsgTime.start(); 00049 lastSignalMsgTime.addMSecs(-2 * kSMExitTimeout); 00050 } 00051 00052 PlayerContext::~PlayerContext() 00053 { 00054 TeardownPlayer(); 00055 nextState.clear(); 00056 } 00057 00058 void PlayerContext::TeardownPlayer(void) 00059 { 00060 ff_rew_state = 0; 00061 ff_rew_index = 0; 00062 ff_rew_speed = 0; 00063 ts_normal = 1.0f; 00064 00065 SetPlayer(NULL); 00066 SetRecorder(NULL); 00067 SetRingBuffer(NULL); 00068 SetTVChain(NULL); 00069 SetPlayingInfo(NULL); 00070 } 00071 00076 void PlayerContext::SetInitialTVState(bool islivetv) 00077 { 00078 TVState newState = kState_None; 00079 QString newPlaygroup("Default"); 00080 00081 LockPlayingInfo(__FILE__, __LINE__); 00082 if (islivetv) 00083 { 00084 SetTVChain(new LiveTVChain()); 00085 newState = kState_WatchingLiveTV; 00086 } 00087 else if (playingInfo) 00088 { 00089 int overrecordseconds = gCoreContext->GetNumSetting("RecordOverTime"); 00090 QDateTime curtime = QDateTime::currentDateTime(); 00091 QDateTime recendts = playingInfo->GetRecordingEndTime() 00092 .addSecs(overrecordseconds); 00093 00094 if (playingInfo->IsRecording()) 00095 { 00096 newState = (curtime < recendts) ? 00097 kState_WatchingRecording : kState_WatchingPreRecorded; 00098 } 00099 else if (playingInfo->IsVideoDVD()) 00100 newState = kState_WatchingDVD; 00101 else if (playingInfo->IsVideoBD()) 00102 newState = kState_WatchingBD; 00103 else 00104 newState = kState_WatchingVideo; 00105 00106 newPlaygroup = playingInfo->GetPlaybackGroup(); 00107 } 00108 UnlockPlayingInfo(__FILE__, __LINE__); 00109 00110 ChangeState(newState); 00111 SetPlayGroup(newPlaygroup); 00112 } 00113 00119 bool PlayerContext::IsPIPSupported(void) const 00120 { 00121 bool supported = false; 00122 QMutexLocker locker(&deletePlayerLock); 00123 if (player) 00124 { 00125 const VideoOutput *vid = player->GetVideoOutput(); 00126 if (vid) 00127 supported = vid->IsPIPSupported(); 00128 } 00129 return supported; 00130 } 00131 00137 bool PlayerContext::IsPBPSupported(void) const 00138 { 00139 bool supported = false; 00140 QMutexLocker locker(&deletePlayerLock); 00141 if (player) 00142 { 00143 const VideoOutput *vid = player->GetVideoOutput(); 00144 if (vid) 00145 supported = vid->IsPBPSupported(); 00146 } 00147 return supported; 00148 } 00149 00150 void PlayerContext::CreatePIPWindow(const QRect &rect, int pos, 00151 QWidget *widget) 00152 { 00153 QString name; 00154 if (pos > -1) 00155 { 00156 pipLocation = pos; 00157 name = QString("pip player %1").arg(toString((PIPLocation)pos)); 00158 } 00159 else 00160 name = "pip player"; 00161 00162 if (widget) 00163 parentWidget = widget; 00164 00165 pipRect = QRect(rect); 00166 } 00167 00172 QRect PlayerContext::GetStandAlonePIPRect(void) 00173 { 00174 QRect rect = QRect(0, 0, 0, 0); 00175 QMutexLocker locker(&deletePlayerLock); 00176 if (player) 00177 { 00178 rect = QRect(pipRect); 00179 00180 float saspect = (float)rect.width() / (float)rect.height(); 00181 float vaspect = player->GetVideoAspect(); 00182 00183 // Calculate new height or width according to relative aspect ratio 00184 if ((int)((saspect + 0.05) * 10) > (int)((vaspect + 0.05) * 10)) 00185 { 00186 rect.setWidth((int) ceil(rect.width() * (vaspect / saspect))); 00187 } 00188 else if ((int)((saspect + 0.05) * 10) < (int)((vaspect + 0.05) * 10)) 00189 { 00190 rect.setHeight((int) ceil(rect.height() * (saspect / vaspect))); 00191 } 00192 00193 rect.setHeight(((rect.height() + 7) / 8) * 8); 00194 rect.setWidth( ((rect.width() + 7) / 8) * 8); 00195 } 00196 return rect; 00197 } 00198 00199 bool PlayerContext::StartPIPPlayer(TV *tv, TVState desiredState) 00200 { 00201 bool ok = false; 00202 00203 if (!useNullVideo && parentWidget) 00204 { 00205 const QRect rect = QRect(pipRect); 00206 ok = CreatePlayer(tv, parentWidget, desiredState, 00207 true, rect); 00208 } 00209 00210 if (useNullVideo || !ok) 00211 { 00212 SetPlayer(NULL); 00213 useNullVideo = true; 00214 ok = CreatePlayer(tv, NULL, desiredState, 00215 false); 00216 } 00217 00218 return ok; 00219 } 00220 00221 00227 void PlayerContext::PIPTeardown(void) 00228 { 00229 if (buffer) 00230 { 00231 buffer->Pause(); 00232 buffer->WaitForPause(); 00233 } 00234 00235 { 00236 QMutexLocker locker(&deletePlayerLock); 00237 StopPlaying(); 00238 } 00239 00240 SetPlayer(NULL); 00241 00242 useNullVideo = false; 00243 parentWidget = NULL; 00244 } 00245 00249 void PlayerContext::ResizePIPWindow(const QRect &rect) 00250 { 00251 if (!IsPIP()) 00252 return; 00253 00254 QRect tmpRect; 00255 if (pipState == kPIPStandAlone) 00256 tmpRect = GetStandAlonePIPRect(); 00257 else 00258 tmpRect = QRect(rect); 00259 00260 LockDeletePlayer(__FILE__, __LINE__); 00261 if (player && player->GetVideoOutput()) 00262 player->GetVideoOutput()->ResizeDisplayWindow(tmpRect, false); 00263 UnlockDeletePlayer(__FILE__, __LINE__); 00264 00265 pipRect = QRect(rect); 00266 } 00267 00268 bool PlayerContext::StartEmbedding(WId wid, const QRect &embedRect) 00269 { 00270 bool ret = false; 00271 LockDeletePlayer(__FILE__, __LINE__); 00272 if (player) 00273 { 00274 ret = true; 00275 player->EmbedInWidget(embedRect); 00276 } 00277 UnlockDeletePlayer(__FILE__, __LINE__); 00278 return ret; 00279 } 00280 00281 bool PlayerContext::IsEmbedding(void) const 00282 { 00283 bool ret = false; 00284 LockDeletePlayer(__FILE__, __LINE__); 00285 if (player) 00286 ret = player->IsEmbedding(); 00287 UnlockDeletePlayer(__FILE__, __LINE__); 00288 return ret; 00289 } 00290 00291 void PlayerContext::StopEmbedding(void) 00292 { 00293 LockDeletePlayer(__FILE__, __LINE__); 00294 if (player) 00295 player->StopEmbedding(); 00296 UnlockDeletePlayer(__FILE__, __LINE__); 00297 } 00298 00299 bool PlayerContext::HasPlayer(void) const 00300 { 00301 QMutexLocker locker(&deletePlayerLock); 00302 return player; 00303 } 00304 00305 bool PlayerContext::IsPlayerErrored(void) const 00306 { 00307 QMutexLocker locker(&deletePlayerLock); 00308 return player && player->IsErrored(); 00309 } 00310 00311 bool PlayerContext::IsPlayerRecoverable(void) const 00312 { 00313 QMutexLocker locker(&deletePlayerLock); 00314 return player && player->IsErrorRecoverable(); 00315 } 00316 00317 bool PlayerContext::IsPlayerDecoderErrored(void) const 00318 { 00319 QMutexLocker locker(&deletePlayerLock); 00320 return player && player->IsDecoderErrored(); 00321 } 00322 00323 bool PlayerContext::IsPlayerPlaying(void) const 00324 { 00325 QMutexLocker locker(&deletePlayerLock); 00326 return player && player->IsPlaying(); 00327 } 00328 00329 bool PlayerContext::HandlePlayerSpeedChangeFFRew(void) 00330 { 00331 QMutexLocker locker(&deletePlayerLock); 00332 if ((ff_rew_state || ff_rew_speed) && player && player->AtNormalSpeed()) 00333 { 00334 ff_rew_speed = 0; 00335 ff_rew_state = 0; 00336 ff_rew_index = TV::kInitFFRWSpeed; 00337 return true; 00338 } 00339 return false; 00340 } 00341 00342 bool PlayerContext::HandlePlayerSpeedChangeEOF(void) 00343 { 00344 QMutexLocker locker(&deletePlayerLock); 00345 if (player && (player->GetNextPlaySpeed() != ts_normal) && 00346 player->AtNormalSpeed()) 00347 { 00348 // Speed got changed in player since we are close to the end of file 00349 ts_normal = 1.0f; 00350 return true; 00351 } 00352 return false; 00353 } 00354 00355 bool PlayerContext::CalcPlayerSliderPosition(osdInfo &info, 00356 bool paddedFields) const 00357 { 00358 QMutexLocker locker(&deletePlayerLock); 00359 if (player) 00360 { 00361 player->calcSliderPos(info); 00362 return true; 00363 } 00364 return false; 00365 } 00366 00367 bool PlayerContext::IsRecorderErrored(void) const 00368 { 00369 return recorder && recorder->GetErrorStatus(); 00370 } 00371 00372 bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget, 00373 TVState desiredState, 00374 bool embed, const QRect &embedbounds, 00375 bool muted) 00376 { 00377 if (HasPlayer()) 00378 { 00379 LOG(VB_GENERAL, LOG_ERR, LOC + 00380 "Attempting to setup a player, but it already exists."); 00381 return false; 00382 } 00383 00384 uint playerflags = kDecodeAllowEXT; // allow VDA etc for normal playback 00385 playerflags |= muted ? kAudioMuted : kNoFlags; 00386 playerflags |= useNullVideo ? kVideoIsNull : kNoFlags; 00387 playerflags |= nohardwaredecoders ? kNoFlags : kDecodeAllowGPU; 00388 00389 MythPlayer *player = NULL; 00390 if (kState_WatchingBD == desiredState) 00391 player = new MythBDPlayer((PlayerFlags)playerflags); 00392 else if (kState_WatchingDVD == desiredState) 00393 player = new MythDVDPlayer((PlayerFlags)playerflags); 00394 else 00395 player = new MythPlayer((PlayerFlags)playerflags); 00396 00397 QString passthru_device = 00398 gCoreContext->GetNumSetting("PassThruDeviceOverride", false) ? 00399 gCoreContext->GetSetting("PassThruOutputDevice") : QString::null; 00400 00401 player->SetPlayerInfo(tv, widget, this); 00402 AudioPlayer *audio = player->GetAudio(); 00403 audio->SetAudioInfo(gCoreContext->GetSetting("AudioOutputDevice"), 00404 passthru_device, 00405 gCoreContext->GetNumSetting("AudioSampleRate", 44100)); 00406 audio->SetStretchFactor(ts_normal); 00407 player->SetLength(playingLen); 00408 00409 player->SetVideoFilters((useNullVideo) ? "onefield" : ""); 00410 00411 if (!IsAudioNeeded()) 00412 audio->SetNoAudio(); 00413 else 00414 { 00415 QString subfn = buffer->GetSubtitleFilename(); 00416 if (!subfn.isEmpty() && player->GetSubReader()) 00417 player->GetSubReader()->LoadExternalSubtitles(subfn); 00418 } 00419 00420 if (embed && !embedbounds.isNull()) 00421 player->EmbedInWidget(embedbounds); 00422 00423 bool isWatchingRecording = (desiredState == kState_WatchingRecording); 00424 player->SetWatchingRecording(isWatchingRecording); 00425 00426 SetPlayer(player); 00427 00428 if (pipState == kPIPOff || pipState == kPBPLeft) 00429 { 00430 if (audio->HasAudioOut()) 00431 { 00432 QString errMsg = audio->ReinitAudio(); 00433 } 00434 } 00435 else if (pipState == kPBPRight) 00436 player->SetMuted(true); 00437 00438 return StartPlaying(-1); 00439 } 00440 00446 bool PlayerContext::StartPlaying(int maxWait) 00447 { 00448 if (!player) 00449 return false; 00450 00451 player->StartPlaying(); 00452 00453 maxWait = (maxWait <= 0) ? 20000 : maxWait; 00454 #ifdef USING_VALGRIND 00455 maxWait = (1<<30); 00456 #endif // USING_VALGRIND 00457 MythTimer t; 00458 t.start(); 00459 00460 while (!player->IsPlaying(50, true) && (t.elapsed() < maxWait)) 00461 ReloadTVChain(); 00462 00463 if (player->IsPlaying()) 00464 { 00465 LOG(VB_PLAYBACK, LOG_INFO, LOC + 00466 QString("StartPlaying(): took %1 ms to start player.") 00467 .arg(t.elapsed())); 00468 return true; 00469 } 00470 else 00471 { 00472 LOG(VB_GENERAL, LOG_ERR, LOC + "StartPlaying() Failed to start player"); 00473 StopPlaying(); 00474 return false; 00475 } 00476 } 00477 00478 void PlayerContext::StopPlaying(void) 00479 { 00480 if (player) 00481 player->StopPlaying(); 00482 } 00483 00484 void PlayerContext::UpdateTVChain(void) 00485 { 00486 QMutexLocker locker(&deletePlayerLock); 00487 if (tvchain && player) 00488 { 00489 tvchain->ReloadAll(); 00490 player->CheckTVChain(); 00491 } 00492 } 00493 00494 bool PlayerContext::ReloadTVChain(void) 00495 { 00496 if (!tvchain) 00497 return false; 00498 00499 tvchain->ReloadAll(); 00500 ProgramInfo *pinfo = tvchain->GetProgramAt(-1); 00501 if (pinfo) 00502 { 00503 SetPlayingInfo(pinfo); 00504 delete pinfo; 00505 } 00506 return (bool) pinfo; 00507 } 00508 00512 void PlayerContext::PushPreviousChannel(void) 00513 { 00514 if (!tvchain) 00515 return; 00516 00517 // Don't store more than kMaxChannelHistory channels. Remove the first item 00518 if (prevChan.size() >= kMaxChannelHistory) 00519 prevChan.pop_front(); 00520 00521 // This method builds the stack of previous channels 00522 QString curChan = tvchain->GetChannelName(-1); 00523 if (prevChan.empty() || 00524 curChan != prevChan[prevChan.size() - 1]) 00525 { 00526 QString chan = curChan; 00527 prevChan.push_back(chan); 00528 } 00529 } 00530 00531 QString PlayerContext::PopPreviousChannel(void) 00532 { 00533 if (prevChan.empty()) 00534 return QString::null; 00535 00536 QString curChan = tvchain->GetChannelName(-1); 00537 if ((curChan == prevChan.back()) && !prevChan.empty()) 00538 prevChan.pop_back(); 00539 00540 if (prevChan.empty()) 00541 return QString::null; 00542 00543 QString chan = prevChan.back(); 00544 prevChan.pop_back(); 00545 // add the current channel back to the list, to allow easy flipping between 00546 // two channels using PREVCHAN 00547 PushPreviousChannel(); 00548 chan.detach(); 00549 return chan; 00550 } 00551 00552 QString PlayerContext::GetPreviousChannel(void) const 00553 { 00554 if (prevChan.empty()) 00555 return QString::null; 00556 00557 QString curChan = tvchain->GetChannelName(-1); 00558 QString preChan = QString::null; 00559 if (curChan != prevChan.back() || prevChan.size() < 2) 00560 preChan = prevChan.back(); 00561 else 00562 preChan = prevChan[prevChan.size()-2]; 00563 preChan.detach(); 00564 return preChan; 00565 } 00566 00567 void PlayerContext::LockPlayingInfo(const char *file, int line) const 00568 { 00569 #if 0 00570 LOG(VB_GENERAL, LOG_DEBUG, QString("LockPlayingInfo(%1,%2)") 00571 .arg(file).arg(line)); 00572 #endif 00573 playingInfoLock.lock(); 00574 } 00575 00576 void PlayerContext::UnlockPlayingInfo(const char *file, int line) const 00577 { 00578 #if 0 00579 LOG(VB_GENERAL, LOG_DEBUG, QString("UnlockPlayingInfo(%1,%2)") 00580 .arg(file).arg(line)); 00581 #endif 00582 playingInfoLock.unlock(); 00583 } 00584 00590 void PlayerContext::LockDeletePlayer(const char *file, int line) const 00591 { 00592 #if 0 00593 LOG(VB_GENERAL, LOG_DEBUG, QString("LockDeletePlayer(%1,%2)") 00594 .arg(file).arg(line)); 00595 #endif 00596 deletePlayerLock.lock(); 00597 } 00598 00602 void PlayerContext::UnlockDeletePlayer(const char *file, int line) const 00603 { 00604 #if 0 00605 LOG(VB_GENERAL, LOG_DEBUG, QString("UnlockDeletePlayer(%1,%2)") 00606 .arg(file).arg(line)); 00607 #endif 00608 deletePlayerLock.unlock(); 00609 } 00610 00611 void PlayerContext::LockState(void) const 00612 { 00613 stateLock.lock(); 00614 } 00615 00616 void PlayerContext::UnlockState(void) const 00617 { 00618 stateLock.unlock(); 00619 } 00620 00621 void PlayerContext::LockOSD() const 00622 { 00623 player->LockOSD(); 00624 } 00625 00626 void PlayerContext::UnlockOSD(void) const 00627 { 00628 player->UnlockOSD(); 00629 } 00630 00631 bool PlayerContext::InStateChange(void) const 00632 { 00633 if (!stateLock.tryLock()) 00634 return true; 00635 bool inStateChange = nextState.size() > 0; 00636 stateLock.unlock(); 00637 return inStateChange; 00638 } 00639 00643 void PlayerContext::ChangeState(TVState newState) 00644 { 00645 QMutexLocker locker(&stateLock); 00646 nextState.enqueue(newState); 00647 } 00648 00649 TVState PlayerContext::DequeueNextState(void) 00650 { 00651 QMutexLocker locker(&stateLock); 00652 return nextState.dequeue(); 00653 } 00654 00658 void PlayerContext::ForceNextStateNone(void) 00659 { 00660 QMutexLocker locker(&stateLock); 00661 nextState.clear(); 00662 nextState.push_back(kState_None); 00663 } 00664 00665 TVState PlayerContext::GetState(void) const 00666 { 00667 QMutexLocker locker(&stateLock); 00668 return playingState; 00669 } 00670 00671 bool PlayerContext::GetPlayingInfoMap(InfoMap &infoMap) const 00672 { 00673 bool loaded = false; 00674 LockPlayingInfo(__FILE__, __LINE__); 00675 if (playingInfo) 00676 { 00677 playingInfo->ToMap(infoMap); 00678 infoMap["tvstate"] = StateToString(playingState); 00679 infoMap["iconpath"] = ChannelUtil::GetIcon(playingInfo->GetChanID()); 00680 if ((playingInfo->IsVideoFile() || playingInfo->IsVideoDVD() || 00681 playingInfo->IsVideoBD()) && playingInfo->GetPathname() != 00682 playingInfo->GetBasename()) 00683 { 00684 infoMap["coverartpath"] = VideoMetaDataUtil::GetArtPath( 00685 playingInfo->GetPathname(), "Coverart"); 00686 infoMap["fanartpath"] = VideoMetaDataUtil::GetArtPath( 00687 playingInfo->GetPathname(), "Fanart"); 00688 infoMap["bannerpath"] = VideoMetaDataUtil::GetArtPath( 00689 playingInfo->GetPathname(), "Banners"); 00690 infoMap["screenshotpath"] = VideoMetaDataUtil::GetArtPath( 00691 playingInfo->GetPathname(), "Screenshots"); 00692 } 00693 else 00694 { 00695 ArtworkMap artmap = GetArtwork(playingInfo->GetInetRef(), 00696 playingInfo->GetSeason()); 00697 infoMap["coverartpath"] = 00698 artmap.value(kArtworkCoverart).url; 00699 infoMap["fanartpath"] = 00700 artmap.value(kArtworkFanart).url; 00701 infoMap["bannerpath"] = 00702 artmap.value(kArtworkBanner).url; 00703 infoMap["screenshotpath"] = 00704 artmap.value(kArtworkScreenshot).url; 00705 } 00706 if (player) 00707 player->GetCodecDescription(infoMap); 00708 00709 infoMap.detach(); 00710 loaded = true; 00711 } 00712 UnlockPlayingInfo(__FILE__, __LINE__); 00713 return loaded; 00714 } 00715 00716 bool PlayerContext::IsSameProgram(const ProgramInfo &p) const 00717 { 00718 bool ret = false; 00719 LockPlayingInfo(__FILE__, __LINE__); 00720 if (playingInfo) 00721 ret = playingInfo->IsSameProgram(p); 00722 UnlockPlayingInfo(__FILE__, __LINE__); 00723 return ret; 00724 } 00725 00726 QString PlayerContext::GetFilters(const QString &baseFilters) const 00727 { 00728 QString filters = baseFilters; 00729 QString chanFilters = QString::null; 00730 00731 if (gCoreContext->IsDatabaseIgnored()) 00732 return baseFilters; 00733 00734 LockPlayingInfo(__FILE__, __LINE__); 00735 if (playingInfo) // Recordings have this info already. 00736 { 00737 chanFilters = playingInfo->GetChannelPlaybackFilters(); 00738 chanFilters.detach(); 00739 } 00740 UnlockPlayingInfo(__FILE__, __LINE__); 00741 00742 if (!chanFilters.isEmpty()) 00743 { 00744 if ((chanFilters[0] != '+')) 00745 { 00746 filters = chanFilters; 00747 } 00748 else 00749 { 00750 if (!filters.isEmpty() && (filters.right(1) != ",")) 00751 filters += ","; 00752 00753 filters += chanFilters.mid(1); 00754 } 00755 } 00756 00757 LOG(VB_CHANNEL, LOG_INFO, LOC + 00758 QString("Output filters for this channel are: '%1'") 00759 .arg(filters)); 00760 00761 filters.detach(); 00762 return filters; 00763 } 00764 00765 QString PlayerContext::GetPlayMessage(void) const 00766 { 00767 QString mesg = QObject::tr("Play"); 00768 if (ts_normal != 1.0) 00769 { 00770 if (ts_normal == 0.5) 00771 mesg += QString(" 1/2x"); 00772 else if (0.32 < ts_normal && ts_normal < 0.34) 00773 mesg += QString(" 1/3x"); 00774 else if (ts_normal == 0.25) 00775 mesg += QString(" 1/4x"); 00776 else if (ts_normal == 0.125) 00777 mesg += QString(" 1/8x"); 00778 else if (ts_normal == 0.0625) 00779 mesg += QString(" 1/16x"); 00780 else 00781 mesg += QString(" %1x").arg(ts_normal); 00782 } 00783 00784 return mesg; 00785 } 00786 00787 void PlayerContext::SetPlayer(MythPlayer *newplayer) 00788 { 00789 QMutexLocker locker(&deletePlayerLock); 00790 if (player) 00791 { 00792 StopPlaying(); 00793 delete player; 00794 } 00795 player = newplayer; 00796 } 00797 00798 void PlayerContext::SetRecorder(RemoteEncoder *rec) 00799 { 00800 if (recorder) 00801 { 00802 delete recorder; 00803 recorder = NULL; 00804 } 00805 00806 if (rec) 00807 { 00808 recorder = rec; 00809 last_cardid = recorder->GetRecorderNumber(); 00810 } 00811 } 00812 00813 void PlayerContext::SetTVChain(LiveTVChain *chain) 00814 { 00815 if (tvchain) 00816 { 00817 tvchain->DestroyChain(); 00818 delete tvchain; 00819 tvchain = NULL; 00820 } 00821 00822 tvchain = chain; 00823 00824 if (tvchain) 00825 { 00826 QString seed = QString(""); 00827 00828 if (IsPIP()) 00829 seed = "PIP"; 00830 00831 seed += gCoreContext->GetHostName(); 00832 00833 tvchain->InitializeNewChain(gCoreContext->GetHostName()); 00834 } 00835 } 00836 00837 void PlayerContext::SetRingBuffer(RingBuffer *buf) 00838 { 00839 if (buffer) 00840 { 00841 delete buffer; 00842 buffer = NULL; 00843 } 00844 00845 buffer = buf; 00846 } 00847 00851 void PlayerContext::SetPlayingInfo(const ProgramInfo *info) 00852 { 00853 bool ignoreDB = gCoreContext->IsDatabaseIgnored(); 00854 00855 QMutexLocker locker(&playingInfoLock); 00856 00857 if (playingInfo) 00858 { 00859 if (!ignoreDB) 00860 playingInfo->MarkAsInUse(false, recUsage); 00861 delete playingInfo; 00862 playingInfo = NULL; 00863 } 00864 00865 if (info) 00866 { 00867 playingInfo = new ProgramInfo(*info); 00868 if (!ignoreDB) 00869 playingInfo->MarkAsInUse(true, recUsage); 00870 playingLen = playingInfo->GetSecondsInRecording(); 00871 } 00872 } 00873 00874 void PlayerContext::SetPlayGroup(const QString &group) 00875 { 00876 fftime = PlayGroup::GetSetting(group, "skipahead", 30); 00877 rewtime = PlayGroup::GetSetting(group, "skipback", 5); 00878 jumptime = PlayGroup::GetSetting(group, "jump", 10); 00879 ts_normal = PlayGroup::GetSetting(group, "timestretch", 100) * 0.01f; 00880 ts_alt = (ts_normal == 1.0f) ? 1.5f : 1.0f; 00881 } 00882 00883 void PlayerContext::SetPseudoLiveTV( 00884 const ProgramInfo *pi, PseudoState new_state) 00885 { 00886 ProgramInfo *old_rec = pseudoLiveTVRec; 00887 ProgramInfo *new_rec = NULL; 00888 00889 if (pi) 00890 { 00891 new_rec = new ProgramInfo(*pi); 00892 QString msg = QString("Wants to record: %1 %2 %3 %4") 00893 .arg(new_rec->GetTitle()).arg(new_rec->GetChanNum()) 00894 .arg(new_rec->GetRecordingStartTime(ISODate)) 00895 .arg(new_rec->GetRecordingEndTime(ISODate)); 00896 LOG(VB_PLAYBACK, LOG_INFO, LOC + msg); 00897 } 00898 00899 pseudoLiveTVRec = new_rec; 00900 pseudoLiveTVState = new_state; 00901 00902 if (old_rec) 00903 { 00904 QString msg = QString("Done recording: %1 %2 %3 %4") 00905 .arg(old_rec->GetTitle()).arg(old_rec->GetChanNum()) 00906 .arg(old_rec->GetRecordingStartTime(ISODate)) 00907 .arg(old_rec->GetRecordingEndTime(ISODate)); 00908 LOG(VB_PLAYBACK, LOG_INFO, LOC + msg); 00909 delete old_rec; 00910 } 00911 }
1.7.6.1