MythTV  0.26-pre
playercontext.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends