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  m_recUsage(inUseID)
31 {
34 }
35 
37 {
39  m_nextState.clear();
40 }
41 
43 {
44  m_ffRewState = 0;
45  m_ffRewIndex = 0;
46  m_ffRewSpeed = 0;
47  m_tsNormal = 1.0F;
48 
49  SetPlayer(nullptr);
50  SetRecorder(nullptr);
51  SetRingBuffer(nullptr);
52  SetTVChain(nullptr);
53  SetPlayingInfo(nullptr);
54 }
55 
61 {
62  TVState newState = kState_None;
63  QString newPlaygroup("Default");
64 
65  LockPlayingInfo(__FILE__, __LINE__);
66  if (islivetv)
67  {
68  SetTVChain(new LiveTVChain());
69  newState = kState_WatchingLiveTV;
70  }
71  else if (m_playingInfo)
72  {
73  int overrecordseconds = gCoreContext->GetNumSetting("RecordOverTime");
74  QDateTime curtime = MythDate::current();
75  QDateTime recendts = m_playingInfo->GetRecordingEndTime()
76  .addSecs(overrecordseconds);
77 
79  {
80  newState = (curtime < recendts) ?
82  }
83  else if (m_playingInfo->IsVideoDVD())
84  newState = kState_WatchingDVD;
85  else if (m_playingInfo->IsVideoBD())
86  newState = kState_WatchingBD;
87  else
88  newState = kState_WatchingVideo;
89 
90  newPlaygroup = m_playingInfo->GetPlaybackGroup();
91  }
92  UnlockPlayingInfo(__FILE__, __LINE__);
93 
94  ChangeState(newState);
95  SetPlayGroup(newPlaygroup);
96 }
97 
104 {
105  bool supported = false;
106  QMutexLocker locker(&m_deletePlayerLock);
107  if (m_player)
108  {
109  const VideoOutput *vid = m_player->GetVideoOutput();
110  if (vid)
111  supported = vid->IsPIPSupported();
112  }
113  return supported;
114 }
115 
122 {
123  bool supported = false;
124  QMutexLocker locker(&m_deletePlayerLock);
125  if (m_player)
126  {
127  const VideoOutput *vid = m_player->GetVideoOutput();
128  if (vid)
129  supported = vid->IsPBPSupported();
130  }
131  return supported;
132 }
133 
134 void PlayerContext::CreatePIPWindow(const QRect &rect, int pos,
135  QWidget *widget)
136 {
137  QString name;
138  if (pos > -1)
139  {
140  m_pipLocation = pos;
141  name = QString("pip player %1").arg(toString((PIPLocation)pos));
142  }
143  else
144  name = "pip player";
145 
146  if (widget)
147  m_parentWidget = widget;
148 
149  m_pipRect = QRect(rect);
150 }
151 
157 {
158  QRect rect = QRect(0, 0, 0, 0);
159  QMutexLocker locker(&m_deletePlayerLock);
160  if (m_player)
161  {
162  rect = m_pipRect;
163 
164  float saspect = (float)rect.width() / (float)rect.height();
165  float vaspect = m_player->GetVideoAspect();
166 
167  // Calculate new height or width according to relative aspect ratio
168  if (lroundf(saspect * 10) > lroundf(vaspect * 10))
169  {
170  rect.setWidth((int) ceil(rect.width() * (vaspect / saspect)));
171  }
172  else if (lroundf(saspect * 10) < lroundf(vaspect * 10))
173  {
174  rect.setHeight((int) ceil(rect.height() * (saspect / vaspect)));
175  }
176 
177  rect.setHeight(((rect.height() + 7) / 8) * 8);
178  rect.setWidth( ((rect.width() + 7) / 8) * 8);
179  }
180  return rect;
181 }
182 
183 bool PlayerContext::StartPIPPlayer(TV *tv, TVState desiredState)
184 {
185  bool ok = false;
186 
188  {
189  const QRect rect = m_pipRect;
190  ok = CreatePlayer(tv, m_parentWidget, desiredState,
191  true, rect);
192  }
193 
194  if (m_useNullVideo || !ok)
195  {
196  SetPlayer(nullptr);
197  m_useNullVideo = true;
198  ok = CreatePlayer(tv, nullptr, desiredState,
199  false);
200  }
201 
202  return ok;
203 }
204 
205 
212 {
213  if (m_buffer)
214  {
215  m_buffer->Pause();
217  }
218 
219  {
220  QMutexLocker locker(&m_deletePlayerLock);
221  StopPlaying();
222  }
223 
224  SetPlayer(nullptr);
225 
226  m_useNullVideo = false;
227  m_parentWidget = nullptr;
228 }
229 
233 void PlayerContext::ResizePIPWindow(const QRect &rect)
234 {
235  if (!IsPIP())
236  return;
237 
238  QRect tmpRect;
239  if (m_pipState == kPIPStandAlone)
240  tmpRect = GetStandAlonePIPRect();
241  else
242  tmpRect = QRect(rect);
243 
244  LockDeletePlayer(__FILE__, __LINE__);
245  if (m_player && m_player->GetVideoOutput())
246  m_player->GetVideoOutput()->ResizeDisplayWindow(tmpRect, false);
247  UnlockDeletePlayer(__FILE__, __LINE__);
248 
249  m_pipRect = QRect(rect);
250 }
251 
252 bool PlayerContext::StartEmbedding(const QRect &embedRect)
253 {
254  bool ret = false;
255  LockDeletePlayer(__FILE__, __LINE__);
256  if (m_player)
257  {
258  ret = true;
259  m_player->EmbedInWidget(embedRect);
260  }
261  UnlockDeletePlayer(__FILE__, __LINE__);
262  return ret;
263 }
264 
266 {
267  bool ret = false;
268  LockDeletePlayer(__FILE__, __LINE__);
269  if (m_player)
270  ret = m_player->IsEmbedding();
271  UnlockDeletePlayer(__FILE__, __LINE__);
272  return ret;
273 }
274 
276 {
277  LockDeletePlayer(__FILE__, __LINE__);
278  if (m_player)
280  UnlockDeletePlayer(__FILE__, __LINE__);
281 }
282 
283 bool PlayerContext::HasPlayer(void) const
284 {
285  QMutexLocker locker(&m_deletePlayerLock);
286  return m_player;
287 }
288 
290 {
291  QMutexLocker locker(&m_deletePlayerLock);
292  return m_player && m_player->IsErrored();
293 }
294 
296 {
297  QMutexLocker locker(&m_deletePlayerLock);
298  return m_player && m_player->IsErrorRecoverable();
299 }
300 
302 {
303  QMutexLocker locker(&m_deletePlayerLock);
304  return m_player && m_player->IsDecoderErrored();
305 }
306 
308 {
309  QMutexLocker locker(&m_deletePlayerLock);
310  return m_player && m_player->IsPlaying();
311 }
312 
314 {
315  QMutexLocker locker(&m_deletePlayerLock);
317  {
318  m_ffRewSpeed = 0;
319  m_ffRewState = 0;
321  return true;
322  }
323  return false;
324 }
325 
327 {
328  QMutexLocker locker(&m_deletePlayerLock);
329  if (m_player && (m_player->GetNextPlaySpeed() != m_tsNormal) &&
331  {
332  // Speed got changed in player since we are close to the end of file
333  m_tsNormal = 1.0F;
334  return true;
335  }
336  return false;
337 }
338 
340  bool paddedFields) const
341 {
342  QMutexLocker locker(&m_deletePlayerLock);
343  if (m_player)
344  {
345  m_player->calcSliderPos(info, paddedFields);
346  return true;
347  }
348  return false;
349 }
350 
352 {
353  return m_recorder && m_recorder->GetErrorStatus();
354 }
355 
356 bool PlayerContext::CreatePlayer(TV *tv, QWidget *widget,
357  TVState desiredState,
358  bool embed, const QRect &embedbounds,
359  bool muted)
360 {
361  if (HasPlayer())
362  {
363  LOG(VB_GENERAL, LOG_ERR, LOC +
364  "Attempting to setup a player, but it already exists.");
365  return false;
366  }
367 
368  uint playerflags = kDecodeAllowEXT; // allow VDA etc for normal playback
369  playerflags |= muted ? kAudioMuted : kNoFlags;
370  playerflags |= m_useNullVideo ? kVideoIsNull : kNoFlags;
371  playerflags |= m_nohardwaredecoders ? kNoFlags : kDecodeAllowGPU;
372 
373  MythPlayer *player = nullptr;
374  if (kState_WatchingBD == desiredState)
375  player = new MythBDPlayer((PlayerFlags)playerflags);
376  else if (kState_WatchingDVD == desiredState)
377  player = new MythDVDPlayer((PlayerFlags)playerflags);
378  else
379  player = new MythPlayer((PlayerFlags)playerflags);
380 
381  QString passthru_device =
382  gCoreContext->GetBoolSetting("PassThruDeviceOverride", false) ?
383  gCoreContext->GetSetting("PassThruOutputDevice") : QString();
384 
385  player->SetPlayerInfo(tv, widget, this);
386  AudioPlayer *audio = player->GetAudio();
387  audio->SetAudioInfo(gCoreContext->GetSetting("AudioOutputDevice"),
388  passthru_device,
389  gCoreContext->GetNumSetting("AudioSampleRate", 44100));
391  player->SetLength(m_playingLen);
392 
394  0, gCoreContext->GetNumSetting("AudioSyncOffset", 0));
395 
396  player->SetVideoFilters((m_useNullVideo) ? "onefield" : "");
397 
398  bool isWatchingRecording = (desiredState == kState_WatchingRecording);
399  player->SetWatchingRecording(isWatchingRecording);
400 
401  if (!IsAudioNeeded())
402  audio->SetNoAudio();
403  else
404  {
405  QString subfn = m_buffer->GetSubtitleFilename();
406  bool isInProgress = (desiredState == kState_WatchingRecording ||
407  desiredState == kState_WatchingLiveTV);
408  if (!subfn.isEmpty() && player->GetSubReader())
409  player->GetSubReader()->LoadExternalSubtitles(subfn, isInProgress);
410  }
411 
412  if (embed && !embedbounds.isNull())
413  player->EmbedInWidget(embedbounds);
414 
415  SetPlayer(player);
416 
417  if (m_pipState == kPIPOff || m_pipState == kPBPLeft)
418  {
419  if (IsAudioNeeded())
420  {
421  // cppcheck-suppress unreadVariable
422  QString errMsg = audio->ReinitAudio();
423  }
424  }
425  else if (m_pipState == kPBPRight)
426  player->SetMuted(true);
427 
428  return StartPlaying(-1);
429 }
430 
437 {
438  if (!m_player)
439  return false;
440 
441  if (!m_player->StartPlaying())
442  {
443  LOG(VB_GENERAL, LOG_ERR, LOC + "StartPlaying() Failed to start player");
444  // no need to call StopPlaying here as the player context will be deleted
445  // later following the error
446  return false;
447  }
448  maxWait = (maxWait <= 0) ? 20000 : maxWait;
449 #ifdef USING_VALGRIND
450  maxWait = (1<<30);
451 #endif // USING_VALGRIND
452  MythTimer t;
453  t.start();
454 
455  while (!m_player->IsPlaying(50, true) && (t.elapsed() < maxWait))
456  ReloadTVChain();
457 
458  if (m_player->IsPlaying())
459  {
460  LOG(VB_PLAYBACK, LOG_INFO, LOC +
461  QString("StartPlaying(): took %1 ms to start player.")
462  .arg(t.elapsed()));
463  return true;
464  }
465  LOG(VB_GENERAL, LOG_ERR, LOC + "StartPlaying() Failed to start player");
466  StopPlaying();
467  return false;
468 }
469 
471 {
472  if (m_player)
474 }
475 
476 void PlayerContext::UpdateTVChain(const QStringList &data)
477 {
478  QMutexLocker locker(&m_deletePlayerLock);
479  if (m_tvchain && m_player)
480  {
481  m_tvchain->ReloadAll(data);
483  }
484 }
485 
487 {
488  if (!m_tvchain)
489  return false;
490 
491  m_tvchain->ReloadAll();
492  ProgramInfo *pinfo = m_tvchain->GetProgramAt(-1);
493  if (pinfo)
494  {
495  SetPlayingInfo(pinfo);
496  delete pinfo;
497  return true;
498  }
499  return false;
500 }
501 
506 {
507  if (!m_tvchain)
508  return;
509 
510  // Don't store more than kMaxChannelHistory channels. Remove the first item
511  if (m_prevChan.size() >= kMaxChannelHistory)
512  m_prevChan.pop_front();
513 
514  // This method builds the stack of previous channels
515  QString curChan = m_tvchain->GetChannelName(-1);
516  if (m_prevChan.empty() ||
517  curChan != m_prevChan[m_prevChan.size() - 1])
518  {
519  const QString& chan = curChan;
520  m_prevChan.push_back(chan);
521  }
522 }
523 
525 {
526  if (m_prevChan.empty())
527  return QString();
528 
529  QString curChan = m_tvchain->GetChannelName(-1);
530  if ((curChan == m_prevChan.back()) && !m_prevChan.empty())
531  m_prevChan.pop_back();
532 
533  if (m_prevChan.empty())
534  return QString();
535 
536  QString chan = m_prevChan.back();
537  m_prevChan.pop_back();
538  // add the current channel back to the list, to allow easy flipping between
539  // two channels using PREVCHAN
541  return chan;
542 }
543 
545 {
546  if (m_prevChan.empty())
547  return QString();
548 
549  QString curChan = m_tvchain->GetChannelName(-1);
550  QString preChan;
551  if (curChan != m_prevChan.back() || m_prevChan.size() < 2)
552  preChan = m_prevChan.back();
553  else
554  preChan = m_prevChan[m_prevChan.size()-2];
555  return preChan;
556 }
557 
558 void PlayerContext::LockPlayingInfo(const char *file, int line) const
559 {
560 #if 0
561  LOG(VB_GENERAL, LOG_DEBUG, QString("LockPlayingInfo(%1,%2)")
562  .arg(file).arg(line));
563 #else
564  Q_UNUSED(file);
565  Q_UNUSED(line);
566 #endif
567  m_playingInfoLock.lock();
568 }
569 
570 void PlayerContext::UnlockPlayingInfo(const char *file, int line) const
571 {
572 #if 0
573  LOG(VB_GENERAL, LOG_DEBUG, QString("UnlockPlayingInfo(%1,%2)")
574  .arg(file).arg(line));
575 #else
576  Q_UNUSED(file);
577  Q_UNUSED(line);
578 #endif
579  m_playingInfoLock.unlock();
580 }
581 
587 void PlayerContext::LockDeletePlayer(const char *file, int line) const
588 {
589 #if 0
590  LOG(VB_GENERAL, LOG_DEBUG, QString("LockDeletePlayer(%1,%2)")
591  .arg(file).arg(line));
592 #else
593  Q_UNUSED(file);
594  Q_UNUSED(line);
595 #endif
596  m_deletePlayerLock.lock();
597 }
598 
602 void PlayerContext::UnlockDeletePlayer(const char *file, int line) const
603 {
604 #if 0
605  LOG(VB_GENERAL, LOG_DEBUG, QString("UnlockDeletePlayer(%1,%2)")
606  .arg(file).arg(line));
607 #else
608  Q_UNUSED(file);
609  Q_UNUSED(line);
610 #endif
611  m_deletePlayerLock.unlock();
612 }
613 
614 void PlayerContext::LockState(void) const
615 {
616  m_stateLock.lock();
617 }
618 
620 {
621  m_stateLock.unlock();
622 }
623 
625 {
626  m_player->LockOSD();
627 }
628 
629 void PlayerContext::UnlockOSD(void) const
630 {
631  m_player->UnlockOSD();
632 }
633 
635 {
636  if (!m_stateLock.tryLock())
637  return true;
638  bool inStateChange = !m_nextState.empty();
639  m_stateLock.unlock();
640  return inStateChange;
641 }
642 
647 {
648  QMutexLocker locker(&m_stateLock);
649  m_nextState.enqueue(newState);
650 }
651 
653 {
654  QMutexLocker locker(&m_stateLock);
655  return m_nextState.dequeue();
656 }
657 
662 {
663  QMutexLocker locker(&m_stateLock);
664  m_nextState.clear();
665  m_nextState.push_back(kState_None);
666 }
667 
669 {
670  QMutexLocker locker(&m_stateLock);
671  return m_playingState;
672 }
673 
675 {
676  bool loaded = false;
677  LockPlayingInfo(__FILE__, __LINE__);
678  if (m_playingInfo)
679  {
680  m_playingInfo->ToMap(infoMap);
681  infoMap["tvstate"] = StateToString(m_playingState);
682  infoMap["iconpath"] = ChannelUtil::GetIcon(m_playingInfo->GetChanID());
686  {
687  infoMap["coverartpath"] = VideoMetaDataUtil::GetArtPath(
688  m_playingInfo->GetPathname(), "Coverart");
689  infoMap["fanartpath"] = VideoMetaDataUtil::GetArtPath(
690  m_playingInfo->GetPathname(), "Fanart");
691  infoMap["bannerpath"] = VideoMetaDataUtil::GetArtPath(
692  m_playingInfo->GetPathname(), "Banners");
693  infoMap["screenshotpath"] = VideoMetaDataUtil::GetArtPath(
694  m_playingInfo->GetPathname(), "Screenshots");
695  }
696  else
697  {
700  infoMap["coverartpath"] =
701  artmap.value(kArtworkCoverart).url;
702  infoMap["fanartpath"] =
703  artmap.value(kArtworkFanart).url;
704  infoMap["bannerpath"] =
705  artmap.value(kArtworkBanner).url;
706  infoMap["screenshotpath"] =
707  artmap.value(kArtworkScreenshot).url;
708  }
709  if (m_player)
710  m_player->GetCodecDescription(infoMap);
711 
712  loaded = true;
713  }
714  UnlockPlayingInfo(__FILE__, __LINE__);
715  return loaded;
716 }
717 
719 {
720  bool ret = false;
721  LockPlayingInfo(__FILE__, __LINE__);
722  if (m_playingInfo)
723  ret = m_playingInfo->IsSameProgram(p);
724  UnlockPlayingInfo(__FILE__, __LINE__);
725  return ret;
726 }
727 
728 QString PlayerContext::GetFilters(const QString &baseFilters) const
729 {
730  QString filters = baseFilters;
731  QString chanFilters;
732 
734  return baseFilters;
735 
736  LockPlayingInfo(__FILE__, __LINE__);
737  if (m_playingInfo) // Recordings have this info already.
738  chanFilters = m_playingInfo->GetChannelPlaybackFilters();
739  UnlockPlayingInfo(__FILE__, __LINE__);
740 
741  if (!chanFilters.isEmpty())
742  {
743  if ((chanFilters[0] != '+'))
744  {
745  filters = chanFilters;
746  }
747  else
748  {
749  if (!filters.isEmpty() && (!filters.endsWith(",")))
750  filters += ",";
751 
752  filters += chanFilters.mid(1);
753  }
754  }
755 
756  LOG(VB_CHANNEL, LOG_INFO, LOC +
757  QString("Output filters for this channel are: '%1'")
758  .arg(filters));
759 
760  return filters;
761 }
762 
763 QString PlayerContext::GetPlayMessage(void) const
764 {
765  QString mesg = QObject::tr("Play");
766  if (m_tsNormal != 1.0F)
767  {
768  if (m_tsNormal == 0.5F)
769  mesg += QString(" 1/2x");
770  else if (0.32F < m_tsNormal && m_tsNormal < 0.34F)
771  mesg += QString(" 1/3x");
772  else if (m_tsNormal == 0.25F)
773  mesg += QString(" 1/4x");
774  else if (m_tsNormal == 0.125F)
775  mesg += QString(" 1/8x");
776  else if (m_tsNormal == 0.0625F)
777  mesg += QString(" 1/16x");
778  else
779  mesg += QString(" %1x").arg(m_tsNormal);
780  }
781 
782  return mesg;
783 }
784 
786 {
787  QMutexLocker locker(&m_deletePlayerLock);
788  if (m_player)
789  {
790  StopPlaying();
791  delete m_player;
792  }
793  m_player = newplayer;
794 }
795 
797 {
798  if (m_recorder)
799  {
800  delete m_recorder;
801  m_recorder = nullptr;
802  }
803 
804  if (rec)
805  {
806  m_recorder = rec;
808  }
809 }
810 
812 {
813  if (m_tvchain)
814  {
816  m_tvchain->DecrRef();
817  m_tvchain = nullptr;
818  }
819 
820  m_tvchain = chain;
821 
822  if (m_tvchain)
823  {
824 #if 0
825  QString seed = QString("");
826 
827  if (IsPIP())
828  seed = "PIP";
829 
830  seed += gCoreContext->GetHostName();
831 #endif
833  }
834 }
835 
837 {
838  if (m_buffer)
839  {
840  delete m_buffer;
841  m_buffer = nullptr;
842  }
843 
844  m_buffer = buf;
845 }
846 
851 {
852  bool ignoreDB = gCoreContext->IsDatabaseIgnored();
853 
854  QMutexLocker locker(&m_playingInfoLock);
855 
856  if (m_playingInfo)
857  {
858  if (!ignoreDB)
860  delete m_playingInfo;
861  m_playingInfo = nullptr;
862  }
863 
864  if (info)
865  {
866  m_playingInfo = new ProgramInfo(*info);
867  if (!ignoreDB)
870  }
871 }
872 
873 void PlayerContext::SetPlayGroup(const QString &group)
874 {
875  m_fftime = PlayGroup::GetSetting(group, "skipahead", 30);
876  m_rewtime = PlayGroup::GetSetting(group, "skipback", 5);
877  m_jumptime = PlayGroup::GetSetting(group, "jump", 10);
878  m_tsNormal = PlayGroup::GetSetting(group, "timestretch", 100) * 0.01F;
879  m_tsAlt = (m_tsNormal == 1.0F) ? 1.5F : 1.0F;
880 }
881 
883  const ProgramInfo *pi, PseudoState new_state)
884 {
885  ProgramInfo *old_rec = m_pseudoLiveTVRec;
886  ProgramInfo *new_rec = nullptr;
887 
888  if (pi)
889  {
890  new_rec = new ProgramInfo(*pi);
891  QString msg = QString("Wants to record: %1 %2 %3 %4")
892  .arg(new_rec->GetTitle()).arg(new_rec->GetChanNum())
894  .arg(new_rec->GetRecordingEndTime(MythDate::ISODate));
895  LOG(VB_PLAYBACK, LOG_INFO, LOC + msg);
896  }
897 
898  m_pseudoLiveTVRec = new_rec;
899  m_pseudoLiveTVState = new_state;
900 
901  if (old_rec)
902  {
903  QString msg = QString("Done recording: %1 %2 %3 %4")
904  .arg(old_rec->GetTitle()).arg(old_rec->GetChanNum())
906  .arg(old_rec->GetRecordingEndTime(MythDate::ISODate));
907  LOG(VB_PLAYBACK, LOG_INFO, LOC + msg);
908  delete old_rec;
909  }
910 }
void LockOSD(void)
Definition: mythplayer.h:355
bool IsErrorRecoverable(void) const
Definition: mythplayer.h:208
bool m_nohardwaredecoders
long long m_playingLen
Initial CalculateLength()
int m_ffRewState
0 == normal, +1 == fast forward, -1 == rewind
float GetVideoAspect(void) const
Definition: mythplayer.h:175
void SetStretchFactor(float factor)
void Pause(void)
Pauses the read-ahead thread.
Definition: ringbuffer.cpp:733
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
MythPlayer * m_player
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
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
PIPState m_pipState
QString toString(MarkTypes type)
TVState m_playingState
int m_ffRewIndex
Index into m_ffRewSpeeds for FF and Rewind speeds.
bool HasPlayer(void) const
bool IsPlaying(uint wait_in_msec=0, bool wait_for=true) const
Definition: mythplayer.cpp:478
bool HandlePlayerSpeedChangeFFRew(void)
void DestroyChain(void)
void StopEmbedding(void)
RingBuffer * m_buffer
bool IsVideoDVD(void) const
Definition: programinfo.h:339
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
void SetAudioInfo(const QString &main_device, const QString &passthru_device, uint samplerate, int codec_profile=-1)
Set audio output device parameters.
QString GetTitle(void) const
Definition: programinfo.h:353
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 MarkAsInUse(bool inuse, const QString &usedFor="")
Tracks a recording's in use status, to prevent deletion and to allow the storage scheduler to perform...
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:368
TVState
TVState is an enumeration of the states used by TV and TVRec.
Definition: tv.h:50
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:379
void ForceNextStateNone(void)
Removes any pending state changes, and puts kState_None on the queue.
void StopPlaying(void)
StringDeque m_prevChan
Previous channels.
bool IsPlayerDecoderErrored(void) const
QString GetInetRef(void) const
Definition: programinfo.h:429
QWidget * m_parentWidget
virtual bool IsPBPSupported(void) const
Definition: videooutbase.h:166
PseudoState m_pseudoLiveTVState
void EmbedInWidget(QRect rect)
bool StartPlaying(int maxWait=-1)
Starts player, must be called after StartRecorder().
bool IsPlayerErrored(void) const
ProgramInfo * m_playingInfo
Currently playing info.
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
void SetPlayer(MythPlayer *newplayer)
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:1066
bool IsPlayerRecoverable(void) const
TVState DequeueNextState(void)
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
bool IsRecording(void) const
Definition: programinfo.h:477
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:41
virtual void StopPlaying(void)
QString GetBasename(void) const
Definition: programinfo.h:336
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:341
void LockOSD(void) const
unsigned char t
Definition: ParseText.cpp:329
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.
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
int m_lastCardid
CardID of current/last recorder.
static QString GetIcon(uint chanid)
Control TV playback.
Definition: tv_play.h:284
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:358
void UnlockOSD(void)
Definition: mythplayer.h:356
virtual void calcSliderPos(osdInfo &info, bool paddedFields=false)
bool IsErrored(void) const
const char * name
Definition: ParseText.cpp:328
virtual void ResizeDisplayWindow(const QRect &, bool)
Resize Display Window.
QMutex m_deletePlayerLock
bool m_useNullVideo
True iff software scaled PIP should be used.
QString GetPlaybackGroup(void) const
Definition: programinfo.h:412
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)
RemoteEncoder * m_recorder
bool IsVideoFile(void) const
Definition: programinfo.h:337
LiveTVChain * m_tvchain
ProgramInfo * m_pseudoLiveTVRec
void UnlockOSD(void) const
void WaitForPause(void)
Waits for Pause(void) to take effect.
Definition: ringbuffer.cpp:770
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:78
int m_ffRewSpeed
Caches value of m_ffRewSpeeds[m_ffRewIndex].
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
void LoadExternalSubtitles(const QString &subtitleFileName, bool isInProgress)
int m_pipLocation
Position of PIP on TV screen.
int GetNumSetting(const QString &key, int defaultval=0)
bool AtNormalSpeed(void) const
Definition: mythplayer.h:224
void GetCodecDescription(InfoMap &infoMap)
bool ReloadTVChain(void)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
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
static int GetSetting(const QString &name, const QString &field, int defval)
Definition: playgroup.cpp:246
bool IsPIP(void) const
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:364
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
MythTimer m_lastSignalMsgTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:396
bool IsDecoderErrored(void) const
Definition: mythplayer.h:210
PseudoState
Definition: playercontext.h:39
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:404
QString m_recUsage
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.
QMutex m_stateLock
float GetNextPlaySpeed(void) const
Definition: mythplayer.h:192
void CreatePIPWindow(const QRect &, int pos=-1, QWidget *widget=nullptr)
void TeardownPlayer(void)
bool IsPlayerPlaying(void) const
MythDeque< TVState > m_nextState
void SetInitialTVState(bool islivetv)
determine initial tv state and playgroup for the recording
float m_tsNormal
Time stretch speed, 1.0F for normal playback.
QMultiMap< VideoArtworkType, ArtworkInfo > ArtworkMap
bool CreatePlayer(TV *tv, QWidget *widget, TVState desiredState, bool embed, const QRect &embedBounds=QRect(), bool muted=false)
static QString GetArtPath(const QString &pathname, const QString &type)
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:335
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:343
void UnlockState(void) const
Default UTC.
Definition: mythdate.h:14
QMutex m_playingInfoLock
ArtworkMap GetArtwork(const QString &inetref, uint season, bool strict)
virtual SubtitleReader * GetSubReader(uint=0)
Definition: mythplayer.h:297