MythTV  master
tv_play.cpp
Go to the documentation of this file.
1 // Std
2 #include <algorithm>
3 #include <chrono>
4 #include <cmath>
5 #include <cstdarg>
6 #include <cstdint>
7 #include <cstdlib>
8 #include <thread>
9 
10 // Qt
11 #include <QApplication>
12 #include <QDomDocument>
13 #include <QDomElement>
14 #include <QDomNode>
15 #include <QEvent>
16 #include <QFile>
17 #include <QKeyEvent>
18 #include <QRegularExpression>
19 #include <QRunnable>
20 #include <QTimerEvent>
21 #include <utility>
22 
23 #include "libmythbase/mythconfig.h"
24 
25 // libmythbase
26 #include "libmythbase/compat.h"
27 #include "libmythbase/lcddevice.h"
31 #include "libmythbase/mythdate.h"
32 #include "libmythbase/mythdb.h"
33 #include "libmythbase/mythdirs.h"
35 #include "libmythbase/mythmedia.h"
39 #include "libmythbase/remoteutil.h"
41 #include "libmythbase/stringutil.h"
42 
43 // libmythui
49 #include "libmythui/mythuihelper.h"
51 
52 // libmythtv
53 #include "Bluray/mythbdbuffer.h"
54 #include "Bluray/mythbdplayer.h"
55 #include "DVD/mythdvdbuffer.h"
56 #include "DVD/mythdvdplayer.h"
57 #include "cardutil.h"
58 #include "channelutil.h"
60 #include "io/mythmediabuffer.h"
61 #include "jobqueue.h"
62 #include "livetvchain.h"
63 #include "mythplayerui.h"
64 #include "mythsystemevent.h"
65 #include "mythtvactionutils.h"
66 #include "playercontext.h"
67 #include "playgroup.h"
68 #include "recordinginfo.h"
69 #include "recordingrule.h"
70 #include "remoteencoder.h"
71 #include "signalmonitorvalue.h"
72 #include "sourceutil.h"
73 #include "tv_play.h"
74 #include "tv_play_win.h"
75 #include "tvremoteutil.h"
76 #include "videometadatautil.h"
77 
78 #define DEBUG_CHANNEL_PREFIX 0
79 #define DEBUG_ACTIONS 0
81 #define LOC QString("TV::%1(): ").arg(__func__)
82 
83 static int comp_originalAirDate_rev(const ProgramInfo *a, const ProgramInfo *b)
84 {
85  QDate dt1 = (a->GetOriginalAirDate().isValid()) ?
86  a->GetOriginalAirDate() : a->GetScheduledStartTime().date();
87  QDate dt2 = (b->GetOriginalAirDate().isValid()) ?
88  b->GetOriginalAirDate() : b->GetScheduledStartTime().date();
89 
90  if (dt1 == dt2)
91  return (a->GetRecordingStartTime() >
92  b->GetRecordingStartTime() ? 1 : -1);
93  return (dt1 > dt2 ? 1 : -1);
94 }
95 
96 static int comp_season_rev(const ProgramInfo *a, const ProgramInfo *b)
97 {
98  if (a->GetSeason() == 0 || b->GetSeason() == 0)
99  return comp_originalAirDate_rev(a, b);
100  if (a->GetSeason() != b->GetSeason())
101  return (a->GetSeason() > b->GetSeason() ? 1 : -1);
102  if (a->GetEpisode() == 0 && b->GetEpisode() == 0)
103  return comp_originalAirDate_rev(a, b);
104  return (a->GetEpisode() > b->GetEpisode() ? 1 : -1);
105 }
106 
107 static bool comp_title(const ProgramInfo *a, const ProgramInfo *b)
108 {
110  if (cmp != 0)
111  return cmp < 0;
112  return comp_season_rev(a, b) < 0;
113 }
114 
119 {
120  int count = 0;
121 
122  MSqlQuery query(MSqlQuery::InitCon());
123  query.prepare("SELECT COUNT(cardid) FROM capturecard;");
124  if (query.exec() && query.isActive() && query.size() && query.next())
125  count = query.value(0).toInt();
126 
127  LOG(VB_RECORD, LOG_INFO,
128  "ConfiguredTunerCards() = " + QString::number(count));
129 
130  return count;
131 }
132 
140 TV* TV::AcquireRelease(int& RefCount, bool Acquire, bool Create /*=false*/)
141 {
142  static QMutex s_lock;
143  static TV* s_tv = nullptr;
144  QMutexLocker locker(&s_lock);
145 
146  if (Acquire)
147  {
148  if (!s_tv && Create)
149  s_tv = new TV(GetMythMainWindow());
150  else if (s_tv)
151  s_tv->IncrRef();
152  }
153  else
154  {
155  if (!s_tv)
156  LOG(VB_GENERAL, LOG_ERR, LOC + "Ref count error");
157  else
158  if (s_tv->DecrRef() == 0)
159  s_tv = nullptr;
160  }
161 
162  if (s_tv)
163  RefCount = s_tv->m_referenceCount;
164  else
165  RefCount = 0;
166  return s_tv;
167 }
168 
174 {
175  bool result = false;
176  int dummy = 0;
177  TV* tv = AcquireRelease(dummy, true);
178  if (tv)
179  {
180  result = true;
181  AcquireRelease(dummy, false);
182  }
183  return result;
184 }
185 
194 {
195  return &m_playerContext;
196 }
197 
198 bool TV::CreatePlayer(TVState State, bool Muted)
199 {
201  {
202  LOG(VB_GENERAL, LOG_ERR, LOC + "Already have a player");
203  return false;
204  }
205 
206  uint playerflags = kDecodeAllowGPU;
207  playerflags |= Muted ? kAudioMuted : kNoFlags;
208  auto flags = static_cast<PlayerFlags>(playerflags);
209 
210  MythPlayerUI *player = nullptr;
211  if (kState_WatchingBD == State)
212  player = new MythBDPlayer(m_mainWindow, this, &m_playerContext, flags);
213  else if (kState_WatchingDVD == State)
214  player = new MythDVDPlayer(m_mainWindow, this, &m_playerContext, flags);
215  else
216  player = new MythPlayerUI(m_mainWindow, this, &m_playerContext, flags);
217 
219 
220  bool isWatchingRecording = (State == kState_WatchingRecording);
221  player->SetWatchingRecording(isWatchingRecording);
222 
223  m_playerContext.SetPlayer(player);
224  emit InitialisePlayerState();
225  m_player = player;
226  return StartPlaying(-1ms);
227 }
228 
234 bool TV::StartPlaying(std::chrono::milliseconds MaxWait)
235 {
236  if (!m_player)
237  return false;
238 
239  if (!m_player->StartPlaying())
240  {
241  LOG(VB_GENERAL, LOG_ERR, LOC + "StartPlaying() Failed to start player");
242  // no need to call StopPlaying here as the player context will be deleted
243  // later following the error
244  return false;
245  }
246  MaxWait = (MaxWait <= 0ms) ? 20s : MaxWait;
247 #if CONFIG_VALGRIND
248  MaxWait = std::chrono::milliseconds::max();
249 #endif // CONFIG_VALGRIND
250  MythTimer t;
251  t.start();
252 
253  while (!m_player->IsPlaying(50ms, true) && (t.elapsed() < MaxWait))
255 
256  if (m_player->IsPlaying())
257  {
258  LOG(VB_PLAYBACK, LOG_INFO, LOC +
259  QString("StartPlaying(): took %1 ms to start player.")
260  .arg(t.elapsed().count()));
261  return true;
262  }
263  LOG(VB_GENERAL, LOG_ERR, LOC + "StartPlaying() Failed to start player");
265  return false;
266 }
267 
269 {
271  PrepareToExitPlayer(__LINE__);
272  SetExitPlayer(true, true);
275 }
276 
287 bool TV::StartTV(ProgramInfo* TVRec, uint Flags, const ChannelInfoList& Selection)
288 {
289  int refs = 0;
290  TV* tv = AcquireRelease(refs, true, true);
291  // handle existing TV object atomically
292  if (refs > 1)
293  {
294  AcquireRelease(refs, false);
295  LOG(VB_GENERAL, LOG_WARNING, LOC + "Already have a TV object.");
297  return false;
298  }
299 
300  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- begin");
301  bool inPlaylist = (Flags & kStartTVInPlayList) != 0U;
302  bool initByNetworkCommand = (Flags & kStartTVByNetworkCommand) != 0U;
303  bool quitAll = false;
304  bool showDialogs = true;
305  bool playCompleted = false;
306  ProgramInfo *curProgram = nullptr;
307  bool startSysEventSent = false;
308  bool startLivetvEventSent = false;
309 
310  if (TVRec)
311  {
312  curProgram = new ProgramInfo(*TVRec);
313  curProgram->SetIgnoreBookmark((Flags & kStartTVIgnoreBookmark) != 0U);
314  curProgram->SetIgnoreProgStart((Flags & kStartTVIgnoreProgStart) != 0U);
315  curProgram->SetIgnoreLastPlayPos((Flags & kStartTVIgnoreLastPlayPos) != 0U);
316  }
317 
318  // Initialize TV
319  if (!tv->Init())
320  {
321  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed initializing TV");
322  AcquireRelease(refs, false);
323  delete curProgram;
325  return false;
326  }
327 
328  if (!lastProgramStringList.empty())
329  {
331  if (pginfo.HasPathname() || pginfo.GetChanID())
332  tv->SetLastProgram(&pginfo);
333  }
334 
335  // Notify others that we are about to play
337 
338  QString playerError;
339  while (!quitAll)
340  {
341  if (curProgram)
342  {
343  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "tv->Playback() -- begin");
344  if (!tv->Playback(*curProgram))
345  {
346  quitAll = true;
347  }
348  else if (!startSysEventSent)
349  {
350  startSysEventSent = true;
351  SendMythSystemPlayEvent("PLAY_STARTED", curProgram);
352  }
353 
354  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "tv->Playback() -- end");
355  }
356  else if (RemoteGetFreeRecorderCount())
357  {
358  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "tv->LiveTV() -- begin");
359  if (!tv->LiveTV(showDialogs, Selection))
360  {
361  tv->SetExitPlayer(true, true);
362  quitAll = true;
363  }
364  else if (!startSysEventSent)
365  {
366  startSysEventSent = true;
367  startLivetvEventSent = true;
368  gCoreContext->SendSystemEvent("LIVETV_STARTED");
369  }
370 
371  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "tv->LiveTV() -- end");
372  }
373  else
374  {
375  if (!ConfiguredTunerCards())
376  LOG(VB_GENERAL, LOG_ERR, LOC + "No tuners configured");
377  else
378  LOG(VB_GENERAL, LOG_ERR, LOC + "No tuners free for live tv");
379  quitAll = true;
380  continue;
381  }
382 
383  tv->SetInPlayList(inPlaylist);
384  tv->setUnderNetworkControl(initByNetworkCommand);
385 
387 
388  // Process Events
389  LOG(VB_GENERAL, LOG_INFO, LOC + "Entering main playback loop.");
390  tv->PlaybackLoop();
391  LOG(VB_GENERAL, LOG_INFO, LOC + "Exiting main playback loop.");
392 
393  if (tv->GetJumpToProgram())
394  {
395  ProgramInfo *nextProgram = tv->GetLastProgram();
396 
397  tv->SetLastProgram(curProgram);
398  delete curProgram;
399  curProgram = nextProgram;
400 
401  SendMythSystemPlayEvent("PLAY_CHANGED", curProgram);
402  continue;
403  }
404 
405  tv->GetPlayerReadLock();
406  PlayerContext* context = tv->GetPlayerContext();
407  quitAll = tv->m_wantsToQuit || (context->m_errored);
408  context->LockDeletePlayer(__FILE__, __LINE__);
409  if (context->m_player && context->m_player->IsErrored())
410  playerError = context->m_player->GetError();
411  context->UnlockDeletePlayer(__FILE__, __LINE__);
412  tv->ReturnPlayerLock();
413  quitAll |= !playerError.isEmpty();
414  }
415 
416  QCoreApplication::processEvents();
417 
418  // check if the show has reached the end.
419  if (TVRec && tv->GetEndOfRecording())
420  playCompleted = true;
421 
422  bool allowrerecord = tv->GetAllowRerecord();
423  bool deleterecording = tv->m_requestDelete;
424  AcquireRelease(refs, false);
427 
428  if (curProgram)
429  {
430  if (startSysEventSent)
431  SendMythSystemPlayEvent("PLAY_STOPPED", curProgram);
432 
433  if (deleterecording)
434  {
435  QStringList list;
436  list.push_back(QString::number(curProgram->GetRecordingID()));
437  list.push_back("0"); // do not force delete
438  list.push_back(allowrerecord ? "1" : "0");
439  MythEvent me("LOCAL_PBB_DELETE_RECORDINGS", list);
440  gCoreContext->dispatch(me);
441  }
442  else if (curProgram->IsRecording())
443  {
444  lastProgramStringList.clear();
445  curProgram->ToStringList(lastProgramStringList);
446  }
447 
448  delete curProgram;
449  }
450  else if (startSysEventSent)
451  {
452  gCoreContext->SendSystemEvent("PLAY_STOPPED");
453  }
454 
455  if (!playerError.isEmpty())
456  {
457  MythScreenStack *ss = GetMythMainWindow()->GetStack("popup stack");
458  auto *dlg = new MythConfirmationDialog(ss, playerError, false);
459  if (!dlg->Create())
460  delete dlg;
461  else
462  ss->AddScreen(dlg);
463  }
464 
465  if (startLivetvEventSent)
466  gCoreContext->SendSystemEvent("LIVETV_ENDED");
467 
468  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end");
469 
470  return playCompleted;
471 }
472 
477 void TV::SetFuncPtr(const char* Name, void* Pointer)
478 {
479  QString name(Name);
480  if (name == "playbackbox")
481  RunPlaybackBoxPtr = reinterpret_cast<EMBEDRETURNVOID>(Pointer);
482  else if (name == "viewscheduled")
483  RunViewScheduledPtr = reinterpret_cast<EMBEDRETURNVOID>(Pointer);
484  else if (name == "programguide")
485  RunProgramGuidePtr = reinterpret_cast<EMBEDRETURNVOIDEPG>(Pointer);
486  else if (name == "programfinder")
487  RunProgramFinderPtr = reinterpret_cast<EMBEDRETURNVOIDFINDER>(Pointer);
488  else if (name == "scheduleeditor")
489  RunScheduleEditorPtr = reinterpret_cast<EMBEDRETURNVOIDSCHEDIT>(Pointer);
490  else if (name == "programlist")
491  RunProgramListPtr = reinterpret_cast<EMBEDRETURNVOIDPROGLIST>(Pointer);
492 }
493 
495 {
496  REG_KEY("TV Frontend", ACTION_PLAYBACK, QT_TRANSLATE_NOOP("MythControls",
497  "Play Program"), "P,Media Play");
498  REG_KEY("TV Frontend", ACTION_STOP, QT_TRANSLATE_NOOP("MythControls",
499  "Stop Program"), "");
500  REG_KEY("TV Frontend", ACTION_TOGGLERECORD, QT_TRANSLATE_NOOP("MythControls",
501  "Toggle recording status of current program"), "R");
502  REG_KEY("TV Frontend", ACTION_DAYLEFT, QT_TRANSLATE_NOOP("MythControls",
503  "Page the program guide back one day"), "Home,Media Previous");
504  REG_KEY("TV Frontend", ACTION_DAYRIGHT, QT_TRANSLATE_NOOP("MythControls",
505  "Page the program guide forward one day"), "End,Media Next");
506  REG_KEY("TV Frontend", ACTION_PAGELEFT, QT_TRANSLATE_NOOP("MythControls",
507  "Page the program guide left"), ",,<,Ctrl+B,Media Rewind");
508  REG_KEY("TV Frontend", ACTION_PAGERIGHT, QT_TRANSLATE_NOOP("MythControls",
509  "Page the program guide right"), ">,.,Ctrl+F,Media Fast Forward");
510  REG_KEY("TV Frontend", ACTION_TOGGLEFAV, QT_TRANSLATE_NOOP("MythControls",
511  "Toggle the current channel as a favorite"), "?");
512  REG_KEY("TV Frontend", ACTION_TOGGLEPGORDER, QT_TRANSLATE_NOOP("MythControls",
513  "Reverse the channel order in the program guide"), "");
514  REG_KEY("TV Frontend", ACTION_GUIDE, QT_TRANSLATE_NOOP("MythControls",
515  "Show the Program Guide"), "S");
516  REG_KEY("TV Frontend", ACTION_FINDER, QT_TRANSLATE_NOOP("MythControls",
517  "Show the Program Finder"), "#");
518  REG_KEY("TV Frontend", ACTION_CHANNELSEARCH, QT_TRANSLATE_NOOP("MythControls",
519  "Show the Channel Search"), "");
520  REG_KEY("TV Frontend", "NEXTFAV", QT_TRANSLATE_NOOP("MythControls",
521  "Cycle through channel groups and all channels in the "
522  "program guide."), "/");
523  REG_KEY("TV Frontend", "CHANUPDATE", QT_TRANSLATE_NOOP("MythControls",
524  "Switch channels without exiting guide in Live TV mode."), "X");
525  REG_KEY("TV Frontend", ACTION_VOLUMEDOWN, QT_TRANSLATE_NOOP("MythControls",
526  "Volume down"), "[,{,F10,Volume Down");
527  REG_KEY("TV Frontend", ACTION_VOLUMEUP, QT_TRANSLATE_NOOP("MythControls",
528  "Volume up"), "],},F11,Volume Up");
529  REG_KEY("TV Frontend", ACTION_MUTEAUDIO, QT_TRANSLATE_NOOP("MythControls",
530  "Mute"), "|,\\,F9,Volume Mute");
531  REG_KEY("TV Frontend", "CYCLEAUDIOCHAN", QT_TRANSLATE_NOOP("MythControls",
532  "Cycle audio channels"), "");
533  REG_KEY("TV Frontend", "RANKINC", QT_TRANSLATE_NOOP("MythControls",
534  "Increase program or channel rank"), "Right");
535  REG_KEY("TV Frontend", "RANKDEC", QT_TRANSLATE_NOOP("MythControls",
536  "Decrease program or channel rank"), "Left");
537  REG_KEY("TV Frontend", "UPCOMING", QT_TRANSLATE_NOOP("MythControls",
538  "List upcoming episodes"), "O");
539  REG_KEY("TV Frontend", ACTION_VIEWSCHEDULED, QT_TRANSLATE_NOOP("MythControls",
540  "List scheduled upcoming episodes"), "");
541  REG_KEY("TV Frontend", ACTION_PREVRECORDED, QT_TRANSLATE_NOOP("MythControls",
542  "List previously recorded episodes"), "");
543  REG_KEY("TV Frontend", "DETAILS", QT_TRANSLATE_NOOP("MythControls",
544  "Show details"), "U");
545  REG_KEY("TV Frontend", "VIEWINPUT", QT_TRANSLATE_NOOP("MythControls",
546  "Switch Recording Input view"), "C");
547  REG_KEY("TV Frontend", "CUSTOMEDIT", QT_TRANSLATE_NOOP("MythControls",
548  "Edit Custom Record Rule"), "");
549  REG_KEY("TV Frontend", "CHANGERECGROUP", QT_TRANSLATE_NOOP("MythControls",
550  "Change Recording Group"), "");
551  REG_KEY("TV Frontend", "CHANGEGROUPVIEW", QT_TRANSLATE_NOOP("MythControls",
552  "Change Group View"), "");
553  REG_KEY("TV Frontend", ACTION_LISTRECORDEDEPISODES, QT_TRANSLATE_NOOP("MythControls",
554  "List recorded episodes"), "");
555  /*
556  * TODO DB update needs to perform the necessary conversion and delete
557  * the following upgrade code and replace bkmKeys and togBkmKeys with "" in the
558  * REG_KEY for ACTION_SETBOOKMARK and ACTION_TOGGLEBOOKMARK.
559  */
560  // Bookmarks - Instead of SELECT to add or toggle,
561  // Use separate bookmark actions. This code is to convert users
562  // who may already be using SELECT. If they are not already using
563  // this frontend then nothing will be assigned to bookmark actions.
564  QString bkmKeys;
565  QString togBkmKeys;
566  // Check if this is a new frontend - if PAUSE returns
567  // "?" then frontend is new, never used before, so we will not assign
568  // any default bookmark keys
569  QString testKey = MythMainWindow::GetKey("TV Playback", ACTION_PAUSE);
570  if (testKey != "?")
571  {
572  int alternate = gCoreContext->GetNumSetting("AltClearSavedPosition",0);
573  QString selectKeys = MythMainWindow::GetKey("Global", ACTION_SELECT);
574  if (selectKeys != "?")
575  {
576  if (alternate)
577  togBkmKeys = selectKeys;
578  else
579  bkmKeys = selectKeys;
580  }
581  }
582  REG_KEY("TV Playback", ACTION_SETBOOKMARK, QT_TRANSLATE_NOOP("MythControls",
583  "Add Bookmark"), bkmKeys);
584  REG_KEY("TV Playback", ACTION_TOGGLEBOOKMARK, QT_TRANSLATE_NOOP("MythControls",
585  "Toggle Bookmark"), togBkmKeys);
586  REG_KEY("TV Playback", "BACK", QT_TRANSLATE_NOOP("MythControls",
587  "Exit or return to DVD menu"), "Esc,Back");
588  REG_KEY("TV Playback", ACTION_MENUCOMPACT, QT_TRANSLATE_NOOP("MythControls",
589  "Playback Compact Menu"), "Alt+M");
590  REG_KEY("TV Playback", ACTION_CLEAROSD, QT_TRANSLATE_NOOP("MythControls",
591  "Clear OSD"), "Backspace");
592  REG_KEY("TV Playback", ACTION_PAUSE, QT_TRANSLATE_NOOP("MythControls",
593  "Pause"), "P,Space,Media Play");
594  REG_KEY("TV Playback", ACTION_SEEKFFWD, QT_TRANSLATE_NOOP("MythControls",
595  "Fast Forward"), "Right");
596  REG_KEY("TV Playback", ACTION_SEEKRWND, QT_TRANSLATE_NOOP("MythControls",
597  "Rewind"), "Left");
598  REG_KEY("TV Playback", ACTION_SEEKARB, QT_TRANSLATE_NOOP("MythControls",
599  "Arbitrary Seek"), "*");
600  REG_KEY("TV Playback", ACTION_SEEKABSOLUTE, QT_TRANSLATE_NOOP("MythControls",
601  "Seek to a position in seconds"), "");
602  REG_KEY("TV Playback", ACTION_CHANNELUP, QT_TRANSLATE_NOOP("MythControls",
603  "Channel up"), "Up");
604  REG_KEY("TV Playback", ACTION_CHANNELDOWN, QT_TRANSLATE_NOOP("MythControls",
605  "Channel down"), "Down");
606  REG_KEY("TV Playback", "NEXTFAV", QT_TRANSLATE_NOOP("MythControls",
607  "Switch to the next favorite channel"), "/");
608  REG_KEY("TV Playback", "PREVCHAN", QT_TRANSLATE_NOOP("MythControls",
609  "Switch to the previous channel"), "H");
610  REG_KEY("TV Playback", ACTION_JUMPFFWD, QT_TRANSLATE_NOOP("MythControls",
611  "Jump ahead"), "PgDown");
612  REG_KEY("TV Playback", ACTION_JUMPRWND, QT_TRANSLATE_NOOP("MythControls",
613  "Jump back"), "PgUp");
614  REG_KEY("TV Playback", "INFOWITHCUTLIST", QT_TRANSLATE_NOOP("MythControls",
615  "Info utilizing cutlist"), "");
616  REG_KEY("TV Playback", ACTION_JUMPBKMRK, QT_TRANSLATE_NOOP("MythControls",
617  "Jump to bookmark"), "K");
618  REG_KEY("TV Playback", "FFWDSTICKY", QT_TRANSLATE_NOOP("MythControls",
619  "Fast Forward (Sticky) or Forward one second while paused"), ">,.,Ctrl+F,Media Fast Forward");
620  REG_KEY("TV Playback", "RWNDSTICKY", QT_TRANSLATE_NOOP("MythControls",
621  "Rewind (Sticky) or Rewind one second while paused"), ",,<,Ctrl+B,Media Rewind");
622  REG_KEY("TV Playback", "NEXTSOURCE", QT_TRANSLATE_NOOP("MythControls",
623  "Next Video Source"), "Y");
624  REG_KEY("TV Playback", "PREVSOURCE", QT_TRANSLATE_NOOP("MythControls",
625  "Previous Video Source"), "");
626  REG_KEY("TV Playback", "NEXTINPUT", QT_TRANSLATE_NOOP("MythControls",
627  "Next Input"), "C");
628  REG_KEY("TV Playback", "NEXTCARD", QT_TRANSLATE_NOOP("MythControls",
629  "Next Card"), "");
630  REG_KEY("TV Playback", "SKIPCOMMERCIAL", QT_TRANSLATE_NOOP("MythControls",
631  "Skip Commercial"), "Z,End,Media Next");
632  REG_KEY("TV Playback", "SKIPCOMMBACK", QT_TRANSLATE_NOOP("MythControls",
633  "Skip Commercial (Reverse)"), "Q,Home,Media Previous");
634  REG_KEY("TV Playback", ACTION_JUMPSTART, QT_TRANSLATE_NOOP("MythControls",
635  "Jump to the start of the recording."), "Ctrl+A");
636  REG_KEY("TV Playback", "TOGGLEBROWSE", QT_TRANSLATE_NOOP("MythControls",
637  "Toggle channel browse mode"), "O");
638  REG_KEY("TV Playback", ACTION_TOGGLERECORD, QT_TRANSLATE_NOOP("MythControls",
639  "Toggle recording status of current program"), "R");
640  REG_KEY("TV Playback", ACTION_TOGGLEFAV, QT_TRANSLATE_NOOP("MythControls",
641  "Toggle the current channel as a favorite"), "?");
642  REG_KEY("TV Playback", ACTION_VOLUMEDOWN, QT_TRANSLATE_NOOP("MythControls",
643  "Volume down"), "[,{,F10,Volume Down");
644  REG_KEY("TV Playback", ACTION_VOLUMEUP, QT_TRANSLATE_NOOP("MythControls",
645  "Volume up"), "],},F11,Volume Up");
646  REG_KEY("TV Playback", ACTION_MUTEAUDIO, QT_TRANSLATE_NOOP("MythControls",
647  "Mute"), "|,\\,F9,Volume Mute");
648  REG_KEY("TV Playback", ACTION_SETVOLUME, QT_TRANSLATE_NOOP("MythControls",
649  "Set the volume"), "");
650  REG_KEY("TV Playback", "CYCLEAUDIOCHAN", QT_TRANSLATE_NOOP("MythControls",
651  "Cycle audio channels"), "");
652  REG_KEY("TV Playback", ACTION_TOGGLEUPMIX, QT_TRANSLATE_NOOP("MythControls",
653  "Toggle audio upmixer"), "Ctrl+U");
654  REG_KEY("TV Playback", ACTION_BOTTOMLINEMOVE,
655  QT_TRANSLATE_NOOP("MythControls", "Move BottomLine off screen"), "L");
656  REG_KEY("TV Playback", ACTION_BOTTOMLINESAVE,
657  QT_TRANSLATE_NOOP("MythControls", "Save manual zoom for BottomLine"), "");
658  REG_KEY("TV Playback", "TOGGLEASPECT", QT_TRANSLATE_NOOP("MythControls",
659  "Toggle the video aspect ratio"), "Ctrl+W");
660  REG_KEY("TV Playback", "TOGGLEFILL", QT_TRANSLATE_NOOP("MythControls",
661  "Next Preconfigured Zoom mode"), "W");
662  REG_KEY("TV Playback", ACTION_TOGGLESUBS, QT_TRANSLATE_NOOP("MythControls",
663  "Toggle any captions"), "T");
664  REG_KEY("TV Playback", ACTION_ENABLESUBS, QT_TRANSLATE_NOOP("MythControls",
665  "Enable any captions"), "");
666  REG_KEY("TV Playback", ACTION_DISABLESUBS, QT_TRANSLATE_NOOP("MythControls",
667  "Disable any captions"), "");
668  REG_KEY("TV Playback", "TOGGLETTC", QT_TRANSLATE_NOOP("MythControls",
669  "Toggle Teletext Captions"),"");
670  REG_KEY("TV Playback", "TOGGLESUBTITLE", QT_TRANSLATE_NOOP("MythControls",
671  "Toggle Subtitles"), "");
672  REG_KEY("TV Playback", "TOGGLECC608", QT_TRANSLATE_NOOP("MythControls",
673  "Toggle VBI CC"), "");
674  REG_KEY("TV Playback", "TOGGLECC708", QT_TRANSLATE_NOOP("MythControls",
675  "Toggle ATSC CC"), "");
676  REG_KEY("TV Playback", "TOGGLETTM", QT_TRANSLATE_NOOP("MythControls",
677  "Toggle Teletext Menu"), "");
678  REG_KEY("TV Playback", ACTION_TOGGLEEXTTEXT, QT_TRANSLATE_NOOP("MythControls",
679  "Toggle External Subtitles"), "");
680  REG_KEY("TV Playback", ACTION_ENABLEEXTTEXT, QT_TRANSLATE_NOOP("MythControls",
681  "Enable External Subtitles"), "");
682  REG_KEY("TV Playback", ACTION_DISABLEEXTTEXT, QT_TRANSLATE_NOOP("MythControls",
683  "Disable External Subtitles"), "");
684  REG_KEY("TV Playback", "TOGGLERAWTEXT", QT_TRANSLATE_NOOP("MythControls",
685  "Toggle Text Subtitles"), "");
686 
687  REG_KEY("TV Playback", "SELECTAUDIO_0", QT_TRANSLATE_NOOP("MythControls",
688  "Play audio track 1"), "");
689  REG_KEY("TV Playback", "SELECTAUDIO_1", QT_TRANSLATE_NOOP("MythControls",
690  "Play audio track 2"), "");
691  REG_KEY("TV Playback", "SELECTSUBTITLE_0",QT_TRANSLATE_NOOP("MythControls",
692  "Display subtitle 1"), "");
693  REG_KEY("TV Playback", "SELECTSUBTITLE_1",QT_TRANSLATE_NOOP("MythControls",
694  "Display subtitle 2"), "");
695  REG_KEY("TV Playback", "SELECTRAWTEXT_0",QT_TRANSLATE_NOOP("MythControls",
696  "Display Text Subtitle 1"), "");
697  REG_KEY("TV Playback", "SELECTCC608_0", QT_TRANSLATE_NOOP("MythControls",
698  "Display VBI CC1"), "");
699  REG_KEY("TV Playback", "SELECTCC608_1", QT_TRANSLATE_NOOP("MythControls",
700  "Display VBI CC2"), "");
701  REG_KEY("TV Playback", "SELECTCC608_2", QT_TRANSLATE_NOOP("MythControls",
702  "Display VBI CC3"), "");
703  REG_KEY("TV Playback", "SELECTCC608_3", QT_TRANSLATE_NOOP("MythControls",
704  "Display VBI CC4"), "");
705  REG_KEY("TV Playback", "SELECTCC708_0", QT_TRANSLATE_NOOP("MythControls",
706  "Display ATSC CC1"), "");
707  REG_KEY("TV Playback", "SELECTCC708_1", QT_TRANSLATE_NOOP("MythControls",
708  "Display ATSC CC2"), "");
709  REG_KEY("TV Playback", "SELECTCC708_2", QT_TRANSLATE_NOOP("MythControls",
710  "Display ATSC CC3"), "");
711  REG_KEY("TV Playback", "SELECTCC708_3", QT_TRANSLATE_NOOP("MythControls",
712  "Display ATSC CC4"), "");
713  REG_KEY("TV Playback", ACTION_ENABLEFORCEDSUBS, QT_TRANSLATE_NOOP("MythControls",
714  "Enable Forced Subtitles"), "");
715  REG_KEY("TV Playback", ACTION_DISABLEFORCEDSUBS, QT_TRANSLATE_NOOP("MythControls",
716  "Disable Forced Subtitles"), "");
717 
718  REG_KEY("TV Playback", "NEXTAUDIO", QT_TRANSLATE_NOOP("MythControls",
719  "Next audio track"), "+");
720  REG_KEY("TV Playback", "PREVAUDIO", QT_TRANSLATE_NOOP("MythControls",
721  "Previous audio track"), "-");
722  REG_KEY("TV Playback", "NEXTSUBTITLE", QT_TRANSLATE_NOOP("MythControls",
723  "Next subtitle track"), "");
724  REG_KEY("TV Playback", "PREVSUBTITLE", QT_TRANSLATE_NOOP("MythControls",
725  "Previous subtitle track"), "");
726  REG_KEY("TV Playback", "NEXTRAWTEXT", QT_TRANSLATE_NOOP("MythControls",
727  "Next Text track"), "");
728  REG_KEY("TV Playback", "PREVRAWTEXT", QT_TRANSLATE_NOOP("MythControls",
729  "Previous Text track"), "");
730  REG_KEY("TV Playback", "NEXTCC608", QT_TRANSLATE_NOOP("MythControls",
731  "Next VBI CC track"), "");
732  REG_KEY("TV Playback", "PREVCC608", QT_TRANSLATE_NOOP("MythControls",
733  "Previous VBI CC track"), "");
734  REG_KEY("TV Playback", "NEXTCC708", QT_TRANSLATE_NOOP("MythControls",
735  "Next ATSC CC track"), "");
736  REG_KEY("TV Playback", "PREVCC708", QT_TRANSLATE_NOOP("MythControls",
737  "Previous ATSC CC track"), "");
738  REG_KEY("TV Playback", "NEXTCC", QT_TRANSLATE_NOOP("MythControls",
739  "Next of any captions"), "");
740 
741  REG_KEY("TV Playback", "NEXTSCAN", QT_TRANSLATE_NOOP("MythControls",
742  "Next video scan overidemode"), "");
743  REG_KEY("TV Playback", "QUEUETRANSCODE", QT_TRANSLATE_NOOP("MythControls",
744  "Queue the current recording for transcoding"), "X");
745  REG_KEY("TV Playback", "SPEEDINC", QT_TRANSLATE_NOOP("MythControls",
746  "Increase the playback speed"), "U");
747  REG_KEY("TV Playback", "SPEEDDEC", QT_TRANSLATE_NOOP("MythControls",
748  "Decrease the playback speed"), "J");
749  REG_KEY("TV Playback", "ADJUSTSTRETCH", QT_TRANSLATE_NOOP("MythControls",
750  "Turn on time stretch control"), "A");
751  REG_KEY("TV Playback", "STRETCHINC", QT_TRANSLATE_NOOP("MythControls",
752  "Increase time stretch speed"), "");
753  REG_KEY("TV Playback", "STRETCHDEC", QT_TRANSLATE_NOOP("MythControls",
754  "Decrease time stretch speed"), "");
755  REG_KEY("TV Playback", "TOGGLESTRETCH", QT_TRANSLATE_NOOP("MythControls",
756  "Toggle time stretch speed"), "");
757  REG_KEY("TV Playback", ACTION_TOGGELAUDIOSYNC,
758  QT_TRANSLATE_NOOP("MythControls",
759  "Turn on audio sync adjustment controls"), "");
760  REG_KEY("TV Playback", ACTION_SETAUDIOSYNC,
761  QT_TRANSLATE_NOOP("MythControls",
762  "Set the audio sync adjustment"), "");
763  REG_KEY("TV Playback", "TOGGLEPICCONTROLS",
764  QT_TRANSLATE_NOOP("MythControls", "Playback picture adjustments"),
765  "F");
766  REG_KEY("TV Playback", ACTION_SETBRIGHTNESS,
767  QT_TRANSLATE_NOOP("MythControls", "Set the picture brightness"), "");
768  REG_KEY("TV Playback", ACTION_SETCONTRAST,
769  QT_TRANSLATE_NOOP("MythControls", "Set the picture contrast"), "");
770  REG_KEY("TV Playback", ACTION_SETCOLOUR,
771  QT_TRANSLATE_NOOP("MythControls", "Set the picture color"), "");
772  REG_KEY("TV Playback", ACTION_SETHUE,
773  QT_TRANSLATE_NOOP("MythControls", "Set the picture hue"), "");
774  REG_KEY("TV Playback", ACTION_TOGGLECHANCONTROLS,
775  QT_TRANSLATE_NOOP("MythControls", "Recording picture adjustments "
776  "for this channel"), "Ctrl+G");
777  REG_KEY("TV Playback", ACTION_TOGGLERECCONTROLS,
778  QT_TRANSLATE_NOOP("MythControls", "Recording picture adjustments "
779  "for this recorder"), "G");
780  REG_KEY("TV Playback", "CYCLECOMMSKIPMODE",
781  QT_TRANSLATE_NOOP("MythControls", "Cycle Commercial Skip mode"),
782  "");
783  REG_KEY("TV Playback", ACTION_GUIDE, QT_TRANSLATE_NOOP("MythControls",
784  "Show the Program Guide"), "S");
785  REG_KEY("TV Playback", ACTION_FINDER, QT_TRANSLATE_NOOP("MythControls",
786  "Show the Program Finder"), "#");
787  REG_KEY("TV Playback", ACTION_TOGGLESLEEP, QT_TRANSLATE_NOOP("MythControls",
788  "Toggle the Sleep Timer"), "F8");
789  REG_KEY("TV Playback", ACTION_PLAY, QT_TRANSLATE_NOOP("MythControls", "Play"),
790  "Ctrl+P");
791  REG_KEY("TV Playback", ACTION_JUMPPREV, QT_TRANSLATE_NOOP("MythControls",
792  "Jump to previously played recording"), "");
793  REG_KEY("TV Playback", ACTION_JUMPREC, QT_TRANSLATE_NOOP("MythControls",
794  "Display menu of recorded programs to jump to"), "");
795  REG_KEY("TV Playback", ACTION_VIEWSCHEDULED, QT_TRANSLATE_NOOP("MythControls",
796  "Display scheduled recording list"), "");
797  REG_KEY("TV Playback", ACTION_PREVRECORDED, QT_TRANSLATE_NOOP("MythControls",
798  "Display previously recorded episodes"), "");
799  REG_KEY("TV Playback", ACTION_SIGNALMON, QT_TRANSLATE_NOOP("MythControls",
800  "Monitor Signal Quality"), "Alt+F7");
801  REG_KEY("TV Playback", ACTION_JUMPTODVDROOTMENU,
802  QT_TRANSLATE_NOOP("MythControls", "Jump to the DVD Root Menu"), "");
803  REG_KEY("TV Playback", ACTION_JUMPTOPOPUPMENU,
804  QT_TRANSLATE_NOOP("MythControls", "Jump to the Popup Menu"), "");
805  REG_KEY("TV Playback", ACTION_JUMPTODVDCHAPTERMENU,
806  QT_TRANSLATE_NOOP("MythControls", "Jump to the DVD Chapter Menu"), "");
807  REG_KEY("TV Playback", ACTION_JUMPTODVDTITLEMENU,
808  QT_TRANSLATE_NOOP("MythControls", "Jump to the DVD Title Menu"), "");
809  REG_KEY("TV Playback", ACTION_EXITSHOWNOPROMPTS,
810  QT_TRANSLATE_NOOP("MythControls", "Exit Show without any prompts"),
811  "");
812  REG_KEY("TV Playback", ACTION_JUMPCHAPTER, QT_TRANSLATE_NOOP("MythControls",
813  "Jump to a chapter"), "");
814  REG_KEY("TV Playback", ACTION_SWITCHTITLE, QT_TRANSLATE_NOOP("MythControls",
815  "Switch title"), "");
816  REG_KEY("TV Playback", ACTION_SWITCHANGLE, QT_TRANSLATE_NOOP("MythControls",
817  "Switch angle"), "");
818  REG_KEY("TV Playback", ACTION_OSDNAVIGATION, QT_TRANSLATE_NOOP("MythControls",
819  "OSD Navigation"), "");
820  REG_KEY("TV Playback", ACTION_ZOOMUP, QT_TRANSLATE_NOOP("MythControls",
821  "Zoom mode - shift up"), "");
822  REG_KEY("TV Playback", ACTION_ZOOMDOWN, QT_TRANSLATE_NOOP("MythControls",
823  "Zoom mode - shift down"), "");
824  REG_KEY("TV Playback", ACTION_ZOOMLEFT, QT_TRANSLATE_NOOP("MythControls",
825  "Zoom mode - shift left"), "");
826  REG_KEY("TV Playback", ACTION_ZOOMRIGHT, QT_TRANSLATE_NOOP("MythControls",
827  "Zoom mode - shift right"), "");
828  REG_KEY("TV Playback", ACTION_ZOOMASPECTUP,
829  QT_TRANSLATE_NOOP("MythControls",
830  "Zoom mode - increase aspect ratio"), "3");
831  REG_KEY("TV Playback", ACTION_ZOOMASPECTDOWN,
832  QT_TRANSLATE_NOOP("MythControls",
833  "Zoom mode - decrease aspect ratio"), "7");
834  REG_KEY("TV Playback", ACTION_ZOOMIN, QT_TRANSLATE_NOOP("MythControls",
835  "Zoom mode - zoom in"), "9");
836  REG_KEY("TV Playback", ACTION_ZOOMOUT, QT_TRANSLATE_NOOP("MythControls",
837  "Zoom mode - zoom out"), "1");
838  REG_KEY("TV Playback", ACTION_ZOOMVERTICALIN,
839  QT_TRANSLATE_NOOP("MythControls",
840  "Zoom mode - vertical zoom in"), "8");
841  REG_KEY("TV Playback", ACTION_ZOOMVERTICALOUT,
842  QT_TRANSLATE_NOOP("MythControls",
843  "Zoom mode - vertical zoom out"), "2");
844  REG_KEY("TV Playback", ACTION_ZOOMHORIZONTALIN,
845  QT_TRANSLATE_NOOP("MythControls",
846  "Zoom mode - horizontal zoom in"), "6");
847  REG_KEY("TV Playback", ACTION_ZOOMHORIZONTALOUT,
848  QT_TRANSLATE_NOOP("MythControls",
849  "Zoom mode - horizontal zoom out"), "4");
850  REG_KEY("TV Playback", ACTION_ZOOMQUIT, QT_TRANSLATE_NOOP("MythControls",
851  "Zoom mode - quit and abandon changes"), "");
852  REG_KEY("TV Playback", ACTION_ZOOMCOMMIT, QT_TRANSLATE_NOOP("MythControls",
853  "Zoom mode - commit changes"), "");
854 
855  REG_KEY("TV Playback", ACTION_CAST, QT_TRANSLATE_NOOP("MythControls",
856  "Display list of cast members"), "");
857 
858  /* Interactive Television keys */
859  REG_KEY("TV Playback", ACTION_MENURED, QT_TRANSLATE_NOOP("MythControls",
860  "Menu Red"), "F2");
861  REG_KEY("TV Playback", ACTION_MENUGREEN, QT_TRANSLATE_NOOP("MythControls",
862  "Menu Green"), "F3");
863  REG_KEY("TV Playback", ACTION_MENUYELLOW, QT_TRANSLATE_NOOP("MythControls",
864  "Menu Yellow"), "F4");
865  REG_KEY("TV Playback", ACTION_MENUBLUE, QT_TRANSLATE_NOOP("MythControls",
866  "Menu Blue"), "F5");
867  REG_KEY("TV Playback", ACTION_TEXTEXIT, QT_TRANSLATE_NOOP("MythControls",
868  "Menu Exit"), "F6");
869  REG_KEY("TV Playback", ACTION_MENUTEXT, QT_TRANSLATE_NOOP("MythControls",
870  "Menu Text"), "F7");
871  REG_KEY("TV Playback", ACTION_MENUEPG, QT_TRANSLATE_NOOP("MythControls",
872  "Menu EPG"), "F12");
873 
874  /* Editing keys */
875  REG_KEY("TV Editing", ACTION_CLEARMAP, QT_TRANSLATE_NOOP("MythControls",
876  "Clear editing cut points"), "C,Q,Home");
877  REG_KEY("TV Editing", ACTION_INVERTMAP, QT_TRANSLATE_NOOP("MythControls",
878  "Invert Begin/End cut points"),"I,Home Page");
879  REG_KEY("TV Editing", ACTION_SAVEMAP, QT_TRANSLATE_NOOP("MythControls",
880  "Save cuts"),"");
881  REG_KEY("TV Editing", ACTION_LOADCOMMSKIP,QT_TRANSLATE_NOOP("MythControls",
882  "Load cuts from detected commercials"), "Z,End");
883  REG_KEY("TV Editing", ACTION_NEXTCUT, QT_TRANSLATE_NOOP("MythControls",
884  "Jump to the next cut point"), "PgDown,Media Next");
885  REG_KEY("TV Editing", ACTION_PREVCUT, QT_TRANSLATE_NOOP("MythControls",
886  "Jump to the previous cut point"), "PgUp,Media Previous");
887  REG_KEY("TV Editing", ACTION_BIGJUMPREW, QT_TRANSLATE_NOOP("MythControls",
888  "Jump back 10x the normal amount"), ",,<,Ctrl+B,Media Rewind");
889  REG_KEY("TV Editing", ACTION_BIGJUMPFWD, QT_TRANSLATE_NOOP("MythControls",
890  "Jump forward 10x the normal amount"), ">,.,Ctrl+F,Media Fast Forward");
891  REG_KEY("TV Editing", ACTION_MENUCOMPACT, QT_TRANSLATE_NOOP("MythControls",
892  "Cut point editor compact menu"), "Alt+M");
893 
894  /* Teletext keys */
895  REG_KEY("Teletext Menu", ACTION_NEXTPAGE, QT_TRANSLATE_NOOP("MythControls",
896  "Next Page"), "Down");
897  REG_KEY("Teletext Menu", ACTION_PREVPAGE, QT_TRANSLATE_NOOP("MythControls",
898  "Previous Page"), "Up");
899  REG_KEY("Teletext Menu", ACTION_NEXTSUBPAGE, QT_TRANSLATE_NOOP("MythControls",
900  "Next Subpage"), "Right");
901  REG_KEY("Teletext Menu", ACTION_PREVSUBPAGE, QT_TRANSLATE_NOOP("MythControls",
902  "Previous Subpage"), "Left");
903  REG_KEY("Teletext Menu", ACTION_TOGGLETT, QT_TRANSLATE_NOOP("MythControls",
904  "Toggle Teletext"), "T");
905  REG_KEY("Teletext Menu", ACTION_MENURED, QT_TRANSLATE_NOOP("MythControls",
906  "Menu Red"), "F2");
907  REG_KEY("Teletext Menu", ACTION_MENUGREEN, QT_TRANSLATE_NOOP("MythControls",
908  "Menu Green"), "F3");
909  REG_KEY("Teletext Menu", ACTION_MENUYELLOW, QT_TRANSLATE_NOOP("MythControls",
910  "Menu Yellow"), "F4");
911  REG_KEY("Teletext Menu", ACTION_MENUBLUE, QT_TRANSLATE_NOOP("MythControls",
912  "Menu Blue"), "F5");
913  REG_KEY("Teletext Menu", ACTION_MENUWHITE, QT_TRANSLATE_NOOP("MythControls",
914  "Menu White"), "F6");
915  REG_KEY("Teletext Menu", ACTION_TOGGLEBACKGROUND,
916  QT_TRANSLATE_NOOP("MythControls", "Toggle Background"), "F7");
917  REG_KEY("Teletext Menu", ACTION_REVEAL, QT_TRANSLATE_NOOP("MythControls",
918  "Reveal hidden Text"), "F8");
919 
920  /* Visualisations */
921  REG_KEY("TV Playback", ACTION_TOGGLEVISUALISATION,
922  QT_TRANSLATE_NOOP("MythControls", "Toggle audio visualisation"), "");
923 
924  /* OSD playback information screen */
925  REG_KEY("TV Playback", ACTION_TOGGLEOSDDEBUG,
926  QT_TRANSLATE_NOOP("MythControls", "Toggle OSD playback information"), "");
927 
928  /* 3D/Frame compatible/Stereoscopic TV */
929  REG_KEY("TV Playback", ACTION_3DNONE,
930  QT_TRANSLATE_NOOP("MythControls", "Auto 3D"), "");
931  REG_KEY("TV Playback", ACTION_3DIGNORE,
932  QT_TRANSLATE_NOOP("MythControls", "Ignore 3D"), "");
933  REG_KEY("TV Playback", ACTION_3DSIDEBYSIDEDISCARD,
934  QT_TRANSLATE_NOOP("MythControls", "Discard 3D Side by Side"), "");
935  REG_KEY("TV Playback", ACTION_3DTOPANDBOTTOMDISCARD,
936  QT_TRANSLATE_NOOP("MythControls", "Discard 3D Top and Bottom"), "");
937 
938 /*
939  keys already used:
940 
941  Global: I M 0123456789
942  Playback: ABCDEFGH JK NOPQRSTUVWXYZ
943  Frontend: CD OP R U XY 01 3 7 9
944  Editing: C E I Q Z
945  Teletext: T
946 
947  Playback: <>,.?/|[]{}\+-*#^
948  Frontend: <>,.?/
949  Editing: <>,.
950 
951  Global: PgDown, PgUp, Right, Left, Home, End, Up, Down,
952  Playback: PgDown, PgUp, Right, Left, Home, End, Up, Down, Backspace,
953  Frontend: Right, Left, Home, End
954  Editing: PgDown, PgUp, Home, End
955  Teletext: Right, Left, Up, Down,
956 
957  Global: Return, Enter, Space, Esc
958 
959  Global: F1,
960  Playback: F7,F8,F9,F10,F11
961  Teletext F2,F3,F4,F5,F6,F7,F8
962  ITV F2,F3,F4,F5,F6,F7,F12
963 
964  Playback: Ctrl-B,Ctrl-G,Ctrl-Y,Ctrl-U,L
965 */
966 }
967 
969 {
970  m_mainWindow->ClearKeyContext("TV Frontend");
971  m_mainWindow->ClearKeyContext("TV Playback");
972  m_mainWindow->ClearKeyContext("TV Editing");
973  m_mainWindow->ClearKeyContext("Teletext Menu");
974  InitKeys();
975 }
976 
977 
979 {
980  public:
981  SleepTimerInfo(QString String, std::chrono::milliseconds MilliSeconds)
982  : dispString(std::move(String)),
983  milliseconds(MilliSeconds) {}
984  QString dispString;
985  std::chrono::milliseconds milliseconds;
986 };
987 
988 const std::vector<TV::SleepTimerInfo> TV::s_sleepTimes =
989 {
990  { tr("Off", "Sleep timer"), 0min },
991  { tr("30m", "Sleep timer"), 30min },
992  { tr("1h", "Sleep timer"), 60min },
993  { tr("1h30m", "Sleep timer"), 90min },
994  { tr("2h", "Sleep timer"), 120min }
995 };
996 
1009  : ReferenceCounter("TV"),
1010  TVBrowseHelper(this),
1011  m_mainWindow(MainWindow),
1012  m_posThreadPool(new MThreadPool("PosSaverPool"))
1013 
1014 {
1015  LOG(VB_GENERAL, LOG_INFO, LOC + "Creating TV object");
1016 
1017  QObject::setObjectName("TV");
1019  connect(this, &TV::RequestEmbedding, this, &TV::Embed);
1020  InitFromDB();
1021 
1022 #ifdef Q_OS_ANDROID
1023  connect(qApp, &QApplication::applicationStateChanged, this, &TV::onApplicationStateChange);
1024 #endif
1025 
1026  if (m_mainWindow)
1028 
1029  // Setup various state signals
1030  connect(this, &TV::ChangeAudioOffset, [&]() { m_audiosyncAdjustment = true; });
1031  connect(this, &TV::AdjustSubtitleZoom, [&]() { m_subtitleZoomAdjustment = true; });
1032  connect(this, &TV::AdjustSubtitleDelay, [&]() { m_subtitleDelayAdjustment = true; });
1033 
1034  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Finished creating TV object");
1035 }
1036 
1038 {
1039  QMap<QString,QString> kv;
1040  kv["LiveTVIdleTimeout"] = "0";
1041  kv["BrowseMaxForward"] = "240";
1042  kv["PlaybackExitPrompt"] = "0";
1043  kv["AutomaticSetWatched"] = "0";
1044  kv["EndOfRecordingExitPrompt"] = "0";
1045  kv["JumpToProgramOSD"] = "1";
1046  kv["GuiSizeForTV"] = "0";
1047  kv["UseVideoModes"] = "0";
1048  kv["JobsRunOnRecordHost"] = "0";
1049  kv["ContinueEmbeddedTVPlay"] = "0";
1050  kv["UseFixedWindowSize"] = "1";
1051  kv["RunFrontendInWindow"] = "0";
1052  kv["PersistentBrowseMode"] = "0";
1053  kv["BrowseAllTuners"] = "0";
1054  kv["ChannelOrdering"] = "channum";
1055 
1056  kv["CustomFilters"] = "";
1057  kv["ChannelFormat"] = "<num> <sign>";
1058 
1059  kv["TryUnflaggedSkip"] = "0";
1060 
1061  kv["ChannelGroupDefault"] = "-1";
1062  kv["BrowseChannelGroup"] = "0";
1063  kv["SmartForward"] = "0";
1064  kv["FFRewReposTime"] = "100";
1065  kv["FFRewReverse"] = "1";
1066 
1067  kv["BrowseChannelGroup"] = "0";
1068  kv["ChannelGroupDefault"] = "-1";
1069  kv["ChannelGroupRememberLast"] = "0";
1070 
1071  kv["VbiFormat"] = "";
1072  kv["DecodeVBIFormat"] = "";
1073 
1074  // these need exactly 12 items, comma cant be used as it is the delimiter
1075  kv["PlaybackScreenPressKeyMap"] = "P,Up,Z,],Left,Return,Return,Right,A,Down,Q,[";
1076  kv["LiveTVScreenPressKeyMap"] = "P,Up,Z,S,Left,Return,Return,Right,A,Down,Q,F";
1077 
1078  constexpr std::array<const int,8> ff_rew_def { 3, 5, 10, 20, 30, 60, 120, 180 };
1079  for (size_t i = 0; i < ff_rew_def.size(); i++)
1080  kv[QString("FFRewSpeed%1").arg(i)] = QString::number(ff_rew_def[i]);
1081 
1082  MythDB::getMythDB()->GetSettings(kv);
1083 
1084  m_screenPressKeyMapPlayback = ConvertScreenPressKeyMap(kv["PlaybackScreenPressKeyMap"]);
1085  m_screenPressKeyMapLiveTV = ConvertScreenPressKeyMap(kv["LiveTVScreenPressKeyMap"]);
1086 
1087  QString db_channel_ordering;
1088 
1089  m_dbIdleTimeout = std::chrono::minutes(kv["LiveTVIdleTimeout"].toUInt());
1090  auto db_browse_max_forward = std::chrono::minutes(kv["BrowseMaxForward"].toUInt());
1091  m_dbPlaybackExitPrompt = kv["PlaybackExitPrompt"].toInt();
1092  m_dbAutoSetWatched = (kv["AutomaticSetWatched"].toInt() != 0);
1093  m_dbEndOfRecExitPrompt = (kv["EndOfRecordingExitPrompt"].toInt() != 0);
1094  m_dbJumpPreferOsd = (kv["JumpToProgramOSD"].toInt() != 0);
1095  m_dbUseGuiSizeForTv = (kv["GuiSizeForTV"].toInt() != 0);
1096  m_dbUseVideoModes = (kv["UseVideoModes"].toInt() != 0);
1097  m_dbRunJobsOnRemote = (kv["JobsRunOnRecordHost"].toInt() != 0);
1098  m_dbContinueEmbedded = (kv["ContinueEmbeddedTVPlay"].toInt() != 0);
1099  m_dbBrowseAlways = (kv["PersistentBrowseMode"].toInt() != 0);
1100  m_dbBrowseAllTuners = (kv["BrowseAllTuners"].toInt() != 0);
1101  db_channel_ordering = kv["ChannelOrdering"];
1102  m_dbChannelFormat = kv["ChannelFormat"];
1103  m_smartForward = (kv["SmartForward"].toInt() != 0);
1104  m_ffRewRepos = kv["FFRewReposTime"].toFloat() * 0.01F;
1105  m_ffRewReverse = (kv["FFRewReverse"].toInt() != 0);
1106 
1107  m_dbUseChannelGroups = (kv["BrowseChannelGroup"].toInt() != 0);
1108  m_dbRememberLastChannelGroup = (kv["ChannelGroupRememberLast"].toInt() != 0);
1109  m_channelGroupId = kv["ChannelGroupDefault"].toInt();
1110 
1111  QString beVBI = kv["VbiFormat"];
1112  QString feVBI = kv["DecodeVBIFormat"];
1113 
1114  RecordingRule record;
1115  record.LoadTemplate("Default");
1116  m_dbAutoexpireDefault = static_cast<uint>(record.m_autoExpire);
1117 
1119  {
1121  if (m_channelGroupId > -1)
1122  {
1123  m_channelGroupChannelList = ChannelUtil::GetChannels(0, true, "channum, callsign",
1124  static_cast<uint>(m_channelGroupId));
1126  }
1127  }
1128 
1129  for (size_t i = 0; i < sizeof(ff_rew_def)/sizeof(ff_rew_def[0]); i++)
1130  m_ffRewSpeeds.push_back(kv[QString("FFRewSpeed%1").arg(i)].toInt());
1131 
1132  // process it..
1133  BrowseInit(db_browse_max_forward, m_dbBrowseAllTuners, m_dbUseChannelGroups, db_channel_ordering);
1134 
1135  m_vbimode = VBIMode::Parse(!feVBI.isEmpty() ? feVBI : beVBI);
1136 
1137  gCoreContext->addListener(this);
1139 }
1140 
1145 bool TV::Init()
1146 {
1147  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- begin");
1148 
1149  if (!m_mainWindow)
1150  {
1151  LOG(VB_GENERAL, LOG_ERR, LOC + "No MythMainWindow");
1152  return false;
1153  }
1154 
1155  bool fullscreen = !m_dbUseGuiSizeForTv;
1156  m_savedGuiBounds = QRect(m_mainWindow->geometry().topLeft(), m_mainWindow->size());
1157 
1158  // adjust for window manager wierdness.
1159  QRect screen = m_mainWindow->GetScreenRect();
1160  if ((abs(m_savedGuiBounds.x() - screen.left()) < 3) &&
1161  (abs(m_savedGuiBounds.y() - screen.top()) < 3))
1162  {
1163  m_savedGuiBounds = QRect(screen.topLeft(), m_mainWindow->size());
1164  }
1165 
1166  // if width && height are zero users expect fullscreen playback
1167  if (!fullscreen)
1168  {
1169  int gui_width = 0;
1170  int gui_height = 0;
1171  gCoreContext->GetResolutionSetting("Gui", gui_width, gui_height);
1172  fullscreen |= (0 == gui_width && 0 == gui_height);
1173  }
1174 
1176  if (fullscreen)
1178 
1179  // player window sizing
1180  MythScreenStack *mainStack = m_mainWindow->GetMainStack();
1181 
1182  m_myWindow = new TvPlayWindow(mainStack, "Playback");
1183 
1184  if (m_myWindow->Create())
1185  {
1186  mainStack->AddScreen(m_myWindow, false);
1187  LOG(VB_GENERAL, LOG_INFO, LOC + "Created TvPlayWindow.");
1188  }
1189  else
1190  {
1191  delete m_myWindow;
1192  m_myWindow = nullptr;
1193  }
1194 
1196  m_mainWindow->GetPaintWindow()->update();
1197  m_mainWindow->installEventFilter(this);
1198  QCoreApplication::processEvents();
1199 
1204  m_playerContext.m_tsNormal = 1.0F;
1205  ReturnPlayerLock();
1206 
1207  m_sleepIndex = 0;
1208 
1209  emit ChangeOSDPositionUpdates(false);
1210 
1212  ClearInputQueues(false);
1213  ReturnPlayerLock();
1214 
1215  m_switchToRec = nullptr;
1216  SetExitPlayer(false, false);
1217 
1219  m_lcdTimerId = StartTimer(1ms, __LINE__);
1222 
1223  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end");
1224  return true;
1225 }
1226 
1228 {
1229  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- begin");
1230 
1231  BrowseStop();
1232  BrowseWait();
1233 
1236 
1237  if (m_mainWindow)
1238  {
1239  m_mainWindow->removeEventFilter(this);
1240  if (m_weDisabledGUI)
1242  }
1243 
1244  if (m_myWindow)
1245  {
1246  m_myWindow->Close();
1247  m_myWindow = nullptr;
1248  }
1249 
1250  LOG(VB_PLAYBACK, LOG_INFO, LOC + "-- lock");
1251 
1252  // restore window to gui size and position
1253  if (m_mainWindow)
1254  {
1255  MythDisplay* display = m_mainWindow->GetDisplay();
1256  if (display->UsingVideoModes())
1257  {
1258  bool hide = display->NextModeIsLarger(display->GetGUIResolution());
1259  if (hide)
1260  m_mainWindow->hide();
1261  display->SwitchToGUI(true);
1262  if (hide)
1263  m_mainWindow->Show();
1264  }
1266  #ifdef Q_OS_ANDROID
1267  m_mainWindow->Show();
1268  #else
1269  m_mainWindow->show();
1270  #endif
1271  m_mainWindow->PauseIdleTimer(false);
1272  }
1273 
1274  qDeleteAll(m_screenPressKeyMapPlayback);
1276  qDeleteAll(m_screenPressKeyMapLiveTV);
1277  m_screenPressKeyMapLiveTV.clear();
1278 
1279  delete m_lastProgram;
1280 
1281  if (LCD *lcd = LCD::Get())
1282  {
1283  lcd->setFunctionLEDs(FUNC_TV, false);
1284  lcd->setFunctionLEDs(FUNC_MOVIE, false);
1285  lcd->switchToTime();
1286  }
1287 
1288  if (m_posThreadPool)
1289  {
1290  // Wait for "PositionSaver" to complete before proceeding
1292  delete m_posThreadPool;
1293  m_posThreadPool = nullptr;
1294  }
1295 
1296  m_playerLock.lockForWrite();
1298  m_player = nullptr;
1299  m_playerLock.unlock();
1300 
1301  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end");
1302 }
1303 
1308 {
1309  while (true)
1310  {
1311  QCoreApplication::processEvents();
1313  {
1314  m_wantsToQuit = true;
1315  return;
1316  }
1317 
1318  TVState state = GetState();
1319  if ((kState_Error == state) || (kState_None == state))
1320  return;
1321 
1322  if (kState_ChangingState == state)
1323  continue;
1324 
1326  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
1327  if (m_player && !m_player->IsErrored())
1328  {
1329  m_player->EventLoop();
1330  m_player->VideoLoop();
1331  }
1332  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
1333  ReturnPlayerLock();
1334 
1336  return;
1337  }
1338 }
1339 
1343 void TV::UpdateChannelList(int GroupID)
1344 {
1345  if (!m_dbUseChannelGroups)
1346  return;
1347 
1348  QMutexLocker locker(&m_channelGroupLock);
1349  if (GroupID == m_channelGroupId)
1350  return;
1351 
1352  ChannelInfoList list;
1353  if (GroupID >= 0)
1354  {
1355  list = ChannelUtil::GetChannels(0, true, "channum, callsign", static_cast<uint>(GroupID));
1356  ChannelUtil::SortChannels(list, "channum", true);
1357  }
1358 
1359  m_channelGroupId = GroupID;
1361 
1363  gCoreContext->SaveSetting("ChannelGroupDefault", m_channelGroupId);
1364 }
1365 
1367 {
1370  ret = m_playerContext.GetState();
1371  return ret;
1372 }
1373 
1374 // XXX what about subtitlezoom?
1376 {
1377  QVariantMap status;
1378 
1380  status.insert("state", StateToString(GetState()));
1381  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
1383  {
1384  status.insert("title", m_playerContext.m_playingInfo->GetTitle());
1385  status.insert("subtitle", m_playerContext.m_playingInfo->GetSubtitle());
1386  status.insert("starttime", m_playerContext.m_playingInfo->GetRecordingStartTime()
1387  .toUTC().toString("yyyy-MM-ddThh:mm:ssZ"));
1388  status.insert("chanid", QString::number(m_playerContext.m_playingInfo->GetChanID()));
1389  status.insert("programid", m_playerContext.m_playingInfo->GetProgramID());
1390  status.insert("pathname", m_playerContext.m_playingInfo->GetPathname());
1391  }
1392  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
1393  osdInfo info;
1395  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
1396  if (m_player)
1397  {
1398  if (!info.text["totalchapters"].isEmpty())
1399  {
1400  QList<std::chrono::seconds> chapters;
1401  m_player->GetChapterTimes(chapters);
1402  QVariantList var;
1403  for (std::chrono::seconds chapter : std::as_const(chapters))
1404  var << QVariant((long long)chapter.count());
1405  status.insert("chaptertimes", var);
1406  }
1407 
1409  QVariantMap tracks;
1410 
1411  QStringList list = m_player->GetTracks(kTrackTypeSubtitle);
1412  int currenttrack = -1;
1413  if (!list.isEmpty() && (kDisplayAVSubtitle == capmode))
1414  currenttrack = m_player->GetTrack(kTrackTypeSubtitle);
1415  for (int i = 0; i < list.size(); i++)
1416  {
1417  if (i == currenttrack)
1418  status.insert("currentsubtitletrack", list[i]);
1419  tracks.insert("SELECTSUBTITLE_" + QString::number(i), list[i]);
1420  }
1421 
1423  currenttrack = -1;
1424  if (!list.isEmpty() && (kDisplayTeletextCaptions == capmode))
1425  currenttrack = m_player->GetTrack(kTrackTypeTeletextCaptions);
1426  for (int i = 0; i < list.size(); i++)
1427  {
1428  if (i == currenttrack)
1429  status.insert("currentsubtitletrack", list[i]);
1430  tracks.insert("SELECTTTC_" + QString::number(i), list[i]);
1431  }
1432 
1434  currenttrack = -1;
1435  if (!list.isEmpty() && (kDisplayCC708 == capmode))
1436  currenttrack = m_player->GetTrack(kTrackTypeCC708);
1437  for (int i = 0; i < list.size(); i++)
1438  {
1439  if (i == currenttrack)
1440  status.insert("currentsubtitletrack", list[i]);
1441  tracks.insert("SELECTCC708_" + QString::number(i), list[i]);
1442  }
1443 
1445  currenttrack = -1;
1446  if (!list.isEmpty() && (kDisplayCC608 == capmode))
1447  currenttrack = m_player->GetTrack(kTrackTypeCC608);
1448  for (int i = 0; i < list.size(); i++)
1449  {
1450  if (i == currenttrack)
1451  status.insert("currentsubtitletrack", list[i]);
1452  tracks.insert("SELECTCC608_" + QString::number(i), list[i]);
1453  }
1454 
1456  currenttrack = -1;
1457  if (!list.isEmpty() && (kDisplayRawTextSubtitle == capmode))
1458  currenttrack = m_player->GetTrack(kTrackTypeRawText);
1459  for (int i = 0; i < list.size(); i++)
1460  {
1461  if (i == currenttrack)
1462  status.insert("currentsubtitletrack", list[i]);
1463  tracks.insert("SELECTRAWTEXT_" + QString::number(i), list[i]);
1464  }
1465 
1467  {
1468  if (kDisplayTextSubtitle == capmode)
1469  status.insert("currentsubtitletrack", tr("External Subtitles"));
1470  tracks.insert(ACTION_ENABLEEXTTEXT, tr("External Subtitles"));
1471  }
1472 
1473  status.insert("totalsubtitletracks", tracks.size());
1474  if (!tracks.isEmpty())
1475  status.insert("subtitletracks", tracks);
1476 
1477  tracks.clear();
1479  currenttrack = m_player->GetTrack(kTrackTypeAudio);
1480  for (int i = 0; i < list.size(); i++)
1481  {
1482  if (i == currenttrack)
1483  status.insert("currentaudiotrack", list[i]);
1484  tracks.insert("SELECTAUDIO_" + QString::number(i), list[i]);
1485  }
1486 
1487  status.insert("totalaudiotracks", tracks.size());
1488  if (!tracks.isEmpty())
1489  status.insert("audiotracks", tracks);
1490 
1491  status.insert("playspeed", m_player->GetPlaySpeed());
1492  status.insert("audiosyncoffset", static_cast<long long>(m_audioState.m_audioOffset.count()));
1493 
1495  {
1496  status.insert("volume", m_audioState.m_volume);
1497  status.insert("mute", m_audioState.m_muteState);
1498  }
1499 
1502  status.insert("brightness", m_videoColourState.GetValue(kPictureAttribute_Brightness));
1504  status.insert("contrast", m_videoColourState.GetValue(kPictureAttribute_Contrast));
1506  status.insert("colour", m_videoColourState.GetValue(kPictureAttribute_Colour));
1507  if (supp & kPictureAttributeSupported_Hue)
1508  status.insert("hue", m_videoColourState.GetValue(kPictureAttribute_Hue));
1509  }
1510  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
1511  ReturnPlayerLock();
1512 
1513  for (auto tit =info.text.cbegin(); tit != info.text.cend(); ++tit)
1514  status.insert(tit.key(), tit.value());
1515 
1516  QHashIterator<QString,int> vit(info.values);
1517  while (vit.hasNext())
1518  {
1519  vit.next();
1520  status.insert(vit.key(), vit.value());
1521  }
1522 
1524 }
1525 
1531 bool TV::LiveTV(bool ShowDialogs, const ChannelInfoList &Selection)
1532 {
1533  m_requestDelete = false;
1534  m_allowRerecord = false;
1535  m_jumpToProgram = false;
1536 
1538  if (m_playerContext.GetState() == kState_None && RequestNextRecorder(ShowDialogs, Selection))
1539  {
1542  m_switchToRec = nullptr;
1543 
1544  // Start Idle Timer
1545  if (m_dbIdleTimeout > 0ms)
1546  {
1548  LOG(VB_GENERAL, LOG_INFO, QString("Using Idle Timer. %1 minutes")
1549  .arg(duration_cast<std::chrono::minutes>(m_dbIdleTimeout).count()));
1550  }
1551 
1552  ReturnPlayerLock();
1553  return true;
1554  }
1555  ReturnPlayerLock();
1556  return false;
1557 }
1558 
1559 bool TV::RequestNextRecorder(bool ShowDialogs, const ChannelInfoList &Selection)
1560 {
1561  m_playerContext.SetRecorder(nullptr);
1562 
1563  RemoteEncoder *testrec = nullptr;
1564  if (m_switchToRec)
1565  {
1566  // If this is set we, already got a new recorder in SwitchCards()
1567  testrec = m_switchToRec;
1568  m_switchToRec = nullptr;
1569  }
1570  else if (!Selection.empty())
1571  {
1572  for (const auto & ci : Selection)
1573  {
1574  uint chanid = ci.m_chanId;
1575  QString channum = ci.m_chanNum;
1576  if (!chanid || channum.isEmpty())
1577  continue;
1578  QVector<uint> cards = IsTunableOn(&m_playerContext, chanid);
1579 
1580  if (chanid && !channum.isEmpty() && !cards.isEmpty())
1581  {
1582  testrec = RemoteGetExistingRecorder(static_cast<int>(*(cards.begin())));
1583  m_initialChanID = chanid;
1584  break;
1585  }
1586  }
1587  }
1588  else
1589  {
1590  // When starting LiveTV we just get the next free recorder
1591  testrec = RemoteRequestNextFreeRecorder(-1);
1592  }
1593 
1594  if (!testrec)
1595  return false;
1596 
1597  if (!testrec->IsValidRecorder())
1598  {
1599  if (ShowDialogs)
1601 
1602  delete testrec;
1603 
1604  return false;
1605  }
1606 
1607  m_playerContext.SetRecorder(testrec);
1608 
1609  return true;
1610 }
1611 
1612 void TV::AskAllowRecording(const QStringList &Msg, int Timeuntil, bool HasRec, bool HasLater)
1613 {
1614  if (!StateIsLiveTV(GetState()))
1615  return;
1616 
1617  auto *info = new ProgramInfo(Msg);
1618  if (!info->GetChanID())
1619  {
1620  delete info;
1621  return;
1622  }
1623 
1624  QMutexLocker locker(&m_askAllowLock);
1625  QString key = info->MakeUniqueKey();
1626  if (Timeuntil > 0)
1627  {
1628  // add program to list
1629 #if 0
1630  LOG(VB_GENERAL, LOG_DEBUG, LOC + "AskAllowRecording -- " +
1631  QString("adding '%1'").arg(info->m_title));
1632 #endif
1633  QDateTime expiry = MythDate::current().addSecs(Timeuntil);
1634  m_askAllowPrograms[key] = AskProgramInfo(expiry, HasRec, HasLater, info);
1635  }
1636  else
1637  {
1638  // remove program from list
1639  LOG(VB_GENERAL, LOG_INFO, LOC + "-- " +
1640  QString("removing '%1'").arg(info->GetTitle()));
1641  QMap<QString,AskProgramInfo>::iterator it = m_askAllowPrograms.find(key);
1642  if (it != m_askAllowPrograms.end())
1643  {
1644  delete (*it).m_info;
1645  m_askAllowPrograms.erase(it);
1646  }
1647  delete info;
1648  }
1649 
1650  ShowOSDAskAllow();
1651 }
1652 
1654 {
1655  QMutexLocker locker(&m_askAllowLock);
1657  return;
1658 
1659  uint cardid = m_playerContext.GetCardID();
1660 
1661  QString single_rec = tr("MythTV wants to record \"%1\" on %2 in %d seconds. Do you want to:");
1662 
1663  QString record_watch = tr("Record and watch while it records");
1664  QString let_record1 = tr("Let it record and go back to the Main Menu");
1665  QString let_recordm = tr("Let them record and go back to the Main Menu");
1666  QString record_later1 = tr("Record it later, I want to watch TV");
1667  QString record_laterm = tr("Record them later, I want to watch TV");
1668  QString do_not_record1= tr("Don't let it record, I want to watch TV");
1669  QString do_not_recordm= tr("Don't let them record, I want to watch TV");
1670 
1671  // eliminate timed out programs
1672  QDateTime timeNow = MythDate::current();
1673  QMap<QString,AskProgramInfo>::iterator it = m_askAllowPrograms.begin();
1674  while (it != m_askAllowPrograms.end())
1675  {
1676  if ((*it).m_expiry <= timeNow)
1677  {
1678 #if 0
1679  LOG(VB_GENERAL, LOG_DEBUG, LOC + "-- " +
1680  QString("removing '%1'").arg((*it).m_info->m_title));
1681 #endif
1682  delete (*it).m_info;
1683  it = m_askAllowPrograms.erase(it);
1684  }
1685  else
1686  {
1687  it++;
1688  }
1689  }
1690  std::chrono::milliseconds timeuntil = 0ms;
1691  QString message;
1692  uint conflict_count = static_cast<uint>(m_askAllowPrograms.size());
1693 
1694  it = m_askAllowPrograms.begin();
1695  if ((1 == m_askAllowPrograms.size()) && ((*it).m_info->GetInputID() == cardid))
1696  {
1697  (*it).m_isInSameInputGroup = (*it).m_isConflicting = true;
1698  }
1699  else if (!m_askAllowPrograms.empty())
1700  {
1701  // get the currently used input on our card
1702  bool busy_input_grps_loaded = false;
1703  std::vector<uint> busy_input_grps;
1704  InputInfo busy_input;
1705  RemoteIsBusy(cardid, busy_input);
1706 
1707  // check if current input can conflict
1708  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1709  {
1710  (*it).m_isInSameInputGroup =
1711  (cardid == (*it).m_info->GetInputID());
1712 
1713  if ((*it).m_isInSameInputGroup)
1714  continue;
1715 
1716  // is busy_input in same input group as recording
1717  if (!busy_input_grps_loaded)
1718  {
1719  busy_input_grps = CardUtil::GetInputGroups(busy_input.m_inputId);
1720  busy_input_grps_loaded = true;
1721  }
1722 
1723  std::vector<uint> input_grps =
1724  CardUtil::GetInputGroups((*it).m_info->GetInputID());
1725 
1726  for (uint grp : input_grps)
1727  {
1728  if (find(busy_input_grps.begin(), busy_input_grps.end(),
1729  grp) != busy_input_grps.end())
1730  {
1731  (*it).m_isInSameInputGroup = true;
1732  break;
1733  }
1734  }
1735  }
1736 
1737  // check if inputs that can conflict are ok
1738  conflict_count = 0;
1739  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1740  {
1741  if (!(*it).m_isInSameInputGroup)
1742  (*it).m_isConflicting = false; // NOLINT(bugprone-branch-clone)
1743  else if (cardid == (*it).m_info->GetInputID())
1744  (*it).m_isConflicting = true; // NOLINT(bugprone-branch-clone)
1745  else if (!CardUtil::IsTunerShared(cardid, (*it).m_info->GetInputID()))
1746  (*it).m_isConflicting = true;
1747  else if ((busy_input.m_mplexId &&
1748  (busy_input.m_mplexId == (*it).m_info->QueryMplexID())) ||
1749  (!busy_input.m_mplexId &&
1750  (busy_input.m_chanId == (*it).m_info->GetChanID())))
1751  (*it).m_isConflicting = false;
1752  else
1753  (*it).m_isConflicting = true;
1754 
1755  conflict_count += (*it).m_isConflicting ? 1 : 0;
1756  }
1757  }
1758 
1759  it = m_askAllowPrograms.begin();
1760  for (; it != m_askAllowPrograms.end() && !(*it).m_isConflicting; ++it);
1761 
1762  if (conflict_count == 0)
1763  {
1764  LOG(VB_GENERAL, LOG_INFO, LOC + "The scheduler wants to make "
1765  "a non-conflicting recording.");
1766  // TODO take down mplexid and inform user of problem
1767  // on channel changes.
1768  }
1769  else if (conflict_count == 1 && ((*it).m_info->GetInputID() == cardid))
1770  {
1771 #if 0
1772  LOG(VB_GENERAL, LOG_DEBUG, LOC + "UpdateOSDAskAllowDialog -- " +
1773  "kAskAllowOneRec");
1774 #endif
1775 
1776  it = m_askAllowPrograms.begin();
1777 
1778  QString channel = m_dbChannelFormat;
1779  channel
1780  .replace("<num>", (*it).m_info->GetChanNum())
1781  .replace("<sign>", (*it).m_info->GetChannelSchedulingID())
1782  .replace("<name>", (*it).m_info->GetChannelName());
1783 
1784  message = single_rec.arg((*it).m_info->GetTitle(), channel);
1785 
1786  BrowseEnd(false);
1787  timeuntil = MythDate::secsInFuture((*it).m_expiry);
1788  MythOSDDialogData dialog { OSD_DLG_ASKALLOW, message, timeuntil };
1789  dialog.m_buttons.push_back({ record_watch, "DIALOG_ASKALLOW_WATCH_0", false, !((*it).m_hasRec)} );
1790  dialog.m_buttons.push_back({ let_record1, "DIALOG_ASKALLOW_EXIT_0" });
1791  dialog.m_buttons.push_back({ ((*it).m_hasLater) ? record_later1 : do_not_record1,
1792  "DIALOG_ASKALLOW_CANCELRECORDING_0", false, ((*it).m_hasRec) });
1793  emit ChangeOSDDialog(dialog);
1794  }
1795  else
1796  {
1797  if (conflict_count > 1)
1798  {
1799  message = tr(
1800  "MythTV wants to record these programs in %d seconds:");
1801  message += "\n";
1802  }
1803 
1804  bool has_rec = false;
1805  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1806  {
1807  if (!(*it).m_isConflicting)
1808  continue;
1809 
1810  QString title = (*it).m_info->GetTitle();
1811  if ((title.length() < 10) && !(*it).m_info->GetSubtitle().isEmpty())
1812  title += ": " + (*it).m_info->GetSubtitle();
1813  if (title.length() > 20)
1814  title = title.left(17) + "...";
1815 
1816  QString channel = m_dbChannelFormat;
1817  channel
1818  .replace("<num>", (*it).m_info->GetChanNum())
1819  .replace("<sign>", (*it).m_info->GetChannelSchedulingID())
1820  .replace("<name>", (*it).m_info->GetChannelName());
1821 
1822  if (conflict_count > 1)
1823  {
1824  message += tr("\"%1\" on %2").arg(title, channel);
1825  message += "\n";
1826  }
1827  else
1828  {
1829  message = single_rec.arg((*it).m_info->GetTitle(), channel);
1830  has_rec = (*it).m_hasRec;
1831  }
1832  }
1833 
1834  if (conflict_count > 1)
1835  {
1836  message += "\n";
1837  message += tr("Do you want to:");
1838  }
1839 
1840  bool all_have_later = true;
1841  timeuntil = 9999999ms;
1842  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1843  {
1844  if ((*it).m_isConflicting)
1845  {
1846  all_have_later &= (*it).m_hasLater;
1847  auto tmp = std::chrono::milliseconds(MythDate::secsInFuture((*it).m_expiry));
1848  timeuntil = std::clamp(tmp, 0ms, timeuntil);
1849  }
1850  }
1851  timeuntil = (9999999ms == timeuntil) ? 0ms : timeuntil;
1852 
1853  if (conflict_count > 1)
1854  {
1855  BrowseEnd(false);
1856  emit ChangeOSDDialog( { OSD_DLG_ASKALLOW, message, timeuntil, {
1857  { let_recordm, "DIALOG_ASKALLOW_EXIT_0", false, true },
1858  { all_have_later ? record_laterm : do_not_recordm, "DIALOG_ASKALLOW_CANCELCONFLICTING_0" }
1859  }});
1860  }
1861  else
1862  {
1863  BrowseEnd(false);
1864  emit ChangeOSDDialog( {OSD_DLG_ASKALLOW, message, timeuntil, {
1865  { let_record1, "DIALOG_ASKALLOW_EXIT_0", false, !has_rec},
1866  { all_have_later ? record_later1 : do_not_record1, "DIALOG_ASKALLOW_CANCELRECORDING_0", false, has_rec}
1867  }});
1868  }
1869  }
1870 }
1871 
1872 void TV::HandleOSDAskAllow(const QString& Action)
1873 {
1875  return;
1876 
1877  if (!m_askAllowLock.tryLock())
1878  {
1879  LOG(VB_GENERAL, LOG_ERR, "allowrecordingbox : askAllowLock is locked");
1880  return;
1881  }
1882 
1883  if (Action == "CANCELRECORDING")
1884  {
1887  }
1888  else if (Action == "CANCELCONFLICTING")
1889  {
1890  for (const auto& pgm : std::as_const(m_askAllowPrograms))
1891  {
1892  if (pgm.m_isConflicting)
1893  RemoteCancelNextRecording(pgm.m_info->GetInputID(), true);
1894  }
1895  }
1896  else if (Action == "WATCH")
1897  {
1900  }
1901  else // if (action == "EXIT")
1902  {
1903  PrepareToExitPlayer(__LINE__);
1904  SetExitPlayer(true, true);
1905  }
1906 
1907  m_askAllowLock.unlock();
1908 }
1909 
1911 {
1912  m_wantsToQuit = false;
1913  m_jumpToProgram = false;
1914  m_allowRerecord = false;
1915  m_requestDelete = false;
1917 
1920  {
1921  ReturnPlayerLock();
1922  return 0;
1923  }
1924 
1926 
1930 
1931  ReturnPlayerLock();
1932 
1933  if (LCD *lcd = LCD::Get())
1934  {
1935  lcd->switchToChannel(ProgInfo.GetChannelSchedulingID(), ProgInfo.GetTitle(), ProgInfo.GetSubtitle());
1936  lcd->setFunctionLEDs((ProgInfo.IsRecording())?FUNC_TV:FUNC_MOVIE, true);
1937  }
1938 
1939  return 1;
1940 }
1941 
1943 {
1945 }
1946 
1948 {
1949  return (State == kState_WatchingPreRecorded ||
1954 }
1955 
1957 {
1958  return (State == kState_WatchingLiveTV);
1959 }
1960 
1961 // NOLINTBEGIN(cppcoreguidelines-macro-usage)
1962 #define TRANSITION(ASTATE,BSTATE) ((ctxState == (ASTATE)) && (desiredNextState == (BSTATE)))
1963 
1964 #define SET_NEXT() do { nextState = desiredNextState; changed = true; } while(false)
1965 #define SET_LAST() do { nextState = ctxState; changed = true; } while(false)
1966 // NOLINTEND(cppcoreguidelines-macro-usage)
1967 
1968 static QString tv_i18n(const QString &msg)
1969 {
1970  QByteArray msg_arr = msg.toLatin1();
1971  QString msg_i18n = TV::tr(msg_arr.constData());
1972  QByteArray msg_i18n_arr = msg_i18n.toLatin1();
1973  return (msg_arr == msg_i18n_arr) ? msg_i18n : msg;
1974 }
1975 
1985 {
1986  if (m_playerContext.IsErrored())
1987  {
1988  LOG(VB_GENERAL, LOG_ERR, LOC + "Called after fatal error detected.");
1989  return;
1990  }
1991 
1992  bool changed = false;
1993 
1995  TVState nextState = m_playerContext.GetState();
1996  if (m_playerContext.m_nextState.empty())
1997  {
1998  LOG(VB_GENERAL, LOG_WARNING, LOC + "Warning, called with no state to change to.");
2000  return;
2001  }
2002 
2003  TVState ctxState = m_playerContext.GetState();
2004  TVState desiredNextState = m_playerContext.DequeueNextState();
2005 
2006  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Attempting to change from %1 to %2")
2007  .arg(StateToString(nextState), StateToString(desiredNextState)));
2008 
2009  if (desiredNextState == kState_Error)
2010  {
2011  LOG(VB_GENERAL, LOG_ERR, LOC + "Attempting to set to an error state!");
2012  SetErrored();
2014  return;
2015  }
2016 
2017  bool ok = false;
2019  {
2021 
2023 
2024  QDateTime timerOffTime = MythDate::current();
2025  m_lockTimerOn = false;
2026 
2027  SET_NEXT();
2028 
2029  uint chanid = m_initialChanID;
2030  if (!chanid)
2031  chanid = static_cast<uint>(gCoreContext->GetNumSetting("DefaultChanid", 0));
2032 
2033  if (chanid && !IsTunablePriv(chanid))
2034  chanid = 0;
2035 
2036  QString channum = "";
2037 
2038  if (chanid)
2039  {
2040  QStringList reclist;
2041 
2042  MSqlQuery query(MSqlQuery::InitCon());
2043  query.prepare("SELECT channum FROM channel "
2044  "WHERE chanid = :CHANID");
2045  query.bindValue(":CHANID", chanid);
2046  if (query.exec() && query.isActive() && query.size() > 0 && query.next())
2047  channum = query.value(0).toString();
2048  else
2049  channum = QString::number(chanid);
2050 
2052  QString::number(chanid));
2053 
2054  if (getit)
2055  reclist = ChannelUtil::GetValidRecorderList(chanid, channum);
2056 
2057  if (!reclist.empty())
2058  {
2059  RemoteEncoder *testrec = RemoteRequestFreeRecorderFromList(reclist, 0);
2060  if (testrec && testrec->IsValidRecorder())
2061  {
2062  m_playerContext.SetRecorder(testrec);
2064  }
2065  else
2066  {
2067  delete testrec; // If testrec isn't a valid recorder ...
2068  }
2069  }
2070  else if (getit)
2071  {
2072  chanid = 0;
2073  }
2074  }
2075 
2076  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Spawning LiveTV Recorder -- begin");
2077 
2078  if (chanid && !channum.isEmpty())
2080  else
2082 
2083  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Spawning LiveTV Recorder -- end");
2084 
2086  {
2087  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully started");
2089  m_playerContext.SetRecorder(nullptr);
2090  SetErrored();
2091  SET_LAST();
2092  }
2093  else
2094  {
2095  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2096  QString playbackURL = m_playerContext.m_playingInfo->GetPlaybackURL(true);
2097  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2098 
2099  bool opennow = (m_playerContext.m_tvchain->GetInputType(-1) != "DUMMY");
2100 
2101  LOG(VB_GENERAL, LOG_INFO, LOC +
2102  QString("playbackURL(%1) inputtype(%2)")
2103  .arg(playbackURL, m_playerContext.m_tvchain->GetInputType(-1)));
2104 
2107  playbackURL, false, true,
2108  opennow ? MythMediaBuffer::kLiveTVOpenTimeout : -1ms));
2109 
2112  }
2113 
2114 
2116  {
2117  ok = StartPlayer(desiredNextState);
2118  }
2119  if (!ok)
2120  {
2121  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully started");
2123  m_playerContext.SetRecorder(nullptr);
2124  SetErrored();
2125  SET_LAST();
2126  }
2127  else
2128  {
2129  if (!m_lastLockSeenTime.isValid() ||
2130  (m_lastLockSeenTime < timerOffTime))
2131  {
2132  m_lockTimer.start();
2133  m_lockTimerOn = true;
2134  }
2135  }
2136  }
2138  {
2139  SET_NEXT();
2141  StopStuff(true, true, true);
2142  }
2148  {
2149  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2150  QString playbackURL = m_playerContext.m_playingInfo->GetPlaybackURL(true);
2151  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2152 
2153  MythMediaBuffer *buffer = MythMediaBuffer::Create(playbackURL, false);
2154  if (buffer && !buffer->GetLastError().isEmpty())
2155  {
2156  ShowNotificationError(tr("Can't start playback"),
2157  TV::tr( "TV Player" ), buffer->GetLastError());
2158  delete buffer;
2159  buffer = nullptr;
2160  }
2162 
2164  {
2165  if (desiredNextState == kState_WatchingRecording)
2166  {
2167  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2169  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2170 
2172 
2173  if (!m_playerContext.m_recorder ||
2175  {
2176  LOG(VB_GENERAL, LOG_ERR, LOC +
2177  "Couldn't find recorder for in-progress recording");
2178  desiredNextState = kState_WatchingPreRecorded;
2179  m_playerContext.SetRecorder(nullptr);
2180  }
2181  else
2182  {
2184  }
2185  }
2186 
2187  ok = StartPlayer(desiredNextState);
2188 
2189  if (ok)
2190  {
2191  SET_NEXT();
2192 
2193  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2195  {
2196  QString message = "COMMFLAG_REQUEST ";
2198  gCoreContext->SendMessage(message);
2199  }
2200  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2201  }
2202  }
2203 
2204  if (!ok)
2205  {
2206  SET_LAST();
2207  SetErrored();
2209  {
2211  TV::tr( "TV Player" ),
2212  playbackURL);
2213  // We're going to display this error as notification
2214  // no need to display it later as popup
2216  }
2217  }
2218  }
2224  {
2225  SET_NEXT();
2227  StopStuff(true, true, false);
2228  }
2231  {
2232  SET_NEXT();
2233  }
2234 
2235  // Print state changed message...
2236  if (!changed)
2237  {
2238  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unknown state transition: %1 to %2")
2239  .arg(StateToString(m_playerContext.GetState()), StateToString(desiredNextState)));
2240  }
2241  else if (m_playerContext.GetState() != nextState)
2242  {
2243  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Changing from %1 to %2")
2244  .arg(StateToString(m_playerContext.GetState()), StateToString(nextState)));
2245  }
2246 
2247  // update internal state variable
2248  TVState lastState = m_playerContext.GetState();
2249  m_playerContext.m_playingState = nextState;
2251 
2253  {
2254  LOG(VB_GENERAL, LOG_INFO, LOC + "State is LiveTV");
2255  UpdateOSDInput();
2256  LOG(VB_GENERAL, LOG_INFO, LOC + "UpdateOSDInput done");
2257  UpdateLCD();
2258  LOG(VB_GENERAL, LOG_INFO, LOC + "UpdateLCD done");
2259  ITVRestart(true);
2260  LOG(VB_GENERAL, LOG_INFO, LOC + "ITVRestart done");
2261  }
2262  else if (StateIsPlaying(m_playerContext.GetState()) && lastState == kState_None)
2263  {
2264  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2265  int count = PlayGroup::GetCount();
2266  QString msg = tr("%1 Settings")
2268  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2269  if (count > 0)
2270  emit ChangeOSDMessage(msg);
2271  ITVRestart(false);
2272  }
2273 
2275  {
2276  UpdateLCD();
2277  }
2278 
2281 
2287 
2291 
2293  {
2295  }
2296 
2303  {
2305  // m_playerBounds is not applicable when switching modes so
2306  // skip this logic in that case.
2307  if (!m_dbUseVideoModes)
2309 
2310  if (!m_weDisabledGUI)
2311  {
2312  m_weDisabledGUI = true;
2314  }
2315  // we no longer need the contents of myWindow
2316  if (m_myWindow)
2318 
2319  LOG(VB_GENERAL, LOG_INFO, LOC + "Main UI disabled.");
2320  }
2321 
2322  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + " -- end");
2323 }
2324 
2325 #undef TRANSITION
2326 #undef SET_NEXT
2327 #undef SET_LAST
2328 
2334 bool TV::StartRecorder(std::chrono::milliseconds MaxWait)
2335 {
2337  MaxWait = (MaxWait <= 0ms) ? 40s : MaxWait;
2338  MythTimer t;
2339  t.start();
2340  bool recording = false;
2341  bool ok = true;
2342  if (!rec)
2343  {
2344  LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid Remote Encoder");
2345  SetErrored();
2346  return false;
2347  }
2348  while (!(recording = rec->IsRecording(&ok)) && !m_exitPlayerTimerId && t.elapsed() < MaxWait)
2349  {
2350  if (!ok)
2351  {
2352  LOG(VB_GENERAL, LOG_ERR, LOC + "Lost contact with backend");
2353  SetErrored();
2354  return false;
2355  }
2356  std::this_thread::sleep_for(5us);
2357  }
2358 
2359  if (!recording || m_exitPlayerTimerId)
2360  {
2361  if (!m_exitPlayerTimerId)
2362  LOG(VB_GENERAL, LOG_ERR, LOC + "Timed out waiting for recorder to start");
2363  return false;
2364  }
2365 
2366  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Took %1 ms to start recorder.")
2367  .arg(t.elapsed().count()));
2368  return true;
2369 }
2370 
2384 void TV::StopStuff(bool StopRingBuffer, bool StopPlayer, bool StopRecorder)
2385 {
2386  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- begin");
2387 
2388  emit PlaybackExiting(this);
2389 
2392 
2393  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
2394  if (StopPlayer)
2396  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
2397 
2398  if (StopRingBuffer)
2399  {
2400  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Stopping ring buffer");
2402  {
2406  }
2407  }
2408 
2409  if (StopRecorder)
2410  {
2411  LOG(VB_PLAYBACK, LOG_INFO, LOC + "stopping recorder");
2414  }
2415 
2416  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end");
2417 }
2418 
2419 void TV::timerEvent(QTimerEvent *Event)
2420 {
2421  const int timer_id = Event->timerId();
2422 
2424  bool errored = m_playerContext.IsErrored();
2425  ReturnPlayerLock();
2426  if (errored)
2427  return;
2428 
2429  bool handled = true;
2430  if (timer_id == m_lcdTimerId)
2432  else if (timer_id == m_lcdVolumeTimerId)
2434  else if (timer_id == m_sleepTimerId)
2435  ShowOSDSleep();
2436  else if (timer_id == m_sleepDialogTimerId)
2438  else if (timer_id == m_idleTimerId)
2439  ShowOSDIdle();
2440  else if (timer_id == m_idleDialogTimerId)
2442  else if (timer_id == m_endOfPlaybackTimerId)
2444  else if (timer_id == m_endOfRecPromptTimerId)
2446  else if (timer_id == m_videoExitDialogTimerId)
2448  else if (timer_id == m_pseudoChangeChanTimerId)
2450  else if (timer_id == m_speedChangeTimerId)
2452  else if (timer_id == m_saveLastPlayPosTimerId)
2454  else
2455  handled = false;
2456 
2457  if (handled)
2458  return;
2459 
2460  // Check if it matches a signalMonitorTimerId
2461  if (timer_id == m_signalMonitorTimerId)
2462  {
2466  if (!m_playerContext.m_lastSignalMsg.empty())
2467  {
2468  // set last signal msg, so we get some feedback...
2471  }
2473  ReturnPlayerLock();
2474  return;
2475  }
2476 
2477  // Check if it matches networkControlTimerId
2478  QString netCmd;
2479  if (timer_id == m_networkControlTimerId)
2480  {
2481  if (!m_networkControlCommands.empty())
2482  netCmd = m_networkControlCommands.dequeue();
2483  if (m_networkControlCommands.empty())
2484  {
2487  }
2488  }
2489 
2490  if (!netCmd.isEmpty())
2491  {
2494  ReturnPlayerLock();
2495  handled = true;
2496  }
2497 
2498  if (handled)
2499  return;
2500 
2501  // Check if it matches exitPlayerTimerId
2502  if (timer_id == m_exitPlayerTimerId)
2503  {
2505  emit DialogQuit();
2506  emit HideAll();
2507 
2509  {
2510  if (!m_lastProgram->IsFileReadable())
2511  {
2512  emit ChangeOSDMessage(tr("Last Program: \"%1\" Doesn't Exist")
2513  .arg(m_lastProgram->GetTitle()));
2514  lastProgramStringList.clear();
2515  SetLastProgram(nullptr);
2516  LOG(VB_PLAYBACK, LOG_ERR, LOC + "Last Program File does not exist");
2517  m_jumpToProgram = false;
2518  }
2519  else
2520  {
2522  }
2523  }
2524  else
2525  {
2527  }
2528 
2529  ReturnPlayerLock();
2530 
2532  m_exitPlayerTimerId = 0;
2533  handled = true;
2534  }
2535 
2536  if (handled)
2537  return;
2538 
2539  if (timer_id == m_ccInputTimerId)
2540  {
2542  // Clear closed caption input mode when timer expires
2543  if (m_ccInputMode)
2544  {
2545  m_ccInputMode = false;
2546  ClearInputQueues(true);
2547  }
2548  ReturnPlayerLock();
2549 
2551  m_ccInputTimerId = 0;
2552  handled = true;
2553  }
2554 
2555  if (handled)
2556  return;
2557 
2558  if (timer_id == m_asInputTimerId)
2559  {
2561  // Clear closed caption input mode when timer expires
2562  if (m_asInputMode)
2563  {
2564  m_asInputMode = false;
2565  ClearInputQueues(true);
2566  }
2567  ReturnPlayerLock();
2568 
2570  m_asInputTimerId = 0;
2571  handled = true;
2572  }
2573 
2574  if (handled)
2575  return;
2576 
2577  if (timer_id == m_queueInputTimerId)
2578  {
2580  // Commit input when the OSD fades away
2581  if (HasQueuedChannel())
2582  {
2583  OSD *osd = GetOSDL();
2584  if (osd && !osd->IsWindowVisible(OSD_WIN_INPUT))
2585  {
2586  ReturnOSDLock();
2588  }
2589  else
2590  {
2591  ReturnOSDLock();
2592  }
2593  }
2594  ReturnPlayerLock();
2595 
2596  if (!m_queuedChanID && m_queuedChanNum.isEmpty() && m_queueInputTimerId)
2597  {
2599  m_queueInputTimerId = 0;
2600  }
2601  handled = true;
2602  }
2603 
2604  if (handled)
2605  return;
2606 
2607  if (timer_id == m_browseTimerId)
2608  {
2610  BrowseEnd(false);
2611  ReturnPlayerLock();
2612  handled = true;
2613  }
2614 
2615  if (handled)
2616  return;
2617 
2618  if (timer_id == m_errorRecoveryTimerId)
2619  {
2623  {
2624  SetExitPlayer(true, false);
2626  }
2627  ReturnPlayerLock();
2628 
2632  return;
2633  }
2634 
2635  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Unknown timer: %1").arg(timer_id));
2636 }
2637 
2639 {
2641  LCD *lcd = LCD::Get();
2642  if (lcd)
2643  {
2644  float progress = 0.0F;
2645  QString lcd_time_string;
2646  bool showProgress = true;
2647 
2648  if (StateIsLiveTV(GetState()))
2650 
2652  {
2653  ShowLCDDVDInfo();
2655  }
2656 
2657  if (showProgress)
2658  {
2659  osdInfo info;
2661  progress = info.values["position"] * 0.001F;
2662 
2663  lcd_time_string = info.text["playedtime"] + " / " + info.text["totaltime"];
2664  // if the string is longer than the LCD width, remove all spaces
2665  if (lcd_time_string.length() > lcd->getLCDWidth())
2666  lcd_time_string.remove(' ');
2667  }
2668  }
2669  lcd->setChannelProgress(lcd_time_string, progress);
2670  }
2671  ReturnPlayerLock();
2672 
2674  m_lcdTimerId = StartTimer(kLCDTimeout, __LINE__);
2675 
2676  return true;
2677 }
2678 
2680 {
2682  LCD *lcd = LCD::Get();
2683  if (lcd)
2684  {
2687  }
2688  ReturnPlayerLock();
2689 
2691  m_lcdVolumeTimerId = 0;
2692 }
2693 
2694 int TV::StartTimer(std::chrono::milliseconds Interval, int Line)
2695 {
2696  int timer = startTimer(Interval);
2697  if (!timer)
2698  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to start timer on line %1 of %2").arg(Line).arg(__FILE__));
2699  return timer;
2700 }
2701 
2702 void TV::KillTimer(int Id)
2703 {
2704  killTimer(Id);
2705 }
2706 
2708 {
2711 }
2712 
2714 {
2715  auto StateChange = [&]()
2716  {
2718  if (!m_playerContext.m_nextState.empty())
2719  {
2721  if ((kState_None == m_playerContext.GetState() ||
2723  {
2724  ReturnPlayerLock();
2727  m_player = nullptr;
2728  }
2729  }
2730  ReturnPlayerLock();
2731  };
2732 
2733  QTimer::singleShot(0, this, StateChange);
2734 }
2735 
2737 {
2738  auto InputChange = [&]()
2739  {
2741  if (m_switchToInputId)
2742  {
2744  m_switchToInputId = 0;
2745  SwitchInputs(0, QString(), tmp);
2746  }
2747  ReturnPlayerLock();
2748  };
2749 
2750  QTimer::singleShot(0, this, InputChange);
2751 }
2752 
2754 {
2755  m_playerContext.m_errored = true;
2757  m_errorRecoveryTimerId = StartTimer(1ms, __LINE__);
2758 }
2759 
2761 {
2762  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switching to program: %1")
2763  .arg(ProgInfo.toString(ProgramInfo::kTitleSubtitle)));
2765  PrepareToExitPlayer(__LINE__);
2766  m_jumpToProgram = true;
2767  SetExitPlayer(true, true);
2768 }
2769 
2771 {
2772  m_playerContext.LockDeletePlayer(__FILE__, Line);
2774  {
2775  // Clear last play position when we're at the end of a recording.
2776  // unless the recording is in-progress.
2777  bool at_end = !StateIsRecording(m_playerContext.GetState()) &&
2779 
2780  // Clear last play position on exit when the user requested this
2781  if (m_clearPosOnExit)
2782  {
2783  at_end = true;
2784  }
2785 
2786  // Save total frames for video file if not already present
2788  {
2789  auto totalFrames = m_playerContext.m_playingInfo->QueryTotalFrames();
2790  if (!totalFrames)
2791  {
2794  }
2795  }
2796 
2797  // Clear/Save play position without notification
2798  // The change must be broadcast when file is no longer in use
2799  // to update previews, ie. with the MarkNotInUse notification
2800  uint64_t frame = at_end ? 0 : m_playerContext.m_player->GetFramesPlayed();
2802  emit UpdateLastPlayPosition(frame);
2803  if (m_dbAutoSetWatched)
2804  m_player->SetWatched();
2805  }
2806  m_playerContext.UnlockDeletePlayer(__FILE__, Line);
2807 }
2808 
2809 void TV::SetExitPlayer(bool SetIt, bool WantsTo)
2810 {
2811  if (SetIt)
2812  {
2813  m_wantsToQuit = WantsTo;
2814  if (!m_exitPlayerTimerId)
2815  m_exitPlayerTimerId = StartTimer(1ms, __LINE__);
2816  }
2817  else
2818  {
2819  if (m_exitPlayerTimerId)
2821  m_exitPlayerTimerId = 0;
2822  m_wantsToQuit = WantsTo;
2823  }
2824 }
2825 
2827 {
2831 
2832  bool is_playing = false;
2834  if (StateIsPlaying(GetState()))
2835  {
2837  {
2838  is_playing = true;
2839  }
2840  // If the end of playback is destined to pop up the end of
2841  // recording delete prompt, then don't exit the player here.
2842  else if (GetState() != kState_WatchingPreRecorded ||
2844  {
2846  m_endOfRecording = true;
2847  PrepareToExitPlayer(__LINE__);
2848  SetExitPlayer(true, true);
2849  }
2850  }
2851  ReturnPlayerLock();
2852 
2853  if (is_playing)
2855 }
2856 
2858 {
2861  {
2862  return;
2863  }
2864 
2866  OSD *osd = GetOSDL();
2867  if (osd && osd->DialogVisible())
2868  {
2869  ReturnOSDLock();
2870  ReturnPlayerLock();
2871  return;
2872  }
2873  ReturnOSDLock();
2874 
2875  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
2876  bool do_prompt = (m_playerContext.GetState() == kState_WatchingPreRecorded &&
2878  !m_player->IsPlaying());
2879  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
2880 
2881  if (do_prompt)
2882  ShowOSDPromptDeleteRecording(tr("End Of Recording"));
2883 
2884  ReturnPlayerLock();
2885 }
2886 
2888 {
2892 
2893  // disable dialog and exit playback after timeout
2895  OSD *osd = GetOSDL();
2896  if (!osd || !osd->DialogVisible(OSD_DLG_VIDEOEXIT))
2897  {
2898  ReturnOSDLock();
2899  ReturnPlayerLock();
2900  return;
2901  }
2902  ReturnOSDLock();
2903  DoTogglePause(true);
2904  ClearOSD();
2905  PrepareToExitPlayer(__LINE__);
2906  ReturnPlayerLock();
2907 
2908  m_requestDelete = false;
2909  SetExitPlayer(true, true);
2910 }
2911 
2913 {
2916 
2917  bool restartTimer = false;
2920  {
2922  {
2923  restartTimer = true;
2924  }
2925  else
2926  {
2927  LOG(VB_CHANNEL, LOG_INFO, "REC_PROGRAM -- channel change");
2928 
2930  QString channum = m_playerContext.m_pseudoLiveTVRec->GetChanNum();
2932 
2933  m_playerContext.m_prevChan.clear();
2934  ChangeChannel(chanid, channum);
2937  }
2938  }
2939  ReturnPlayerLock();
2940 
2941  if (restartTimer)
2943  m_pseudoChangeChanTimerId = StartTimer(25ms, __LINE__);
2944 }
2945 
2946 void TV::SetSpeedChangeTimer(std::chrono::milliseconds When, int Line)
2947 {
2950  m_speedChangeTimerId = StartTimer(When, Line);
2951 }
2952 
2954 {
2958 
2960  bool update_msg = m_playerContext.HandlePlayerSpeedChangeFFRew();
2962  if (update_msg)
2964  ReturnPlayerLock();
2965 }
2966 
2990 bool TV::eventFilter(QObject* Object, QEvent* Event)
2991 {
2992  // We want to intercept all resize events sent to the main window
2993  if ((Event->type() == QEvent::Resize))
2994  return (m_mainWindow != Object) ? false : event(Event);
2995 
2996  // Intercept keypress events unless they need to be handled by a main UI
2997  // screen (e.g. GuideGrid, ProgramFinder)
2998 
2999  if ( (QEvent::KeyPress == Event->type() || QEvent::KeyRelease == Event->type())
3000  && m_ignoreKeyPresses )
3001  return TVPlaybackState::eventFilter(Object, Event);
3002 
3003  QScopedPointer<QEvent> sNewEvent(nullptr);
3004  if (m_mainWindow->KeyLongPressFilter(&Event, sNewEvent))
3005  return true;
3006 
3007  if (QEvent::KeyPress == Event->type())
3008  return event(Event);
3009 
3010  if (MythGestureEvent::kEventType == Event->type())
3011  return m_ignoreKeyPresses ? false : event(Event);
3012 
3013  if (Event->type() == MythEvent::kMythEventMessage ||
3014  Event->type() == MythEvent::kMythUserMessage ||
3016  Event->type() == MythMediaEvent::kEventType)
3017  {
3018  customEvent(Event);
3019  return true;
3020  }
3021 
3022  switch (Event->type())
3023  {
3024  case QEvent::Paint:
3025  case QEvent::UpdateRequest:
3026  case QEvent::Enter:
3027  {
3028  event(Event);
3029  return TVPlaybackState::eventFilter(Object, Event);
3030  }
3031  default:
3032  return TVPlaybackState::eventFilter(Object, Event);
3033  }
3034 }
3035 
3037 bool TV::event(QEvent* Event)
3038 {
3039  if (Event == nullptr)
3040  return TVPlaybackState::event(Event);
3041 
3042  if (QEvent::Resize == Event->type())
3043  {
3044  // These events probably aren't received by a direct call from
3045  // the Qt event dispacther, but are received by way of the event
3046  // dispatcher calling TV::eventFilter(MainWindow, Event).
3047  const auto *qre = dynamic_cast<const QResizeEvent*>(Event);
3048  if (qre)
3049  emit WindowResized(qre->size());
3050  return TVPlaybackState::event(Event);
3051  }
3052 
3053  if (QEvent::KeyPress == Event->type() || MythGestureEvent::kEventType == Event->type())
3054  {
3055  // These events aren't received by a direct call from the Qt
3056  // event dispacther, but are received by way of the event
3057  // dispatcher calling TV::eventFilter(MainWindow, Event).
3058 #if DEBUG_ACTIONS
3059  if (QEvent::KeyPress == Event->type())
3060  {
3061  const auto * ke = dynamic_cast<QKeyEvent*>(Event);
3062  if (ke)
3063  {
3064  LOG(VB_GENERAL, LOG_INFO, LOC + QString("keypress: %1 '%2'")
3065  .arg(ke->key()).arg(ke->text()));
3066  }
3067  }
3068  else
3069  {
3070  const auto * ge = dynamic_cast<MythGestureEvent*>(Event);
3071  if (ge)
3072  {
3073  LOG(VB_GENERAL, LOG_INFO, LOC + QString("mythgesture: g:%1 pos:%2,%3 b:%4")
3074  .arg(ge->GetGesture()).arg(ge->GetPosition().x())
3075  .arg(ge->GetPosition().y()).arg(ge->GetButton()));
3076  }
3077  }
3078 #endif
3079  bool handled = false;
3081  if (m_playerContext.HasPlayer())
3082  handled = ProcessKeypressOrGesture(Event);
3083  ReturnPlayerLock();
3084  if (handled)
3085  return true;
3086  }
3087 
3088  switch (Event->type())
3089  {
3090  case QEvent::Paint:
3091  case QEvent::UpdateRequest:
3092  case QEvent::Enter:
3093  // These events aren't received by a direct call from the Qt
3094  // event dispacther, but are received by way of the event
3095  // dispatcher calling TV::eventFilter(MainWindow, Event).
3096  return true;
3097  default:
3098  break;
3099  }
3100 
3101  return QObject::event(Event);
3102 }
3103 
3104 bool TV::HandleTrackAction(const QString &Action)
3105 {
3106  bool handled = true;
3107 
3110  else if (ACTION_ENABLEEXTTEXT == Action)
3112  else if (ACTION_DISABLEEXTTEXT == Action)
3114  else if (ACTION_ENABLEFORCEDSUBS == Action)
3115  emit ChangeAllowForcedSubtitles(true);
3116  else if (ACTION_DISABLEFORCEDSUBS == Action)
3117  emit ChangeAllowForcedSubtitles(false);
3118  else if (Action == ACTION_ENABLESUBS)
3119  emit SetCaptionsEnabled(true, true);
3120  else if (Action == ACTION_DISABLESUBS)
3121  emit SetCaptionsEnabled(false, true);
3123  {
3124  if (m_ccInputMode)
3125  {
3126  bool valid = false;
3127  int page = GetQueuedInputAsInt(&valid, 16);
3128  if (m_vbimode == VBIMode::PAL_TT && valid)
3129  emit SetTeletextPage(static_cast<uint>(page));
3130  else if (m_vbimode == VBIMode::NTSC_CC)
3131  emit SetTrack(kTrackTypeCC608, static_cast<uint>(std::clamp(page - 1, 0, 1)));
3132 
3133  ClearInputQueues(true);
3134 
3135  m_ccInputMode = false;
3136  if (m_ccInputTimerId)
3137  {
3139  m_ccInputTimerId = 0;
3140  }
3141  }
3143  {
3144  ClearInputQueues(false);
3145  AddKeyToInputQueue(0);
3146 
3147  m_ccInputMode = true;
3148  m_asInputMode = false;
3150  if (m_asInputTimerId)
3151  {
3153  m_asInputTimerId = 0;
3154  }
3155  }
3156  else
3157  {
3158  emit ToggleCaptions();
3159  }
3160  }
3161  else if (Action.startsWith("TOGGLE"))
3162  {
3163  int type = to_track_type(Action.mid(6));
3165  emit EnableTeletext();
3166  else if (type >= kTrackTypeSubtitle)
3167  emit ToggleCaptionsByType(static_cast<uint>(type));
3168  else
3169  handled = false;
3170  }
3171  else if (Action.startsWith("SELECT"))
3172  {
3173  int type = to_track_type(Action.mid(6));
3174  uint num = Action.section("_", -1).toUInt();
3175  if (type >= kTrackTypeAudio)
3176  emit SetTrack(static_cast<uint>(type), num);
3177  else
3178  handled = false;
3179  }
3180  else if (Action.startsWith("NEXT") || Action.startsWith("PREV"))
3181  {
3182  int dir = (Action.startsWith("NEXT")) ? +1 : -1;
3183  int type = to_track_type(Action.mid(4));
3184  if (type >= kTrackTypeAudio)
3185  emit ChangeTrack(static_cast<uint>(type), dir);
3186  else if (Action.endsWith("CC"))
3187  emit ChangeCaptionTrack(dir);
3188  else
3189  handled = false;
3190  }
3191  else
3192  {
3193  handled = false;
3194  }
3195  return handled;
3196 }
3197 
3198 // Make a special check for global system-related events.
3199 //
3200 // This check needs to be done early in the keypress event processing,
3201 // because FF/REW processing causes unknown events to stop FF/REW, and
3202 // manual zoom mode processing consumes all but a few event types.
3203 // Ideally, we would just call MythScreenType::keyPressEvent()
3204 // unconditionally, but we only want certain keypresses handled by
3205 // that method.
3206 //
3207 // As a result, some of the MythScreenType::keyPressEvent() string
3208 // compare logic is copied here.
3209 static bool SysEventHandleAction(MythMainWindow* MainWindow, QKeyEvent *e, const QStringList &actions)
3210 {
3211  QStringList::const_iterator it;
3212  for (it = actions.begin(); it != actions.end(); ++it)
3213  {
3214  if ((*it).startsWith("SYSEVENT") ||
3215  *it == ACTION_SCREENSHOT ||
3216  *it == ACTION_TVPOWERON ||
3217  *it == ACTION_TVPOWEROFF)
3218  {
3219  return MainWindow->GetMainStack()->GetTopScreen()->keyPressEvent(e);
3220  }
3221  }
3222  return false;
3223 }
3224 
3225 QList<QKeyEvent*> TV::ConvertScreenPressKeyMap(const QString &KeyList)
3226 {
3227  QList<QKeyEvent*> keyPressList;
3228  int i = 0;
3229  QStringList stringKeyList = KeyList.split(',');
3230  for (const auto & str : std::as_const(stringKeyList))
3231  {
3232  QKeySequence keySequence(str);
3233  for (i = 0; i < keySequence.count(); i++)
3234  {
3235 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
3236  int keynum = keySequence[i];
3237  int keyCode = keynum & ~Qt::KeyboardModifierMask;
3238  auto modifiers = static_cast<Qt::KeyboardModifiers>(keynum & Qt::KeyboardModifierMask);
3239 #else
3240  int keyCode = keySequence[i].key();
3241  Qt::KeyboardModifiers modifiers = keySequence[i].keyboardModifiers();
3242 #endif
3243  auto * keyEvent = new QKeyEvent(QEvent::None, keyCode, modifiers);
3244  keyPressList.append(keyEvent);
3245  }
3246  }
3247  if (stringKeyList.count() < kScreenPressRegionCount)
3248  {
3249  // add default remainders
3250  for(; i < kScreenPressRegionCount; i++)
3251  {
3252  auto * keyEvent = new QKeyEvent(QEvent::None, Qt::Key_Escape, Qt::NoModifier);
3253  keyPressList.append(keyEvent);
3254  }
3255  }
3256  return keyPressList;
3257 }
3258 
3259 bool TV::TranslateGesture(const QString &Context, MythGestureEvent *Event,
3260  QStringList &Actions, bool IsLiveTV)
3261 {
3262  if (Event && Context == "TV Playback")
3263  {
3264  // TODO make this configuable via a similar mechanism to
3265  // TranslateKeyPress
3266  // possibly with configurable hot zones of various sizes in a theme
3267  // TODO enhance gestures to support other non Click types too
3268  if ((Event->GetGesture() == MythGestureEvent::Click) &&
3269  (Event->GetButton() == Qt::LeftButton))
3270  {
3271  // divide screen into 12 regions
3272  QSize size = m_mainWindow->size();
3273  QPoint pos = Event->GetPosition();
3274  int region = 0;
3275  const int widthDivider = 4;
3276  int w4 = size.width() / widthDivider;
3277  region = pos.x() / w4;
3278  int h3 = size.height() / 3;
3279  region += (pos.y() / h3) * widthDivider;
3280 
3281  if (IsLiveTV)
3282  return m_mainWindow->TranslateKeyPress(Context, m_screenPressKeyMapLiveTV[region], Actions, true);
3283  return m_mainWindow->TranslateKeyPress(Context, m_screenPressKeyMapPlayback[region], Actions, true);
3284  }
3285  return false;
3286  }
3287  return false;
3288 }
3289 
3290 bool TV::TranslateKeyPressOrGesture(const QString &Context, QEvent *Event,
3291  QStringList &Actions, bool IsLiveTV, bool AllowJumps)
3292 {
3293  if (Event)
3294  {
3295  if (QEvent::KeyPress == Event->type())
3296  return m_mainWindow->TranslateKeyPress(Context, dynamic_cast<QKeyEvent*>(Event), Actions, AllowJumps);
3297  if (MythGestureEvent::kEventType == Event->type())
3298  return TranslateGesture(Context, dynamic_cast<MythGestureEvent*>(Event), Actions, IsLiveTV);
3299  }
3300  return false;
3301 }
3302 
3304 {
3305  if (Event == nullptr)
3306  return false;
3307 
3308  bool ignoreKeys = m_playerContext.IsPlayerChangingBuffers();
3309 
3310 #if DEBUG_ACTIONS
3311  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("ignoreKeys: %1").arg(ignoreKeys));
3312 #endif
3313 
3314  if (m_idleTimerId)
3315  {
3318  }
3319 
3320 #ifdef Q_OS_LINUX
3321  // Fixups for _some_ linux native codes that QT doesn't know
3322  auto* eKeyEvent = dynamic_cast<QKeyEvent*>(Event);
3323  if (eKeyEvent) {
3324  if (eKeyEvent->key() <= 0)
3325  {
3326  int keycode = 0;
3327  switch(eKeyEvent->nativeScanCode())
3328  {
3329  case 209: // XF86AudioPause
3330  keycode = Qt::Key_MediaPause;
3331  break;
3332  default:
3333  break;
3334  }
3335 
3336  if (keycode > 0)
3337  {
3338  auto *key = new QKeyEvent(QEvent::KeyPress, keycode, eKeyEvent->modifiers());
3339  QCoreApplication::postEvent(this, key);
3340  }
3341  }
3342  }
3343 #endif
3344 
3345  QStringList actions;
3346  bool handled = false;
3347  bool alreadyTranslatedPlayback = false;
3348 
3349  TVState state = GetState();
3350  bool isLiveTV = StateIsLiveTV(state);
3351 
3352  if (ignoreKeys)
3353  {
3354  handled = TranslateKeyPressOrGesture("TV Playback", Event, actions, isLiveTV);
3355  alreadyTranslatedPlayback = true;
3356 
3357  if (handled || actions.isEmpty())
3358  return handled;
3359 
3360  bool esc = IsActionable({ "ESCAPE", "BACK" }, actions);
3361  bool pause = IsActionable(ACTION_PAUSE, actions);
3362  bool play = IsActionable(ACTION_PLAY, actions);
3363 
3364  if ((!esc || m_overlayState.m_browsing) && !pause && !play)
3365  return false;
3366  }
3367 
3368  OSD *osd = GetOSDL();
3369  if (osd && osd->DialogVisible())
3370  {
3371  if (QEvent::KeyPress == Event->type())
3372  {
3373  auto *qke = dynamic_cast<QKeyEvent*>(Event);
3374  handled = (qke != nullptr) && osd->DialogHandleKeypress(qke);
3375  }
3376  if (MythGestureEvent::kEventType == Event->type())
3377  {
3378  auto *mge = dynamic_cast<MythGestureEvent*>(Event);
3379  handled = (mge != nullptr) && osd->DialogHandleGesture(mge);
3380  }
3381  }
3382  ReturnOSDLock();
3383 
3384  if (m_overlayState.m_editing && !handled)
3385  {
3386  handled |= TranslateKeyPressOrGesture("TV Editing", Event, actions, isLiveTV);
3387 
3388  if (!handled && m_player)
3389  {
3390  if (IsActionable("MENU", actions))
3391  {
3392  ShowOSDCutpoint("EDIT_CUT_POINTS");
3393  handled = true;
3394  }
3395  if (IsActionable(ACTION_MENUCOMPACT, actions))
3396  {
3397  ShowOSDCutpoint("EDIT_CUT_POINTS_COMPACT");
3398  handled = true;
3399  }
3400  if (IsActionable("ESCAPE", actions))
3401  {
3402  emit RefreshEditorState(true);
3403  if (!m_editorState.m_saved)
3404  ShowOSDCutpoint("EXIT_EDIT_MODE");
3405  else
3406  emit DisableEdit(0);
3407  handled = true;
3408  }
3409  else
3410  {
3411  emit RefreshEditorState();
3414  {
3415  ShowOSDCutpoint("EDIT_CUT_POINTS");
3416  handled = true;
3417  }
3418  else
3419  {
3420  handled |= m_player->HandleProgramEditorActions(actions);
3421  }
3422  }
3423  }
3424  }
3425 
3426  if (handled)
3427  return true;
3428 
3429  // If text is already queued up, be more lax on what is ok.
3430  // This allows hex teletext entry and minor channel entry.
3431  if (QEvent::KeyPress == Event->type())
3432  {
3433  auto *qke = dynamic_cast<QKeyEvent*>(Event);
3434  if (qke == nullptr)
3435  return false;
3436  const QString txt = qke->text();
3437  if (HasQueuedInput() && (1 == txt.length()))
3438  {
3439  bool ok = false;
3440  (void)txt.toInt(&ok, 16);
3441  if (ok || txt=="_" || txt=="-" || txt=="#" || txt==".")
3442  {
3443  AddKeyToInputQueue(txt.at(0).toLatin1());
3444  return true;
3445  }
3446  }
3447  }
3448 
3449  // Teletext menu
3451  {
3452  QStringList tt_actions;
3453  handled = TranslateKeyPressOrGesture("Teletext Menu", Event, tt_actions, isLiveTV);
3454 
3455  if (!handled && !tt_actions.isEmpty())
3456  {
3457  for (const QString& action : std::as_const(tt_actions))
3458  {
3459  emit HandleTeletextAction(action, handled);
3460  if (handled)
3461  return true;
3462  }
3463  }
3464  }
3465 
3466  // Interactive television
3468  {
3469  if (!alreadyTranslatedPlayback)
3470  {
3471  handled = TranslateKeyPressOrGesture("TV Playback", Event, actions, isLiveTV);
3472  alreadyTranslatedPlayback = true;
3473  }
3474 
3475  if (!handled && !actions.isEmpty())
3476  {
3477  for (const QString& action : std::as_const(actions))
3478  {
3479  emit HandleITVAction(action, handled);
3480  if (handled)
3481  return true;
3482  }
3483  }
3484  }
3485 
3486  if (!alreadyTranslatedPlayback)
3487  handled = TranslateKeyPressOrGesture("TV Playback", Event, actions, isLiveTV);
3488 
3489  if (handled || actions.isEmpty())
3490  return handled;
3491 
3492  handled = false;
3493 
3496 
3497  if (QEvent::KeyPress == Event->type())
3498  handled = handled || SysEventHandleAction(m_mainWindow, dynamic_cast<QKeyEvent*>(Event), actions);
3499  handled = handled || BrowseHandleAction(actions);
3500  handled = handled || ManualZoomHandleAction(actions);
3501  handled = handled || PictureAttributeHandleAction(actions);
3502  handled = handled || TimeStretchHandleAction(actions);
3503  handled = handled || AudioSyncHandleAction(actions);
3504  handled = handled || SubtitleZoomHandleAction(actions);
3505  handled = handled || SubtitleDelayHandleAction(actions);
3506  handled = handled || DiscMenuHandleAction(actions);
3507  handled = handled || ActiveHandleAction(actions, isDVD, isMenuOrStill);
3508  handled = handled || ToggleHandleAction(actions, isDVD);
3509  handled = handled || FFRewHandleAction(actions);
3510  handled = handled || ActivePostQHandleAction(actions);
3511 
3512 #if DEBUG_ACTIONS
3513  for (int i = 0; i < actions.size(); ++i)
3514  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("handled(%1) actions[%2](%3)")
3515  .arg(handled).arg(i).arg(actions[i]));
3516 #endif // DEBUG_ACTIONS
3517 
3518  if (handled)
3519  return true;
3520 
3521  if (!handled)
3522  {
3523  for (int i = 0; i < actions.size() && !handled; i++)
3524  {
3525  const QString& action = actions[i];
3526  bool ok = false;
3527  int val = action.toInt(&ok);
3528 
3529  if (ok)
3530  {
3531  AddKeyToInputQueue(static_cast<char>('0' + val));
3532  handled = true;
3533  }
3534  }
3535  }
3536 
3537  return true;
3538 }
3539 
3540 bool TV::BrowseHandleAction(const QStringList &Actions)
3541 {
3543  return false;
3544 
3545  bool handled = true;
3546 
3547  if (IsActionable({ ACTION_UP, ACTION_CHANNELUP }, Actions))
3549  else if (IsActionable( { ACTION_DOWN, ACTION_CHANNELDOWN }, Actions))
3551  else if (IsActionable(ACTION_LEFT, Actions))
3553  else if (IsActionable(ACTION_RIGHT, Actions))
3555  else if (IsActionable("NEXTFAV", Actions))
3557  else if (IsActionable(ACTION_SELECT, Actions))
3558  BrowseEnd(true);
3559  else if (IsActionable({ ACTION_CLEAROSD, "ESCAPE", "BACK", "TOGGLEBROWSE" }, Actions))
3560  BrowseEnd(false);
3561  else if (IsActionable(ACTION_TOGGLERECORD, Actions))
3562  QuickRecord();
3563  else
3564  {
3565  handled = false;
3566  for (const auto& action : std::as_const(Actions))
3567  {
3568  if (action.length() == 1 && action[0].isDigit())
3569  {
3570  AddKeyToInputQueue(action[0].toLatin1());
3571  handled = true;
3572  }
3573  }
3574  }
3575 
3576  // only pass-through actions listed below
3577  static const QStringList passthrough =
3578  {
3579  ACTION_VOLUMEUP, ACTION_VOLUMEDOWN, "STRETCHINC", "STRETCHDEC",
3580  ACTION_MUTEAUDIO, "CYCLEAUDIOCHAN", "BOTTOMLINEMOVE", "BOTTOMLINESAVE", "TOGGLEASPECT"
3581  };
3582  return handled || !IsActionable(passthrough, Actions);
3583 }
3584 
3585 bool TV::ManualZoomHandleAction(const QStringList &Actions)
3586 {
3587  if (!m_zoomMode)
3588  return false;
3589 
3590  bool endmanualzoom = false;
3591  bool handled = true;
3592  bool updateOSD = true;
3593  ZoomDirection zoom = kZoom_END;
3595  zoom = kZoomUp;
3597  zoom = kZoomDown;
3598  else if (IsActionable({ ACTION_ZOOMLEFT, ACTION_LEFT }, Actions))
3599  zoom = kZoomLeft;
3600  else if (IsActionable({ ACTION_ZOOMRIGHT, ACTION_RIGHT }, Actions))
3601  zoom = kZoomRight;
3602  else if (IsActionable({ ACTION_ZOOMASPECTUP, ACTION_VOLUMEUP }, Actions))
3603  zoom = kZoomAspectUp;
3604  else if (IsActionable({ ACTION_ZOOMASPECTDOWN, ACTION_VOLUMEDOWN }, Actions))
3605  zoom = kZoomAspectDown;
3606  else if (IsActionable({ ACTION_ZOOMIN, ACTION_JUMPFFWD }, Actions))
3607  zoom = kZoomIn;
3608  else if (IsActionable({ ACTION_ZOOMOUT, ACTION_JUMPRWND }, Actions))
3609  zoom = kZoomOut;
3610  else if (IsActionable(ACTION_ZOOMVERTICALIN, Actions))
3611  zoom = kZoomVerticalIn;
3612  else if (IsActionable(ACTION_ZOOMVERTICALOUT, Actions))
3613  zoom = kZoomVerticalOut;
3614  else if (IsActionable(ACTION_ZOOMHORIZONTALIN, Actions))
3615  zoom = kZoomHorizontalIn;
3616  else if (IsActionable(ACTION_ZOOMHORIZONTALOUT, Actions))
3617  zoom = kZoomHorizontalOut;
3618  else if (IsActionable({ ACTION_ZOOMQUIT, "ESCAPE", "BACK" }, Actions))
3619  {
3620  zoom = kZoomHome;
3621  endmanualzoom = true;
3622  }
3623  else if (IsActionable({ ACTION_ZOOMCOMMIT, ACTION_SELECT }, Actions))
3624  {
3625  endmanualzoom = true;
3626  SetManualZoom(false, tr("Zoom Committed"));
3627  }
3628  else
3629  {
3630  updateOSD = false;
3631  // only pass-through actions listed below
3632  static const QStringList passthrough =
3633  {
3634  "STRETCHINC", "STRETCHDEC", ACTION_MUTEAUDIO,
3635  "CYCLEAUDIOCHAN", ACTION_PAUSE, ACTION_CLEAROSD
3636  };
3637  handled = !IsActionable(passthrough, Actions);
3638  }
3639 
3640  QString msg = tr("Zoom Committed");
3641  if (zoom != kZoom_END)
3642  {
3643  emit ChangeZoom(zoom);
3644  msg = endmanualzoom ? tr("Zoom Ignored") :
3648  }
3649  else if (endmanualzoom)
3650  {
3651  msg = tr("%1 Committed").arg(GetZoomString(m_videoBoundsState.m_manualHorizScale,
3654  }
3655 
3656  if (updateOSD)
3657  SetManualZoom(!endmanualzoom, msg);
3658 
3659  return handled;
3660 }
3661 
3662 bool TV::PictureAttributeHandleAction(const QStringList &Actions)
3663 {
3664  if (!m_adjustingPicture)
3665  return false;
3666 
3667  bool up = IsActionable(ACTION_RIGHT, Actions);
3668  bool down = up ? false : IsActionable(ACTION_LEFT, Actions);
3669  if (!(up || down))
3670  return false;
3671 
3673  {
3675  VolumeChange(up);
3676  else
3678  return true;
3679  }
3680 
3681  int value = 99;
3685  UpdateOSDStatus(toTitleString(m_adjustingPicture), text, QString::number(value),
3687  emit ChangeOSDPositionUpdates(false);
3688  return true;
3689 }
3690 
3691 bool TV::TimeStretchHandleAction(const QStringList &Actions)
3692 {
3693  if (!m_stretchAdjustment)
3694  return false;
3695 
3696  bool handled = true;
3697 
3698  if (IsActionable(ACTION_LEFT, Actions))
3699  ChangeTimeStretch(-1);
3700  else if (IsActionable(ACTION_RIGHT, Actions))
3701  ChangeTimeStretch(1);
3702  else if (IsActionable(ACTION_DOWN, Actions))
3703  ChangeTimeStretch(-5);
3704  else if (IsActionable(ACTION_UP, Actions))
3705  ChangeTimeStretch(5);
3706  else if (IsActionable("ADJUSTSTRETCH", Actions))
3708  else if (IsActionable(ACTION_SELECT, Actions))
3709  ClearOSD();
3710  else
3711  handled = false;
3712 
3713  return handled;
3714 }
3715 
3716 bool TV::AudioSyncHandleAction(const QStringList& Actions)
3717 {
3718  if (!m_audiosyncAdjustment)
3719  return false;
3720 
3721  bool handled = true;
3722 
3723  if (IsActionable(ACTION_LEFT, Actions))
3724  emit ChangeAudioOffset(-1ms);
3725  else if (IsActionable(ACTION_RIGHT, Actions))
3726  emit ChangeAudioOffset(1ms);
3727  else if (IsActionable(ACTION_UP, Actions))
3728  emit ChangeAudioOffset(10ms);
3729  else if (IsActionable(ACTION_DOWN, Actions))
3730  emit ChangeAudioOffset(-10ms);
3731  else if (IsActionable({ ACTION_TOGGELAUDIOSYNC, ACTION_SELECT }, Actions))
3732  ClearOSD();
3733  else
3734  handled = false;
3735 
3736  return handled;
3737 }
3738 
3739 bool TV::SubtitleZoomHandleAction(const QStringList &Actions)
3740 {
3742  return false;
3743 
3744  bool handled = true;
3745 
3746  if (IsActionable(ACTION_LEFT, Actions))
3747  emit AdjustSubtitleZoom(-1);
3748  else if (IsActionable(ACTION_RIGHT, Actions))
3749  emit AdjustSubtitleZoom(1);
3750  else if (IsActionable(ACTION_UP, Actions))
3751  emit AdjustSubtitleZoom(10);
3752  else if (IsActionable(ACTION_DOWN, Actions))
3753  emit AdjustSubtitleZoom(-10);
3754  else if (IsActionable({ ACTION_TOGGLESUBTITLEZOOM, ACTION_SELECT }, Actions))
3755  ClearOSD();
3756  else
3757  handled = false;
3758 
3759  return handled;
3760 }
3761 
3762 bool TV::SubtitleDelayHandleAction(const QStringList &Actions)
3763 {
3765  return false;
3766 
3767  bool handled = true;
3768 
3769  if (IsActionable(ACTION_LEFT, Actions))
3770  emit AdjustSubtitleDelay(-5ms);
3771  else if (IsActionable(ACTION_RIGHT, Actions))
3772  emit AdjustSubtitleDelay(5ms);
3773  else if (IsActionable(ACTION_UP, Actions))
3774  emit AdjustSubtitleDelay(25ms);
3775  else if (IsActionable(ACTION_DOWN, Actions))
3776  emit AdjustSubtitleDelay(-25ms);
3777  else if (IsActionable({ ACTION_TOGGLESUBTITLEDELAY, ACTION_SELECT }, Actions))
3778  ClearOSD();
3779  else
3780  handled = false;
3781 
3782  return handled;
3783 }
3784 
3785 bool TV::DiscMenuHandleAction(const QStringList& Actions) const
3786 {
3787  mpeg::chrono::pts pts = 0_pts;
3789  if (output)
3790  {
3791  MythVideoFrame *frame = output->GetLastShownFrame();
3792  // convert timecode (msec) to pts (90kHz)
3793  if (frame)
3794  pts = duration_cast<mpeg::chrono::pts>(frame->m_timecode);
3795  }
3797  return m_playerContext.m_buffer->HandleAction(Actions, pts);
3798  return false;
3799 }
3800 
3801 bool TV::ActiveHandleAction(const QStringList &Actions,
3802  bool IsDVD, bool IsDVDStillFrame)
3803 {
3804  bool handled = true;
3805 
3806  if (IsActionable("SKIPCOMMERCIAL", Actions) && !IsDVD)
3807  DoSkipCommercials(1);
3808  else if (IsActionable("SKIPCOMMBACK", Actions) && !IsDVD)
3809  DoSkipCommercials(-1);
3810  else if (IsActionable("QUEUETRANSCODE", Actions) && !IsDVD)
3811  DoQueueTranscode("Default");
3812  else if (IsActionable("QUEUETRANSCODE_AUTO", Actions) && !IsDVD)
3813  DoQueueTranscode("Autodetect");
3814  else if (IsActionable("QUEUETRANSCODE_HIGH", Actions) && !IsDVD)
3815  DoQueueTranscode("High Quality");
3816  else if (IsActionable("QUEUETRANSCODE_MEDIUM", Actions) && !IsDVD)
3817  DoQueueTranscode("Medium Quality");
3818  else if (IsActionable("QUEUETRANSCODE_LOW", Actions) && !IsDVD)
3819  DoQueueTranscode("Low Quality");
3820  else if (IsActionable(ACTION_PLAY, Actions))
3821  DoPlay();
3822  else if (IsActionable(ACTION_PAUSE, Actions))
3823  DoTogglePause(true);
3824  else if (IsActionable("SPEEDINC", Actions) && !IsDVDStillFrame)
3825  ChangeSpeed(1);
3826  else if (IsActionable("SPEEDDEC", Actions) && !IsDVDStillFrame)
3827  ChangeSpeed(-1);
3828  else if (IsActionable("ADJUSTSTRETCH", Actions))
3829  ChangeTimeStretch(0); // just display
3830  else if (IsActionable("CYCLECOMMSKIPMODE",Actions) && !IsDVD)
3832  else if (IsActionable("NEXTSCAN", Actions))
3833  {
3834  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
3836  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
3837  OverrideScan(scan);
3838  }
3839  else if (IsActionable(ACTION_SEEKARB, Actions) && !IsDVD)
3840  {
3841  if (m_asInputMode)
3842  {
3843  ClearInputQueues(true);
3844  emit ChangeOSDText(OSD_WIN_INPUT, {{"osd_number_entry", tr("Seek:")}}, kOSDTimeout_Med);
3845  m_asInputMode = false;
3846  if (m_asInputTimerId)
3847  {
3849  m_asInputTimerId = 0;
3850  }
3851  }
3852  else
3853  {
3854  ClearInputQueues(false);
3855  AddKeyToInputQueue(0);
3856  m_asInputMode = true;
3857  m_ccInputMode = false;
3859  if (m_ccInputTimerId)
3860  {
3862  m_ccInputTimerId = 0;
3863  }
3864  }
3865  }
3866  else if (IsActionable(ACTION_JUMPRWND, Actions))
3867  {
3868  DoJumpRWND();
3869  }
3870  else if (IsActionable(ACTION_JUMPFFWD, Actions))
3871  {
3872  DoJumpFFWD();
3873  }
3874  else if (IsActionable(ACTION_JUMPBKMRK, Actions))
3875  {
3876  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
3877  uint64_t bookmark = m_player->GetBookmark();
3878  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
3879 
3880  if (bookmark)
3881  {
3882  DoPlayerSeekToFrame(bookmark);
3883  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
3884  UpdateOSDSeekMessage(tr("Jump to Bookmark"), kOSDTimeout_Med);
3885  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
3886  }
3887  }
3888  else if (IsActionable(ACTION_JUMPSTART,Actions))
3889  {
3890  DoSeek(0, tr("Jump to Beginning"), /*timeIsOffset*/false, /*honorCutlist*/true);
3891  }
3892  else if (IsActionable(ACTION_CLEAROSD, Actions))
3893  {
3894  ClearOSD();
3895  }
3896  else if (IsActionable(ACTION_VIEWSCHEDULED, Actions))
3897  {
3899  }
3900  else if (HandleJumpToProgramAction(Actions))
3901  { // NOLINT(bugprone-branch-clone)
3902  }
3903  else if (IsActionable(ACTION_SIGNALMON, Actions))
3904  {
3906  {
3907  QString input = m_playerContext.m_recorder->GetInput();
3909 
3910  if (timeout == 0xffffffff)
3911  {
3912  emit ChangeOSDMessage("No Signal Monitor");
3913  return false;
3914  }
3915 
3916  std::chrono::milliseconds rate = m_sigMonMode ? 0ms : 100ms;
3917  bool notify = !m_sigMonMode;
3918 
3919  PauseLiveTV();
3921  UnpauseLiveTV();
3922 
3923  m_lockTimerOn = false;
3925  }
3926  }
3927  else if (IsActionable(ACTION_SCREENSHOT, Actions))
3928  {
3930  }
3931  else if (IsActionable(ACTION_STOP, Actions))
3932  {
3933  PrepareToExitPlayer(__LINE__);
3934  SetExitPlayer(true, true);
3935  }
3936  else if (IsActionable(ACTION_EXITSHOWNOPROMPTS, Actions))
3937  {
3938  m_requestDelete = false;
3939  PrepareToExitPlayer(__LINE__);
3940  SetExitPlayer(true, true);
3941  }
3942  else if (IsActionable({ "ESCAPE", "BACK" }, Actions))
3943  {
3946  {
3947  ClearOSD();
3948  }
3949  else
3950  {
3951  bool visible = false;
3952  emit IsOSDVisible(visible);
3953  if (visible)
3954  {
3955  ClearOSD();
3956  return handled;
3957  }
3958  }
3959 
3960  NormalSpeed();
3961  StopFFRew();
3962  bool exit = false;
3963  if (StateIsLiveTV(GetState()))
3964  {
3966  {
3968  return handled;
3969  }
3970  exit = true;
3971  }
3972  else
3973  {
3975  !m_underNetworkControl && !IsDVDStillFrame)
3976  {
3978  return handled;
3979  }
3980  if (16 & m_dbPlaybackExitPrompt)
3981  {
3982  m_clearPosOnExit = true;
3983  }
3984  PrepareToExitPlayer(__LINE__);
3985  m_requestDelete = false;
3986  exit = true;
3987  }
3988 
3989  if (exit)
3990  {
3991  // If it's a DVD, and we're not trying to execute a
3992  // jumppoint, try to back up.
3993  if (IsDVD && !m_mainWindow->IsExitingToMain() && IsActionable("BACK", Actions) &&
3995  {
3996  return handled;
3997  }
3998  SetExitPlayer(true, true);
3999  }
4000  }
4001  else if (IsActionable(ACTION_ENABLEUPMIX, Actions))
4002  {
4003  emit ChangeUpmix(true);
4004  }
4005  else if (IsActionable(ACTION_DISABLEUPMIX, Actions))
4006  {
4007  emit ChangeUpmix(false);
4008  }
4009  else if (IsActionable(ACTION_VOLUMEDOWN, Actions))
4010  {
4011  VolumeChange(false);
4012  }
4013  else if (IsActionable(ACTION_VOLUMEUP, Actions))
4014  {
4015  VolumeChange(true);
4016  }
4017  else if (IsActionable("CYCLEAUDIOCHAN", Actions))
4018  {
4019  emit ChangeMuteState(true);
4020  }
4021  else if (IsActionable(ACTION_MUTEAUDIO, Actions))
4022  {
4023  emit ChangeMuteState();
4024  }
4025  else if (IsActionable("STRETCHINC", Actions))
4026  {
4027  ChangeTimeStretch(1);
4028  }
4029  else if (IsActionable("STRETCHDEC", Actions))
4030  {
4031  ChangeTimeStretch(-1);
4032  }
4033  else if (IsActionable("MENU", Actions))
4034  {
4035  ShowOSDMenu();
4036  }
4037  else if (IsActionable(ACTION_MENUCOMPACT, Actions))
4038  {
4039  ShowOSDMenu(true);
4040  }
4041  else if (IsActionable({ "INFO", "INFOWITHCUTLIST" }, Actions))
4042  {
4043  if (HasQueuedInput())
4044  DoArbSeek(ARBSEEK_SET, IsActionable("INFOWITHCUTLIST", Actions));
4045  else
4046  ToggleOSD(true);
4047  }
4048  else if (IsActionable(ACTION_TOGGLEOSDDEBUG, Actions))
4049  {
4050  emit ChangeOSDDebug();
4051  }
4052  else if (!IsDVDStillFrame && SeekHandleAction(Actions, IsDVD))
4053  {
4054  }
4055  else if (IsActionable(ACTION_SELECT, Actions) && HasQueuedChannel())
4056  {
4058  }
4059  else
4060  {
4061  handled = false;
4062  for (auto it = Actions.cbegin(); it != Actions.cend() && !handled; ++it)
4063  handled = HandleTrackAction(*it);
4064  }
4065 
4066  return handled;
4067 }
4068 
4069 bool TV::FFRewHandleAction(const QStringList &Actions)
4070 {
4071  bool handled = false;
4072 
4074  {
4075  for (int i = 0; i < Actions.size() && !handled; i++)
4076  {
4077  const QString& action = Actions[i];
4078  bool ok = false;
4079  int val = action.toInt(&ok);
4080 
4081  if (ok && val < static_cast<int>(m_ffRewSpeeds.size()))
4082  {
4083  SetFFRew(val);
4084  handled = true;
4085  }
4086  }
4087 
4088  if (!handled)
4089  {
4092  handled = true;
4093  }
4094  }
4095 
4097  {
4098  NormalSpeed();
4100  handled = true;
4101  }
4102 
4103  return handled;
4104 }
4105 
4106 bool TV::ToggleHandleAction(const QStringList &Actions, bool IsDVD)
4107 {
4108  bool handled = true;
4109  bool islivetv = StateIsLiveTV(GetState());
4110 
4111  if (IsActionable(ACTION_BOTTOMLINEMOVE, Actions))
4112  emit ToggleMoveBottomLine();
4113  else if (IsActionable(ACTION_BOTTOMLINESAVE, Actions))
4114  emit SaveBottomLine();
4115  else if (IsActionable("TOGGLEASPECT", Actions))
4116  emit ChangeAspectOverride();
4117  else if (IsActionable("TOGGLEFILL", Actions))
4118  emit ChangeAdjustFill();
4119  else if (IsActionable(ACTION_TOGGELAUDIOSYNC, Actions))
4120  emit ChangeAudioOffset(0ms); // just display
4121  else if (IsActionable(ACTION_TOGGLESUBTITLEZOOM, Actions))
4122  emit AdjustSubtitleZoom(0); // just display
4123  else if (IsActionable(ACTION_TOGGLESUBTITLEDELAY, Actions))
4124  emit AdjustSubtitleDelay(0ms); // just display
4125  else if (IsActionable(ACTION_TOGGLEVISUALISATION, Actions))
4126  emit EnableVisualiser(false, true);
4127  else if (IsActionable(ACTION_ENABLEVISUALISATION, Actions))
4128  emit EnableVisualiser(true);
4129  else if (IsActionable(ACTION_DISABLEVISUALISATION, Actions))
4130  emit EnableVisualiser(false);
4131  else if (IsActionable("TOGGLEPICCONTROLS", Actions))
4133  else if (IsActionable("TOGGLESTRETCH", Actions))
4135  else if (IsActionable(ACTION_TOGGLEUPMIX, Actions))
4136  emit ChangeUpmix(false, true);
4137  else if (IsActionable(ACTION_TOGGLESLEEP, Actions))
4138  ToggleSleepTimer();
4139  else if (IsActionable(ACTION_TOGGLERECORD, Actions) && islivetv)
4140  QuickRecord();
4141  else if (IsActionable(ACTION_TOGGLEFAV, Actions) && islivetv)
4143  else if (IsActionable(ACTION_TOGGLECHANCONTROLS, Actions) && islivetv)
4145  else if (IsActionable(ACTION_TOGGLERECCONTROLS, Actions) && islivetv)
4147  else if (IsActionable("TOGGLEBROWSE", Actions))
4148  {
4149  if (islivetv)
4150  BrowseStart();
4151  else if (!IsDVD)
4152  ShowOSDMenu();
4153  else
4154  handled = false;
4155  }
4156  else if (IsActionable("EDIT", Actions))
4157  {
4158  if (islivetv)
4160  else if (!IsDVD)
4162  }
4163  else if (IsActionable(ACTION_OSDNAVIGATION, Actions))
4164  {
4166  }
4167  else
4168  {
4169  handled = false;
4170  }
4171 
4172  return handled;
4173 }
4174 
4176 {
4177  if (Clear)
4178  {
4179  emit UpdateBookmark(true);
4180  emit ChangeOSDMessage(tr("Bookmark Cleared"));
4181  }
4182  else // if (IsBookmarkAllowed(ctx))
4183  {
4184  emit UpdateBookmark();
4185  osdInfo info;
4187  info.text["title"] = tr("Position");
4189  emit ChangeOSDMessage(tr("Bookmark Saved"));
4190  }
4191 }
4192 
4193 bool TV::ActivePostQHandleAction(const QStringList &Actions)
4194 {
4195  bool handled = true;
4196  TVState state = GetState();
4197  bool islivetv = StateIsLiveTV(state);
4198  bool isdvd = state == kState_WatchingDVD;
4199  bool isdisc = isdvd || state == kState_WatchingBD;
4200 
4201  if (IsActionable(ACTION_SETBOOKMARK, Actions))
4202  {
4203  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4204  SetBookmark(false);
4205  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4206  }
4207  if (IsActionable(ACTION_TOGGLEBOOKMARK, Actions))
4208  {
4209  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4210  SetBookmark(m_player->GetBookmark() != 0U);
4211  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4212  }
4213  else if (IsActionable("NEXTFAV", Actions) && islivetv)
4214  {
4216  }
4217  else if (IsActionable("NEXTSOURCE", Actions) && islivetv)
4218  {
4220  }
4221  else if (IsActionable("PREVSOURCE", Actions) && islivetv)
4222  {
4224  }
4225  else if (IsActionable("NEXTINPUT", Actions) && islivetv)
4226  {
4227  SwitchInputs();
4228  }
4229  else if (IsActionable(ACTION_GUIDE, Actions))
4230  {
4232  }
4233  else if (IsActionable("PREVCHAN", Actions) && islivetv)
4234  {
4235  PopPreviousChannel(false);
4236  }
4237  else if (IsActionable(ACTION_CHANNELUP, Actions))
4238  {
4239  if (islivetv)
4240  {
4241  if (m_dbBrowseAlways)
4243  else
4245  }
4246  else
4247  {
4248  DoJumpRWND();
4249  }
4250  }
4251  else if (IsActionable(ACTION_CHANNELDOWN, Actions))
4252  {
4253  if (islivetv)
4254  {
4255  if (m_dbBrowseAlways)
4257  else
4259  }
4260  else
4261  {
4262  DoJumpFFWD();
4263  }
4264  }
4265  else if (IsActionable("DELETE", Actions) && !islivetv)
4266  {
4267  NormalSpeed();
4268  StopFFRew();
4269  PrepareToExitPlayer(__LINE__);
4270  ShowOSDPromptDeleteRecording(tr("Are you sure you want to delete:"));
4271  }
4272  else if (IsActionable(ACTION_JUMPTODVDROOTMENU, Actions) && isdisc)
4273  {
4274  emit GoToMenu("root");
4275  }
4276  else if (IsActionable(ACTION_JUMPTODVDCHAPTERMENU, Actions) && isdisc)
4277  {
4278  emit GoToMenu("chapter");
4279  }
4280  else if (IsActionable(ACTION_JUMPTODVDTITLEMENU, Actions) && isdisc)
4281  {
4282  emit GoToMenu("title");
4283  }
4284  else if (IsActionable(ACTION_JUMPTOPOPUPMENU, Actions) && isdisc)
4285  {
4286  emit GoToMenu("popup");
4287  }
4288  else if (IsActionable(ACTION_FINDER, Actions))
4289  {
4291  }
4292  else
4293  {
4294  handled = false;
4295  }
4296 
4297  return handled;
4298 }
4299 
4300 
4302 {
4303  bool ignoreKeys = m_playerContext.IsPlayerChangingBuffers();
4304 
4305 #ifdef DEBUG_ACTIONS
4306  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("(%1) ignoreKeys: %2").arg(Command).arg(ignoreKeys));
4307 #endif
4308 
4309  if (ignoreKeys)
4310  {
4311  LOG(VB_GENERAL, LOG_WARNING, LOC + "Ignoring network control command because ignoreKeys is set");
4312  return;
4313  }
4314 
4315  QStringList tokens = Command.split(" ", Qt::SkipEmptyParts);
4316  if (tokens.size() < 2)
4317  {
4318  LOG(VB_GENERAL, LOG_ERR, LOC + "Not enough tokens in network control command " + QString("'%1'").arg(Command));
4319  return;
4320  }
4321 
4322  OSD *osd = GetOSDL();
4323  bool dlg = false;
4324  if (osd)
4325  dlg = osd->DialogVisible();
4326  ReturnOSDLock();
4327 
4328  if (dlg)
4329  {
4330  LOG(VB_GENERAL, LOG_WARNING, LOC +
4331  "Ignoring network control command\n\t\t\t" +
4332  QString("because dialog is waiting for a response"));
4333  return;
4334  }
4335 
4336  if (tokens[1] != "QUERY")
4337  ClearOSD();
4338 
4339  if (tokens.size() == 3 && tokens[1] == "CHANID")
4340  {
4341  m_queuedChanID = tokens[2].toUInt();
4342  m_queuedChanNum.clear();
4344  }
4345  else if (tokens.size() == 3 && tokens[1] == "CHANNEL")
4346  {
4347  if (StateIsLiveTV(GetState()))
4348  {
4349  static const QRegularExpression kChannelNumRE { R"(^[-\.\d_#]+$)" };
4350  if (tokens[2] == "UP")
4352  else if (tokens[2] == "DOWN")
4354  else if (tokens[2].contains(kChannelNumRE))
4355  ChangeChannel(0, tokens[2]);
4356  }
4357  }
4358  else if (tokens.size() == 3 && tokens[1] == "SPEED")
4359  {
4360  bool paused = ContextIsPaused(__FILE__, __LINE__);
4361 
4362  if (tokens[2] == "0x")
4363  {
4364  NormalSpeed();
4365  StopFFRew();
4366  if (!paused)
4367  DoTogglePause(true);
4368  }
4369  else if (tokens[2] == "normal")
4370  {
4371  NormalSpeed();
4372  StopFFRew();
4373  if (paused)
4374  DoTogglePause(true);
4375  return;
4376  }
4377  else
4378  {
4379  static const QRegularExpression kSpeedRE { R"(^\-*(\d*\.)?\d+x$)" };
4380  float tmpSpeed = 1.0F;
4381  bool ok = false;
4382 
4383  if (tokens[2].contains(kSpeedRE))
4384  {
4385  QString speed = tokens[2].left(tokens[2].length()-1);
4386  tmpSpeed = speed.toFloat(&ok);
4387  }
4388  else
4389  {
4390  static const QRegularExpression re { R"(^(\-*\d+)\/(\d+)x$)" };
4391  auto match = re.match(tokens[2]);
4392  if (match.hasMatch())
4393  {
4394  QStringList matches = match.capturedTexts();
4395  int numerator = matches[1].toInt(&ok);
4396  int denominator = matches[2].toInt(&ok);
4397 
4398  if (ok && denominator != 0)
4399  tmpSpeed = static_cast<float>(numerator) / static_cast<float>(denominator);
4400  else
4401  ok = false;
4402  }
4403  }
4404 
4405  if (ok)
4406  {
4407  float searchSpeed = fabs(tmpSpeed);
4408 
4409  if (paused)
4410  DoTogglePause(true);
4411 
4412  if (tmpSpeed == 0.0F)
4413  {
4414  NormalSpeed();
4415  StopFFRew();
4416 
4417  if (!paused)
4418  DoTogglePause(true);
4419  }
4420  else if (tmpSpeed == 1.0F)
4421  {
4422  StopFFRew();
4423  m_playerContext.m_tsNormal = 1.0F;
4424  ChangeTimeStretch(0, false);
4425  return;
4426  }
4427 
4428  NormalSpeed();
4429 
4430  size_t index = 0;
4431  for ( ; index < m_ffRewSpeeds.size(); index++)
4432  if (m_ffRewSpeeds[index] == static_cast<int>(searchSpeed))
4433  break;
4434 
4435  if ((index < m_ffRewSpeeds.size()) && (m_ffRewSpeeds[index] == static_cast<int>(searchSpeed)))
4436  {
4437  if (tmpSpeed < 0)
4439  else if (tmpSpeed > 1)
4441  else
4442  StopFFRew();
4443 
4445  SetFFRew(static_cast<int>(index));
4446  }
4447  else if (0.125F <= tmpSpeed && tmpSpeed <= 2.0F)
4448  {
4449  StopFFRew();
4450  m_playerContext.m_tsNormal = tmpSpeed; // alter speed before display
4451  ChangeTimeStretch(0, false);
4452  }
4453  else
4454  {
4455  LOG(VB_GENERAL, LOG_WARNING, QString("Couldn't find %1 speed. Setting Speed to 1x")
4456  .arg(static_cast<double>(searchSpeed)));
4459  }
4460  }
4461  else
4462  {
4463  LOG(VB_GENERAL, LOG_ERR, QString("Found an unknown speed of %1").arg(tokens[2]));
4464  }
4465  }
4466  }
4467  else if (tokens.size() == 2 && tokens[1] == "STOP")
4468  {
4469  PrepareToExitPlayer(__LINE__);
4470  SetExitPlayer(true, true);
4471  }
4472  else if (tokens.size() >= 3 && tokens[1] == "SEEK" && m_playerContext.HasPlayer())
4473  {
4474  static const QRegularExpression kDigitsRE { "^\\d+$" };
4476  return;
4477 
4478  if (tokens[2] == "BEGINNING")
4479  {
4480  DoSeek(0, tr("Jump to Beginning"), /*timeIsOffset*/false, /*honorCutlist*/true);
4481  }
4482  else if (tokens[2] == "FORWARD")
4483  {
4484  DoSeek(m_playerContext.m_fftime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
4485  }
4486  else if (tokens[2] == "BACKWARD")
4487  {
4488  DoSeek(-m_playerContext.m_rewtime, tr("Skip Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
4489  }
4490  else if ((tokens[2] == "POSITION" ||
4491  tokens[2] == "POSITIONWITHCUTLIST") &&
4492  (tokens.size() == 4) &&
4493  (tokens[3].contains(kDigitsRE)))
4494  {
4495  DoSeekAbsolute(tokens[3].toInt(), tokens[2] == "POSITIONWITHCUTLIST");
4496  }
4497  }
4498  else if (tokens.size() >= 3 && tokens[1] == "SUBTITLES")
4499  {
4500  bool ok = false;
4501  uint track = tokens[2].toUInt(&ok);
4502 
4503  if (!ok)
4504  return;
4505 
4506  if (track == 0)
4507  {
4508  emit SetCaptionsEnabled(false, true);
4509  }
4510  else
4511  {
4512  QStringList subs = m_player->GetTracks(kTrackTypeSubtitle);
4513  uint size = static_cast<uint>(subs.size());
4514  uint start = 1;
4515  uint finish = start + size;
4516  if (track >= start && track < finish)
4517  {
4518  emit SetTrack(kTrackTypeSubtitle, track - start);
4520  return;
4521  }
4522 
4523  start = finish + 1;
4525  finish = start + size;
4526  if (track >= start && track < finish)
4527  {
4528  emit SetTrack(kTrackTypeCC708, track - start);
4530  return;
4531  }
4532 
4533  start = finish + 1;
4535  finish = start + size;
4536  if (track >= start && track < finish)
4537  {
4538  emit SetTrack(kTrackTypeCC608, track - start);
4540  return;
4541  }
4542 
4543  start = finish + 1;
4545  finish = start + size;
4546  if (track >= start && track < finish)
4547  {
4548  emit SetTrack(kTrackTypeTeletextCaptions, track - start);
4550  return;
4551  }
4552 
4553  start = finish + 1;
4555  finish = start + size;
4556  if (track >= start && track < finish)
4557  {
4558  emit SetTrack(kTrackTypeTeletextMenu, track - start);
4560  return;
4561  }
4562 
4563  start = finish + 1;
4565  finish = start + size;
4566  if (track >= start && track < finish)
4567  {
4568  emit SetTrack(kTrackTypeRawText, track - start);
4570  return;
4571  }
4572  }
4573  }
4574  else if (tokens.size() >= 3 && tokens[1] == "VOLUME")
4575  {
4576  static const QRegularExpression re { "(\\d+)%?" };
4577  auto match = re.match(tokens[2]);
4578  if (match.hasMatch())
4579  {
4580  QStringList matches = match.capturedTexts();
4581 
4582  LOG(VB_GENERAL, LOG_INFO, QString("Set Volume to %1%").arg(matches[1]));
4583 
4584  bool ok = false;
4585  int vol = matches[1].toInt(&ok);
4586  if (!ok)
4587  return;
4588 
4589  if (0 <= vol && vol <= 100)
4590  emit ChangeVolume(true, vol);
4591  }
4592  }
4593  else if (tokens.size() >= 3 && tokens[1] == "QUERY")
4594  {
4595  if (tokens[2] == "POSITION")
4596  {
4597  if (!m_player)
4598  return;
4599  QString speedStr;
4600  if (ContextIsPaused(__FILE__, __LINE__))
4601  {
4602  speedStr = "pause";
4603  }
4604  else if (m_playerContext.m_ffRewState)
4605  {
4606  speedStr = QString("%1x").arg(m_playerContext.m_ffRewSpeed);
4607  }
4608  else
4609  {
4610  static const QRegularExpression re { "Play (.*)x" };
4611  auto match = re.match(m_playerContext.GetPlayMessage());
4612  if (match.hasMatch())
4613  {
4614  QStringList matches = match.capturedTexts();
4615  speedStr = QString("%1x").arg(matches[1]);
4616  }
4617  else
4618  {
4619  speedStr = "1x";
4620  }
4621  }
4622 
4623  osdInfo info;
4625 
4626  QDateTime respDate = MythDate::current(true);
4627  QString infoStr = "";
4628 
4629  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4630  uint64_t fplay = 0;
4631  double rate = 30.0;
4632  if (m_player)
4633  {
4634  fplay = m_player->GetFramesPlayed();
4635  rate = static_cast<double>(m_player->GetFrameRate()); // for display only
4636  }
4637  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4638 
4639  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
4641  {
4642  infoStr = "LiveTV";
4645  }
4646  else
4647  {
4649  infoStr = "DVD";
4651  infoStr = "Recorded";
4652  else
4653  infoStr = "Video";
4654 
4657  }
4658 
4659  QString bufferFilename =
4660  m_playerContext.m_buffer ? m_playerContext.m_buffer->GetFilename() : QString("no buffer");
4661  if ((infoStr == "Recorded") || (infoStr == "LiveTV"))
4662  {
4663  infoStr += QString(" %1 %2 %3 %4 %5 %6 %7")
4664  .arg(info.text["description"],
4665  speedStr,
4666  m_playerContext.m_playingInfo != nullptr
4667  ? QString::number(m_playerContext.m_playingInfo->GetChanID()) : "0",
4668  respDate.toString(Qt::ISODate),
4669  QString::number(fplay),
4670  bufferFilename,
4671  QString::number(rate));
4672  }
4673  else
4674  {
4675  QString position = info.text["description"].section(" ",0,0);
4676  infoStr += QString(" %1 %2 %3 %4 %5")
4677  .arg(position,
4678  speedStr,
4679  bufferFilename,
4680  QString::number(fplay),
4681  QString::number(rate));
4682  }
4683 
4684  infoStr += QString(" Subtitles:");
4685 
4687 
4688  if (subtype == kDisplayNone)
4689  infoStr += QString(" *0:[None]*");
4690  else
4691  infoStr += QString(" 0:[None]");
4692 
4693  uint n = 1;
4694 
4695  QStringList subs = m_player->GetTracks(kTrackTypeSubtitle);
4696  for (int i = 0; i < subs.size(); i++)
4697  {
4698  if ((subtype & kDisplayAVSubtitle) && (m_player->GetTrack(kTrackTypeSubtitle) == i))
4699  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4700  else
4701  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4702  n++;
4703  }
4704 
4706  for (int i = 0; i < subs.size(); i++)
4707  {
4708  if ((subtype & kDisplayCC708) && (m_player->GetTrack(kTrackTypeCC708) == i))
4709  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4710  else
4711  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4712  n++;
4713  }
4714 
4716  for (int i = 0; i < subs.size(); i++)
4717  {
4718  if ((subtype & kDisplayCC608) && (m_player->GetTrack(kTrackTypeCC608) == i))
4719  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4720  else
4721  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4722  n++;
4723  }
4724 
4726  for (int i = 0; i < subs.size(); i++)
4727  {
4729  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4730  else
4731  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4732  n++;
4733  }
4734 
4736  for (int i = 0; i < subs.size(); i++)
4737  {
4739  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4740  else
4741  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4742  n++;
4743  }
4744 
4746  for (int i = 0; i < subs.size(); i++)
4747  {
4748  if ((subtype & kDisplayRawTextSubtitle) && m_player->GetTrack(kTrackTypeRawText) == i)
4749  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4750  else
4751  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4752  n++;
4753  }
4754 
4755  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
4756 
4757  QString message = QString("NETWORK_CONTROL ANSWER %1").arg(infoStr);
4758  MythEvent me(message);
4759  gCoreContext->dispatch(me);
4760  }
4761  else if (tokens[2] == "VOLUME")
4762  {
4763  QString infoStr = QString("%1%").arg(m_audioState.m_volume);
4764  QString message = QString("NETWORK_CONTROL ANSWER %1").arg(infoStr);
4765  MythEvent me(message);
4766  gCoreContext->dispatch(me);
4767  }
4768  }
4769 }
4770 
4771 bool TV::StartPlayer(TVState desiredState)
4772 {
4773  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("(%1) -- begin").arg(StateToString(desiredState)));
4774 
4775  bool ok = CreatePlayer(desiredState);
4777 
4778  if (ok)
4779  {
4780  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Created player."));
4781  SetSpeedChangeTimer(25ms, __LINE__);
4782  }
4783  else
4784  {
4785  LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Failed to create player."));
4786  }
4787 
4788  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("(%1) -- end %2")
4789  .arg(StateToString(desiredState), (ok) ? "ok" : "error"));
4790 
4791  return ok;
4792 }
4793 
4795 {
4796  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4797  if (!m_player)
4798  {
4799  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4800  return;
4801  }
4802 
4803  float time = 0.0;
4804 
4806  m_player->IsPaused())
4807  {
4809  time = StopFFRew();
4810  else if (m_player->IsPaused())
4812 
4816  }
4817  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4818 
4819  DoPlayerSeek(time);
4821 
4823 
4824  SetSpeedChangeTimer(0ms, __LINE__);
4826 }
4827 
4829 {
4830 
4832  return 0.0F;
4833 
4835  float time = 0.0F;
4836 
4837  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4838  if (!m_player)
4839  {
4840  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4841  return 0.0F;
4842  }
4843  if (m_player->IsPaused())
4844  {
4846  }
4847  else
4848  {
4850  time = StopFFRew();
4851  m_player->Pause();
4852  }
4853  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4854  return time;
4855 }
4856 
4857 void TV::DoTogglePauseFinish(float Time, bool ShowOSD)
4858 {
4859  if (!m_playerContext.HasPlayer())
4860  return;
4861 
4863  return;
4864 
4865  if (ContextIsPaused(__FILE__, __LINE__))
4866  {
4869 
4870  DoPlayerSeek(Time);
4871  if (ShowOSD)
4872  UpdateOSDSeekMessage(tr("Paused"), kOSDTimeout_None);
4874  }
4875  else
4876  {
4877  DoPlayerSeek(Time);
4878  if (ShowOSD)
4881  }
4882 
4883  SetSpeedChangeTimer(0ms, __LINE__);
4884 }
4885 
4893 {
4894  bool paused = false;
4895  int dummy = 0;
4896  TV* tv = AcquireRelease(dummy, true);
4897  if (tv)
4898  {
4899  tv->GetPlayerReadLock();
4900  PlayerContext* context = tv->GetPlayerContext();
4901  if (!context->IsErrored())
4902  {
4903  context->LockDeletePlayer(__FILE__, __LINE__);
4904  if (context->m_player)
4905  paused = context->m_player->IsPaused();
4906  context->UnlockDeletePlayer(__FILE__, __LINE__);
4907  }
4908  tv->ReturnPlayerLock();
4909  AcquireRelease(dummy, false);
4910  }
4911  return paused;
4912 }
4913 
4914 void TV::DoTogglePause(bool ShowOSD)
4915 {
4916  bool ignore = false;
4917  bool paused = false;
4918  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4919  if (m_player)
4920  {
4921  ignore = m_player->GetEditMode();
4922  paused = m_player->IsPaused();
4923  }
4924  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4925 
4926  if (paused)
4928  else
4930 
4931  if (!ignore)
4933  // Emit Pause or Unpaused signal
4935 }
4936 
4937 bool TV::DoPlayerSeek(float Time)
4938 {
4940  return false;
4941 
4942  if (Time > -0.001F && Time < +0.001F)
4943  return false;
4944 
4945  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1 seconds").arg(static_cast<double>(Time)));
4946 
4947  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4948  if (!m_player)
4949  {
4950  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4951  return false;
4952  }
4953 
4955  {
4956  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4957  return false;
4958  }
4959 
4960  emit PauseAudioUntilReady();
4961 
4962  bool res = false;
4963 
4964  if (Time > 0.0F)
4965  res = m_player->FastForward(Time);
4966  else if (Time < 0.0F)
4967  res = m_player->Rewind(-Time);
4968  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4969 
4970  return res;
4971 }
4972 
4973 bool TV::DoPlayerSeekToFrame(uint64_t FrameNum)
4974 {
4976  return false;
4977 
4978  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1").arg(FrameNum));
4979 
4980  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4981  if (!m_player)
4982  {
4983  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4984  return false;
4985  }
4986 
4988  {
4989  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4990  return false;
4991  }
4992 
4993  emit PauseAudioUntilReady();
4994 
4995  bool res = m_player->JumpToFrame(FrameNum);
4996 
4997  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4998 
4999  return res;
5000 }
5001 
5002 bool TV::SeekHandleAction(const QStringList& Actions, const bool IsDVD)
5003 {
5004  const int kRewind = 4;
5005  const int kForward = 8;
5006  const int kSticky = 16;
5007  const int kSlippery = 32;
5008  const int kRelative = 64;
5009  const int kAbsolute = 128;
5010  const int kIgnoreCutlist = 256;
5011  const int kWhenceMask = 3;
5012  int flags = 0;
5013  if (IsActionable(ACTION_SEEKFFWD, Actions))
5014  flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative;
5015  else if (IsActionable("FFWDSTICKY", Actions))
5016  flags = ARBSEEK_END | kForward | kSticky | kAbsolute;
5017  else if (IsActionable(ACTION_RIGHT, Actions))
5018  flags = ARBSEEK_FORWARD | kForward | kSticky | kRelative;
5019  else if (IsActionable(ACTION_SEEKRWND, Actions))
5020  flags = ARBSEEK_REWIND | kRewind | kSlippery | kRelative;
5021  else if (IsActionable("RWNDSTICKY", Actions))
5022  flags = ARBSEEK_SET | kRewind | kSticky | kAbsolute;
5023  else if (IsActionable(ACTION_LEFT, Actions))
5024  flags = ARBSEEK_REWIND | kRewind | kSticky | kRelative;
5025  else
5026  return false;
5027 
5028  int direction = (flags & kRewind) ? -1 : 1;
5029  if (HasQueuedInput())
5030  {
5031  DoArbSeek(static_cast<ArbSeekWhence>(flags & kWhenceMask), (flags & kIgnoreCutlist) == 0);
5032  }
5033  else if (ContextIsPaused(__FILE__, __LINE__))
5034  {
5035  if (!IsDVD)
5036  {
5037  QString message = (flags & kRewind) ? tr("Rewind") :
5038  tr("Forward");
5039  if (flags & kAbsolute) // FFWDSTICKY/RWNDSTICKY
5040  {
5041  float time = direction;
5042  DoSeek(time, message, /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5043  }
5044  else
5045  {
5046  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5047  uint64_t frameAbs = m_player->GetFramesPlayed();
5048  uint64_t frameRel = m_player->TranslatePositionAbsToRel(frameAbs);
5049  uint64_t targetRel = frameRel + static_cast<uint64_t>(direction);
5050  if (frameRel == 0 && direction < 0)
5051  targetRel = 0;
5052  uint64_t maxAbs = m_player->GetCurrentFrameCount();
5053  uint64_t maxRel = m_player->TranslatePositionAbsToRel(maxAbs);
5054  targetRel = std::min(targetRel, maxRel);
5055  uint64_t targetAbs = m_player->TranslatePositionRelToAbs(targetRel);
5056  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5057  DoPlayerSeekToFrame(targetAbs);
5059  }
5060  }
5061  }
5062  else if (flags & kSticky)
5063  {
5064  ChangeFFRew(direction);
5065  }
5066  else if (flags & kRewind)
5067  {
5068  if (m_smartForward)
5069  m_doSmartForward = true;
5070  DoSeek(-m_playerContext.m_rewtime, tr("Skip Back"), /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5071  }
5072  else
5073  {
5075  {
5076  DoSeek(m_playerContext.m_rewtime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5077  }
5078  else
5079  {
5080  DoSeek(m_playerContext.m_fftime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5081  }
5082  }
5083  return true;
5084 }
5085 
5086 void TV::DoSeek(float Time, const QString &Msg, bool TimeIsOffset, bool HonorCutlist)
5087 {
5088  if (!m_player)
5089  return;
5090 
5091  bool limitkeys = false;
5092 
5093  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5094  if (m_player->GetLimitKeyRepeat())
5095  limitkeys = true;
5096 
5097  if (!limitkeys || (m_keyRepeatTimer.elapsed() > kKeyRepeatTimeout))
5098  {
5100  NormalSpeed();
5101  Time += StopFFRew();
5102  if (TimeIsOffset)
5103  {
5104  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5105  DoPlayerSeek(Time);
5106  }
5107  else
5108  {
5109  auto time = millisecondsFromFloat(Time * 1000);
5110  uint64_t desiredFrameRel = m_player->TranslatePositionMsToFrame(time, HonorCutlist);
5111  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5112  DoPlayerSeekToFrame(desiredFrameRel);
5113  }
5114  bool paused = m_player->IsPaused();
5116  }
5117  else
5118  {
5119  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5120  }
5121 }
5122 
5123 void TV::DoSeekAbsolute(long long Seconds, bool HonorCutlist)
5124 {
5125  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5126  if (!m_player)
5127  {
5128  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5130  return;
5131  }
5132  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5133  DoSeek(Seconds, tr("Jump To"), /*timeIsOffset*/false, HonorCutlist);
5135 }
5136 
5137 void TV::DoArbSeek(ArbSeekWhence Whence, bool HonorCutlist)
5138 {
5139  bool ok = false;
5140  int seek = GetQueuedInputAsInt(&ok);
5141  ClearInputQueues(true);
5142  if (!ok)
5143  return;
5144 
5145  int64_t time = ((seek / 100) * 3600) + ((seek % 100) * 60);
5146 
5147  if (Whence == ARBSEEK_FORWARD)
5148  {
5149  DoSeek(time, tr("Jump Ahead"), /*timeIsOffset*/true, HonorCutlist);
5150  }
5151  else if (Whence == ARBSEEK_REWIND)
5152  {
5153  DoSeek(-time, tr("Jump Back"), /*timeIsOffset*/true, HonorCutlist);
5154  }
5155  else if (Whence == ARBSEEK_END)
5156  {
5157  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5158  if (!m_player)
5159  {
5160  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5161  return;
5162  }
5163  uint64_t total_frames = m_player->GetCurrentFrameCount();
5164  float dur = m_player->ComputeSecs(total_frames, HonorCutlist);
5165  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5166  DoSeek(std::max(0.0F, dur - static_cast<float>(time)), tr("Jump To"), /*timeIsOffset*/false, HonorCutlist);
5167  }
5168  else
5169  {
5170  DoSeekAbsolute(time, HonorCutlist);
5171  }
5172 }
5173 
5175 {
5177  return;
5178 
5180 
5181  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5182  if (m_player)
5184  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5185 
5186  SetSpeedChangeTimer(0ms, __LINE__);
5187 }
5188 
5189 void TV::ChangeSpeed(int Direction)
5190 {
5191  int old_speed = m_playerContext.m_ffRewSpeed;
5192 
5193  if (ContextIsPaused(__FILE__, __LINE__))
5195 
5196  m_playerContext.m_ffRewSpeed += Direction;
5197 
5198  float time = StopFFRew();
5199  float speed {NAN};
5200 
5201  // Make sure these values for m_ffRewSpeed in TV::ChangeSpeed()
5202  // and PlayerContext::GetPlayMessage() stay in sync.
5203  if (m_playerContext.m_ffRewSpeed == 0)
5204  speed = m_playerContext.m_tsNormal;
5205  else if (m_playerContext.m_ffRewSpeed == -1)
5206  speed = 1.0F / 3;
5207  else if (m_playerContext.m_ffRewSpeed == -2)
5208  speed = 1.0F / 8;
5209  else if (m_playerContext.m_ffRewSpeed == -3)
5210  speed = 1.0F / 16;
5211  else if (m_playerContext.m_ffRewSpeed == -4)
5212  {
5213  DoTogglePause(true);
5214  return;
5215  }
5216  else
5217  {
5218  m_playerContext.m_ffRewSpeed = old_speed;
5219  return;
5220  }
5221 
5222  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5223  if (m_player && !m_player->Play(speed, m_playerContext.m_ffRewSpeed == 0))
5224  {
5225  m_playerContext.m_ffRewSpeed = old_speed;
5226  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5227  return;
5228  }
5229  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5230  DoPlayerSeek(time);
5231  QString mesg = m_playerContext.GetPlayMessage();
5233 
5234  SetSpeedChangeTimer(0ms, __LINE__);
5235 }
5236 
5238 {
5239  float time = 0.0;
5240 
5242  return time;
5243 
5244  if (m_playerContext.m_ffRewState > 0)
5245  time = -m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)] * m_ffRewRepos;
5246  else
5247  time = m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)] * m_ffRewRepos;
5248 
5251 
5252  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5253  if (m_player)
5255  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5256 
5257  SetSpeedChangeTimer(0ms, __LINE__);
5258 
5259  return time;
5260 }
5261 
5262 void TV::ChangeFFRew(int Direction)
5263 {
5264  if (m_playerContext.m_ffRewState == Direction)
5265  {
5266  while (++m_playerContext.m_ffRewIndex < static_cast<int>(m_ffRewSpeeds.size()))
5267  if (m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)])
5268  break;
5269  if (m_playerContext.m_ffRewIndex >= static_cast<int>(m_ffRewSpeeds.size()))
5272  }
5273  else if (!m_ffRewReverse && m_playerContext.m_ffRewState == -Direction)
5274  {
5276  if (m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)])
5277  break;
5280  else
5281  {
5282  float time = StopFFRew();
5283  DoPlayerSeek(time);
5285  }
5286  }
5287  else
5288  {
5289  NormalSpeed();
5290  m_playerContext.m_ffRewState = Direction;
5292  }
5293 }
5294 
5295 void TV::SetFFRew(int Index)
5296 {
5298  return;
5299 
5300  auto index = static_cast<size_t>(Index);
5301  if (!m_ffRewSpeeds[index])
5302  return;
5303 
5304  auto ffrewindex = static_cast<size_t>(m_playerContext.m_ffRewIndex);
5305  int speed = 0;
5306  QString mesg;
5307  if (m_playerContext.m_ffRewState > 0)
5308  {
5309  speed = m_ffRewSpeeds[index];
5310  // Don't allow ffwd if seeking is needed but not available
5312  return;
5313 
5314  m_playerContext.m_ffRewIndex = Index;
5315  mesg = tr("Forward %1X").arg(m_ffRewSpeeds[ffrewindex]);
5316  m_playerContext.m_ffRewSpeed = speed;
5317  }
5318  else
5319  {
5320  // Don't rewind if we cannot seek
5322  return;
5323 
5324  m_playerContext.m_ffRewIndex = Index;
5325  mesg = tr("Rewind %1X").arg(m_ffRewSpeeds[ffrewindex]);
5326  speed = -m_ffRewSpeeds[ffrewindex];
5327  m_playerContext.m_ffRewSpeed = speed;
5328  }
5329 
5330  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5331  if (m_player)
5332  m_player->Play(static_cast<float>(speed), (speed == 1) && (m_playerContext.m_ffRewState > 0));
5333  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5334 
5336 
5337  SetSpeedChangeTimer(0ms, __LINE__);
5338 }
5339 
5340 void TV::DoQueueTranscode(const QString& Profile)
5341 {
5342  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
5343 
5345  {
5346  bool stop = false;
5347  if (m_queuedTranscode ||
5349  JOB_TRANSCODE,
5352  {
5353  stop = true;
5354  }
5355 
5356  if (stop)
5357  {
5359  JOB_TRANSCODE,
5362  m_queuedTranscode = false;
5363  emit ChangeOSDMessage(tr("Stopping Transcode"));
5364  }
5365  else
5366  {
5368  recinfo.ApplyTranscoderProfileChange(Profile);
5369  QString jobHost = "";
5370 
5371  if (m_dbRunJobsOnRemote)
5373 
5374  QString msg = tr("Try Again");
5378  jobHost, "", "", JOB_USE_CUTLIST))
5379  {
5380  m_queuedTranscode = true;
5381  msg = tr("Transcoding");
5382  }
5383  emit ChangeOSDMessage(msg);
5384  }
5385  }
5386  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
5387 }
5388 
5390 {
5391  int num_chapters = 0;
5392  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5393  if (m_player)
5394  num_chapters = m_player->GetNumChapters();
5395  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5396  return num_chapters;
5397 }
5398 
5399 void TV::GetChapterTimes(QList<std::chrono::seconds> &Times)
5400 {
5401  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5402  if (m_player)
5403  m_player->GetChapterTimes(Times);
5404  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5405 }
5406 
5408 {
5409  int chapter = 0;
5410  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5411  if (m_player)
5412  chapter = m_player->GetCurrentChapter();
5413  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5414  return chapter;
5415 }
5416 
5417 void TV::DoJumpChapter(int Chapter)
5418 {
5419  NormalSpeed();
5420  StopFFRew();
5421 
5422  emit PauseAudioUntilReady();
5423 
5424  UpdateOSDSeekMessage(tr("Jump Chapter"), kOSDTimeout_Med);
5425 
5426  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5427  if (m_player)
5428  m_player->JumpChapter(Chapter);
5429  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5430 }
5431 
5433 {
5434  int num_titles = 0;
5435  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5436  if (m_player)
5437  num_titles = m_player->GetNumTitles();
5438  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5439  return num_titles;
5440 }
5441 
5443 {
5444  int currentTitle = 0;
5445  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5446  if (m_player)
5447  currentTitle = m_player->GetCurrentTitle();
5448  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5449  return currentTitle;
5450 }
5451 
5453 {
5454  int num_angles = 0;
5455  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5456  if (m_player)
5457  num_angles = m_player->GetNumAngles();
5458  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5459  return num_angles;
5460 }
5461 
5463 {
5464  int currentAngle = 0;
5465  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5466  if (m_player)
5467  currentAngle = m_player->GetCurrentAngle();
5468  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5469  return currentAngle;
5470 }
5471 
5472 QString TV::GetAngleName(int Angle)
5473 {
5474  QString name;
5475  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5476  if (m_player)
5477  name = m_player->GetAngleName(Angle);
5478  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5479  return name;
5480 }
5481 
5482 std::chrono::seconds TV::GetTitleDuration(int Title)
5483 {
5484  std::chrono::seconds seconds = 0s;
5485  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5486  if (m_player)
5487  seconds = m_player->GetTitleDuration(Title);
5488  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5489  return seconds;
5490 }
5491 
5492 
5493 QString TV::GetTitleName(int Title)
5494 {
5495  QString name;
5496  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5497  if (m_player)
5498  name = m_player->GetTitleName(Title);
5499  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5500  return name;
5501 }
5502 
5503 void TV::DoSwitchTitle(int Title)
5504 {
5505  NormalSpeed();
5506  StopFFRew();
5507 
5508  emit PauseAudioUntilReady();
5509 
5510  UpdateOSDSeekMessage(tr("Switch Title"), kOSDTimeout_Med);
5511  emit ChangeOSDPositionUpdates(true);
5512 
5513  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5514  if (m_player)
5515  m_player->SwitchTitle(Title);
5516  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5517 }
5518 
5519 void TV::DoSwitchAngle(int Angle)
5520 {
5521  NormalSpeed();
5522  StopFFRew();
5523 
5524  emit PauseAudioUntilReady();
5525 
5526  UpdateOSDSeekMessage(tr("Switch Angle"), kOSDTimeout_Med);
5527  emit ChangeOSDPositionUpdates(true);
5528 
5529  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5530  if (m_player)
5531  m_player->SwitchAngle(Angle);
5532  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5533 }
5534 
5535 void TV::DoSkipCommercials(int Direction)
5536 {
5537  NormalSpeed();
5538  StopFFRew();
5539 
5540  if (StateIsLiveTV(GetState()))
5541  return;
5542 
5543  emit PauseAudioUntilReady();
5544 
5545  osdInfo info;
5547  info.text["title"] = tr("Skip");
5548  info.text["description"] = tr("Searching");
5550  emit ChangeOSDPositionUpdates(true);
5551 
5552  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5553  if (m_player)
5554  m_player->SkipCommercials(Direction);
5555  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5556 }
5557 
5558 void TV::SwitchSource(uint Direction)
5559 {
5560  QMap<uint,InputInfo> sources;
5561  uint cardid = m_playerContext.GetCardID();
5562 
5563  InfoMap info;
5565  uint sourceid = info["sourceid"].toUInt();
5566 
5567  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(cardid);
5568  for (auto & input : inputs)
5569  {
5570  // prefer the current card's input in sources list
5571  if ((!sources.contains(input.m_sourceId)) ||
5572  ((cardid == input.m_inputId) && (cardid != sources[input.m_sourceId].m_inputId)))
5573  {
5574  sources[input.m_sourceId] = input;
5575  }
5576  }
5577 
5578  // Source switching
5579  QMap<uint,InputInfo>::const_iterator beg = sources.constFind(sourceid);
5580  QMap<uint,InputInfo>::const_iterator sit = beg;
5581 
5582  if (sit == sources.constEnd())
5583  return;
5584 
5585  if (kNextSource == Direction)
5586  {
5587  ++sit;
5588  if (sit == sources.constEnd())
5589  sit = sources.constBegin();
5590  }
5591 
5592  if (kPreviousSource == Direction)
5593  {
5594  if (sit != sources.constBegin())
5595  --sit;
5596  else
5597  {
5598  QMap<uint,InputInfo>::const_iterator tmp = sources.constBegin();
5599  while (tmp != sources.constEnd())
5600  {
5601  sit = tmp;
5602  ++tmp;
5603  }
5604  }
5605  }
5606 
5607  if (sit == beg)
5608  return;
5609 
5610  m_switchToInputId = (*sit).m_inputId;
5612 }
5613 
5614 void TV::SwitchInputs(uint ChanID, QString ChanNum, uint InputID)
5615 {
5617  return;
5618 
5619  // this will re-create the player. Ensure any outstanding events are delivered
5620  // and processed before the player is deleted so that we don't confuse the
5621  // state of the new player e.g. when switching inputs from the guide grid,
5622  // "EPG_EXITING" may not be received until after the player is re-created
5623  // and we inadvertantly disable drawing...
5624  // TODO with recent changes, embedding should be ended synchronously and hence
5625  // this extra call should no longer be needed
5626  QCoreApplication::processEvents();
5627 
5628  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("(%1,'%2',%3)").arg(ChanID).arg(ChanNum).arg(InputID));
5629 
5630  RemoteEncoder *testrec = nullptr;
5631 
5632  if (!StateIsLiveTV(GetState()))
5633  return;
5634 
5635  QStringList reclist;
5636  if (InputID)
5637  {
5638  reclist.push_back(QString::number(InputID));
5639  }
5640  else if (ChanID || !ChanNum.isEmpty())
5641  {
5642  // If we are switching to a channel not on the current recorder
5643  // we need to find the next free recorder with that channel.
5644  reclist = ChannelUtil::GetValidRecorderList(ChanID, ChanNum);
5645  }
5646 
5647  if (!reclist.empty())
5649 
5650  if (testrec && testrec->IsValidRecorder())
5651  {
5652  InputID = static_cast<uint>(testrec->GetRecorderNumber());
5653 
5654  // We are switching to a specific channel...
5655  if (ChanID && ChanNum.isEmpty())
5656  ChanNum = ChannelUtil::GetChanNum(static_cast<int>(ChanID));
5657 
5658  if (!ChanNum.isEmpty())
5659  CardUtil::SetStartChannel(InputID, ChanNum);
5660  }
5661 
5662  // If we are just switching recorders find first available recorder.
5663  if (!testrec)
5664  testrec = RemoteRequestNextFreeRecorder(static_cast<int>(m_playerContext.GetCardID()));
5665 
5666  if (testrec && testrec->IsValidRecorder())
5667  {
5668  // Switching inputs so clear the pseudoLiveTVState.
5670  bool muted = m_audioState.m_muteState == kMuteAll;
5671 
5672  // pause the decoder first, so we're not reading too close to the end.
5674  {
5677  }
5678 
5679  if (m_player)
5681 
5682  // shutdown stuff
5684  {
5687  }
5688 
5691  m_playerContext.SetPlayer(nullptr);
5692  m_player = nullptr;
5693 
5694  // now restart stuff
5696  m_lockTimerOn = false;
5697 
5698  m_playerContext.SetRecorder(testrec);
5700  // We need to set channum for SpawnLiveTV..
5701  if (ChanNum.isEmpty() && ChanID)
5702  ChanNum = ChannelUtil::GetChanNum(static_cast<int>(ChanID));
5703  if (ChanNum.isEmpty() && InputID)
5704  ChanNum = CardUtil::GetStartChannel(InputID);
5706 
5708  {
5709  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully restarted");
5711  m_playerContext.SetRecorder(nullptr);
5712  SetErrored();
5713  SetExitPlayer(true, false);
5714  }
5715  else
5716  {
5717  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
5718  QString playbackURL = m_playerContext.m_playingInfo->GetPlaybackURL(true);
5719  bool opennow = (m_playerContext.m_tvchain->GetInputType(-1) != "DUMMY");
5722  playbackURL, false, true,
5723  opennow ? MythMediaBuffer::kLiveTVOpenTimeout : -1ms));
5724 
5728  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
5729  }
5730 
5731  bool ok = false;
5733  {
5734  if (CreatePlayer(m_playerContext.GetState(), muted))
5735  {
5737  ok = true;
5739  SetSpeedChangeTimer(25ms, __LINE__);
5740  }
5741  else
5742  {
5743  StopStuff(true, true, true);
5744  }
5745  }
5746 
5747  if (!ok)
5748  {
5749  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully started");
5751  m_playerContext.SetRecorder(nullptr);
5752  SetErrored();
5753  SetExitPlayer(true, false);
5754  }
5755  else
5756  {
5757  m_lockTimer.start();
5758  m_lockTimerOn = true;
5759  }
5760  }
5761  else
5762  {
5763  LOG(VB_GENERAL, LOG_ERR, LOC + "No recorder to switch to...");
5764  delete testrec;
5765  }
5766 
5767  UnpauseLiveTV();
5768  UpdateOSDInput();
5769 
5770  ITVRestart(true);
5771 }
5772 
5774 {
5775  // TOGGLEFAV was broken in [20523], this just prints something
5776  // out so as not to cause further confusion. See #8948.
5777  LOG(VB_GENERAL, LOG_ERR, "TV::ToggleChannelFavorite() -- currently disabled");
5778 }
5779 
5780 void TV::ToggleChannelFavorite(const QString& ChangroupName) const
5781 {
5784 }
5785 
5786 QString TV::GetQueuedInput() const
5787 {
5788  return m_queuedInput;
5789 }
5790 
5791 int TV::GetQueuedInputAsInt(bool *OK, int Base) const
5792 {
5793  return m_queuedInput.toInt(OK, Base);
5794 }
5795 
5796 QString TV::GetQueuedChanNum() const
5797 {
5798  if (m_queuedChanNum.isEmpty())
5799  return "";
5800 
5801  // strip initial zeros and other undesirable characters
5802  int i = 0;
5803  for (; i < m_queuedChanNum.length(); i++)
5804  {
5805  if ((m_queuedChanNum[i] > '0') && (m_queuedChanNum[i] <= '9'))
5806  break;
5807  }
5808  m_queuedChanNum = m_queuedChanNum.right(m_queuedChanNum.length() - i);
5809 
5810  // strip whitespace at end of string
5811  m_queuedChanNum = m_queuedChanNum.trimmed();
5812 
5813  return m_queuedChanNum;
5814 }
5815 
5820 void TV::ClearInputQueues(bool Hideosd)
5821 {
5822  if (Hideosd)
5824 
5825  m_queuedInput = "";
5826  m_queuedChanNum = "";
5827  m_queuedChanID = 0;
5828  if (m_queueInputTimerId)
5829  {
5831  m_queueInputTimerId = 0;
5832  }
5833 }
5834 
5836 {
5837  if (Key)
5838  {
5839  m_queuedInput = m_queuedInput.append(Key).right(kInputKeysMax);
5840  m_queuedChanNum = m_queuedChanNum.append(Key).right(kInputKeysMax);
5841  if (!m_queueInputTimerId)
5842  m_queueInputTimerId = StartTimer(10ms, __LINE__);
5843  }
5844 
5845  bool commitSmart = false;
5846  QString inputStr = GetQueuedInput();
5847 
5848  // Always use immediate channel change when channel numbers are entered
5849  // in browse mode because in browse mode space/enter exit browse
5850  // mode and change to the currently browsed channel.
5852  {
5853  commitSmart = ProcessSmartChannel(inputStr);
5854  }
5855 
5856  // Handle OSD...
5857  inputStr = inputStr.isEmpty() ? "?" : inputStr;
5858  if (m_ccInputMode)
5859  {
5860  QString entryStr = (m_vbimode==VBIMode::PAL_TT) ? tr("TXT:") : tr("CC:");
5861  inputStr = entryStr + " " + inputStr;
5862  }
5863  else if (m_asInputMode)
5864  {
5865  inputStr = tr("Seek:", "seek to location") + " " + inputStr;
5866  }
5867  // NOLINTNEXTLINE(readability-misleading-indentation)
5868  emit ChangeOSDText(OSD_WIN_INPUT, {{ "osd_number_entry", inputStr}}, kOSDTimeout_Med);
5869 
5870  // Commit the channel if it is complete and smart changing is enabled.
5871  if (commitSmart)
5873 }
5874 
5875 static QString add_spacer(const QString &chan, const QString &spacer)
5876 {
5877  if ((chan.length() >= 2) && !spacer.isEmpty())
5878  return chan.left(chan.length()-1) + spacer + chan.right(1);
5879  return chan;
5880 }
5881 
5882 bool TV::ProcessSmartChannel(QString &InputStr)
5883 {
5884  QString chan = GetQueuedChanNum();
5885 
5886  if (chan.isEmpty())
5887  return false;
5888 
5889  // Check for and remove duplicate separator characters
5890 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
5891  int size = chan.size();
5892 #else
5893  qsizetype size = chan.size();
5894 #endif
5895  if ((size > 2) && (chan.at(size - 1) == chan.at(size - 2)))
5896  {
5897  bool ok = false;
5898  chan.right(1).toUInt(&ok);
5899  if (!ok)
5900  {
5901  chan = chan.left(chan.length()-1);
5902  m_queuedChanNum = chan;
5903  if (!m_queueInputTimerId)
5904  m_queueInputTimerId = StartTimer(10ms, __LINE__);
5905  }
5906  }
5907 
5908  // Look for channel in line-up
5909  QString needed_spacer;
5910  uint pref_cardid = 0;
5911  bool is_not_complete = true;
5912 
5913  bool valid_prefix = false;
5915  {
5917  chan, pref_cardid, is_not_complete, needed_spacer);
5918  }
5919 
5920 #if DEBUG_CHANNEL_PREFIX
5921  LOG(VB_GENERAL, LOG_DEBUG, QString("valid_pref(%1) cardid(%2) chan(%3) "
5922  "pref_cardid(%4) complete(%5) sp(%6)")
5923  .arg(valid_prefix).arg(0).arg(chan)
5924  .arg(pref_cardid).arg(is_not_complete).arg(needed_spacer));
5925 #endif
5926 
5927  if (!valid_prefix)
5928  {
5929  // not a valid prefix.. reset...
5930  m_queuedChanNum = "";
5931  }
5932  else if (!needed_spacer.isEmpty())
5933  {
5934  // need a spacer..
5935  m_queuedChanNum = add_spacer(chan, needed_spacer);
5936  }
5937 
5938 #if DEBUG_CHANNEL_PREFIX
5939  LOG(VB_GENERAL, LOG_DEBUG, QString(" ValidPref(%1) CardId(%2) Chan(%3) "
5940  " PrefCardId(%4) Complete(%5) Sp(%6)")
5941  .arg(valid_prefix).arg(0).arg(GetQueuedChanNum())
5942  .arg(pref_cardid).arg(is_not_complete).arg(needed_spacer));
5943 #endif
5944 
5945  InputStr = m_queuedChanNum;
5946  if (!m_queueInputTimerId)
5947  m_queueInputTimerId = StartTimer(10ms, __LINE__);
5948 
5949  return !is_not_complete;
5950 }
5951 
5953 {
5954  bool commited = false;
5955 
5956  LOG(VB_PLAYBACK, LOG_INFO, LOC +
5957  QString("livetv(%1) qchannum(%2) qchanid(%3)")
5958  .arg(StateIsLiveTV(GetState()))
5959  .arg(GetQueuedChanNum())
5960  .arg(GetQueuedChanID()));
5961 
5962  if (m_ccInputMode)
5963  {
5964  commited = true;
5965  if (HasQueuedInput())
5967  }
5968  else if (m_asInputMode)
5969  {
5970  commited = true;
5971  if (HasQueuedInput())
5972  // XXX Should the cutlist be honored?
5973  DoArbSeek(ARBSEEK_FORWARD, /*honorCutlist*/false);
5974  }
5975  else if (StateIsLiveTV(GetState()))
5976  {
5977  QString channum = GetQueuedChanNum();
5979  {
5980  uint sourceid = 0;
5981  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
5984  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
5985 
5986  commited = true;
5987  if (channum.isEmpty())
5988  channum = GetBrowsedInfo().m_chanNum;
5989  uint chanid = GetBrowseChanId(channum, m_playerContext.GetCardID(), sourceid);
5990  if (chanid)
5991  BrowseChannel(channum);
5992 
5994  }
5995  else if (GetQueuedChanID() || !channum.isEmpty())
5996  {
5997  commited = true;
5998  ChangeChannel(GetQueuedChanID(), channum);
5999  }
6000  }
6001 
6002  ClearInputQueues(true);
6003  return commited;
6004 }
6005 
6007 {
6008  if (m_dbUseChannelGroups || (Direction == CHANNEL_DIRECTION_FAVORITE))
6009  {
6010  uint old_chanid = 0;
6011  if (m_channelGroupId > -1)
6012  {
6013  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
6015  {
6016  LOG(VB_GENERAL, LOG_ERR, LOC +
6017  "no active ctx playingInfo.");
6018  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6019  ReturnPlayerLock();
6020  return;
6021  }
6022  // Collect channel info
6023  old_chanid = m_playerContext.m_playingInfo->GetChanID();
6024  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6025  }
6026 
6027  if (old_chanid)
6028  {
6029  QMutexLocker locker(&m_channelGroupLock);
6030  if (m_channelGroupId > -1)
6031  {
6033  m_channelGroupChannelList, old_chanid, 0, 0, Direction);
6034  if (chanid)
6035  ChangeChannel(chanid, "");
6036  return;
6037  }
6038  }
6039  }
6040 
6041  if (Direction == CHANNEL_DIRECTION_FAVORITE)
6042  Direction = CHANNEL_DIRECTION_UP;
6043 
6044  QString oldinputname = m_playerContext.m_recorder->GetInput();
6045 
6046  if (ContextIsPaused(__FILE__, __LINE__))
6047  {
6050  }
6051 
6052  // Save the current channel if this is the first time
6053  if (m_playerContext.m_prevChan.empty())
6055 
6056  emit PauseAudioUntilReady();
6057  PauseLiveTV();
6058 
6059  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
6060  if (m_player)
6061  {
6062  emit ResetCaptions();
6063  emit ResetTeletext();
6064  }
6065  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
6066 
6068  ClearInputQueues(false);
6069 
6070  emit ResetAudio();
6071 
6072  UnpauseLiveTV();
6073 
6074  if (oldinputname != m_playerContext.m_recorder->GetInput())
6075  UpdateOSDInput();
6076 }
6077 
6078 static uint get_chanid(const PlayerContext *ctx,
6079  uint cardid, const QString &channum)
6080 {
6081  uint chanid = 0;
6082  uint cur_sourceid = 0;
6083 
6084  // try to find channel on current input
6085  if (ctx && ctx->m_playingInfo && ctx->m_playingInfo->GetSourceID())
6086  {
6087  cur_sourceid = ctx->m_playingInfo->GetSourceID();
6088  chanid = std::max(ChannelUtil::GetChanID(cur_sourceid, channum), 0);
6089  if (chanid)
6090  return chanid;
6091  }
6092 
6093  // try to find channel on specified input
6094  uint sourceid = CardUtil::GetSourceID(cardid);
6095  if (cur_sourceid != sourceid && sourceid)
6096  chanid = std::max(ChannelUtil::GetChanID(sourceid, channum), 0);
6097  return chanid;
6098 }
6099 
6100 void TV::ChangeChannel(uint Chanid, const QString &Channum)
6101 {
6102  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("(%1, '%2')").arg(Chanid).arg(Channum));
6103 
6104  if ((!Chanid && Channum.isEmpty()) || !m_playerContext.m_recorder)
6105  return;
6106 
6107  QString channum = Channum;
6108  QStringList reclist;
6109  QVector<uint> tunable_on;
6110 
6111  QString oldinputname = m_playerContext.m_recorder->GetInput();
6112 
6113  if (channum.isEmpty() && Chanid)
6114  channum = ChannelUtil::GetChanNum(static_cast<int>(Chanid));
6115 
6116  bool getit = false;
6118  {
6120  {
6121  getit = false;
6122  }
6124  {
6125  getit = true;
6126  }
6127  else if (Chanid)
6128  {
6129  tunable_on = IsTunableOn(&m_playerContext, Chanid);
6130  getit = !tunable_on.contains(m_playerContext.GetCardID());
6131  }
6132  else
6133  {
6134  QString needed_spacer;
6135  uint pref_cardid = 0;
6136  uint cardid = m_playerContext.GetCardID();
6137  bool dummy = false;
6138 
6140  dummy, needed_spacer);
6141 
6142  LOG(VB_CHANNEL, LOG_INFO, LOC +
6143  QString("CheckChannelPrefix(%1, pref_cardid %2, %3, '%4') "
6144  "cardid %5")
6145  .arg(Channum).arg(pref_cardid).arg(dummy).arg(needed_spacer)
6146  .arg(cardid));
6147 
6148  channum = add_spacer(Channum, needed_spacer);
6149  if (pref_cardid != cardid)
6150  {
6151  getit = true;
6152  }
6153  else
6154  {
6155  if (!Chanid)
6156  Chanid = get_chanid(&m_playerContext, cardid, Channum);
6157  tunable_on = IsTunableOn(&m_playerContext, Chanid);
6158  getit = !tunable_on.contains(cardid);
6159  }
6160  }
6161 
6162  if (getit)
6163  {
6164  QStringList tmp =
6165  ChannelUtil::GetValidRecorderList(Chanid, channum);
6166  if (tunable_on.empty())
6167  {
6168  if (!Chanid)
6170  tunable_on = IsTunableOn(&m_playerContext, Chanid);
6171  }
6172  for (const auto& rec : std::as_const(tmp))
6173  {
6174  if ((Chanid == 0U) || tunable_on.contains(rec.toUInt()))
6175  reclist.push_back(rec);
6176  }
6177  }
6178  }
6179 
6180  if (!reclist.empty())
6181  {
6183  if (!testrec || !testrec->IsValidRecorder())
6184  {
6185  ClearInputQueues(true);
6187  delete testrec;
6188  return;
6189  }
6190 
6191  if (!m_playerContext.m_prevChan.empty() &&
6192  m_playerContext.m_prevChan.back() == channum)
6193  {
6194  // need to remove it if the new channel is the same as the old.
6195  m_playerContext.m_prevChan.pop_back();
6196  }
6197 
6198  // found the card on a different recorder.
6199  uint inputid = static_cast<uint>(testrec->GetRecorderNumber());
6200  delete testrec;
6201  // Save the current channel if this is the first time
6202  if (m_playerContext.m_prevChan.empty())
6204  SwitchInputs(Chanid, channum, inputid);
6205  return;
6206  }
6207 
6209  return;
6210 
6211  if (ContextIsPaused(__FILE__, __LINE__))
6212  {
6215  }
6216 
6217  // Save the current channel if this is the first time
6218  if (m_playerContext.m_prevChan.empty())
6220 
6221  emit PauseAudioUntilReady();
6222  PauseLiveTV();
6223 
6224  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
6225  if (m_player)
6226  {
6227  emit ResetCaptions();
6228  emit ResetTeletext();
6229  }
6230  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
6231 
6233 
6234  emit ResetAudio();
6235 
6236  UnpauseLiveTV((Chanid != 0U) && (GetQueuedChanID() != 0U));
6237 
6238  if (oldinputname != m_playerContext.m_recorder->GetInput())
6239  UpdateOSDInput();
6240 }
6241 
6243 {
6244  for (const auto & option : Options)
6245  {
6246  uint chanid = option.m_chanId;
6247  QString channum = option.m_chanNum;
6248 
6249  if (chanid && !channum.isEmpty() && IsTunablePriv(chanid))
6250  {
6251  // hide the channel number, activated by certain signal monitors
6253  m_queuedInput = channum;
6254  m_queuedChanNum = channum;
6255  m_queuedChanID = chanid;
6256  if (!m_queueInputTimerId)
6257  m_queueInputTimerId = StartTimer(10ms, __LINE__);
6258  break;
6259  }
6260  }
6261 }
6262 
6264 {
6265  QString channum = m_playerContext.GetPreviousChannel();
6266  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Previous channel number '%1'").arg(channum));
6267  if (channum.isEmpty())
6268  return;
6269  emit ChangeOSDText(OSD_WIN_INPUT, {{ "osd_number_entry", channum }}, kOSDTimeout_Med);
6270 }
6271 
6272 void TV::PopPreviousChannel(bool ImmediateChange)
6273 {
6275  return;
6276 
6277  if (!ImmediateChange)
6279 
6280  QString prev_channum = m_playerContext.PopPreviousChannel();
6281  QString cur_channum = m_playerContext.m_tvchain->GetChannelName(-1);
6282 
6283  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("'%1'->'%2'")
6284  .arg(cur_channum, prev_channum));
6285 
6286  // Only change channel if previous channel != current channel
6287  if (cur_channum != prev_channum && !prev_channum.isEmpty())
6288  {
6289  m_queuedInput = prev_channum;
6290  m_queuedChanNum = prev_channum;
6291  m_queuedChanID = 0;
6292  if (!m_queueInputTimerId)
6293  m_queueInputTimerId = StartTimer(10ms, __LINE__);
6294  }
6295 
6296  if (ImmediateChange)
6297  {
6298  // Turn off OSD Channel Num so the channel changes right away
6300  }
6301 }
6302 
6304 {
6305  if (HasQueuedInput() || HasQueuedChannel())
6306  ClearInputQueues(true);
6307 
6308  emit DialogQuit();
6309  // pop OSD screen
6310  emit HideAll(true, nullptr, true);
6311 
6313  BrowseEnd(false);
6314 }
6315 
6319 void TV::ToggleOSD(bool IncludeStatusOSD)
6320 {
6321  OSD *osd = GetOSDL();
6322  if (!osd)
6323  {
6324  ReturnOSDLock();
6325  return;
6326  }
6327 
6328  bool hideAll = false;
6329  bool showStatus = false;
6330  bool paused = ContextIsPaused(__FILE__, __LINE__);
6331  bool is_status_disp = osd->IsWindowVisible(OSD_WIN_STATUS);
6332  bool has_prog_info = osd->HasWindow(OSD_WIN_PROGINFO);
6333  bool is_prog_info_disp = osd->IsWindowVisible(OSD_WIN_PROGINFO);
6334 
6335  ReturnOSDLock();
6336 
6337  if (is_status_disp)
6338  {
6339  if (has_prog_info)
6341  else
6342  hideAll = true;
6343  }
6344  else if (is_prog_info_disp && !paused)
6345  {
6346  hideAll = true;
6347  }
6348  else if (IncludeStatusOSD)
6349  {
6350  showStatus = true;
6351  }
6352  else
6353  {
6354  if (has_prog_info)
6356  }
6357 
6358  if (hideAll || showStatus)
6359  emit HideAll();
6360 
6361  if (showStatus)
6362  {
6363  osdInfo info;
6365  {
6366  info.text["title"] = (paused ? tr("Paused") : tr("Position"));
6368  paused ? kOSDTimeout_None : kOSDTimeout_Med);
6369  emit ChangeOSDPositionUpdates(true);
6370  }
6371  else
6372  {
6373  emit ChangeOSDPositionUpdates(false);
6374  }
6375  }
6376  else
6377  {
6378  emit ChangeOSDPositionUpdates(false);
6379  }
6380 }
6381 
6385 void TV::UpdateOSDProgInfo(const char *WhichInfo)
6386 {
6387  InfoMap infoMap;
6389  if (m_player)
6390  m_player->GetCodecDescription(infoMap);
6391 
6392  // Clear previous osd and add new info
6393  emit HideAll();
6394  emit ChangeOSDText(WhichInfo, infoMap, kOSDTimeout_Long);
6395 }
6396 
6397 void TV::UpdateOSDStatus(osdInfo &Info, int Type, OSDTimeout Timeout)
6398 {
6399  OSD *osd = GetOSDL();
6400  if (osd)
6401  {
6403  osd->SetValues(OSD_WIN_STATUS, Info.values, Timeout);
6404  emit ChangeOSDText(OSD_WIN_STATUS, Info.text, Timeout);
6405  if (Type != kOSDFunctionalType_Default)
6406  osd->SetFunctionalWindow(OSD_WIN_STATUS, static_cast<OSDFunctionalType>(Type));
6407  }
6408  ReturnOSDLock();
6409 }
6410 
6411 void TV::UpdateOSDStatus(const QString& Title, const QString& Desc,
6412  const QString& Value, int Type, const QString& Units,
6413  int Position, OSDTimeout Timeout)
6414 {
6415  osdInfo info;
6416  info.values.insert("position", Position);
6417  info.values.insert("relposition", Position);
6418  info.text.insert("title", Title);
6419  info.text.insert("description", Desc);
6420  info.text.insert("value", Value);
6421  info.text.insert("units", Units);
6422  UpdateOSDStatus(info, Type, Timeout);
6423 }
6424 
6425 void TV::UpdateOSDSeekMessage(const QString &Msg, enum OSDTimeout Timeout)
6426 {
6427  LOG(VB_PLAYBACK, LOG_INFO, QString("UpdateOSDSeekMessage(%1, %2)").arg(Msg).arg(Timeout));
6428 
6429  osdInfo info;
6431  {
6433  info.text["title"] = Msg;
6434  UpdateOSDStatus(info, osdtype, Timeout);
6435  emit ChangeOSDPositionUpdates(true);
6436  }
6437 }
6438 
6440 {
6442  return;
6443  QString displayName = CardUtil::GetDisplayName(m_playerContext.GetCardID());
6444  emit ChangeOSDMessage(displayName);
6445 }
6446 
6450 void TV::UpdateOSDSignal(const QStringList &List)
6451 {
6452  OSD *osd = GetOSDL();
6453  if (!osd || m_overlayState.m_browsing || !m_queuedChanNum.isEmpty())
6454  {
6455  if (&m_playerContext.m_lastSignalMsg != &List)
6457  ReturnOSDLock();
6458  m_signalMonitorTimerId = StartTimer(1ms, __LINE__);
6459  return;
6460  }
6461  ReturnOSDLock();
6462 
6464 
6468  infoMap["callsign"].isEmpty())
6469  {
6472  if (m_player)
6473  m_player->GetCodecDescription(infoMap);
6474 
6477  }
6478 
6479  int i = 0;
6480  SignalMonitorList::const_iterator it;
6481  for (it = slist.begin(); it != slist.end(); ++it)
6482  if ("error" == it->GetShortName())
6483  infoMap[QString("error%1").arg(i++)] = it->GetName();
6484  i = 0;
6485  for (it = slist.begin(); it != slist.end(); ++it)
6486  if ("message" == it->GetShortName())
6487  infoMap[QString("message%1").arg(i++)] = it->GetName();
6488 
6489  int sig = 0;
6490  double snr = 0.0;
6491  uint ber = 0xffffffff;
6492  int pos = -1;
6493  int tuned = -1;
6494  QString pat("");
6495  QString pmt("");
6496  QString mgt("");
6497  QString vct("");
6498  QString nit("");
6499  QString sdt("");
6500  QString crypt("");
6501  QString err;
6502  QString msg;
6503  for (it = slist.begin(); it != slist.end(); ++it)
6504  {
6505  if ("error" == it->GetShortName())
6506  {
6507  err = it->GetName();
6508  continue;
6509  }
6510 
6511  if ("message" == it->GetShortName())
6512  {
6513  msg = it->GetName();
6514  LOG(VB_GENERAL, LOG_INFO, "msg: " + msg);
6515  continue;
6516  }
6517 
6518  infoMap[it->GetShortName()] = QString::number(it->GetValue());
6519  if ("signal" == it->GetShortName())
6520  sig = it->GetNormalizedValue(0, 100);
6521  else if ("snr" == it->GetShortName())
6522  snr = it->GetValue();
6523  else if ("ber" == it->GetShortName())
6524  ber = static_cast<uint>(it->GetValue());
6525  else if ("pos" == it->GetShortName())
6526  pos = it->GetValue();
6527  else if ("script" == it->GetShortName())
6528  tuned = it->GetValue();
6529  else if ("seen_pat" == it->GetShortName())
6530  pat = it->IsGood() ? "a" : "_";
6531  else if ("matching_pat" == it->GetShortName())
6532  pat = it->IsGood() ? "A" : pat;
6533  else if ("seen_pmt" == it->GetShortName())
6534  pmt = it->IsGood() ? "m" : "_";
6535  else if ("matching_pmt" == it->GetShortName())
6536  pmt = it->IsGood() ? "M" : pmt;
6537  else if ("seen_mgt" == it->GetShortName())
6538  mgt = it->IsGood() ? "g" : "_";
6539  else if ("matching_mgt" == it->GetShortName())
6540  mgt = it->IsGood() ? "G" : mgt;
6541  else if ("seen_vct" == it->GetShortName())
6542  vct = it->IsGood() ? "v" : "_";
6543  else if ("matching_vct" == it->GetShortName())
6544  vct = it->IsGood() ? "V" : vct;
6545  else if ("seen_nit" == it->GetShortName())
6546  nit = it->IsGood() ? "n" : "_";
6547  else if ("matching_nit" == it->GetShortName())
6548  nit = it->IsGood() ? "N" : nit;
6549  else if ("seen_sdt" == it->GetShortName())
6550  sdt = it->IsGood() ? "s" : "_";
6551  else if ("matching_sdt" == it->GetShortName())
6552  sdt = it->IsGood() ? "S" : sdt;
6553  else if ("seen_crypt" == it->GetShortName())
6554  crypt = it->IsGood() ? "c" : "_";
6555  else if ("matching_crypt" == it->GetShortName())
6556  crypt = it->IsGood() ? "C" : crypt;
6557  }
6558  if (sig)
6559  infoMap["signal"] = QString::number(sig); // use normalized value
6560 
6561  bool allGood = SignalMonitorValue::AllGood(slist);
6562  QString tuneCode;
6563  QString slock = ("1" == infoMap["slock"]) ? "L" : "l";
6564  QString lockMsg = (slock=="L") ? tr("Partial Lock") : tr("No Lock");
6565  QString sigMsg = allGood ? tr("Lock") : lockMsg;
6566 
6567  QString sigDesc = tr("Signal %1%").arg(sig,2);
6568  if (snr > 0.0)
6569  sigDesc += " | " + tr("S/N %1dB").arg(log10(snr), 3, 'f', 1);
6570  if (ber != 0xffffffff)
6571  sigDesc += " | " + tr("BE %1", "Bit Errors").arg(ber, 2);
6572  if ((pos >= 0) && (pos < 100))
6573  sigDesc += " | " + tr("Rotor %1%").arg(pos,2);
6574 
6575  if (tuned == 1)
6576  tuneCode = "t";
6577  else if (tuned == 2)
6578  tuneCode = "F";
6579  else if (tuned == 3)
6580  tuneCode = "T";
6581  else
6582  tuneCode = "_";
6583 
6584  sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8%9) %10")
6585  .arg(tuneCode, slock, pat, pmt, mgt, vct,
6586  nit, sdt, crypt)
6587  .arg(sigMsg);
6588 
6589  if (!err.isEmpty())
6590  sigDesc = err;
6591  else if (!msg.isEmpty())
6592  sigDesc = msg;
6593 
6594  infoMap["description"] = sigDesc;
6596 
6599 
6600  // Turn off lock timer if we have an "All Good" or good PMT
6601  if (allGood || (pmt == "M"))
6602  {
6603  m_lockTimerOn = false;
6605  }
6606 }
6607 
6609 {
6610  bool timed_out = false;
6611 
6613  {
6614  QString input = m_playerContext.m_recorder->GetInput();
6616  timed_out = m_lockTimerOn && m_lockTimer.hasExpired(timeout);
6617  }
6618 
6619  OSD *osd = GetOSDL();
6620 
6621  if (!osd)
6622  {
6623  if (timed_out)
6624  {
6625  LOG(VB_GENERAL, LOG_ERR, LOC +
6626  "You have no OSD, but tuning has already taken too long.");
6627  }
6628  ReturnOSDLock();
6629  return;
6630  }
6631 
6632  bool showing = osd->DialogVisible(OSD_DLG_INFO);
6633  if (!timed_out)
6634  {
6635  if (showing)
6636  emit DialogQuit();
6637  ReturnOSDLock();
6638  return;
6639  }
6640 
6641  if (showing)
6642  {
6643  ReturnOSDLock();
6644  return;
6645  }
6646 
6647  ReturnOSDLock();
6648 
6649  // create dialog...
6650  static QString s_chanUp = GET_KEY("TV Playback", ACTION_CHANNELUP);
6651  static QString s_chanDown = GET_KEY("TV Playback", ACTION_CHANNELDOWN);
6652  static QString s_nextSrc = GET_KEY("TV Playback", "NEXTSOURCE");
6653  static QString s_togCards = GET_KEY("TV Playback", "NEXTINPUT");
6654 
6655  QString message = tr(
6656  "You should have received a channel lock by now. "
6657  "You can continue to wait for a signal, or you "
6658  "can change the channel with %1 or %2, change "
6659  "video source (%3), inputs (%4), etc.")
6660  .arg(s_chanUp, s_chanDown, s_nextSrc, s_togCards);
6661 
6662  emit ChangeOSDDialog({ OSD_DLG_INFO, message, 0ms,
6663  { {tr("OK"), "DIALOG_INFO_CHANNELLOCK_0" } },
6664  { "", "DIALOG_INFO_CHANNELLOCK_0", true } });
6665 }
6666 
6667 bool TV::CalcPlayerSliderPosition(osdInfo &info, bool paddedFields) const
6668 {
6669  bool result = false;
6671  if (m_player)
6672  {
6673  m_player->UpdateSliderInfo(info, paddedFields);
6674  result = true;
6675  }
6676  ReturnPlayerLock();
6677  return result;
6678 }
6679 
6680 void TV::HideOSDWindow(const char *window)
6681 {
6682  OSD *osd = GetOSDL();
6683  if (osd)
6684  osd->HideWindow(window);
6685  ReturnOSDLock();
6686 }
6687 
6689 {
6690  // Make sure the LCD information gets updated shortly
6691  if (m_lcdTimerId)
6693  m_lcdTimerId = StartTimer(1ms, __LINE__);
6694 }
6695 
6697 {
6698  LCD *lcd = LCD::Get();
6699  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
6700  if (!lcd || !m_playerContext.m_playingInfo)
6701  {
6702  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6703  return;
6704  }
6705 
6706  QString title = m_playerContext.m_playingInfo->GetTitle();
6707  QString subtitle = m_playerContext.m_playingInfo->GetSubtitle();
6709 
6710  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6711 
6712  if ((callsign != m_lcdCallsign) || (title != m_lcdTitle) ||
6713  (subtitle != m_lcdSubtitle))
6714  {
6715  lcd->switchToChannel(callsign, title, subtitle);
6716  m_lcdCallsign = callsign;
6717  m_lcdTitle = title;
6718  m_lcdSubtitle = subtitle;
6719  }
6720 }
6721 
6723 {
6724  LCD *lcd = LCD::Get();
6726  return;
6727 
6729  QString dvdName;
6730  QString dvdSerial;
6731  QString mainStatus;
6732  QString subStatus;
6733 
6734  if (!dvd->GetNameAndSerialNum(dvdName, dvdSerial))
6735  dvdName = tr("DVD");
6736 
6737  if (dvd->IsInMenu())
6738  {
6739  mainStatus = tr("Menu");
6740  }
6741  else if (dvd->IsInStillFrame())
6742  {
6743  mainStatus = tr("Still Frame");
6744  }
6745  else
6746  {
6747  int playingTitle = 0;
6748  int playingPart = 0;
6749 
6750  dvd->GetPartAndTitle(playingPart, playingTitle);
6751  int totalParts = dvd->NumPartsInTitle();
6752 
6753  mainStatus = tr("Title: %1 (%2)").arg(playingTitle)
6754  .arg(MythDate::formatTime(dvd->GetTotalTimeOfTitle(), "HH:mm"));
6755  subStatus = tr("Chapter: %1/%2").arg(playingPart).arg(totalParts);
6756  }
6757  if ((dvdName != m_lcdCallsign) || (mainStatus != m_lcdTitle) || (subStatus != m_lcdSubtitle))
6758  {
6759  lcd->switchToChannel(dvdName, mainStatus, subStatus);
6760  m_lcdCallsign = dvdName;
6761  m_lcdTitle = mainStatus;
6762  m_lcdSubtitle = subStatus;
6763  }
6764 }
6765 
6766 bool TV::IsTunable(uint ChanId)
6767 {
6768  int dummy = 0;
6769  TV* tv = AcquireRelease(dummy, true);
6770  if (tv)
6771  {
6772  tv->GetPlayerReadLock();
6773  bool result = !TV::IsTunableOn(tv->GetPlayerContext(), ChanId).empty();
6774  tv->ReturnPlayerLock();
6775  AcquireRelease(dummy, false);
6776  return result;
6777  }
6778 
6779  return !TV::IsTunableOn(nullptr, ChanId).empty();
6780 }
6781 
6783 {
6784  return !IsTunableOn(&m_playerContext, ChanId).empty();
6785 }
6786 
6787 static QString toCommaList(const QVector<uint> &list)
6788 {
6789  QString ret = "";
6790  for (uint i : std::as_const(list))
6791  ret += QString("%1,").arg(i);
6792 
6793  if (!ret.isEmpty())
6794  return ret.left(ret.length()-1);
6795 
6796  return "";
6797 }
6798 
6799 QVector<uint> TV::IsTunableOn(PlayerContext* Context, uint ChanId)
6800 {
6801  QVector<uint> tunable_cards;
6802 
6803  if (!ChanId)
6804  {
6805  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("ChanId (%1) - no").arg(ChanId));
6806  return tunable_cards;
6807  }
6808 
6809  uint mplexid = ChannelUtil::GetMplexID(ChanId);
6810  mplexid = (32767 == mplexid) ? 0 : mplexid;
6811 
6812  uint excluded_input = 0;
6813  if (Context && Context->m_recorder && Context->m_pseudoLiveTVState == kPseudoNormalLiveTV)
6814  excluded_input = Context->GetCardID();
6815 
6816  uint sourceid = ChannelUtil::GetSourceIDForChannel(ChanId);
6817 
6818  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(excluded_input);
6819 
6820  for (auto & input : inputs)
6821  {
6822  if (input.m_sourceId != sourceid)
6823  continue;
6824 
6825  if (input.m_mplexId &&
6826  input.m_mplexId != mplexid)
6827  continue;
6828 
6829  if (!input.m_mplexId && input.m_chanId &&
6830  input.m_chanId != ChanId)
6831  continue;
6832 
6833  tunable_cards.push_back(input.m_inputId);
6834  }
6835 
6836  if (tunable_cards.empty())
6837  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("ChanId (%1) - no").arg(ChanId));
6838  else
6839  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("ChanId (%1) yes { %2 }").arg(ChanId).arg(toCommaList(tunable_cards)));
6840  return tunable_cards;
6841 }
6842 
6843 void TV::Embed(bool Embed, QRect Rect, const QStringList& Data)
6844 {
6845  emit EmbedPlayback(Embed, Rect);
6846  if (Embed)
6847  return;
6848 
6849  emit ResizeScreenForVideo();
6850 
6851  // m_playerBounds is not applicable when switching modes so
6852  // skip this logic in that case.
6853  if (!m_dbUseVideoModes)
6855 
6856  // Restore pause
6858 
6859  if (!m_weDisabledGUI)
6860  {
6861  m_weDisabledGUI = true;
6863  }
6864 
6865  m_ignoreKeyPresses = false;
6866 
6867  // additional data returned by PlaybackBox
6868  if (!Data.isEmpty())
6869  {
6870  ProgramInfo pginfo(Data);
6871  if (pginfo.HasPathname() || pginfo.GetChanID())
6873  }
6874 }
6875 
6876 bool TV::DoSetPauseState(bool Pause)
6877 {
6878  bool waspaused = ContextIsPaused(__FILE__, __LINE__);
6879  float time = 0.0F;
6880  if (Pause ^ waspaused)
6881  time = DoTogglePauseStart();
6882  if (Pause ^ waspaused)
6883  DoTogglePauseFinish(time, false);
6884  return waspaused;
6885 }
6886 
6887 void TV::DoEditSchedule(int EditType, const QString & EditArg)
6888 {
6889  // Prevent nesting of the pop-up UI
6890  if (m_ignoreKeyPresses)
6891  return;
6892 
6893  if ((EditType == kScheduleProgramGuide && !RunProgramGuidePtr) ||
6894  (EditType == kScheduleProgramFinder && !RunProgramFinderPtr) ||
6895  (EditType == kScheduledRecording && !RunScheduleEditorPtr) ||
6896  (EditType == kViewSchedule && !RunViewScheduledPtr) ||
6897  (EditType == kPlaybackBox && !RunPlaybackBoxPtr))
6898  {
6899  return;
6900  }
6901 
6903 
6904  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
6906  {
6907  LOG(VB_GENERAL, LOG_ERR, LOC + "no active ctx playingInfo.");
6908  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6909  ReturnPlayerLock();
6910  return;
6911  }
6912 
6913  // Collect channel info
6914  const ProgramInfo pginfo(*m_playerContext.m_playingInfo);
6915  uint chanid = pginfo.GetChanID();
6916  QString channum = pginfo.GetChanNum();
6917  QDateTime starttime = MythDate::current();
6918  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6919 
6920  ClearOSD();
6921 
6922  // Pause playback as needed...
6923  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
6924  bool pause = !m_player || (!StateIsLiveTV(GetState()) && !m_dbContinueEmbedded);
6925  if (m_player)
6926  {
6927  pause |= !m_player->GetVideoOutput();
6928  pause |= m_player->IsPaused();
6929  if (!pause)
6930  pause |= (!StateIsLiveTV(GetState()) && m_player->IsNearEnd());
6931  }
6932  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
6933 
6934  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Pausing player: %1").arg(pause));
6935  m_savedPause = DoSetPauseState(pause);
6936 
6937  // Resize window to the MythTV GUI size
6938  MythDisplay* display = m_mainWindow->GetDisplay();
6939  if (display->UsingVideoModes())
6940  {
6941  bool hide = display->NextModeIsLarger(display->GetGUIResolution());
6942  if (hide)
6943  m_mainWindow->hide();
6944  display->SwitchToGUI(true);
6945  if (hide)
6946  m_mainWindow->Show();
6947  }
6948 
6949  if (!m_dbUseGuiSizeForTv)
6951 #ifdef Q_OS_ANDROID
6952  m_mainWindow->Show();
6953 #else
6954  m_mainWindow->show();
6955 #endif
6956  ReturnPlayerLock();
6957 
6958 
6959  // Actually show the pop-up UI
6960  switch (EditType)
6961  {
6962  case kScheduleProgramGuide:
6963  {
6964  RunProgramGuidePtr(chanid, channum, starttime, this,
6965  !pause, true, m_channelGroupId);
6966  m_ignoreKeyPresses = true;
6967  break;
6968  }
6970  {
6971  RunProgramFinderPtr(this, !pause, true);
6972  m_ignoreKeyPresses = true;
6973  break;
6974  }
6975  case kScheduleProgramList:
6976  {
6977  /*
6978  4 = plPeopleSearch in mythfrontend/proglist.h
6979  This could be expanded to view other program lists...
6980  */
6981  RunProgramListPtr(this, 4, EditArg);
6982  m_ignoreKeyPresses = true;
6983  break;
6984  }
6985  case kScheduledRecording:
6986  {
6987  RunScheduleEditorPtr(&pginfo, reinterpret_cast<void*>(this));
6988  m_ignoreKeyPresses = true;
6989  break;
6990  }
6991  case kViewSchedule:
6992  {
6993  RunViewScheduledPtr(reinterpret_cast<void*>(this), !pause);
6994  m_ignoreKeyPresses = true;
6995  break;
6996  }
6997  case kPlaybackBox:
6998  {
6999  RunPlaybackBoxPtr(reinterpret_cast<void*>(this), !pause);
7000  m_ignoreKeyPresses = true;
7001  break;
7002  }
7003  }
7004 
7005  // We are embedding in a mythui window so assuming no one
7006  // else has disabled painting show the MythUI window again.
7007  if (m_weDisabledGUI)
7008  {
7010  m_weDisabledGUI = false;
7011  }
7012 }
7013 
7014 void TV::EditSchedule(int EditType, const QString& arg)
7015 {
7016  // post the request so the guide will be created in the UI thread
7017  QString message = QString("START_EPG %1 %2").arg(EditType).arg(arg);
7018  auto* me = new MythEvent(message);
7019  QCoreApplication::postEvent(this, me);
7020 }
7021 
7022 void TV::VolumeChange(bool Up, int NewVolume)
7023 {
7025  return;
7026 
7027  if ((m_audioState.m_muteState == kMuteAll) && (Up || NewVolume >= 0))
7028  emit ChangeMuteState();
7029 
7030  emit ChangeVolume(Up, NewVolume);
7031 
7033  {
7034  if (LCD *lcd = LCD::Get())
7035  {
7036  QString appName = tr("Video");
7037 
7038  if (StateIsLiveTV(GetState()))
7039  appName = tr("TV");
7040 
7042  appName = tr("DVD");
7043 
7044  lcd->switchToVolume(appName);
7045  lcd->setVolumeLevel(static_cast<float>(m_audioState.m_volume) / 100);
7046 
7047  if (m_lcdVolumeTimerId)
7049  m_lcdVolumeTimerId = StartTimer(2s, __LINE__);
7050  }
7051  }
7052 }
7053 
7055 {
7056  if (m_playerContext.m_tsNormal == 1.0F)
7057  {
7059  }
7060  else
7061  {
7063  m_playerContext.m_tsNormal = 1.0F;
7064  }
7065  ChangeTimeStretch(0, false);
7066 }
7067 
7068 void TV::ChangeTimeStretch(int Dir, bool AllowEdit)
7069 {
7070  const float kTimeStretchMin = 0.125;
7071  const float kTimeStretchMax = 2.0;
7072  const float kTimeStretchStep = 0.05F;
7073  float new_ts_normal = m_playerContext.m_tsNormal + (kTimeStretchStep * Dir);
7074  m_stretchAdjustment = AllowEdit;
7075 
7076  if (new_ts_normal > kTimeStretchMax &&
7077  m_playerContext.m_tsNormal < kTimeStretchMax)
7078  {
7079  new_ts_normal = kTimeStretchMax;
7080  }
7081  else if (new_ts_normal < kTimeStretchMin &&
7082  m_playerContext.m_tsNormal > kTimeStretchMin)
7083  {
7084  new_ts_normal = kTimeStretchMin;
7085  }
7086 
7087  if (new_ts_normal > kTimeStretchMax ||
7088  new_ts_normal < kTimeStretchMin)
7089  {
7090  return;
7091  }
7092 
7093  m_playerContext.m_tsNormal = kTimeStretchStep * lroundf(new_ts_normal / kTimeStretchStep);
7094 
7095  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7096  if (m_player && !m_player->IsPaused())
7098  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7099 
7101  {
7102  if (!AllowEdit)
7103  {
7105  }
7106  else
7107  {
7108  UpdateOSDStatus(tr("Adjust Time Stretch"), tr("Time Stretch"),
7109  QString::number(static_cast<double>(m_playerContext.m_tsNormal), 'f', 2),
7111  static_cast<int>(m_playerContext.m_tsNormal * (1000 / kTimeStretchMax)),
7113  emit ChangeOSDPositionUpdates(false);
7114  }
7115  }
7116 
7117  SetSpeedChangeTimer(0ms, __LINE__);
7118 }
7119 
7121 {
7122  QString text;
7123 
7124  // increment sleep index, cycle through
7125  if (++m_sleepIndex == s_sleepTimes.size())
7126  m_sleepIndex = 0;
7127 
7128  // set sleep timer to next sleep_index timeout
7129  if (m_sleepTimerId)
7130  {
7132  m_sleepTimerId = 0;
7133  m_sleepTimerTimeout = 0ms;
7134  }
7135 
7136  if (s_sleepTimes[m_sleepIndex].milliseconds != 0ms)
7137  {
7140  }
7141 
7142  text = tr("Sleep ") + " " + s_sleepTimes[m_sleepIndex].dispString;
7143  emit ChangeOSDMessage(text);
7144 }
7145 
7147 {
7149  m_sleepTimerId = 0;
7150 
7151  QString message = tr("MythTV was set to sleep after %1 minutes and will exit in %d seconds.\n"
7152  "Do you wish to continue watching?")
7153  .arg(duration_cast<std::chrono::minutes>(m_sleepTimerTimeout).count());
7154 
7156  { { tr("Yes"), "DIALOG_SLEEP_YES_0" },
7157  { tr("No"), "DIALOG_SLEEP_NO_0" } }});
7158 
7160 }
7161 
7162 void TV::HandleOSDSleep(const QString& Action)
7163 {
7165  return;
7166 
7167  if (Action == "YES")
7168  {
7170  {
7173  }
7175  }
7176  else
7177  {
7178  LOG(VB_GENERAL, LOG_INFO, LOC + "No longer watching TV, exiting");
7179  SetExitPlayer(true, true);
7180  }
7181 }
7182 
7184 {
7187 
7188  LOG(VB_GENERAL, LOG_INFO, LOC + "Sleep timeout reached, exiting player.");
7189 
7190  SetExitPlayer(true, true);
7191 }
7192 
7202 {
7204  m_idleTimerId = 0;
7205 
7206  QString message = tr("MythTV has been idle for %1 minutes and "
7207  "will exit in %d seconds. Are you still watching?")
7208  .arg(duration_cast<std::chrono::minutes>(m_dbIdleTimeout).count());
7209 
7211  { { tr("Yes"), "DIALOG_IDLE_YES_0" },
7212  { tr("No"), "DIALOG_IDLE_NO_0" }}});
7213 
7215 }
7216 
7217 void TV::HandleOSDIdle(const QString& Action)
7218 {
7220  return;
7221 
7222  if (Action == "YES")
7223  {
7224  if (m_idleDialogTimerId)
7225  {
7227  m_idleDialogTimerId = 0;
7228  }
7229  if (m_idleTimerId)
7232  }
7233  else
7234  {
7235  LOG(VB_GENERAL, LOG_INFO, LOC + "No longer watching LiveTV, exiting");
7236  SetExitPlayer(true, true);
7237  }
7238 }
7239 
7241 {
7243  m_idleDialogTimerId = 0;
7244 
7247  {
7248  LOG(VB_GENERAL, LOG_INFO, LOC + "Idle timeout reached, leaving LiveTV");
7249  SetExitPlayer(true, true);
7250  }
7251  ReturnPlayerLock();
7252 }
7253 
7254 // Retrieve the proper MythTVMenu object from The TV object, given its
7255 // id number. This is used to find the original menu again, instead of
7256 // serializing/deserializing the entire MythTVMenu object to/from a
7257 // QVariant.
7259 {
7260  switch (id) {
7261  case kMenuIdPlayback:
7262  return m_playbackMenu;
7264  return m_playbackCompactMenu;
7265  case kMenuIdCutlist:
7266  return m_cutlistMenu;
7267  case kMenuIdCutlistCompact:
7268  return m_cutlistCompactMenu;
7269  default:
7270  return dummy_menubase;
7271  }
7272 }
7273 
7275 void TV::customEvent(QEvent *Event)
7276 {
7278  {
7280  return;
7281  }
7282 
7283  if (Event->type() == MythEvent::kMythUserMessage)
7284  {
7285  auto *me = dynamic_cast<MythEvent*>(Event);
7286  if (me == nullptr)
7287  return;
7288  QString message = me->Message();
7289 
7290  if (message.isEmpty())
7291  return;
7292 
7293  std::chrono::milliseconds timeout = 0ms;
7294  if (me->ExtraDataCount() == 1)
7295  {
7296  auto t = std::chrono::seconds(me->ExtraData(0).toInt());
7297  if (t > 0s && t < 1000s)
7298  timeout = t;
7299  }
7300 
7301  if (timeout > 0ms)
7302  message += " (%d)";
7303 
7304  emit ChangeOSDDialog( { OSD_DLG_CONFIRM, message, timeout });
7305  return;
7306  }
7307 
7309  {
7310  auto *b = reinterpret_cast<UpdateBrowseInfoEvent*>(Event);
7312  return;
7313  }
7314 
7316  {
7317  auto *dce = reinterpret_cast<DialogCompletionEvent*>(Event);
7318  if (dce->GetData().userType() == qMetaTypeId<MythTVMenuNodeTuple>())
7319  {
7320  auto data = dce->GetData().value<MythTVMenuNodeTuple>();
7321  const MythTVMenu& Menu = getMenuFromId(data.m_id);
7322  QDomNode Node = Menu.GetNodeFromPath(data.m_path);
7323  if (dce->GetResult() == -1) // menu exit/back
7324  PlaybackMenuShow(Menu, Node.parentNode(), Node);
7325  else
7326  PlaybackMenuShow(Menu, Node, QDomNode());
7327  }
7328  else
7329  {
7330  OSDDialogEvent(dce->GetResult(), dce->GetResultText(), dce->GetData().toString());
7331  }
7332  return;
7333  }
7334 
7335  // Stop DVD playback cleanly when the DVD is ejected
7336  if (Event->type() == MythMediaEvent::kEventType)
7337  {
7339  TVState state = m_playerContext.GetState();
7340  if (state != kState_WatchingDVD)
7341  {
7342  ReturnPlayerLock();
7343  return;
7344  }
7345 
7346  auto *me = dynamic_cast<MythMediaEvent*>(Event);
7347  if (me == nullptr)
7348  return;
7349  MythMediaDevice *device = me->getDevice();
7350 
7352 
7353  if (device && filename.endsWith(device->getDevicePath()) && (device->getStatus() == MEDIASTAT_OPEN))
7354  {
7355  LOG(VB_GENERAL, LOG_NOTICE, "DVD has been ejected, exiting playback");
7356  PrepareToExitPlayer(__LINE__);
7357  SetExitPlayer(true, true);
7358  }
7359  ReturnPlayerLock();
7360  return;
7361  }
7362 
7363  if (Event->type() != MythEvent::kMythEventMessage)
7364  return;
7365 
7366  uint cardnum = 0;
7367  auto *me = dynamic_cast<MythEvent*>(Event);
7368  if (me == nullptr)
7369  return;
7370  QString message = me->Message();
7371 
7372  // TODO Go through these and make sure they make sense...
7373  QStringList tokens = message.split(" ", Qt::SkipEmptyParts);
7374 
7375  if (me->ExtraDataCount() == 1)
7376  {
7378  int value = me->ExtraData(0).toInt();
7379  if (message == ACTION_SETVOLUME)
7380  VolumeChange(false, value);
7381  else if (message == ACTION_SETAUDIOSYNC)
7382  emit ChangeAudioOffset(0ms, std::chrono::milliseconds(value));
7383  else if (message == ACTION_SETBRIGHTNESS)
7385  else if (message == ACTION_SETCONTRAST)
7387  else if (message == ACTION_SETCOLOUR)
7389  else if (message == ACTION_SETHUE)
7390  emit ChangePictureAttribute(kPictureAttribute_Hue, false, value);
7391  else if (message == ACTION_JUMPCHAPTER)
7392  DoJumpChapter(value);
7393  else if (message == ACTION_SWITCHTITLE)
7394  DoSwitchTitle(value - 1);
7395  else if (message == ACTION_SWITCHANGLE)
7396  DoSwitchAngle(value);
7397  else if (message == ACTION_SEEKABSOLUTE)
7398  DoSeekAbsolute(value, /*honorCutlist*/true);
7399  ReturnPlayerLock();
7400  }
7401 
7402  if (message == ACTION_SCREENSHOT)
7403  {
7404  int width = 0;
7405  int height = 0;
7406  QString filename;
7407 
7408  if (me->ExtraDataCount() >= 2)
7409  {
7410  width = me->ExtraData(0).toInt();
7411  height = me->ExtraData(1).toInt();
7412 
7413  if (me->ExtraDataCount() == 3)
7414  filename = me->ExtraData(2);
7415  }
7416  MythMainWindow::ScreenShot(width, height, filename);
7417  }
7418  else if (message == ACTION_GETSTATUS)
7419  {
7420  GetStatus();
7421  }
7422  else if (message.startsWith("DONE_RECORDING"))
7423  {
7424  std::chrono::seconds seconds = 0s;
7425  //long long frames = 0;
7426  int NUMTOKENS = 4; // Number of tokens expected
7427  if (tokens.size() == NUMTOKENS)
7428  {
7429  cardnum = tokens[1].toUInt();
7430  seconds = std::chrono::seconds(tokens[2].toInt());
7431  //frames = tokens[3].toLongLong();
7432  }
7433  else
7434  {
7435  LOG(VB_GENERAL, LOG_ERR, QString("DONE_RECORDING event received "
7436  "with invalid number of arguments, "
7437  "%1 expected, %2 actual")
7438  .arg(NUMTOKENS-1)
7439  .arg(tokens.size()-1));
7440  return;
7441  }
7442 
7445  {
7446  if (m_playerContext.m_recorder && (cardnum == m_playerContext.GetCardID()))
7447  {
7448  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7449  if (m_player)
7450  {
7452  if (seconds > 0s)
7453  m_player->SetLength(seconds);
7454  }
7455  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7456 
7459  }
7460  }
7462  {
7463  if (m_playerContext.m_recorder && cardnum == m_playerContext.GetCardID() &&
7465  {
7466  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7467  if (m_player)
7468  {
7470  if (seconds > 0s)
7471  m_player->SetLength(seconds);
7472  }
7473  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7474  }
7475  }
7476  ReturnPlayerLock();
7477  }
7478 
7479  if (message.startsWith("ASK_RECORDING "))
7480  {
7481  int timeuntil = 0;
7482  bool hasrec = false;
7483  bool haslater = false;
7484  if (tokens.size() >= 5)
7485  {
7486  cardnum = tokens[1].toUInt();
7487  timeuntil = tokens[2].toInt();
7488  hasrec = (tokens[3].toInt() != 0);
7489  haslater = (tokens[4].toInt() != 0);
7490  }
7491  LOG(VB_GENERAL, LOG_DEBUG,
7492  LOC + message + QString(" hasrec: %1 haslater: %2")
7493  .arg(hasrec).arg(haslater));
7494 
7497  AskAllowRecording(me->ExtraDataList(), timeuntil, hasrec, haslater);
7498 
7499  ReturnPlayerLock();
7500  }
7501 
7502  if (message.startsWith("QUIT_LIVETV"))
7503  {
7504  cardnum = (tokens.size() >= 2) ? tokens[1].toUInt() : 0;
7505 
7507  bool match = m_playerContext.GetCardID() == cardnum;
7508  if (match && m_playerContext.m_recorder)
7509  {
7510  SetLastProgram(nullptr);
7511  m_jumpToProgram = true;
7512  SetExitPlayer(true, false);
7513  }
7514  ReturnPlayerLock();
7515  }
7516 
7517  if (message.startsWith("LIVETV_WATCH"))
7518  {
7519  int watch = 0;
7520  if (tokens.size() >= 3)
7521  {
7522  cardnum = tokens[1].toUInt();
7523  watch = tokens[2].toInt();
7524  }
7525 
7527  if (m_playerContext.GetCardID() == cardnum)
7528  {
7529  if (watch)
7530  {
7531  ProgramInfo pi(me->ExtraDataList());
7532  if (pi.HasPathname() || pi.GetChanID())
7533  {
7536  m_pseudoChangeChanTimerId = StartTimer(0ms, __LINE__);
7537  }
7538  }
7539  else
7540  {
7542  }
7543  }
7544  ReturnPlayerLock();
7545  }
7546 
7547  if (message.startsWith("LIVETV_CHAIN"))
7548  {
7549  QString id;
7550  if ((tokens.size() >= 2) && tokens[1] == "UPDATE")
7551  id = tokens[2];
7552 
7555  m_playerContext.UpdateTVChain(me->ExtraDataList());
7556  ReturnPlayerLock();
7557  }
7558 
7559  if (message.startsWith("EXIT_TO_MENU"))
7560  {
7562  PrepareToExitPlayer(__LINE__);
7563  SetExitPlayer(true, true);
7564  emit DisableEdit(-1);
7565  ReturnPlayerLock();
7566  }
7567 
7568  if (message.startsWith("SIGNAL"))
7569  {
7570  cardnum = (tokens.size() >= 2) ? tokens[1].toUInt() : 0;
7571  const QStringList& signalList = me->ExtraDataList();
7572 
7574  OSD *osd = GetOSDL();
7575  if (osd)
7576  {
7577  if (m_playerContext.m_recorder && (m_playerContext.GetCardID() == cardnum) && !signalList.empty())
7578  {
7579  UpdateOSDSignal(signalList);
7581  }
7582  }
7583  ReturnOSDLock();
7584  ReturnPlayerLock();
7585  }
7586 
7587  if (message.startsWith("NETWORK_CONTROL"))
7588  {
7589  if ((tokens.size() >= 2) &&
7590  (tokens[1] != "ANSWER") && (tokens[1] != "RESPONSE"))
7591  {
7592  QStringList tokens2 = message.split(" ", Qt::SkipEmptyParts);
7593  if ((tokens2.size() >= 2) &&
7594  (tokens2[1] != "ANSWER") && (tokens2[1] != "RESPONSE"))
7595  {
7598  m_networkControlTimerId = StartTimer(1ms, __LINE__);
7599  }
7600  }
7601  }
7602 
7603  if (message.startsWith("START_EPG"))
7604  {
7605  int editType = tokens[1].toInt();
7606  QString arg = message.section(" ", 2, -1);
7607  DoEditSchedule(editType, arg);
7608  }
7609 
7610  if (message.startsWith("COMMFLAG_START") && (tokens.size() >= 2))
7611  {
7612  uint evchanid = 0;
7613  QDateTime evrecstartts;
7614  ProgramInfo::ExtractKey(tokens[1], evchanid, evrecstartts);
7615 
7617  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7618  bool doit = ((m_playerContext.m_playingInfo) &&
7619  (m_playerContext.m_playingInfo->GetChanID() == evchanid) &&
7620  (m_playerContext.m_playingInfo->GetRecordingStartTime() == evrecstartts));
7621  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7622 
7623  if (doit)
7624  {
7625  QString msg = "COMMFLAG_REQUEST ";
7626  msg += ProgramInfo::MakeUniqueKey(evchanid, evrecstartts);
7627  gCoreContext->SendMessage(msg);
7628  }
7629  ReturnPlayerLock();
7630  }
7631 
7632  if (message.startsWith("COMMFLAG_UPDATE") && (tokens.size() >= 3))
7633  {
7634  uint evchanid = 0;
7635  QDateTime evrecstartts;
7636  ProgramInfo::ExtractKey(tokens[1], evchanid, evrecstartts);
7637 
7639  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7640  bool doit = ((m_playerContext.m_playingInfo) &&
7641  (m_playerContext.m_playingInfo->GetChanID() == evchanid) &&
7642  (m_playerContext.m_playingInfo->GetRecordingStartTime() == evrecstartts));
7643  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7644 
7645  if (doit)
7646  {
7647  frm_dir_map_t newMap;
7648  QStringList mark;
7649  QStringList marks = tokens[2].split(",", Qt::SkipEmptyParts);
7650  for (int j = 0; j < marks.size(); j++)
7651  {
7652  mark = marks[j].split(":", Qt::SkipEmptyParts);
7653  if (marks.size() >= 2)
7654  newMap[mark[0].toULongLong()] = static_cast<MarkTypes>(mark[1].toInt());
7655  }
7656  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7657  if (m_player)
7658  m_player->SetCommBreakMap(newMap);
7659  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7660  }
7661  ReturnPlayerLock();
7662  }
7663 
7664  if (message == "NOTIFICATION")
7665  {
7666  if (!GetNotificationCenter())
7667  return;
7668  MythNotification mn(*me);
7670  }
7671 }
7672 
7674 {
7675  BrowseInfo bi = GetBrowsedInfo();
7676  if (bi.m_chanId)
7677  {
7678  InfoMap infoMap;
7679  QDateTime startts = MythDate::fromString(bi.m_startTime);
7680 
7682  RecordingInfo recinfo(bi.m_chanId, startts, false, 0h, &status);
7683  if (RecordingInfo::kFoundProgram == status)
7684  recinfo.QuickRecord();
7685  recinfo.ToMap(infoMap);
7686  infoMap["iconpath"] = ChannelUtil::GetIcon(recinfo.GetChanID());
7687  if ((recinfo.IsVideoFile() || recinfo.IsVideoDVD() ||
7688  recinfo.IsVideoBD()) && recinfo.GetPathname() != recinfo.GetBasename())
7689  {
7690  infoMap["coverartpath"] = VideoMetaDataUtil::GetArtPath(
7691  recinfo.GetPathname(), "Coverart");
7692  infoMap["fanartpath"] = VideoMetaDataUtil::GetArtPath(
7693  recinfo.GetPathname(), "Fanart");
7694  infoMap["bannerpath"] = VideoMetaDataUtil::GetArtPath(
7695  recinfo.GetPathname(), "Banners");
7696  infoMap["screenshotpath"] = VideoMetaDataUtil::GetArtPath(
7697  recinfo.GetPathname(), "Screenshots");
7698  }
7699 
7701  InfoMap map;
7702  map.insert("message_text", tr("Record"));
7704  return;
7705  }
7706 
7707  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7709  {
7710  LOG(VB_GENERAL, LOG_CRIT, LOC + "Unknown recording during live tv.");
7711  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7712  return;
7713  }
7714 
7715  QString cmdmsg("");
7717  {
7719  recInfo.SaveAutoExpire(static_cast<AutoExpireType>(m_dbAutoexpireDefault));
7720  recInfo.ApplyRecordRecGroupChange("Default");
7721  *m_playerContext.m_playingInfo = recInfo;
7722 
7723  cmdmsg = tr("Record");
7726  LOG(VB_RECORD, LOG_INFO, LOC + "Toggling Record on");
7727  }
7728  else
7729  {
7732  recInfo.ApplyRecordRecGroupChange("LiveTV");
7733  *m_playerContext.m_playingInfo = recInfo;
7734 
7735  cmdmsg = tr("Cancel Record");
7738  LOG(VB_RECORD, LOG_INFO, LOC + "Toggling Record off");
7739  }
7740 
7741  QString msg = cmdmsg + " \"" + m_playerContext.m_playingInfo->GetTitle() + "\"";
7742 
7743  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7744 
7745  emit ChangeOSDMessage(msg);
7746 }
7747 
7748 void TV::HandleOSDClosed(int OSDType)
7749 {
7750  switch (OSDType)
7751  {
7755  break;
7757  m_doSmartForward = false;
7758  break;
7760  m_stretchAdjustment = false;
7761  break;
7763  m_audiosyncAdjustment = false;
7764  gCoreContext->SaveSetting("AudioSyncOffset", QString::number(m_audioState.m_audioOffset.count()));
7765  break;
7767  m_subtitleZoomAdjustment = false;
7768  break;
7770  m_subtitleDelayAdjustment = false;
7771  break;
7773  break;
7774  }
7775 }
7776 
7778 {
7780  if ((kAdjustingPicture_Playback == Type))
7781  {
7785  // Filter out range
7787  }
7788  else if ((kAdjustingPicture_Channel == Type) || (kAdjustingPicture_Recording == Type))
7789  {
7794  }
7795 
7796  return ::next_picattr(static_cast<PictureAttributeSupported>(sup), Attr);
7797 }
7798 
7800 {
7802  if (kPictureAttribute_None == attr)
7803  return;
7804 
7805  m_adjustingPicture = Type;
7807 
7808  QString title = toTitleString(Type);
7809 
7810  int value = 99;
7811  if (kAdjustingPicture_Playback == Type)
7812  {
7814  {
7815  value = m_videoColourState.GetValue(attr);
7816  }
7818  {
7819  value = static_cast<int>(m_audioState.m_volume);
7820  title = tr("Adjust Volume");
7821  }
7822  }
7823 
7826 
7827  QString text = toString(attr) + " " + toTypeString(Type);
7828 
7829  UpdateOSDStatus(title, text, QString::number(value),
7831  value * 10, kOSDTimeout_Med);
7832  emit ChangeOSDPositionUpdates(false);
7833 }
7834 
7835 void TV::ShowOSDCutpoint(const QString &Type)
7836 {
7837  if (Type == "EDIT_CUT_POINTS")
7838  {
7839  if (!m_cutlistMenu.IsLoaded())
7840  {
7841  // TODO which translation context to use?
7843  "menu_cutlist.xml", tr("Edit Cut Points"),
7844  metaObject()->className(), "TV Editing");
7845  }
7846 
7847  if (m_cutlistMenu.IsLoaded())
7849  }
7850  else if (Type == "EDIT_CUT_POINTS_COMPACT")
7851  {
7853  {
7854  // TODO which translation context to use?
7856  "menu_cutlist_compact.xml", tr("Edit Cut Points"),
7857  metaObject()->className(), "TV Editing");
7858  }
7859 
7862  }
7863  else if (Type == "EXIT_EDIT_MODE")
7864  {
7865  MythOSDDialogData dialog { OSD_DLG_CUTPOINT, tr("Exit Recording Editor") };
7866  dialog.m_buttons.push_back( { tr("Save Cuts and Exit"), "DIALOG_CUTPOINT_SAVEEXIT_0" } );
7867  dialog.m_buttons.push_back( { tr("Exit Without Saving"), "DIALOG_CUTPOINT_REVERTEXIT_0" } );
7868  dialog.m_buttons.push_back( { tr("Save Cuts"), "DIALOG_CUTPOINT_SAVEMAP_0" } );
7869  dialog.m_buttons.push_back( { tr("Undo Changes"), "DIALOG_CUTPOINT_REVERT_0" } );
7870  dialog.m_back = { "", "DIALOG_CUTPOINT_DONOTHING_0", true };
7871  emit ChangeOSDDialog(dialog);
7872 
7873  InfoMap map;
7874  map.insert("title", tr("Edit"));
7876  }
7877 }
7878 
7879 bool TV::HandleOSDCutpoint(const QString& Action)
7880 {
7881  bool res = true;
7883  return res;
7884 
7885  OSD *osd = GetOSDL();
7886  if (Action == "DONOTHING" && osd)
7887  {
7888  }
7889  else if (osd)
7890  {
7891  QStringList actions(Action);
7892  if (!m_player->HandleProgramEditorActions(actions))
7893  LOG(VB_GENERAL, LOG_ERR, LOC + "Unrecognised cutpoint action");
7894  }
7895  ReturnOSDLock();
7896  return res;
7897 }
7898 
7903 {
7904  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7905  bool isEditing = m_playerContext.m_playingInfo->QueryIsEditing();
7906  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7907 
7908  if (isEditing)
7909  {
7911  return;
7912  }
7913 
7914  emit EnableEdit();
7915 }
7916 
7918 {
7919  bool paused = ContextIsPaused(__FILE__, __LINE__);
7920  if (!paused)
7921  DoTogglePause(true);
7922 
7923  QString message = tr("This program is currently being edited");
7924  QString def = QString("DIALOG_EDITING_CONTINUE_%1").arg(static_cast<int>(paused));
7925  emit ChangeOSDDialog( { OSD_DLG_EDITING, message, 0ms,
7926  { { tr("Continue Editing"), def, false, true },
7927  { tr("Do not edit"), QString("DIALOG_EDITING_STOP_%1").arg(static_cast<int>(paused)) }},
7928  { "", def, true} });
7929 }
7930 
7931 void TV::HandleOSDAlreadyEditing(const QString& Action, bool WasPaused)
7932 {
7934  return;
7935 
7936  bool paused = ContextIsPaused(__FILE__, __LINE__);
7937 
7938  if (Action == "STOP")
7939  {
7940  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7943  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7944  if (!WasPaused && paused)
7945  DoTogglePause(true);
7946  }
7947  else // action == "CONTINUE"
7948  {
7949  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7951  emit EnableEdit();
7952  if (!m_overlayState.m_editing && !WasPaused && paused)
7953  DoTogglePause(false);
7954  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7955  }
7956 
7957 }
7958 
7959 static void insert_map(InfoMap &infoMap, const InfoMap &newMap)
7960 {
7961  for (auto it = newMap.cbegin(); it != newMap.cend(); ++it)
7962  infoMap.insert(it.key(), *it);
7963 }
7964 
7969 {
7970  OSD *osd = GetOSDL();
7971  if (!m_playerContext.m_recorder || !osd)
7972  {
7973  ReturnOSDLock();
7974  return;
7975  }
7976  ReturnOSDLock();
7977 
7978  QMutexLocker locker(&m_chanEditMapLock);
7979 
7980  // Get the info available from the backend
7981  m_chanEditMap.clear();
7983 
7984  // Update with XDS Info
7986 
7987  // Set proper initial values for channel editor, and make it visible..
7988  osd = GetOSDL();
7989  if (osd)
7990  {
7991  emit ChangeOSDDialog({ OSD_DLG_EDITOR });
7993  }
7994  ReturnOSDLock();
7995 }
7996 
7998 {
7999  OSD *osd = GetOSDL();
8000  if (osd)
8001  {
8002  emit HideAll();
8003  ToggleOSD(true);
8005  }
8006  ReturnOSDLock();
8007 }
8008 
8012 bool TV::HandleOSDChannelEdit(const QString& Action)
8013 {
8014  QMutexLocker locker(&m_chanEditMapLock);
8015  bool hide = false;
8016 
8018  return hide;
8019 
8020  OSD *osd = GetOSDL();
8021  if (osd && Action == "PROBE")
8022  {
8023  InfoMap infoMap;
8024  osd->DialogGetText(infoMap);
8025  ChannelEditAutoFill(infoMap);
8026  insert_map(m_chanEditMap, infoMap);
8028  }
8029  else if (osd && Action == "OK")
8030  {
8031  InfoMap infoMap;
8032  osd->DialogGetText(infoMap);
8033  insert_map(m_chanEditMap, infoMap);
8035  hide = true;
8036  }
8037  else if (osd && Action == "QUIT")
8038  {
8039  hide = true;
8040  }
8041  ReturnOSDLock();
8042  return hide;
8043 }
8044 
8049 {
8050 #if 0
8051  const QString keys[4] = { "XMLTV", "callsign", "channame", "channum", };
8052 #endif
8053 
8054  // fill in uninitialized and unchanged fields from XDS
8055  ChannelEditXDSFill(Info);
8056 }
8057 
8059 {
8060  QMap<QString,bool> modifiable;
8061  modifiable["callsign"] = Info["callsign"].isEmpty();
8062  if (!modifiable["callsign"])
8063  {
8064  QString unsetsign = tr("UNKNOWN%1", "Synthesized callsign");
8065  int unsetcmpl = unsetsign.length() - 2;
8066  unsetsign = unsetsign.left(unsetcmpl);
8067  if (Info["callsign"].left(unsetcmpl) == unsetsign) // was unsetcmpl????
8068  modifiable["callsign"] = true;
8069  }
8070  modifiable["channame"] = Info["channame"].isEmpty();
8071 
8072  const std::array<const QString,2> xds_keys { "callsign", "channame", };
8073  for (const auto & key : xds_keys)
8074  {
8075  if (!modifiable[key])
8076  continue;
8077 
8078  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
8079  QString tmp = m_player->GetXDS(key).toUpper();
8080  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
8081 
8082  if (tmp.isEmpty())
8083  continue;
8084 
8085  if ((key == "callsign") &&
8086  ((tmp.length() > 5) || (tmp.indexOf(" ") >= 0)))
8087  {
8088  continue;
8089  }
8090 
8091  Info[key] = tmp;
8092  }
8093 }
8094 
8095 void TV::OSDDialogEvent(int Result, const QString& Text, QString Action)
8096 {
8098  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("result %1 text %2 action %3")
8099  .arg(QString::number(Result), Text, Action));
8100 
8101  bool hide = true;
8102  if (Result == 100)
8103  hide = false;
8104 
8105  bool handled = true;
8106  if (Action.startsWith("DIALOG_"))
8107  {
8108  Action.remove("DIALOG_");
8109  QStringList desc = Action.split("_");
8110  bool valid = desc.size() == 3;
8111  if (valid && desc[0] == ACTION_JUMPREC)
8112  {
8113  FillOSDMenuJumpRec(desc[1], desc[2].toInt(), Text);
8114  hide = false;
8115  }
8116  else if (valid && desc[0] == "VIDEOEXIT")
8117  {
8118  hide = HandleOSDVideoExit(desc[1]);
8119  }
8120  else if (valid && desc[0] == "SLEEP")
8121  {
8122  HandleOSDSleep(desc[1]);
8123  }
8124  else if (valid && desc[0] == "IDLE")
8125  {
8126  HandleOSDIdle(desc[1]);
8127  }
8128  else if (valid && desc[0] == "INFO")
8129  {
8130  HandleOSDInfo(desc[1]);
8131  }
8132  else if (valid && desc[0] == "EDITING")
8133  {
8134  HandleOSDAlreadyEditing(desc[1], desc[2].toInt() != 0);
8135  }
8136  else if (valid && desc[0] == "ASKALLOW")
8137  {
8138  HandleOSDAskAllow(desc[1]);
8139  }
8140  else if (valid && desc[0] == "EDITOR")
8141  {
8142  hide = HandleOSDChannelEdit(desc[1]);
8143  }
8144  else if (valid && desc[0] == "CUTPOINT")
8145  {
8146  hide = HandleOSDCutpoint(desc[1]);
8147  }
8148  else if ((valid && desc[0] == "DELETE") ||
8149  (valid && desc[0] == "CONFIRM"))
8150  {
8151  }
8152  else if (valid && desc[0] == ACTION_PLAY)
8153  {
8154  DoPlay();
8155  }
8156  else
8157  {
8158  LOG(VB_GENERAL, LOG_ERR, "Unrecognised dialog event.");
8159  }
8160  }
8161  else if (Result < 0)
8162  { // NOLINT(bugprone-branch-clone)
8163  ; // exit dialog
8164  }
8165  else if (HandleTrackAction(Action))
8166  {
8167  ;
8168  }
8169  else if (Action == ACTION_PAUSE)
8170  {
8171  DoTogglePause(true);
8172  }
8173  else if (Action == ACTION_STOP)
8174  {
8175  PrepareToExitPlayer(__LINE__);
8176  SetExitPlayer(true, true);
8177  }
8178  else if (Action == "CANCELPLAYLIST")
8179  {
8180  SetInPlayList(false);
8181  MythEvent xe("CANCEL_PLAYLIST");
8182  gCoreContext->dispatch(xe);
8183  }
8184  else if (Action == ACTION_JUMPFFWD)
8185  {
8186  DoJumpFFWD();
8187  }
8188  else if (Action == ACTION_JUMPRWND)
8189  {
8190  DoJumpRWND();
8191  }
8192  else if (Action == ACTION_SEEKFFWD)
8193  {
8194  DoSeekFFWD();
8195  }
8196  else if (Action == ACTION_SEEKRWND)
8197  {
8198  DoSeekRWND();
8199  }
8200  else if (Action == ACTION_TOGGLEOSDDEBUG)
8201  {
8202  emit ChangeOSDDebug();
8203  }
8204  else if (Action == "TOGGLEMANUALZOOM")
8205  {
8206  SetManualZoom(true, tr("Zoom Mode ON"));
8207  }
8208  else if (Action == ACTION_BOTTOMLINEMOVE)
8209  {
8210  emit ToggleMoveBottomLine();
8211  }
8212  else if (Action == ACTION_BOTTOMLINESAVE)
8213  {
8214  emit SaveBottomLine();
8215  }
8216  else if (Action == "TOGGLESTRETCH")
8217  {
8219  }
8220  else if (Action == ACTION_ENABLEUPMIX)
8221  {
8222  emit ChangeUpmix(true);
8223  }
8224  else if (Action == ACTION_DISABLEUPMIX)
8225  {
8226  emit ChangeUpmix(false);
8227  }
8228  else if (Action.startsWith("ADJUSTSTRETCH"))
8229  {
8230  bool floatRead = false;
8231  float stretch = Action.right(Action.length() - 13).toFloat(&floatRead);
8232  if (floatRead &&
8233  stretch <= 2.0F &&
8234  stretch >= 0.48F)
8235  {
8236  m_playerContext.m_tsNormal = stretch; // alter speed before display
8237  }
8238 
8239  StopFFRew();
8240 
8241  if (ContextIsPaused(__FILE__, __LINE__))
8242  DoTogglePause(true);
8243 
8244  ChangeTimeStretch(0, !floatRead); // just display
8245  }
8246  else if (Action.startsWith("SELECTSCAN_"))
8247  {
8248  OverrideScan(static_cast<FrameScanType>(Action.right(1).toInt()));
8249  }
8250  else if (Action.startsWith(ACTION_TOGGELAUDIOSYNC))
8251  {
8252  emit ChangeAudioOffset(0ms);
8253  }
8254  else if (Action == ACTION_TOGGLESUBTITLEZOOM)
8255  {
8256  emit AdjustSubtitleZoom(0);
8257  }
8258  else if (Action == ACTION_TOGGLESUBTITLEDELAY)
8259  {
8260  emit AdjustSubtitleDelay(0ms);
8261  }
8262  else if (Action == ACTION_TOGGLEVISUALISATION)
8263  {
8264  emit EnableVisualiser(false, true);
8265  }
8266  else if (Action == ACTION_ENABLEVISUALISATION)
8267  {
8268  emit EnableVisualiser(true);
8269  }
8270  else if (Action == ACTION_DISABLEVISUALISATION)
8271  {
8272  emit EnableVisualiser(false);
8273  }
8274  else if (Action.startsWith(ACTION_TOGGLESLEEP))
8275  {
8276  ToggleSleepTimer(Action.left(13));
8277  }
8278  else if (Action.startsWith("TOGGLEPICCONTROLS"))
8279  {
8280  m_adjustingPictureAttribute = static_cast<PictureAttribute>(Action.right(1).toInt() - 1);
8282  }
8283  else if (Action == "TOGGLEASPECT")
8284  {
8285  emit ChangeAspectOverride();
8286  }
8287  else if (Action.startsWith("TOGGLEASPECT"))
8288  {
8289  emit ChangeAspectOverride(static_cast<AspectOverrideMode>(Action.right(1).toInt()));
8290  }
8291  else if (Action == "TOGGLEFILL")
8292  {
8293  emit ChangeAdjustFill();
8294  }
8295  else if (Action.startsWith("TOGGLEFILL"))
8296  {
8297  emit ChangeAdjustFill(static_cast<AdjustFillMode>(Action.right(1).toInt()));
8298  }
8299  else if (Action == "MENU")
8300  {
8301  ShowOSDMenu();
8302  }
8303  else if (Action == "AUTODETECT_FILL")
8304  {
8305  emit ToggleDetectLetterBox();
8306  }
8307  else if (Action == ACTION_GUIDE)
8308  {
8310  }
8311  else if (Action.startsWith("CHANGROUP_") && m_dbUseChannelGroups)
8312  {
8313  if (Action == "CHANGROUP_ALL_CHANNELS")
8314  {
8315  UpdateChannelList(-1);
8316  }
8317  else
8318  {
8319  Action.remove("CHANGROUP_");
8320 
8321  UpdateChannelList(Action.toInt());
8322 
8323  // make sure the current channel is from the selected group
8324  // or tune to the first in the group
8325  QString cur_channum;
8326  QString new_channum;
8328  {
8329  QMutexLocker locker(&m_channelGroupLock);
8331  cur_channum = m_playerContext.m_tvchain->GetChannelName(-1);
8332  new_channum = cur_channum;
8333 
8334  auto it = list.cbegin();
8335  for (; it != list.cend(); ++it)
8336  {
8337  if ((*it).m_chanNum == cur_channum)
8338  {
8339  break;
8340  }
8341  }
8342 
8343  if (it == list.end())
8344  {
8345  // current channel not found so switch to the
8346  // first channel in the group
8347  it = list.begin();
8348  if (it != list.end())
8349  new_channum = (*it).m_chanNum;
8350  }
8351 
8352  LOG(VB_CHANNEL, LOG_INFO, LOC +
8353  QString("Channel Group: '%1'->'%2'")
8354  .arg(cur_channum, new_channum));
8355  }
8356 
8358  {
8359  // Only change channel if new channel != current channel
8360  if (cur_channum != new_channum && !new_channum.isEmpty())
8361  {
8362  m_queuedInput = new_channum;
8363  m_queuedChanNum = new_channum;
8364  m_queuedChanID = 0;
8365  if (!m_queueInputTimerId)
8366  m_queueInputTimerId = StartTimer(10ms, __LINE__);
8367  }
8368 
8369  // Turn off OSD Channel Num so the channel
8370  // changes right away
8372  }
8373  }
8374  }
8375  else if (Action == ACTION_FINDER)
8376  {
8378  }
8379  else if (Action == "SCHEDULE")
8380  {
8382  }
8383  else if (Action == ACTION_VIEWSCHEDULED)
8384  {
8386  }
8387  else if (Action == ACTION_CAST)
8388  {
8389  FillOSDMenuCast();
8390  hide = false;
8391  }
8392  else if (Action.startsWith("JUMPCAST|"))
8393  {
8394  QStringList tokens = Action.split("|");
8395  if (tokens.size() == 3)
8396  FillOSDMenuActorShows(tokens[1], tokens[2].toInt());
8397  else if (tokens.size() == 4)
8398  FillOSDMenuActorShows(tokens[1], tokens[2].toInt(), tokens[3]);
8399 
8400  hide = false;
8401  }
8402  else if (Action.startsWith("VISUALISER"))
8403  {
8404  emit EnableVisualiser(true, false, Action.mid(11));
8405  }
8406  else if (Action.startsWith("3D"))
8407  {
8409  }
8410  else if (HandleJumpToProgramAction(QStringList(Action)))
8411  {
8412  }
8413  else if (StateIsLiveTV(GetState()))
8414  {
8415  if (Action == "TOGGLEBROWSE")
8416  BrowseStart();
8417  else if (Action == "PREVCHAN")
8418  PopPreviousChannel(true);
8419  else if (Action.startsWith("SWITCHTOINPUT_"))
8420  {
8421  m_switchToInputId = Action.mid(14).toUInt();
8423  }
8424  else if (Action == "EDIT")
8425  {
8427  hide = false;
8428  }
8429  else
8430  {
8431  handled = false;
8432  }
8433  }
8434  else
8435  {
8436  handled = false;
8437  }
8438  if (!handled && StateIsPlaying(m_playerContext.GetState()))
8439  {
8440  handled = true;
8443  {
8445  emit GoToMenu("chapter");
8446  else if (Action == ACTION_JUMPTODVDTITLEMENU)
8447  emit GoToMenu("title");
8448  else if (Action == ACTION_JUMPTOPOPUPMENU)
8449  emit GoToMenu("popup");
8450  else
8451  emit GoToMenu("root");
8452  }
8453  else if (Action.startsWith(ACTION_JUMPCHAPTER))
8454  {
8455  int chapter = Action.right(3).toInt();
8456  DoJumpChapter(chapter);
8457  }
8458  else if (Action.startsWith(ACTION_SWITCHTITLE))
8459  {
8460  int title = Action.right(3).toInt();
8461  DoSwitchTitle(title);
8462  }
8463  else if (Action.startsWith(ACTION_SWITCHANGLE))
8464  {
8465  int angle = Action.right(3).toInt();
8466  DoSwitchAngle(angle);
8467  }
8468  else if (Action == "EDIT")
8469  {
8471  hide = false;
8472  }
8473  else if (Action == "TOGGLEAUTOEXPIRE")
8474  {
8475  ToggleAutoExpire();
8476  }
8477  else if (Action.startsWith("TOGGLECOMMSKIP"))
8478  {
8479  SetAutoCommercialSkip(static_cast<CommSkipMode>(Action.right(1).toInt()));
8480  }
8481  else if (Action == "QUEUETRANSCODE")
8482  {
8483  DoQueueTranscode("Default");
8484  }
8485  else if (Action == "QUEUETRANSCODE_AUTO")
8486  {
8487  DoQueueTranscode("Autodetect");
8488  }
8489  else if (Action == "QUEUETRANSCODE_HIGH")
8490  {
8491  DoQueueTranscode("High Quality");
8492  }
8493  else if (Action == "QUEUETRANSCODE_MEDIUM")
8494  {
8495  DoQueueTranscode("Medium Quality");
8496  }
8497  else if (Action == "QUEUETRANSCODE_LOW")
8498  {
8499  DoQueueTranscode("Low Quality");
8500  }
8501  else
8502  {
8503  handled = false;
8504  }
8505  }
8506 
8507  if (!handled)
8508  {
8511  handled = ActiveHandleAction(QStringList(Action), isDVD, isMenuOrStill);
8512  }
8513 
8514  if (!handled)
8515  handled = ActivePostQHandleAction(QStringList(Action));
8516 
8517  if (!handled)
8518  {
8519  LOG(VB_GENERAL, LOG_ERR, LOC +
8520  "Unknown menu action selected: " + Action);
8521  hide = false;
8522  }
8523 
8524  if (hide)
8525  emit DialogQuit();
8526  ReturnPlayerLock();
8527 }
8528 
8529 bool TV::DialogIsVisible(const QString &Dialog)
8530 {
8531  bool visible = false;
8532  OSD *osd = GetOSDL();
8533  if (osd)
8534  visible = osd->DialogVisible(Dialog);
8535  ReturnOSDLock();
8536  return visible;
8537 }
8538 
8539 void TV::HandleOSDInfo(const QString& Action)
8540 {
8542  return;
8543 
8544  if (Action == "CHANNELLOCK")
8545  m_lockTimerOn = false;
8546 }
8547 
8548 // NOLINTBEGIN(cppcoreguidelines-macro-usage)
8549 #define BUTTON(action, text) \
8550  result = Context.AddButton(Menu, active, (action), (text), "", false, "")
8551 #define BUTTON2(action, textActive, textInactive) \
8552  result = Context.AddButton(Menu, active, (action), (textActive), (textInactive), false, "")
8553 #define BUTTON3(action, textActive, textInactive, isMenu) \
8554  result = Context.AddButton(Menu, active, (action), (textActive), (textInactive), (isMenu), "")
8555 // NOLINTEND(cppcoreguidelines-macro-usage)
8556 
8558 {
8559  if (&Context.m_menu == &m_playbackMenu || &Context.m_menu == &m_playbackCompactMenu)
8560  return MenuItemDisplayPlayback(Context, Menu);
8561  if (&Context.m_menu == &m_cutlistMenu || &Context.m_menu == &m_cutlistCompactMenu)
8562  return MenuItemDisplayCutlist(Context, Menu);
8563  return false;
8564 }
8565 
8567 {
8568  MenuCategory category = Context.m_category;
8569  const QString &actionName = Context.m_action;
8570 
8571  bool result = false;
8572  if (category == kMenuCategoryMenu)
8573  {
8574  result = Context.m_menu.Show(Context.m_node, QDomNode(), *this, Menu, false);
8575  if (result && Context.m_visible)
8576  {
8577  QVariant v;
8578  v.setValue(MythTVMenuNodeTuple(Context.m_menu.m_id,
8580  Menu->m_buttons.push_back( { Context.m_menuName, v, true,
8581  Context.m_currentContext != kMenuCurrentDefault });
8582  }
8583  return result;
8584  }
8585 
8586  emit RefreshEditorState();
8587 
8588  if (category == kMenuCategoryItem)
8589  {
8590  bool active = true;
8591  if (actionName == "DIALOG_CUTPOINT_MOVEPREV_0")
8592  {
8597  {
8599  BUTTON2(actionName, tr("Move Previous Cut End Here"), tr("Move Start of Cut Here"));
8600  }
8601  }
8602  else if (actionName == "DIALOG_CUTPOINT_MOVENEXT_0")
8603  {
8608  {
8610  BUTTON2(actionName, tr("Move Next Cut Start Here"), tr("Move End of Cut Here"));
8611  }
8612  }
8613  else if (actionName == "DIALOG_CUTPOINT_CUTTOBEGINNING_0")
8614  {
8616  BUTTON(actionName, tr("Cut to Beginning"));
8617  }
8618  else if (actionName == "DIALOG_CUTPOINT_CUTTOEND_0")
8619  {
8622  {
8623  BUTTON(actionName, tr("Cut to End"));
8624  }
8625  }
8626  else if (actionName == "DIALOG_CUTPOINT_DELETE_0")
8627  {
8628  active = m_editorState.m_frameInDelete;
8629  BUTTON2(actionName, tr("Delete This Cut"), tr("Join Surrounding Cuts"));
8630  }
8631  else if (actionName == "DIALOG_CUTPOINT_NEWCUT_0")
8632  {
8634  BUTTON(actionName, tr("Add New Cut"));
8635  }
8636  else if (actionName == "DIALOG_CUTPOINT_UNDO_0")
8637  {
8638  active = m_editorState.m_hasUndo;
8639  //: %1 is the undo message
8640  QString text = tr("Undo - %1");
8641  result = Context.AddButton(Menu, active, actionName, text, "", false,
8643  }
8644  else if (actionName == "DIALOG_CUTPOINT_REDO_0")
8645  {
8646  active = m_editorState.m_hasRedo;
8647  //: %1 is the redo message
8648  QString text = tr("Redo - %1");
8649  result = Context.AddButton(Menu, active, actionName, text, "", false,
8651  }
8652  else if (actionName == "DIALOG_CUTPOINT_CLEARMAP_0")
8653  {
8654  BUTTON(actionName, tr("Clear Cuts"));
8655  }
8656  else if (actionName == "DIALOG_CUTPOINT_INVERTMAP_0")
8657  {
8658  BUTTON(actionName, tr("Reverse Cuts"));
8659  }
8660  else if (actionName == "DIALOG_CUTPOINT_LOADCOMMSKIP_0")
8661  {
8662  BUTTON(actionName, tr("Load Detected Commercials"));
8663  }
8664  else if (actionName == "DIALOG_CUTPOINT_REVERT_0")
8665  {
8666  BUTTON(actionName, tr("Undo Changes"));
8667  }
8668  else if (actionName == "DIALOG_CUTPOINT_REVERTEXIT_0")
8669  {
8670  BUTTON(actionName, tr("Exit Without Saving"));
8671  }
8672  else if (actionName == "DIALOG_CUTPOINT_SAVEMAP_0")
8673  {
8674  BUTTON(actionName, tr("Save Cuts"));
8675  }
8676  else if (actionName == "DIALOG_CUTPOINT_SAVEEXIT_0")
8677  {
8678  BUTTON(actionName, tr("Save Cuts and Exit"));
8679  }
8680  else
8681  {
8682  // Allow an arbitrary action if it has a translated
8683  // description available to be used as the button text.
8684  // Look in the specified keybinding context as well as the
8685  // Global context.
8686  // XXX This doesn't work well (yet) because a keybinding
8687  // action named "foo" is actually a menu action named
8688  // "DIALOG_CUTPOINT_foo_0".
8689  QString text = m_mainWindow->GetActionText(Context.m_menu.GetKeyBindingContext(), actionName);
8690  if (text.isEmpty())
8691  text = m_mainWindow->GetActionText("Global", actionName);
8692  if (!text.isEmpty())
8693  BUTTON(actionName, text);
8694  }
8695  }
8696 
8697  return result;
8698 }
8699 
8700 // Returns true if at least one item should be displayed.
8702  MythOSDDialogData *Menu)
8703 {
8704  MenuCategory category = Context.m_category;
8705  const QString &actionName = Context.m_action;
8706 
8707  bool result = false;
8708  bool active = true;
8709 
8710  if (category == kMenuCategoryMenu)
8711  {
8712  result = Context.m_menu.Show(Context.m_node, QDomNode(), *this, Menu, false);
8713  if (result && Context.m_visible)
8714  {
8715  QVariant v;
8716  v.setValue(MythTVMenuNodeTuple(Context.m_menu.m_id,
8718  Menu->m_buttons.push_back( { Context.m_menuName, v, true,
8719  Context.m_currentContext != kMenuCurrentDefault } );
8720  }
8721  return result;
8722  }
8723  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
8724  QString prefix;
8725  if (MythTVMenu::MatchesGroup(actionName, "VISUALISER_", category, prefix) &&
8727  {
8728  for (auto & visualiser : m_visualiserState.m_visualiserList)
8729  {
8730  active = m_visualiserState.m_visualiserName == visualiser;
8731  BUTTON(prefix + visualiser, visualiser);
8732  }
8733  }
8734  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLEASPECT", category, prefix))
8735  {
8736  for (int j = kAspect_Off; j < kAspect_END; j++)
8737  {
8738  // swap 14:9 and 16:9
8739  int i {j};
8740  if (kAspect_14_9 == j)
8741  i = kAspect_16_9;
8742  else if (kAspect_16_9 == j)
8743  i = kAspect_14_9;
8744  QString action = prefix + QString::number(i);
8745  active = (m_videoBoundsState.m_aspectOverrideMode == i);
8746  BUTTON(action, toString(static_cast<AspectOverrideMode>(i)));
8747  }
8748  }
8749  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLEFILL", category, prefix))
8750  {
8751  for (int i = kAdjustFill_Off; i < kAdjustFill_END; i++)
8752  {
8753  QString action = prefix + QString::number(i);
8754  active = (m_videoBoundsState.m_adjustFillMode == i);
8755  BUTTON(action, toString(static_cast<AdjustFillMode>(i)));
8756  }
8757  }
8758  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLEPICCONTROLS", category, prefix))
8759  {
8760  for (int i = kPictureAttribute_MIN; i < kPictureAttribute_MAX; i++)
8761  {
8763  {
8764  QString action = prefix + QString::number(i - kPictureAttribute_MIN);
8765  if (static_cast<PictureAttribute>(i) != kPictureAttribute_Range)
8766  BUTTON(action, toString(static_cast<PictureAttribute>(i)));
8767  }
8768  }
8769  }
8770  else if (MythTVMenu::MatchesGroup(actionName, "3D", category, prefix))
8771  {
8773  BUTTON(ACTION_3DNONE, tr("Auto"));
8775  BUTTON(ACTION_3DIGNORE, tr("Ignore"));
8777  BUTTON(ACTION_3DSIDEBYSIDEDISCARD, tr("Discard Side by Side"));
8779  BUTTON(ACTION_3DTOPANDBOTTOMDISCARD, tr("Discard Top and Bottom"));
8780  }
8781  else if (MythTVMenu::MatchesGroup(actionName, "SELECTSCAN_", category, prefix) && m_player)
8782  {
8784  active = (scan == kScan_Detect);
8785  BUTTON("SELECTSCAN_0", ScanTypeToUserString(kScan_Detect));
8786  active = (scan == kScan_Progressive);
8787  BUTTON("SELECTSCAN_3", ScanTypeToUserString(kScan_Progressive));
8788  active = (scan == kScan_Interlaced);
8789  BUTTON("SELECTSCAN_1", ScanTypeToUserString(kScan_Interlaced));
8790  active = (scan == kScan_Intr2ndField);
8792  }
8793  else if (MythTVMenu::MatchesGroup(actionName, "SELECTSUBTITLE_", category, prefix) ||
8794  MythTVMenu::MatchesGroup(actionName, "SELECTRAWTEXT_", category, prefix) ||
8795  MythTVMenu::MatchesGroup(actionName, "SELECTCC708_", category, prefix) ||
8796  MythTVMenu::MatchesGroup(actionName, "SELECTCC608_", category, prefix) ||
8797  MythTVMenu::MatchesGroup(actionName, "SELECTTTC_", category, prefix) ||
8798  MythTVMenu::MatchesGroup(actionName, "SELECTAUDIO_", category, prefix))
8799  {
8800  int i = 0;
8802  if (prefix == "SELECTSUBTITLE_")
8804  else if (prefix == "SELECTRAWTEXT_")
8806  else if (prefix == "SELECTCC708_")
8808  else if (prefix == "SELECTCC608_")
8810  else if (prefix == "SELECTTTC_")
8812  else if (prefix == "SELECTAUDIO_")
8813  {
8815  if (m_tvmTracks[type].size() <= 1)
8816  i = 1; // don't show choices if only 1 audio track
8817  }
8818 
8819  for (; i < m_tvmTracks[type].size(); i++)
8820  {
8821  QString action = prefix + QString::number(i);
8822  active = (i == m_tvmCurtrack[type]);
8823  BUTTON(action, m_tvmTracks[type][i]);
8824  }
8825  }
8826  else if (MythTVMenu::MatchesGroup(actionName, "ADJUSTSTRETCH", category, prefix))
8827  {
8828  struct speed
8829  {
8830  int m_speedX100;
8831  QString m_suffix;
8832  QString m_trans;
8833  };
8834 
8835  static const std::array<const speed,9> s_speeds {{
8836  { 0, "", tr("Adjust")},
8837  { 50, "0.5", tr("0.5x")},
8838  { 90, "0.9", tr("0.9x")},
8839  {100, "1.0", tr("1.0x")},
8840  {110, "1.1", tr("1.1x")},
8841  {120, "1.2", tr("1.2x")},
8842  {130, "1.3", tr("1.3x")},
8843  {140, "1.4", tr("1.4x")},
8844  {150, "1.5", tr("1.5x")},
8845  }};
8846 
8847  for (const auto & speed : s_speeds)
8848  {
8849  QString action = prefix + speed.m_suffix;
8850  active = (m_tvmSpeedX100 == speed.m_speedX100);
8851  BUTTON(action, speed.m_trans);
8852  }
8853  }
8854  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLESLEEP", category, prefix))
8855  {
8856  active = false;
8857  if (m_sleepTimerId)
8858  BUTTON(ACTION_TOGGLESLEEP + "ON", tr("Sleep Off"));
8859  BUTTON(ACTION_TOGGLESLEEP + "30", tr("%n minute(s)", "", 30));
8860  BUTTON(ACTION_TOGGLESLEEP + "60", tr("%n minute(s)", "", 60));
8861  BUTTON(ACTION_TOGGLESLEEP + "90", tr("%n minute(s)", "", 90));
8862  BUTTON(ACTION_TOGGLESLEEP + "120", tr("%n minute(s)", "", 120));
8863  }
8864  else if (MythTVMenu::MatchesGroup(actionName, "CHANGROUP_", category, prefix))
8865  {
8867  {
8868  active = false;
8869  BUTTON("CHANGROUP_ALL_CHANNELS", tr("All Channels"));
8870  ChannelGroupList::const_iterator it;
8871  for (it = m_dbChannelGroups.begin();
8872  it != m_dbChannelGroups.end(); ++it)
8873  {
8874  QString action = prefix + QString::number(it->m_grpId);
8875  active = (static_cast<int>(it->m_grpId) == m_channelGroupId);
8876  BUTTON(action, it->m_name);
8877  }
8878  }
8879  }
8880  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLECOMMSKIP", category, prefix))
8881  {
8883  {
8884  static constexpr std::array<const uint,3> kCasOrd { 0, 2, 1 };
8885  for (uint csm : kCasOrd)
8886  {
8887  const auto mode = static_cast<CommSkipMode>(csm);
8888  QString action = prefix + QString::number(csm);
8889  active = (mode == m_tvmCurSkip);
8890  BUTTON(action, toString(static_cast<CommSkipMode>(csm)));
8891  }
8892  }
8893  }
8894  else if (MythTVMenu::MatchesGroup(actionName, "JUMPTOCHAPTER", category, prefix))
8895  {
8896  if (m_tvmNumChapters &&
8898  {
8899  int size = QString::number(m_tvmNumChapters).size();
8900  for (int i = 0; i < m_tvmNumChapters; i++)
8901  {
8902  QString chapter1 = QString("%1").arg(i+1, size, 10, QChar(48));
8903  QString chapter2 = QString("%1").arg(i+1, 3 , 10, QChar(48));
8904  QString timestr = MythDate::formatTime(m_tvmChapterTimes[i], "HH:mm:ss");
8905  QString desc = chapter1 + QString(" (%1)").arg(timestr);
8906  QString action = prefix + chapter2;
8907  active = (m_tvmCurrentChapter == (i + 1));
8908  BUTTON(action, desc);
8909  }
8910  }
8911  }
8912  else if (MythTVMenu::MatchesGroup(actionName, "SWITCHTOANGLE", category, prefix))
8913  {
8914  if (m_tvmNumAngles > 1)
8915  {
8916  for (int i = 1; i <= m_tvmNumAngles; i++)
8917  {
8918  QString angleIdx = QString("%1").arg(i, 3, 10, QChar(48));
8919  QString desc = GetAngleName(i);
8920  QString action = prefix + angleIdx;
8921  active = (m_tvmCurrentAngle == i);
8922  BUTTON(action, desc);
8923  }
8924  }
8925  }
8926  else if (MythTVMenu::MatchesGroup(actionName, "JUMPTOTITLE", category, prefix))
8927  {
8928  for (int i = 0; i < m_tvmNumTitles; i++)
8929  {
8930  if (GetTitleDuration(i) < 2min) // Ignore < 2 minutes long
8931  continue;
8932 
8933  QString titleIdx = QString("%1").arg(i, 3, 10, QChar(48));
8934  QString desc = GetTitleName(i);
8935  QString action = prefix + titleIdx;
8936  active = (m_tvmCurrentTitle == i);
8937  BUTTON(action, desc);
8938  }
8939  }
8940  else if (MythTVMenu::MatchesGroup(actionName, "SWITCHTOINPUT_", category, prefix))
8941  {
8943  {
8944  uint inputid = m_playerContext.GetCardID();
8945  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(inputid);
8946  QVector <QString> addednames;
8947  addednames += CardUtil::GetDisplayName(inputid);
8948  for (auto & input : inputs)
8949  {
8950  if (input.m_inputId == inputid ||
8951  addednames.contains(input.m_displayName))
8952  continue;
8953  active = false;
8954  addednames += input.m_displayName;
8955  QString action = QString("SWITCHTOINPUT_") +
8956  QString::number(input.m_inputId);
8957  BUTTON(action, input.m_displayName);
8958  }
8959  }
8960  }
8961  else if (MythTVMenu::MatchesGroup(actionName, "SWITCHTOSOURCE_", category, prefix))
8962  {
8964  {
8965  uint inputid = m_playerContext.GetCardID();
8966  InfoMap info;
8968  uint sourceid = info["sourceid"].toUInt();
8969  QMap<uint, bool> sourceids;
8970  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(inputid);
8971  for (auto & input : inputs)
8972  {
8973  if (input.m_sourceId == sourceid ||
8974  sourceids[input.m_sourceId])
8975  continue;
8976  active = false;
8977  sourceids[input.m_sourceId] = true;
8978  QString action = QString("SWITCHTOINPUT_") +
8979  QString::number(input.m_inputId);
8980  BUTTON(action, SourceUtil::GetSourceName(input.m_sourceId));
8981  }
8982  }
8983  }
8984  else if (category == kMenuCategoryItem)
8985  {
8986  if (actionName == "TOGGLEAUDIOSYNC")
8987  {
8988  BUTTON(actionName, tr("Adjust Audio Sync"));
8989  }
8990  else if (m_visualiserState.m_canVisualise && (actionName == "DISABLEVISUALISATION"))
8991  {
8992  BUTTON(actionName, tr("None"));
8993  }
8994  else if (actionName == "DISABLEUPMIX")
8995  {
8997  {
8998  active = !m_audioState.m_isUpmixing;
8999  BUTTON(actionName, tr("Disable Audio Upmixer"));
9000  }
9001  }
9002  else if (actionName == "ENABLEUPMIX")
9003  {
9005  {
9006  active = m_audioState.m_isUpmixing;
9007  BUTTON(actionName, tr("Auto Detect"));
9008  }
9009  }
9010  else if (actionName == "AUTODETECT_FILL")
9011  {
9012  if (m_tvmFillAutoDetect)
9013  {
9014  active =
9017  BUTTON(actionName, tr("Auto Detect"));
9018  }
9019  }
9020  else if (actionName == "TOGGLEMANUALZOOM")
9021  {
9022  BUTTON(actionName, tr("Manual Zoom Mode"));
9023  }
9024  else if (actionName == "DISABLESUBS")
9025  {
9027  if (m_tvmSubsHaveSubs)
9028  BUTTON(actionName, tr("Disable Subtitles"));
9029  }
9030  else if (actionName == "ENABLESUBS")
9031  {
9033  if (m_tvmSubsHaveSubs)
9034  BUTTON(actionName, tr("Enable Subtitles"));
9035  }
9036  else if (actionName == "DISABLEFORCEDSUBS")
9037  {
9038  active = !m_tvmSubsForcedOn;
9039  if (!m_tvmTracks[kTrackTypeSubtitle].empty() ||
9040  !m_tvmTracks[kTrackTypeRawText].empty())
9041  {
9042  BUTTON(actionName, tr("Disable Forced Subtitles"));
9043  }
9044  }
9045  else if (actionName == "ENABLEFORCEDSUBS")
9046  {
9047  active = m_tvmSubsForcedOn;
9048  if (!m_tvmTracks[kTrackTypeSubtitle].empty() ||
9049  !m_tvmTracks[kTrackTypeRawText].empty())
9050  {
9051  BUTTON(actionName, tr("Enable Forced Subtitles"));
9052  }
9053  }
9054  else if (actionName == "DISABLEEXTTEXT")
9055  {
9058  BUTTON(actionName, tr("Disable External Subtitles"));
9059  }
9060  else if (actionName == "ENABLEEXTTEXT")
9061  {
9064  BUTTON(actionName, tr("Enable External Subtitles"));
9065  }
9066  else if (actionName == "TOGGLETTM")
9067  {
9068  if (!m_tvmTracks[kTrackTypeTeletextMenu].empty())
9069  BUTTON(actionName, tr("Toggle Teletext Menu"));
9070  }
9071  else if (actionName == "TOGGLESUBZOOM")
9072  {
9074  BUTTON(actionName, tr("Adjust Subtitle Zoom"));
9075  }
9076  else if (actionName == "TOGGLESUBDELAY")
9077  {
9081  {
9082  BUTTON(actionName, tr("Adjust Subtitle Delay"));
9083  }
9084  }
9085  else if (actionName == "PAUSE")
9086  {
9087  active = m_tvmIsPaused;
9088  BUTTON2(actionName, tr("Play"), tr("Pause"));
9089  }
9090  else if (actionName == "TOGGLESTRETCH")
9091  {
9092  BUTTON(actionName, tr("Toggle"));
9093  }
9094  else if (actionName == "TOGGLEBROWSE")
9095  {
9097  BUTTON(actionName, tr("Toggle Browse Mode"));
9098  }
9099  else if (actionName == "CANCELPLAYLIST")
9100  {
9101  if (m_inPlaylist)
9102  BUTTON(actionName, tr("Cancel Playlist"));
9103  }
9104  else if (actionName == "DEBUGOSD")
9105  {
9106  BUTTON(actionName, tr("Playback Data"));
9107  }
9108  else if (actionName == "JUMPFFWD")
9109  {
9110  if (m_tvmJump)
9111  BUTTON(actionName, tr("Jump Ahead"));
9112  }
9113  else if (actionName == "JUMPRWND")
9114  {
9115  if (m_tvmJump)
9116  BUTTON(actionName, tr("Jump Back"));
9117  }
9118  else if (actionName == "JUMPTODVDROOTMENU")
9119  {
9120  if (m_tvmIsBd || m_tvmIsDvd)
9121  {
9122  active = m_tvmIsDvd;
9123  BUTTON2(actionName, tr("DVD Root Menu"), tr("Top menu"));
9124  }
9125  }
9126  else if (actionName == "JUMPTOPOPUPMENU")
9127  {
9128  if (m_tvmIsBd)
9129  BUTTON(actionName, tr("Popup menu"));
9130  }
9131  else if (actionName == "JUMPTODVDTITLEMENU")
9132  {
9133  if (m_tvmIsDvd)
9134  BUTTON(actionName, tr("DVD Title Menu"));
9135  }
9136  else if (actionName == "JUMPTODVDCHAPTERMENU")
9137  {
9138  if (m_tvmIsDvd)
9139  BUTTON(actionName, tr("DVD Chapter Menu"));
9140  }
9141  else if (actionName == "PREVCHAN")
9142  {
9143  if (m_tvmPreviousChan)
9144  BUTTON(actionName, tr("Previous Channel"));
9145  }
9146  else if (actionName == "GUIDE")
9147  {
9148  BUTTON(actionName, tr("Program Guide"));
9149  }
9150  else if (actionName == "FINDER")
9151  {
9152  BUTTON(actionName, tr("Program Finder"));
9153  }
9154  else if (actionName == "VIEWSCHEDULED")
9155  {
9156  BUTTON(actionName, tr("Upcoming Recordings"));
9157  }
9158  else if (actionName == "SCHEDULE")
9159  {
9160  BUTTON(actionName, tr("Edit Recording Schedule"));
9161  }
9162  else if (actionName == "DIALOG_JUMPREC_X_0")
9163  {
9164  BUTTON3(actionName, tr("Recorded Program"), "", true);
9165  QVariant v;
9166  v.setValue(MythTVMenuNodeTuple(Context.m_menu.m_id,
9169  }
9170  else if (actionName == "JUMPPREV")
9171  {
9172  if (m_lastProgram != nullptr)
9173  {
9174  if (m_lastProgram->GetSubtitle().isEmpty())
9175  BUTTON(actionName, m_lastProgram->GetTitle());
9176  else
9177  {
9178  BUTTON(actionName,
9179  QString("%1: %2")
9180  .arg(m_lastProgram->GetTitle(),
9182  }
9183  }
9184  }
9185  else if (actionName == "EDIT")
9186  {
9187  if (m_tvmIsLiveTv || m_tvmIsRecorded ||
9189  {
9190  active = m_tvmIsLiveTv;
9191  BUTTON2(actionName, tr("Edit Channel"), tr("Edit Recording"));
9192  }
9193  }
9194  else if (actionName == "TOGGLEAUTOEXPIRE")
9195  {
9197  {
9198  active = m_tvmIsOn;
9199  BUTTON2(actionName,
9200  tr("Turn Auto-Expire OFF"), tr("Turn Auto-Expire ON"));
9201  }
9202  }
9203  else if (actionName == "QUEUETRANSCODE")
9204  {
9205  if (m_tvmIsRecorded)
9206  {
9207  active = m_tvmTranscoding;
9208  BUTTON2(actionName, tr("Stop Transcoding"), tr("Default"));
9209  }
9210  }
9211  else if (actionName == "QUEUETRANSCODE_AUTO")
9212  {
9213  if (m_tvmIsRecorded)
9214  {
9215  active = m_tvmTranscoding;
9216  BUTTON(actionName, tr("Autodetect"));
9217  }
9218  }
9219  else if (actionName == "QUEUETRANSCODE_HIGH")
9220  {
9221  if (m_tvmIsRecorded)
9222  {
9223  active = m_tvmTranscoding;
9224  BUTTON(actionName, tr("High Quality"));
9225  }
9226  }
9227  else if (actionName == "QUEUETRANSCODE_MEDIUM")
9228  {
9229  if (m_tvmIsRecorded)
9230  {
9231  active = m_tvmTranscoding;
9232  BUTTON(actionName, tr("Medium Quality"));
9233  }
9234  }
9235  else if (actionName == "QUEUETRANSCODE_LOW")
9236  {
9237  if (m_tvmIsRecorded)
9238  {
9239  active = m_tvmTranscoding;
9240  BUTTON(actionName, tr("Low Quality"));
9241  }
9242  }
9243  else if (actionName == ACTION_CAST)
9244  {
9245  if (!m_actors.isEmpty() || !m_guest_stars.isEmpty() ||
9246  !m_guests.isEmpty())
9247  BUTTON(actionName, tr("Cast"));
9248  }
9249  else
9250  {
9251  // Allow an arbitrary action if it has a translated
9252  // description available to be used as the button text.
9253  // Look in the specified keybinding context as well as the
9254  // Global context.
9255  QString text = m_mainWindow->GetActionText(Context.m_menu.GetKeyBindingContext(), actionName);
9256  if (text.isEmpty())
9257  text = m_mainWindow->GetActionText("Global", actionName);
9258  if (!text.isEmpty())
9259  BUTTON(actionName, text);
9260  }
9261  }
9262 
9263  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9264  return result;
9265 }
9266 
9267 void TV::MenuLazyInit(void *Field)
9268 {
9269  if (Field == &m_tvmFreeRecorderCount)
9270  if (m_tvmFreeRecorderCount < 0)
9272 }
9273 
9275 {
9277  if (&Menu != &m_playbackMenu && &Menu != &m_playbackCompactMenu)
9278  return;
9279 
9280  m_tvmAvsync = true;
9281 
9282  m_tvmFillAutoDetect = false;
9283 
9284  m_tvmSpeedX100 = std::lroundf(m_playerContext.m_tsNormal * 100);
9290  m_tvmIsPaused = false;
9295  m_tvmJump = ((m_tvmNumChapters == 0) && !m_tvmIsDvd &&
9299  m_tvmPreviousChan = false;
9300 
9307  m_tvmChapterTimes.clear();
9309 
9310  m_tvmSubsForcedOn = true;
9311  m_tvmSubsHaveSubs = false;
9312 
9313  for (int i = kTrackTypeUnknown ; i < kTrackTypeCount ; ++i)
9314  m_tvmCurtrack[i] = -1;
9315 
9316  if (m_tvmIsLiveTv)
9317  {
9318  QString prev_channum = m_playerContext.GetPreviousChannel();
9319  QString cur_channum = QString();
9321  cur_channum = m_playerContext.m_tvchain->GetChannelName(-1);
9322  if (!prev_channum.isEmpty() && prev_channum != cur_channum)
9323  m_tvmPreviousChan = true;
9324  }
9325 
9326  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9327 
9328  if (m_player && m_player->GetVideoOutput())
9329  {
9330  for (uint i = kTrackTypeUnknown ; i < kTrackTypeCount ; ++i)
9331  {
9332  m_tvmTracks[i] = m_player->GetTracks(i);
9333  if (!m_tvmTracks[i].empty())
9334  m_tvmCurtrack[i] = m_player->GetTrack(i);
9335  }
9337  !m_tvmTracks[kTrackTypeSubtitle].empty() ||
9339  !m_tvmTracks[kTrackTypeCC708].empty() ||
9340  !m_tvmTracks[kTrackTypeCC608].empty() ||
9342  !m_tvmTracks[kTrackTypeRawText].empty();
9344  !m_tvmTracks[kTrackTypeAudio].empty();
9349  if (vo)
9350  {
9352  }
9353  }
9354  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
9359  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
9360 
9361  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9362 }
9363 
9364 void TV::PlaybackMenuDeinit(const MythTVMenu& /*Menu*/)
9365 {
9366  ReturnPlayerLock();
9367 }
9368 
9369 void TV::PlaybackMenuShow(const MythTVMenu &Menu, const QDomNode &Node, const QDomNode &Selected)
9370 {
9371  PlaybackMenuInit(Menu);
9372  bool isPlayback = (&Menu == &m_playbackMenu || &Menu == &m_playbackCompactMenu);
9373  bool isCutlist = (&Menu == &m_cutlistMenu || &Menu == &m_cutlistCompactMenu);
9374  QString text = Menu.Translate(Node.toElement().attribute("text", Menu.GetName()));
9375  const char* windowtitle { "???" };
9376  if (isPlayback)
9377  windowtitle = OSD_DLG_MENU;
9378  else if (isCutlist)
9379  windowtitle = OSD_DLG_CUTPOINT;
9380  MythOSDDialogData menu {windowtitle, text };
9381  Menu.Show(Node, Selected, *this, &menu);
9382  QDomNode parent = Node.parentNode();
9383  if (!parent.parentNode().isNull())
9384  {
9385  QVariant v;
9386  v.setValue(MythTVMenuNodeTuple(Menu.m_id, MythTVMenu::GetPathFromNode(Node)));
9387  menu.m_back = { "", v };
9388  }
9389 
9390  emit ChangeOSDDialog(menu);
9391 
9392  if (isCutlist)
9393  {
9394  // hack to unhide the editbar
9395  InfoMap map;
9396  map.insert("title", tr("Edit"));
9398  }
9399  PlaybackMenuDeinit(Menu);
9400 }
9401 
9403 {
9404  // Playback menu
9405  (void)tr("Playback Menu");
9406  (void)tr("Playback Compact Menu");
9407  (void)tr("Audio");
9408  (void)tr("Select Audio Track");
9409  (void)tr("Visualisation");
9410  (void)tr("Video");
9411  (void)tr("Change Aspect Ratio");
9412  (void)tr("Adjust Fill");
9413  (void)tr("Adjust Picture");
9414  (void)tr("3D");
9415  (void)tr("Advanced");
9416  (void)tr("Video Scan");
9417  (void)tr("Deinterlacer");
9418  (void)tr("Subtitles");
9419  (void)tr("Select Subtitle");
9420  (void)tr("Text Subtitles");
9421  (void)tr("Select ATSC CC");
9422  (void)tr("Select VBI CC");
9423  (void)tr("Select Teletext CC");
9424  (void)tr("Playback");
9425  (void)tr("Adjust Time Stretch");
9426  (void)tr("Picture-in-Picture");
9427  (void)tr("Sleep");
9428  (void)tr("Channel Groups");
9429  (void)tr("Navigate");
9430  (void)tr("Commercial Auto-Skip");
9431  (void)tr("Chapter");
9432  (void)tr("Angle");
9433  (void)tr("Title");
9434  (void)tr("Schedule");
9435  (void)tr("Source");
9436  (void)tr("Jump to Program");
9437  (void)tr("Switch Input");
9438  (void)tr("Switch Source");
9439  (void)tr("Jobs");
9440  (void)tr("Begin Transcoding");
9441  (void)tr("Cast");
9442  (void)tr("Recorded");
9443  (void)tr("Upcoming");
9444 
9445  // Cutlist editor menu
9446  (void)tr("Edit Cut Points");
9447  (void)tr("Edit Cut Points (Compact)");
9448  (void)tr("Cut List Options");
9449 }
9450 
9451 void TV::ShowOSDMenu(bool isCompact)
9452 {
9453  if (!m_playbackMenu.IsLoaded())
9454  {
9456  "menu_playback.xml", tr("Playback Menu"),
9457  metaObject()->className(), "TV Playback");
9459  "menu_playback_compact.xml", tr("Playback Compact Menu"),
9460  metaObject()->className(), "TV Playback");
9461  }
9462 
9463  if (isCompact && m_playbackCompactMenu.IsLoaded())
9465  else if (m_playbackMenu.IsLoaded())
9467 }
9468 
9469 void TV::FillOSDMenuJumpRec(const QString &Category, int Level, const QString &Selected)
9470 {
9471  // bool in_recgroup = !category.isEmpty() && level > 0;
9472  if (Level < 0 || Level > 1)
9473  {
9474  Level = 0;
9475  // in_recgroup = false;
9476  }
9477 
9478  MythOSDDialogData dialog { "osd_jumprec", tr("Recorded Program") };
9479 
9480  QMutexLocker locker(&m_progListsLock);
9481  m_progLists.clear();
9482  std::vector<ProgramInfo*> *infoList = RemoteGetRecordedList(0);
9483  bool LiveTVInAllPrograms = gCoreContext->GetBoolSetting("LiveTVInAllPrograms",false);
9484  if (infoList)
9485  {
9486  QList<QString> titles_seen;
9487 
9488  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
9489  QString currecgroup = m_playerContext.m_playingInfo->GetRecordingGroup();
9490  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
9491 
9492  for (auto *pi : *infoList)
9493  {
9494  if (pi->GetRecordingGroup() != "LiveTV" || LiveTVInAllPrograms ||
9495  pi->GetRecordingGroup() == currecgroup)
9496  {
9497  m_progLists[pi->GetRecordingGroup()].push_front(
9498  new ProgramInfo(*pi));
9499  }
9500  }
9501 
9502  ProgramInfo *lastprog = GetLastProgram();
9503  QMap<QString,ProgramList>::const_iterator Iprog;
9504  for (Iprog = m_progLists.cbegin(); Iprog != m_progLists.cend(); ++Iprog)
9505  {
9506  const ProgramList &plist = *Iprog;
9507  auto progIndex = static_cast<uint>(plist.size());
9508  const QString& group = Iprog.key();
9509 
9510  if (plist[0] && (plist[0]->GetRecordingGroup() != currecgroup))
9511  SetLastProgram(plist[0]);
9512 
9513  if (progIndex == 1 && Level == 0)
9514  {
9515  dialog.m_buttons.push_back( {Iprog.key(), QString("JUMPPROG %1 0").arg(group) });
9516  }
9517  else if (progIndex > 1 && Level == 0)
9518  {
9519  QString act = QString("DIALOG_%1_%2_1")
9520  .arg(ACTION_JUMPREC, group);
9521  dialog.m_buttons.push_back( {group, act, true, Selected == group });
9522  }
9523  else if (Level == 1 && Iprog.key() == Category)
9524  {
9525  for (auto pit = plist.begin(); pit != plist.end(); ++pit)
9526  {
9527  const ProgramInfo *p = *pit;
9528 
9529  if (titles_seen.contains(p->GetTitle()))
9530  continue;
9531 
9532  titles_seen.push_back(p->GetTitle());
9533 
9534  int j = -1;
9535  for (auto *q : plist)
9536  {
9537  j++;
9538 
9539  if (q->GetTitle() != p->GetTitle())
9540  continue;
9541 
9542  dialog.m_buttons.push_back( { q->GetSubtitle().isEmpty() ?
9543  q->GetTitle() : q->GetSubtitle(),
9544  QString("JUMPPROG %1 %2").arg(Iprog.key()).arg(j) });
9545  }
9546  }
9547  }
9548  }
9549  SetLastProgram(lastprog);
9550  delete lastprog;
9551 
9552  while (!infoList->empty())
9553  {
9554  delete infoList->back();
9555  infoList->pop_back();
9556  }
9557  delete infoList;
9558  }
9559 
9560  if (!Category.isEmpty())
9561  {
9562  if (Level == 1)
9563  dialog.m_back = { Category, "DIALOG_" + ACTION_JUMPREC + "_X_0" };
9564  else if (Level == 0)
9565  {
9566  if (m_tvmJumprecBackHack.isValid())
9567  dialog.m_back = { "", m_tvmJumprecBackHack };
9568  else
9569  dialog.m_back = { ACTION_JUMPREC, "DIALOG_MENU_" + ACTION_JUMPREC +"_0" };
9570  }
9571  }
9572 
9573  emit ChangeOSDDialog(dialog);
9574 }
9575 
9577 {
9578  bool recorded = (ProgInfo.GetFilesize() > 0);
9579  QString table = recorded ? "recordedcredits" : "credits";
9580 
9581  m_actors.clear();
9582  m_guest_stars.clear();
9583  m_guests.clear();
9584 
9585  MSqlQuery query(MSqlQuery::InitCon());
9586  query.prepare(QString("SELECT role, people.name,"
9587  " roles.name, people.person FROM %1"
9588  " AS credits"
9589  " LEFT JOIN people ON"
9590  " credits.person = people.person"
9591  " LEFT JOIN roles ON"
9592  " credits.roleid = roles.roleid"
9593  " WHERE credits.chanid = :CHANID"
9594  " AND credits.starttime = :STARTTIME"
9595  " AND role IN ('guest','actor','guest_star')"
9596  " ORDER BY role, priority;").arg(table));
9597 
9598  query.bindValue(":CHANID", ProgInfo.GetChanID());
9599  query.bindValue(":STARTTIME", ProgInfo.GetScheduledStartTime());
9600 
9601  if (query.exec() && query.size() > 0)
9602  {
9603  QStringList plist;
9604  QString role;
9605  QString pname;
9606  QString character;
9607 
9608  while(query.next())
9609  {
9610  role = query.value(0).toString();
9611  /* The people.name, roles.name columns uses utf8_bin collation.
9612  * Qt-MySQL drivers use QVariant::ByteArray for string-type
9613  * MySQL fields marked with the BINARY attribute (those using a
9614  * *_bin collation) and QVariant::String for all others.
9615  * Since QVariant::toString() uses QString::fromAscii()
9616  * (through QVariant::convert()) when the QVariant's type is
9617  * QVariant::ByteArray, we have to use QString::fromUtf8()
9618  * explicitly to prevent corrupting characters.
9619  * The following code should be changed to use the simpler
9620  * toString() approach, as above, if we do a DB update to
9621  * coalesce the people.name values that differ only in case and
9622  * change the collation to utf8_general_ci, to match the
9623  * majority of other columns, or we'll have the same problem in
9624  * reverse.
9625  */
9626  int pid = query.value(3).toInt();
9627  pname = QString::fromUtf8(query.value(1)
9628  .toByteArray().constData()) +
9629  "|" + QString::number(pid);
9630  character = QString::fromUtf8(query.value(2)
9631  .toByteArray().constData());
9632 
9633  if (role == "actor")
9634  m_actors.append(qMakePair(pname, character));
9635  else if (role == "guest_star")
9636  m_guest_stars.append(qMakePair(pname, character));
9637  else if (role == "guest")
9638  m_guests.append(qMakePair(pname, character));
9639  }
9640  }
9641 
9642 }
9643 
9645  const QVector<string_pair> & people)
9646 {
9647  for (const auto & [actor, role] : std::as_const(people))
9648  {
9649  if (role.isEmpty())
9650  {
9651  dialog.m_buttons.push_back( {actor.split('|')[0],
9652  QString("JUMPCAST|%1").arg(actor), true} );
9653  }
9654  else
9655  {
9656  dialog.m_buttons.push_back( {QString("%1 as %2")
9657  .arg(actor.split('|')[0], role),
9658  QString("JUMPCAST|%1").arg(actor), true} );
9659  }
9660  }
9661 }
9662 
9664 {
9665  MythOSDDialogData dialog { "osd_cast", tr("Cast") };
9666  const ProgramInfo pginfo(*m_playerContext.m_playingInfo);
9667 
9671 
9672  emit ChangeOSDDialog(dialog);
9673 }
9674 
9675 void TV::FillOSDMenuActorShows(const QString & actor, int person_id,
9676  const QString & category)
9677 {
9678  MythOSDDialogData dialog { actor, actor };
9679 
9680  if (category.isEmpty())
9681  {
9682  dialog.m_buttons.push_back( {"Recorded",
9683  QString("JUMPCAST|%1|%2|Recorded").arg(actor).arg(person_id) } );
9684  dialog.m_buttons.push_back( {"Upcoming",
9685  QString("JUMPCAST|%1|%2|Upcoming").arg(actor).arg(person_id) } );
9686  emit ChangeOSDDialog(dialog);
9687  return;
9688  }
9689 
9690  if (category == "Upcoming")
9691  {
9693  return;
9694  }
9695 
9696  /*
9697  JUMPCAST|Amanda Burton|133897|Recorded
9698  JUMPCAST|Amanda Burton|133897|Upcoming
9699  */
9700  if (!m_progLists.contains(actor))
9701  {
9702  QString table = "recordedcredits";
9703  MSqlQuery query(MSqlQuery::InitCon());
9704  query.prepare(QString("SELECT chanid, starttime from %1"
9705  " where person = :PERSON"
9706  " ORDER BY starttime;").arg(table));
9707  query.bindValue(":PERSON", person_id);
9708 
9709  QDateTime starttime;
9710  if (query.exec() && query.size() > 0)
9711  {
9712  while(query.next())
9713  {
9714  int chanid = query.value(0).toInt();
9715  starttime = MythDate::fromString(query.value(1).toString());
9716  auto *pi = new ProgramInfo(chanid, starttime.toUTC());
9717  if (!pi->GetTitle().isEmpty() &&
9718  pi->GetRecordingGroup() != "LiveTV" &&
9719  pi->GetRecordingGroup() != "Deleted")
9720  m_progLists[actor].push_back(pi);
9721  }
9722 
9723  std::stable_sort(m_progLists[actor].begin(),
9724  m_progLists[actor].end(), comp_title);
9725  }
9726  }
9727 
9728  QString show;
9729  int idx = -1;
9730  for (auto & pi : m_progLists[actor])
9731  {
9732  show = pi->GetTitle();
9733  if (show.isEmpty())
9734  continue;
9735  if (!pi->GetSubtitle().isEmpty())
9736  {
9737  show += QString(" %1x%2 %3").arg(pi->GetSeason())
9738  .arg(pi->GetEpisode())
9739  .arg(pi->GetSubtitle());
9740  }
9741 
9742  dialog.m_buttons.push_back( {show,
9743  QString("JUMPPROG %1 %2").arg(actor).arg(++idx) });
9744  }
9745  emit ChangeOSDDialog(dialog);
9746 }
9747 
9749 {
9750  QString message;
9751  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9752  if (m_player)
9753  {
9754  m_player->SetScanOverride(Scan);
9755  message = ScanTypeToUserString(Scan == kScan_Detect ? kScan_Detect :
9757  }
9758  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9759 
9760  if (!message.isEmpty())
9761  emit ChangeOSDMessage(message);
9762 }
9763 
9765 {
9766  QString desc;
9767 
9768  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
9769 
9771  {
9773  desc = tr("Auto-Expire OFF");
9774  }
9775  else
9776  {
9778  desc = tr("Auto-Expire ON");
9779  }
9780 
9781  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
9782 
9783  if (!desc.isEmpty())
9785 }
9786 
9788 {
9789  QString desc;
9790 
9791  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9792  if (m_player)
9793  {
9794  m_player->SetAutoCommercialSkip(SkipMode);
9796  }
9797  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9798 
9799  if (!desc.isEmpty())
9801 }
9802 
9803 void TV::SetManualZoom(bool ZoomON, const QString& Desc)
9804 {
9805  m_zoomMode = ZoomON;
9806  if (ZoomON)
9807  ClearOSD();
9808  if (!Desc.isEmpty())
9810 }
9811 
9812 bool TV::HandleJumpToProgramAction(const QStringList &Actions)
9813 {
9814  TVState state = GetState();
9815  if (IsActionable({ ACTION_JUMPPREV, "PREVCHAN" }, Actions) &&
9816  !StateIsLiveTV(state))
9817  {
9818  PrepareToExitPlayer(__LINE__);
9819  m_jumpToProgram = true;
9820  SetExitPlayer(true, true);
9821  return true;
9822  }
9823 
9824  for (const auto& action : std::as_const(Actions))
9825  {
9826  if (!action.startsWith("JUMPPROG"))
9827  continue;
9828 
9829  bool ok = false;
9830  QString key = action.section(" ",1,-2);
9831  uint index = action.section(" ",-1,-1).toUInt(&ok);
9832  ProgramInfo* proginfo = nullptr;
9833 
9834  if (ok)
9835  {
9836  QMutexLocker locker(&m_progListsLock);
9837  auto pit = m_progLists.find(key);
9838  if (pit != m_progLists.end())
9839  {
9840  const ProgramInfo* tmp = (*pit)[index];
9841  if (tmp)
9842  proginfo = new ProgramInfo(*tmp);
9843  }
9844  }
9845 
9846  if (!proginfo)
9847  {
9848  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to locate jump to program '%1' @ %2")
9849  .arg(key, action.section(" ",-1,-1)));
9850  return true;
9851  }
9852 
9853  PrepToSwitchToRecordedProgram(*proginfo);
9854 
9855  delete proginfo;
9856  return true;
9857  }
9858 
9859  if (!IsActionable(ACTION_JUMPREC, Actions))
9860  return false;
9861 
9862  if (m_dbJumpPreferOsd && (StateIsPlaying(state) || StateIsLiveTV(state)))
9863  {
9864  // TODO I'm not sure this really needs to be asyncronous
9865  auto Jump = [&]()
9866  {
9869  ReturnPlayerLock();
9870  };
9871  QTimer::singleShot(0, this, Jump);
9872  }
9873  else if (RunPlaybackBoxPtr)
9874  {
9876  }
9877  else
9878  {
9879  LOG(VB_GENERAL, LOG_ERR, "Failed to open jump to program GUI");
9880  }
9881 
9882  return true;
9883 }
9884 
9885 void TV::ToggleSleepTimer(const QString& Time)
9886 {
9887  std::chrono::minutes mins { 0min };
9888 
9889  if (Time == ACTION_TOGGLESLEEP + "ON")
9890  {
9891  if (m_sleepTimerId)
9892  {
9894  m_sleepTimerId = 0;
9895  }
9896  else
9897  {
9898  m_sleepTimerTimeout = mins = 60min;
9900  }
9901  }
9902  else
9903  {
9904  if (m_sleepTimerId)
9905  {
9907  m_sleepTimerId = 0;
9908  }
9909 
9910  if (Time.length() > 11)
9911  {
9912  bool intRead = false;
9913  mins = std::chrono::minutes(Time.right(Time.length() - 11).toUInt(&intRead));
9914 
9915  if (intRead)
9916  {
9917  // catch 120 -> 240 mins
9918  if (mins < 30min)
9919  {
9920  mins *= 10;
9921  }
9922  }
9923  else
9924  {
9925  mins = 0min;
9926  LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid time " + Time);
9927  }
9928  }
9929  else
9930  {
9931  LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid time string " + Time);
9932  }
9933 
9934  if (mins > 0min)
9935  {
9936  m_sleepTimerTimeout = mins;
9938  }
9939  }
9940 
9941  QString out;
9942  if (mins != 0min)
9943  out = tr("Sleep") + " " + QString::number(mins.count());
9944  else
9945  out = tr("Sleep") + " " + s_sleepTimes[0].dispString;
9946  emit ChangeOSDMessage(out);
9947 }
9948 
9950 {
9951  QString errorText;
9952 
9953  switch (MsgType)
9954  {
9955  case kNoRecorders:
9956  errorText = tr("MythTV is already using all available "
9957  "inputs for the channel you selected. "
9958  "If you want to watch an in-progress recording, "
9959  "select one from the playback menu. If you "
9960  "want to watch Live TV, cancel one of the "
9961  "in-progress recordings from the delete "
9962  "menu.");
9963  break;
9964  case kNoCurrRec:
9965  errorText = tr("Error: MythTV is using all inputs, "
9966  "but there are no active recordings?");
9967  break;
9968  case kNoTuners:
9969  errorText = tr("MythTV has no capture cards defined. "
9970  "Please run the mythtv-setup program.");
9971  break;
9972  }
9973 
9974  emit ChangeOSDDialog({ OSD_DLG_INFO, errorText, 0ms, {{ tr("OK"), "DIALOG_INFO_X_X" }}});
9975 }
9976 
9981 {
9982  m_lockTimerOn = false;
9983 
9984  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9986  {
9991  }
9992  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9993 
9994  // XXX: Get rid of this?
9996 
9999 
10000  m_lockTimerOn = false;
10001 
10002  QString input = m_playerContext.m_recorder->GetInput();
10004 
10005  if (timeout < 0xffffffff)
10006  {
10007  m_lockTimer.start();
10008  m_lockTimerOn = true;
10009  }
10010 
10011  SetSpeedChangeTimer(0ms, __LINE__);
10012 }
10013 
10017 void TV::UnpauseLiveTV(bool Quietly)
10018 {
10020  {
10022  m_playerContext.m_tvchain->JumpTo(-1, 1s);
10023  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10024  if (m_player)
10025  m_player->Play(m_playerContext.m_tsNormal, true, false);
10026  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10029  SetSpeedChangeTimer(0ms, __LINE__);
10030  }
10031 
10032  ITVRestart(true);
10033 
10034  if (m_playerContext.HasPlayer() && !Quietly)
10035  {
10037  UpdateLCD();
10039  }
10040 }
10041 
10045 void TV::ITVRestart(bool IsLive)
10046 {
10047  int chanid = -1;
10048  int sourceid = -1;
10049 
10050  if (ContextIsPaused(__FILE__, __LINE__))
10051  return;
10052 
10053  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10055  {
10056  chanid = static_cast<int>(m_playerContext.m_playingInfo->GetChanID());
10057  sourceid = static_cast<int>(ChannelUtil::GetSourceIDForChannel(static_cast<uint>(chanid)));
10058  }
10059  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10060 
10061  emit RestartITV(static_cast<uint>(chanid), static_cast<uint>(sourceid), IsLive);
10062 }
10063 
10065 {
10066  if (GetState() == kState_WatchingDVD)
10067  DVDJumpForward();
10068  else if (GetNumChapters() > 0)
10069  DoJumpChapter(9999);
10070  else
10071  DoSeek(m_playerContext.m_jumptime, tr("Jump Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
10072 }
10073 
10075 {
10076  DoSeek(m_playerContext.m_fftime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
10077 }
10078 
10080 {
10081  if (GetState() == kState_WatchingDVD)
10082  DVDJumpBack();
10083  else if (GetNumChapters() > 0)
10084  DoJumpChapter(-1);
10085  else
10086  DoSeek(-m_playerContext.m_jumptime, tr("Jump Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
10087 }
10088 
10090 {
10091  DoSeek(-m_playerContext.m_rewtime, tr("Jump Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
10092 }
10093 
10094 /* \fn TV::DVDJumpBack(PlayerContext*)
10095  \brief jump to the previous dvd title or chapter
10096 */
10098 {
10099  auto *dvd = dynamic_cast<MythDVDBuffer*>(m_playerContext.m_buffer);
10100  if (!m_playerContext.HasPlayer() || !dvd)
10101  return;
10102 
10104  {
10105  UpdateOSDSeekMessage(tr("Skip Back Not Allowed"), kOSDTimeout_Med);
10106  }
10107  else if (!dvd->StartOfTitle())
10108  {
10109  DoJumpChapter(-1);
10110  }
10111  else
10112  {
10113  std::chrono::seconds titleLength = dvd->GetTotalTimeOfTitle();
10114  std::chrono::seconds chapterLength = dvd->GetChapterLength();
10115  if ((titleLength == chapterLength) && chapterLength > 5min)
10116  {
10117  DoSeek(-m_playerContext.m_jumptime, tr("Jump Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
10118  }
10119  else
10120  {
10121  emit GoToDVDProgram(false);
10122  UpdateOSDSeekMessage(tr("Previous Title"), kOSDTimeout_Med);
10123  }
10124  }
10125 }
10126 
10127 /* \fn TV::DVDJumpForward(PlayerContext*)
10128  * \brief jump to the next dvd title or chapter
10129  */
10131 {
10132  auto *dvd = dynamic_cast<MythDVDBuffer*>(m_playerContext.m_buffer);
10133  if (!m_playerContext.HasPlayer() || !dvd)
10134  return;
10135 
10136  bool in_still = dvd->IsInStillFrame();
10137  bool in_menu = dvd->IsInMenu();
10138  if (in_still && !dvd->NumMenuButtons())
10139  {
10140  dvd->SkipStillFrame();
10141  UpdateOSDSeekMessage(tr("Skip Still Frame"), kOSDTimeout_Med);
10142  }
10143  else if (!dvd->EndOfTitle() && !in_still && !in_menu)
10144  {
10145  DoJumpChapter(9999);
10146  }
10147  else if (!in_still && !in_menu)
10148  {
10149  std::chrono::seconds titleLength = dvd->GetTotalTimeOfTitle();
10150  std::chrono::seconds chapterLength = dvd->GetChapterLength();
10151  std::chrono::seconds currentTime = dvd->GetCurrentTime();
10152  if ((titleLength == chapterLength) && (chapterLength > 5min) &&
10153  (currentTime < (chapterLength - (duration_cast<std::chrono::seconds>(m_playerContext.m_jumptime)))))
10154  {
10155  DoSeek(m_playerContext.m_jumptime, tr("Jump Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
10156  }
10157  else
10158  {
10159  emit GoToDVDProgram(true);
10160  UpdateOSDSeekMessage(tr("Next Title"), kOSDTimeout_Med);
10161  }
10162  }
10163 }
10164 
10165 /* \fn TV::IsBookmarkAllowed(const PlayerContext*) const
10166  * \brief Returns true if bookmarks are allowed for the current player.
10167  */
10169 {
10170  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10171 
10172  // Allow bookmark of "Record current LiveTV program"
10175  {
10176  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10177  return false;
10178  }
10179 
10181  {
10182  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10183  return false;
10184  }
10185 
10186  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10187 
10189 }
10190 
10191 /* \fn TV::IsDeleteAllowed() const
10192  * \brief Returns true if the delete menu option should be offered.
10193  */
10195 {
10196  bool allowed = false;
10197 
10198  if (!StateIsLiveTV(GetState()))
10199  {
10200  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10202  allowed = curProgram && curProgram->QueryIsDeleteCandidate(true);
10203  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10204  }
10205 
10206  return allowed;
10207 }
10208 
10210 {
10211  ClearOSD();
10212 
10213  if (!ContextIsPaused(__FILE__, __LINE__))
10214  DoTogglePause(false);
10215 
10216  QString videotype;
10217 
10218  if (StateIsLiveTV(GetState()))
10219  videotype = tr("Live TV");
10221  videotype = tr("this DVD");
10222 
10223  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10224  if (videotype.isEmpty() && m_playerContext.m_playingInfo->IsVideo())
10225  videotype = tr("this Video");
10226  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10227 
10228  if (videotype.isEmpty())
10229  videotype = tr("this recording");
10230 
10231  MythOSDDialogData dialog { OSD_DLG_VIDEOEXIT, tr("You are exiting %1").arg(videotype) };
10232 
10233  dialog.m_buttons.push_back({tr("Exit %1").arg(videotype), ACTION_STOP});
10234 
10235  dialog.m_buttons.push_back({tr("Exit Without Saving"), "DIALOG_VIDEOEXIT_CLEARLASTPLAYEDPOSITION_0"});
10236 
10237  if (IsDeleteAllowed())
10238  dialog.m_buttons.push_back({tr("Delete this recording"), "DIALOG_VIDEOEXIT_CONFIRMDELETE_0"});
10239 
10240  dialog.m_buttons.push_back({tr("Keep watching"), "DIALOG_VIDEOEXIT_KEEPWATCHING_0"});
10241  dialog.m_back = { "", "DIALOG_VIDEOEXIT_KEEPWATCHING_0", true };
10242  emit ChangeOSDDialog(dialog);
10243 
10244  if (m_videoExitDialogTimerId)
10245  KillTimer(m_videoExitDialogTimerId);
10246  m_videoExitDialogTimerId = StartTimer(kVideoExitDialogTimeout, __LINE__);
10247 }
10248 
10249 void TV::ShowOSDPromptDeleteRecording(const QString& Title, bool Force)
10250 {
10251  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10252 
10254  {
10255  // this should only occur when the cat walks on the keyboard.
10256  LOG(VB_GENERAL, LOG_ERR, "It is unsafe to delete at the moment");
10257  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10258  return;
10259  }
10260 
10261  bool paused = ContextIsPaused(__FILE__, __LINE__);
10263  {
10264  LOG(VB_GENERAL, LOG_ERR, "This program cannot be deleted at this time.");
10266  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10267 
10268  OSD *osd = GetOSDL();
10269  if (osd && !osd->DialogVisible())
10270  {
10271  QString message = tr("Cannot delete program ") + QString("%1 ").arg(pginfo.GetTitle());
10272 
10273  if (!pginfo.GetSubtitle().isEmpty())
10274  message += QString("\"%1\" ").arg(pginfo.GetSubtitle());
10275 
10276  if (!pginfo.IsRecording())
10277  {
10278  message += tr("because it is not a recording.");
10279  }
10280  else
10281  {
10282  message += tr("because it is in use by");
10283  QStringList byWho;
10284  pginfo.QueryIsInUse(byWho);
10285  for (int i = 0; (i + 2) < byWho.size(); i += 3)
10286  {
10287  if (byWho[i + 1] == gCoreContext->GetHostName() && byWho[i].contains(kPlayerInUseID))
10288  continue;
10289  if (byWho[i].contains(kRecorderInUseID))
10290  continue;
10291  message += " " + byWho[i+2];
10292  }
10293  }
10294  emit ChangeOSDDialog({OSD_DLG_DELETE, message, 0ms,
10295  {{ tr("OK"), "DIALOG_DELETE_OK_0" }},
10296  { "", "DIALOG_DELETE_OK_0", true }});
10297  }
10298  ReturnOSDLock();
10299  // If the delete prompt is to be displayed at the end of a
10300  // recording that ends in a final cut region, it will get into
10301  // a loop of popping up the OK button while the cut region
10302  // plays. Avoid this.
10303  if (m_player->IsNearEnd() && !paused)
10304  SetExitPlayer(true, true);
10305 
10306  return;
10307  }
10308  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10309 
10310  ClearOSD();
10311 
10312  if (!paused)
10313  DoTogglePause(false);
10314 
10315  InfoMap infoMap;
10317  if (m_player)
10318  m_player->GetCodecDescription(infoMap);
10319  QString message = QString("%1\n%2\n%3")
10320  .arg(Title, infoMap["title"], infoMap["timedate"]);
10321 
10322  OSD *osd = GetOSDL();
10323  if (osd && (!osd->DialogVisible() || Force))
10324  {
10325  MythOSDDialogData dialog { OSD_DLG_VIDEOEXIT, message };
10326  if (Title == "End Of Recording")
10327  {
10328  dialog.m_buttons.push_back({tr("Delete it, but allow it to re-record"), "DIALOG_VIDEOEXIT_DELETEANDRERECORD_0"});
10329  dialog.m_buttons.push_back({tr("Delete it"), "DIALOG_VIDEOEXIT_JUSTDELETE_0"});
10330  dialog.m_buttons.push_back({tr("Save it so I can watch it again"), ACTION_STOP, false, true});
10331  }
10332  else
10333  {
10334  dialog.m_buttons.push_back({tr("Yes, and allow re-record"), "DIALOG_VIDEOEXIT_DELETEANDRERECORD_0"});
10335  dialog.m_buttons.push_back({tr("Yes, delete it"), "DIALOG_VIDEOEXIT_JUSTDELETE_0"});
10336  dialog.m_buttons.push_back({tr("No, keep it"), ACTION_STOP, false, true});
10337  if (!paused)
10338  dialog.m_back = { "", "DIALOG_PLAY_0_0", true };
10339  }
10340 
10341  emit ChangeOSDDialog(dialog);
10342 
10346  }
10347  ReturnOSDLock();
10348 }
10349 
10350 bool TV::HandleOSDVideoExit(const QString& Action)
10351 {
10353  return false;
10354 
10355  bool hide = true;
10356  bool delete_ok = IsDeleteAllowed();
10357 
10358  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10359  bool near_end = m_player && m_player->IsNearEnd();
10360  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10361 
10362  if (Action == "DELETEANDRERECORD" && delete_ok)
10363  {
10364  m_allowRerecord = true;
10365  m_requestDelete = true;
10366  PrepareToExitPlayer(__LINE__);
10367  SetExitPlayer(true, true);
10368  }
10369  else if (Action == "JUSTDELETE" && delete_ok)
10370  {
10371  m_requestDelete = true;
10372  PrepareToExitPlayer(__LINE__);
10373  SetExitPlayer(true, true);
10374  }
10375  else if (Action == "CONFIRMDELETE")
10376  {
10377  hide = false;
10378  ShowOSDPromptDeleteRecording(tr("Are you sure you want to delete:"), true);
10379  }
10380  else if (Action == "KEEPWATCHING" && !near_end)
10381  {
10382  DoTogglePause(true);
10383  }
10384  else if (Action == "CLEARLASTPLAYEDPOSITION")
10385  {
10386  m_clearPosOnExit = true;
10387  PrepareToExitPlayer(__LINE__);
10388  SetExitPlayer(true, true);
10389  }
10390 
10391  return hide;
10392 }
10393 
10395 {
10397  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10398  bool playing = m_player && !m_player->IsPaused();
10399  // Don't bother saving lastplaypos while paused
10400  if (playing)
10401  {
10402  uint64_t framesPlayed = m_player->GetFramesPlayed();
10403  auto *savPosThread = new SavePositionThread(m_playerContext.m_playingInfo,
10404  framesPlayed);
10405  GetPosThreadPool()->start(savPosThread, "PositionSaver");
10406  }
10407  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10408  ReturnPlayerLock();
10409 
10410  m_savePosOnExit = true;
10411 }
10412 
10414 {
10415  QMutexLocker locker(&m_lastProgramLock);
10416 
10417  delete m_lastProgram;
10418 
10419  if (ProgInfo)
10421  else
10422  m_lastProgram = nullptr;
10423 }
10424 
10426 {
10427  QMutexLocker locker(&m_lastProgramLock);
10428  if (m_lastProgram)
10429  return new ProgramInfo(*m_lastProgram);
10430  return nullptr;
10431 }
10432 
10433 QString TV::GetRecordingGroup() const
10434 {
10435  QString ret;
10436 
10438  if (StateIsPlaying(GetState()))
10439  {
10440  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10443  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10444  }
10445  ReturnPlayerLock();
10446  return ret;
10447 }
10448 
10450 {
10451  if (!ProgInfo)
10452  return false;
10453 
10454  bool ret = false;
10457  ReturnPlayerLock();
10458  return ret;
10459 }
10460 
10461 bool TV::ContextIsPaused(const char *File, int Location)
10462 {
10463  bool paused = false;
10464  m_playerContext.LockDeletePlayer(File, Location);
10465  if (m_player)
10466  paused = m_player->IsPaused();
10467  m_playerContext.UnlockDeletePlayer(File, Location);
10468  return paused;
10469 }
10470 
10472 {
10473  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10474  if (m_player)
10475  {
10476  m_player->LockOSD();
10477  OSD *osd = m_player->GetOSD();
10478  if (!osd)
10479  {
10480  m_player->UnlockOSD();
10481  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10482  }
10483  return osd;
10484  }
10485  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10486  return nullptr;
10487 }
10488 
10489 void TV::ReturnOSDLock() const
10490 {
10491  if (m_player)
10492  m_player->UnlockOSD();
10493  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10494 }
10495 
10497 {
10498  m_playerLock.lockForWrite();
10499 }
10500 
10502 {
10503  m_playerLock.lockForRead();
10504 }
10505 
10507 {
10508  m_playerLock.unlock();
10509 }
10510 
10511 void TV::onApplicationStateChange(Qt::ApplicationState State)
10512 {
10513  switch (State)
10514  {
10515  case Qt::ApplicationState::ApplicationSuspended:
10516  {
10517  LOG(VB_GENERAL, LOG_NOTICE, "Exiting playback on app suspecnd");
10518  StopPlayback();
10519  break;
10520  }
10521  default:
10522  break;
10523  }
10524 }
10525 
10527 {
10528  return m_posThreadPool;
10529 }
10530 
10532 {
10533  if (m_progInfo)
10534  {
10535  try
10536  {
10538  }
10539  catch (...)
10540  {
10541  LOG(VB_GENERAL, LOG_ERR, "An exception occurred");
10542  }
10543  }
10544 }
TVPlaybackState::ChangePictureAttribute
void ChangePictureAttribute(PictureAttribute Attribute, bool Direction, int Value)
SignalMonitorValue::Parse
static SignalMonitorList Parse(const QStringList &slist)
Converts a list of strings to SignalMonitorValue classes.
Definition: signalmonitorvalue.cpp:149
TV::HandleStateChange
void HandleStateChange()
Changes the state to the state on the front of the state change queue.
Definition: tv_play.cpp:1984
ACTION_PLAY
#define ACTION_PLAY
Definition: tv_actions.h:30
TvPlayWindow::Create
bool Create(void) override
Definition: tv_play_win.cpp:21
TV::onApplicationStateChange
void onApplicationStateChange(Qt::ApplicationState State)
Definition: tv_play.cpp:10511
toCommaList
static QString toCommaList(const QVector< uint > &list)
Definition: tv_play.cpp:6787
MythPlayer::IsNearEnd
bool IsNearEnd(void)
Returns true iff near end of recording.
Definition: mythplayer.cpp:1538
kZoomAspectDown
@ kZoomAspectDown
Definition: videoouttypes.h:56
TV::kEndOfPlaybackCheckFrequency
static const std::chrono::milliseconds kEndOfPlaybackCheckFrequency
Definition: tv_play.h:763
TV::m_tvmCurrentTitle
int m_tvmCurrentTitle
Definition: tv_play.h:733
ACTION_TOGGLETT
#define ACTION_TOGGLETT
Definition: tv_actions.h:100
MythCoreContext::emitTVPlaybackUnpaused
void emitTVPlaybackUnpaused(void)
Definition: mythcorecontext.h:275
IsActionable
bool IsActionable(const QString &Action, const QStringList &Actions)
Definition: mythtvactionutils.h:8
ProgramInfo::GetSortTitle
QString GetSortTitle(void) const
Definition: programinfo.h:363
OSD_DLG_MENU
static constexpr const char * OSD_DLG_MENU
Definition: osd.h:17
MythMediaBuffer::BD
const MythBDBuffer * BD(void) const
Definition: mythmediabuffer.cpp:1855
MythPlayer::SetLength
void SetLength(std::chrono::seconds len)
Definition: mythplayer.h:116
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:215
kState_WatchingBD
@ kState_WatchingBD
Watching BD is the state when we are watching a BD.
Definition: tv.h:78
ProgramInfo::QueryIsDeleteCandidate
bool QueryIsDeleteCandidate(bool one_playback_allowed=false) const
Returns true iff this is a recording, it is not in use (except by the recorder), and at most one play...
Definition: programinfo.cpp:3283
TV::m_actors
QVector< string_pair > m_actors
Definition: tv_play.h:576
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
TV::PrepToSwitchToRecordedProgram
void PrepToSwitchToRecordedProgram(const ProgramInfo &ProgInfo)
Definition: tv_play.cpp:2760
TV::InitKeys
static void InitKeys()
Definition: tv_play.cpp:494
TV::StartPlayer
bool StartPlayer(TVState desiredState)
Definition: tv_play.cpp:4771
PlayerContext::IsRecorderErrored
bool IsRecorderErrored(void) const
Definition: playercontext.cpp:146
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
kViewSchedule
@ kViewSchedule
Definition: tv_play.h:98
MythUIStateTracker::SetState
static void SetState(const QVariantMap &NewState)
Definition: mythuistatetracker.cpp:26
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:317
TV::SetAutoCommercialSkip
void SetAutoCommercialSkip(CommSkipMode SkipMode=kCommSkipOff)
Definition: tv_play.cpp:9787
TVPlaybackState::RequestEmbedding
void RequestEmbedding(bool Embed, const QRect &Rect={}, const QStringList &Data={})
TV::m_requestDelete
bool m_requestDelete
User wants last video deleted.
Definition: tv_play.h:558
TV::m_endOfPlaybackTimerId
volatile int m_endOfPlaybackTimerId
Definition: tv_play.h:688
PlayerContext::IsErrored
bool IsErrored(void) const
This is set if the player encountered some irrecoverable error.
Definition: playercontext.h:107
CardUtil::IsTunerShared
static bool IsTunerShared(uint inputidA, uint inputidB)
Definition: cardutil.cpp:242
OSD::DialogGetText
void DialogGetText(InfoMap &Map)
Definition: osd.cpp:836
MythTimer::elapsed
std::chrono::milliseconds elapsed(void)
Returns milliseconds elapsed since last start() or restart()
Definition: mythtimer.cpp:91
kZoomVerticalIn
@ kZoomVerticalIn
Definition: videoouttypes.h:47
PlayerContext::m_lastSignalUIInfo
InfoMap m_lastSignalUIInfo
Definition: playercontext.h:157
kTrackTypeCC708
@ kTrackTypeCC708
Definition: decoderbase.h:33
ACTION_SETCONTRAST
#define ACTION_SETCONTRAST
Definition: tv_actions.h:60
TV::~TV
~TV() override
Definition: tv_play.cpp:1227
TV::GetPlayerWriteLock
void GetPlayerWriteLock() const
Definition: tv_play.cpp:10496
TV::StartOsdNavigation
void StartOsdNavigation()
Definition: tv_play.cpp:7997
TV::kSaveLastPlayPosTimeout
static const std::chrono::milliseconds kSaveLastPlayPosTimeout
Definition: tv_play.h:768
TV::m_lastProgramLock
QMutex m_lastProgramLock
Definition: tv_play.h:630
kTrackTypeUnknown
@ kTrackTypeUnknown
Definition: decoderbase.h:28
ProgramInfo::MakeUniqueKey
QString MakeUniqueKey(void) const
Creates a unique string that can be used to identify an existing recording.
Definition: programinfo.h:340
OSD::DialogVisible
bool DialogVisible(const QString &Window=QString())
Definition: osd.cpp:699
TV::IsSameProgram
bool IsSameProgram(const ProgramInfo *ProgInfo) const
Definition: tv_play.cpp:10449
RemoteEncoder::SetSignalMonitoringRate
std::chrono::milliseconds SetSignalMonitoringRate(std::chrono::milliseconds rate, int notifyFrontend=1)
Sets the signal monitoring rate.
Definition: remoteencoder.cpp:493
TV::SeekHandleAction
bool SeekHandleAction(const QStringList &Actions, bool IsDVD)
Definition: tv_play.cpp:5002
ACTION_DISABLEUPMIX
#define ACTION_DISABLEUPMIX
Definition: tv_actions.h:109
MythEditorState::m_hasRedo
bool m_hasRedo
Definition: mythplayerstate.h:162
PlayerContext::GetState
TVState GetState(void) const
Definition: playercontext.cpp:331
ACTION_ZOOMOUT
#define ACTION_ZOOMOUT
Definition: tv_actions.h:138
MythGestureEvent::Click
@ Click
Definition: mythgesture.h:77
RemoteEncoder::SetChannelInfo
bool SetChannelInfo(const InfoMap &infoMap)
Definition: remoteencoder.cpp:744
MythCoreContext::SendMessage
void SendMessage(const QString &message)
Definition: mythcorecontext.cpp:1545
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
MSqlQuery::size
int size(void) const
Definition: mythdbcon.h:214
TV::StateIsPlaying
static bool StateIsPlaying(TVState State)
Definition: tv_play.cpp:1947
MEDIASTAT_OPEN
@ MEDIASTAT_OPEN
CD/DVD tray open (meaningless for non-CDs?)
Definition: mythmedia.h:16
TV::GetState
TVState GetState() const
Definition: tv_play.cpp:1366
TV::m_doSmartForward
bool m_doSmartForward
Definition: tv_play.h:560
TVPlaybackState::RefreshEditorState
void RefreshEditorState(bool CheckSaved=false)
OSD_WIN_BROWSE
static constexpr const char * OSD_WIN_BROWSE
Definition: osd.h:34
MThread::start
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
Definition: mthread.cpp:283
ACTION_VIEWSCHEDULED
#define ACTION_VIEWSCHEDULED
Definition: tv_actions.h:31
TVPlaybackState::EnableEdit
void EnableEdit()
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:101
ACTION_TOGGLESUBTITLEDELAY
#define ACTION_TOGGLESUBTITLEDELAY
Definition: tv_actions.h:74
ACTION_DOWN
static constexpr const char * ACTION_DOWN
Definition: mythuiactions.h:17
ACTION_SIGNALMON
#define ACTION_SIGNALMON
Definition: tv_actions.h:33
TV::HandleSaveLastPlayPosEvent
void HandleSaveLastPlayPosEvent()
Definition: tv_play.cpp:10394
TVBrowseHelper::BrowseEnd
void BrowseEnd(bool ChangeChannel)
Ends channel browsing.
Definition: tvbrowsehelper.cpp:115
ProgramInfo::SaveEditing
void SaveEditing(bool edit)
Sets "editing" field in "recorded" table to "edit".
Definition: programinfo.cpp:3150
TV::HandleJumpToProgramAction
bool HandleJumpToProgramAction(const QStringList &Actions)
Definition: tv_play.cpp:9812
MythDisplay::GetScreenBounds
QRect GetScreenBounds()
Definition: mythdisplay.cpp:317
MythEvent::kMythUserMessage
static const Type kMythUserMessage
Definition: mythevent.h:80
InputInfo::m_chanId
uint m_chanId
chanid restriction if applicable
Definition: inputinfo.h:51
TV::IdleDialogTimeout
void IdleDialogTimeout()
Definition: tv_play.cpp:7240
RemoteGetExistingRecorder
RemoteEncoder * RemoteGetExistingRecorder(const ProgramInfo *pginfo)
Definition: tvremoteutil.cpp:313
LCD::switchToChannel
void switchToChannel(const QString &channum="", const QString &title="", const QString &subtitle="")
Definition: lcddevice.cpp:577
kState_None
@ kState_None
None State, this is the initial state in both TV and TVRec, it indicates that we are ready to change ...
Definition: tv.h:61
MythPlayer::TranslatePositionAbsToRel
uint64_t TranslatePositionAbsToRel(uint64_t position) const
Definition: mythplayer.h:266
CardUtil::GetDisplayName
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1876
TV::IsTunablePriv
bool IsTunablePriv(uint ChanId)
Definition: tv_play.cpp:6782
osdInfo
Definition: playercontext.h:34
MythPlayer::GetVideoOutput
MythVideoOutput * GetVideoOutput(void)
Definition: mythplayer.h:164
REG_KEY
static void REG_KEY(const QString &Context, const QString &Action, const QString &Description, const QString &Key)
Definition: mythmainwindow.h:175
PlayerContext::UnlockPlayingInfo
void UnlockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:249
mythbdplayer.h
PlayerContext::IsPlayerChangingBuffers
bool IsPlayerChangingBuffers(void) const
Definition: playercontext.h:100
MythEvent::kMythEventMessage
static const Type kMythEventMessage
Definition: mythevent.h:79
ACTION_JUMPRWND
#define ACTION_JUMPRWND
Definition: tv_actions.h:45
TV::ProcessNetworkControlCommand
void ProcessNetworkControlCommand(const QString &Command)
Definition: tv_play.cpp:4301
TV::m_playerLock
QReadWriteLock m_playerLock
lock on player and playerActive changes
Definition: tv_play.h:644
RemoteEncoder::GetRecorderNumber
int GetRecorderNumber(void) const
Definition: remoteencoder.cpp:62
ScanTypeToUserString
QString ScanTypeToUserString(FrameScanType Scan, bool Forced=false)
Definition: videoouttypes.h:198
TV::m_smartForward
bool m_smartForward
Definition: tv_play.h:540
PlayerContext::kSMExitTimeout
static constexpr std::chrono::milliseconds kSMExitTimeout
Timeout after last Signal Monitor message for ignoring OSD when exiting.
Definition: playercontext.h:164
MythVideoOutput
Definition: mythvideoout.h:35
TV::ITVRestart
void ITVRestart(bool IsLive)
Restart the MHEG/MHP engine.
Definition: tv_play.cpp:10045
BrowseInfo::m_chanNum
QString m_chanNum
Definition: tvbrowsehelper.h:38
PlayerContext::m_ffRewIndex
int m_ffRewIndex
Index into m_ffRewSpeeds for FF and Rewind speeds.
Definition: playercontext.h:124
MythEvent::kUpdateBrowseInfoEventType
static const Type kUpdateBrowseInfoEventType
Definition: mythevent.h:88
PlayerContext::m_lastSignalMsg
QStringList m_lastSignalMsg
Definition: playercontext.h:155
ACTION_ZOOMHORIZONTALIN
#define ACTION_ZOOMHORIZONTALIN
Definition: tv_actions.h:141
PictureAttribute
PictureAttribute
Definition: videoouttypes.h:103
TV::m_subtitleZoomAdjustment
bool m_subtitleZoomAdjustment
True if subtitle zoom is turned on.
Definition: tv_play.h:553
TV::StopFFRew
float StopFFRew()
Definition: tv_play.cpp:5237
MythBDBuffer::IsHDMVNavigation
bool IsHDMVNavigation(void) const
Definition: mythbdbuffer.cpp:1219
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:124
ShowNotificationError
void ShowNotificationError(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
convenience utility to display error message as notification
Definition: mythnotificationcenter.cpp:1426
ACTION_PLAYBACK
#define ACTION_PLAYBACK
Definition: tv_actions.h:7
TVPlaybackState::ChangeOSDDialog
void ChangeOSDDialog(const MythOSDDialogData &Data)
ProgramInfo::GetHostname
QString GetHostname(void) const
Definition: programinfo.h:422
mythplayerui.h
TV::ShowOSDMenu
void ShowOSDMenu(bool isCompact=false)
Definition: tv_play.cpp:9451
TV::SetExitPlayer
void SetExitPlayer(bool SetIt, bool WantsTo)
Definition: tv_play.cpp:2809
ACTION_3DIGNORE
#define ACTION_3DIGNORE
Definition: tv_actions.h:126
TVPlaybackState::m_overlayState
MythOverlayState m_overlayState
Definition: tvplaybackstate.h:104
TV::m_tvmIsRecorded
bool m_tvmIsRecorded
Definition: tv_play.h:715
RecordingInfo::kFoundProgram
@ kFoundProgram
Definition: recordinginfo.h:182
kTrackTypeSubtitle
@ kTrackTypeSubtitle
Definition: decoderbase.h:31
ACTION_PAGERIGHT
#define ACTION_PAGERIGHT
Definition: tv_actions.h:12
TV::ShowNoRecorderDialog
void ShowNoRecorderDialog(NoRecorderMsg MsgType=kNoRecorders)
Definition: tv_play.cpp:9949
kZoomLeft
@ kZoomLeft
Definition: videoouttypes.h:53
TV::m_lcdVolumeTimerId
volatile int m_lcdVolumeTimerId
Definition: tv_play.h:683
TV::MenuLazyInit
void MenuLazyInit(void *Field)
Definition: tv_play.cpp:9267
TV::TranslateKeyPressOrGesture
bool TranslateKeyPressOrGesture(const QString &Context, QEvent *Event, QStringList &Actions, bool IsLiveTV, bool AllowJumps=true)
Definition: tv_play.cpp:3290
ACTION_TOGGLESUBS
#define ACTION_TOGGLESUBS
Definition: tv_actions.h:67
mythdb.h
PlayerContext::SetPseudoLiveTV
void SetPseudoLiveTV(const ProgramInfo *pi, PseudoState new_state)
Definition: playercontext.cpp:546
MythTVMenuNodeTuple
Definition: mythtvmenu.h:121
TV::DoJumpRWND
void DoJumpRWND()
Definition: tv_play.cpp:10079
TV::DoPlay
void DoPlay()
Definition: tv_play.cpp:4794
TV::m_ffRewSpeeds
std::vector< int > m_ffRewSpeeds
Definition: tv_play.h:543
SourceUtil::GetSourceName
static QString GetSourceName(uint sourceid)
Definition: sourceutil.cpp:47
kMenuIdPlaybackCompact
@ kMenuIdPlaybackCompact
Definition: mythtvmenu.h:40
TV::GetRecordingGroup
QString GetRecordingGroup() const
Definition: tv_play.cpp:10433
MythEditorState::m_totalFrames
uint64_t m_totalFrames
Definition: mythplayerstate.h:156
TV::ConvertScreenPressKeyMap
static QList< QKeyEvent * > ConvertScreenPressKeyMap(const QString &KeyList)
Definition: tv_play.cpp:3225
TVPlaybackState::UpdateBookmark
void UpdateBookmark(bool Clear=false)
ACTION_TEXTEXIT
#define ACTION_TEXTEXIT
Definition: tv_actions.h:81
JobQueue::QueueJob
static bool QueueJob(int jobType, uint chanid, const QDateTime &recstartts, const QString &args="", const QString &comment="", QString host="", int flags=0, int status=JOB_QUEUED, QDateTime schedruntime=QDateTime())
Definition: jobqueue.cpp:508
TV::StopPlayback
void StopPlayback()
Definition: tv_play.cpp:268
kScheduleProgramFinder
@ kScheduleProgramFinder
Definition: tv_play.h:96
MenuTypeId
MenuTypeId
Definition: mythtvmenu.h:36
TV::GetLastProgram
ProgramInfo * GetLastProgram() const
Definition: tv_play.cpp:10425
PlayerContext::SetPlayingInfo
void SetPlayingInfo(const ProgramInfo *info)
assign programinfo to the context
Definition: playercontext.cpp:513
TV::m_tvmIsDvd
bool m_tvmIsDvd
Definition: tv_play.h:720
MythTimer
A QElapsedTimer based timer to replace use of QTime as a timer.
Definition: mythtimer.h:13
LiveTVChain::HasNext
bool HasNext(void) const
Definition: livetvchain.cpp:406
TV::UnpauseLiveTV
void UnpauseLiveTV(bool Quietly=false)
Used in ChangeChannel() to restart video output.
Definition: tv_play.cpp:10017
TV::DoTogglePauseFinish
void DoTogglePauseFinish(float Time, bool ShowOSD)
Definition: tv_play.cpp:4857
OSD_DLG_CUTPOINT
static constexpr const char * OSD_DLG_CUTPOINT
Definition: osd.h:24
ACTION_BOTTOMLINEMOVE
#define ACTION_BOTTOMLINEMOVE
Definition: tv_actions.h:145
TV::ScheduleInputChange
void ScheduleInputChange()
Definition: tv_play.cpp:2736
ACTION_SCREENSHOT
static constexpr const char * ACTION_SCREENSHOT
Definition: mythuiactions.h:22
to_track_type
int to_track_type(const QString &str)
Definition: decoderbase.cpp:1205
RemoteEncoder::ToggleChannelFavorite
void ToggleChannelFavorite(const QString &changroupname)
Definition: remoteencoder.cpp:442
TVPlaybackState::ChangeAspectOverride
void ChangeAspectOverride(AspectOverrideMode AspectMode=kAspect_Toggle)
TV::UpdateOSDProgInfo
void UpdateOSDProgInfo(const char *WhichInfo)
Update and display the passed OSD set with programinfo.
Definition: tv_play.cpp:6385
TV::m_wantsToQuit
bool m_wantsToQuit
True if the user told MythTV to stop playback.
Definition: tv_play.h:550
kRecorderInUseID
const QString kRecorderInUseID
Definition: programtypes.cpp:20
GetZoomString
QString GetZoomString(float HorizScale, float VertScale, QPoint Move)
Definition: videoouttypes.h:359
MythVisualiserState::m_embedding
bool m_embedding
Definition: mythplayerstate.h:136
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:389
JobQueue::ChangeJobCmds
static bool ChangeJobCmds(int jobID, int newCmds)
Definition: jobqueue.cpp:919
TVPlaybackState::HandleTeletextAction
void HandleTeletextAction(const QString &Action, bool &Handled)
TV::HandleTrackAction
bool HandleTrackAction(const QString &Action)
Definition: tv_play.cpp:3104
TV::m_tvmFillAutoDetect
bool m_tvmFillAutoDetect
Definition: tv_play.h:709
TV::SetErrored
void SetErrored()
Definition: tv_play.cpp:2753
TV::m_cutlistMenu
MythTVMenu m_cutlistMenu
Definition: tv_play.h:746
MythOpticalBuffer::IsInMenu
bool IsInMenu(void) const override
Definition: mythopticalbuffer.cpp:9
PlayerContext::IsPlayerPlaying
bool IsPlayerPlaying(void) const
Definition: playercontext.cpp:114
SavePositionThread::m_progInfo
ProgramInfo * m_progInfo
Definition: tv_play.h:788
MythPlayer::GetNumAngles
virtual int GetNumAngles(void) const
Definition: mythplayer.h:224
TV::HandleOSDAlreadyEditing
void HandleOSDAlreadyEditing(const QString &Action, bool WasPaused)
Definition: tv_play.cpp:7931
TV::m_keyRepeatTimer
MythTimer m_keyRepeatTimer
Queue of unprocessed key presses.
Definition: tv_play.h:594
SET_NEXT
#define SET_NEXT()
Definition: tv_play.cpp:1964
kPictureAttribute_Colour
@ kPictureAttribute_Colour
Definition: videoouttypes.h:109
OSD::IsWindowVisible
bool IsWindowVisible(const QString &Window)
Definition: osd.cpp:628
TV::DialogIsVisible
bool DialogIsVisible(const QString &Dialog)
Definition: tv_play.cpp:8529
PlayerContext::m_tsNormal
float m_tsNormal
Time stretch speed, 1.0F for normal playback.
Definition: playercontext.h:147
MythDVDBuffer::IsInStillFrame
bool IsInStillFrame(void) const override
Definition: mythdvdbuffer.cpp:225
TV::m_tvmFreeRecorderCount
int m_tvmFreeRecorderCount
Definition: tv_play.h:719
progress
bool progress
Definition: mythcommflag.cpp:59
MythMediaBuffer::StopReads
void StopReads(void)
Definition: mythmediabuffer.cpp:669
ProgramInfo::SaveTotalFrames
void SaveTotalFrames(int64_t frames)
Store the Total Frames at frame 0 in the recordedmarkup table.
Definition: programinfo.cpp:4432
AdjustFillMode
AdjustFillMode
Definition: videoouttypes.h:71
ChannelChangeDirection
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.
Definition: tv.h:31
TV::m_initialChanID
uint m_initialChanID
Initial chanid override for Live TV.
Definition: tv_play.h:612
MythPlayerCaptionsUI::GetTrack
int GetTrack(uint Type)
Definition: mythplayercaptionsui.cpp:371
TVPlaybackState::ChangeOSDText
void ChangeOSDText(const QString &Window, const InfoMap &Map, OSDTimeout Timeout)
TV::m_underNetworkControl
bool m_underNetworkControl
initial show started via by the network control interface
Definition: tv_play.h:633
TV::StartChannelEditMode
void StartChannelEditMode()
Starts channel editing mode.
Definition: tv_play.cpp:7968
TV::m_dbUseVideoModes
bool m_dbUseVideoModes
Definition: tv_play.h:531
MythCoreContext::emitTVPlaybackStopped
void emitTVPlaybackStopped(void)
Definition: mythcorecontext.h:271
MythOverlayState::m_browsing
bool m_browsing
Definition: mythplayerstate.h:25
BrowseInfo::m_chanId
uint m_chanId
Definition: tvbrowsehelper.h:39
MythDVDBuffer::GetPartAndTitle
void GetPartAndTitle(int &Part, int &Title) const
Definition: mythdvdbuffer.cpp:464
TV::m_sleepTimerTimeout
std::chrono::milliseconds m_sleepTimerTimeout
Current sleep timeout in msec.
Definition: tv_play.h:586
ACTION_FINDER
#define ACTION_FINDER
Definition: tv_actions.h:27
ACTION_ZOOMVERTICALIN
#define ACTION_ZOOMVERTICALIN
Definition: tv_actions.h:139
ACTION_LISTRECORDEDEPISODES
#define ACTION_LISTRECORDEDEPISODES
Definition: tv_actions.h:24
CardUtil::SetStartChannel
static bool SetStartChannel(uint inputid, const QString &channum)
Definition: cardutil.cpp:1680
MythTVMenuItemContext
Definition: mythtvmenu.h:49
OSD::DialogHandleGesture
bool DialogHandleGesture(MythGestureEvent *Event)
Definition: osd.cpp:713
RecordingInfo
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:35
TV::HandleOSDVideoExit
bool HandleOSDVideoExit(const QString &Action)
Definition: tv_play.cpp:10350
TV::m_dbAutoexpireDefault
uint m_dbAutoexpireDefault
Definition: tv_play.h:526
kScan_Progressive
@ kScan_Progressive
Definition: videoouttypes.h:100
TV::m_idleTimerId
int m_idleTimerId
Timer for turning off playback after idle period.
Definition: tv_play.h:590
mythscreenstack.h
TV::SleepTimerInfo::dispString
QString dispString
Definition: tv_play.cpp:984
TV::OSDDialogEvent
void OSDDialogEvent(int Result, const QString &Text, QString Action)
Definition: tv_play.cpp:8095
RemoteEncoder::FrontendReady
void FrontendReady(void)
Definition: remoteencoder.cpp:329
MythPlayerUI::GetCodecDescription
void GetCodecDescription(InfoMap &Map)
Definition: mythplayerui.cpp:854
MarkTypes
MarkTypes
Definition: programtypes.h:46
PlayerContext::m_playingState
TVState m_playingState
Definition: playercontext.h:127
TV::m_ccInputTimerId
volatile int m_ccInputTimerId
Definition: tv_play.h:685
kPictureAttributeSupported_Volume
@ kPictureAttributeSupported_Volume
Definition: videoouttypes.h:124
TV::m_savedPause
bool m_savedPause
saved pause state before embedding
Definition: tv_play.h:668
MythAudioState::m_muteState
MuteState m_muteState
Definition: mythplayerstate.h:56
MythCoreContext::emitTVPlaybackPlaying
void emitTVPlaybackPlaying(void)
Definition: mythcorecontext.h:277
TV::ArbSeekWhence
ArbSeekWhence
Definition: tv_play.h:372
ACTION_TOGGLECHANCONTROLS
#define ACTION_TOGGLECHANCONTROLS
Definition: tv_actions.h:21
TV::ShowOSDSleep
void ShowOSDSleep()
Definition: tv_play.cpp:7146
ACTION_TOGGELAUDIOSYNC
#define ACTION_TOGGELAUDIOSYNC
Definition: tv_actions.h:113
LiveTVChain::GetChannelName
QString GetChannelName(int pos=-1) const
Definition: livetvchain.cpp:682
TVPlaybackState::ChangeOSDMessage
void ChangeOSDMessage(const QString &Message)
ProgramInfo::GetRecordingID
uint GetRecordingID(void) const
Definition: programinfo.h:450
TVBrowseHelper::m_browseTimerId
int m_browseTimerId
Definition: tvbrowsehelper.h:65
TV::ShowPreviousChannel
void ShowPreviousChannel()
Definition: tv_play.cpp:6263
kPictureAttribute_None
@ kPictureAttribute_None
Definition: videoouttypes.h:105
PlayerContext::UpdateTVChain
void UpdateTVChain(const QStringList &data=QStringList())
Definition: playercontext.cpp:157
TVPlaybackState::EnableVisualiser
void EnableVisualiser(bool Enable, bool Toggle=false, const QString &Name=QString())
LiveTVChain::GetID
QString GetID(void) const
Definition: livetvchain.h:54
MythPlayer::IsPaused
bool IsPaused(void) const
Definition: mythplayer.h:151
TV::RequestNextRecorder
bool RequestNextRecorder(bool ShowDialogs, const ChannelInfoList &Selection=ChannelInfoList())
Definition: tv_play.cpp:1559
TV::UpdateOSDSeekMessage
void UpdateOSDSeekMessage(const QString &Msg, enum OSDTimeout Timeout)
Definition: tv_play.cpp:6425
ProgramInfo::GetChanNum
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:377
TVPlaybackState::SaveBottomLine
void SaveBottomLine()
TV::StateIsRecording
static bool StateIsRecording(TVState State)
Definition: tv_play.cpp:1942
TV::StartRecorder
bool StartRecorder(std::chrono::milliseconds MaxWait=-1ms)
Starts recorder, must be called before StartPlayer().
Definition: tv_play.cpp:2334
TV::GetEndOfRecording
bool GetEndOfRecording() const
This is set to true if the player reaches the end of the recording without the user explicitly exitin...
Definition: tv_play.h:317
MythEvent
This class is used as a container for messages.
Definition: mythevent.h:16
RemoteEncoder::CancelNextRecording
void CancelNextRecording(bool cancel)
Definition: remoteencoder.cpp:320
MythTVMenuItemContext::m_visible
bool m_visible
Definition: mythtvmenu.h:73
ACTION_JUMPSTART
#define ACTION_JUMPSTART
Definition: tv_actions.h:47
ACTION_ENABLEUPMIX
#define ACTION_ENABLEUPMIX
Definition: tv_actions.h:108
MythAudioState::m_volume
uint m_volume
Definition: mythplayerstate.h:55
TV::m_tvmIsRecording
bool m_tvmIsRecording
Definition: tv_play.h:714
MythMediaBuffer::kLiveTVOpenTimeout
static constexpr std::chrono::milliseconds kLiveTVOpenTimeout
Definition: mythmediabuffer.h:72
TV::RetrieveCast
void RetrieveCast(const ProgramInfo &ProgInfo)
Definition: tv_play.cpp:9576
TV::SleepDialogTimeout
void SleepDialogTimeout()
Definition: tv_play.cpp:7183
kPseudoChangeChannel
@ kPseudoChangeChannel
Definition: playercontext.h:43
ACTION_TOGGLERECORD
#define ACTION_TOGGLERECORD
Definition: tv_actions.h:19
mythdvdbuffer.h
RemoteGetFreeRecorderCount
int RemoteGetFreeRecorderCount(void)
Definition: tvremoteutil.cpp:169
kOSDTimeout_Med
@ kOSDTimeout_Med
Definition: osd.h:60
PlayerContext::TeardownPlayer
void TeardownPlayer(void)
Definition: playercontext.cpp:40
PlayerContext::GetPlayingInfoMap
bool GetPlayingInfoMap(InfoMap &infoMap) const
Definition: playercontext.cpp:337
BUTTON3
#define BUTTON3(action, textActive, textInactive, isMenu)
Definition: tv_play.cpp:8553
MythVideoScanTracker::NextScanOverride
FrameScanType NextScanOverride()
Definition: mythvideoscantracker.cpp:45
MythPlayer::GetNumTitles
virtual int GetNumTitles(void) const
Definition: mythplayer.h:218
TV::InitFromDB
void InitFromDB()
Definition: tv_play.cpp:1037
TV::m_screenPressKeyMapPlayback
QList< QKeyEvent * > m_screenPressKeyMapPlayback
Definition: tv_play.h:620
kDisplayCC708
@ kDisplayCC708
Definition: videoouttypes.h:17
TV::customEvent
void customEvent(QEvent *Event) override
This handles all custom events.
Definition: tv_play.cpp:7275
MythPlayerOverlayUI::LockOSD
void LockOSD()
Definition: mythplayeroverlayui.h:25
TV::m_errorRecoveryTimerId
volatile int m_errorRecoveryTimerId
Definition: tv_play.h:693
OSD::ResetWindow
void ResetWindow(const QString &Window)
Definition: osd.cpp:636
MythVisualiserState::m_visualiserList
QStringList m_visualiserList
Definition: mythplayerstate.h:139
OSD_DLG_SLEEP
static constexpr const char * OSD_DLG_SLEEP
Definition: osd.h:18
mythdialogbox.h
MythPlayer::GetAngleName
virtual QString GetAngleName(int) const
Definition: mythplayer.h:226
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
MythScreenStack
Definition: mythscreenstack.h:16
TV::DoTogglePause
void DoTogglePause(bool ShowOSD)
Definition: tv_play.cpp:4914
MythMainWindow::RestoreScreensaver
static void RestoreScreensaver()
Definition: mythmainwindow.cpp:576
TV::ShowOSDAlreadyEditing
void ShowOSDAlreadyEditing()
Definition: tv_play.cpp:7917
ProgramInfo::GetChannelSchedulingID
QString GetChannelSchedulingID(void) const
This is the unique programming identifier of a channel.
Definition: programinfo.h:384
ACTION_LEFT
static constexpr const char * ACTION_LEFT
Definition: mythuiactions.h:18
TV::HasQueuedChannel
bool HasQueuedChannel() const
Definition: tv_play.h:340
MythTimer::isRunning
bool isRunning(void) const
Returns true if start() or restart() has been called at least once since construction and since any c...
Definition: mythtimer.cpp:135
TV::m_clearPosOnExit
bool m_clearPosOnExit
False unless requested by user on playback exit.
Definition: tv_play.h:563
frm_dir_map_t
QMap< uint64_t, MarkTypes > frm_dir_map_t
Frame # -> Mark map.
Definition: programtypes.h:117
VBIMode::NTSC_CC
@ NTSC_CC
Definition: tv.h:14
ACTION_VOLUMEUP
#define ACTION_VOLUMEUP
Definition: tv_actions.h:110
OSD_DLG_CONFIRM
static constexpr const char * OSD_DLG_CONFIRM
Definition: osd.h:27
TV::GetChapterTimes
void GetChapterTimes(QList< std::chrono::seconds > &Times)
Definition: tv_play.cpp:5399
TV::m_tvmTracks
QStringList m_tvmTracks[kTrackTypeCount]
Definition: tv_play.h:702
MythNotification
Definition: mythnotification.h:29
MythDate::formatTime
QString formatTime(std::chrono::milliseconds msecs, QString fmt)
Format a milliseconds time value.
Definition: mythdate.cpp:242
TVPlaybackState::ResetTeletext
void ResetTeletext()
RecordingRule
Internal representation of a recording rule, mirrors the record table.
Definition: recordingrule.h:29
EMBEDRETURNVOID
void(*)(void *, bool) EMBEDRETURNVOID
Definition: tv_play.h:59
TV::m_tvmSpeedX100
int m_tvmSpeedX100
Definition: tv_play.h:712
MythCoreContext::emitTVPlaybackStarted
void emitTVPlaybackStarted(void)
Definition: mythcorecontext.h:270
OSD_DLG_INFO
static constexpr const char * OSD_DLG_INFO
Definition: osd.h:20
TV::TimeStretchHandleAction
bool TimeStretchHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3691
signalmonitorvalue.h
TV::ToggleHandleAction
bool ToggleHandleAction(const QStringList &Actions, bool IsDVD)
Definition: tv_play.cpp:4106
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
TV::FFRewHandleAction
bool FFRewHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:4069
ProgramInfo::ExtractKey
static bool ExtractKey(const QString &uniquekey, uint &chanid, QDateTime &recstartts)
Extracts chanid and recstartts from a unique key generated by MakeUniqueKey().
Definition: programinfo.cpp:1186
PlayerContext::GetPlayMessage
QString GetPlayMessage(void) const
Definition: playercontext.cpp:423
BROWSE_UP
@ BROWSE_UP
Fetch information on previous channel.
Definition: tv.h:44
MythMediaDevice::getDevicePath
const QString & getDevicePath() const
Definition: mythmedia.h:61
MythTVMenuItemContext::m_currentContext
MenuCurrentContext m_currentContext
Definition: mythtvmenu.h:70
TV::GetAngleName
QString GetAngleName(int Angle)
Definition: tv_play.cpp:5472
MythMediaEvent::kEventType
static const Type kEventType
Definition: mythmedia.h:193
MythMediaDevice::getStatus
MythMediaStatus getStatus() const
Definition: mythmedia.h:70
kMenuIdCutlistCompact
@ kMenuIdCutlistCompact
Definition: mythtvmenu.h:42
MythMainWindow::Show
void Show()
Definition: mythmainwindow.cpp:965
TV::ChangeChannel
void ChangeChannel(const ChannelInfoList &Options)
Definition: tv_play.cpp:6242
kAspect_END
@ kAspect_END
Definition: videoouttypes.h:68
ACTION_TOGGLEPGORDER
#define ACTION_TOGGLEPGORDER
Definition: tv_actions.h:13
MythMediaBuffer
Definition: mythmediabuffer.h:59
ACTION_PREVRECORDED
#define ACTION_PREVRECORDED
Definition: tv_actions.h:32
MythMediaBuffer::IgnoreWaitStates
virtual void IgnoreWaitStates(bool)
Definition: mythmediabuffer.h:139
CHANNEL_DIRECTION_FAVORITE
@ CHANNEL_DIRECTION_FAVORITE
Definition: tv.h:35
TVPlaybackState::ChangeZoom
void ChangeZoom(ZoomDirection Zoom)
TV::RunProgramGuidePtr
static EMBEDRETURNVOIDEPG RunProgramGuidePtr
Definition: tv_play.h:200
MythPlayer::IsErrored
bool IsErrored(void) const
Definition: mythplayer.cpp:1947
ACTION_ENABLESUBS
#define ACTION_ENABLESUBS
Definition: tv_actions.h:65
MythMediaBuffer::IsDVD
bool IsDVD(void) const
Definition: mythmediabuffer.cpp:1840
OSDTimeout
OSDTimeout
Definition: osd.h:55
MythPlayer::GetFrameRate
float GetFrameRate(void) const
Definition: mythplayer.h:133
TV::ActiveHandleAction
bool ActiveHandleAction(const QStringList &Actions, bool IsDVD, bool IsDVDStillFrame)
Definition: tv_play.cpp:3801
MythTimer::start
void start(void)
starts measuring elapsed time.
Definition: mythtimer.cpp:47
PlayerContext::m_jumptime
std::chrono::minutes m_jumptime
Definition: playercontext.h:140
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
playgroup.h
ACTION_ZOOMDOWN
#define ACTION_ZOOMDOWN
Definition: tv_actions.h:132
kPictureAttributeSupported_Range
@ kPictureAttributeSupported_Range
Definition: videoouttypes.h:123
TV::RunScheduleEditorPtr
static EMBEDRETURNVOIDSCHEDIT RunScheduleEditorPtr
Definition: tv_play.h:202
ACTION_MENUYELLOW
#define ACTION_MENUYELLOW
Definition: tv_actions.h:79
TV::DoArbSeek
void DoArbSeek(ArbSeekWhence Whence, bool HonorCutlist)
Definition: tv_play.cpp:5137
MythPlayer::GetCurrentFrameCount
uint64_t GetCurrentFrameCount(void) const
Definition: mythplayer.cpp:1737
MythPlayer::IsPlaying
bool IsPlaying(std::chrono::milliseconds wait_in_msec=0ms, bool wait_for=true) const
Definition: mythplayer.cpp:251
VBIMode::Parse
static uint Parse(const QString &vbiformat)
Definition: tv.h:17
PlayerContext::GetPreviousChannel
QString GetPreviousChannel(void) const
Definition: playercontext.cpp:225
TV::m_networkControlTimerId
volatile int m_networkControlTimerId
Definition: tv_play.h:684
TV::StartProgramEditMode
void StartProgramEditMode()
Starts Program Cut Map Editing mode.
Definition: tv_play.cpp:7902
MythPlayerOverlayUI::GetOSD
OSD * GetOSD()
Definition: mythplayeroverlayui.h:24
show
static void show(uint8_t *buf, int length)
Definition: ringbuffer.cpp:341
MenuCategory
MenuCategory
Definition: mythtvmenu.h:11
TV::PictureAttributeHandleAction
bool PictureAttributeHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3662
kOSDFunctionalType_PictureAdjust
@ kOSDFunctionalType_PictureAdjust
Definition: osd.h:47
kAdjustFill_AutoDetect_DefaultHalf
@ kAdjustFill_AutoDetect_DefaultHalf
Definition: videoouttypes.h:83
TV::SubtitleZoomHandleAction
bool SubtitleZoomHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3739
BUTTON2
#define BUTTON2(action, textActive, textInactive)
Definition: tv_play.cpp:8551
TV::StopStuff
void StopStuff(bool StopRingBuffer, bool StopPlayer, bool StopRecorder)
Can shut down the ringbuffers, the players, and in LiveTV it can shut down the recorders.
Definition: tv_play.cpp:2384
MythMediaBuffer::HandleAction
virtual bool HandleAction(const QStringList &, mpeg::chrono::pts)
Definition: mythmediabuffer.h:143
TV::ClearOSD
void ClearOSD()
Definition: tv_play.cpp:6303
ACTION_PREVCUT
#define ACTION_PREVCUT
Definition: tv_actions.h:91
ACTION_LOADCOMMSKIP
#define ACTION_LOADCOMMSKIP
Definition: tv_actions.h:89
ACTION_CLEAROSD
#define ACTION_CLEAROSD
Definition: tv_actions.h:14
ChannelUtil::GetMplexID
static uint GetMplexID(uint sourceid, const QString &channum)
Definition: channelutil.cpp:463
LiveTVChain::JumpTo
void JumpTo(int num, std::chrono::seconds pos)
Definition: livetvchain.cpp:605
PlayerFlags
PlayerFlags
Definition: mythplayer.h:64
mythsystemevent.h
ChannelGroup::GetChannelGroups
static ChannelGroupList GetChannelGroups(bool includeEmpty=true)
Definition: channelgroup.cpp:328
MythPlayer::Pause
bool Pause(void)
Definition: mythplayer.cpp:153
PlayerContext::HandlePlayerSpeedChangeFFRew
bool HandlePlayerSpeedChangeFFRew(void)
Definition: playercontext.cpp:120
RemoteEncoder::IsValidRecorder
bool IsValidRecorder(void) const
Definition: remoteencoder.cpp:57
MythMediaBuffer::IsBD
bool IsBD(void) const
Definition: mythmediabuffer.cpp:1845
TV::DoSwitchTitle
void DoSwitchTitle(int Title)
Definition: tv_play.cpp:5503
TV::ChannelEditXDSFill
void ChannelEditXDSFill(InfoMap &Info)
Definition: tv_play.cpp:8058
TV::m_queuedInput
QString m_queuedInput
Input key presses queued up so far...
Definition: tv_play.h:606
RemoteEncoder::ChangePictureAttribute
int ChangePictureAttribute(PictureAdjustType type, PictureAttribute attr, bool up)
Changes brightness/contrast/colour/hue of a recording.
Definition: remoteencoder.cpp:568
TVPlaybackState::EnableCaptions
void EnableCaptions(uint Mode, bool UpdateOSD=true)
mythdirs.h
OSD_DLG_DELETE
static constexpr const char * OSD_DLG_DELETE
Definition: osd.h:25
PlayerContext::StopPlaying
void StopPlaying(void) const
Definition: playercontext.cpp:151
TVBrowseHelper::GetBrowseChanId
uint GetBrowseChanId(const QString &Channum, uint PrefCardid, uint PrefSourceid) const
Returns a chanid for the channum, or 0 if none is available.
Definition: tvbrowsehelper.cpp:212
MythPlayer::GetBookmark
virtual uint64_t GetBookmark(void)
Definition: mythplayer.cpp:1315
TV::ShowLCDDVDInfo
void ShowLCDDVDInfo()
Definition: tv_play.cpp:6722
PlayerContext::m_fftime
std::chrono::seconds m_fftime
Definition: playercontext.h:138
TV::m_tvmState
TVState m_tvmState
Definition: tv_play.h:713
ChannelUtil::GetNextChannel
static uint GetNextChannel(const ChannelInfoList &sorted, uint old_chanid, uint mplexid_restriction, uint chanid_restriction, ChannelChangeDirection direction, bool skip_non_visible=true, bool skip_same_channum_and_callsign=false, bool skip_other_sources=false)
Definition: channelutil.cpp:2395
MythEditorState::m_hasUndo
bool m_hasUndo
Definition: mythplayerstate.h:160
MythTVMenuItemContext::m_menuName
const QString m_menuName
Definition: mythtvmenu.h:68
ZoomDirection
ZoomDirection
Definition: videoouttypes.h:42
kPictureAttributeSupported_Colour
@ kPictureAttributeSupported_Colour
Definition: videoouttypes.h:121
ACTION_SELECT
static constexpr const char * ACTION_SELECT
Definition: mythuiactions.h:15
MythGestureEvent::kEventType
static const Type kEventType
Definition: mythgesture.h:91
MythPlayerUI::VideoLoop
virtual bool VideoLoop()
Definition: mythplayerui.cpp:498
ProgramInfo::GetRecordingGroup
QString GetRecordingGroup(void) const
Definition: programinfo.h:420
ACTION_TOGGLEUPMIX
#define ACTION_TOGGLEUPMIX
Definition: tv_actions.h:107
RemoteEncoder::ShouldSwitchToAnotherCard
bool ShouldSwitchToAnotherCard(const QString &channelid)
Checks if named channel exists on current tuner, or another tuner. This only works on local recorders...
Definition: remoteencoder.cpp:632
TV::GetNumTitles
int GetNumTitles()
Definition: tv_play.cpp:5432
MythCoreContext::emitTVPlaybackSought
void emitTVPlaybackSought(qint64 position)
Definition: mythcorecontext.h:272
MythPlayer::SkipCommercials
void SkipCommercials(int direction)
Definition: mythplayer.h:280
TV::m_inPlaylist
bool m_inPlaylist
show is part of a playlist
Definition: tv_play.h:632
ACTION_NEXTPAGE
#define ACTION_NEXTPAGE
Definition: tv_actions.h:96
TV::m_endOfRecording
bool m_endOfRecording
!player->IsPlaying() && StateIsPlaying()
Definition: tv_play.h:557
TV::ChangeTimeStretch
void ChangeTimeStretch(int Dir, bool AllowEdit=true)
Definition: tv_play.cpp:7068
CommSkipMode
CommSkipMode
Definition: tv.h:133
MythTVMenu::GetKeyBindingContext
const QString & GetKeyBindingContext() const
Definition: mythtvmenu.cpp:113
OSD_WIN_MESSAGE
static constexpr const char * OSD_WIN_MESSAGE
Definition: osd.h:29
TV::ReloadKeys
void ReloadKeys()
Definition: tv_play.cpp:968
remoteutil.h
TV::m_dbRunJobsOnRemote
bool m_dbRunJobsOnRemote
Definition: tv_play.h:532
kNormalAutoExpire
@ kNormalAutoExpire
Definition: programtypes.h:194
TV::StateIsLiveTV
static bool StateIsLiveTV(TVState State)
Definition: tv_play.cpp:1956
ACTION_BOTTOMLINESAVE
#define ACTION_BOTTOMLINESAVE
Definition: tv_actions.h:146
ACTION_ZOOMASPECTDOWN
#define ACTION_ZOOMASPECTDOWN
Definition: tv_actions.h:136
TVPlaybackState::GoToDVDProgram
void GoToDVDProgram(bool Direction)
hardwareprofile.distros.mythtv_data.data_mythtv.prefix
string prefix
Definition: data_mythtv.py:37
LCD::Get
static LCD * Get(void)
Definition: lcddevice.cpp:69
MythDVDBuffer::GetTotalTimeOfTitle
std::chrono::seconds GetTotalTimeOfTitle(void) const
get the total time of the title in seconds 90000 ticks = 1 sec
Definition: mythdvdbuffer.cpp:1157
TV::GetNumAngles
int GetNumAngles()
Definition: tv_play.cpp:5452
TV::AcquireRelease
static TV * AcquireRelease(int &RefCount, bool Acquire, bool Create=false)
Statically create, destroy or check the existence of the TV instance.
Definition: tv_play.cpp:140
TVPlaybackState::ToggleCaptionsByType
void ToggleCaptionsByType(uint Type)
ACTION_SETHUE
#define ACTION_SETHUE
Definition: tv_actions.h:62
OSD_WIN_PROGEDIT
static constexpr const char * OSD_WIN_PROGEDIT
Definition: osd.h:35
MythCaptionsState::m_textDisplayMode
uint m_textDisplayMode
Definition: mythplayerstate.h:70
TV::m_progLists
QMap< QString, ProgramList > m_progLists
Definition: tv_play.h:574
MythUIType::DeleteAllChildren
void DeleteAllChildren(void)
Delete all child widgets.
Definition: mythuitype.cpp:222
MythPlayer::GetLimitKeyRepeat
bool GetLimitKeyRepeat(void) const
Definition: mythplayer.h:152
TV::m_endOfRecPromptTimerId
volatile int m_endOfRecPromptTimerId
Definition: tv_play.h:689
kZoomUp
@ kZoomUp
Definition: videoouttypes.h:51
kPictureAttributeSupported_Brightness
@ kPictureAttributeSupported_Brightness
Definition: videoouttypes.h:119
hardwareprofile.scan.scan
def scan(profile, smoonURL, gate)
Definition: scan.py:54
OSDFunctionalType
OSDFunctionalType
Definition: osd.h:44
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:15
TV::QuickRecord
void QuickRecord()
Definition: tv_play.cpp:7673
MythEditorState::m_redoMessage
QString m_redoMessage
Definition: mythplayerstate.h:163
TV::m_playerBounds
QRect m_playerBounds
Prior GUI window bounds, for DoEditSchedule() and player exit().
Definition: tv_play.h:660
MythEvent::Message
const QString & Message() const
Definition: mythevent.h:65
RemoteEncoder::Setup
bool Setup(void)
Definition: remoteencoder.cpp:28
TV::Embed
void Embed(bool Embed, QRect Rect={}, const QStringList &Data={})
Definition: tv_play.cpp:6843
TVPlaybackState::ToggleCaptions
void ToggleCaptions()
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:405
ProgramInfo::GetPathname
QString GetPathname(void) const
Definition: programinfo.h:344
kCommSkipOff
@ kCommSkipOff
Definition: tv.h:135
VBIMode::PAL_TT
@ PAL_TT
Definition: tv.h:13
TV::StartTV
static bool StartTV(ProgramInfo *TVRec, uint Flags, const ChannelInfoList &Selection=ChannelInfoList())
Start playback of media.
Definition: tv_play.cpp:287
TV::getMenuFromId
const MythTVMenu & getMenuFromId(MenuTypeId id)
Definition: tv_play.cpp:7258
TVPlaybackState::GoToMenu
void GoToMenu(const QString &Menu)
RemoteEncoder
Definition: remoteencoder.h:24
TV::GetTitleName
QString GetTitleName(int Title)
Definition: tv_play.cpp:5493
kPseudoRecording
@ kPseudoRecording
Definition: playercontext.h:44
PlayerContext::IsPlayerErrored
bool IsPlayerErrored(void) const
Definition: playercontext.cpp:108
TV::IsDeleteAllowed
bool IsDeleteAllowed()
Definition: tv_play.cpp:10194
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
TV::HandleOSDCutpoint
bool HandleOSDCutpoint(const QString &Action)
Definition: tv_play.cpp:7879
Action
An action (for this plugin) consists of a description, and a set of key sequences.
Definition: action.h:40
kMenuCategoryItem
@ kMenuCategoryItem
Definition: mythtvmenu.h:13
TV::DoSeekFFWD
void DoSeekFFWD()
Definition: tv_play.cpp:10074
State
State
Definition: zmserver.h:68
ACTION_INVERTMAP
#define ACTION_INVERTMAP
Definition: tv_actions.h:87
SignalMonitorList
std::vector< SignalMonitorValue > SignalMonitorList
Definition: signalmonitorvalue.h:149
RecordingInfo::ApplyTranscoderProfileChange
void ApplyTranscoderProfileChange(const QString &profile) const
Sets the transcoder profile for a recording.
Definition: recordinginfo.cpp:848
NoRecorderMsg
NoRecorderMsg
Type of message displayed in ShowNoRecorderDialog()
Definition: tv_play.h:106
SET_LAST
#define SET_LAST()
Definition: tv_play.cpp:1965
programtypes.h
TV::m_tvmIsBd
bool m_tvmIsBd
Definition: tv_play.h:721
MythPlayer::SetAutoCommercialSkip
void SetAutoCommercialSkip(CommSkipMode autoskip)
Definition: mythplayer.h:278
MythEditorState::m_hasTempMark
bool m_hasTempMark
Definition: mythplayerstate.h:159
MythPlayer::ResetErrored
void ResetErrored(void)
Definition: mythplayer.cpp:1940
TV::m_dbEndOfRecExitPrompt
bool m_dbEndOfRecExitPrompt
Definition: tv_play.h:528
InfoMap
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
PlayerContext::ReloadTVChain
bool ReloadTVChain(void)
Definition: playercontext.cpp:167
ChannelUtil::SortChannels
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
Definition: channelutil.cpp:2338
kDisplayTeletextMenu
@ kDisplayTeletextMenu
Definition: videoouttypes.h:22
PlayerContext::GetCardID
uint GetCardID(void) const
Definition: playercontext.h:93
MythObservable::addListener
void addListener(QObject *listener)
Add a listener to the observable.
Definition: mythobservable.cpp:38
MythPlayer::SwitchTitle
virtual bool SwitchTitle(int)
Definition: mythplayer.h:167
PlayerContext::PushPreviousChannel
void PushPreviousChannel(void)
most recently selected channel to the previous channel list
Definition: playercontext.cpp:186
TV::m_lockTimer
QElapsedTimer m_lockTimer
Definition: tv_play.h:624
MythPlayer::GetPlaySpeed
float GetPlaySpeed(void) const
Definition: mythplayer.h:138
MythDisplay::GetGUIResolution
QSize GetGUIResolution()
Definition: mythdisplay.cpp:312
JOB_USE_CUTLIST
@ JOB_USE_CUTLIST
Definition: jobqueue.h:60
MythMainWindow::GetDisplay
MythDisplay * GetDisplay()
Definition: mythmainwindow.cpp:252
MythMainWindow::DisableScreensaver
static void DisableScreensaver()
Definition: mythmainwindow.cpp:582
TV::SwitchInputs
void SwitchInputs(uint ChanID=0, QString ChanNum="", uint InputID=0)
Definition: tv_play.cpp:5614
AutoDeleteDeque::begin
iterator begin(void)
Definition: autodeletedeque.h:50
TV::SetSpeedChangeTimer
void SetSpeedChangeTimer(std::chrono::milliseconds When, int Line)
Definition: tv_play.cpp:2946
MythMainWindow::GetKey
static QString GetKey(const QString &Context, const QString &Action)
Definition: mythmainwindow.cpp:1322
kZoomAspectUp
@ kZoomAspectUp
Definition: videoouttypes.h:55
TV::m_dbBrowseAllTuners
bool m_dbBrowseAllTuners
Definition: tv_play.h:535
TV::PrepareToExitPlayer
void PrepareToExitPlayer(int Line)
Definition: tv_play.cpp:2770
TV::MenuItemDisplayPlayback
bool MenuItemDisplayPlayback(const MythTVMenuItemContext &Context, MythOSDDialogData *Menu)
Definition: tv_play.cpp:8701
BUTTON
#define BUTTON(action, text)
Definition: tv_play.cpp:8549
MythDate::secsInFuture
std::chrono::seconds secsInFuture(const QDateTime &future)
Definition: mythdate.cpp:217
ACTION_ENABLEFORCEDSUBS
#define ACTION_ENABLEFORCEDSUBS
Definition: tv_actions.h:68
MythTVMenu::GetPathFromNode
static QString GetPathFromNode(QDomNode Node)
Definition: mythtvmenu.cpp:131
MythMainWindow::KeyLongPressFilter
bool KeyLongPressFilter(QEvent **Event, QScopedPointer< QEvent > &NewEvent)
Definition: mythmainwindow.cpp:1550
RecordingInfo::kNoProgram
@ kNoProgram
Definition: recordinginfo.h:181
MythCoreContext::UnregisterForPlayback
void UnregisterForPlayback(QObject *sender)
Definition: mythcorecontext.cpp:1985
insert_map
static void insert_map(InfoMap &infoMap, const InfoMap &newMap)
Definition: tv_play.cpp:7959
TV::ARBSEEK_FORWARD
@ ARBSEEK_FORWARD
Definition: tv_play.h:372
EMBEDRETURNVOIDFINDER
void(*)(TV *, bool, bool) EMBEDRETURNVOIDFINDER
Definition: tv_play.h:61
TV::UpdateOSDInput
void UpdateOSDInput()
Definition: tv_play.cpp:6439
TV::m_sleepIndex
uint m_sleepIndex
Index into sleep_times.
Definition: tv_play.h:585
RemoteEncoder::IsRecording
bool IsRecording(bool *ok=nullptr)
Definition: remoteencoder.cpp:117
MythPlayerUI
Definition: mythplayerui.h:12
MythMediaBuffer::GetFilename
QString GetFilename(void) const
Definition: mythmediabuffer.cpp:1749
TV::GetCurrentTitle
int GetCurrentTitle()
Definition: tv_play.cpp:5442
CardUtil::GetInputGroups
static std::vector< uint > GetInputGroups(uint inputid)
Definition: cardutil.cpp:2188
OSD_WIN_STATUS
static constexpr const char * OSD_WIN_STATUS
Definition: osd.h:32
ProgramInfo::IsVideoBD
bool IsVideoBD(void) const
Definition: programinfo.h:350
kPictureAttributeSupported_Contrast
@ kPictureAttributeSupported_Contrast
Definition: videoouttypes.h:120
MythPlayer::GetFramesPlayed
uint64_t GetFramesPlayed(void) const
Definition: mythplayer.h:144
MythPlayer::ComputeSecs
float ComputeSecs(uint64_t position, bool use_cutlist) const
Definition: mythplayer.h:272
PlayerContext::m_prevChan
StringDeque m_prevChan
Previous channels.
Definition: playercontext.h:132
ACTION_BIGJUMPREW
#define ACTION_BIGJUMPREW
Definition: tv_actions.h:92
TV::ToggleChannelFavorite
static void ToggleChannelFavorite()
Definition: tv_play.cpp:5773
TV::HandleOSDSleep
void HandleOSDSleep(const QString &Action)
Definition: tv_play.cpp:7162
TV::HandlePseudoLiveTVTimerEvent
void HandlePseudoLiveTVTimerEvent()
Definition: tv_play.cpp:2912
BROWSE_RIGHT
@ BROWSE_RIGHT
Fetch information on current channel in the future.
Definition: tv.h:47
ACTION_SETAUDIOSYNC
#define ACTION_SETAUDIOSYNC
Definition: tv_actions.h:114
mythdate.h
sourceutil.h
TV::AskAllowRecording
void AskAllowRecording(const QStringList &Msg, int Timeuntil, bool HasRec, bool HasLater)
Definition: tv_play.cpp:1612
TV::DoSeekRWND
void DoSeekRWND()
Definition: tv_play.cpp:10089
TV::GetStatus
void GetStatus()
Definition: tv_play.cpp:1375
ACTION_ZOOMCOMMIT
#define ACTION_ZOOMCOMMIT
Definition: tv_actions.h:144
TV::m_tvmNumTitles
int m_tvmNumTitles
Definition: tv_play.h:732
LCD::getLCDWidth
int getLCDWidth(void) const
Definition: lcddevice.h:293
TV::m_tvmChapterTimes
QList< std::chrono::seconds > m_tvmChapterTimes
Definition: tv_play.h:729
TVBrowseHelper::BrowseWait
void BrowseWait()
Definition: tvbrowsehelper.cpp:68
TV::m_signalMonitorTimerId
volatile int m_signalMonitorTimerId
Definition: tv_play.h:696
ACTION_SWITCHTITLE
#define ACTION_SWITCHTITLE
Definition: tv_actions.h:53
OSD_WIN_PROGINFO
static constexpr const char * OSD_WIN_PROGINFO
Definition: osd.h:31
TV::m_dbChannelGroups
ChannelGroupList m_dbChannelGroups
Definition: tv_play.h:538
CHANNEL_DIRECTION_DOWN
@ CHANNEL_DIRECTION_DOWN
Definition: tv.h:34
MythMediaOverlay::HasWindow
bool HasWindow(const QString &Window)
Definition: mythmediaoverlay.cpp:87
TV::GetOSDL
OSD * GetOSDL()
Definition: tv_play.cpp:10471
kOSDTimeout_None
@ kOSDTimeout_None
Definition: osd.h:58
TV::DoSwitchAngle
void DoSwitchAngle(int Angle)
Definition: tv_play.cpp:5519
TV::m_channelGroupChannelList
ChannelInfoList m_channelGroupChannelList
Definition: tv_play.h:676
programinfo.h
MythTVMenu::GetName
QString GetName() const
Definition: mythtvmenu.cpp:93
ChannelUtil::GetChanID
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
Definition: channelutil.cpp:1336
kCommSkipIncr
@ kCommSkipIncr
Definition: tv.h:139
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:391
Command
Definition: gamesettings.cpp:234
TV::StartPlaying
bool StartPlaying(std::chrono::milliseconds MaxWait=-1ms)
Definition: tv_play.cpp:234
JobQueue::IsJobQueuedOrRunning
static bool IsJobQueuedOrRunning(int jobType, uint chanid, const QDateTime &recstartts)
Definition: jobqueue.cpp:1098
mythlogging.h
PictureAttributeSupported
PictureAttributeSupported
Definition: videoouttypes.h:116
TV::m_cutlistCompactMenu
MythTVMenu m_cutlistCompactMenu
Definition: tv_play.h:747
TV::kInputModeTimeout
static const std::chrono::milliseconds kInputModeTimeout
Definition: tv_play.h:755
TV::ChangeSpeed
void ChangeSpeed(int Direction)
Definition: tv_play.cpp:5189
TV::AudioSyncHandleAction
bool AudioSyncHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3716
ACTION_MENURED
#define ACTION_MENURED
Definition: tv_actions.h:77
PlayGroup::GetCount
static int GetCount(void)
Definition: playgroup.cpp:220
TV::DoEditSchedule
void DoEditSchedule(int EditType=kScheduleProgramGuide, const QString &EditArg="")
Definition: tv_play.cpp:6887
kScheduleProgramGuide
@ kScheduleProgramGuide
Definition: tv_play.h:95
PlayerContext::SetInitialTVState
void SetInitialTVState(bool islivetv)
determine initial tv state and playgroup for the recording
Definition: playercontext.cpp:58
ACTION_CLEARMAP
#define ACTION_CLEARMAP
Definition: tv_actions.h:86
TV::IsPaused
static bool IsPaused()
Check whether playback is paused.
Definition: tv_play.cpp:4892
TV::HandleVideoExitDialogTimerEvent
void HandleVideoExitDialogTimerEvent()
Definition: tv_play.cpp:2887
MythOSDDialogData
Definition: osd.h:64
TV::GetQueuedInputAsInt
int GetQueuedInputAsInt(bool *OK=nullptr, int Base=10) const
Definition: tv_play.cpp:5791
TV::ConfiguredTunerCards
static int ConfiguredTunerCards()
If any cards are configured, return the number.
Definition: tv_play.cpp:118
PlayerContext::m_errored
bool m_errored
Definition: playercontext.h:129
TV::Playback
int Playback(const ProgramInfo &ProgInfo)
Definition: tv_play.cpp:1910
TV::ToggleOSD
void ToggleOSD(bool IncludeStatusOSD)
Cycle through the available Info OSDs.
Definition: tv_play.cpp:6319
RemoteRequestFreeInputInfo
std::vector< InputInfo > RemoteRequestFreeInputInfo(uint excluded_input)
Definition: tvremoteutil.cpp:138
TV::FillOSDMenuActorShows
void FillOSDMenuActorShows(const QString &actor, int person_id, const QString &category="")
Definition: tv_play.cpp:9675
TV::m_ffRewRepos
float m_ffRewRepos
Definition: tv_play.h:541
TV::m_chanEditMap
InfoMap m_chanEditMap
Channel Editing initial map.
Definition: tv_play.h:581
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89
TV::kPreviousSource
static const uint kPreviousSource
Definition: tv_play.h:753
ACTION_3DTOPANDBOTTOMDISCARD
#define ACTION_3DTOPANDBOTTOMDISCARD
Definition: tv_actions.h:128
TV::lastProgramStringList
static QStringList lastProgramStringList
Definition: tv_play.h:197
MythTVMenu::IsLoaded
bool IsLoaded() const
Definition: mythtvmenu.cpp:98
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1115
RemoteIsBusy
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)
Definition: tvremoteutil.cpp:363
TV::MenuItemDisplay
bool MenuItemDisplay(const MythTVMenuItemContext &Context, MythOSDDialogData *Menu) override
Definition: tv_play.cpp:8557
MythMediaBuffer::WaitForPause
void WaitForPause(void)
Waits for Pause(void) to take effect.
Definition: mythmediabuffer.cpp:718
TV::m_queuedChanID
uint m_queuedChanID
Queued ChanID (from EPG channel selector)
Definition: tv_play.h:610
TV::m_dbUseChannelGroups
bool m_dbUseChannelGroups
Definition: tv_play.h:536
PlayerContext::SetRecorder
void SetRecorder(RemoteEncoder *rec)
Definition: playercontext.cpp:469
kPictureAttribute_Volume
@ kPictureAttribute_Volume
Definition: videoouttypes.h:112
ACTION_TOGGLEEXTTEXT
#define ACTION_TOGGLEEXTTEXT
Definition: tv_actions.h:72
MythVideoBoundsState::m_aspectOverrideMode
AspectOverrideMode m_aspectOverrideMode
Definition: mythplayerstate.h:105
MythMediaBuffer::IsInDiscMenuOrStillFrame
virtual bool IsInDiscMenuOrStillFrame(void) const
Definition: mythmediabuffer.h:142
PlayerContext::m_playingInfo
ProgramInfo * m_playingInfo
Currently playing info.
Definition: playercontext.h:117
TV::ScheduleStateChange
void ScheduleStateChange()
Definition: tv_play.cpp:2713
TVPlaybackState::AdjustSubtitleZoom
void AdjustSubtitleZoom(int Delta)
TV::HandleLCDVolumeTimerEvent
void HandleLCDVolumeTimerEvent()
Definition: tv_play.cpp:2679
MythEditorState::m_nextCut
uint64_t m_nextCut
Definition: mythplayerstate.h:155
MThreadPool::waitForDone
void waitForDone(void)
Definition: mthreadpool.cpp:556
ACTION_SEEKARB
#define ACTION_SEEKARB
Definition: tv_actions.h:41
ACTION_TVPOWERON
static constexpr const char * ACTION_TVPOWERON
Definition: mythuiactions.h:25
TV::m_idleDialogTimerId
int m_idleDialogTimerId
Timer for idle dialog.
Definition: tv_play.h:591
ACTION_ENABLEVISUALISATION
#define ACTION_ENABLEVISUALISATION
Definition: tv_actions.h:118
EMBEDRETURNVOIDSCHEDIT
void(*)(const ProgramInfo *, void *) EMBEDRETURNVOIDSCHEDIT
Definition: tv_play.h:63
MythVisualiserState::m_canVisualise
bool m_canVisualise
Definition: mythplayerstate.h:135
TV::SetManualZoom
void SetManualZoom(bool ZoomON, const QString &Desc)
Definition: tv_play.cpp:9803
comp_originalAirDate_rev
static int comp_originalAirDate_rev(const ProgramInfo *a, const ProgramInfo *b)
Definition: tv_play.cpp:83
TV::m_chanEditMapLock
QRecursiveMutex m_chanEditMapLock
Lock for chanEditMap and ddMap.
Definition: tv_play.h:580
TV::HandleEndOfRecordingExitPromptTimerEvent
void HandleEndOfRecordingExitPromptTimerEvent()
Definition: tv_play.cpp:2857
MythCoreContext::SendSystemEvent
void SendSystemEvent(const QString &msg)
Definition: mythcorecontext.cpp:1572
ACTION_NEXTCUT
#define ACTION_NEXTCUT
Definition: tv_actions.h:90
PlayerContext::m_tsAlt
float m_tsAlt
Definition: playercontext.h:148
MythOverlayState::m_editing
bool m_editing
Definition: mythplayerstate.h:26
hardwareprofile.config.p
p
Definition: config.py:33
kMenuIdPlayback
@ kMenuIdPlayback
Definition: mythtvmenu.h:39
signalhandling.h
osdInfo::values
QHash< QString, int > values
Definition: playercontext.h:37
TV::eventFilter
bool eventFilter(QObject *Object, QEvent *Event) override
Prevent events from being sent to another object.
Definition: tv_play.cpp:2990
RemoteEncoder::SpawnLiveTV
void SpawnLiveTV(const QString &chainid, bool pip, const QString &startchan)
Tells TVRec to Spawn a "Live TV" recorder.
Definition: remoteencoder.cpp:354
TV::m_stretchAdjustment
bool m_stretchAdjustment
True if time stretch is turned on.
Definition: tv_play.h:551
ACTION_DISABLEEXTTEXT
#define ACTION_DISABLEEXTTEXT
Definition: tv_actions.h:70
Event
Event details.
Definition: zmdefines.h:27
MythPlayer::GetAutoCommercialSkip
CommSkipMode GetAutoCommercialSkip(void)
Definition: mythplayer.h:283
mythdvdplayer.h
ACTION_SEEKABSOLUTE
#define ACTION_SEEKABSOLUTE
Definition: tv_actions.h:40
hardwareprofile.i18n.t
t
Definition: i18n.py:36
MythVisualiserState::m_visualiserName
QString m_visualiserName
Definition: mythplayerstate.h:138
PlayerContext::LockPlayingInfo
void LockPlayingInfo(const char *file, int line) const
Definition: playercontext.cpp:239
TV::DoSeekAbsolute
void DoSeekAbsolute(long long Seconds, bool HonorCutlist)
Definition: tv_play.cpp:5123
TV::m_tvmCurrentAngle
int m_tvmCurrentAngle
Definition: tv_play.h:731
MythTVMenu::MatchesGroup
static bool MatchesGroup(const QString &Name, const QString &Prefix, MenuCategory Category, QString &OutPrefix)
Definition: mythtvmenu.cpp:123
TV::m_dbRememberLastChannelGroup
bool m_dbRememberLastChannelGroup
Definition: tv_play.h:537
MythVideoFrame::m_timecode
std::chrono::milliseconds m_timecode
Definition: mythframe.h:130
TV::ShowOSDCutpoint
void ShowOSDCutpoint(const QString &Type)
Definition: tv_play.cpp:7835
TVPlaybackState::ChangeAllowForcedSubtitles
void ChangeAllowForcedSubtitles(bool Allow)
ACTION_PREVSUBPAGE
#define ACTION_PREVSUBPAGE
Definition: tv_actions.h:99
TV::StartTimer
int StartTimer(std::chrono::milliseconds Interval, int Line)
Definition: tv_play.cpp:2694
MythPlayer::GetTitleDuration
virtual std::chrono::seconds GetTitleDuration(int) const
Definition: mythplayer.h:220
menu
static MythThemedMenu * menu
Definition: mythtv-setup.cpp:58
kPlaybackBox
@ kPlaybackBox
Definition: tv_play.h:99
TV::m_tvmSubsForcedOn
bool m_tvmSubsForcedOn
Definition: tv_play.h:735
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:362
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
ACTION_SETCOLOUR
#define ACTION_SETCOLOUR
Definition: tv_actions.h:61
ACTION_CAST
#define ACTION_CAST
Definition: tv_actions.h:149
RemoteEncoder::GetInput
QString GetInput(void)
Definition: remoteencoder.cpp:409
TVPlaybackState::ChangeAdjustFill
void ChangeAdjustFill(AdjustFillMode FillMode=kAdjustFill_Toggle)
compat.h
PlayerContext::m_rewtime
std::chrono::seconds m_rewtime
Definition: playercontext.h:139
TV::setUnderNetworkControl
void setUnderNetworkControl(bool setting)
Definition: tv_play.h:294
kAspect_16_9
@ kAspect_16_9
Definition: videoouttypes.h:65
TV::ManualZoomHandleAction
bool ManualZoomHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3585
kTrackTypeTextSubtitle
@ kTrackTypeTextSubtitle
Definition: decoderbase.h:42
MythDVDBuffer::GoBack
bool GoBack(void)
Attempts to back-up by trying to jump to the 'Go up' PGC, the root menu or the title menu in turn.
Definition: mythdvdbuffer.cpp:1274
TVPlaybackState::m_visualiserState
MythVisualiserState m_visualiserState
Definition: tvplaybackstate.h:110
kDisplayRawTextSubtitle
@ kDisplayRawTextSubtitle
Definition: videoouttypes.h:20
osdInfo::text
InfoMap text
Definition: playercontext.h:36
MythDVDPlayer
Definition: mythdvdplayer.h:10
TV::GetTitleDuration
std::chrono::seconds GetTitleDuration(int Title)
Definition: tv_play.cpp:5482
TV::KillTimer
void KillTimer(int Id)
Definition: tv_play.cpp:2702
TV::m_tvmIsLiveTv
bool m_tvmIsLiveTv
Definition: tv_play.h:723
kAdjustingPicture_Channel
@ kAdjustingPicture_Channel
Definition: tv.h:127
PlayerContext::m_buffer
MythMediaBuffer * m_buffer
Definition: playercontext.h:116
TV::SleepTimerInfo
Definition: tv_play.cpp:978
MythEditorState::m_saved
bool m_saved
Definition: mythplayerstate.h:164
TV::RunPlaybackBoxPtr
static EMBEDRETURNVOID RunPlaybackBoxPtr
Definition: tv_play.h:198
RemoteEncoder::ChangeChannel
void ChangeChannel(int channeldirection)
Definition: remoteencoder.cpp:451
EMBEDRETURNVOIDPROGLIST
void(*)(TV *, int, const QString &) EMBEDRETURNVOIDPROGLIST
Definition: tv_play.h:62
kScheduledRecording
@ kScheduledRecording
Definition: tv_play.h:97
TVPlaybackState::SetTeletextPage
void SetTeletextPage(uint Page)
TVPlaybackState::ResetCaptions
void ResetCaptions()
StringUtil::naturalCompare
MBASE_PUBLIC int naturalCompare(const QString &_a, const QString &_b, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
This method chops the input a and b into pieces of digits and non-digits (a1.05 becomes a | 1 | .
Definition: stringutil.cpp:160
TV::kSpeedChangeCheckFrequency
static const std::chrono::milliseconds kSpeedChangeCheckFrequency
Definition: tv_play.h:765
MythMediaEvent
Definition: mythmedia.h:183
TVBrowseHelper::BrowseInit
void BrowseInit(std::chrono::seconds BrowseMaxForward, bool BrowseAllTuners, bool UseChannelGroups, const QString &DBChannelOrdering)
Definition: tvbrowsehelper.cpp:40
RecordingRule::m_autoExpire
bool m_autoExpire
Definition: recordingrule.h:127
videometadatautil.h
TV::kKeyRepeatTimeout
static const std::chrono::milliseconds kKeyRepeatTimeout
Definition: tv_play.h:758
ACTION_CHANNELSEARCH
#define ACTION_CHANNELSEARCH
Definition: tv_actions.h:28
ProgramInfo::GetSourceID
uint GetSourceID(void) const
Definition: programinfo.h:466
RemoteEncoder::SetLiveRecording
void SetLiveRecording(bool recording)
Definition: remoteencoder.cpp:400
ACTION_PAUSE
#define ACTION_PAUSE
Definition: tv_actions.h:15
ProgramInfo::SetIgnoreLastPlayPos
void SetIgnoreLastPlayPos(bool ignore)
If "ignore" is true QueryLastPlayPos() will return 0, otherwise QueryLastPlayPos() will return the la...
Definition: programinfo.h:578
TVPlaybackState::HandleITVAction
void HandleITVAction(const QString &Action, bool &Handled)
TV::m_playerContext
PlayerContext m_playerContext
Definition: tv_play.h:639
ACTION_TOGGLEOSDDEBUG
#define ACTION_TOGGLEOSDDEBUG
Definition: tv_actions.h:122
MythVideoBoundsState::m_manualMove
QPoint m_manualMove
Definition: mythplayerstate.h:108
tv_play_win.h
ACTION_ZOOMHORIZONTALOUT
#define ACTION_ZOOMHORIZONTALOUT
Definition: tv_actions.h:142
mythtvactionutils.h
kOSDFunctionalType_SubtitleZoomAdjust
@ kOSDFunctionalType_SubtitleZoomAdjust
Definition: osd.h:51
TVPlaybackState::RestartITV
void RestartITV(uint Chanid, uint Cardid, bool IsLiveTV)
PlayerContext::m_pseudoLiveTVRec
ProgramInfo * m_pseudoLiveTVRec
Definition: playercontext.h:135
kTrackTypeTeletextMenu
@ kTrackTypeTeletextMenu
Definition: decoderbase.h:35
MythPlayerCaptionsUI::GetTracks
QStringList GetTracks(uint Type)
Definition: mythplayercaptionsui.cpp:318
TV::m_pseudoChangeChanTimerId
volatile int m_pseudoChangeChanTimerId
Definition: tv_play.h:691
TV::ShowOSDIdle
void ShowOSDIdle()
After idleTimer has expired, display a dialogue warning the user that we will exit LiveTV unless they...
Definition: tv_play.cpp:7201
TV::m_tvmIsVideo
bool m_tvmIsVideo
Definition: tv_play.h:716
ACTION_JUMPTODVDTITLEMENU
#define ACTION_JUMPTODVDTITLEMENU
Definition: tv_actions.h:51
TV::m_dbJumpPreferOsd
bool m_dbJumpPreferOsd
Definition: tv_play.h:529
stringutil.h
showStatus
static void showStatus(void)
Definition: mythfrontend.cpp:693
MythEvent::kUpdateTvProgressEventType
static const Type kUpdateTvProgressEventType
Definition: mythevent.h:81
kNoRecorders
@ kNoRecorders
No free recorders.
Definition: tv_play.h:108
TV::m_playbackCompactMenu
MythTVMenu m_playbackCompactMenu
Definition: tv_play.h:745
RecordingInfo::QuickRecord
void QuickRecord(void)
Create a kSingleRecord if not already scheduled.
Definition: recordinginfo.cpp:920
AutoExpireType
AutoExpireType
Definition: programtypes.h:192
TV::m_zoomMode
bool m_zoomMode
Definition: tv_play.h:555
mythmedia.h
kDecodeAllowGPU
@ kDecodeAllowGPU
Definition: mythplayer.h:72
TV::kEndOfPlaybackFirstCheckTimer
static const std::chrono::milliseconds kEndOfPlaybackFirstCheckTimer
Definition: tv_play.h:772
kAdjustFill_END
@ kAdjustFill_END
Definition: videoouttypes.h:81
TVPlaybackState::HideAll
void HideAll(bool KeepSubs=true, MythScreenType *Except=nullptr, bool DropNotification=false)
TV::kSleepTimerDialogTimeout
static const std::chrono::milliseconds kSleepTimerDialogTimeout
Definition: tv_play.h:760
kStartTVIgnoreProgStart
@ kStartTVIgnoreProgStart
Definition: tv_play.h:118
RemoteEncoder::GetSignalLockTimeout
uint GetSignalLockTimeout(const QString &input)
Definition: remoteencoder.cpp:506
TV::m_queuedChanNum
QString m_queuedChanNum
Input key presses queued up so far to form a valid ChanNum.
Definition: tv_play.h:608
TV::m_savePosOnExit
bool m_savePosOnExit
False until first timer event.
Definition: tv_play.h:562
ACTION_ZOOMUP
#define ACTION_ZOOMUP
Definition: tv_actions.h:131
ProgramInfo::toString
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
Definition: programinfo.cpp:1955
PlayerContext::LockDeletePlayer
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 ...
Definition: playercontext.cpp:264
TV::ToggleAutoExpire
void ToggleAutoExpire()
Definition: tv_play.cpp:9764
TV::SleepTimerInfo::SleepTimerInfo
SleepTimerInfo(QString String, std::chrono::milliseconds MilliSeconds)
Definition: tv_play.cpp:981
TV::PlaybackMenuShow
void PlaybackMenuShow(const MythTVMenu &Menu, const QDomNode &Node, const QDomNode &Selected)
Definition: tv_play.cpp:9369
kZoomDown
@ kZoomDown
Definition: videoouttypes.h:52
ACTION_ZOOMQUIT
#define ACTION_ZOOMQUIT
Definition: tv_actions.h:143
TV::GetQueuedInput
QString GetQueuedInput() const
Definition: tv_play.cpp:5786
TV::m_savedGuiBounds
QRect m_savedGuiBounds
Definition: tv_play.h:662
TV::MenuItemDisplayCutlist
bool MenuItemDisplayCutlist(const MythTVMenuItemContext &Context, MythOSDDialogData *Menu)
Definition: tv_play.cpp:8566
MythPlayer::PauseDecoder
bool PauseDecoder(void)
Definition: mythplayer.cpp:968
OSD_DLG_IDLE
static constexpr const char * OSD_DLG_IDLE
Definition: osd.h:19
TVPlaybackState::SetCaptionsEnabled
void SetCaptionsEnabled(bool Enable, bool UpdateOSD=true)
kAspect_Off
@ kAspect_Off
Definition: videoouttypes.h:63
TV::HandleSpeedChangeTimerEvent
void HandleSpeedChangeTimerEvent()
Definition: tv_play.cpp:2953
kMenuCategoryMenu
@ kMenuCategoryMenu
Definition: mythtvmenu.h:15
kTrackTypeCC608
@ kTrackTypeCC608
Definition: decoderbase.h:32
ProgramInfo::ToMap
virtual void ToMap(InfoMap &progMap, bool showrerecord=false, uint star_range=10, uint date_format=0) const
Converts ProgramInfo into QString QHash containing each field in ProgramInfo converted into localized...
Definition: programinfo.cpp:1588
MythCoreContext::GetResolutionSetting
void GetResolutionSetting(const QString &type, int &width, int &height, double &forced_aspect, double &refresh_rate, int index=-1)
Definition: mythcorecontext.cpp:856
TV::PopPreviousChannel
void PopPreviousChannel(bool ImmediateChange)
Definition: tv_play.cpp:6272
TV::m_queuedTranscode
bool m_queuedTranscode
Definition: tv_play.h:561
kDisplayNUVTeletextCaptions
@ kDisplayNUVTeletextCaptions
Definition: videoouttypes.h:13
StringDeque
std::deque< QString > StringDeque
Definition: playercontext.h:47
MythTVMenu::GetRoot
QDomElement GetRoot() const
Definition: mythtvmenu.cpp:103
TV::m_posThreadPool
MThreadPool * m_posThreadPool
Definition: tv_play.h:520
TV::IsTunable
static bool IsTunable(uint ChanId)
Definition: tv_play.cpp:6766
MythCoreContext::RegisterForPlayback
void RegisterForPlayback(QObject *sender, PlaybackStartCb method)
Definition: mythcorecontext.cpp:1964
TVPlaybackState::DialogQuit
void DialogQuit()
TV::kInputKeysMax
static const uint kInputKeysMax
Definition: tv_play.h:751
ACTION_SEEKRWND
#define ACTION_SEEKRWND
Definition: tv_actions.h:42
TVBrowseHelper::BrowseStop
void BrowseStop()
Definition: tvbrowsehelper.cpp:60
TV::m_ffRewReverse
bool m_ffRewReverse
Definition: tv_play.h:542
TV::SetLastProgram
void SetLastProgram(const ProgramInfo *ProgInfo)
Definition: tv_play.cpp:10413
TV::m_guest_stars
QVector< string_pair > m_guest_stars
Definition: tv_play.h:577
kDisplayAVSubtitle
@ kDisplayAVSubtitle
Definition: videoouttypes.h:15
kOSDFunctionalType_TimeStretchAdjust
@ kOSDFunctionalType_TimeStretchAdjust
Definition: osd.h:49
UpdateBrowseInfoEvent
Definition: mythevent.h:119
ACTION_ZOOMVERTICALOUT
#define ACTION_ZOOMVERTICALOUT
Definition: tv_actions.h:140
OSD::SetFunctionalWindow
void SetFunctionalWindow(const QString &Window, enum OSDFunctionalType Type)
Definition: osd.cpp:667
get_chanid
static uint get_chanid(const PlayerContext *ctx, uint cardid, const QString &channum)
Definition: tv_play.cpp:6078
kState_Error
@ kState_Error
Error State, if we ever try to enter this state errored is set.
Definition: tv.h:57
MythVideoBoundsState::m_adjustFillMode
AdjustFillMode m_adjustFillMode
Definition: mythplayerstate.h:104
kZoomOut
@ kZoomOut
Definition: videoouttypes.h:46
PlayerContext::m_playingLen
std::chrono::seconds m_playingLen
Initial CalculateLength()
Definition: playercontext.h:118
TV::m_asInputMode
bool m_asInputMode
Are we in Arbitrary seek input mode?
Definition: tv_play.h:602
ACTION_ENABLEEXTTEXT
#define ACTION_ENABLEEXTTEXT
Definition: tv_actions.h:71
kState_WatchingLiveTV
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:66
next_picattr
PictureAttribute next_picattr(PictureAttributeSupported Supported, PictureAttribute Attribute)
Definition: videoouttypes.h:350
TV::m_lcdTimerId
volatile int m_lcdTimerId
Definition: tv_play.h:682
ACTION_SETBRIGHTNESS
#define ACTION_SETBRIGHTNESS
Definition: tv_actions.h:59
TV::ProcessSmartChannel
bool ProcessSmartChannel(QString &InputStr)
Definition: tv_play.cpp:5882
MythMainWindow::GetPaintWindow
QWidget * GetPaintWindow()
Definition: mythmainwindow.cpp:267
TV::kEndOfRecPromptCheckFrequency
static const std::chrono::milliseconds kEndOfRecPromptCheckFrequency
Definition: tv_play.h:767
TVPlaybackState::ToggleMoveBottomLine
void ToggleMoveBottomLine()
ProgramInfo::GetPlaybackGroup
QString GetPlaybackGroup(void) const
Definition: programinfo.h:421
TV::HandleEndOfPlaybackTimerEvent
void HandleEndOfPlaybackTimerEvent()
Definition: tv_play.cpp:2826
jobqueue.h
ACTION_STOP
#define ACTION_STOP
Definition: tv_actions.h:8
ACTION_TOGGLESLEEP
#define ACTION_TOGGLESLEEP
Definition: tv_actions.h:29
MythPlayer::SwitchAngle
virtual bool SwitchAngle(int)
Definition: mythplayer.h:172
kPictureAttribute_MIN
@ kPictureAttribute_MIN
Definition: videoouttypes.h:106
TVPlaybackState::ResetAudio
void ResetAudio()
TV::AddKeyToInputQueue
void AddKeyToInputQueue(char Key)
Definition: tv_play.cpp:5835
OSD_DLG_VIDEOEXIT
static constexpr const char * OSD_DLG_VIDEOEXIT
Definition: osd.h:16
toTypeString
QString toTypeString(PictureAdjustType type)
Definition: tv.cpp:49
kStartTVByNetworkCommand
@ kStartTVByNetworkCommand
Definition: tv_play.h:116
TRANSITION
#define TRANSITION(ASTATE, BSTATE)
Definition: tv_play.cpp:1962
TV::HandleOSDClosed
void HandleOSDClosed(int OSDType)
Definition: tv_play.cpp:7748
ACTION_TVPOWEROFF
static constexpr const char * ACTION_TVPOWEROFF
Definition: mythuiactions.h:24
ACTION_DISABLEFORCEDSUBS
#define ACTION_DISABLEFORCEDSUBS
Definition: tv_actions.h:69
TV::SleepTimerInfo::milliseconds
std::chrono::milliseconds milliseconds
Definition: tv_play.cpp:985
TVPlaybackState::m_videoBoundsState
MythVideoBoundsState m_videoBoundsState
Definition: tvplaybackstate.h:108
MythPlayer::GetEditMode
bool GetEditMode(void) const
Definition: mythplayer.h:315
ChannelUtil::GetChannels
static ChannelInfoList GetChannels(uint sourceid, bool visible_only, const QString &group_by=QString(), uint channel_groupid=0)
Definition: channelutil.h:251
TV::PlaybackMenuInit
void PlaybackMenuInit(const MythTVMenu &Menu)
Definition: tv_play.cpp:9274
PlayerContext::IsSameProgram
bool IsSameProgram(const ProgramInfo &p) const
Definition: playercontext.cpp:378
TV::ShowOSDStopWatchingRecording
void ShowOSDStopWatchingRecording()
Definition: tv_play.cpp:10209
kState_ChangingState
@ kState_ChangingState
This is a placeholder state which we never actually enter, but is returned by GetState() when we are ...
Definition: tv.h:92
MythPlayer::GetChapterTimes
virtual void GetChapterTimes(QList< std::chrono::seconds > &times)
Definition: mythplayer.cpp:1827
TV::m_dbAutoSetWatched
bool m_dbAutoSetWatched
Definition: tv_play.h:527
TV::m_switchToRec
RemoteEncoder * m_switchToRec
Main recorder to use after a successful SwitchCards() call.
Definition: tv_play.h:650
OSD_DLG_NAVIGATE
static constexpr const char * OSD_DLG_NAVIGATE
Definition: osd.h:26
MythDVDBuffer::NumPartsInTitle
int NumPartsInTitle(void) const
Definition: mythdvdbuffer.cpp:1198
TvPlayWindow::UpdateProgress
void UpdateProgress(void)
Definition: tv_play_win.cpp:44
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
MythPlayer::GetCurrentAngle
virtual int GetCurrentAngle(void) const
Definition: mythplayer.h:225
EMBEDRETURNVOIDEPG
void(*)(uint, const QString &, const QDateTime, TV *, bool, bool, int) EMBEDRETURNVOIDEPG
Definition: tv_play.h:60
kPictureAttribute_Hue
@ kPictureAttribute_Hue
Definition: videoouttypes.h:110
clamp
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:206
TVPlaybackState::ChangeAudioOffset
void ChangeAudioOffset(std::chrono::milliseconds Delta, std::chrono::milliseconds Value=-9999ms)
TVPlaybackState::InitialisePlayerState
void InitialisePlayerState()
MythVideoColourState::m_supportedAttributes
PictureAttributeSupported m_supportedAttributes
Definition: mythplayerstate.h:122
kOSDFunctionalType_SubtitleDelayAdjust
@ kOSDFunctionalType_SubtitleDelayAdjust
Definition: osd.h:52
TV::m_allowRerecord
bool m_allowRerecord
User wants to rerecord the last video if deleted.
Definition: tv_play.h:559
TV::FillOSDMenuJumpRec
void FillOSDMenuJumpRec(const QString &Category="", int Level=0, const QString &Selected="")
Definition: tv_play.cpp:9469
ACTION_ZOOMRIGHT
#define ACTION_ZOOMRIGHT
Definition: tv_actions.h:134
TV::IsBookmarkAllowed
bool IsBookmarkAllowed()
Definition: tv_play.cpp:10168
mythuistatetracker.h
PlayerContext::UnlockDeletePlayer
void UnlockDeletePlayer(const char *file, int line) const
allow player to be deleted.
Definition: playercontext.cpp:277
TVBrowseHelper
Definition: tvbrowsehelper.h:45
MythPlayer::GetAllowForcedSubtitles
bool GetAllowForcedSubtitles(void) const
Definition: mythplayer.h:204
kZoom_END
@ kZoom_END
Definition: videoouttypes.h:57
TV::ARBSEEK_SET
@ ARBSEEK_SET
Definition: tv_play.h:372
PlayerContext::PopPreviousChannel
QString PopPreviousChannel(void)
Definition: playercontext.cpp:205
kDisableAutoExpire
@ kDisableAutoExpire
Definition: programtypes.h:193
MythDisplay
Definition: mythdisplay.h:22
PlayerContext::m_lastSignalUIInfoTime
MythTimer m_lastSignalUIInfoTime
Definition: playercontext.h:158
kZoomRight
@ kZoomRight
Definition: videoouttypes.h:54
AutoDeleteDeque::end
iterator end(void)
Definition: autodeletedeque.h:51
TV::m_myWindow
TvPlayWindow * m_myWindow
Our screen, if it exists.
Definition: tv_play.h:658
PlayerContext::m_tvchain
LiveTVChain * m_tvchain
Definition: playercontext.h:115
TV::ShowLCDChannelInfo
void ShowLCDChannelInfo()
Definition: tv_play.cpp:6696
kAdjustingPicture_Recording
@ kAdjustingPicture_Recording
Definition: tv.h:128
ProgramInfo::QueryTotalFrames
int64_t QueryTotalFrames(void) const
If present in recording this loads total frames of the main video stream from database's stream marku...
Definition: programinfo.cpp:4659
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:919
ACTION_SETBOOKMARK
#define ACTION_SETBOOKMARK
Definition: tv_actions.h:34
TVBrowseHelper::BrowseDispInfo
void BrowseDispInfo(const BrowseInfo &Browseinfo)
Definition: tvbrowsehelper.cpp:140
TVPlaybackState::DisableEdit
void DisableEdit(int HowToSave)
TV::DVDJumpForward
void DVDJumpForward()
Definition: tv_play.cpp:10130
TV::HandleOSDAskAllow
void HandleOSDAskAllow(const QString &Action)
Definition: tv_play.cpp:1872
OSD_WIN_INPUT
static constexpr const char * OSD_WIN_INPUT
Definition: osd.h:30
TV::ContextIsPaused
bool ContextIsPaused(const char *File, int Location)
Definition: tv_play.cpp:10461
TV::m_askAllowLock
QRecursiveMutex m_askAllowLock
Definition: tv_play.h:571
MythDB::getMythDB
static MythDB * getMythDB()
Definition: mythdb.cpp:30
ProgramInfo::GetOriginalAirDate
QDate GetOriginalAirDate(void) const
Definition: programinfo.h:432
OSD_DLG_EDITOR
static constexpr const char * OSD_DLG_EDITOR
Definition: osd.h:23
ACTION_DISABLESUBS
#define ACTION_DISABLESUBS
Definition: tv_actions.h:66
kOSDTimeout_Long
@ kOSDTimeout_Long
Definition: osd.h:61
LOC
#define LOC
Definition: tv_play.cpp:81
ProgramInfo::SaveAutoExpire
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".
Definition: programinfo.cpp:3414
TVPlaybackState::AdjustSubtitleDelay
void AdjustSubtitleDelay(std::chrono::milliseconds Delta)
ACTION_MENUTEXT
#define ACTION_MENUTEXT
Definition: tv_actions.h:82
SysEventHandleAction
static bool SysEventHandleAction(MythMainWindow *MainWindow, QKeyEvent *e, const QStringList &actions)
Definition: tv_play.cpp:3209
TVPlaybackState::m_captionsState
MythCaptionsState m_captionsState
Definition: tvplaybackstate.h:107
kState_WatchingRecording
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
Definition: tv.h:83
TV::IsTVRunning
static bool IsTVRunning()
Check whether media is currently playing.
Definition: tv_play.cpp:173
TV::kIdleTimerDialogTimeout
static const std::chrono::milliseconds kIdleTimerDialogTimeout
Definition: tv_play.h:761
mythmediabuffer.h
TV::GetNumChapters
int GetNumChapters()
Definition: tv_play.cpp:5389
channelutil.h
RemoteEncoder::CheckChannelPrefix
bool CheckChannelPrefix(const QString &prefix, uint &complete_valid_channel_on_rec, bool &is_extra_char_useful, QString &needed_spacer)
Checks a prefix against the channels in the DB.
Definition: remoteencoder.cpp:653
TV::HandleOSDInfo
void HandleOSDInfo(const QString &Action)
Definition: tv_play.cpp:8539
kStartTVIgnoreLastPlayPos
@ kStartTVIgnoreLastPlayPos
Definition: tv_play.h:119
TV::m_dbContinueEmbedded
bool m_dbContinueEmbedded
Definition: tv_play.h:533
MythMediaBuffer::IgnoreLiveEOF
void IgnoreLiveEOF(bool Ignore)
Tells RingBuffer whether to ignore the end-of-file.
Definition: mythmediabuffer.cpp:1828
TVPlaybackState::SetTrack
void SetTrack(uint Type, uint TrackNo)
tvremoteutil.h
InputInfo::m_inputId
uint m_inputId
unique key in DB for this input
Definition: inputinfo.h:49
MythMainWindow::PushDrawDisabled
uint PushDrawDisabled()
Definition: mythmainwindow.cpp:987
TVBrowseHelper::GetBrowsedInfo
BrowseInfo GetBrowsedInfo() const
Definition: tvbrowsehelper.cpp:195
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:39
TV::CalcPlayerSliderPosition
bool CalcPlayerSliderPosition(osdInfo &info, bool paddedFields=false) const
Definition: tv_play.cpp:6667
MythTVMenu::Translate
QString Translate(const QString &Text) const
Definition: mythtvmenu.cpp:118
MythPlayer::JumpChapter
void JumpChapter(int chapter)
Definition: mythplayer.cpp:913
kAspect_14_9
@ kAspect_14_9
Definition: videoouttypes.h:66
TV::ToggleTimeStretch
void ToggleTimeStretch()
Definition: tv_play.cpp:7054
MythPlayer::GetNumChapters
virtual int GetNumChapters(void)
Definition: mythplayer.cpp:1813
TV::HasQueuedInput
bool HasQueuedInput() const
Definition: tv_play.h:339
TV::NextPictureAdjustType
PictureAttribute NextPictureAdjustType(PictureAdjustType Type, PictureAttribute Attr)
Definition: tv_play.cpp:7777
ACTION_UP
static constexpr const char * ACTION_UP
Definition: mythuiactions.h:16
TV::m_dbBrowseAlways
bool m_dbBrowseAlways
Definition: tv_play.h:534
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:913
TV::ActivePostQHandleAction
bool ActivePostQHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:4193
ACTION_ZOOMASPECTUP
#define ACTION_ZOOMASPECTUP
Definition: tv_actions.h:135
TV::ChannelEditAutoFill
void ChannelEditAutoFill(InfoMap &Info)
Automatically fills in as much information as possible.
Definition: tv_play.cpp:8048
MythPlayer::GetCurrentTitle
virtual int GetCurrentTitle(void) const
Definition: mythplayer.h:219
kState_WatchingPreRecorded
@ kState_WatchingPreRecorded
Watching Pre-recorded is a TV only state for when we are watching a pre-existing recording.
Definition: tv.h:70
ACTION_JUMPBKMRK
#define ACTION_JUMPBKMRK
Definition: tv_actions.h:46
AutoDeleteDeque< ProgramInfo * >
kScan_Interlaced
@ kScan_Interlaced
Definition: videoouttypes.h:98
kMenuIdCutlist
@ kMenuIdCutlist
Definition: mythtvmenu.h:41
MythBDPlayer
Definition: mythbdplayer.h:10
MythPlayer::GetError
QString GetError(void) const
Definition: mythplayer.cpp:1953
mythburn.chapterLength
int chapterLength
Definition: mythburn.py:191
mthreadpool.h
PlayerContext::LockState
void LockState(void) const
Definition: playercontext.cpp:287
PlayerContext::m_pseudoLiveTVState
PseudoState m_pseudoLiveTVState
Definition: playercontext.h:136
TV::ReturnOSDLock
void ReturnOSDLock() const
Definition: tv_play.cpp:10489
MythEditorState::m_frameInDelete
bool m_frameInDelete
Definition: mythplayerstate.h:157
ACTION_3DSIDEBYSIDEDISCARD
#define ACTION_3DSIDEBYSIDEDISCARD
Definition: tv_actions.h:127
mythuihelper.h
MythOSDDialogData::m_buttons
std::vector< MythOSDDialogButton > m_buttons
Definition: osd.h:87
tv_i18n
static QString tv_i18n(const QString &msg)
Definition: tv_play.cpp:1968
TV::HandleLCDTimerEvent
bool HandleLCDTimerEvent()
Definition: tv_play.cpp:2638
kDisplayTextSubtitle
@ kDisplayTextSubtitle
Definition: videoouttypes.h:18
TV::HideOSDWindow
void HideOSDWindow(const char *window)
Definition: tv_play.cpp:6680
TV::m_ccInputMode
bool m_ccInputMode
Are we in CC/Teletext page/stream selection mode?
Definition: tv_play.h:598
TV::ClearInputQueues
void ClearInputQueues(bool Hideosd)
Clear channel key buffer of input keys.
Definition: tv_play.cpp:5820
TV::HandleOSDChannelEdit
bool HandleOSDChannelEdit(const QString &Action)
Processes channel editing key.
Definition: tv_play.cpp:8012
TV::LiveTV
bool LiveTV(bool ShowDialogs, const ChannelInfoList &Selection)
Starts LiveTV.
Definition: tv_play.cpp:1531
ACTION_SAVEMAP
#define ACTION_SAVEMAP
Definition: tv_actions.h:88
recordinginfo.h
kPseudoNormalLiveTV
@ kPseudoNormalLiveTV
Definition: playercontext.h:42
mythbdbuffer.h
kLiveTVAutoExpire
@ kLiveTVAutoExpire
Definition: programtypes.h:196
ACTION_MENUBLUE
#define ACTION_MENUBLUE
Definition: tv_actions.h:80
LiveTVChain::GetInputType
QString GetInputType(int pos=-1) const
Definition: livetvchain.cpp:698
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:373
GET_KEY
static QString GET_KEY(const QString &Context, const QString &Action)
Definition: mythmainwindow.h:182
MThreadPool
Definition: mthreadpool.h:18
AspectOverrideMode
AspectOverrideMode
Definition: videoouttypes.h:60
TV::m_jumpToProgram
bool m_jumpToProgram
Definition: tv_play.h:636
TVPlaybackState::EnableTeletext
void EnableTeletext(int Page=0x100)
ProgramInfo::GetEpisode
uint GetEpisode(void) const
Definition: programinfo.h:368
livetvchain.h
kDisplayCC608
@ kDisplayCC608
Definition: videoouttypes.h:16
TV::ReturnPlayerLock
void ReturnPlayerLock() const
Definition: tv_play.cpp:10506
kPictureAttributeSupported_None
@ kPictureAttributeSupported_None
Definition: videoouttypes.h:118
ACTION_SETVOLUME
#define ACTION_SETVOLUME
Definition: tv_actions.h:112
Channum
Definition: channelsettings.cpp:118
ProgramInfo::QueryAutoExpire
AutoExpireType QueryAutoExpire(void) const
Returns "autoexpire" field from "recorded" table.
Definition: programinfo.cpp:3469
BrowseInfo
Definition: tvbrowsehelper.h:23
MythMediaBuffer::IsBookmarkAllowed
virtual bool IsBookmarkAllowed(void)
Definition: mythmediabuffer.h:136
comp_title
static bool comp_title(const ProgramInfo *a, const ProgramInfo *b)
Definition: tv_play.cpp:107
kTrackTypeCount
@ kTrackTypeCount
Definition: decoderbase.h:38
kNoFlags
@ kNoFlags
Definition: mythplayer.h:66
TV::ShowOSDPromptDeleteRecording
void ShowOSDPromptDeleteRecording(const QString &Title, bool Force=false)
Definition: tv_play.cpp:10249
MythTVMenuItemContext::AddButton
bool AddButton(MythOSDDialogData *Menu, bool Active, const QString &Action, const QString &DefaultTextActive, const QString &DefaultTextInactive, bool IsMenu, const QString &TextArg) const
Definition: mythtvmenu.cpp:14
TV::kNextSource
static const uint kNextSource
Definition: tv_play.h:752
MythVideoColourState::GetValue
int GetValue(PictureAttribute Attribute)
Definition: mythplayerstate.cpp:63
MythPlayer::SetWatchingRecording
void SetWatchingRecording(bool mode)
Definition: mythplayer.cpp:120
ChannelUtil::GetIcon
static QString GetIcon(uint chanid)
Definition: channelutil.cpp:1271
kOSDFunctionalType_SmartForward
@ kOSDFunctionalType_SmartForward
Definition: osd.h:48
ProgramInfo::kTitleSubtitle
@ kTitleSubtitle
Definition: programinfo.h:514
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
RecordingRule::LoadTemplate
bool LoadTemplate(const QString &title, const QString &category="Default", const QString &categoryType="Default")
Definition: recordingrule.cpp:277
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:407
TV::s_sleepTimes
static const std::vector< SleepTimerInfo > s_sleepTimes
Definition: tv_play.h:583
TV::OverrideScan
void OverrideScan(FrameScanType Scan)
Definition: tv_play.cpp:9748
TV::VolumeChange
void VolumeChange(bool Up, int NewVolume=-1)
Definition: tv_play.cpp:7022
TV::GetCurrentAngle
int GetCurrentAngle()
Definition: tv_play.cpp:5462
TV::m_exitPlayerTimerId
volatile int m_exitPlayerTimerId
Definition: tv_play.h:694
TV::m_lastLockSeenTime
QDateTime m_lastLockSeenTime
Definition: tv_play.h:626
mythmiscutil.h
TV::m_progListsLock
QMutex m_progListsLock
Definition: tv_play.h:573
MythDisplay::NextModeIsLarger
bool NextModeIsLarger(QSize Size)
Check whether the next mode is larger in size than the current mode.
Definition: mythdisplay.cpp:678
TVPlaybackState::ResizeScreenForVideo
void ResizeScreenForVideo(QSize Size={})
MythTVMenu::m_id
MenuTypeId m_id
Definition: mythtvmenu.h:112
kScheduleProgramList
@ kScheduleProgramList
Definition: tv_play.h:100
MythTVMenuItemContext::m_menu
const MythTVMenu & m_menu
Definition: mythtvmenu.h:65
ACTION_MENUCOMPACT
#define ACTION_MENUCOMPACT
Definition: tv_actions.h:6
kAdjustingPicture_None
@ kAdjustingPicture_None
Definition: tv.h:125
ACTION_GETSTATUS
static constexpr const char * ACTION_GETSTATUS
Definition: mythuiactions.h:27
FUNC_TV
@ FUNC_TV
Definition: lcddevice.h:164
TV::UpdateLCD
void UpdateLCD()
Definition: tv_play.cpp:6688
TV::m_subtitleDelayAdjustment
bool m_subtitleDelayAdjustment
True if subtitle delay is turned on.
Definition: tv_play.h:554
ACTION_OSDNAVIGATION
#define ACTION_OSDNAVIGATION
Definition: tv_actions.h:55
ACTION_RIGHT
static constexpr const char * ACTION_RIGHT
Definition: mythuiactions.h:19
SavePositionThread::m_framesPlayed
uint64_t m_framesPlayed
Definition: tv_play.h:789
TVPlaybackState::ChangeUpmix
void ChangeUpmix(bool Enable, bool Toggle=false)
TV::GetPosThreadPool
MThreadPool * GetPosThreadPool()
Definition: tv_play.cpp:10526
ACTION_TOGGLEVISUALISATION
#define ACTION_TOGGLEVISUALISATION
Definition: tv_actions.h:117
TV::m_asInputTimerId
volatile int m_asInputTimerId
Definition: tv_play.h:686
RecordingInfo::LoadStatus
LoadStatus
Definition: recordinginfo.h:180
TV::m_dbUseGuiSizeForTv
bool m_dbUseGuiSizeForTv
Definition: tv_play.h:530
RemoteEncoder::SetChannel
void SetChannel(const QString &channel)
Definition: remoteencoder.cpp:464
MythConfirmationDialog
Dialog asking for user confirmation. Ok and optional Cancel button.
Definition: mythdialogbox.h:271
ProgramInfo::ToStringList
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
Definition: programinfo.cpp:1276
OptionalCaptionEnabled
bool OptionalCaptionEnabled(uint Captions)
Return whether any optional captions are enabled.
Definition: videoouttypes.h:30
add_spacer
static QString add_spacer(const QString &chan, const QString &spacer)
Definition: tv_play.cpp:5875
MythVideoScanTracker::SetScanOverride
void SetScanOverride(FrameScanType Scan)
Definition: mythvideoscantracker.cpp:53
ProgramInfo::GetSeason
uint GetSeason(void) const
Definition: programinfo.h:367
mythcorecontext.h
SendMythSystemPlayEvent
void SendMythSystemPlayEvent(const QString &msg, const ProgramInfo *pginfo)
Definition: mythsystemevent.cpp:352
TV::timerEvent
void timerEvent(QTimerEvent *Event) override
Definition: tv_play.cpp:2419
TV::m_sigMonMode
bool m_sigMonMode
Are we in signal monitoring mode?
Definition: tv_play.h:556
TV::m_ignoreKeyPresses
bool m_ignoreKeyPresses
should we ignore keypresses
Definition: tv_play.h:667
cardutil.h
Clear
#define Clear(a)
Definition: audiooutputopensles.cpp:54
ACTION_MENUGREEN
#define ACTION_MENUGREEN
Definition: tv_actions.h:78
TV::CreatePlayer
bool CreatePlayer(TVState State, bool Muted=false)
Definition: tv_play.cpp:198
playercontext.h
TV::GetPlayerContext
PlayerContext * GetPlayerContext()
Return a pointer to TV::m_playerContext.
Definition: tv_play.cpp:193
TV::HandleOSDIdle
void HandleOSDIdle(const QString &Action)
Definition: tv_play.cpp:7217
ProgramInfo::QueryIsEditing
bool QueryIsEditing(void) const
Queries "recorded" table for its "editing" field and returns true if it is set to true.
Definition: programinfo.cpp:3124
kState_WatchingVideo
@ kState_WatchingVideo
Watching Video is the state when we are watching a video and is not a dvd or BD.
Definition: tv.h:74
kPlayerInUseID
const QString kPlayerInUseID
Definition: programtypes.cpp:16
MythUIScreenBounds::GetScreenRect
QRect GetScreenRect()
Definition: mythuiscreenbounds.cpp:214
MythDisplay::SwitchToGUI
bool SwitchToGUI(bool Wait=false)
Switches to the GUI resolution.
Definition: mythdisplay.cpp:780
TVPlaybackState::ChangeOSDPositionUpdates
void ChangeOSDPositionUpdates(bool Enable)
kZoomHome
@ kZoomHome
Definition: videoouttypes.h:44
PlayerContext::m_lastSignalMsgTime
MythTimer m_lastSignalMsgTime
Definition: playercontext.h:156
kPictureAttribute_Range
@ kPictureAttribute_Range
Definition: videoouttypes.h:111
JOB_STOP
@ JOB_STOP
Definition: jobqueue.h:54
TV::m_channelGroupId
volatile int m_channelGroupId
Definition: tv_play.h:675
kTrackTypeVideo
@ kTrackTypeVideo
Definition: decoderbase.h:30
MythMainWindow::PopDrawDisabled
uint PopDrawDisabled()
Definition: mythmainwindow.cpp:996
Name
Definition: channelsettings.cpp:103
ProgramInfo::SetIgnoreBookmark
void SetIgnoreBookmark(bool ignore)
If "ignore" is true GetBookmark() will return 0, otherwise GetBookmark() will return the bookmark pos...
Definition: programinfo.h:563
TV::EditSchedule
void EditSchedule(int EditType=kScheduleProgramGuide, const QString &arg="")
Definition: tv_play.cpp:7014
TV::SwitchSource
void SwitchSource(uint Direction)
Definition: tv_play.cpp:5558
ProgramInfo::IsFileReadable
bool IsFileReadable(void)
Attempts to ascertain if the main file for this ProgramInfo is readable.
Definition: programinfo.cpp:5060
MythPlayerOverlayUI::UnlockOSD
void UnlockOSD()
Definition: mythplayeroverlayui.h:26
TV::m_tvmJumprecBackHack
QVariant m_tvmJumprecBackHack
Definition: tv_play.h:741
toTitleString
QString toTitleString(PictureAdjustType type)
Definition: tv.cpp:62
TV::m_tvmIsOn
bool m_tvmIsOn
Definition: tv_play.h:738
MythPlayer::GetTitleName
virtual QString GetTitleName(int) const
Definition: mythplayer.h:221
MythDVDBuffer::GetNameAndSerialNum
bool GetNameAndSerialNum(QString &Name, QString &SerialNumber) override
Get the dvd title and serial num.
Definition: mythdvdbuffer.cpp:1917
ProgramInfo::GetPlaybackURL
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false)
Returns filename or URL to be used to play back this recording.
Definition: programinfo.cpp:2567
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
ACTION_JUMPTODVDROOTMENU
#define ACTION_JUMPTODVDROOTMENU
Definition: tv_actions.h:48
ChannelUtil::GetSourceIDForChannel
static uint GetSourceIDForChannel(uint chanid)
Definition: channelutil.cpp:808
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
MythAudioState::m_canUpmix
bool m_canUpmix
Definition: mythplayerstate.h:57
kOSDFunctionalType_AudioSyncAdjust
@ kOSDFunctionalType_AudioSyncAdjust
Definition: osd.h:50
TVPlaybackState::m_editorState
MythEditorState m_editorState
Definition: tvplaybackstate.h:111
ACTION_JUMPTOPOPUPMENU
#define ACTION_JUMPTOPOPUPMENU
Definition: tv_actions.h:49
TV::m_lockTimerOn
bool m_lockTimerOn
Definition: tv_play.h:625
TV::kErrorRecoveryCheckFrequency
static const std::chrono::milliseconds kErrorRecoveryCheckFrequency
Definition: tv_play.h:766
PlayerContext::SetPlayer
void SetPlayer(MythPlayer *newplayer)
Definition: playercontext.cpp:458
TV::UpdateChannelList
void UpdateChannelList(int GroupID)
update the channel list with channels from the selected channel group
Definition: tv_play.cpp:1343
RemoteEncoder::StopLiveTV
void StopLiveTV(void)
Tells TVRec to stop a "Live TV" recorder.
Definition: remoteencoder.cpp:370
TV::PlaybackExiting
void PlaybackExiting(TV *Player)
ProgInfo
Definition: programdata.h:226
DialogCompletionEvent
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
Definition: mythdialogbox.h:40
MythPlayer::TranslatePositionMsToFrame
uint64_t TranslatePositionMsToFrame(std::chrono::milliseconds position, bool use_cutlist) const
Definition: mythplayer.h:257
ActionToStereoscopic
StereoscopicMode ActionToStereoscopic(const QString &Action)
Definition: mythtvactionutils.h:18
RemoteRequestFreeRecorderFromList
RemoteEncoder * RemoteRequestFreeRecorderFromList(const QStringList &qualifiedRecorders, uint excluded_input)
Definition: tvremoteutil.cpp:265
TV::m_player
MythPlayerUI * m_player
Definition: tv_play.h:642
MythCoreContext::emitTVPlaybackPaused
void emitTVPlaybackPaused(void)
Definition: mythcorecontext.h:274
ProgramInfo::IsVideo
bool IsVideo(void) const
Definition: programinfo.h:490
CHANNEL_DIRECTION_UP
@ CHANNEL_DIRECTION_UP
Definition: tv.h:33
RemoteEncoder::GetChannelInfo
void GetChannelInfo(InfoMap &infoMap, uint chanid=0)
Definition: remoteencoder.cpp:725
PlayerContext::SetRingBuffer
void SetRingBuffer(MythMediaBuffer *Buffer)
Definition: playercontext.cpp:499
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:142
TV::PauseLiveTV
void PauseLiveTV()
Used in ChangeChannel() to temporarily stop video output.
Definition: tv_play.cpp:9980
TVPlaybackState::m_audioState
MythAudioState m_audioState
Definition: tvplaybackstate.h:106
TV::MenuStrings
static void MenuStrings()
Definition: tv_play.cpp:9402
TV::m_lcdCallsign
QString m_lcdCallsign
Definition: tv_play.h:655
MythVideoScanTracker::GetScanTypeWithOverride
FrameScanType GetScanTypeWithOverride() const
Definition: mythvideoscantracker.cpp:104
MythVideoBoundsState::m_manualVertScale
float m_manualVertScale
Definition: mythplayerstate.h:107
ACTION_REVEAL
#define ACTION_REVEAL
Definition: tv_actions.h:103
kScan_Detect
@ kScan_Detect
Definition: videoouttypes.h:97
TVPlaybackState::ChangeMuteState
void ChangeMuteState(bool CycleChannels=false)
PlayerContext::m_ffRewSpeed
int m_ffRewSpeed
Caches value of m_ffRewSpeeds[m_ffRewIndex].
Definition: playercontext.h:126
TV::m_speedChangeTimerId
volatile int m_speedChangeTimerId
Definition: tv_play.h:692
TVPlaybackState::EmbedPlayback
void EmbedPlayback(bool Embed, const QRect &Rect={})
TV::FillOSDMenuCastButton
static void FillOSDMenuCastButton(MythOSDDialogData &dialog, const QVector< string_pair > &people)
Definition: tv_play.cpp:9644
TV::DoTogglePauseStart
float DoTogglePauseStart()
Definition: tv_play.cpp:4828
TV::RunViewScheduledPtr
static EMBEDRETURNVOID RunViewScheduledPtr
Definition: tv_play.h:199
kTrackTypeTeletextCaptions
@ kTrackTypeTeletextCaptions
Definition: decoderbase.h:34
ACTION_ZOOMLEFT
#define ACTION_ZOOMLEFT
Definition: tv_actions.h:133
TV::event
bool event(QEvent *Event) override
This handles all standard events.
Definition: tv_play.cpp:3037
GetNotificationCenter
MythNotificationCenter * GetNotificationCenter(void)
Definition: mythmainwindow.cpp:124
MythTVMenu
Definition: mythtvmenu.h:83
TVState
TVState
TVState is an enumeration of the states used by TV and TVRec.
Definition: tv.h:53
ACTION_DAYRIGHT
#define ACTION_DAYRIGHT
Definition: tv_actions.h:10
PlayerContext::DequeueNextState
TVState DequeueNextState(void)
Definition: playercontext.cpp:315
ProgramInfo::IsVideoDVD
bool IsVideoDVD(void) const
Definition: programinfo.h:348
ACTION_TOGGLERECCONTROLS
#define ACTION_TOGGLERECCONTROLS
Definition: tv_actions.h:22
TV::m_sleepDialogTimerId
int m_sleepDialogTimerId
Timer for sleep dialog.
Definition: tv_play.h:588
PlayerContext::InStateChange
bool InStateChange(void) const
Definition: playercontext.cpp:297
kPictureAttributeSupported_Hue
@ kPictureAttributeSupported_Hue
Definition: videoouttypes.h:122
TV::SetFuncPtr
static void SetFuncPtr(const char *Name, void *Pointer)
Import pointers to functions used to embed the TV window into other containers e.g.
Definition: tv_play.cpp:477
TVBrowseHelper::TV
friend class TV
Definition: tvbrowsehelper.h:47
DialogCompletionEvent::kEventType
static const Type kEventType
Definition: mythdialogbox.h:56
kZoomIn
@ kZoomIn
Definition: videoouttypes.h:45
CardUtil::GetSourceID
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1948
OSD::HideWindow
void HideWindow(const QString &Window) override
Definition: osd.cpp:675
ACTION_JUMPFFWD
#define ACTION_JUMPFFWD
Definition: tv_actions.h:44
ACTION_TOGGLEBOOKMARK
#define ACTION_TOGGLEBOOKMARK
Definition: tv_actions.h:35
TV::m_lcdTitle
QString m_lcdTitle
Definition: tv_play.h:653
TV::DiscMenuHandleAction
bool DiscMenuHandleAction(const QStringList &Actions) const
Definition: tv_play.cpp:3785
kPictureAttribute_MAX
@ kPictureAttribute_MAX
Definition: videoouttypes.h:113
TV::m_saveLastPlayPosTimerId
volatile int m_saveLastPlayPosTimerId
Definition: tv_play.h:695
ACTION_DAYLEFT
#define ACTION_DAYLEFT
Definition: tv_actions.h:9
MThread::exit
void exit(int retcode=0)
Use this to exit from the thread if you are using a Qt event loop.
Definition: mthread.cpp:278
TV::UpdateOSDStatus
void UpdateOSDStatus(const QString &Title, const QString &Desc, const QString &Value, int Type, const QString &Units, int Position=0, enum OSDTimeout Timeout=kOSDTimeout_Med)
Definition: tv_play.cpp:6411
TV::m_mainWindow
MythMainWindow * m_mainWindow
Definition: tv_play.h:519
kAudioMuted
@ kAudioMuted
Definition: mythplayer.h:74
MythTVMenuItemContext::m_category
MenuCategory m_category
Definition: mythtvmenu.h:67
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:104
ProgramInfo::IsVideoFile
bool IsVideoFile(void) const
Definition: programinfo.h:346
OK
static constexpr int OK
Definition: dvbci.cpp:69
TV::m_channelGroupLock
QMutex m_channelGroupLock
Lock necessary when modifying channel group variables.
Definition: tv_play.h:674
TV::ToggleSleepTimer
void ToggleSleepTimer()
Definition: tv_play.cpp:7120
TV::UpdateOSDSignal
void UpdateOSDSignal(const QStringList &List)
Updates Signal portion of OSD...
Definition: tv_play.cpp:6450
TV::DoTogglePictureAttribute
void DoTogglePictureAttribute(PictureAdjustType Type)
Definition: tv_play.cpp:7799
RemoteCancelNextRecording
void RemoteCancelNextRecording(uint inputid, bool cancel)
Definition: tvremoteutil.cpp:129
TV::m_weDisabledGUI
bool m_weDisabledGUI
true if this instance disabled MythUI drawing.
Definition: tv_play.h:664
MythPlayer::SetCommBreakMap
void SetCommBreakMap(const frm_dir_map_t &NewMap)
Definition: mythplayer.cpp:1728
TV::NormalSpeed
void NormalSpeed()
Definition: tv_play.cpp:5174
PlayerContext
Definition: playercontext.h:49
TV::GetCurrentChapter
int GetCurrentChapter()
Definition: tv_play.cpp:5407
TV::m_guests
QVector< string_pair > m_guests
Definition: tv_play.h:578
TV::kInitFFRWSpeed
static const int kInitFFRWSpeed
Definition: tv_play.h:750
JOB_TRANSCODE
@ JOB_TRANSCODE
Definition: jobqueue.h:78
ACTION_PAGELEFT
#define ACTION_PAGELEFT
Definition: tv_actions.h:11
build_compdb.action
action
Definition: build_compdb.py:9
TV::ForceNextStateNone
void ForceNextStateNone()
Definition: tv_play.cpp:2707
MythMediaBuffer::Create
static MythMediaBuffer * Create(const QString &Filename, bool Write, bool UseReadAhead=true, std::chrono::milliseconds Timeout=kDefaultOpenTimeout, bool StreamOnly=false)
Creates a RingBuffer instance.
Definition: mythmediabuffer.cpp:99
InputInfo
Definition: inputinfo.h:14
TVPlaybackState::DisableCaptions
void DisableCaptions(uint Mode, bool UpdateOSD=true)
remoteencoder.h
MythCoreContext::TVInWantingPlayback
void TVInWantingPlayback(bool b)
Let the TV class tell us if we was interrupted following a call to WantingPlayback().
Definition: mythcorecontext.cpp:2070
MythMediaBuffer::GetLastError
QString GetLastError(void) const
Definition: mythmediabuffer.cpp:1770
toMask
PictureAttributeSupported toMask(PictureAttribute PictureAttribute)
Definition: videoouttypes.h:334
ACTION_GUIDE
#define ACTION_GUIDE
Definition: tv_actions.h:26
FUNC_MOVIE
@ FUNC_MOVIE
Definition: lcddevice.h:161
MythVideoBoundsState::m_stereoOverride
StereoscopicMode m_stereoOverride
Definition: mythplayerstate.h:109
PlayerContext::HasPlayer
bool HasPlayer(void) const
Definition: playercontext.cpp:102
TVBrowseHelper::BrowseChannel
void BrowseChannel(const QString &Channum)
Definition: tvbrowsehelper.cpp:165
ReferenceCounter::m_referenceCount
QAtomicInt m_referenceCount
Definition: referencecounter.h:57
mpeg::chrono::pts
std::chrono::duration< CHRONO_TYPE, std::ratio< 1, 90000 > > pts
Definition: mythchrono.h:55
MythPlayerUI::SetWatched
void SetWatched(bool ForceWatched=false)
Determines if the recording should be considered watched.
Definition: mythplayerui.cpp:749
RemoteEncoder::CheckChannel
bool CheckChannel(const QString &channel)
Checks if named channel exists on current tuner.
Definition: remoteencoder.cpp:611
MythVideoBoundsState::m_manualHorizScale
float m_manualHorizScale
Definition: mythplayerstate.h:106
TVPlaybackState::ChangeCaptionTrack
void ChangeCaptionTrack(int Direction)
kState_RecordingOnly
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:87
MythMainWindow::IsExitingToMain
bool IsExitingToMain() const
Definition: mythmainwindow.cpp:1043
MythVideoOutput::HasSoftwareFrames
bool HasSoftwareFrames() const
Definition: mythvideoout.h:86
TV::m_dbPlaybackExitPrompt
int m_dbPlaybackExitPrompt
Definition: tv_play.h:525
OSD::SetValues
void SetValues(const QString &Window, const QHash< QString, int > &Map, OSDTimeout Timeout)
Definition: osd.cpp:152
LiveTVChain::SetProgram
void SetProgram(const ProgramInfo &pginfo)
Definition: livetvchain.cpp:394
kPictureAttribute_Contrast
@ kPictureAttribute_Contrast
Definition: videoouttypes.h:108
TV::PlaybackMenuDeinit
void PlaybackMenuDeinit(const MythTVMenu &Menu)
Definition: tv_play.cpp:9364
MythMediaBuffer::SetLiveMode
void SetLiveMode(LiveTVChain *Chain)
Assigns a LiveTVChain to this RingBuffer.
Definition: mythmediabuffer.cpp:1820
TV::m_screenPressKeyMapLiveTV
QList< QKeyEvent * > m_screenPressKeyMapLiveTV
Definition: tv_play.h:621
TV::m_playbackMenu
MythTVMenu m_playbackMenu
Definition: tv_play.h:744
PlayerContext::m_nextState
MythDeque< TVState > m_nextState
Definition: playercontext.h:161
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &Stackname)
Definition: mythmainwindow.cpp:322
TV::m_lastProgram
ProgramInfo * m_lastProgram
last program played with this player
Definition: tv_play.h:631
kStereoscopicModeTopAndBottomDiscard
@ kStereoscopicModeTopAndBottomDiscard
Definition: videoouttypes.h:139
kTrackTypeAudio
@ kTrackTypeAudio
Definition: decoderbase.h:29
TV::m_tvmIsPaused
bool m_tvmIsPaused
Definition: tv_play.h:718
ACTION_BIGJUMPFWD
#define ACTION_BIGJUMPFWD
Definition: tv_actions.h:93
MythCoreContext::WantingPlayback
void WantingPlayback(QObject *sender)
All the objects that have registered using MythCoreContext::RegisterForPlayback but sender will be ca...
Definition: mythcorecontext.cpp:2004
TV::DoQueueTranscode
void DoQueueTranscode(const QString &Profile)
Definition: tv_play.cpp:5340
mythcodeccontext.h
TV::DoPlayerSeekToFrame
bool DoPlayerSeekToFrame(uint64_t FrameNum)
Definition: tv_play.cpp:4973
ACTION_PREVPAGE
#define ACTION_PREVPAGE
Definition: tv_actions.h:97
kAdjustFill_AutoDetect_DefaultOff
@ kAdjustFill_AutoDetect_DefaultOff
Definition: videoouttypes.h:82
TV::SetInPlayList
void SetInPlayList(bool InPlayList)
Definition: tv_play.h:293
TV::m_queueInputTimerId
volatile int m_queueInputTimerId
Definition: tv_play.h:687
kTrackTypeRawText
@ kTrackTypeRawText
Definition: decoderbase.h:36
TV::m_tvmCurSkip
CommSkipMode m_tvmCurSkip
Definition: tv_play.h:717
MythMainWindow::ClearKeyContext
void ClearKeyContext(const QString &Context)
Definition: mythmainwindow.cpp:1208
OSD::DialogHandleKeypress
bool DialogHandleKeypress(QKeyEvent *Event)
Definition: osd.cpp:706
MythPlayer::JumpToFrame
virtual bool JumpToFrame(uint64_t frame)
Definition: mythplayer.cpp:892
TVPlaybackState::m_videoColourState
MythVideoColourState m_videoColourState
Definition: tvplaybackstate.h:109
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:845
TV::m_tvmCurtrack
int m_tvmCurtrack[kTrackTypeCount]
Definition: tv_play.h:703
TV::SetFFRew
void SetFFRew(int Index)
Definition: tv_play.cpp:5295
kStartTVInPlayList
@ kStartTVInPlayList
Definition: tv_play.h:115
MythMediaBuffer::DVD
const MythDVDBuffer * DVD(void) const
Definition: mythmediabuffer.cpp:1850
mythuiactions.h
MythMediaDevice
Definition: mythmedia.h:48
MythPlayerEditorUI::HandleProgramEditorActions
bool HandleProgramEditorActions(const QStringList &Actions)
Definition: mythplayereditorui.cpp:141
ProgramInfo::SetIgnoreProgStart
void SetIgnoreProgStart(bool ignore)
If "ignore" is true QueryProgStart() will return 0, otherwise QueryProgStart() will return the progst...
Definition: programinfo.h:570
MythNotificationCenter::GetInstance
static MythNotificationCenter * GetInstance(void)
returns the MythNotificationCenter singleton
Definition: mythnotificationcenter.cpp:1318
ChannelUtil::GetValidRecorderList
static QStringList GetValidRecorderList(uint chanid, const QString &channum)
Returns list of the recorders that have chanid or channum in their sources.
Definition: channelutil.cpp:1116
mconcurrent.h
SignalMonitorValue::AllGood
static bool AllGood(const SignalMonitorList &slist)
Returns true if all the values in the list return true on IsGood().
Definition: signalmonitorvalue.cpp:176
ProgramInfo::GetProgramID
QString GetProgramID(void) const
Definition: programinfo.h:440
azlyrics.info
dictionary info
Definition: azlyrics.py:7
TV::DoSeek
void DoSeek(float Time, const QString &Msg, bool TimeIsOffset, bool HonorCutlist)
Definition: tv_play.cpp:5086
ProgramInfo::QueryIsInUse
bool QueryIsInUse(QStringList &byWho) const
Returns true if Program is in use.
Definition: programinfo.cpp:3203
TV::m_tvmTranscoding
bool m_tvmTranscoding
Definition: tv_play.h:739
TV::DoJumpChapter
void DoJumpChapter(int Chapter)
Definition: tv_play.cpp:5417
MythEditorState::m_undoMessage
QString m_undoMessage
Definition: mythplayerstate.h:161
FrameScanType
FrameScanType
Definition: videoouttypes.h:94
TV::m_tvmNumAngles
int m_tvmNumAngles
Definition: tv_play.h:730
MythGestureEvent
A custom event that represents a mouse gesture.
Definition: mythgesture.h:39
StateToString
QString StateToString(TVState state)
Returns a human readable QString representing a TVState.
Definition: tv.cpp:11
ACTION_TOGGLESUBTITLEZOOM
#define ACTION_TOGGLESUBTITLEZOOM
Definition: tv_actions.h:73
ACTION_TOGGLEFAV
#define ACTION_TOGGLEFAV
Definition: tv_actions.h:20
VideoMetaDataUtil::GetArtPath
static QString GetArtPath(const QString &pathname, const QString &type)
Definition: videometadatautil.cpp:17
TV::m_vbimode
uint m_vbimode
Definition: tv_play.h:545
BROWSE_DOWN
@ BROWSE_DOWN
Fetch information on next channel.
Definition: tv.h:45
TV::kLCDTimeout
static const std::chrono::milliseconds kLCDTimeout
Definition: tv_play.h:756
kStereoscopicModeSideBySideDiscard
@ kStereoscopicModeSideBySideDiscard
Definition: videoouttypes.h:138
MythMainWindow::MoveResize
void MoveResize(QRect &Geometry)
Definition: mythmainwindow.cpp:976
ACTION_JUMPTODVDCHAPTERMENU
#define ACTION_JUMPTODVDCHAPTERMENU
Definition: tv_actions.h:50
MythPlayer::GetXDS
QString GetXDS(const QString &key) const
Definition: mythplayer.cpp:1721
RemoteEncoder::GetPictureAttribute
int GetPictureAttribute(PictureAttribute attr)
Definition: remoteencoder.cpp:540
ACTION_MENUWHITE
#define ACTION_MENUWHITE
Definition: tv_actions.h:101
ACTION_3DNONE
#define ACTION_3DNONE
Definition: tv_actions.h:125
kZoomHorizontalIn
@ kZoomHorizontalIn
Definition: videoouttypes.h:49
PlayerContext::HandlePlayerSpeedChangeEOF
bool HandlePlayerSpeedChangeEOF(void)
Definition: playercontext.cpp:133
ACTION_ZOOMIN
#define ACTION_ZOOMIN
Definition: tv_actions.h:137
TVPlaybackState::ChangeVolume
void ChangeVolume(bool Direction, int Volume)
ACTION_DISABLEVISUALISATION
#define ACTION_DISABLEVISUALISATION
Definition: tv_actions.h:119
MythCaptionsState::m_externalTextSubs
bool m_externalTextSubs
Definition: mythplayerstate.h:71
MythDisplay::UsingVideoModes
virtual bool UsingVideoModes()
Definition: mythdisplay.h:30
MythTVMenu::LoadFromFile
bool LoadFromFile(MenuTypeId id, const QString &Filename, const QString &Menuname, const char *TranslationContext, const QString &KeyBindingContext, int IncludeLevel=0)
Definition: mythtvmenu.cpp:189
TrackType
TrackType
Track types.
Definition: decoderbase.h:26
MythVideoFrame
Definition: mythframe.h:87
BROWSE_FAVORITE
@ BROWSE_FAVORITE
Fetch information on the next favorite channel.
Definition: tv.h:48
TV::m_dbIdleTimeout
std::chrono::milliseconds m_dbIdleTimeout
Definition: tv_play.h:524
TV::m_adjustingPictureAttribute
PictureAttribute m_adjustingPictureAttribute
Picture attribute to modify (on arrow left or right)
Definition: tv_play.h:567
TV::GetPlayerReadLock
void GetPlayerReadLock() const
Definition: tv_play.cpp:10501
SavePositionThread
Definition: tv_play.h:776
TV::SetBookmark
void SetBookmark(bool Clear=false)
Definition: tv_play.cpp:4175
TV::CommitQueuedInput
bool CommitQueuedInput()
Definition: tv_play.cpp:5952
TV::FillOSDMenuCast
void FillOSDMenuCast(void)
Definition: tv_play.cpp:9663
MythPlayerCaptionsUI::GetTrackCount
uint GetTrackCount(uint Type)
Definition: mythplayercaptionsui.cpp:325
PlayerContext::m_recorder
RemoteEncoder * m_recorder
Definition: playercontext.h:114
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:888
TV::BrowseHandleAction
bool BrowseHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3540
TV::m_sleepTimerId
int m_sleepTimerId
Timer for turning off playback.
Definition: tv_play.h:587
ACTION_CHANNELUP
#define ACTION_CHANNELUP
Definition: tv_actions.h:16
RemoteGetRecordedList
std::vector< ProgramInfo * > * RemoteGetRecordedList(int sort)
Definition: remoteutil.cpp:19
SignalHandler::IsExiting
static bool IsExiting(void)
Definition: signalhandling.h:36
ChannelUtil::GetChanNum
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
Definition: channelutil.cpp:778
TVPlaybackState::ChangeStereoOverride
void ChangeStereoOverride(StereoscopicMode Mode)
PlayerContext::UnlockState
void UnlockState(void) const
Definition: playercontext.cpp:292
OSD_DLG_EDITING
static constexpr const char * OSD_DLG_EDITING
Definition: osd.h:21
TV::ChangeFFRew
void ChangeFFRew(int Direction)
Definition: tv_play.cpp:5262
TV::GetAllowRerecord
bool GetAllowRerecord() const
Returns true if the user told Mythtv to allow re-recording of the show.
Definition: tv_play.h:314
ACTION_VOLUMEDOWN
#define ACTION_VOLUMEDOWN
Definition: tv_actions.h:111
TV::kScreenPressRegionCount
static const int kScreenPressRegionCount
screen area to keypress translation region is now 0..11 0 1 2 3 4 5 6 7 8 9 10 11
Definition: tv_play.h:619
lcddevice.h
MythEditorState::m_previousCut
uint64_t m_previousCut
Definition: mythplayerstate.h:154
ACTION_CHANNELDOWN
#define ACTION_CHANNELDOWN
Definition: tv_actions.h:17
MythCaptionsState::m_haveITV
bool m_haveITV
Definition: mythplayerstate.h:72
TV::m_tvmJump
bool m_tvmJump
Definition: tv_play.h:722
TvPlayWindow
Simple screen shown while the video player is starting up.
Definition: tv_play_win.h:12
RecordingInfo::ApplyRecordRecGroupChange
void ApplyRecordRecGroupChange(const QString &newrecgroup)
Sets the recording group, both in this RecordingInfo and in the database.
Definition: recordinginfo.cpp:659
ACTION_MENUEPG
#define ACTION_MENUEPG
Definition: tv_actions.h:83
TV::GetQueuedChanNum
QString GetQueuedChanNum() const
Definition: tv_play.cpp:5796
PlayerContext::m_ffRewState
int m_ffRewState
0 == normal, +1 == fast forward, -1 == rewind
Definition: playercontext.h:122
recordingrule.h
ACTION_NEXTSUBPAGE
#define ACTION_NEXTSUBPAGE
Definition: tv_actions.h:98
MythMediaBuffer::StartReads
void StartReads(void)
Definition: mythmediabuffer.cpp:679
kMuteAll
@ kMuteAll
Definition: volumebase.h:12
ACTION_EXITSHOWNOPROMPTS
#define ACTION_EXITSHOWNOPROMPTS
Definition: tv_actions.h:4
ProgramInfo::IsRecording
bool IsRecording(void) const
Definition: programinfo.h:491
TV::RunProgramListPtr
static EMBEDRETURNVOIDPROGLIST RunProgramListPtr
Definition: tv_play.h:203
TV::m_tvmSubsHaveSubs
bool m_tvmSubsHaveSubs
Definition: tv_play.h:736
MythDVDBuffer
Definition: mythdvdbuffer.h:37
MythAudioState::m_audioOffset
std::chrono::milliseconds m_audioOffset
Definition: mythplayerstate.h:60
MythAudioState::m_volumeControl
bool m_volumeControl
Definition: mythplayerstate.h:54
RemoteEncoder::PauseRecorder
void PauseRecorder(void)
Tells TVRec to pause a recorder, used for channel and input changes.
Definition: remoteencoder.cpp:383
MythDeque::dequeue
T dequeue()
Removes item from front of list and returns a copy. O(1).
Definition: mythdeque.h:31
TVPlaybackState::ChangeOSDDebug
void ChangeOSDDebug()
TV::ARBSEEK_END
@ ARBSEEK_END
Definition: tv_play.h:372
MythMainWindow::ScreenShot
static bool ScreenShot(int Width=0, int Height=0, QString Filename="")
Definition: mythmainwindow.cpp:564
ProgramInfo::GetBasename
QString GetBasename(void) const
Definition: programinfo.h:345
ReferenceCounter::IncrRef
virtual int IncrRef(void)
Increments reference count.
Definition: referencecounter.cpp:100
TV::m_networkControlCommands
MythDeque< QString > m_networkControlCommands
Definition: tv_play.h:679
build_compdb.filename
filename
Definition: build_compdb.py:21
kZoomVerticalOut
@ kZoomVerticalOut
Definition: videoouttypes.h:48
kScan_Intr2ndField
@ kScan_Intr2ndField
Definition: videoouttypes.h:99
kOSDTimeout_Short
@ kOSDTimeout_Short
Definition: osd.h:59
TVPlaybackState::WindowResized
void WindowResized(const QSize &Size)
TV::m_lcdSubtitle
QString m_lcdSubtitle
Definition: tv_play.h:654
dummy_menubase
static const MythTVMenu dummy_menubase
Definition: mythtvmenu.h:119
kDisplayTeletextCaptions
@ kDisplayTeletextCaptions
Definition: videoouttypes.h:14
kStereoscopicModeAuto
@ kStereoscopicModeAuto
Definition: videoouttypes.h:136
mythmainwindow.h
SavePositionThread::run
void run() override
Definition: tv_play.cpp:10531
ACTION_MUTEAUDIO
#define ACTION_MUTEAUDIO
Definition: tv_actions.h:106
kAdjustFill_Off
@ kAdjustFill_Off
Definition: videoouttypes.h:74
MythMediaBuffer::IsSeekingAllowed
virtual bool IsSeekingAllowed(void)
Definition: mythmediabuffer.h:135
TV::DoSetPauseState
bool DoSetPauseState(bool Pause)
Definition: tv_play.cpp:6876
TVPlaybackState::PauseAudioUntilReady
void PauseAudioUntilReady()
ACTION_JUMPPREV
#define ACTION_JUMPPREV
Definition: tv_actions.h:38
TV::DoJumpFFWD
void DoJumpFFWD()
Definition: tv_play.cpp:10064
TV::DoPlayerSeek
bool DoPlayerSeek(float Time)
Definition: tv_play.cpp:4937
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
TV::DVDJumpBack
void DVDJumpBack()
Definition: tv_play.cpp:10097
TV::m_tvmCurrentChapter
int m_tvmCurrentChapter
Definition: tv_play.h:728
kZoomHorizontalOut
@ kZoomHorizontalOut
Definition: videoouttypes.h:50
PlayerContext::m_player
MythPlayer * m_player
Definition: playercontext.h:112
MythPlayerUI::EventLoop
virtual void EventLoop()
Definition: mythplayerui.cpp:116
ACTION_JUMPCHAPTER
#define ACTION_JUMPCHAPTER
Definition: tv_actions.h:52
kState_WatchingDVD
@ kState_WatchingDVD
Watching DVD is the state when we are watching a DVD.
Definition: tv.h:76
TV::GetQueuedChanID
uint GetQueuedChanID() const
Definition: tv_play.h:346
TV::DoSkipCommercials
void DoSkipCommercials(int Direction)
Definition: tv_play.cpp:5535
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1746
MythMainWindow::GetActionText
QString GetActionText(const QString &Context, const QString &Action) const
Definition: mythmainwindow.cpp:1343
LCD::setChannelProgress
void setChannelProgress(const QString &time, float value)
Definition: lcddevice.cpp:463
MythTVMenuItemContext::m_node
const QDomNode & m_node
Definition: mythtvmenu.h:66
OSD_DLG_ASKALLOW
static constexpr const char * OSD_DLG_ASKALLOW
Definition: osd.h:22
output
#define output
Definition: synaesthesia.cpp:223
MythPlayerUI::StartPlaying
bool StartPlaying()
Definition: mythplayerui.cpp:73
TVBrowseHelper::BrowseStart
bool BrowseStart(bool SkipBrowse=false)
Begins channel browsing.
Definition: tvbrowsehelper.cpp:75
TV::m_tvmPreviousChan
bool m_tvmPreviousChan
Definition: tv_play.h:724
kStereoscopicModeIgnore3D
@ kStereoscopicModeIgnore3D
Definition: videoouttypes.h:137
comp_season_rev
static int comp_season_rev(const ProgramInfo *a, const ProgramInfo *b)
Definition: tv_play.cpp:96
TV::kVideoExitDialogTimeout
static const std::chrono::milliseconds kVideoExitDialogTimeout
Definition: tv_play.h:762
kPictureAttribute_Brightness
@ kPictureAttribute_Brightness
Definition: videoouttypes.h:107
TV::m_audiosyncAdjustment
bool m_audiosyncAdjustment
True if audiosync is turned on.
Definition: tv_play.h:552
MythPlayer::FastForward
virtual bool FastForward(float seconds)
Definition: mythplayer.cpp:839
MythObservable::removeListener
void removeListener(QObject *listener)
Remove a listener to the observable.
Definition: mythobservable.cpp:55
TV::ProcessKeypressOrGesture
bool ProcessKeypressOrGesture(QEvent *Event)
Definition: tv_play.cpp:3303
TV::ShowOSDAskAllow
void ShowOSDAskAllow()
Definition: tv_play.cpp:1653
ACTION_TOGGLEBACKGROUND
#define ACTION_TOGGLEBACKGROUND
Definition: tv_actions.h:102
MythMediaBuffer::Pause
void Pause(void)
Pauses the read-ahead thread. Calls StopReads(void).
Definition: mythmediabuffer.cpp:690
PlayerContext::ChangeState
void ChangeState(TVState newState)
Puts a state change on the nextState queue.
Definition: playercontext.cpp:309
MythPlayerOverlayUI::UpdateSliderInfo
virtual void UpdateSliderInfo(osdInfo &Info, bool PaddedFields=false)
Definition: mythplayeroverlayui.cpp:128
OSD
Definition: osd.h:93
ACTION_SWITCHANGLE
#define ACTION_SWITCHANGLE
Definition: tv_actions.h:54
TV::m_switchToInputId
uint m_switchToInputId
Definition: tv_play.h:546
TV::Init
bool Init()
Performs instance initialization, returns true on success.
Definition: tv_play.cpp:1145
ACTION_SEEKFFWD
#define ACTION_SEEKFFWD
Definition: tv_actions.h:43
CardUtil::GetStartChannel
static QString GetStartChannel(uint inputid)
Definition: cardutil.cpp:1792
LCD
Definition: lcddevice.h:169
MythMainWindow
Definition: mythmainwindow.h:28
kOSDFunctionalType_Default
@ kOSDFunctionalType_Default
Definition: osd.h:46
TVPlaybackState::UpdateLastPlayPosition
void UpdateLastPlayPosition(uint64_t frame)
TVPlaybackState::ToggleDetectLetterBox
void ToggleDetectLetterBox()
MythPlayer::Play
bool Play(float speed=1.0, bool normal=true, bool unpauseaudio=true)
Definition: mythplayer.cpp:186
ReferenceCounter
General purpose reference counter.
Definition: referencecounter.h:26
MThreadPool::start
void start(QRunnable *runnable, const QString &debugName, int priority=0)
Definition: mthreadpool.cpp:331
TV::RunProgramFinderPtr
static EMBEDRETURNVOIDFINDER RunProgramFinderPtr
Definition: tv_play.h:201
TV::SubtitleDelayHandleAction
bool SubtitleDelayHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3762
kNoCurrRec
@ kNoCurrRec
No current recordings.
Definition: tv_play.h:109
MythAudioState::m_hasAudioOut
bool m_hasAudioOut
Definition: mythplayerstate.h:53
ProgramInfo::HasPathname
bool HasPathname(void) const
Definition: programinfo.h:359
TV::UpdateOSDTimeoutMessage
void UpdateOSDTimeoutMessage()
Definition: tv_play.cpp:6608
TV::m_adjustingPicture
PictureAdjustType m_adjustingPicture
Picture attribute type to modify.
Definition: tv_play.h:565
InputInfo::m_mplexId
uint m_mplexId
mplexid restriction if applicable
Definition: inputinfo.h:50
mythscreentype.h
AutoDeleteDeque::size
size_t size(void) const
Definition: autodeletedeque.h:67
TV::m_videoExitDialogTimerId
volatile int m_videoExitDialogTimerId
Definition: tv_play.h:690
find
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
Definition: dvbstreamhandler.cpp:363
MythAudioState::m_isUpmixing
bool m_isUpmixing
Definition: mythplayerstate.h:58
MythTVMenuItemContext::m_action
const QString m_action
Definition: mythtvmenu.h:71
MythEditorState::m_isTempMark
bool m_isTempMark
Definition: mythplayerstate.h:158
TV::PlaybackLoop
void PlaybackLoop()
The main playback loop.
Definition: tv_play.cpp:1307
TV::m_tvmAvsync
bool m_tvmAvsync
Definition: tv_play.h:706
ProgramInfo::SaveLastPlayPos
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
Definition: programinfo.cpp:2727
TV::ARBSEEK_REWIND
@ ARBSEEK_REWIND
Definition: tv_play.h:372
TV::GetJumpToProgram
bool GetJumpToProgram() const
This is set if the user asked MythTV to jump to the previous recording in the playlist.
Definition: tv_play.h:320
MythPlayer::TranslatePositionRelToAbs
uint64_t TranslatePositionRelToAbs(uint64_t position) const
Definition: mythplayer.h:269
MythMainWindow::PauseIdleTimer
void PauseIdleTimer(bool Pause)
Pause the idle timeout timer.
Definition: mythmainwindow.cpp:2158
MythCoreContext::emitTVPlaybackAborted
void emitTVPlaybackAborted(void)
Definition: mythcorecontext.h:276
uint
unsigned int uint
Definition: freesurround.h:24
kDisplayNone
@ kDisplayNone
Definition: videoouttypes.h:12
MythMediaBuffer::IsOpen
virtual bool IsOpen(void) const =0
kStartTVIgnoreBookmark
@ kStartTVIgnoreBookmark
Definition: tv_play.h:117
BROWSE_LEFT
@ BROWSE_LEFT
Fetch information on current channel in the past.
Definition: tv.h:46
MythDeque::enqueue
void enqueue(const T &d)
Adds item to the back of the list. O(1).
Definition: mythdeque.h:41
TVPlaybackState::ChangeTrack
void ChangeTrack(uint Type, int Direction)
kAdjustingPicture_Playback
@ kAdjustingPicture_Playback
Definition: tv.h:126
TV::IsTunableOn
static QVector< uint > IsTunableOn(PlayerContext *Context, uint ChanId)
Definition: tv_play.cpp:6799
millisecondsFromFloat
std::enable_if_t< std::is_floating_point_v< T >, std::chrono::milliseconds > millisecondsFromFloat(T value)
Helper function for convert a floating point number to a duration.
Definition: mythchrono.h:91
PlayerContext::ForceNextStateNone
void ForceNextStateNone(void)
Removes any pending state changes, and puts kState_None on the queue.
Definition: playercontext.cpp:324
DialogCompletionEvent::GetData
QVariant GetData()
Definition: mythdialogbox.h:54
TVPlaybackState::IsOSDVisible
void IsOSDVisible(bool &Visible)
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
TV::TranslateGesture
bool TranslateGesture(const QString &Context, MythGestureEvent *Event, QStringList &Actions, bool IsLiveTV)
Definition: tv_play.cpp:3259
MythTVMenu::Show
bool Show(const QDomNode &Node, const QDomNode &Selected, MythTVMenuItemDisplayer &Displayer, MythOSDDialogData *Menu, bool Visible=true) const
Definition: mythtvmenu.cpp:294
kMenuCurrentDefault
@ kMenuCurrentDefault
Definition: mythtvmenu.h:27
RemoteRequestNextFreeRecorder
RemoteEncoder * RemoteRequestNextFreeRecorder(int inputid)
Definition: tvremoteutil.cpp:181
tv_play.h
MythScreenStack::GetTopScreen
virtual MythScreenType * GetTopScreen(void) const
Definition: mythscreenstack.cpp:182
TV::m_askAllowPrograms
QMap< QString, AskProgramInfo > m_askAllowPrograms
Definition: tv_play.h:570
TV::m_tvmNumChapters
int m_tvmNumChapters
Definition: tv_play.h:727
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:364
PictureAdjustType
PictureAdjustType
Definition: tv.h:123
MythPlayer::Rewind
virtual bool Rewind(float seconds)
Definition: mythplayer.cpp:869
BrowseInfo::m_startTime
QString m_startTime
Definition: tvbrowsehelper.h:40
ACTION_JUMPREC
#define ACTION_JUMPREC
Definition: tv_actions.h:39
MythNotificationCenter::Queue
bool Queue(const MythNotification &notification)
Queue a notification Queue() is thread-safe and can be called from anywhere.
Definition: mythnotificationcenter.cpp:1349
MythPlayer::GetCurrentChapter
virtual int GetCurrentChapter(void)
Definition: mythplayer.cpp:1820
TV
Control TV playback.
Definition: tv_play.h:155
ChannelInfoList
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:131
AskProgramInfo
Definition: tv_play.h:122
kNoTuners
@ kNoTuners
No capture cards configured.
Definition: tv_play.h:110
TV::m_dbChannelFormat
QString m_dbChannelFormat
Definition: tv_play.h:523