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
00032 ff_rew_state(0), ff_rew_index(0), ff_rew_speed(0),
00033
00034 playingState(kState_None),
00035 errored(false),
00036
00037 pseudoLiveTVRec(NULL), pseudoLiveTVState(kPseudoNormalLiveTV),
00038
00039 fftime(0), rewtime(0),
00040 jumptime(0), ts_normal(1.0f), ts_alt(1.5f),
00041
00042 playingInfoLock(QMutex::Recursive), deletePlayerLock(QMutex::Recursive),
00043 stateLock(QMutex::Recursive),
00044
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
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
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;
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
00518 if (prevChan.size() >= kMaxChannelHistory)
00519 prevChan.pop_front();
00520
00521
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
00546
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)
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 }