MythTV  master
playercontext.cpp
Go to the documentation of this file.
1 #include <cmath>
2 
3 #include <QPainter>
4 
5 #include "mythconfig.h"
6 
7 #include "playercontext.h"
8 #include "mythplayer.h"
9 #include "remoteencoder.h"
10 #include "livetvchain.h"
11 #include "ringbuffer.h"
12 #include "playgroup.h"
13 #include "videoouttypes.h"
14 #include "storagegroup.h"
15 #include "mythcorecontext.h"
16 #include "videometadatautil.h"
17 #include "metadataimagehelper.h"
18 #include "mythlogging.h"
19 #include "DVD/mythdvdplayer.h"
20 #include "Bluray/mythbdplayer.h"
21 #include "channelutil.h"
22 #include "tv_play.h"
23 
24 #define LOC QString("playCtx: ")
25 
28 
29 PlayerContext::PlayerContext(const QString &inUseID) :
30  recUsage(inUseID), player(nullptr), playerUnsafe(false), recorder(nullptr),
31  tvchain(nullptr), buffer(nullptr), playingInfo(nullptr), playingLen(0),
32  nohardwaredecoders(false), last_cardid(-1),
33  // Fast forward state
34  ff_rew_state(0), ff_rew_index(0), ff_rew_speed(0),
35  // Other state
36  playingState(kState_None),
37  errored(false),
38  // pseudo states
39  pseudoLiveTVRec(nullptr), pseudoLiveTVState(kPseudoNormalLiveTV),
40  // DB values
41  fftime(0), rewtime(0),
42  jumptime(0), ts_normal(1.0f), ts_alt(1.5f),
43  // locks
44  playingInfoLock(QMutex::Recursive), deletePlayerLock(QMutex::Recursive),
45  stateLock(QMutex::Recursive),
46  // pip
47  pipState(kPIPOff), pipRect(0,0,0,0), parentWidget(nullptr), pipLocation(0),
48  useNullVideo(false)
49 {
52 }
53 
55 {
57  nextState.clear();
58 }
59 
61 {
62  ff_rew_state = 0;
63  ff_rew_index = 0;
64  ff_rew_speed = 0;
65  ts_normal = 1.0f;
66 
67  SetPlayer(nullptr);
68  SetRecorder(nullptr);
69  SetRingBuffer(nullptr);
70  SetTVChain(nullptr);
71  SetPlayingInfo(nullptr);
72 }
73 
79 {
80  TVState newState = kState_None;
81  QString newPlaygroup("Default");
82 
83  LockPlayingInfo(__FILE__, __LINE__);
84  if (islivetv)
85  {
86  SetTVChain(new LiveTVChain());
87  newState = kState_WatchingLiveTV;
88  }
89  else if (playingInfo)
90  {
91  int overrecordseconds = gCoreContext->GetNumSetting("RecordOverTime");
92  QDateTime curtime = MythDate::current();
93  QDateTime recendts = playingInfo->GetRecordingEndTime()
94  .addSecs(overrecordseconds);
95 
96  if (playingInfo->IsRecording())
97  {
98  newState = (curtime < recendts) ?
100  }
101  else if (playingInfo->IsVideoDVD())
102  newState = kState_WatchingDVD;
103  else if (playingInfo->IsVideoBD())
104  newState = kState_WatchingBD;
105  else
106  newState = kState_WatchingVideo;
107 
108  newPlaygroup = playingInfo->GetPlaybackGroup();
109  }
110  UnlockPlayingInfo(__FILE__, __LINE__);
111 
112  ChangeState(newState);
113  SetPlayGroup(newPlaygroup);
114 }
115 
122 {
123  bool supported = false;
124  QMutexLocker locker(&deletePlayerLock);
125  if (player)
126  {
127  const VideoOutput *vid = player->GetVideoOutput();
128  if (vid)
129  supported = vid->IsPIPSupported();
130  }
131  return supported;
132 }
133 
140 {
141  bool supported = false;
142  QMutexLocker locker(&deletePlayerLock);
143  if (player)
144  {
145  const VideoOutput *vid = player->GetVideoOutput();
146  if (vid)
147  supported = vid->IsPBPSupported();
148  }
149  return supported;
150 }
151 
152 void PlayerContext::CreatePIPWindow(const QRect &rect, int pos,
153  QWidget *widget)
154 {
155  QString name;
156  if (pos > -1)
157  {
158  pipLocation = pos;
159  name = QString("pip player %1").arg(toString((PIPLocation)pos));
160  }
161  else
162  name = "pip player";
163 
164  if (widget)
165  parentWidget = widget;
166 
167  pipRect = QRect(rect);
168 }
169 
175 {
176  QRect rect = QRect(0, 0, 0, 0);
177  QMutexLocker locker(&deletePlayerLock);
178  if (player)
179  {
180  rect = pipRect;
181 
182  float saspect = (float)rect.width() / (float)rect.height();
183  float vaspect = player->GetVideoAspect();
184 
185  // Calculate new height or width according to relative aspect ratio
186  if (lroundf(saspect * 10) > lroundf(vaspect * 10))
187  {
188  rect.setWidth((int) ceil(rect.width() * (vaspect / saspect)));
189  }
190  else if (lroundf(saspect * 10) < lroundf(vaspect * 10))
191  {
192  rect.setHeight((int) ceil(rect.height() * (saspect / vaspect)));
193  }
194 
195  rect.setHeight(((rect.height() + 7) / 8) * 8);
196  rect.setWidth( ((rect.width() + 7) / 8) * 8);
197  }
198  return rect;
199 }
200 
201 bool PlayerContext::StartPIPPlayer(TV *tv, TVState desiredState)
202 {
203  bool ok = false;
204 
205  if (!useNullVideo && parentWidget)
206  {
207  const QRect rect = pipRect;
208  ok = CreatePlayer(tv, parentWidget, desiredState,
209  true, rect);
210  }
211 
212  if (useNullVideo || !ok)
213  {
214  SetPlayer(nullptr);
215  useNullVideo = true;
216  ok = CreatePlayer(tv, nullptr, desiredState,
217  false);
218  }
219 
220  return ok;
221 }
222 
223 
230 {
231  if (buffer)
232  {
233  buffer->Pause();
234  buffer->WaitForPause();
235  }
236 
237  {
238  QMutexLocker locker(&deletePlayerLock);
239  StopPlaying();
240  }
241 
242  SetPlayer(nullptr);
243 
244  useNullVideo = false;
245  parentWidget = nullptr;
246 }
247 
251 void PlayerContext::ResizePIPWindow(const QRect &rect)
252 {
253  if (!IsPIP())
254  return;
255 
256  QRect tmpRect;
257  if (pipState == kPIPStandAlone)
258  tmpRect = GetStandAlonePIPRect();
259  else
260  tmpRect = QRect(rect);
261 
262  LockDeletePlayer(__FILE__, __LINE__);
263  if (player && player->GetVideoOutput())
264  player->GetVideoOutput()->ResizeDisplayWindow(tmpRect, false);
265  UnlockDeletePlayer(__FILE__, __LINE__);
266 
267  pipRect = QRect(rect);
268 }
269 
270 bool PlayerContext::StartEmbedding(const QRect &embedRect)
271 {
272  bool ret = false;
273  LockDeletePlayer(__FILE__, __LINE__);
274  if (player)
275  {
276  ret = true;
277  player->EmbedInWidget(embedRect);
278  }
279  UnlockDeletePlayer(__FILE__, __LINE__);
280  return ret;
281 }
282 
284 {
285  bool ret = false;
286  LockDeletePlayer(__FILE__, __LINE__);
287  if (player)
288  ret = player->IsEmbedding();
289  UnlockDeletePlayer(__FILE__, __LINE__);
290  return ret;
291 }
292 
294 {
295  LockDeletePlayer(__FILE__, __LINE__);
296  if (player)
298  UnlockDeletePlayer(__FILE__, __LINE__);
299 }
300 
301 bool PlayerContext::HasPlayer(void) const
302 {
303  QMutexLocker locker(&deletePlayerLock);
304  return player;
305 }
306 
308 {
309  QMutexLocker locker(&deletePlayerLock);
310  return player && player->IsErrored();
311 }
312 
314 {
315  QMutexLocker locker(&deletePlayerLock);
316  return player && player->IsErrorRecoverable();
317 }
318 
320 {
321  QMutexLocker locker(&deletePlayerLock);
322  return player && player->IsDecoderErrored();
323 }
324 
326 {
327  QMutexLocker locker(&deletePlayerLock);
328  return player && player->IsPlaying();
329 }
330 
332 {
333  QMutexLocker locker(&deletePlayerLock);
335  {
336  ff_rew_speed = 0;
337  ff_rew_state = 0;
339  return true;
340  }
341  return false;
342 }
343 
345 {
346  QMutexLocker locker(&deletePlayerLock);
347  if (player && (player->GetNextPlaySpeed() != ts_normal) &&
349  {
350  // Speed got changed in player since we are close to the end of file
351  ts_normal = 1.0f;
352  return true;
353  }
354  return false;
355 }
356 
358  bool paddedFields) const
359 {
360  QMutexLocker locker(&deletePlayerLock);
361  if (player)
362  {
363  player->calcSliderPos(info, paddedFields);
364  return true;
365  }
366  return false;
367 }
368 
370 {
371  return recorder && recorder->GetErrorStatus();
372 }
373 
374 bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget,
375  TVState desiredState,
376  bool embed, const QRect &embedbounds,
377  bool muted)
378 {
379  if (HasPlayer())
380  {
381  LOG(VB_GENERAL, LOG_ERR, LOC +
382  "Attempting to setup a player, but it already exists.");
383  return false;
384  }
385 
386  uint playerflags = kDecodeAllowEXT; // allow VDA etc for normal playback
387  playerflags |= muted ? kAudioMuted : kNoFlags;
388  playerflags |= useNullVideo ? kVideoIsNull : kNoFlags;
389  playerflags |= nohardwaredecoders ? kNoFlags : kDecodeAllowGPU;
390 
391  MythPlayer *player = nullptr;
392  if (kState_WatchingBD == desiredState)
393  player = new MythBDPlayer((PlayerFlags)playerflags);
394  else if (kState_WatchingDVD == desiredState)
395  player = new MythDVDPlayer((PlayerFlags)playerflags);
396  else
397  player = new MythPlayer((PlayerFlags)playerflags);
398 
399  QString passthru_device =
400  gCoreContext->GetBoolSetting("PassThruDeviceOverride", false) ?
401  gCoreContext->GetSetting("PassThruOutputDevice") : QString();
402 
403  player->SetPlayerInfo(tv, widget, this);
404  AudioPlayer *audio = player->GetAudio();
405  audio->SetAudioInfo(gCoreContext->GetSetting("AudioOutputDevice"),
406  passthru_device,
407  gCoreContext->GetNumSetting("AudioSampleRate", 44100));
408  audio->SetStretchFactor(ts_normal);
410 
412  0, gCoreContext->GetNumSetting("AudioSyncOffset", 0));
413 
414  player->SetVideoFilters((useNullVideo) ? "onefield" : "");
415 
416  bool isWatchingRecording = (desiredState == kState_WatchingRecording);
417  player->SetWatchingRecording(isWatchingRecording);
418 
419  if (!IsAudioNeeded())
420  audio->SetNoAudio();
421  else
422  {
423  QString subfn = buffer->GetSubtitleFilename();
424  bool isInProgress = (desiredState == kState_WatchingRecording ||
425  desiredState == kState_WatchingLiveTV);
426  if (!subfn.isEmpty() && player->GetSubReader())
427  player->GetSubReader()->LoadExternalSubtitles(subfn, isInProgress);
428  }
429 
430  if (embed && !embedbounds.isNull())
431  player->EmbedInWidget(embedbounds);
432 
433  SetPlayer(player);
434 
435  if (pipState == kPIPOff || pipState == kPBPLeft)
436  {
437  if (IsAudioNeeded())
438  {
439  QString errMsg = audio->ReinitAudio();
440  }
441  }
442  else if (pipState == kPBPRight)
443  player->SetMuted(true);
444 
445  return StartPlaying(-1);
446 }
447 
454 {
455  if (!player)
456  return false;
457 
458  if (!player->StartPlaying())
459  {
460  LOG(VB_GENERAL, LOG_ERR, LOC + "StartPlaying() Failed to start player");
461  // no need to call StopPlaying here as the player context will be deleted
462  // later following the error
463  return false;
464  }
465  maxWait = (maxWait <= 0) ? 20000 : maxWait;
466 #ifdef USING_VALGRIND
467  maxWait = (1<<30);
468 #endif // USING_VALGRIND
469  MythTimer t;
470  t.start();
471 
472  while (!player->IsPlaying(50, true) && (t.elapsed() < maxWait))
473  ReloadTVChain();
474 
475  if (player->IsPlaying())
476  {
477  LOG(VB_PLAYBACK, LOG_INFO, LOC +
478  QString("StartPlaying(): took %1 ms to start player.")
479  .arg(t.elapsed()));
480  return true;
481  }
482  else
483  {
484  LOG(VB_GENERAL, LOG_ERR, LOC + "StartPlaying() Failed to start player");
485  StopPlaying();
486  return false;
487  }
488 }
489 
491 {
492  if (player)
493  player->StopPlaying();
494 }
495 
496 void PlayerContext::UpdateTVChain(const QStringList &data)
497 {
498  QMutexLocker locker(&deletePlayerLock);
499  if (tvchain && player)
500  {
501  tvchain->ReloadAll(data);
502  player->CheckTVChain();
503  }
504 }
505 
507 {
508  if (!tvchain)
509  return false;
510 
511  tvchain->ReloadAll();
512  ProgramInfo *pinfo = tvchain->GetProgramAt(-1);
513  if (pinfo)
514  {
515  SetPlayingInfo(pinfo);
516  delete pinfo;
517  return true;
518  }
519  else
520  {
521  return false;
522  }
523 }
524 
529 {
530  if (!tvchain)
531  return;
532 
533  // Don't store more than kMaxChannelHistory channels. Remove the first item
534  if (prevChan.size() >= kMaxChannelHistory)
535  prevChan.pop_front();
536 
537  // This method builds the stack of previous channels
538  QString curChan = tvchain->GetChannelName(-1);
539  if (prevChan.empty() ||
540  curChan != prevChan[prevChan.size() - 1])
541  {
542  QString chan = curChan;
543  prevChan.push_back(chan);
544  }
545 }
546 
548 {
549  if (prevChan.empty())
550  return QString();
551 
552  QString curChan = tvchain->GetChannelName(-1);
553  if ((curChan == prevChan.back()) && !prevChan.empty())
554  prevChan.pop_back();
555 
556  if (prevChan.empty())
557  return QString();
558 
559  QString chan = prevChan.back();
560  prevChan.pop_back();
561  // add the current channel back to the list, to allow easy flipping between
562  // two channels using PREVCHAN
564  return chan;
565 }
566 
568 {
569  if (prevChan.empty())
570  return QString();
571 
572  QString curChan = tvchain->GetChannelName(-1);
573  QString preChan;
574  if (curChan != prevChan.back() || prevChan.size() < 2)
575  preChan = prevChan.back();
576  else
577  preChan = prevChan[prevChan.size()-2];
578  return preChan;
579 }
580 
581 void PlayerContext::LockPlayingInfo(const char *file, int line) const
582 {
583 #if 0
584  LOG(VB_GENERAL, LOG_DEBUG, QString("LockPlayingInfo(%1,%2)")
585  .arg(file).arg(line));
586 #else
587  Q_UNUSED(file);
588  Q_UNUSED(line);
589 #endif
590  playingInfoLock.lock();
591 }
592 
593 void PlayerContext::UnlockPlayingInfo(const char *file, int line) const
594 {
595 #if 0
596  LOG(VB_GENERAL, LOG_DEBUG, QString("UnlockPlayingInfo(%1,%2)")
597  .arg(file).arg(line));
598 #else
599  Q_UNUSED(file);
600  Q_UNUSED(line);
601 #endif
602  playingInfoLock.unlock();
603 }
604 
610 void PlayerContext::LockDeletePlayer(const char *file, int line) const
611 {
612 #if 0
613  LOG(VB_GENERAL, LOG_DEBUG, QString("LockDeletePlayer(%1,%2)")
614  .arg(file).arg(line));
615 #else
616  Q_UNUSED(file);
617  Q_UNUSED(line);
618 #endif
619  deletePlayerLock.lock();
620 }
621 
625 void PlayerContext::UnlockDeletePlayer(const char *file, int line) const
626 {
627 #if 0
628  LOG(VB_GENERAL, LOG_DEBUG, QString("UnlockDeletePlayer(%1,%2)")
629  .arg(file).arg(line));
630 #else
631  Q_UNUSED(file);
632  Q_UNUSED(line);
633 #endif
634  deletePlayerLock.unlock();
635 }
636 
637 void PlayerContext::LockState(void) const
638 {
639  stateLock.lock();
640 }
641 
643 {
644  stateLock.unlock();
645 }
646 
648 {
649  player->LockOSD();
650 }
651 
652 void PlayerContext::UnlockOSD(void) const
653 {
654  player->UnlockOSD();
655 }
656 
658 {
659  if (!stateLock.tryLock())
660  return true;
661  bool inStateChange = nextState.size() > 0;
662  stateLock.unlock();
663  return inStateChange;
664 }
665 
670 {
671  QMutexLocker locker(&stateLock);
672  nextState.enqueue(newState);
673 }
674 
676 {
677  QMutexLocker locker(&stateLock);
678  return nextState.dequeue();
679 }
680 
685 {
686  QMutexLocker locker(&stateLock);
687  nextState.clear();
688  nextState.push_back(kState_None);
689 }
690 
692 {
693  QMutexLocker locker(&stateLock);
694  return playingState;
695 }
696 
698 {
699  bool loaded = false;
700  LockPlayingInfo(__FILE__, __LINE__);
701  if (playingInfo)
702  {
703  playingInfo->ToMap(infoMap);
704  infoMap["tvstate"] = StateToString(playingState);
705  infoMap["iconpath"] = ChannelUtil::GetIcon(playingInfo->GetChanID());
709  {
710  infoMap["coverartpath"] = VideoMetaDataUtil::GetArtPath(
711  playingInfo->GetPathname(), "Coverart");
712  infoMap["fanartpath"] = VideoMetaDataUtil::GetArtPath(
713  playingInfo->GetPathname(), "Fanart");
714  infoMap["bannerpath"] = VideoMetaDataUtil::GetArtPath(
715  playingInfo->GetPathname(), "Banners");
716  infoMap["screenshotpath"] = VideoMetaDataUtil::GetArtPath(
717  playingInfo->GetPathname(), "Screenshots");
718  }
719  else
720  {
723  infoMap["coverartpath"] =
724  artmap.value(kArtworkCoverart).url;
725  infoMap["fanartpath"] =
726  artmap.value(kArtworkFanart).url;
727  infoMap["bannerpath"] =
728  artmap.value(kArtworkBanner).url;
729  infoMap["screenshotpath"] =
730  artmap.value(kArtworkScreenshot).url;
731  }
732  if (player)
733  player->GetCodecDescription(infoMap);
734 
735  loaded = true;
736  }
737  UnlockPlayingInfo(__FILE__, __LINE__);
738  return loaded;
739 }
740 
742 {
743  bool ret = false;
744  LockPlayingInfo(__FILE__, __LINE__);
745  if (playingInfo)
746  ret = playingInfo->IsSameProgram(p);
747  UnlockPlayingInfo(__FILE__, __LINE__);
748  return ret;
749 }
750 
751 QString PlayerContext::GetFilters(const QString &baseFilters) const
752 {
753  QString filters = baseFilters;
754  QString chanFilters;
755 
757  return baseFilters;
758 
759  LockPlayingInfo(__FILE__, __LINE__);
760  if (playingInfo) // Recordings have this info already.
761  chanFilters = playingInfo->GetChannelPlaybackFilters();
762  UnlockPlayingInfo(__FILE__, __LINE__);
763 
764  if (!chanFilters.isEmpty())
765  {
766  if ((chanFilters[0] != '+'))
767  {
768  filters = chanFilters;
769  }
770  else
771  {
772  if (!filters.isEmpty() && (!filters.endsWith(",")))
773  filters += ",";
774 
775  filters += chanFilters.mid(1);
776  }
777  }
778 
779  LOG(VB_CHANNEL, LOG_INFO, LOC +
780  QString("Output filters for this channel are: '%1'")
781  .arg(filters));
782 
783  return filters;
784 }
785 
786 QString PlayerContext::GetPlayMessage(void) const
787 {
788  QString mesg = QObject::tr("Play");
789  if (ts_normal != 1.0f)
790  {
791  if (ts_normal == 0.5f)
792  mesg += QString(" 1/2x");
793  else if (0.32f < ts_normal && ts_normal < 0.34f)
794  mesg += QString(" 1/3x");
795  else if (ts_normal == 0.25f)
796  mesg += QString(" 1/4x");
797  else if (ts_normal == 0.125f)
798  mesg += QString(" 1/8x");
799  else if (ts_normal == 0.0625f)
800  mesg += QString(" 1/16x");
801  else
802  mesg += QString(" %1x").arg(ts_normal);
803  }
804 
805  return mesg;
806 }
807 
809 {
810  QMutexLocker locker(&deletePlayerLock);
811  if (player)
812  {
813  StopPlaying();
814  delete player;
815  }
816  player = newplayer;
817 }
818 
820 {
821  if (recorder)
822  {
823  delete recorder;
824  recorder = nullptr;
825  }
826 
827  if (rec)
828  {
829  recorder = rec;
831  }
832 }
833 
835 {
836  if (tvchain)
837  {
839  tvchain->DecrRef();
840  tvchain = nullptr;
841  }
842 
843  tvchain = chain;
844 
845  if (tvchain)
846  {
847  QString seed = QString("");
848 
849  if (IsPIP())
850  seed = "PIP";
851 
852  seed += gCoreContext->GetHostName();
853 
855  }
856 }
857 
859 {
860  if (buffer)
861  {
862  delete buffer;
863  buffer = nullptr;
864  }
865 
866  buffer = buf;
867 }
868 
873 {
874  bool ignoreDB = gCoreContext->IsDatabaseIgnored();
875 
876  QMutexLocker locker(&playingInfoLock);
877 
878  if (playingInfo)
879  {
880  if (!ignoreDB)
882  delete playingInfo;
883  playingInfo = nullptr;
884  }
885 
886  if (info)
887  {
888  playingInfo = new ProgramInfo(*info);
889  if (!ignoreDB)
892  }
893 }
894 
895 void PlayerContext::SetPlayGroup(const QString &group)
896 {
897  fftime = PlayGroup::GetSetting(group, "skipahead", 30);
898  rewtime = PlayGroup::GetSetting(group, "skipback", 5);
899  jumptime = PlayGroup::GetSetting(group, "jump", 10);
900  ts_normal = PlayGroup::GetSetting(group, "timestretch", 100) * 0.01f;
901  ts_alt = (ts_normal == 1.0f) ? 1.5f : 1.0f;
902 }
903 
905  const ProgramInfo *pi, PseudoState new_state)
906 {
907  ProgramInfo *old_rec = pseudoLiveTVRec;
908  ProgramInfo *new_rec = nullptr;
909 
910  if (pi)
911  {
912  new_rec = new ProgramInfo(*pi);
913  QString msg = QString("Wants to record: %1 %2 %3 %4")
914  .arg(new_rec->GetTitle()).arg(new_rec->GetChanNum())
916  .arg(new_rec->GetRecordingEndTime(MythDate::ISODate));
917  LOG(VB_PLAYBACK, LOG_INFO, LOC + msg);
918  }
919 
920  pseudoLiveTVRec = new_rec;
921  pseudoLiveTVState = new_state;
922 
923  if (old_rec)
924  {
925  QString msg = QString("Done recording: %1 %2 %3 %4")
926  .arg(old_rec->GetTitle()).arg(old_rec->GetChanNum())
928  .arg(old_rec->GetRecordingEndTime(MythDate::ISODate));
929  LOG(VB_PLAYBACK, LOG_INFO, LOC + msg);
930  delete old_rec;
931  }
932 }
void LockOSD(void)
Definition: mythplayer.h:355
bool IsErrorRecoverable(void) const
Definition: mythplayer.h:208
float GetVideoAspect(void) const
Definition: mythplayer.h:175
void SetStretchFactor(float factor)
void Pause(void)
Pauses the read-ahead thread.
Definition: ringbuffer.cpp:768
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:63
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
PlayerFlags
Definition: mythplayer.h:88
QString GetPreviousChannel(void) const
int ff_rew_speed
Caches value of ff_rew_speeds[ff_rew_index].
PlayerContext(const QString &inUseID=QString("Unknown"))
void ChangeState(TVState newState)
Puts a state change on the nextState queue.
VideoOutput * GetVideoOutput(void)
Definition: mythplayer.h:244
MythDeque< TVState > nextState
QString toString(MarkTypes type)
bool HasPlayer(void) const
int last_cardid
CardID of current/last recorder.
bool HandlePlayerSpeedChangeFFRew(void)
void DestroyChain(void)
long long playingLen
Initial CalculateLength()
void SetAudioInfo(const QString &main_device, const QString &passthru_device, uint samplerate, int bitrate=-1)
Set audio output device parameters.
bool IsPlaying(uint wait_ms=0, bool wait_for=true) const
Definition: mythplayer.cpp:476
void MarkAsInUse(bool inuse, QString usedFor="")
Tracks a recording's in use status, to prevent deletion and to allow the storage scheduler to perform...
void StopEmbedding(void)
bool IsVideoDVD(void) const
Definition: programinfo.h:341
QString GetPlayMessage(void) const
void UnlockPlayingInfo(const char *file, int line) const
virtual bool StartPlaying(void)
ProgramInfo * GetProgramAt(int at) const
Returns program at the desired location.
void LockDeletePlayer(const char *file, int line) const
prevent MythPlayer from being deleted used to ensure player can only be deleted after osd in TV() is ...
QString StateToString(TVState state)
Returns a human readable QString representing a TVState.
Definition: tv.cpp:10
QString GetTitle(void) const
Definition: programinfo.h:355
int pipLocation
Position of PIP on TV screen.
void SetPlayer(MythPlayer *new_player)
void SetRingBuffer(RingBuffer *buf)
void SetNoAudio(void)
Definition: audioplayer.h:51
Watching Recording is the state for when we are watching an in progress recording,...
Definition: tv.h:80
unsigned int uint
Definition: compat.h:140
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString ReinitAudio(void)
bool IsEmbedding(void) const
Watching Pre-recorded is a TV only state for when we are watching a pre-existing recording.
Definition: tv.h:67
void SetRecorder(RemoteEncoder *rec)
bool IsDatabaseIgnored(void) const
/brief Returns true if database is being ignored.
Watching DVD is the state when we are watching a DVD.
Definition: tv.h:73
void SetLength(int len)
Definition: mythplayer.h:152
QString PopPreviousChannel(void)
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:370
TVState
TVState is an enumeration of the states used by TV and TVRec.
Definition: tv.h:50
void LoadExternalSubtitles(const QString &videoFile, bool isInProgress)
void enqueue(T d)
Adds item to the back of the list. O(1).
Definition: mythdeque.h:42
void PushPreviousChannel(void)
most recently selected channel to the previous channel list
QString GetChannelPlaybackFilters(void) const
Definition: programinfo.h:381
MythPlayer * player
static QString GetArtPath(const QString &basename, const QString &type)
float ts_normal
Time stretch speed, 1.0f for normal playback.
void ForceNextStateNone(void)
Removes any pending state changes, and puts kState_None on the queue.
void StopPlaying(void)
MythTimer lastSignalMsgTime
ProgramInfo * pseudoLiveTVRec
bool IsPlayerDecoderErrored(void) const
QString GetInetRef(void) const
Definition: programinfo.h:431
virtual bool IsPBPSupported(void) const
Definition: videooutbase.h:166
void EmbedInWidget(QRect rect)
bool StartPlaying(int maxWait=-1)
Starts player, must be called after StartRecorder().
bool IsPlayerErrored(void) const
This class serves as the base class for all video output methods.
Definition: videooutbase.h:46
Holds information on recordings and videos.
Definition: programinfo.h:66
void SetPlayingInfo(const ProgramInfo *info)
assign programinfo to the context
void ReloadAll(const QStringList &data=QStringList())
QRect GetStandAlonePIPRect(void)
Get PIP more accurate display size for standalone PIP by factoring the aspect ratio of the video.
static const uint kMaxChannelHistory
QString GetChannelName(int pos=-1) const
AudioPlayer * GetAudio(void)
Definition: mythplayer.h:189
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
bool StartEmbedding(const QRect &)
bool GetPlayingInfoMap(InfoMap &infoMap) const
uint GetSecondsInRecording(void) const
Returns length of program/recording in seconds.
static const int kInitFFRWSpeed
1x, default to normal speed
Definition: tv_play.h:1080
bool IsPlayerRecoverable(void) const
TVState DequeueNextState(void)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
bool IsRecording(void) const
Definition: programinfo.h:479
Watching Video is the state when we are watching a video and is not a dvd or BD.
Definition: tv.h:71
void SetPlayGroup(const QString &group)
QString InitializeNewChain(const QString &seed)
Definition: livetvchain.cpp:44
virtual void StopPlaying(void)
QString GetBasename(void) const
Definition: programinfo.h:338
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
T dequeue()
Removes item from front of list and returns a copy. O(1).
Definition: mythdeque.h:32
void CheckTVChain()
QString GetSetting(const QString &key, const QString &defaultval="")
bool IsVideoBD(void) const
Definition: programinfo.h:343
void LockOSD(void) const
unsigned char t
Definition: ParseText.cpp:340
bool IsRecorderErrored(void) const
bool IsAudioNeeded(void) const
void LockPlayingInfo(const char *file, int line) const
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
PseudoState pseudoLiveTVState
void SetPseudoLiveTV(const ProgramInfo *pi, PseudoState new_state)
void UnlockDeletePlayer(const char *file, int line) const
allow player to be deleted.
void LockState(void) const
static QString GetIcon(uint chanid)
Control TV playback.
Definition: tv_play.h:288
QString GetFilters(const QString &baseFilters) const
Watching BD is the state when we are watching a BD.
Definition: tv.h:75
uint GetSeason(void) const
Definition: programinfo.h:360
bool useNullVideo
True iff software scaled PIP should be used.
void UnlockOSD(void)
Definition: mythplayer.h:356
RingBuffer * buffer
virtual void calcSliderPos(osdInfo &info, bool paddedFields=false)
bool IsErrored(void) const
const char * name
Definition: ParseText.cpp:339
virtual void ResizeDisplayWindow(const QRect &, bool)
Resize Display Window.
PIPState pipState
StringDeque prevChan
Previous channels.
ProgramInfo * playingInfo
Currently playing info.
QString GetPlaybackGroup(void) const
Definition: programinfo.h:414
static const uint kSMExitTimeout
Timeout after last Signal Monitor message for ignoring OSD when exiting.
void StopEmbedding(void)
int64_t AdjustAudioTimecodeOffset(int64_t v, int newsync=-9999)
void ResizePIPWindow(void)
bool IsVideoFile(void) const
Definition: programinfo.h:339
TVState playingState
void UnlockOSD(void) const
void WaitForPause(void)
Waits for Pause(void) to take effect.
Definition: ringbuffer.cpp:805
void addMSecs(int ms)
Adds an offset to the last call to start() or restart().
Definition: mythtimer.cpp:145
void SetPlayerInfo(TV *tv, QWidget *widget, PlayerContext *ctx)
bool GetErrorStatus(void)
Definition: remoteencoder.h:77
None State, this is the initial state in both TV and TVRec, it indicates that we are ready to change ...
Definition: tv.h:58
PIPLocation
Definition: videoouttypes.h:19
virtual bool IsPIPSupported(void) const
Definition: videooutbase.h:165
int GetNumSetting(const QString &key, int defaultval=0)
bool AtNormalSpeed(void) const
Definition: mythplayer.h:224
void GetCodecDescription(InfoMap &infoMap)
bool ReloadTVChain(void)
QMutex deletePlayerLock
QString recUsage
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
QMutex playingInfoLock
bool HandlePlayerSpeedChangeEOF(void)
TVState GetState(void) const
bool GetBoolSetting(const QString &key, bool defaultval=false)
bool IsPBPSupported(void) const
Check if PBP is supported for current video renderer running.
QString GetSubtitleFilename(void) const
bool nohardwaredecoders
static int GetSetting(const QString &name, const QString &field, int defval)
Definition: playgroup.cpp:246
bool IsPIP(void) const
int ff_rew_state
0 == normal, +1 == fast forward, -1 == rewind
RemoteEncoder * recorder
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:366
bool InStateChange(void) const
bool IsEmbedding(void)
bool IsPIPSupported(void) const
Check if PIP is supported for current video renderer running.
#define LOC
int GetRecorderNumber(void) const
bool CalcPlayerSliderPosition(osdInfo &info, bool paddedFields=false) const
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:398
int ff_rew_index
Index into ff_rew_speeds for FF and Rewind speeds.
bool IsDecoderErrored(void) const
Definition: mythplayer.h:210
PseudoState
Definition: playercontext.h:40
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:406
RemoteEncoder * recorder
LiveTVChain * tvchain
void SetVideoFilters(const QString &overridefilter)
void SetTVChain(LiveTVChain *chain)
bool StartPIPPlayer(TV *tv, TVState desiredState)
void PIPTeardown(void)
stop player but pause the ringbuffer.
void UpdateTVChain(const QStringList &data=QStringList())
bool SetMuted(bool mute)
Definition: mythplayer.h:411
Implements a file/stream reader/writer.
float GetNextPlaySpeed(void) const
Definition: mythplayer.h:192
void CreatePIPWindow(const QRect &, int pos=-1, QWidget *widget=nullptr)
QWidget * parentWidget
void TeardownPlayer(void)
bool IsPlayerPlaying(void) const
void SetInitialTVState(bool islivetv)
determine initial tv state and playgroup for the recording
ArtworkMap GetArtwork(QString inetref, uint season, bool strict)
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
bool CreatePlayer(TV *tv, QWidget *widget, TVState desiredState, bool embed, const QRect &embedBounds=QRect(), bool muted=false)
QString GetHostName(void)
bool IsSameProgram(const ProgramInfo &p) const
bool IsSameProgram(const ProgramInfo &other) const
Checks whether this is the same program as "other", which may or may not be a repeat or on another ch...
QString GetPathname(void) const
Definition: programinfo.h:337
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
Keeps track of recordings in a current LiveTV instance.
Definition: livetvchain.h:31
void SetWatchingRecording(bool mode)
Definition: mythplayer.cpp:341
void UnlockState(void) const
Default UTC.
Definition: mythdate.h:14
virtual SubtitleReader * GetSubReader(uint=0)
Definition: mythplayer.h:297