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 #ifdef USING_VALGRIND
248  MaxWait = std::chrono::milliseconds::max();
249 #endif // USING_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 
1013 {
1014  LOG(VB_GENERAL, LOG_INFO, LOC + "Creating TV object");
1015 
1016  QObject::setObjectName("TV");
1018  connect(this, &TV::RequestEmbedding, this, &TV::Embed);
1019  InitFromDB();
1020 
1021 #ifdef Q_OS_ANDROID
1022  connect(qApp, &QApplication::applicationStateChanged, this, &TV::onApplicationStateChange);
1023 #endif
1024 
1025  if (m_mainWindow)
1027 
1028  // Setup various state signals
1029  connect(this, &TV::ChangeAudioOffset, [&]() { m_audiosyncAdjustment = true; });
1030  connect(this, &TV::AdjustSubtitleZoom, [&]() { m_subtitleZoomAdjustment = true; });
1031  connect(this, &TV::AdjustSubtitleDelay, [&]() { m_subtitleDelayAdjustment = true; });
1032 
1033  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Finished creating TV object");
1034 }
1035 
1037 {
1038  QMap<QString,QString> kv;
1039  kv["LiveTVIdleTimeout"] = "0";
1040  kv["BrowseMaxForward"] = "240";
1041  kv["PlaybackExitPrompt"] = "0";
1042  kv["AutomaticSetWatched"] = "0";
1043  kv["EndOfRecordingExitPrompt"] = "0";
1044  kv["JumpToProgramOSD"] = "1";
1045  kv["GuiSizeForTV"] = "0";
1046  kv["UseVideoModes"] = "0";
1047  kv["JobsRunOnRecordHost"] = "0";
1048  kv["ContinueEmbeddedTVPlay"] = "0";
1049  kv["UseFixedWindowSize"] = "1";
1050  kv["RunFrontendInWindow"] = "0";
1051  kv["PersistentBrowseMode"] = "0";
1052  kv["BrowseAllTuners"] = "0";
1053  kv["ChannelOrdering"] = "channum";
1054 
1055  kv["CustomFilters"] = "";
1056  kv["ChannelFormat"] = "<num> <sign>";
1057 
1058  kv["TryUnflaggedSkip"] = "0";
1059 
1060  kv["ChannelGroupDefault"] = "-1";
1061  kv["BrowseChannelGroup"] = "0";
1062  kv["SmartForward"] = "0";
1063  kv["FFRewReposTime"] = "100";
1064  kv["FFRewReverse"] = "1";
1065 
1066  kv["BrowseChannelGroup"] = "0";
1067  kv["ChannelGroupDefault"] = "-1";
1068  kv["ChannelGroupRememberLast"] = "0";
1069 
1070  kv["VbiFormat"] = "";
1071  kv["DecodeVBIFormat"] = "";
1072 
1073  // these need exactly 12 items, comma cant be used as it is the delimiter
1074  kv["PlaybackScreenPressKeyMap"] = "P,Up,Z,],Left,Return,Return,Right,A,Down,Q,[";
1075  kv["LiveTVScreenPressKeyMap"] = "P,Up,Z,S,Left,Return,Return,Right,A,Down,Q,F";
1076 
1077  constexpr std::array<const int,8> ff_rew_def { 3, 5, 10, 20, 30, 60, 120, 180 };
1078  for (size_t i = 0; i < ff_rew_def.size(); i++)
1079  kv[QString("FFRewSpeed%1").arg(i)] = QString::number(ff_rew_def[i]);
1080 
1081  MythDB::getMythDB()->GetSettings(kv);
1082 
1083  m_screenPressKeyMapPlayback = ConvertScreenPressKeyMap(kv["PlaybackScreenPressKeyMap"]);
1084  m_screenPressKeyMapLiveTV = ConvertScreenPressKeyMap(kv["LiveTVScreenPressKeyMap"]);
1085 
1086  QString db_channel_ordering;
1087 
1088  m_dbIdleTimeout = std::chrono::minutes(kv["LiveTVIdleTimeout"].toUInt());
1089  auto db_browse_max_forward = std::chrono::minutes(kv["BrowseMaxForward"].toUInt());
1090  m_dbPlaybackExitPrompt = kv["PlaybackExitPrompt"].toInt();
1091  m_dbAutoSetWatched = (kv["AutomaticSetWatched"].toInt() != 0);
1092  m_dbEndOfRecExitPrompt = (kv["EndOfRecordingExitPrompt"].toInt() != 0);
1093  m_dbJumpPreferOsd = (kv["JumpToProgramOSD"].toInt() != 0);
1094  m_dbUseGuiSizeForTv = (kv["GuiSizeForTV"].toInt() != 0);
1095  m_dbUseVideoModes = (kv["UseVideoModes"].toInt() != 0);
1096  m_dbRunJobsOnRemote = (kv["JobsRunOnRecordHost"].toInt() != 0);
1097  m_dbContinueEmbedded = (kv["ContinueEmbeddedTVPlay"].toInt() != 0);
1098  m_dbBrowseAlways = (kv["PersistentBrowseMode"].toInt() != 0);
1099  m_dbBrowseAllTuners = (kv["BrowseAllTuners"].toInt() != 0);
1100  db_channel_ordering = kv["ChannelOrdering"];
1101  m_dbChannelFormat = kv["ChannelFormat"];
1102  m_smartForward = (kv["SmartForward"].toInt() != 0);
1103  m_ffRewRepos = kv["FFRewReposTime"].toFloat() * 0.01F;
1104  m_ffRewReverse = (kv["FFRewReverse"].toInt() != 0);
1105 
1106  m_dbUseChannelGroups = (kv["BrowseChannelGroup"].toInt() != 0);
1107  m_dbRememberLastChannelGroup = (kv["ChannelGroupRememberLast"].toInt() != 0);
1108  m_channelGroupId = kv["ChannelGroupDefault"].toInt();
1109 
1110  QString beVBI = kv["VbiFormat"];
1111  QString feVBI = kv["DecodeVBIFormat"];
1112 
1113  RecordingRule record;
1114  record.LoadTemplate("Default");
1115  m_dbAutoexpireDefault = static_cast<uint>(record.m_autoExpire);
1116 
1118  {
1120  if (m_channelGroupId > -1)
1121  {
1122  m_channelGroupChannelList = ChannelUtil::GetChannels(0, true, "channum, callsign",
1123  static_cast<uint>(m_channelGroupId));
1125  }
1126  }
1127 
1128  for (size_t i = 0; i < sizeof(ff_rew_def)/sizeof(ff_rew_def[0]); i++)
1129  m_ffRewSpeeds.push_back(kv[QString("FFRewSpeed%1").arg(i)].toInt());
1130 
1131  // process it..
1132  BrowseInit(db_browse_max_forward, m_dbBrowseAllTuners, m_dbUseChannelGroups, db_channel_ordering);
1133 
1134  m_vbimode = VBIMode::Parse(!feVBI.isEmpty() ? feVBI : beVBI);
1135 
1136  gCoreContext->addListener(this);
1138 }
1139 
1144 bool TV::Init()
1145 {
1146  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- begin");
1147 
1148  if (!m_mainWindow)
1149  {
1150  LOG(VB_GENERAL, LOG_ERR, LOC + "No MythMainWindow");
1151  return false;
1152  }
1153 
1154  bool fullscreen = !m_dbUseGuiSizeForTv;
1155  m_savedGuiBounds = QRect(m_mainWindow->geometry().topLeft(), m_mainWindow->size());
1156 
1157  // adjust for window manager wierdness.
1158  QRect screen = m_mainWindow->GetScreenRect();
1159  if ((abs(m_savedGuiBounds.x() - screen.left()) < 3) &&
1160  (abs(m_savedGuiBounds.y() - screen.top()) < 3))
1161  {
1162  m_savedGuiBounds = QRect(screen.topLeft(), m_mainWindow->size());
1163  }
1164 
1165  // if width && height are zero users expect fullscreen playback
1166  if (!fullscreen)
1167  {
1168  int gui_width = 0;
1169  int gui_height = 0;
1170  gCoreContext->GetResolutionSetting("Gui", gui_width, gui_height);
1171  fullscreen |= (0 == gui_width && 0 == gui_height);
1172  }
1173 
1175  if (fullscreen)
1177 
1178  // player window sizing
1179  MythScreenStack *mainStack = m_mainWindow->GetMainStack();
1180 
1181  m_myWindow = new TvPlayWindow(mainStack, "Playback");
1182 
1183  if (m_myWindow->Create())
1184  {
1185  mainStack->AddScreen(m_myWindow, false);
1186  LOG(VB_GENERAL, LOG_INFO, LOC + "Created TvPlayWindow.");
1187  }
1188  else
1189  {
1190  delete m_myWindow;
1191  m_myWindow = nullptr;
1192  }
1193 
1195  m_mainWindow->GetPaintWindow()->update();
1196  m_mainWindow->installEventFilter(this);
1197  QCoreApplication::processEvents();
1198 
1203  m_playerContext.m_tsNormal = 1.0F;
1204  ReturnPlayerLock();
1205 
1206  m_sleepIndex = 0;
1207 
1208  emit ChangeOSDPositionUpdates(false);
1209 
1211  ClearInputQueues(false);
1212  ReturnPlayerLock();
1213 
1214  m_switchToRec = nullptr;
1215  SetExitPlayer(false, false);
1216 
1218  m_lcdTimerId = StartTimer(1ms, __LINE__);
1221 
1222  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end");
1223  return true;
1224 }
1225 
1227 {
1228  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- begin");
1229 
1230  BrowseStop();
1231  BrowseWait();
1232 
1235 
1236  if (m_mainWindow)
1237  {
1238  m_mainWindow->removeEventFilter(this);
1239  if (m_weDisabledGUI)
1241  }
1242 
1243  if (m_myWindow)
1244  {
1245  m_myWindow->Close();
1246  m_myWindow = nullptr;
1247  }
1248 
1249  LOG(VB_PLAYBACK, LOG_INFO, LOC + "-- lock");
1250 
1251  // restore window to gui size and position
1252  if (m_mainWindow)
1253  {
1254  MythDisplay* display = m_mainWindow->GetDisplay();
1255  if (display->UsingVideoModes())
1256  {
1257  bool hide = display->NextModeIsLarger(display->GetGUIResolution());
1258  if (hide)
1259  m_mainWindow->hide();
1260  display->SwitchToGUI(true);
1261  if (hide)
1262  m_mainWindow->Show();
1263  }
1265  #ifdef Q_OS_ANDROID
1266  m_mainWindow->Show();
1267  #else
1268  m_mainWindow->show();
1269  #endif
1270  m_mainWindow->PauseIdleTimer(false);
1271  }
1272 
1273  qDeleteAll(m_screenPressKeyMapPlayback);
1275  qDeleteAll(m_screenPressKeyMapLiveTV);
1276  m_screenPressKeyMapLiveTV.clear();
1277 
1278  delete m_lastProgram;
1279 
1280  if (LCD *lcd = LCD::Get())
1281  {
1282  lcd->setFunctionLEDs(FUNC_TV, false);
1283  lcd->setFunctionLEDs(FUNC_MOVIE, false);
1284  lcd->switchToTime();
1285  }
1286 
1287  m_playerLock.lockForWrite();
1289  m_player = nullptr;
1290  m_playerLock.unlock();
1291 
1292  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end");
1293 }
1294 
1299 {
1300  while (true)
1301  {
1302  QCoreApplication::processEvents();
1304  {
1305  m_wantsToQuit = true;
1306  return;
1307  }
1308 
1309  TVState state = GetState();
1310  if ((kState_Error == state) || (kState_None == state))
1311  return;
1312 
1313  if (kState_ChangingState == state)
1314  continue;
1315 
1317  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
1318  if (m_player && !m_player->IsErrored())
1319  {
1320  m_player->EventLoop();
1321  m_player->VideoLoop();
1322  }
1323  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
1324  ReturnPlayerLock();
1325 
1327  return;
1328  }
1329 }
1330 
1334 void TV::UpdateChannelList(int GroupID)
1335 {
1336  if (!m_dbUseChannelGroups)
1337  return;
1338 
1339  QMutexLocker locker(&m_channelGroupLock);
1340  if (GroupID == m_channelGroupId)
1341  return;
1342 
1343  ChannelInfoList list;
1344  if (GroupID >= 0)
1345  {
1346  list = ChannelUtil::GetChannels(0, true, "channum, callsign", static_cast<uint>(GroupID));
1347  ChannelUtil::SortChannels(list, "channum", true);
1348  }
1349 
1350  m_channelGroupId = GroupID;
1352 
1354  gCoreContext->SaveSetting("ChannelGroupDefault", m_channelGroupId);
1355 }
1356 
1358 {
1361  ret = m_playerContext.GetState();
1362  return ret;
1363 }
1364 
1365 // XXX what about subtitlezoom?
1367 {
1368  QVariantMap status;
1369 
1371  status.insert("state", StateToString(GetState()));
1372  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
1374  {
1375  status.insert("title", m_playerContext.m_playingInfo->GetTitle());
1376  status.insert("subtitle", m_playerContext.m_playingInfo->GetSubtitle());
1377  status.insert("starttime", m_playerContext.m_playingInfo->GetRecordingStartTime()
1378  .toUTC().toString("yyyy-MM-ddThh:mm:ssZ"));
1379  status.insert("chanid", QString::number(m_playerContext.m_playingInfo->GetChanID()));
1380  status.insert("programid", m_playerContext.m_playingInfo->GetProgramID());
1381  status.insert("pathname", m_playerContext.m_playingInfo->GetPathname());
1382  }
1383  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
1384  osdInfo info;
1386  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
1387  if (m_player)
1388  {
1389  if (!info.text["totalchapters"].isEmpty())
1390  {
1391  QList<std::chrono::seconds> chapters;
1392  m_player->GetChapterTimes(chapters);
1393  QVariantList var;
1394  for (std::chrono::seconds chapter : std::as_const(chapters))
1395  var << QVariant((long long)chapter.count());
1396  status.insert("chaptertimes", var);
1397  }
1398 
1400  QVariantMap tracks;
1401 
1402  QStringList list = m_player->GetTracks(kTrackTypeSubtitle);
1403  int currenttrack = -1;
1404  if (!list.isEmpty() && (kDisplayAVSubtitle == capmode))
1405  currenttrack = m_player->GetTrack(kTrackTypeSubtitle);
1406  for (int i = 0; i < list.size(); i++)
1407  {
1408  if (i == currenttrack)
1409  status.insert("currentsubtitletrack", list[i]);
1410  tracks.insert("SELECTSUBTITLE_" + QString::number(i), list[i]);
1411  }
1412 
1414  currenttrack = -1;
1415  if (!list.isEmpty() && (kDisplayTeletextCaptions == capmode))
1416  currenttrack = m_player->GetTrack(kTrackTypeTeletextCaptions);
1417  for (int i = 0; i < list.size(); i++)
1418  {
1419  if (i == currenttrack)
1420  status.insert("currentsubtitletrack", list[i]);
1421  tracks.insert("SELECTTTC_" + QString::number(i), list[i]);
1422  }
1423 
1425  currenttrack = -1;
1426  if (!list.isEmpty() && (kDisplayCC708 == capmode))
1427  currenttrack = m_player->GetTrack(kTrackTypeCC708);
1428  for (int i = 0; i < list.size(); i++)
1429  {
1430  if (i == currenttrack)
1431  status.insert("currentsubtitletrack", list[i]);
1432  tracks.insert("SELECTCC708_" + QString::number(i), list[i]);
1433  }
1434 
1436  currenttrack = -1;
1437  if (!list.isEmpty() && (kDisplayCC608 == capmode))
1438  currenttrack = m_player->GetTrack(kTrackTypeCC608);
1439  for (int i = 0; i < list.size(); i++)
1440  {
1441  if (i == currenttrack)
1442  status.insert("currentsubtitletrack", list[i]);
1443  tracks.insert("SELECTCC608_" + QString::number(i), list[i]);
1444  }
1445 
1447  currenttrack = -1;
1448  if (!list.isEmpty() && (kDisplayRawTextSubtitle == capmode))
1449  currenttrack = m_player->GetTrack(kTrackTypeRawText);
1450  for (int i = 0; i < list.size(); i++)
1451  {
1452  if (i == currenttrack)
1453  status.insert("currentsubtitletrack", list[i]);
1454  tracks.insert("SELECTRAWTEXT_" + QString::number(i), list[i]);
1455  }
1456 
1458  {
1459  if (kDisplayTextSubtitle == capmode)
1460  status.insert("currentsubtitletrack", tr("External Subtitles"));
1461  tracks.insert(ACTION_ENABLEEXTTEXT, tr("External Subtitles"));
1462  }
1463 
1464  status.insert("totalsubtitletracks", tracks.size());
1465  if (!tracks.isEmpty())
1466  status.insert("subtitletracks", tracks);
1467 
1468  tracks.clear();
1470  currenttrack = m_player->GetTrack(kTrackTypeAudio);
1471  for (int i = 0; i < list.size(); i++)
1472  {
1473  if (i == currenttrack)
1474  status.insert("currentaudiotrack", list[i]);
1475  tracks.insert("SELECTAUDIO_" + QString::number(i), list[i]);
1476  }
1477 
1478  status.insert("totalaudiotracks", tracks.size());
1479  if (!tracks.isEmpty())
1480  status.insert("audiotracks", tracks);
1481 
1482  status.insert("playspeed", m_player->GetPlaySpeed());
1483  status.insert("audiosyncoffset", static_cast<long long>(m_audioState.m_audioOffset.count()));
1484 
1486  {
1487  status.insert("volume", m_audioState.m_volume);
1488  status.insert("mute", m_audioState.m_muteState);
1489  }
1490 
1493  status.insert("brightness", m_videoColourState.GetValue(kPictureAttribute_Brightness));
1495  status.insert("contrast", m_videoColourState.GetValue(kPictureAttribute_Contrast));
1497  status.insert("colour", m_videoColourState.GetValue(kPictureAttribute_Colour));
1498  if (supp & kPictureAttributeSupported_Hue)
1499  status.insert("hue", m_videoColourState.GetValue(kPictureAttribute_Hue));
1500  }
1501  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
1502  ReturnPlayerLock();
1503 
1504  for (auto tit =info.text.cbegin(); tit != info.text.cend(); ++tit)
1505  status.insert(tit.key(), tit.value());
1506 
1507  QHashIterator<QString,int> vit(info.values);
1508  while (vit.hasNext())
1509  {
1510  vit.next();
1511  status.insert(vit.key(), vit.value());
1512  }
1513 
1515 }
1516 
1522 bool TV::LiveTV(bool ShowDialogs, const ChannelInfoList &Selection)
1523 {
1524  m_requestDelete = false;
1525  m_allowRerecord = false;
1526  m_jumpToProgram = false;
1527 
1529  if (m_playerContext.GetState() == kState_None && RequestNextRecorder(ShowDialogs, Selection))
1530  {
1533  m_switchToRec = nullptr;
1534 
1535  // Start Idle Timer
1536  if (m_dbIdleTimeout > 0ms)
1537  {
1539  LOG(VB_GENERAL, LOG_INFO, QString("Using Idle Timer. %1 minutes")
1540  .arg(duration_cast<std::chrono::minutes>(m_dbIdleTimeout).count()));
1541  }
1542 
1543  ReturnPlayerLock();
1544  return true;
1545  }
1546  ReturnPlayerLock();
1547  return false;
1548 }
1549 
1550 bool TV::RequestNextRecorder(bool ShowDialogs, const ChannelInfoList &Selection)
1551 {
1552  m_playerContext.SetRecorder(nullptr);
1553 
1554  RemoteEncoder *testrec = nullptr;
1555  if (m_switchToRec)
1556  {
1557  // If this is set we, already got a new recorder in SwitchCards()
1558  testrec = m_switchToRec;
1559  m_switchToRec = nullptr;
1560  }
1561  else if (!Selection.empty())
1562  {
1563  for (const auto & ci : Selection)
1564  {
1565  uint chanid = ci.m_chanId;
1566  QString channum = ci.m_chanNum;
1567  if (!chanid || channum.isEmpty())
1568  continue;
1569  QVector<uint> cards = IsTunableOn(&m_playerContext, chanid);
1570 
1571  if (chanid && !channum.isEmpty() && !cards.isEmpty())
1572  {
1573  testrec = RemoteGetExistingRecorder(static_cast<int>(*(cards.begin())));
1574  m_initialChanID = chanid;
1575  break;
1576  }
1577  }
1578  }
1579  else
1580  {
1581  // When starting LiveTV we just get the next free recorder
1582  testrec = RemoteRequestNextFreeRecorder(-1);
1583  }
1584 
1585  if (!testrec)
1586  return false;
1587 
1588  if (!testrec->IsValidRecorder())
1589  {
1590  if (ShowDialogs)
1592 
1593  delete testrec;
1594 
1595  return false;
1596  }
1597 
1598  m_playerContext.SetRecorder(testrec);
1599 
1600  return true;
1601 }
1602 
1603 void TV::AskAllowRecording(const QStringList &Msg, int Timeuntil, bool HasRec, bool HasLater)
1604 {
1605  if (!StateIsLiveTV(GetState()))
1606  return;
1607 
1608  auto *info = new ProgramInfo(Msg);
1609  if (!info->GetChanID())
1610  {
1611  delete info;
1612  return;
1613  }
1614 
1615  QMutexLocker locker(&m_askAllowLock);
1616  QString key = info->MakeUniqueKey();
1617  if (Timeuntil > 0)
1618  {
1619  // add program to list
1620 #if 0
1621  LOG(VB_GENERAL, LOG_DEBUG, LOC + "AskAllowRecording -- " +
1622  QString("adding '%1'").arg(info->m_title));
1623 #endif
1624  QDateTime expiry = MythDate::current().addSecs(Timeuntil);
1625  m_askAllowPrograms[key] = AskProgramInfo(expiry, HasRec, HasLater, info);
1626  }
1627  else
1628  {
1629  // remove program from list
1630  LOG(VB_GENERAL, LOG_INFO, LOC + "-- " +
1631  QString("removing '%1'").arg(info->GetTitle()));
1632  QMap<QString,AskProgramInfo>::iterator it = m_askAllowPrograms.find(key);
1633  if (it != m_askAllowPrograms.end())
1634  {
1635  delete (*it).m_info;
1636  m_askAllowPrograms.erase(it);
1637  }
1638  delete info;
1639  }
1640 
1641  ShowOSDAskAllow();
1642 }
1643 
1645 {
1646  QMutexLocker locker(&m_askAllowLock);
1648  return;
1649 
1650  uint cardid = m_playerContext.GetCardID();
1651 
1652  QString single_rec = tr("MythTV wants to record \"%1\" on %2 in %d seconds. Do you want to:");
1653 
1654  QString record_watch = tr("Record and watch while it records");
1655  QString let_record1 = tr("Let it record and go back to the Main Menu");
1656  QString let_recordm = tr("Let them record and go back to the Main Menu");
1657  QString record_later1 = tr("Record it later, I want to watch TV");
1658  QString record_laterm = tr("Record them later, I want to watch TV");
1659  QString do_not_record1= tr("Don't let it record, I want to watch TV");
1660  QString do_not_recordm= tr("Don't let them record, I want to watch TV");
1661 
1662  // eliminate timed out programs
1663  QDateTime timeNow = MythDate::current();
1664  QMap<QString,AskProgramInfo>::iterator it = m_askAllowPrograms.begin();
1665  while (it != m_askAllowPrograms.end())
1666  {
1667  if ((*it).m_expiry <= timeNow)
1668  {
1669 #if 0
1670  LOG(VB_GENERAL, LOG_DEBUG, LOC + "-- " +
1671  QString("removing '%1'").arg((*it).m_info->m_title));
1672 #endif
1673  delete (*it).m_info;
1674  it = m_askAllowPrograms.erase(it);
1675  }
1676  else
1677  {
1678  it++;
1679  }
1680  }
1681  std::chrono::milliseconds timeuntil = 0ms;
1682  QString message;
1683  uint conflict_count = static_cast<uint>(m_askAllowPrograms.size());
1684 
1685  it = m_askAllowPrograms.begin();
1686  if ((1 == m_askAllowPrograms.size()) && ((*it).m_info->GetInputID() == cardid))
1687  {
1688  (*it).m_isInSameInputGroup = (*it).m_isConflicting = true;
1689  }
1690  else if (!m_askAllowPrograms.empty())
1691  {
1692  // get the currently used input on our card
1693  bool busy_input_grps_loaded = false;
1694  std::vector<uint> busy_input_grps;
1695  InputInfo busy_input;
1696  RemoteIsBusy(cardid, busy_input);
1697 
1698  // check if current input can conflict
1699  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1700  {
1701  (*it).m_isInSameInputGroup =
1702  (cardid == (*it).m_info->GetInputID());
1703 
1704  if ((*it).m_isInSameInputGroup)
1705  continue;
1706 
1707  // is busy_input in same input group as recording
1708  if (!busy_input_grps_loaded)
1709  {
1710  busy_input_grps = CardUtil::GetInputGroups(busy_input.m_inputId);
1711  busy_input_grps_loaded = true;
1712  }
1713 
1714  std::vector<uint> input_grps =
1715  CardUtil::GetInputGroups((*it).m_info->GetInputID());
1716 
1717  for (uint grp : input_grps)
1718  {
1719  if (find(busy_input_grps.begin(), busy_input_grps.end(),
1720  grp) != busy_input_grps.end())
1721  {
1722  (*it).m_isInSameInputGroup = true;
1723  break;
1724  }
1725  }
1726  }
1727 
1728  // check if inputs that can conflict are ok
1729  conflict_count = 0;
1730  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1731  {
1732  if (!(*it).m_isInSameInputGroup)
1733  (*it).m_isConflicting = false; // NOLINT(bugprone-branch-clone)
1734  else if (cardid == (*it).m_info->GetInputID())
1735  (*it).m_isConflicting = true; // NOLINT(bugprone-branch-clone)
1736  else if (!CardUtil::IsTunerShared(cardid, (*it).m_info->GetInputID()))
1737  (*it).m_isConflicting = true;
1738  else if ((busy_input.m_mplexId &&
1739  (busy_input.m_mplexId == (*it).m_info->QueryMplexID())) ||
1740  (!busy_input.m_mplexId &&
1741  (busy_input.m_chanId == (*it).m_info->GetChanID())))
1742  (*it).m_isConflicting = false;
1743  else
1744  (*it).m_isConflicting = true;
1745 
1746  conflict_count += (*it).m_isConflicting ? 1 : 0;
1747  }
1748  }
1749 
1750  it = m_askAllowPrograms.begin();
1751  for (; it != m_askAllowPrograms.end() && !(*it).m_isConflicting; ++it);
1752 
1753  if (conflict_count == 0)
1754  {
1755  LOG(VB_GENERAL, LOG_INFO, LOC + "The scheduler wants to make "
1756  "a non-conflicting recording.");
1757  // TODO take down mplexid and inform user of problem
1758  // on channel changes.
1759  }
1760  else if (conflict_count == 1 && ((*it).m_info->GetInputID() == cardid))
1761  {
1762 #if 0
1763  LOG(VB_GENERAL, LOG_DEBUG, LOC + "UpdateOSDAskAllowDialog -- " +
1764  "kAskAllowOneRec");
1765 #endif
1766 
1767  it = m_askAllowPrograms.begin();
1768 
1769  QString channel = m_dbChannelFormat;
1770  channel
1771  .replace("<num>", (*it).m_info->GetChanNum())
1772  .replace("<sign>", (*it).m_info->GetChannelSchedulingID())
1773  .replace("<name>", (*it).m_info->GetChannelName());
1774 
1775  message = single_rec.arg((*it).m_info->GetTitle(), channel);
1776 
1777  BrowseEnd(false);
1778  timeuntil = MythDate::secsInFuture((*it).m_expiry);
1779  MythOSDDialogData dialog { OSD_DLG_ASKALLOW, message, timeuntil };
1780  dialog.m_buttons.push_back({ record_watch, "DIALOG_ASKALLOW_WATCH_0", false, !((*it).m_hasRec)} );
1781  dialog.m_buttons.push_back({ let_record1, "DIALOG_ASKALLOW_EXIT_0" });
1782  dialog.m_buttons.push_back({ ((*it).m_hasLater) ? record_later1 : do_not_record1,
1783  "DIALOG_ASKALLOW_CANCELRECORDING_0", false, ((*it).m_hasRec) });
1784  emit ChangeOSDDialog(dialog);
1785  }
1786  else
1787  {
1788  if (conflict_count > 1)
1789  {
1790  message = tr(
1791  "MythTV wants to record these programs in %d seconds:");
1792  message += "\n";
1793  }
1794 
1795  bool has_rec = false;
1796  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1797  {
1798  if (!(*it).m_isConflicting)
1799  continue;
1800 
1801  QString title = (*it).m_info->GetTitle();
1802  if ((title.length() < 10) && !(*it).m_info->GetSubtitle().isEmpty())
1803  title += ": " + (*it).m_info->GetSubtitle();
1804  if (title.length() > 20)
1805  title = title.left(17) + "...";
1806 
1807  QString channel = m_dbChannelFormat;
1808  channel
1809  .replace("<num>", (*it).m_info->GetChanNum())
1810  .replace("<sign>", (*it).m_info->GetChannelSchedulingID())
1811  .replace("<name>", (*it).m_info->GetChannelName());
1812 
1813  if (conflict_count > 1)
1814  {
1815  message += tr("\"%1\" on %2").arg(title, channel);
1816  message += "\n";
1817  }
1818  else
1819  {
1820  message = single_rec.arg((*it).m_info->GetTitle(), channel);
1821  has_rec = (*it).m_hasRec;
1822  }
1823  }
1824 
1825  if (conflict_count > 1)
1826  {
1827  message += "\n";
1828  message += tr("Do you want to:");
1829  }
1830 
1831  bool all_have_later = true;
1832  timeuntil = 9999999ms;
1833  for (it = m_askAllowPrograms.begin(); it != m_askAllowPrograms.end(); ++it)
1834  {
1835  if ((*it).m_isConflicting)
1836  {
1837  all_have_later &= (*it).m_hasLater;
1838  auto tmp = std::chrono::milliseconds(MythDate::secsInFuture((*it).m_expiry));
1839  timeuntil = std::clamp(tmp, 0ms, timeuntil);
1840  }
1841  }
1842  timeuntil = (9999999ms == timeuntil) ? 0ms : timeuntil;
1843 
1844  if (conflict_count > 1)
1845  {
1846  BrowseEnd(false);
1847  emit ChangeOSDDialog( { OSD_DLG_ASKALLOW, message, timeuntil, {
1848  { let_recordm, "DIALOG_ASKALLOW_EXIT_0", false, true },
1849  { all_have_later ? record_laterm : do_not_recordm, "DIALOG_ASKALLOW_CANCELCONFLICTING_0" }
1850  }});
1851  }
1852  else
1853  {
1854  BrowseEnd(false);
1855  emit ChangeOSDDialog( {OSD_DLG_ASKALLOW, message, timeuntil, {
1856  { let_record1, "DIALOG_ASKALLOW_EXIT_0", false, !has_rec},
1857  { all_have_later ? record_later1 : do_not_record1, "DIALOG_ASKALLOW_CANCELRECORDING_0", false, has_rec}
1858  }});
1859  }
1860  }
1861 }
1862 
1863 void TV::HandleOSDAskAllow(const QString& Action)
1864 {
1866  return;
1867 
1868  if (!m_askAllowLock.tryLock())
1869  {
1870  LOG(VB_GENERAL, LOG_ERR, "allowrecordingbox : askAllowLock is locked");
1871  return;
1872  }
1873 
1874  if (Action == "CANCELRECORDING")
1875  {
1878  }
1879  else if (Action == "CANCELCONFLICTING")
1880  {
1881  for (const auto& pgm : std::as_const(m_askAllowPrograms))
1882  {
1883  if (pgm.m_isConflicting)
1884  RemoteCancelNextRecording(pgm.m_info->GetInputID(), true);
1885  }
1886  }
1887  else if (Action == "WATCH")
1888  {
1891  }
1892  else // if (action == "EXIT")
1893  {
1894  PrepareToExitPlayer(__LINE__);
1895  SetExitPlayer(true, true);
1896  }
1897 
1898  m_askAllowLock.unlock();
1899 }
1900 
1902 {
1903  m_wantsToQuit = false;
1904  m_jumpToProgram = false;
1905  m_allowRerecord = false;
1906  m_requestDelete = false;
1908 
1911  {
1912  ReturnPlayerLock();
1913  return 0;
1914  }
1915 
1917 
1921 
1922  ReturnPlayerLock();
1923 
1924  if (LCD *lcd = LCD::Get())
1925  {
1926  lcd->switchToChannel(ProgInfo.GetChannelSchedulingID(), ProgInfo.GetTitle(), ProgInfo.GetSubtitle());
1927  lcd->setFunctionLEDs((ProgInfo.IsRecording())?FUNC_TV:FUNC_MOVIE, true);
1928  }
1929 
1930  return 1;
1931 }
1932 
1934 {
1936 }
1937 
1939 {
1940  return (State == kState_WatchingPreRecorded ||
1945 }
1946 
1948 {
1949  return (State == kState_WatchingLiveTV);
1950 }
1951 
1952 // NOLINTBEGIN(cppcoreguidelines-macro-usage)
1953 #define TRANSITION(ASTATE,BSTATE) ((ctxState == (ASTATE)) && (desiredNextState == (BSTATE)))
1954 
1955 #define SET_NEXT() do { nextState = desiredNextState; changed = true; } while(false)
1956 #define SET_LAST() do { nextState = ctxState; changed = true; } while(false)
1957 // NOLINTEND(cppcoreguidelines-macro-usage)
1958 
1959 static QString tv_i18n(const QString &msg)
1960 {
1961  QByteArray msg_arr = msg.toLatin1();
1962  QString msg_i18n = TV::tr(msg_arr.constData());
1963  QByteArray msg_i18n_arr = msg_i18n.toLatin1();
1964  return (msg_arr == msg_i18n_arr) ? msg_i18n : msg;
1965 }
1966 
1976 {
1977  if (m_playerContext.IsErrored())
1978  {
1979  LOG(VB_GENERAL, LOG_ERR, LOC + "Called after fatal error detected.");
1980  return;
1981  }
1982 
1983  bool changed = false;
1984 
1986  TVState nextState = m_playerContext.GetState();
1987  if (m_playerContext.m_nextState.empty())
1988  {
1989  LOG(VB_GENERAL, LOG_WARNING, LOC + "Warning, called with no state to change to.");
1991  return;
1992  }
1993 
1994  TVState ctxState = m_playerContext.GetState();
1995  TVState desiredNextState = m_playerContext.DequeueNextState();
1996 
1997  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Attempting to change from %1 to %2")
1998  .arg(StateToString(nextState), StateToString(desiredNextState)));
1999 
2000  if (desiredNextState == kState_Error)
2001  {
2002  LOG(VB_GENERAL, LOG_ERR, LOC + "Attempting to set to an error state!");
2003  SetErrored();
2005  return;
2006  }
2007 
2008  bool ok = false;
2010  {
2012 
2014 
2015  QDateTime timerOffTime = MythDate::current();
2016  m_lockTimerOn = false;
2017 
2018  SET_NEXT();
2019 
2020  uint chanid = m_initialChanID;
2021  if (!chanid)
2022  chanid = static_cast<uint>(gCoreContext->GetNumSetting("DefaultChanid", 0));
2023 
2024  if (chanid && !IsTunablePriv(chanid))
2025  chanid = 0;
2026 
2027  QString channum = "";
2028 
2029  if (chanid)
2030  {
2031  QStringList reclist;
2032 
2033  MSqlQuery query(MSqlQuery::InitCon());
2034  query.prepare("SELECT channum FROM channel "
2035  "WHERE chanid = :CHANID");
2036  query.bindValue(":CHANID", chanid);
2037  if (query.exec() && query.isActive() && query.size() > 0 && query.next())
2038  channum = query.value(0).toString();
2039  else
2040  channum = QString::number(chanid);
2041 
2043  QString::number(chanid));
2044 
2045  if (getit)
2046  reclist = ChannelUtil::GetValidRecorderList(chanid, channum);
2047 
2048  if (!reclist.empty())
2049  {
2050  RemoteEncoder *testrec = RemoteRequestFreeRecorderFromList(reclist, 0);
2051  if (testrec && testrec->IsValidRecorder())
2052  {
2053  m_playerContext.SetRecorder(testrec);
2055  }
2056  else
2057  {
2058  delete testrec; // If testrec isn't a valid recorder ...
2059  }
2060  }
2061  else if (getit)
2062  {
2063  chanid = 0;
2064  }
2065  }
2066 
2067  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Spawning LiveTV Recorder -- begin");
2068 
2069  if (chanid && !channum.isEmpty())
2071  else
2073 
2074  LOG(VB_GENERAL, LOG_DEBUG, LOC + "Spawning LiveTV Recorder -- end");
2075 
2077  {
2078  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully started");
2080  m_playerContext.SetRecorder(nullptr);
2081  SetErrored();
2082  SET_LAST();
2083  }
2084  else
2085  {
2086  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2087  QString playbackURL = m_playerContext.m_playingInfo->GetPlaybackURL(true);
2088  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2089 
2090  bool opennow = (m_playerContext.m_tvchain->GetInputType(-1) != "DUMMY");
2091 
2092  LOG(VB_GENERAL, LOG_INFO, LOC +
2093  QString("playbackURL(%1) inputtype(%2)")
2094  .arg(playbackURL, m_playerContext.m_tvchain->GetInputType(-1)));
2095 
2098  playbackURL, false, true,
2099  opennow ? MythMediaBuffer::kLiveTVOpenTimeout : -1ms));
2100 
2103  }
2104 
2105 
2107  {
2108  ok = StartPlayer(desiredNextState);
2109  }
2110  if (!ok)
2111  {
2112  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully started");
2114  m_playerContext.SetRecorder(nullptr);
2115  SetErrored();
2116  SET_LAST();
2117  }
2118  else
2119  {
2120  if (!m_lastLockSeenTime.isValid() ||
2121  (m_lastLockSeenTime < timerOffTime))
2122  {
2123  m_lockTimer.start();
2124  m_lockTimerOn = true;
2125  }
2126  }
2127  }
2129  {
2130  SET_NEXT();
2132  StopStuff(true, true, true);
2133  }
2139  {
2140  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2141  QString playbackURL = m_playerContext.m_playingInfo->GetPlaybackURL(true);
2142  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2143 
2144  MythMediaBuffer *buffer = MythMediaBuffer::Create(playbackURL, false);
2145  if (buffer && !buffer->GetLastError().isEmpty())
2146  {
2147  ShowNotificationError(tr("Can't start playback"),
2148  TV::tr( "TV Player" ), buffer->GetLastError());
2149  delete buffer;
2150  buffer = nullptr;
2151  }
2153 
2155  {
2156  if (desiredNextState == kState_WatchingRecording)
2157  {
2158  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2160  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2161 
2163 
2164  if (!m_playerContext.m_recorder ||
2166  {
2167  LOG(VB_GENERAL, LOG_ERR, LOC +
2168  "Couldn't find recorder for in-progress recording");
2169  desiredNextState = kState_WatchingPreRecorded;
2170  m_playerContext.SetRecorder(nullptr);
2171  }
2172  else
2173  {
2175  }
2176  }
2177 
2178  ok = StartPlayer(desiredNextState);
2179 
2180  if (ok)
2181  {
2182  SET_NEXT();
2183 
2184  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2186  {
2187  QString message = "COMMFLAG_REQUEST ";
2189  gCoreContext->SendMessage(message);
2190  }
2191  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2192  }
2193  }
2194 
2195  if (!ok)
2196  {
2197  SET_LAST();
2198  SetErrored();
2200  {
2202  TV::tr( "TV Player" ),
2203  playbackURL);
2204  // We're going to display this error as notification
2205  // no need to display it later as popup
2207  }
2208  }
2209  }
2215  {
2216  SET_NEXT();
2218  StopStuff(true, true, false);
2219  }
2222  {
2223  SET_NEXT();
2224  }
2225 
2226  // Print state changed message...
2227  if (!changed)
2228  {
2229  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Unknown state transition: %1 to %2")
2230  .arg(StateToString(m_playerContext.GetState()), StateToString(desiredNextState)));
2231  }
2232  else if (m_playerContext.GetState() != nextState)
2233  {
2234  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Changing from %1 to %2")
2235  .arg(StateToString(m_playerContext.GetState()), StateToString(nextState)));
2236  }
2237 
2238  // update internal state variable
2239  TVState lastState = m_playerContext.GetState();
2240  m_playerContext.m_playingState = nextState;
2242 
2244  {
2245  LOG(VB_GENERAL, LOG_INFO, LOC + "State is LiveTV");
2246  UpdateOSDInput();
2247  LOG(VB_GENERAL, LOG_INFO, LOC + "UpdateOSDInput done");
2248  UpdateLCD();
2249  LOG(VB_GENERAL, LOG_INFO, LOC + "UpdateLCD done");
2250  ITVRestart(true);
2251  LOG(VB_GENERAL, LOG_INFO, LOC + "ITVRestart done");
2252  }
2253  else if (StateIsPlaying(m_playerContext.GetState()) && lastState == kState_None)
2254  {
2255  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
2256  int count = PlayGroup::GetCount();
2257  QString msg = tr("%1 Settings")
2259  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
2260  if (count > 0)
2261  emit ChangeOSDMessage(msg);
2262  ITVRestart(false);
2263  }
2264 
2266  {
2267  UpdateLCD();
2268  }
2269 
2272 
2278 
2282 
2284  {
2286  }
2287 
2294  {
2296  // m_playerBounds is not applicable when switching modes so
2297  // skip this logic in that case.
2298  if (!m_dbUseVideoModes)
2300 
2301  if (!m_weDisabledGUI)
2302  {
2303  m_weDisabledGUI = true;
2305  }
2306  // we no longer need the contents of myWindow
2307  if (m_myWindow)
2309 
2310  LOG(VB_GENERAL, LOG_INFO, LOC + "Main UI disabled.");
2311  }
2312 
2313  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + " -- end");
2314 }
2315 
2316 #undef TRANSITION
2317 #undef SET_NEXT
2318 #undef SET_LAST
2319 
2325 bool TV::StartRecorder(std::chrono::milliseconds MaxWait)
2326 {
2328  MaxWait = (MaxWait <= 0ms) ? 40s : MaxWait;
2329  MythTimer t;
2330  t.start();
2331  bool recording = false;
2332  bool ok = true;
2333  if (!rec)
2334  {
2335  LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid Remote Encoder");
2336  SetErrored();
2337  return false;
2338  }
2339  while (!(recording = rec->IsRecording(&ok)) && !m_exitPlayerTimerId && t.elapsed() < MaxWait)
2340  {
2341  if (!ok)
2342  {
2343  LOG(VB_GENERAL, LOG_ERR, LOC + "Lost contact with backend");
2344  SetErrored();
2345  return false;
2346  }
2347  std::this_thread::sleep_for(5us);
2348  }
2349 
2350  if (!recording || m_exitPlayerTimerId)
2351  {
2352  if (!m_exitPlayerTimerId)
2353  LOG(VB_GENERAL, LOG_ERR, LOC + "Timed out waiting for recorder to start");
2354  return false;
2355  }
2356 
2357  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Took %1 ms to start recorder.")
2358  .arg(t.elapsed().count()));
2359  return true;
2360 }
2361 
2375 void TV::StopStuff(bool StopRingBuffer, bool StopPlayer, bool StopRecorder)
2376 {
2377  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- begin");
2378 
2379  emit PlaybackExiting(this);
2380 
2383 
2384  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
2385  if (StopPlayer)
2387  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
2388 
2389  if (StopRingBuffer)
2390  {
2391  LOG(VB_PLAYBACK, LOG_INFO, LOC + "Stopping ring buffer");
2393  {
2397  }
2398  }
2399 
2400  if (StopRecorder)
2401  {
2402  LOG(VB_PLAYBACK, LOG_INFO, LOC + "stopping recorder");
2405  }
2406 
2407  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + "-- end");
2408 }
2409 
2410 void TV::timerEvent(QTimerEvent *Event)
2411 {
2412  const int timer_id = Event->timerId();
2413 
2415  bool errored = m_playerContext.IsErrored();
2416  ReturnPlayerLock();
2417  if (errored)
2418  return;
2419 
2420  bool handled = true;
2421  if (timer_id == m_lcdTimerId)
2423  else if (timer_id == m_lcdVolumeTimerId)
2425  else if (timer_id == m_sleepTimerId)
2426  ShowOSDSleep();
2427  else if (timer_id == m_sleepDialogTimerId)
2429  else if (timer_id == m_idleTimerId)
2430  ShowOSDIdle();
2431  else if (timer_id == m_idleDialogTimerId)
2433  else if (timer_id == m_endOfPlaybackTimerId)
2435  else if (timer_id == m_endOfRecPromptTimerId)
2437  else if (timer_id == m_videoExitDialogTimerId)
2439  else if (timer_id == m_pseudoChangeChanTimerId)
2441  else if (timer_id == m_speedChangeTimerId)
2443  else if (timer_id == m_saveLastPlayPosTimerId)
2445  else
2446  handled = false;
2447 
2448  if (handled)
2449  return;
2450 
2451  // Check if it matches a signalMonitorTimerId
2452  if (timer_id == m_signalMonitorTimerId)
2453  {
2457  if (!m_playerContext.m_lastSignalMsg.empty())
2458  {
2459  // set last signal msg, so we get some feedback...
2462  }
2464  ReturnPlayerLock();
2465  return;
2466  }
2467 
2468  // Check if it matches networkControlTimerId
2469  QString netCmd;
2470  if (timer_id == m_networkControlTimerId)
2471  {
2472  if (!m_networkControlCommands.empty())
2473  netCmd = m_networkControlCommands.dequeue();
2474  if (m_networkControlCommands.empty())
2475  {
2478  }
2479  }
2480 
2481  if (!netCmd.isEmpty())
2482  {
2485  ReturnPlayerLock();
2486  handled = true;
2487  }
2488 
2489  if (handled)
2490  return;
2491 
2492  // Check if it matches exitPlayerTimerId
2493  if (timer_id == m_exitPlayerTimerId)
2494  {
2496  emit DialogQuit();
2497  emit HideAll();
2498 
2500  {
2501  if (!m_lastProgram->IsFileReadable())
2502  {
2503  emit ChangeOSDMessage(tr("Last Program: \"%1\" Doesn't Exist")
2504  .arg(m_lastProgram->GetTitle()));
2505  lastProgramStringList.clear();
2506  SetLastProgram(nullptr);
2507  LOG(VB_PLAYBACK, LOG_ERR, LOC + "Last Program File does not exist");
2508  m_jumpToProgram = false;
2509  }
2510  else
2511  {
2513  }
2514  }
2515  else
2516  {
2518  }
2519 
2520  ReturnPlayerLock();
2521 
2523  m_exitPlayerTimerId = 0;
2524  handled = true;
2525  }
2526 
2527  if (handled)
2528  return;
2529 
2530  if (timer_id == m_ccInputTimerId)
2531  {
2533  // Clear closed caption input mode when timer expires
2534  if (m_ccInputMode)
2535  {
2536  m_ccInputMode = false;
2537  ClearInputQueues(true);
2538  }
2539  ReturnPlayerLock();
2540 
2542  m_ccInputTimerId = 0;
2543  handled = true;
2544  }
2545 
2546  if (handled)
2547  return;
2548 
2549  if (timer_id == m_asInputTimerId)
2550  {
2552  // Clear closed caption input mode when timer expires
2553  if (m_asInputMode)
2554  {
2555  m_asInputMode = false;
2556  ClearInputQueues(true);
2557  }
2558  ReturnPlayerLock();
2559 
2561  m_asInputTimerId = 0;
2562  handled = true;
2563  }
2564 
2565  if (handled)
2566  return;
2567 
2568  if (timer_id == m_queueInputTimerId)
2569  {
2571  // Commit input when the OSD fades away
2572  if (HasQueuedChannel())
2573  {
2574  OSD *osd = GetOSDL();
2575  if (osd && !osd->IsWindowVisible(OSD_WIN_INPUT))
2576  {
2577  ReturnOSDLock();
2579  }
2580  else
2581  {
2582  ReturnOSDLock();
2583  }
2584  }
2585  ReturnPlayerLock();
2586 
2587  if (!m_queuedChanID && m_queuedChanNum.isEmpty() && m_queueInputTimerId)
2588  {
2590  m_queueInputTimerId = 0;
2591  }
2592  handled = true;
2593  }
2594 
2595  if (handled)
2596  return;
2597 
2598  if (timer_id == m_browseTimerId)
2599  {
2601  BrowseEnd(false);
2602  ReturnPlayerLock();
2603  handled = true;
2604  }
2605 
2606  if (handled)
2607  return;
2608 
2609  if (timer_id == m_errorRecoveryTimerId)
2610  {
2614  {
2615  SetExitPlayer(true, false);
2617  }
2618  ReturnPlayerLock();
2619 
2623  return;
2624  }
2625 
2626  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Unknown timer: %1").arg(timer_id));
2627 }
2628 
2630 {
2632  LCD *lcd = LCD::Get();
2633  if (lcd)
2634  {
2635  float progress = 0.0F;
2636  QString lcd_time_string;
2637  bool showProgress = true;
2638 
2639  if (StateIsLiveTV(GetState()))
2641 
2643  {
2644  ShowLCDDVDInfo();
2646  }
2647 
2648  if (showProgress)
2649  {
2650  osdInfo info;
2652  progress = info.values["position"] * 0.001F;
2653 
2654  lcd_time_string = info.text["playedtime"] + " / " + info.text["totaltime"];
2655  // if the string is longer than the LCD width, remove all spaces
2656  if (lcd_time_string.length() > lcd->getLCDWidth())
2657  lcd_time_string.remove(' ');
2658  }
2659  }
2660  lcd->setChannelProgress(lcd_time_string, progress);
2661  }
2662  ReturnPlayerLock();
2663 
2665  m_lcdTimerId = StartTimer(kLCDTimeout, __LINE__);
2666 
2667  return true;
2668 }
2669 
2671 {
2673  LCD *lcd = LCD::Get();
2674  if (lcd)
2675  {
2678  }
2679  ReturnPlayerLock();
2680 
2682  m_lcdVolumeTimerId = 0;
2683 }
2684 
2685 int TV::StartTimer(std::chrono::milliseconds Interval, int Line)
2686 {
2687  int timer = startTimer(Interval);
2688  if (!timer)
2689  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to start timer on line %1 of %2").arg(Line).arg(__FILE__));
2690  return timer;
2691 }
2692 
2693 void TV::KillTimer(int Id)
2694 {
2695  killTimer(Id);
2696 }
2697 
2699 {
2702 }
2703 
2705 {
2706  auto StateChange = [&]()
2707  {
2709  if (!m_playerContext.m_nextState.empty())
2710  {
2712  if ((kState_None == m_playerContext.GetState() ||
2714  {
2715  ReturnPlayerLock();
2718  m_player = nullptr;
2719  }
2720  }
2721  ReturnPlayerLock();
2722  };
2723 
2724  QTimer::singleShot(0, this, StateChange);
2725 }
2726 
2728 {
2729  auto InputChange = [&]()
2730  {
2732  if (m_switchToInputId)
2733  {
2735  m_switchToInputId = 0;
2736  SwitchInputs(0, QString(), tmp);
2737  }
2738  ReturnPlayerLock();
2739  };
2740 
2741  QTimer::singleShot(0, this, InputChange);
2742 }
2743 
2745 {
2746  m_playerContext.m_errored = true;
2748  m_errorRecoveryTimerId = StartTimer(1ms, __LINE__);
2749 }
2750 
2752 {
2753  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Switching to program: %1")
2754  .arg(ProgInfo.toString(ProgramInfo::kTitleSubtitle)));
2756  PrepareToExitPlayer(__LINE__);
2757  m_jumpToProgram = true;
2758  SetExitPlayer(true, true);
2759 }
2760 
2762 {
2763  m_playerContext.LockDeletePlayer(__FILE__, Line);
2765  {
2766  // Clear last play position when we're at the end of a recording.
2767  // unless the recording is in-progress.
2768  bool at_end = !StateIsRecording(m_playerContext.GetState()) &&
2770 
2771  // Clear last play position on exit when the user requested this
2772  if (m_clearPosOnExit)
2773  {
2774  at_end = true;
2775  }
2776 
2777  // Save total frames for video file if not already present
2779  {
2780  auto totalFrames = m_playerContext.m_playingInfo->QueryTotalFrames();
2781  if (!totalFrames)
2782  {
2785  }
2786  }
2787 
2788  // Clear/Save play position without notification
2789  // The change must be broadcast when file is no longer in use
2790  // to update previews, ie. with the MarkNotInUse notification
2791  uint64_t frame = at_end ? 0 : m_playerContext.m_player->GetFramesPlayed();
2793  emit UpdateLastPlayPosition(frame);
2794  if (m_dbAutoSetWatched)
2795  m_player->SetWatched();
2796  }
2797  m_playerContext.UnlockDeletePlayer(__FILE__, Line);
2798 }
2799 
2800 void TV::SetExitPlayer(bool SetIt, bool WantsTo)
2801 {
2802  if (SetIt)
2803  {
2804  m_wantsToQuit = WantsTo;
2805  if (!m_exitPlayerTimerId)
2806  m_exitPlayerTimerId = StartTimer(1ms, __LINE__);
2807  }
2808  else
2809  {
2810  if (m_exitPlayerTimerId)
2812  m_exitPlayerTimerId = 0;
2813  m_wantsToQuit = WantsTo;
2814  }
2815 }
2816 
2818 {
2822 
2823  bool is_playing = false;
2825  if (StateIsPlaying(GetState()))
2826  {
2828  {
2829  is_playing = true;
2830  }
2831  // If the end of playback is destined to pop up the end of
2832  // recording delete prompt, then don't exit the player here.
2833  else if (GetState() != kState_WatchingPreRecorded ||
2835  {
2837  m_endOfRecording = true;
2838  PrepareToExitPlayer(__LINE__);
2839  SetExitPlayer(true, true);
2840  }
2841  }
2842  ReturnPlayerLock();
2843 
2844  if (is_playing)
2846 }
2847 
2849 {
2852  {
2853  return;
2854  }
2855 
2857  OSD *osd = GetOSDL();
2858  if (osd && osd->DialogVisible())
2859  {
2860  ReturnOSDLock();
2861  ReturnPlayerLock();
2862  return;
2863  }
2864  ReturnOSDLock();
2865 
2866  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
2867  bool do_prompt = (m_playerContext.GetState() == kState_WatchingPreRecorded &&
2869  !m_player->IsPlaying());
2870  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
2871 
2872  if (do_prompt)
2873  ShowOSDPromptDeleteRecording(tr("End Of Recording"));
2874 
2875  ReturnPlayerLock();
2876 }
2877 
2879 {
2883 
2884  // disable dialog and exit playback after timeout
2886  OSD *osd = GetOSDL();
2887  if (!osd || !osd->DialogVisible(OSD_DLG_VIDEOEXIT))
2888  {
2889  ReturnOSDLock();
2890  ReturnPlayerLock();
2891  return;
2892  }
2893  ReturnOSDLock();
2894  DoTogglePause(true);
2895  ClearOSD();
2896  PrepareToExitPlayer(__LINE__);
2897  ReturnPlayerLock();
2898 
2899  m_requestDelete = false;
2900  SetExitPlayer(true, true);
2901 }
2902 
2904 {
2907 
2908  bool restartTimer = false;
2911  {
2913  {
2914  restartTimer = true;
2915  }
2916  else
2917  {
2918  LOG(VB_CHANNEL, LOG_INFO, "REC_PROGRAM -- channel change");
2919 
2921  QString channum = m_playerContext.m_pseudoLiveTVRec->GetChanNum();
2923 
2924  m_playerContext.m_prevChan.clear();
2925  ChangeChannel(chanid, channum);
2928  }
2929  }
2930  ReturnPlayerLock();
2931 
2932  if (restartTimer)
2934  m_pseudoChangeChanTimerId = StartTimer(25ms, __LINE__);
2935 }
2936 
2937 void TV::SetSpeedChangeTimer(std::chrono::milliseconds When, int Line)
2938 {
2941  m_speedChangeTimerId = StartTimer(When, Line);
2942 }
2943 
2945 {
2949 
2951  bool update_msg = m_playerContext.HandlePlayerSpeedChangeFFRew();
2953  if (update_msg)
2955  ReturnPlayerLock();
2956 }
2957 
2981 bool TV::eventFilter(QObject* Object, QEvent* Event)
2982 {
2983  // We want to intercept all resize events sent to the main window
2984  if ((Event->type() == QEvent::Resize))
2985  return (m_mainWindow != Object) ? false : event(Event);
2986 
2987  // Intercept keypress events unless they need to be handled by a main UI
2988  // screen (e.g. GuideGrid, ProgramFinder)
2989 
2990  if ( (QEvent::KeyPress == Event->type() || QEvent::KeyRelease == Event->type())
2991  && m_ignoreKeyPresses )
2992  return TVPlaybackState::eventFilter(Object, Event);
2993 
2994  QScopedPointer<QEvent> sNewEvent(nullptr);
2995  if (m_mainWindow->KeyLongPressFilter(&Event, sNewEvent))
2996  return true;
2997 
2998  if (QEvent::KeyPress == Event->type())
2999  return event(Event);
3000 
3001  if (MythGestureEvent::kEventType == Event->type())
3002  return m_ignoreKeyPresses ? false : event(Event);
3003 
3004  if (Event->type() == MythEvent::kMythEventMessage ||
3005  Event->type() == MythEvent::kMythUserMessage ||
3007  Event->type() == MythMediaEvent::kEventType)
3008  {
3009  customEvent(Event);
3010  return true;
3011  }
3012 
3013  switch (Event->type())
3014  {
3015  case QEvent::Paint:
3016  case QEvent::UpdateRequest:
3017  case QEvent::Enter:
3018  {
3019  event(Event);
3020  return TVPlaybackState::eventFilter(Object, Event);
3021  }
3022  default:
3023  return TVPlaybackState::eventFilter(Object, Event);
3024  }
3025 }
3026 
3028 bool TV::event(QEvent* Event)
3029 {
3030  if (Event == nullptr)
3031  return TVPlaybackState::event(Event);
3032 
3033  if (QEvent::Resize == Event->type())
3034  {
3035  // These events probably aren't received by a direct call from
3036  // the Qt event dispacther, but are received by way of the event
3037  // dispatcher calling TV::eventFilter(MainWindow, Event).
3038  const auto *qre = dynamic_cast<const QResizeEvent*>(Event);
3039  if (qre)
3040  emit WindowResized(qre->size());
3041  return TVPlaybackState::event(Event);
3042  }
3043 
3044  if (QEvent::KeyPress == Event->type() || MythGestureEvent::kEventType == Event->type())
3045  {
3046  // These events aren't received by a direct call from the Qt
3047  // event dispacther, but are received by way of the event
3048  // dispatcher calling TV::eventFilter(MainWindow, Event).
3049 #if DEBUG_ACTIONS
3050  if (QEvent::KeyPress == Event->type())
3051  {
3052  const auto * ke = dynamic_cast<QKeyEvent*>(Event);
3053  if (ke)
3054  {
3055  LOG(VB_GENERAL, LOG_INFO, LOC + QString("keypress: %1 '%2'")
3056  .arg(ke->key()).arg(ke->text()));
3057  }
3058  }
3059  else
3060  {
3061  const auto * ge = dynamic_cast<MythGestureEvent*>(Event);
3062  if (ge)
3063  {
3064  LOG(VB_GENERAL, LOG_INFO, LOC + QString("mythgesture: g:%1 pos:%2,%3 b:%4")
3065  .arg(ge->GetGesture()).arg(ge->GetPosition().x())
3066  .arg(ge->GetPosition().y()).arg(ge->GetButton()));
3067  }
3068  }
3069 #endif
3070  bool handled = false;
3072  if (m_playerContext.HasPlayer())
3073  handled = ProcessKeypressOrGesture(Event);
3074  ReturnPlayerLock();
3075  if (handled)
3076  return true;
3077  }
3078 
3079  switch (Event->type())
3080  {
3081  case QEvent::Paint:
3082  case QEvent::UpdateRequest:
3083  case QEvent::Enter:
3084  // These events aren't received by a direct call from the Qt
3085  // event dispacther, but are received by way of the event
3086  // dispatcher calling TV::eventFilter(MainWindow, Event).
3087  return true;
3088  default:
3089  break;
3090  }
3091 
3092  return QObject::event(Event);
3093 }
3094 
3095 bool TV::HandleTrackAction(const QString &Action)
3096 {
3097  bool handled = true;
3098 
3101  else if (ACTION_ENABLEEXTTEXT == Action)
3103  else if (ACTION_DISABLEEXTTEXT == Action)
3105  else if (ACTION_ENABLEFORCEDSUBS == Action)
3106  emit ChangeAllowForcedSubtitles(true);
3107  else if (ACTION_DISABLEFORCEDSUBS == Action)
3108  emit ChangeAllowForcedSubtitles(false);
3109  else if (Action == ACTION_ENABLESUBS)
3110  emit SetCaptionsEnabled(true, true);
3111  else if (Action == ACTION_DISABLESUBS)
3112  emit SetCaptionsEnabled(false, true);
3114  {
3115  if (m_ccInputMode)
3116  {
3117  bool valid = false;
3118  int page = GetQueuedInputAsInt(&valid, 16);
3119  if (m_vbimode == VBIMode::PAL_TT && valid)
3120  emit SetTeletextPage(static_cast<uint>(page));
3121  else if (m_vbimode == VBIMode::NTSC_CC)
3122  emit SetTrack(kTrackTypeCC608, static_cast<uint>(std::clamp(page - 1, 0, 1)));
3123 
3124  ClearInputQueues(true);
3125 
3126  m_ccInputMode = false;
3127  if (m_ccInputTimerId)
3128  {
3130  m_ccInputTimerId = 0;
3131  }
3132  }
3134  {
3135  ClearInputQueues(false);
3136  AddKeyToInputQueue(0);
3137 
3138  m_ccInputMode = true;
3139  m_asInputMode = false;
3141  if (m_asInputTimerId)
3142  {
3144  m_asInputTimerId = 0;
3145  }
3146  }
3147  else
3148  {
3149  emit ToggleCaptions();
3150  }
3151  }
3152  else if (Action.startsWith("TOGGLE"))
3153  {
3154  int type = to_track_type(Action.mid(6));
3156  emit EnableTeletext();
3157  else if (type >= kTrackTypeSubtitle)
3158  emit ToggleCaptionsByType(static_cast<uint>(type));
3159  else
3160  handled = false;
3161  }
3162  else if (Action.startsWith("SELECT"))
3163  {
3164  int type = to_track_type(Action.mid(6));
3165  uint num = Action.section("_", -1).toUInt();
3166  if (type >= kTrackTypeAudio)
3167  emit SetTrack(static_cast<uint>(type), num);
3168  else
3169  handled = false;
3170  }
3171  else if (Action.startsWith("NEXT") || Action.startsWith("PREV"))
3172  {
3173  int dir = (Action.startsWith("NEXT")) ? +1 : -1;
3174  int type = to_track_type(Action.mid(4));
3175  if (type >= kTrackTypeAudio)
3176  emit ChangeTrack(static_cast<uint>(type), dir);
3177  else if (Action.endsWith("CC"))
3178  emit ChangeCaptionTrack(dir);
3179  else
3180  handled = false;
3181  }
3182  else
3183  {
3184  handled = false;
3185  }
3186  return handled;
3187 }
3188 
3189 // Make a special check for global system-related events.
3190 //
3191 // This check needs to be done early in the keypress event processing,
3192 // because FF/REW processing causes unknown events to stop FF/REW, and
3193 // manual zoom mode processing consumes all but a few event types.
3194 // Ideally, we would just call MythScreenType::keyPressEvent()
3195 // unconditionally, but we only want certain keypresses handled by
3196 // that method.
3197 //
3198 // As a result, some of the MythScreenType::keyPressEvent() string
3199 // compare logic is copied here.
3200 static bool SysEventHandleAction(MythMainWindow* MainWindow, QKeyEvent *e, const QStringList &actions)
3201 {
3202  QStringList::const_iterator it;
3203  for (it = actions.begin(); it != actions.end(); ++it)
3204  {
3205  if ((*it).startsWith("SYSEVENT") ||
3206  *it == ACTION_SCREENSHOT ||
3207  *it == ACTION_TVPOWERON ||
3208  *it == ACTION_TVPOWEROFF)
3209  {
3210  return MainWindow->GetMainStack()->GetTopScreen()->keyPressEvent(e);
3211  }
3212  }
3213  return false;
3214 }
3215 
3216 QList<QKeyEvent*> TV::ConvertScreenPressKeyMap(const QString &KeyList)
3217 {
3218  QList<QKeyEvent*> keyPressList;
3219  int i = 0;
3220  QStringList stringKeyList = KeyList.split(',');
3221  for (const auto & str : std::as_const(stringKeyList))
3222  {
3223  QKeySequence keySequence(str);
3224  for (i = 0; i < keySequence.count(); i++)
3225  {
3226 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
3227  int keynum = keySequence[i];
3228  int keyCode = keynum & ~Qt::KeyboardModifierMask;
3229  auto modifiers = static_cast<Qt::KeyboardModifiers>(keynum & Qt::KeyboardModifierMask);
3230 #else
3231  int keyCode = keySequence[i].key();
3232  Qt::KeyboardModifiers modifiers = keySequence[i].keyboardModifiers();
3233 #endif
3234  auto * keyEvent = new QKeyEvent(QEvent::None, keyCode, modifiers);
3235  keyPressList.append(keyEvent);
3236  }
3237  }
3238  if (stringKeyList.count() < kScreenPressRegionCount)
3239  {
3240  // add default remainders
3241  for(; i < kScreenPressRegionCount; i++)
3242  {
3243  auto * keyEvent = new QKeyEvent(QEvent::None, Qt::Key_Escape, Qt::NoModifier);
3244  keyPressList.append(keyEvent);
3245  }
3246  }
3247  return keyPressList;
3248 }
3249 
3250 bool TV::TranslateGesture(const QString &Context, MythGestureEvent *Event,
3251  QStringList &Actions, bool IsLiveTV)
3252 {
3253  if (Event && Context == "TV Playback")
3254  {
3255  // TODO make this configuable via a similar mechanism to
3256  // TranslateKeyPress
3257  // possibly with configurable hot zones of various sizes in a theme
3258  // TODO enhance gestures to support other non Click types too
3259  if ((Event->GetGesture() == MythGestureEvent::Click) &&
3260  (Event->GetButton() == Qt::LeftButton))
3261  {
3262  // divide screen into 12 regions
3263  QSize size = m_mainWindow->size();
3264  QPoint pos = Event->GetPosition();
3265  int region = 0;
3266  const int widthDivider = 4;
3267  int w4 = size.width() / widthDivider;
3268  region = pos.x() / w4;
3269  int h3 = size.height() / 3;
3270  region += (pos.y() / h3) * widthDivider;
3271 
3272  if (IsLiveTV)
3273  return m_mainWindow->TranslateKeyPress(Context, m_screenPressKeyMapLiveTV[region], Actions, true);
3274  return m_mainWindow->TranslateKeyPress(Context, m_screenPressKeyMapPlayback[region], Actions, true);
3275  }
3276  return false;
3277  }
3278  return false;
3279 }
3280 
3281 bool TV::TranslateKeyPressOrGesture(const QString &Context, QEvent *Event,
3282  QStringList &Actions, bool IsLiveTV, bool AllowJumps)
3283 {
3284  if (Event)
3285  {
3286  if (QEvent::KeyPress == Event->type())
3287  return m_mainWindow->TranslateKeyPress(Context, dynamic_cast<QKeyEvent*>(Event), Actions, AllowJumps);
3288  if (MythGestureEvent::kEventType == Event->type())
3289  return TranslateGesture(Context, dynamic_cast<MythGestureEvent*>(Event), Actions, IsLiveTV);
3290  }
3291  return false;
3292 }
3293 
3295 {
3296  if (Event == nullptr)
3297  return false;
3298 
3299  bool ignoreKeys = m_playerContext.IsPlayerChangingBuffers();
3300 
3301 #if DEBUG_ACTIONS
3302  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("ignoreKeys: %1").arg(ignoreKeys));
3303 #endif
3304 
3305  if (m_idleTimerId)
3306  {
3309  }
3310 
3311 #ifdef Q_OS_LINUX
3312  // Fixups for _some_ linux native codes that QT doesn't know
3313  auto* eKeyEvent = dynamic_cast<QKeyEvent*>(Event);
3314  if (eKeyEvent) {
3315  if (eKeyEvent->key() <= 0)
3316  {
3317  int keycode = 0;
3318  switch(eKeyEvent->nativeScanCode())
3319  {
3320  case 209: // XF86AudioPause
3321  keycode = Qt::Key_MediaPause;
3322  break;
3323  default:
3324  break;
3325  }
3326 
3327  if (keycode > 0)
3328  {
3329  auto *key = new QKeyEvent(QEvent::KeyPress, keycode, eKeyEvent->modifiers());
3330  QCoreApplication::postEvent(this, key);
3331  }
3332  }
3333  }
3334 #endif
3335 
3336  QStringList actions;
3337  bool handled = false;
3338  bool alreadyTranslatedPlayback = false;
3339 
3340  TVState state = GetState();
3341  bool isLiveTV = StateIsLiveTV(state);
3342 
3343  if (ignoreKeys)
3344  {
3345  handled = TranslateKeyPressOrGesture("TV Playback", Event, actions, isLiveTV);
3346  alreadyTranslatedPlayback = true;
3347 
3348  if (handled || actions.isEmpty())
3349  return handled;
3350 
3351  bool esc = IsActionable({ "ESCAPE", "BACK" }, actions);
3352  bool pause = IsActionable(ACTION_PAUSE, actions);
3353  bool play = IsActionable(ACTION_PLAY, actions);
3354 
3355  if ((!esc || m_overlayState.m_browsing) && !pause && !play)
3356  return false;
3357  }
3358 
3359  OSD *osd = GetOSDL();
3360  if (osd && osd->DialogVisible())
3361  {
3362  if (QEvent::KeyPress == Event->type())
3363  {
3364  auto *qke = dynamic_cast<QKeyEvent*>(Event);
3365  handled = (qke != nullptr) && osd->DialogHandleKeypress(qke);
3366  }
3367  if (MythGestureEvent::kEventType == Event->type())
3368  {
3369  auto *mge = dynamic_cast<MythGestureEvent*>(Event);
3370  handled = (mge != nullptr) && osd->DialogHandleGesture(mge);
3371  }
3372  }
3373  ReturnOSDLock();
3374 
3375  if (m_overlayState.m_editing && !handled)
3376  {
3377  handled |= TranslateKeyPressOrGesture("TV Editing", Event, actions, isLiveTV);
3378 
3379  if (!handled && m_player)
3380  {
3381  if (IsActionable("MENU", actions))
3382  {
3383  ShowOSDCutpoint("EDIT_CUT_POINTS");
3384  handled = true;
3385  }
3386  if (IsActionable(ACTION_MENUCOMPACT, actions))
3387  {
3388  ShowOSDCutpoint("EDIT_CUT_POINTS_COMPACT");
3389  handled = true;
3390  }
3391  if (IsActionable("ESCAPE", actions))
3392  {
3393  emit RefreshEditorState(true);
3394  if (!m_editorState.m_saved)
3395  ShowOSDCutpoint("EXIT_EDIT_MODE");
3396  else
3397  emit DisableEdit(0);
3398  handled = true;
3399  }
3400  else
3401  {
3402  emit RefreshEditorState();
3405  {
3406  ShowOSDCutpoint("EDIT_CUT_POINTS");
3407  handled = true;
3408  }
3409  else
3410  {
3411  handled |= m_player->HandleProgramEditorActions(actions);
3412  }
3413  }
3414  }
3415  }
3416 
3417  if (handled)
3418  return true;
3419 
3420  // If text is already queued up, be more lax on what is ok.
3421  // This allows hex teletext entry and minor channel entry.
3422  if (QEvent::KeyPress == Event->type())
3423  {
3424  auto *qke = dynamic_cast<QKeyEvent*>(Event);
3425  if (qke == nullptr)
3426  return false;
3427  const QString txt = qke->text();
3428  if (HasQueuedInput() && (1 == txt.length()))
3429  {
3430  bool ok = false;
3431  (void)txt.toInt(&ok, 16);
3432  if (ok || txt=="_" || txt=="-" || txt=="#" || txt==".")
3433  {
3434  AddKeyToInputQueue(txt.at(0).toLatin1());
3435  return true;
3436  }
3437  }
3438  }
3439 
3440  // Teletext menu
3442  {
3443  QStringList tt_actions;
3444  handled = TranslateKeyPressOrGesture("Teletext Menu", Event, tt_actions, isLiveTV);
3445 
3446  if (!handled && !tt_actions.isEmpty())
3447  {
3448  for (const QString& action : std::as_const(tt_actions))
3449  {
3450  emit HandleTeletextAction(action, handled);
3451  if (handled)
3452  return true;
3453  }
3454  }
3455  }
3456 
3457  // Interactive television
3459  {
3460  if (!alreadyTranslatedPlayback)
3461  {
3462  handled = TranslateKeyPressOrGesture("TV Playback", Event, actions, isLiveTV);
3463  alreadyTranslatedPlayback = true;
3464  }
3465 
3466  if (!handled && !actions.isEmpty())
3467  {
3468  for (const QString& action : std::as_const(actions))
3469  {
3470  emit HandleITVAction(action, handled);
3471  if (handled)
3472  return true;
3473  }
3474  }
3475  }
3476 
3477  if (!alreadyTranslatedPlayback)
3478  handled = TranslateKeyPressOrGesture("TV Playback", Event, actions, isLiveTV);
3479 
3480  if (handled || actions.isEmpty())
3481  return handled;
3482 
3483  handled = false;
3484 
3487 
3488  if (QEvent::KeyPress == Event->type())
3489  handled = handled || SysEventHandleAction(m_mainWindow, dynamic_cast<QKeyEvent*>(Event), actions);
3490  handled = handled || BrowseHandleAction(actions);
3491  handled = handled || ManualZoomHandleAction(actions);
3492  handled = handled || PictureAttributeHandleAction(actions);
3493  handled = handled || TimeStretchHandleAction(actions);
3494  handled = handled || AudioSyncHandleAction(actions);
3495  handled = handled || SubtitleZoomHandleAction(actions);
3496  handled = handled || SubtitleDelayHandleAction(actions);
3497  handled = handled || DiscMenuHandleAction(actions);
3498  handled = handled || ActiveHandleAction(actions, isDVD, isMenuOrStill);
3499  handled = handled || ToggleHandleAction(actions, isDVD);
3500  handled = handled || FFRewHandleAction(actions);
3501  handled = handled || ActivePostQHandleAction(actions);
3502 
3503 #if DEBUG_ACTIONS
3504  for (int i = 0; i < actions.size(); ++i)
3505  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("handled(%1) actions[%2](%3)")
3506  .arg(handled).arg(i).arg(actions[i]));
3507 #endif // DEBUG_ACTIONS
3508 
3509  if (handled)
3510  return true;
3511 
3512  if (!handled)
3513  {
3514  for (int i = 0; i < actions.size() && !handled; i++)
3515  {
3516  const QString& action = actions[i];
3517  bool ok = false;
3518  int val = action.toInt(&ok);
3519 
3520  if (ok)
3521  {
3522  AddKeyToInputQueue(static_cast<char>('0' + val));
3523  handled = true;
3524  }
3525  }
3526  }
3527 
3528  return true;
3529 }
3530 
3531 bool TV::BrowseHandleAction(const QStringList &Actions)
3532 {
3534  return false;
3535 
3536  bool handled = true;
3537 
3538  if (IsActionable({ ACTION_UP, ACTION_CHANNELUP }, Actions))
3540  else if (IsActionable( { ACTION_DOWN, ACTION_CHANNELDOWN }, Actions))
3542  else if (IsActionable(ACTION_LEFT, Actions))
3544  else if (IsActionable(ACTION_RIGHT, Actions))
3546  else if (IsActionable("NEXTFAV", Actions))
3548  else if (IsActionable(ACTION_SELECT, Actions))
3549  BrowseEnd(true);
3550  else if (IsActionable({ ACTION_CLEAROSD, "ESCAPE", "BACK", "TOGGLEBROWSE" }, Actions))
3551  BrowseEnd(false);
3552  else if (IsActionable(ACTION_TOGGLERECORD, Actions))
3553  QuickRecord();
3554  else
3555  {
3556  handled = false;
3557  for (const auto& action : std::as_const(Actions))
3558  {
3559  if (action.length() == 1 && action[0].isDigit())
3560  {
3561  AddKeyToInputQueue(action[0].toLatin1());
3562  handled = true;
3563  }
3564  }
3565  }
3566 
3567  // only pass-through actions listed below
3568  static const QStringList passthrough =
3569  {
3570  ACTION_VOLUMEUP, ACTION_VOLUMEDOWN, "STRETCHINC", "STRETCHDEC",
3571  ACTION_MUTEAUDIO, "CYCLEAUDIOCHAN", "BOTTOMLINEMOVE", "BOTTOMLINESAVE", "TOGGLEASPECT"
3572  };
3573  return handled || !IsActionable(passthrough, Actions);
3574 }
3575 
3576 bool TV::ManualZoomHandleAction(const QStringList &Actions)
3577 {
3578  if (!m_zoomMode)
3579  return false;
3580 
3581  bool endmanualzoom = false;
3582  bool handled = true;
3583  bool updateOSD = true;
3584  ZoomDirection zoom = kZoom_END;
3586  zoom = kZoomUp;
3588  zoom = kZoomDown;
3589  else if (IsActionable({ ACTION_ZOOMLEFT, ACTION_LEFT }, Actions))
3590  zoom = kZoomLeft;
3591  else if (IsActionable({ ACTION_ZOOMRIGHT, ACTION_RIGHT }, Actions))
3592  zoom = kZoomRight;
3593  else if (IsActionable({ ACTION_ZOOMASPECTUP, ACTION_VOLUMEUP }, Actions))
3594  zoom = kZoomAspectUp;
3595  else if (IsActionable({ ACTION_ZOOMASPECTDOWN, ACTION_VOLUMEDOWN }, Actions))
3596  zoom = kZoomAspectDown;
3597  else if (IsActionable({ ACTION_ZOOMIN, ACTION_JUMPFFWD }, Actions))
3598  zoom = kZoomIn;
3599  else if (IsActionable({ ACTION_ZOOMOUT, ACTION_JUMPRWND }, Actions))
3600  zoom = kZoomOut;
3601  else if (IsActionable(ACTION_ZOOMVERTICALIN, Actions))
3602  zoom = kZoomVerticalIn;
3603  else if (IsActionable(ACTION_ZOOMVERTICALOUT, Actions))
3604  zoom = kZoomVerticalOut;
3605  else if (IsActionable(ACTION_ZOOMHORIZONTALIN, Actions))
3606  zoom = kZoomHorizontalIn;
3607  else if (IsActionable(ACTION_ZOOMHORIZONTALOUT, Actions))
3608  zoom = kZoomHorizontalOut;
3609  else if (IsActionable({ ACTION_ZOOMQUIT, "ESCAPE", "BACK" }, Actions))
3610  {
3611  zoom = kZoomHome;
3612  endmanualzoom = true;
3613  }
3614  else if (IsActionable({ ACTION_ZOOMCOMMIT, ACTION_SELECT }, Actions))
3615  {
3616  endmanualzoom = true;
3617  SetManualZoom(false, tr("Zoom Committed"));
3618  }
3619  else
3620  {
3621  updateOSD = false;
3622  // only pass-through actions listed below
3623  static const QStringList passthrough =
3624  {
3625  "STRETCHINC", "STRETCHDEC", ACTION_MUTEAUDIO,
3626  "CYCLEAUDIOCHAN", ACTION_PAUSE, ACTION_CLEAROSD
3627  };
3628  handled = !IsActionable(passthrough, Actions);
3629  }
3630 
3631  QString msg = tr("Zoom Committed");
3632  if (zoom != kZoom_END)
3633  {
3634  emit ChangeZoom(zoom);
3635  msg = endmanualzoom ? tr("Zoom Ignored") :
3639  }
3640  else if (endmanualzoom)
3641  {
3642  msg = tr("%1 Committed").arg(GetZoomString(m_videoBoundsState.m_manualHorizScale,
3645  }
3646 
3647  if (updateOSD)
3648  SetManualZoom(!endmanualzoom, msg);
3649 
3650  return handled;
3651 }
3652 
3653 bool TV::PictureAttributeHandleAction(const QStringList &Actions)
3654 {
3655  if (!m_adjustingPicture)
3656  return false;
3657 
3658  bool up = IsActionable(ACTION_RIGHT, Actions);
3659  bool down = up ? false : IsActionable(ACTION_LEFT, Actions);
3660  if (!(up || down))
3661  return false;
3662 
3664  {
3666  VolumeChange(up);
3667  else
3669  return true;
3670  }
3671 
3672  int value = 99;
3676  UpdateOSDStatus(toTitleString(m_adjustingPicture), text, QString::number(value),
3678  emit ChangeOSDPositionUpdates(false);
3679  return true;
3680 }
3681 
3682 bool TV::TimeStretchHandleAction(const QStringList &Actions)
3683 {
3684  if (!m_stretchAdjustment)
3685  return false;
3686 
3687  bool handled = true;
3688 
3689  if (IsActionable(ACTION_LEFT, Actions))
3690  ChangeTimeStretch(-1);
3691  else if (IsActionable(ACTION_RIGHT, Actions))
3692  ChangeTimeStretch(1);
3693  else if (IsActionable(ACTION_DOWN, Actions))
3694  ChangeTimeStretch(-5);
3695  else if (IsActionable(ACTION_UP, Actions))
3696  ChangeTimeStretch(5);
3697  else if (IsActionable("ADJUSTSTRETCH", Actions))
3699  else if (IsActionable(ACTION_SELECT, Actions))
3700  ClearOSD();
3701  else
3702  handled = false;
3703 
3704  return handled;
3705 }
3706 
3707 bool TV::AudioSyncHandleAction(const QStringList& Actions)
3708 {
3709  if (!m_audiosyncAdjustment)
3710  return false;
3711 
3712  bool handled = true;
3713 
3714  if (IsActionable(ACTION_LEFT, Actions))
3715  emit ChangeAudioOffset(-1ms);
3716  else if (IsActionable(ACTION_RIGHT, Actions))
3717  emit ChangeAudioOffset(1ms);
3718  else if (IsActionable(ACTION_UP, Actions))
3719  emit ChangeAudioOffset(10ms);
3720  else if (IsActionable(ACTION_DOWN, Actions))
3721  emit ChangeAudioOffset(-10ms);
3722  else if (IsActionable({ ACTION_TOGGELAUDIOSYNC, ACTION_SELECT }, Actions))
3723  ClearOSD();
3724  else
3725  handled = false;
3726 
3727  return handled;
3728 }
3729 
3730 bool TV::SubtitleZoomHandleAction(const QStringList &Actions)
3731 {
3733  return false;
3734 
3735  bool handled = true;
3736 
3737  if (IsActionable(ACTION_LEFT, Actions))
3738  emit AdjustSubtitleZoom(-1);
3739  else if (IsActionable(ACTION_RIGHT, Actions))
3740  emit AdjustSubtitleZoom(1);
3741  else if (IsActionable(ACTION_UP, Actions))
3742  emit AdjustSubtitleZoom(10);
3743  else if (IsActionable(ACTION_DOWN, Actions))
3744  emit AdjustSubtitleZoom(-10);
3745  else if (IsActionable({ ACTION_TOGGLESUBTITLEZOOM, ACTION_SELECT }, Actions))
3746  ClearOSD();
3747  else
3748  handled = false;
3749 
3750  return handled;
3751 }
3752 
3753 bool TV::SubtitleDelayHandleAction(const QStringList &Actions)
3754 {
3756  return false;
3757 
3758  bool handled = true;
3759 
3760  if (IsActionable(ACTION_LEFT, Actions))
3761  emit AdjustSubtitleDelay(-5ms);
3762  else if (IsActionable(ACTION_RIGHT, Actions))
3763  emit AdjustSubtitleDelay(5ms);
3764  else if (IsActionable(ACTION_UP, Actions))
3765  emit AdjustSubtitleDelay(25ms);
3766  else if (IsActionable(ACTION_DOWN, Actions))
3767  emit AdjustSubtitleDelay(-25ms);
3768  else if (IsActionable({ ACTION_TOGGLESUBTITLEDELAY, ACTION_SELECT }, Actions))
3769  ClearOSD();
3770  else
3771  handled = false;
3772 
3773  return handled;
3774 }
3775 
3776 bool TV::DiscMenuHandleAction(const QStringList& Actions) const
3777 {
3778  mpeg::chrono::pts pts = 0_pts;
3780  if (output)
3781  {
3782  MythVideoFrame *frame = output->GetLastShownFrame();
3783  // convert timecode (msec) to pts (90kHz)
3784  if (frame)
3785  pts = duration_cast<mpeg::chrono::pts>(frame->m_timecode);
3786  }
3788  return m_playerContext.m_buffer->HandleAction(Actions, pts);
3789  return false;
3790 }
3791 
3792 bool TV::ActiveHandleAction(const QStringList &Actions,
3793  bool IsDVD, bool IsDVDStillFrame)
3794 {
3795  bool handled = true;
3796 
3797  if (IsActionable("SKIPCOMMERCIAL", Actions) && !IsDVD)
3798  DoSkipCommercials(1);
3799  else if (IsActionable("SKIPCOMMBACK", Actions) && !IsDVD)
3800  DoSkipCommercials(-1);
3801  else if (IsActionable("QUEUETRANSCODE", Actions) && !IsDVD)
3802  DoQueueTranscode("Default");
3803  else if (IsActionable("QUEUETRANSCODE_AUTO", Actions) && !IsDVD)
3804  DoQueueTranscode("Autodetect");
3805  else if (IsActionable("QUEUETRANSCODE_HIGH", Actions) && !IsDVD)
3806  DoQueueTranscode("High Quality");
3807  else if (IsActionable("QUEUETRANSCODE_MEDIUM", Actions) && !IsDVD)
3808  DoQueueTranscode("Medium Quality");
3809  else if (IsActionable("QUEUETRANSCODE_LOW", Actions) && !IsDVD)
3810  DoQueueTranscode("Low Quality");
3811  else if (IsActionable(ACTION_PLAY, Actions))
3812  DoPlay();
3813  else if (IsActionable(ACTION_PAUSE, Actions))
3814  DoTogglePause(true);
3815  else if (IsActionable("SPEEDINC", Actions) && !IsDVDStillFrame)
3816  ChangeSpeed(1);
3817  else if (IsActionable("SPEEDDEC", Actions) && !IsDVDStillFrame)
3818  ChangeSpeed(-1);
3819  else if (IsActionable("ADJUSTSTRETCH", Actions))
3820  ChangeTimeStretch(0); // just display
3821  else if (IsActionable("CYCLECOMMSKIPMODE",Actions) && !IsDVD)
3823  else if (IsActionable("NEXTSCAN", Actions))
3824  {
3825  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
3827  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
3828  OverrideScan(scan);
3829  }
3830  else if (IsActionable(ACTION_SEEKARB, Actions) && !IsDVD)
3831  {
3832  if (m_asInputMode)
3833  {
3834  ClearInputQueues(true);
3835  emit ChangeOSDText(OSD_WIN_INPUT, {{"osd_number_entry", tr("Seek:")}}, kOSDTimeout_Med);
3836  m_asInputMode = false;
3837  if (m_asInputTimerId)
3838  {
3840  m_asInputTimerId = 0;
3841  }
3842  }
3843  else
3844  {
3845  ClearInputQueues(false);
3846  AddKeyToInputQueue(0);
3847  m_asInputMode = true;
3848  m_ccInputMode = false;
3850  if (m_ccInputTimerId)
3851  {
3853  m_ccInputTimerId = 0;
3854  }
3855  }
3856  }
3857  else if (IsActionable(ACTION_JUMPRWND, Actions))
3858  {
3859  DoJumpRWND();
3860  }
3861  else if (IsActionable(ACTION_JUMPFFWD, Actions))
3862  {
3863  DoJumpFFWD();
3864  }
3865  else if (IsActionable(ACTION_JUMPBKMRK, Actions))
3866  {
3867  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
3868  uint64_t bookmark = m_player->GetBookmark();
3869  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
3870 
3871  if (bookmark)
3872  {
3873  DoPlayerSeekToFrame(bookmark);
3874  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
3875  UpdateOSDSeekMessage(tr("Jump to Bookmark"), kOSDTimeout_Med);
3876  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
3877  }
3878  }
3879  else if (IsActionable(ACTION_JUMPSTART,Actions))
3880  {
3881  DoSeek(0, tr("Jump to Beginning"), /*timeIsOffset*/false, /*honorCutlist*/true);
3882  }
3883  else if (IsActionable(ACTION_CLEAROSD, Actions))
3884  {
3885  ClearOSD();
3886  }
3887  else if (IsActionable(ACTION_VIEWSCHEDULED, Actions))
3888  {
3890  }
3891  else if (HandleJumpToProgramAction(Actions))
3892  { // NOLINT(bugprone-branch-clone)
3893  }
3894  else if (IsActionable(ACTION_SIGNALMON, Actions))
3895  {
3897  {
3898  QString input = m_playerContext.m_recorder->GetInput();
3900 
3901  if (timeout == 0xffffffff)
3902  {
3903  emit ChangeOSDMessage("No Signal Monitor");
3904  return false;
3905  }
3906 
3907  std::chrono::milliseconds rate = m_sigMonMode ? 0ms : 100ms;
3908  bool notify = !m_sigMonMode;
3909 
3910  PauseLiveTV();
3912  UnpauseLiveTV();
3913 
3914  m_lockTimerOn = false;
3916  }
3917  }
3918  else if (IsActionable(ACTION_SCREENSHOT, Actions))
3919  {
3921  }
3922  else if (IsActionable(ACTION_STOP, Actions))
3923  {
3924  PrepareToExitPlayer(__LINE__);
3925  SetExitPlayer(true, true);
3926  }
3927  else if (IsActionable(ACTION_EXITSHOWNOPROMPTS, Actions))
3928  {
3929  m_requestDelete = false;
3930  PrepareToExitPlayer(__LINE__);
3931  SetExitPlayer(true, true);
3932  }
3933  else if (IsActionable({ "ESCAPE", "BACK" }, Actions))
3934  {
3937  {
3938  ClearOSD();
3939  }
3940  else
3941  {
3942  bool visible = false;
3943  emit IsOSDVisible(visible);
3944  if (visible)
3945  {
3946  ClearOSD();
3947  return handled;
3948  }
3949  }
3950 
3951  NormalSpeed();
3952  StopFFRew();
3953  bool exit = false;
3954  if (StateIsLiveTV(GetState()))
3955  {
3957  {
3959  return handled;
3960  }
3961  exit = true;
3962  }
3963  else
3964  {
3966  !m_underNetworkControl && !IsDVDStillFrame)
3967  {
3969  return handled;
3970  }
3971  if (16 & m_dbPlaybackExitPrompt)
3972  {
3973  m_clearPosOnExit = true;
3974  }
3975  PrepareToExitPlayer(__LINE__);
3976  m_requestDelete = false;
3977  exit = true;
3978  }
3979 
3980  if (exit)
3981  {
3982  // If it's a DVD, and we're not trying to execute a
3983  // jumppoint, try to back up.
3984  if (IsDVD && !m_mainWindow->IsExitingToMain() && IsActionable("BACK", Actions) &&
3986  {
3987  return handled;
3988  }
3989  SetExitPlayer(true, true);
3990  }
3991  }
3992  else if (IsActionable(ACTION_ENABLEUPMIX, Actions))
3993  {
3994  emit ChangeUpmix(true);
3995  }
3996  else if (IsActionable(ACTION_DISABLEUPMIX, Actions))
3997  {
3998  emit ChangeUpmix(false);
3999  }
4000  else if (IsActionable(ACTION_VOLUMEDOWN, Actions))
4001  {
4002  VolumeChange(false);
4003  }
4004  else if (IsActionable(ACTION_VOLUMEUP, Actions))
4005  {
4006  VolumeChange(true);
4007  }
4008  else if (IsActionable("CYCLEAUDIOCHAN", Actions))
4009  {
4010  emit ChangeMuteState(true);
4011  }
4012  else if (IsActionable(ACTION_MUTEAUDIO, Actions))
4013  {
4014  emit ChangeMuteState();
4015  }
4016  else if (IsActionable("STRETCHINC", Actions))
4017  {
4018  ChangeTimeStretch(1);
4019  }
4020  else if (IsActionable("STRETCHDEC", Actions))
4021  {
4022  ChangeTimeStretch(-1);
4023  }
4024  else if (IsActionable("MENU", Actions))
4025  {
4026  ShowOSDMenu();
4027  }
4028  else if (IsActionable(ACTION_MENUCOMPACT, Actions))
4029  {
4030  ShowOSDMenu(true);
4031  }
4032  else if (IsActionable({ "INFO", "INFOWITHCUTLIST" }, Actions))
4033  {
4034  if (HasQueuedInput())
4035  DoArbSeek(ARBSEEK_SET, IsActionable("INFOWITHCUTLIST", Actions));
4036  else
4037  ToggleOSD(true);
4038  }
4039  else if (IsActionable(ACTION_TOGGLEOSDDEBUG, Actions))
4040  {
4041  emit ChangeOSDDebug();
4042  }
4043  else if (!IsDVDStillFrame && SeekHandleAction(Actions, IsDVD))
4044  {
4045  }
4046  else if (IsActionable(ACTION_SELECT, Actions) && HasQueuedChannel())
4047  {
4049  }
4050  else
4051  {
4052  handled = false;
4053  for (auto it = Actions.cbegin(); it != Actions.cend() && !handled; ++it)
4054  handled = HandleTrackAction(*it);
4055  }
4056 
4057  return handled;
4058 }
4059 
4060 bool TV::FFRewHandleAction(const QStringList &Actions)
4061 {
4062  bool handled = false;
4063 
4065  {
4066  for (int i = 0; i < Actions.size() && !handled; i++)
4067  {
4068  const QString& action = Actions[i];
4069  bool ok = false;
4070  int val = action.toInt(&ok);
4071 
4072  if (ok && val < static_cast<int>(m_ffRewSpeeds.size()))
4073  {
4074  SetFFRew(val);
4075  handled = true;
4076  }
4077  }
4078 
4079  if (!handled)
4080  {
4083  handled = true;
4084  }
4085  }
4086 
4088  {
4089  NormalSpeed();
4091  handled = true;
4092  }
4093 
4094  return handled;
4095 }
4096 
4097 bool TV::ToggleHandleAction(const QStringList &Actions, bool IsDVD)
4098 {
4099  bool handled = true;
4100  bool islivetv = StateIsLiveTV(GetState());
4101 
4102  if (IsActionable(ACTION_BOTTOMLINEMOVE, Actions))
4103  emit ToggleMoveBottomLine();
4104  else if (IsActionable(ACTION_BOTTOMLINESAVE, Actions))
4105  emit SaveBottomLine();
4106  else if (IsActionable("TOGGLEASPECT", Actions))
4107  emit ChangeAspectOverride();
4108  else if (IsActionable("TOGGLEFILL", Actions))
4109  emit ChangeAdjustFill();
4110  else if (IsActionable(ACTION_TOGGELAUDIOSYNC, Actions))
4111  emit ChangeAudioOffset(0ms); // just display
4112  else if (IsActionable(ACTION_TOGGLESUBTITLEZOOM, Actions))
4113  emit AdjustSubtitleZoom(0); // just display
4114  else if (IsActionable(ACTION_TOGGLESUBTITLEDELAY, Actions))
4115  emit AdjustSubtitleDelay(0ms); // just display
4116  else if (IsActionable(ACTION_TOGGLEVISUALISATION, Actions))
4117  emit EnableVisualiser(false, true);
4118  else if (IsActionable(ACTION_ENABLEVISUALISATION, Actions))
4119  emit EnableVisualiser(true);
4120  else if (IsActionable(ACTION_DISABLEVISUALISATION, Actions))
4121  emit EnableVisualiser(false);
4122  else if (IsActionable("TOGGLEPICCONTROLS", Actions))
4124  else if (IsActionable("TOGGLESTRETCH", Actions))
4126  else if (IsActionable(ACTION_TOGGLEUPMIX, Actions))
4127  emit ChangeUpmix(false, true);
4128  else if (IsActionable(ACTION_TOGGLESLEEP, Actions))
4129  ToggleSleepTimer();
4130  else if (IsActionable(ACTION_TOGGLERECORD, Actions) && islivetv)
4131  QuickRecord();
4132  else if (IsActionable(ACTION_TOGGLEFAV, Actions) && islivetv)
4134  else if (IsActionable(ACTION_TOGGLECHANCONTROLS, Actions) && islivetv)
4136  else if (IsActionable(ACTION_TOGGLERECCONTROLS, Actions) && islivetv)
4138  else if (IsActionable("TOGGLEBROWSE", Actions))
4139  {
4140  if (islivetv)
4141  BrowseStart();
4142  else if (!IsDVD)
4143  ShowOSDMenu();
4144  else
4145  handled = false;
4146  }
4147  else if (IsActionable("EDIT", Actions))
4148  {
4149  if (islivetv)
4151  else if (!IsDVD)
4153  }
4154  else if (IsActionable(ACTION_OSDNAVIGATION, Actions))
4155  {
4157  }
4158  else
4159  {
4160  handled = false;
4161  }
4162 
4163  return handled;
4164 }
4165 
4167 {
4168  if (Clear)
4169  {
4170  emit UpdateBookmark(true);
4171  emit ChangeOSDMessage(tr("Bookmark Cleared"));
4172  }
4173  else // if (IsBookmarkAllowed(ctx))
4174  {
4175  emit UpdateBookmark();
4176  osdInfo info;
4178  info.text["title"] = tr("Position");
4180  emit ChangeOSDMessage(tr("Bookmark Saved"));
4181  }
4182 }
4183 
4184 bool TV::ActivePostQHandleAction(const QStringList &Actions)
4185 {
4186  bool handled = true;
4187  TVState state = GetState();
4188  bool islivetv = StateIsLiveTV(state);
4189  bool isdvd = state == kState_WatchingDVD;
4190  bool isdisc = isdvd || state == kState_WatchingBD;
4191 
4192  if (IsActionable(ACTION_SETBOOKMARK, Actions))
4193  {
4194  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4195  SetBookmark(false);
4196  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4197  }
4198  if (IsActionable(ACTION_TOGGLEBOOKMARK, Actions))
4199  {
4200  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4201  SetBookmark(m_player->GetBookmark() != 0U);
4202  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4203  }
4204  else if (IsActionable("NEXTFAV", Actions) && islivetv)
4205  {
4207  }
4208  else if (IsActionable("NEXTSOURCE", Actions) && islivetv)
4209  {
4211  }
4212  else if (IsActionable("PREVSOURCE", Actions) && islivetv)
4213  {
4215  }
4216  else if (IsActionable("NEXTINPUT", Actions) && islivetv)
4217  {
4218  SwitchInputs();
4219  }
4220  else if (IsActionable(ACTION_GUIDE, Actions))
4221  {
4223  }
4224  else if (IsActionable("PREVCHAN", Actions) && islivetv)
4225  {
4226  PopPreviousChannel(false);
4227  }
4228  else if (IsActionable(ACTION_CHANNELUP, Actions))
4229  {
4230  if (islivetv)
4231  {
4232  if (m_dbBrowseAlways)
4234  else
4236  }
4237  else
4238  {
4239  DoJumpRWND();
4240  }
4241  }
4242  else if (IsActionable(ACTION_CHANNELDOWN, Actions))
4243  {
4244  if (islivetv)
4245  {
4246  if (m_dbBrowseAlways)
4248  else
4250  }
4251  else
4252  {
4253  DoJumpFFWD();
4254  }
4255  }
4256  else if (IsActionable("DELETE", Actions) && !islivetv)
4257  {
4258  NormalSpeed();
4259  StopFFRew();
4260  PrepareToExitPlayer(__LINE__);
4261  ShowOSDPromptDeleteRecording(tr("Are you sure you want to delete:"));
4262  }
4263  else if (IsActionable(ACTION_JUMPTODVDROOTMENU, Actions) && isdisc)
4264  {
4265  emit GoToMenu("root");
4266  }
4267  else if (IsActionable(ACTION_JUMPTODVDCHAPTERMENU, Actions) && isdisc)
4268  {
4269  emit GoToMenu("chapter");
4270  }
4271  else if (IsActionable(ACTION_JUMPTODVDTITLEMENU, Actions) && isdisc)
4272  {
4273  emit GoToMenu("title");
4274  }
4275  else if (IsActionable(ACTION_JUMPTOPOPUPMENU, Actions) && isdisc)
4276  {
4277  emit GoToMenu("popup");
4278  }
4279  else if (IsActionable(ACTION_FINDER, Actions))
4280  {
4282  }
4283  else
4284  {
4285  handled = false;
4286  }
4287 
4288  return handled;
4289 }
4290 
4291 
4293 {
4294  bool ignoreKeys = m_playerContext.IsPlayerChangingBuffers();
4295 
4296 #ifdef DEBUG_ACTIONS
4297  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("(%1) ignoreKeys: %2").arg(Command).arg(ignoreKeys));
4298 #endif
4299 
4300  if (ignoreKeys)
4301  {
4302  LOG(VB_GENERAL, LOG_WARNING, LOC + "Ignoring network control command because ignoreKeys is set");
4303  return;
4304  }
4305 
4306  QStringList tokens = Command.split(" ", Qt::SkipEmptyParts);
4307  if (tokens.size() < 2)
4308  {
4309  LOG(VB_GENERAL, LOG_ERR, LOC + "Not enough tokens in network control command " + QString("'%1'").arg(Command));
4310  return;
4311  }
4312 
4313  OSD *osd = GetOSDL();
4314  bool dlg = false;
4315  if (osd)
4316  dlg = osd->DialogVisible();
4317  ReturnOSDLock();
4318 
4319  if (dlg)
4320  {
4321  LOG(VB_GENERAL, LOG_WARNING, LOC +
4322  "Ignoring network control command\n\t\t\t" +
4323  QString("because dialog is waiting for a response"));
4324  return;
4325  }
4326 
4327  if (tokens[1] != "QUERY")
4328  ClearOSD();
4329 
4330  if (tokens.size() == 3 && tokens[1] == "CHANID")
4331  {
4332  m_queuedChanID = tokens[2].toUInt();
4333  m_queuedChanNum.clear();
4335  }
4336  else if (tokens.size() == 3 && tokens[1] == "CHANNEL")
4337  {
4338  if (StateIsLiveTV(GetState()))
4339  {
4340  static const QRegularExpression kChannelNumRE { R"(^[-\.\d_#]+$)" };
4341  if (tokens[2] == "UP")
4343  else if (tokens[2] == "DOWN")
4345  else if (tokens[2].contains(kChannelNumRE))
4346  ChangeChannel(0, tokens[2]);
4347  }
4348  }
4349  else if (tokens.size() == 3 && tokens[1] == "SPEED")
4350  {
4351  bool paused = ContextIsPaused(__FILE__, __LINE__);
4352 
4353  if (tokens[2] == "0x")
4354  {
4355  NormalSpeed();
4356  StopFFRew();
4357  if (!paused)
4358  DoTogglePause(true);
4359  }
4360  else if (tokens[2] == "normal")
4361  {
4362  NormalSpeed();
4363  StopFFRew();
4364  if (paused)
4365  DoTogglePause(true);
4366  return;
4367  }
4368  else
4369  {
4370  static const QRegularExpression kSpeedRE { R"(^\-*(\d*\.)?\d+x$)" };
4371  float tmpSpeed = 1.0F;
4372  bool ok = false;
4373 
4374  if (tokens[2].contains(kSpeedRE))
4375  {
4376  QString speed = tokens[2].left(tokens[2].length()-1);
4377  tmpSpeed = speed.toFloat(&ok);
4378  }
4379  else
4380  {
4381  static const QRegularExpression re { R"(^(\-*\d+)\/(\d+)x$)" };
4382  auto match = re.match(tokens[2]);
4383  if (match.hasMatch())
4384  {
4385  QStringList matches = match.capturedTexts();
4386  int numerator = matches[1].toInt(&ok);
4387  int denominator = matches[2].toInt(&ok);
4388 
4389  if (ok && denominator != 0)
4390  tmpSpeed = static_cast<float>(numerator) / static_cast<float>(denominator);
4391  else
4392  ok = false;
4393  }
4394  }
4395 
4396  if (ok)
4397  {
4398  float searchSpeed = fabs(tmpSpeed);
4399 
4400  if (paused)
4401  DoTogglePause(true);
4402 
4403  if (tmpSpeed == 0.0F)
4404  {
4405  NormalSpeed();
4406  StopFFRew();
4407 
4408  if (!paused)
4409  DoTogglePause(true);
4410  }
4411  else if (tmpSpeed == 1.0F)
4412  {
4413  StopFFRew();
4414  m_playerContext.m_tsNormal = 1.0F;
4415  ChangeTimeStretch(0, false);
4416  return;
4417  }
4418 
4419  NormalSpeed();
4420 
4421  size_t index = 0;
4422  for ( ; index < m_ffRewSpeeds.size(); index++)
4423  if (m_ffRewSpeeds[index] == static_cast<int>(searchSpeed))
4424  break;
4425 
4426  if ((index < m_ffRewSpeeds.size()) && (m_ffRewSpeeds[index] == static_cast<int>(searchSpeed)))
4427  {
4428  if (tmpSpeed < 0)
4430  else if (tmpSpeed > 1)
4432  else
4433  StopFFRew();
4434 
4436  SetFFRew(static_cast<int>(index));
4437  }
4438  else if (0.125F <= tmpSpeed && tmpSpeed <= 2.0F)
4439  {
4440  StopFFRew();
4441  m_playerContext.m_tsNormal = tmpSpeed; // alter speed before display
4442  ChangeTimeStretch(0, false);
4443  }
4444  else
4445  {
4446  LOG(VB_GENERAL, LOG_WARNING, QString("Couldn't find %1 speed. Setting Speed to 1x")
4447  .arg(static_cast<double>(searchSpeed)));
4450  }
4451  }
4452  else
4453  {
4454  LOG(VB_GENERAL, LOG_ERR, QString("Found an unknown speed of %1").arg(tokens[2]));
4455  }
4456  }
4457  }
4458  else if (tokens.size() == 2 && tokens[1] == "STOP")
4459  {
4460  PrepareToExitPlayer(__LINE__);
4461  SetExitPlayer(true, true);
4462  }
4463  else if (tokens.size() >= 3 && tokens[1] == "SEEK" && m_playerContext.HasPlayer())
4464  {
4465  static const QRegularExpression kDigitsRE { "^\\d+$" };
4467  return;
4468 
4469  if (tokens[2] == "BEGINNING")
4470  {
4471  DoSeek(0, tr("Jump to Beginning"), /*timeIsOffset*/false, /*honorCutlist*/true);
4472  }
4473  else if (tokens[2] == "FORWARD")
4474  {
4475  DoSeek(m_playerContext.m_fftime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
4476  }
4477  else if (tokens[2] == "BACKWARD")
4478  {
4479  DoSeek(-m_playerContext.m_rewtime, tr("Skip Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
4480  }
4481  else if ((tokens[2] == "POSITION" ||
4482  tokens[2] == "POSITIONWITHCUTLIST") &&
4483  (tokens.size() == 4) &&
4484  (tokens[3].contains(kDigitsRE)))
4485  {
4486  DoSeekAbsolute(tokens[3].toInt(), tokens[2] == "POSITIONWITHCUTLIST");
4487  }
4488  }
4489  else if (tokens.size() >= 3 && tokens[1] == "SUBTITLES")
4490  {
4491  bool ok = false;
4492  uint track = tokens[2].toUInt(&ok);
4493 
4494  if (!ok)
4495  return;
4496 
4497  if (track == 0)
4498  {
4499  emit SetCaptionsEnabled(false, true);
4500  }
4501  else
4502  {
4503  QStringList subs = m_player->GetTracks(kTrackTypeSubtitle);
4504  uint size = static_cast<uint>(subs.size());
4505  uint start = 1;
4506  uint finish = start + size;
4507  if (track >= start && track < finish)
4508  {
4509  emit SetTrack(kTrackTypeSubtitle, track - start);
4511  return;
4512  }
4513 
4514  start = finish + 1;
4516  finish = start + size;
4517  if (track >= start && track < finish)
4518  {
4519  emit SetTrack(kTrackTypeCC708, track - start);
4521  return;
4522  }
4523 
4524  start = finish + 1;
4526  finish = start + size;
4527  if (track >= start && track < finish)
4528  {
4529  emit SetTrack(kTrackTypeCC608, track - start);
4531  return;
4532  }
4533 
4534  start = finish + 1;
4536  finish = start + size;
4537  if (track >= start && track < finish)
4538  {
4539  emit SetTrack(kTrackTypeTeletextCaptions, track - start);
4541  return;
4542  }
4543 
4544  start = finish + 1;
4546  finish = start + size;
4547  if (track >= start && track < finish)
4548  {
4549  emit SetTrack(kTrackTypeTeletextMenu, track - start);
4551  return;
4552  }
4553 
4554  start = finish + 1;
4556  finish = start + size;
4557  if (track >= start && track < finish)
4558  {
4559  emit SetTrack(kTrackTypeRawText, track - start);
4561  return;
4562  }
4563  }
4564  }
4565  else if (tokens.size() >= 3 && tokens[1] == "VOLUME")
4566  {
4567  static const QRegularExpression re { "(\\d+)%?" };
4568  auto match = re.match(tokens[2]);
4569  if (match.hasMatch())
4570  {
4571  QStringList matches = match.capturedTexts();
4572 
4573  LOG(VB_GENERAL, LOG_INFO, QString("Set Volume to %1%").arg(matches[1]));
4574 
4575  bool ok = false;
4576  int vol = matches[1].toInt(&ok);
4577  if (!ok)
4578  return;
4579 
4580  if (0 <= vol && vol <= 100)
4581  emit ChangeVolume(true, vol);
4582  }
4583  }
4584  else if (tokens.size() >= 3 && tokens[1] == "QUERY")
4585  {
4586  if (tokens[2] == "POSITION")
4587  {
4588  if (!m_player)
4589  return;
4590  QString speedStr;
4591  if (ContextIsPaused(__FILE__, __LINE__))
4592  {
4593  speedStr = "pause";
4594  }
4595  else if (m_playerContext.m_ffRewState)
4596  {
4597  speedStr = QString("%1x").arg(m_playerContext.m_ffRewSpeed);
4598  }
4599  else
4600  {
4601  static const QRegularExpression re { "Play (.*)x" };
4602  auto match = re.match(m_playerContext.GetPlayMessage());
4603  if (match.hasMatch())
4604  {
4605  QStringList matches = match.capturedTexts();
4606  speedStr = QString("%1x").arg(matches[1]);
4607  }
4608  else
4609  {
4610  speedStr = "1x";
4611  }
4612  }
4613 
4614  osdInfo info;
4616 
4617  QDateTime respDate = MythDate::current(true);
4618  QString infoStr = "";
4619 
4620  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4621  uint64_t fplay = 0;
4622  double rate = 30.0;
4623  if (m_player)
4624  {
4625  fplay = m_player->GetFramesPlayed();
4626  rate = static_cast<double>(m_player->GetFrameRate()); // for display only
4627  }
4628  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4629 
4630  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
4632  {
4633  infoStr = "LiveTV";
4636  }
4637  else
4638  {
4640  infoStr = "DVD";
4642  infoStr = "Recorded";
4643  else
4644  infoStr = "Video";
4645 
4648  }
4649 
4650  QString bufferFilename =
4651  m_playerContext.m_buffer ? m_playerContext.m_buffer->GetFilename() : QString("no buffer");
4652  if ((infoStr == "Recorded") || (infoStr == "LiveTV"))
4653  {
4654  infoStr += QString(" %1 %2 %3 %4 %5 %6 %7")
4655  .arg(info.text["description"],
4656  speedStr,
4657  m_playerContext.m_playingInfo != nullptr
4658  ? QString::number(m_playerContext.m_playingInfo->GetChanID()) : "0",
4659  respDate.toString(Qt::ISODate),
4660  QString::number(fplay),
4661  bufferFilename,
4662  QString::number(rate));
4663  }
4664  else
4665  {
4666  QString position = info.text["description"].section(" ",0,0);
4667  infoStr += QString(" %1 %2 %3 %4 %5")
4668  .arg(position,
4669  speedStr,
4670  bufferFilename,
4671  QString::number(fplay),
4672  QString::number(rate));
4673  }
4674 
4675  infoStr += QString(" Subtitles:");
4676 
4678 
4679  if (subtype == kDisplayNone)
4680  infoStr += QString(" *0:[None]*");
4681  else
4682  infoStr += QString(" 0:[None]");
4683 
4684  uint n = 1;
4685 
4686  QStringList subs = m_player->GetTracks(kTrackTypeSubtitle);
4687  for (int i = 0; i < subs.size(); i++)
4688  {
4689  if ((subtype & kDisplayAVSubtitle) && (m_player->GetTrack(kTrackTypeSubtitle) == i))
4690  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4691  else
4692  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4693  n++;
4694  }
4695 
4697  for (int i = 0; i < subs.size(); i++)
4698  {
4699  if ((subtype & kDisplayCC708) && (m_player->GetTrack(kTrackTypeCC708) == i))
4700  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4701  else
4702  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4703  n++;
4704  }
4705 
4707  for (int i = 0; i < subs.size(); i++)
4708  {
4709  if ((subtype & kDisplayCC608) && (m_player->GetTrack(kTrackTypeCC608) == i))
4710  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4711  else
4712  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4713  n++;
4714  }
4715 
4717  for (int i = 0; i < subs.size(); i++)
4718  {
4720  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4721  else
4722  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4723  n++;
4724  }
4725 
4727  for (int i = 0; i < subs.size(); i++)
4728  {
4730  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4731  else
4732  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4733  n++;
4734  }
4735 
4737  for (int i = 0; i < subs.size(); i++)
4738  {
4739  if ((subtype & kDisplayRawTextSubtitle) && m_player->GetTrack(kTrackTypeRawText) == i)
4740  infoStr += QString(" *%1:[%2]*").arg(n).arg(subs[i]);
4741  else
4742  infoStr += QString(" %1:[%2]").arg(n).arg(subs[i]);
4743  n++;
4744  }
4745 
4746  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
4747 
4748  QString message = QString("NETWORK_CONTROL ANSWER %1").arg(infoStr);
4749  MythEvent me(message);
4750  gCoreContext->dispatch(me);
4751  }
4752  else if (tokens[2] == "VOLUME")
4753  {
4754  QString infoStr = QString("%1%").arg(m_audioState.m_volume);
4755  QString message = QString("NETWORK_CONTROL ANSWER %1").arg(infoStr);
4756  MythEvent me(message);
4757  gCoreContext->dispatch(me);
4758  }
4759  }
4760 }
4761 
4762 bool TV::StartPlayer(TVState desiredState)
4763 {
4764  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("(%1) -- begin").arg(StateToString(desiredState)));
4765 
4766  bool ok = CreatePlayer(desiredState);
4768 
4769  if (ok)
4770  {
4771  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Created player."));
4772  SetSpeedChangeTimer(25ms, __LINE__);
4773  }
4774  else
4775  {
4776  LOG(VB_GENERAL, LOG_CRIT, LOC + QString("Failed to create player."));
4777  }
4778 
4779  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("(%1) -- end %2")
4780  .arg(StateToString(desiredState), (ok) ? "ok" : "error"));
4781 
4782  return ok;
4783 }
4784 
4786 {
4787  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4788  if (!m_player)
4789  {
4790  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4791  return;
4792  }
4793 
4794  float time = 0.0;
4795 
4797  m_player->IsPaused())
4798  {
4800  time = StopFFRew();
4801  else if (m_player->IsPaused())
4803 
4807  }
4808  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4809 
4810  DoPlayerSeek(time);
4812 
4814 
4815  SetSpeedChangeTimer(0ms, __LINE__);
4817 }
4818 
4820 {
4821 
4823  return 0.0F;
4824 
4826  float time = 0.0F;
4827 
4828  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4829  if (!m_player)
4830  {
4831  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4832  return 0.0F;
4833  }
4834  if (m_player->IsPaused())
4835  {
4837  }
4838  else
4839  {
4841  time = StopFFRew();
4842  m_player->Pause();
4843  }
4844  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4845  return time;
4846 }
4847 
4848 void TV::DoTogglePauseFinish(float Time, bool ShowOSD)
4849 {
4850  if (!m_playerContext.HasPlayer())
4851  return;
4852 
4854  return;
4855 
4856  if (ContextIsPaused(__FILE__, __LINE__))
4857  {
4860 
4861  DoPlayerSeek(Time);
4862  if (ShowOSD)
4863  UpdateOSDSeekMessage(tr("Paused"), kOSDTimeout_None);
4865  }
4866  else
4867  {
4868  DoPlayerSeek(Time);
4869  if (ShowOSD)
4872  }
4873 
4874  SetSpeedChangeTimer(0ms, __LINE__);
4875 }
4876 
4884 {
4885  bool paused = false;
4886  int dummy = 0;
4887  TV* tv = AcquireRelease(dummy, true);
4888  if (tv)
4889  {
4890  tv->GetPlayerReadLock();
4891  PlayerContext* context = tv->GetPlayerContext();
4892  if (!context->IsErrored())
4893  {
4894  context->LockDeletePlayer(__FILE__, __LINE__);
4895  if (context->m_player)
4896  paused = context->m_player->IsPaused();
4897  context->UnlockDeletePlayer(__FILE__, __LINE__);
4898  }
4899  tv->ReturnPlayerLock();
4900  AcquireRelease(dummy, false);
4901  }
4902  return paused;
4903 }
4904 
4905 void TV::DoTogglePause(bool ShowOSD)
4906 {
4907  bool ignore = false;
4908  bool paused = false;
4909  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4910  if (m_player)
4911  {
4912  ignore = m_player->GetEditMode();
4913  paused = m_player->IsPaused();
4914  }
4915  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4916 
4917  if (paused)
4919  else
4921 
4922  if (!ignore)
4924  // Emit Pause or Unpaused signal
4926 }
4927 
4928 bool TV::DoPlayerSeek(float Time)
4929 {
4931  return false;
4932 
4933  if (Time > -0.001F && Time < +0.001F)
4934  return false;
4935 
4936  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1 seconds").arg(static_cast<double>(Time)));
4937 
4938  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4939  if (!m_player)
4940  {
4941  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4942  return false;
4943  }
4944 
4946  {
4947  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4948  return false;
4949  }
4950 
4951  emit PauseAudioUntilReady();
4952 
4953  bool res = false;
4954 
4955  if (Time > 0.0F)
4956  res = m_player->FastForward(Time);
4957  else if (Time < 0.0F)
4958  res = m_player->Rewind(-Time);
4959  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4960 
4961  return res;
4962 }
4963 
4964 bool TV::DoPlayerSeekToFrame(uint64_t FrameNum)
4965 {
4967  return false;
4968 
4969  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("%1").arg(FrameNum));
4970 
4971  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
4972  if (!m_player)
4973  {
4974  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4975  return false;
4976  }
4977 
4979  {
4980  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4981  return false;
4982  }
4983 
4984  emit PauseAudioUntilReady();
4985 
4986  bool res = m_player->JumpToFrame(FrameNum);
4987 
4988  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
4989 
4990  return res;
4991 }
4992 
4993 bool TV::SeekHandleAction(const QStringList& Actions, const bool IsDVD)
4994 {
4995  const int kRewind = 4;
4996  const int kForward = 8;
4997  const int kSticky = 16;
4998  const int kSlippery = 32;
4999  const int kRelative = 64;
5000  const int kAbsolute = 128;
5001  const int kIgnoreCutlist = 256;
5002  const int kWhenceMask = 3;
5003  int flags = 0;
5004  if (IsActionable(ACTION_SEEKFFWD, Actions))
5005  flags = ARBSEEK_FORWARD | kForward | kSlippery | kRelative;
5006  else if (IsActionable("FFWDSTICKY", Actions))
5007  flags = ARBSEEK_END | kForward | kSticky | kAbsolute;
5008  else if (IsActionable(ACTION_RIGHT, Actions))
5009  flags = ARBSEEK_FORWARD | kForward | kSticky | kRelative;
5010  else if (IsActionable(ACTION_SEEKRWND, Actions))
5011  flags = ARBSEEK_REWIND | kRewind | kSlippery | kRelative;
5012  else if (IsActionable("RWNDSTICKY", Actions))
5013  flags = ARBSEEK_SET | kRewind | kSticky | kAbsolute;
5014  else if (IsActionable(ACTION_LEFT, Actions))
5015  flags = ARBSEEK_REWIND | kRewind | kSticky | kRelative;
5016  else
5017  return false;
5018 
5019  int direction = (flags & kRewind) ? -1 : 1;
5020  if (HasQueuedInput())
5021  {
5022  DoArbSeek(static_cast<ArbSeekWhence>(flags & kWhenceMask), (flags & kIgnoreCutlist) == 0);
5023  }
5024  else if (ContextIsPaused(__FILE__, __LINE__))
5025  {
5026  if (!IsDVD)
5027  {
5028  QString message = (flags & kRewind) ? tr("Rewind") :
5029  tr("Forward");
5030  if (flags & kAbsolute) // FFWDSTICKY/RWNDSTICKY
5031  {
5032  float time = direction;
5033  DoSeek(time, message, /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5034  }
5035  else
5036  {
5037  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5038  uint64_t frameAbs = m_player->GetFramesPlayed();
5039  uint64_t frameRel = m_player->TranslatePositionAbsToRel(frameAbs);
5040  uint64_t targetRel = frameRel + static_cast<uint64_t>(direction);
5041  if (frameRel == 0 && direction < 0)
5042  targetRel = 0;
5043  uint64_t maxAbs = m_player->GetCurrentFrameCount();
5044  uint64_t maxRel = m_player->TranslatePositionAbsToRel(maxAbs);
5045  targetRel = std::min(targetRel, maxRel);
5046  uint64_t targetAbs = m_player->TranslatePositionRelToAbs(targetRel);
5047  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5048  DoPlayerSeekToFrame(targetAbs);
5050  }
5051  }
5052  }
5053  else if (flags & kSticky)
5054  {
5055  ChangeFFRew(direction);
5056  }
5057  else if (flags & kRewind)
5058  {
5059  if (m_smartForward)
5060  m_doSmartForward = true;
5061  DoSeek(-m_playerContext.m_rewtime, tr("Skip Back"), /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5062  }
5063  else
5064  {
5066  {
5067  DoSeek(m_playerContext.m_rewtime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5068  }
5069  else
5070  {
5071  DoSeek(m_playerContext.m_fftime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/(flags & kIgnoreCutlist) == 0);
5072  }
5073  }
5074  return true;
5075 }
5076 
5077 void TV::DoSeek(float Time, const QString &Msg, bool TimeIsOffset, bool HonorCutlist)
5078 {
5079  if (!m_player)
5080  return;
5081 
5082  bool limitkeys = false;
5083 
5084  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5085  if (m_player->GetLimitKeyRepeat())
5086  limitkeys = true;
5087 
5088  if (!limitkeys || (m_keyRepeatTimer.elapsed() > kKeyRepeatTimeout))
5089  {
5091  NormalSpeed();
5092  Time += StopFFRew();
5093  if (TimeIsOffset)
5094  {
5095  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5096  DoPlayerSeek(Time);
5097  }
5098  else
5099  {
5100  auto time = millisecondsFromFloat(Time * 1000);
5101  uint64_t desiredFrameRel = m_player->TranslatePositionMsToFrame(time, HonorCutlist);
5102  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5103  DoPlayerSeekToFrame(desiredFrameRel);
5104  }
5105  bool paused = m_player->IsPaused();
5107  }
5108  else
5109  {
5110  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5111  }
5112 }
5113 
5114 void TV::DoSeekAbsolute(long long Seconds, bool HonorCutlist)
5115 {
5116  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5117  if (!m_player)
5118  {
5119  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5121  return;
5122  }
5123  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5124  DoSeek(Seconds, tr("Jump To"), /*timeIsOffset*/false, HonorCutlist);
5126 }
5127 
5128 void TV::DoArbSeek(ArbSeekWhence Whence, bool HonorCutlist)
5129 {
5130  bool ok = false;
5131  int seek = GetQueuedInputAsInt(&ok);
5132  ClearInputQueues(true);
5133  if (!ok)
5134  return;
5135 
5136  int64_t time = ((seek / 100) * 3600) + ((seek % 100) * 60);
5137 
5138  if (Whence == ARBSEEK_FORWARD)
5139  {
5140  DoSeek(time, tr("Jump Ahead"), /*timeIsOffset*/true, HonorCutlist);
5141  }
5142  else if (Whence == ARBSEEK_REWIND)
5143  {
5144  DoSeek(-time, tr("Jump Back"), /*timeIsOffset*/true, HonorCutlist);
5145  }
5146  else if (Whence == ARBSEEK_END)
5147  {
5148  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5149  if (!m_player)
5150  {
5151  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5152  return;
5153  }
5154  uint64_t total_frames = m_player->GetCurrentFrameCount();
5155  float dur = m_player->ComputeSecs(total_frames, HonorCutlist);
5156  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5157  DoSeek(std::max(0.0F, dur - static_cast<float>(time)), tr("Jump To"), /*timeIsOffset*/false, HonorCutlist);
5158  }
5159  else
5160  {
5161  DoSeekAbsolute(time, HonorCutlist);
5162  }
5163 }
5164 
5166 {
5168  return;
5169 
5171 
5172  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5173  if (m_player)
5175  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5176 
5177  SetSpeedChangeTimer(0ms, __LINE__);
5178 }
5179 
5180 void TV::ChangeSpeed(int Direction)
5181 {
5182  int old_speed = m_playerContext.m_ffRewSpeed;
5183 
5184  if (ContextIsPaused(__FILE__, __LINE__))
5186 
5187  m_playerContext.m_ffRewSpeed += Direction;
5188 
5189  float time = StopFFRew();
5190  float speed {NAN};
5191 
5192  // Make sure these values for m_ffRewSpeed in TV::ChangeSpeed()
5193  // and PlayerContext::GetPlayMessage() stay in sync.
5194  if (m_playerContext.m_ffRewSpeed == 0)
5195  speed = m_playerContext.m_tsNormal;
5196  else if (m_playerContext.m_ffRewSpeed == -1)
5197  speed = 1.0F / 3;
5198  else if (m_playerContext.m_ffRewSpeed == -2)
5199  speed = 1.0F / 8;
5200  else if (m_playerContext.m_ffRewSpeed == -3)
5201  speed = 1.0F / 16;
5202  else if (m_playerContext.m_ffRewSpeed == -4)
5203  {
5204  DoTogglePause(true);
5205  return;
5206  }
5207  else
5208  {
5209  m_playerContext.m_ffRewSpeed = old_speed;
5210  return;
5211  }
5212 
5213  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5214  if (m_player && !m_player->Play(speed, m_playerContext.m_ffRewSpeed == 0))
5215  {
5216  m_playerContext.m_ffRewSpeed = old_speed;
5217  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5218  return;
5219  }
5220  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5221  DoPlayerSeek(time);
5222  QString mesg = m_playerContext.GetPlayMessage();
5224 
5225  SetSpeedChangeTimer(0ms, __LINE__);
5226 }
5227 
5229 {
5230  float time = 0.0;
5231 
5233  return time;
5234 
5235  if (m_playerContext.m_ffRewState > 0)
5236  time = -m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)] * m_ffRewRepos;
5237  else
5238  time = m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)] * m_ffRewRepos;
5239 
5242 
5243  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5244  if (m_player)
5246  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5247 
5248  SetSpeedChangeTimer(0ms, __LINE__);
5249 
5250  return time;
5251 }
5252 
5253 void TV::ChangeFFRew(int Direction)
5254 {
5255  if (m_playerContext.m_ffRewState == Direction)
5256  {
5257  while (++m_playerContext.m_ffRewIndex < static_cast<int>(m_ffRewSpeeds.size()))
5258  if (m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)])
5259  break;
5260  if (m_playerContext.m_ffRewIndex >= static_cast<int>(m_ffRewSpeeds.size()))
5263  }
5264  else if (!m_ffRewReverse && m_playerContext.m_ffRewState == -Direction)
5265  {
5267  if (m_ffRewSpeeds[static_cast<size_t>(m_playerContext.m_ffRewIndex)])
5268  break;
5271  else
5272  {
5273  float time = StopFFRew();
5274  DoPlayerSeek(time);
5276  }
5277  }
5278  else
5279  {
5280  NormalSpeed();
5281  m_playerContext.m_ffRewState = Direction;
5283  }
5284 }
5285 
5286 void TV::SetFFRew(int Index)
5287 {
5289  return;
5290 
5291  auto index = static_cast<size_t>(Index);
5292  if (!m_ffRewSpeeds[index])
5293  return;
5294 
5295  auto ffrewindex = static_cast<size_t>(m_playerContext.m_ffRewIndex);
5296  int speed = 0;
5297  QString mesg;
5298  if (m_playerContext.m_ffRewState > 0)
5299  {
5300  speed = m_ffRewSpeeds[index];
5301  // Don't allow ffwd if seeking is needed but not available
5303  return;
5304 
5305  m_playerContext.m_ffRewIndex = Index;
5306  mesg = tr("Forward %1X").arg(m_ffRewSpeeds[ffrewindex]);
5307  m_playerContext.m_ffRewSpeed = speed;
5308  }
5309  else
5310  {
5311  // Don't rewind if we cannot seek
5313  return;
5314 
5315  m_playerContext.m_ffRewIndex = Index;
5316  mesg = tr("Rewind %1X").arg(m_ffRewSpeeds[ffrewindex]);
5317  speed = -m_ffRewSpeeds[ffrewindex];
5318  m_playerContext.m_ffRewSpeed = speed;
5319  }
5320 
5321  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5322  if (m_player)
5323  m_player->Play(static_cast<float>(speed), (speed == 1) && (m_playerContext.m_ffRewState > 0));
5324  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5325 
5327 
5328  SetSpeedChangeTimer(0ms, __LINE__);
5329 }
5330 
5331 void TV::DoQueueTranscode(const QString& Profile)
5332 {
5333  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
5334 
5336  {
5337  bool stop = false;
5338  if (m_queuedTranscode ||
5340  JOB_TRANSCODE,
5343  {
5344  stop = true;
5345  }
5346 
5347  if (stop)
5348  {
5350  JOB_TRANSCODE,
5353  m_queuedTranscode = false;
5354  emit ChangeOSDMessage(tr("Stopping Transcode"));
5355  }
5356  else
5357  {
5359  recinfo.ApplyTranscoderProfileChange(Profile);
5360  QString jobHost = "";
5361 
5362  if (m_dbRunJobsOnRemote)
5364 
5365  QString msg = tr("Try Again");
5369  jobHost, "", "", JOB_USE_CUTLIST))
5370  {
5371  m_queuedTranscode = true;
5372  msg = tr("Transcoding");
5373  }
5374  emit ChangeOSDMessage(msg);
5375  }
5376  }
5377  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
5378 }
5379 
5381 {
5382  int num_chapters = 0;
5383  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5384  if (m_player)
5385  num_chapters = m_player->GetNumChapters();
5386  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5387  return num_chapters;
5388 }
5389 
5390 void TV::GetChapterTimes(QList<std::chrono::seconds> &Times)
5391 {
5392  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5393  if (m_player)
5394  m_player->GetChapterTimes(Times);
5395  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5396 }
5397 
5399 {
5400  int chapter = 0;
5401  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5402  if (m_player)
5403  chapter = m_player->GetCurrentChapter();
5404  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5405  return chapter;
5406 }
5407 
5408 void TV::DoJumpChapter(int Chapter)
5409 {
5410  NormalSpeed();
5411  StopFFRew();
5412 
5413  emit PauseAudioUntilReady();
5414 
5415  UpdateOSDSeekMessage(tr("Jump Chapter"), kOSDTimeout_Med);
5416 
5417  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5418  if (m_player)
5419  m_player->JumpChapter(Chapter);
5420  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5421 }
5422 
5424 {
5425  int num_titles = 0;
5426  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5427  if (m_player)
5428  num_titles = m_player->GetNumTitles();
5429  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5430  return num_titles;
5431 }
5432 
5434 {
5435  int currentTitle = 0;
5436  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5437  if (m_player)
5438  currentTitle = m_player->GetCurrentTitle();
5439  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5440  return currentTitle;
5441 }
5442 
5444 {
5445  int num_angles = 0;
5446  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5447  if (m_player)
5448  num_angles = m_player->GetNumAngles();
5449  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5450  return num_angles;
5451 }
5452 
5454 {
5455  int currentAngle = 0;
5456  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5457  if (m_player)
5458  currentAngle = m_player->GetCurrentAngle();
5459  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5460  return currentAngle;
5461 }
5462 
5463 QString TV::GetAngleName(int Angle)
5464 {
5465  QString name;
5466  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5467  if (m_player)
5468  name = m_player->GetAngleName(Angle);
5469  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5470  return name;
5471 }
5472 
5473 std::chrono::seconds TV::GetTitleDuration(int Title)
5474 {
5475  std::chrono::seconds seconds = 0s;
5476  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5477  if (m_player)
5478  seconds = m_player->GetTitleDuration(Title);
5479  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5480  return seconds;
5481 }
5482 
5483 
5484 QString TV::GetTitleName(int Title)
5485 {
5486  QString name;
5487  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5488  if (m_player)
5489  name = m_player->GetTitleName(Title);
5490  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5491  return name;
5492 }
5493 
5494 void TV::DoSwitchTitle(int Title)
5495 {
5496  NormalSpeed();
5497  StopFFRew();
5498 
5499  emit PauseAudioUntilReady();
5500 
5501  UpdateOSDSeekMessage(tr("Switch Title"), kOSDTimeout_Med);
5502  emit ChangeOSDPositionUpdates(true);
5503 
5504  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5505  if (m_player)
5506  m_player->SwitchTitle(Title);
5507  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5508 }
5509 
5510 void TV::DoSwitchAngle(int Angle)
5511 {
5512  NormalSpeed();
5513  StopFFRew();
5514 
5515  emit PauseAudioUntilReady();
5516 
5517  UpdateOSDSeekMessage(tr("Switch Angle"), kOSDTimeout_Med);
5518  emit ChangeOSDPositionUpdates(true);
5519 
5520  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5521  if (m_player)
5522  m_player->SwitchAngle(Angle);
5523  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5524 }
5525 
5526 void TV::DoSkipCommercials(int Direction)
5527 {
5528  NormalSpeed();
5529  StopFFRew();
5530 
5531  if (StateIsLiveTV(GetState()))
5532  return;
5533 
5534  emit PauseAudioUntilReady();
5535 
5536  osdInfo info;
5538  info.text["title"] = tr("Skip");
5539  info.text["description"] = tr("Searching");
5541  emit ChangeOSDPositionUpdates(true);
5542 
5543  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
5544  if (m_player)
5545  m_player->SkipCommercials(Direction);
5546  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
5547 }
5548 
5549 void TV::SwitchSource(uint Direction)
5550 {
5551  QMap<uint,InputInfo> sources;
5552  uint cardid = m_playerContext.GetCardID();
5553 
5554  InfoMap info;
5556  uint sourceid = info["sourceid"].toUInt();
5557 
5558  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(cardid);
5559  for (auto & input : inputs)
5560  {
5561  // prefer the current card's input in sources list
5562  if ((sources.find(input.m_sourceId) == sources.end()) ||
5563  ((cardid == input.m_inputId) && (cardid != sources[input.m_sourceId].m_inputId)))
5564  {
5565  sources[input.m_sourceId] = input;
5566  }
5567  }
5568 
5569  // Source switching
5570  QMap<uint,InputInfo>::const_iterator beg = sources.constFind(sourceid);
5571  QMap<uint,InputInfo>::const_iterator sit = beg;
5572 
5573  if (sit == sources.constEnd())
5574  return;
5575 
5576  if (kNextSource == Direction)
5577  {
5578  ++sit;
5579  if (sit == sources.constEnd())
5580  sit = sources.constBegin();
5581  }
5582 
5583  if (kPreviousSource == Direction)
5584  {
5585  if (sit != sources.constBegin())
5586  --sit;
5587  else
5588  {
5589  QMap<uint,InputInfo>::const_iterator tmp = sources.constBegin();
5590  while (tmp != sources.constEnd())
5591  {
5592  sit = tmp;
5593  ++tmp;
5594  }
5595  }
5596  }
5597 
5598  if (sit == beg)
5599  return;
5600 
5601  m_switchToInputId = (*sit).m_inputId;
5603 }
5604 
5605 void TV::SwitchInputs(uint ChanID, QString ChanNum, uint InputID)
5606 {
5608  return;
5609 
5610  // this will re-create the player. Ensure any outstanding events are delivered
5611  // and processed before the player is deleted so that we don't confuse the
5612  // state of the new player e.g. when switching inputs from the guide grid,
5613  // "EPG_EXITING" may not be received until after the player is re-created
5614  // and we inadvertantly disable drawing...
5615  // TODO with recent changes, embedding should be ended synchronously and hence
5616  // this extra call should no longer be needed
5617  QCoreApplication::processEvents();
5618 
5619  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("(%1,'%2',%3)").arg(ChanID).arg(ChanNum).arg(InputID));
5620 
5621  RemoteEncoder *testrec = nullptr;
5622 
5623  if (!StateIsLiveTV(GetState()))
5624  return;
5625 
5626  QStringList reclist;
5627  if (InputID)
5628  {
5629  reclist.push_back(QString::number(InputID));
5630  }
5631  else if (ChanID || !ChanNum.isEmpty())
5632  {
5633  // If we are switching to a channel not on the current recorder
5634  // we need to find the next free recorder with that channel.
5635  reclist = ChannelUtil::GetValidRecorderList(ChanID, ChanNum);
5636  }
5637 
5638  if (!reclist.empty())
5640 
5641  if (testrec && testrec->IsValidRecorder())
5642  {
5643  InputID = static_cast<uint>(testrec->GetRecorderNumber());
5644 
5645  // We are switching to a specific channel...
5646  if (ChanID && ChanNum.isEmpty())
5647  ChanNum = ChannelUtil::GetChanNum(static_cast<int>(ChanID));
5648 
5649  if (!ChanNum.isEmpty())
5650  CardUtil::SetStartChannel(InputID, ChanNum);
5651  }
5652 
5653  // If we are just switching recorders find first available recorder.
5654  if (!testrec)
5655  testrec = RemoteRequestNextFreeRecorder(static_cast<int>(m_playerContext.GetCardID()));
5656 
5657  if (testrec && testrec->IsValidRecorder())
5658  {
5659  // Switching inputs so clear the pseudoLiveTVState.
5661  bool muted = m_audioState.m_muteState == kMuteAll;
5662 
5663  // pause the decoder first, so we're not reading too close to the end.
5665  {
5668  }
5669 
5670  if (m_player)
5672 
5673  // shutdown stuff
5675  {
5678  }
5679 
5682  m_playerContext.SetPlayer(nullptr);
5683  m_player = nullptr;
5684 
5685  // now restart stuff
5687  m_lockTimerOn = false;
5688 
5689  m_playerContext.SetRecorder(testrec);
5691  // We need to set channum for SpawnLiveTV..
5692  if (ChanNum.isEmpty() && ChanID)
5693  ChanNum = ChannelUtil::GetChanNum(static_cast<int>(ChanID));
5694  if (ChanNum.isEmpty() && InputID)
5695  ChanNum = CardUtil::GetStartChannel(InputID);
5697 
5699  {
5700  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully restarted");
5702  m_playerContext.SetRecorder(nullptr);
5703  SetErrored();
5704  SetExitPlayer(true, false);
5705  }
5706  else
5707  {
5708  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
5709  QString playbackURL = m_playerContext.m_playingInfo->GetPlaybackURL(true);
5710  bool opennow = (m_playerContext.m_tvchain->GetInputType(-1) != "DUMMY");
5713  playbackURL, false, true,
5714  opennow ? MythMediaBuffer::kLiveTVOpenTimeout : -1ms));
5715 
5719  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
5720  }
5721 
5722  bool ok = false;
5724  {
5725  if (CreatePlayer(m_playerContext.GetState(), muted))
5726  {
5728  ok = true;
5730  SetSpeedChangeTimer(25ms, __LINE__);
5731  }
5732  else
5733  {
5734  StopStuff(true, true, true);
5735  }
5736  }
5737 
5738  if (!ok)
5739  {
5740  LOG(VB_GENERAL, LOG_ERR, LOC + "LiveTV not successfully started");
5742  m_playerContext.SetRecorder(nullptr);
5743  SetErrored();
5744  SetExitPlayer(true, false);
5745  }
5746  else
5747  {
5748  m_lockTimer.start();
5749  m_lockTimerOn = true;
5750  }
5751  }
5752  else
5753  {
5754  LOG(VB_GENERAL, LOG_ERR, LOC + "No recorder to switch to...");
5755  delete testrec;
5756  }
5757 
5758  UnpauseLiveTV();
5759  UpdateOSDInput();
5760 
5761  ITVRestart(true);
5762 }
5763 
5765 {
5766  // TOGGLEFAV was broken in [20523], this just prints something
5767  // out so as not to cause further confusion. See #8948.
5768  LOG(VB_GENERAL, LOG_ERR, "TV::ToggleChannelFavorite() -- currently disabled");
5769 }
5770 
5771 void TV::ToggleChannelFavorite(const QString& ChangroupName) const
5772 {
5775 }
5776 
5777 QString TV::GetQueuedInput() const
5778 {
5779  return m_queuedInput;
5780 }
5781 
5782 int TV::GetQueuedInputAsInt(bool *OK, int Base) const
5783 {
5784  return m_queuedInput.toInt(OK, Base);
5785 }
5786 
5787 QString TV::GetQueuedChanNum() const
5788 {
5789  if (m_queuedChanNum.isEmpty())
5790  return "";
5791 
5792  // strip initial zeros and other undesirable characters
5793  int i = 0;
5794  for (; i < m_queuedChanNum.length(); i++)
5795  {
5796  if ((m_queuedChanNum[i] > '0') && (m_queuedChanNum[i] <= '9'))
5797  break;
5798  }
5799  m_queuedChanNum = m_queuedChanNum.right(m_queuedChanNum.length() - i);
5800 
5801  // strip whitespace at end of string
5802  m_queuedChanNum = m_queuedChanNum.trimmed();
5803 
5804  return m_queuedChanNum;
5805 }
5806 
5811 void TV::ClearInputQueues(bool Hideosd)
5812 {
5813  if (Hideosd)
5815 
5816  m_queuedInput = "";
5817  m_queuedChanNum = "";
5818  m_queuedChanID = 0;
5819  if (m_queueInputTimerId)
5820  {
5822  m_queueInputTimerId = 0;
5823  }
5824 }
5825 
5827 {
5828  if (Key)
5829  {
5830  m_queuedInput = m_queuedInput.append(Key).right(kInputKeysMax);
5831  m_queuedChanNum = m_queuedChanNum.append(Key).right(kInputKeysMax);
5832  if (!m_queueInputTimerId)
5833  m_queueInputTimerId = StartTimer(10ms, __LINE__);
5834  }
5835 
5836  bool commitSmart = false;
5837  QString inputStr = GetQueuedInput();
5838 
5839  // Always use immediate channel change when channel numbers are entered
5840  // in browse mode because in browse mode space/enter exit browse
5841  // mode and change to the currently browsed channel.
5843  {
5844  commitSmart = ProcessSmartChannel(inputStr);
5845  }
5846 
5847  // Handle OSD...
5848  inputStr = inputStr.isEmpty() ? "?" : inputStr;
5849  if (m_ccInputMode)
5850  {
5851  QString entryStr = (m_vbimode==VBIMode::PAL_TT) ? tr("TXT:") : tr("CC:");
5852  inputStr = entryStr + " " + inputStr;
5853  }
5854  else if (m_asInputMode)
5855  {
5856  inputStr = tr("Seek:", "seek to location") + " " + inputStr;
5857  }
5858  // NOLINTNEXTLINE(readability-misleading-indentation)
5859  emit ChangeOSDText(OSD_WIN_INPUT, {{ "osd_number_entry", inputStr}}, kOSDTimeout_Med);
5860 
5861  // Commit the channel if it is complete and smart changing is enabled.
5862  if (commitSmart)
5864 }
5865 
5866 static QString add_spacer(const QString &chan, const QString &spacer)
5867 {
5868  if ((chan.length() >= 2) && !spacer.isEmpty())
5869  return chan.left(chan.length()-1) + spacer + chan.right(1);
5870  return chan;
5871 }
5872 
5873 bool TV::ProcessSmartChannel(QString &InputStr)
5874 {
5875  QString chan = GetQueuedChanNum();
5876 
5877  if (chan.isEmpty())
5878  return false;
5879 
5880  // Check for and remove duplicate separator characters
5881 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
5882  int size = chan.size();
5883 #else
5884  qsizetype size = chan.size();
5885 #endif
5886  if ((size > 2) && (chan.at(size - 1) == chan.at(size - 2)))
5887  {
5888  bool ok = false;
5889  chan.right(1).toUInt(&ok);
5890  if (!ok)
5891  {
5892  chan = chan.left(chan.length()-1);
5893  m_queuedChanNum = chan;
5894  if (!m_queueInputTimerId)
5895  m_queueInputTimerId = StartTimer(10ms, __LINE__);
5896  }
5897  }
5898 
5899  // Look for channel in line-up
5900  QString needed_spacer;
5901  uint pref_cardid = 0;
5902  bool is_not_complete = true;
5903 
5904  bool valid_prefix = false;
5906  {
5908  chan, pref_cardid, is_not_complete, needed_spacer);
5909  }
5910 
5911 #if DEBUG_CHANNEL_PREFIX
5912  LOG(VB_GENERAL, LOG_DEBUG, QString("valid_pref(%1) cardid(%2) chan(%3) "
5913  "pref_cardid(%4) complete(%5) sp(%6)")
5914  .arg(valid_prefix).arg(0).arg(chan)
5915  .arg(pref_cardid).arg(is_not_complete).arg(needed_spacer));
5916 #endif
5917 
5918  if (!valid_prefix)
5919  {
5920  // not a valid prefix.. reset...
5921  m_queuedChanNum = "";
5922  }
5923  else if (!needed_spacer.isEmpty())
5924  {
5925  // need a spacer..
5926  m_queuedChanNum = add_spacer(chan, needed_spacer);
5927  }
5928 
5929 #if DEBUG_CHANNEL_PREFIX
5930  LOG(VB_GENERAL, LOG_DEBUG, QString(" ValidPref(%1) CardId(%2) Chan(%3) "
5931  " PrefCardId(%4) Complete(%5) Sp(%6)")
5932  .arg(valid_prefix).arg(0).arg(GetQueuedChanNum())
5933  .arg(pref_cardid).arg(is_not_complete).arg(needed_spacer));
5934 #endif
5935 
5936  InputStr = m_queuedChanNum;
5937  if (!m_queueInputTimerId)
5938  m_queueInputTimerId = StartTimer(10ms, __LINE__);
5939 
5940  return !is_not_complete;
5941 }
5942 
5944 {
5945  bool commited = false;
5946 
5947  LOG(VB_PLAYBACK, LOG_INFO, LOC +
5948  QString("livetv(%1) qchannum(%2) qchanid(%3)")
5949  .arg(StateIsLiveTV(GetState()))
5950  .arg(GetQueuedChanNum())
5951  .arg(GetQueuedChanID()));
5952 
5953  if (m_ccInputMode)
5954  {
5955  commited = true;
5956  if (HasQueuedInput())
5958  }
5959  else if (m_asInputMode)
5960  {
5961  commited = true;
5962  if (HasQueuedInput())
5963  // XXX Should the cutlist be honored?
5964  DoArbSeek(ARBSEEK_FORWARD, /*honorCutlist*/false);
5965  }
5966  else if (StateIsLiveTV(GetState()))
5967  {
5968  QString channum = GetQueuedChanNum();
5970  {
5971  uint sourceid = 0;
5972  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
5975  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
5976 
5977  commited = true;
5978  if (channum.isEmpty())
5979  channum = GetBrowsedInfo().m_chanNum;
5980  uint chanid = GetBrowseChanId(channum, m_playerContext.GetCardID(), sourceid);
5981  if (chanid)
5982  BrowseChannel(channum);
5983 
5985  }
5986  else if (GetQueuedChanID() || !channum.isEmpty())
5987  {
5988  commited = true;
5989  ChangeChannel(GetQueuedChanID(), channum);
5990  }
5991  }
5992 
5993  ClearInputQueues(true);
5994  return commited;
5995 }
5996 
5998 {
5999  if (m_dbUseChannelGroups || (Direction == CHANNEL_DIRECTION_FAVORITE))
6000  {
6001  uint old_chanid = 0;
6002  if (m_channelGroupId > -1)
6003  {
6004  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
6006  {
6007  LOG(VB_GENERAL, LOG_ERR, LOC +
6008  "no active ctx playingInfo.");
6009  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6010  ReturnPlayerLock();
6011  return;
6012  }
6013  // Collect channel info
6014  old_chanid = m_playerContext.m_playingInfo->GetChanID();
6015  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6016  }
6017 
6018  if (old_chanid)
6019  {
6020  QMutexLocker locker(&m_channelGroupLock);
6021  if (m_channelGroupId > -1)
6022  {
6024  m_channelGroupChannelList, old_chanid, 0, 0, Direction);
6025  if (chanid)
6026  ChangeChannel(chanid, "");
6027  return;
6028  }
6029  }
6030  }
6031 
6032  if (Direction == CHANNEL_DIRECTION_FAVORITE)
6033  Direction = CHANNEL_DIRECTION_UP;
6034 
6035  QString oldinputname = m_playerContext.m_recorder->GetInput();
6036 
6037  if (ContextIsPaused(__FILE__, __LINE__))
6038  {
6041  }
6042 
6043  // Save the current channel if this is the first time
6044  if (m_playerContext.m_prevChan.empty())
6046 
6047  emit PauseAudioUntilReady();
6048  PauseLiveTV();
6049 
6050  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
6051  if (m_player)
6052  {
6053  emit ResetCaptions();
6054  emit ResetTeletext();
6055  }
6056  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
6057 
6059  ClearInputQueues(false);
6060 
6061  emit ResetAudio();
6062 
6063  UnpauseLiveTV();
6064 
6065  if (oldinputname != m_playerContext.m_recorder->GetInput())
6066  UpdateOSDInput();
6067 }
6068 
6069 static uint get_chanid(const PlayerContext *ctx,
6070  uint cardid, const QString &channum)
6071 {
6072  uint chanid = 0;
6073  uint cur_sourceid = 0;
6074 
6075  // try to find channel on current input
6076  if (ctx && ctx->m_playingInfo && ctx->m_playingInfo->GetSourceID())
6077  {
6078  cur_sourceid = ctx->m_playingInfo->GetSourceID();
6079  chanid = std::max(ChannelUtil::GetChanID(cur_sourceid, channum), 0);
6080  if (chanid)
6081  return chanid;
6082  }
6083 
6084  // try to find channel on specified input
6085  uint sourceid = CardUtil::GetSourceID(cardid);
6086  if (cur_sourceid != sourceid && sourceid)
6087  chanid = std::max(ChannelUtil::GetChanID(sourceid, channum), 0);
6088  return chanid;
6089 }
6090 
6091 void TV::ChangeChannel(uint Chanid, const QString &Channum)
6092 {
6093  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("(%1, '%2')").arg(Chanid).arg(Channum));
6094 
6095  if ((!Chanid && Channum.isEmpty()) || !m_playerContext.m_recorder)
6096  return;
6097 
6098  QString channum = Channum;
6099  QStringList reclist;
6100  QVector<uint> tunable_on;
6101 
6102  QString oldinputname = m_playerContext.m_recorder->GetInput();
6103 
6104  if (channum.isEmpty() && Chanid)
6105  channum = ChannelUtil::GetChanNum(static_cast<int>(Chanid));
6106 
6107  bool getit = false;
6109  {
6111  {
6112  getit = false;
6113  }
6115  {
6116  getit = true;
6117  }
6118  else if (Chanid)
6119  {
6120  tunable_on = IsTunableOn(&m_playerContext, Chanid);
6121  getit = !tunable_on.contains(m_playerContext.GetCardID());
6122  }
6123  else
6124  {
6125  QString needed_spacer;
6126  uint pref_cardid = 0;
6127  uint cardid = m_playerContext.GetCardID();
6128  bool dummy = false;
6129 
6131  dummy, needed_spacer);
6132 
6133  LOG(VB_CHANNEL, LOG_INFO, LOC +
6134  QString("CheckChannelPrefix(%1, pref_cardid %2, %3, '%4') "
6135  "cardid %5")
6136  .arg(Channum).arg(pref_cardid).arg(dummy).arg(needed_spacer)
6137  .arg(cardid));
6138 
6139  channum = add_spacer(Channum, needed_spacer);
6140  if (pref_cardid != cardid)
6141  {
6142  getit = true;
6143  }
6144  else
6145  {
6146  if (!Chanid)
6147  Chanid = get_chanid(&m_playerContext, cardid, Channum);
6148  tunable_on = IsTunableOn(&m_playerContext, Chanid);
6149  getit = !tunable_on.contains(cardid);
6150  }
6151  }
6152 
6153  if (getit)
6154  {
6155  QStringList tmp =
6156  ChannelUtil::GetValidRecorderList(Chanid, channum);
6157  if (tunable_on.empty())
6158  {
6159  if (!Chanid)
6161  tunable_on = IsTunableOn(&m_playerContext, Chanid);
6162  }
6163  for (const auto& rec : std::as_const(tmp))
6164  {
6165  if ((Chanid == 0U) || tunable_on.contains(rec.toUInt()))
6166  reclist.push_back(rec);
6167  }
6168  }
6169  }
6170 
6171  if (!reclist.empty())
6172  {
6174  if (!testrec || !testrec->IsValidRecorder())
6175  {
6176  ClearInputQueues(true);
6178  delete testrec;
6179  return;
6180  }
6181 
6182  if (!m_playerContext.m_prevChan.empty() &&
6183  m_playerContext.m_prevChan.back() == channum)
6184  {
6185  // need to remove it if the new channel is the same as the old.
6186  m_playerContext.m_prevChan.pop_back();
6187  }
6188 
6189  // found the card on a different recorder.
6190  uint inputid = static_cast<uint>(testrec->GetRecorderNumber());
6191  delete testrec;
6192  // Save the current channel if this is the first time
6193  if (m_playerContext.m_prevChan.empty())
6195  SwitchInputs(Chanid, channum, inputid);
6196  return;
6197  }
6198 
6200  return;
6201 
6202  if (ContextIsPaused(__FILE__, __LINE__))
6203  {
6206  }
6207 
6208  // Save the current channel if this is the first time
6209  if (m_playerContext.m_prevChan.empty())
6211 
6212  emit PauseAudioUntilReady();
6213  PauseLiveTV();
6214 
6215  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
6216  if (m_player)
6217  {
6218  emit ResetCaptions();
6219  emit ResetTeletext();
6220  }
6221  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
6222 
6224 
6225  emit ResetAudio();
6226 
6227  UnpauseLiveTV((Chanid != 0U) && (GetQueuedChanID() != 0U));
6228 
6229  if (oldinputname != m_playerContext.m_recorder->GetInput())
6230  UpdateOSDInput();
6231 }
6232 
6234 {
6235  for (const auto & option : Options)
6236  {
6237  uint chanid = option.m_chanId;
6238  QString channum = option.m_chanNum;
6239 
6240  if (chanid && !channum.isEmpty() && IsTunablePriv(chanid))
6241  {
6242  // hide the channel number, activated by certain signal monitors
6244  m_queuedInput = channum;
6245  m_queuedChanNum = channum;
6246  m_queuedChanID = chanid;
6247  if (!m_queueInputTimerId)
6248  m_queueInputTimerId = StartTimer(10ms, __LINE__);
6249  break;
6250  }
6251  }
6252 }
6253 
6255 {
6256  QString channum = m_playerContext.GetPreviousChannel();
6257  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Previous channel number '%1'").arg(channum));
6258  if (channum.isEmpty())
6259  return;
6260  emit ChangeOSDText(OSD_WIN_INPUT, {{ "osd_number_entry", channum }}, kOSDTimeout_Med);
6261 }
6262 
6263 void TV::PopPreviousChannel(bool ImmediateChange)
6264 {
6266  return;
6267 
6268  if (!ImmediateChange)
6270 
6271  QString prev_channum = m_playerContext.PopPreviousChannel();
6272  QString cur_channum = m_playerContext.m_tvchain->GetChannelName(-1);
6273 
6274  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("'%1'->'%2'")
6275  .arg(cur_channum, prev_channum));
6276 
6277  // Only change channel if previous channel != current channel
6278  if (cur_channum != prev_channum && !prev_channum.isEmpty())
6279  {
6280  m_queuedInput = prev_channum;
6281  m_queuedChanNum = prev_channum;
6282  m_queuedChanID = 0;
6283  if (!m_queueInputTimerId)
6284  m_queueInputTimerId = StartTimer(10ms, __LINE__);
6285  }
6286 
6287  if (ImmediateChange)
6288  {
6289  // Turn off OSD Channel Num so the channel changes right away
6291  }
6292 }
6293 
6295 {
6296  if (HasQueuedInput() || HasQueuedChannel())
6297  ClearInputQueues(true);
6298 
6299  emit DialogQuit();
6300  // pop OSD screen
6301  emit HideAll(true, nullptr, true);
6302 
6304  BrowseEnd(false);
6305 }
6306 
6310 void TV::ToggleOSD(bool IncludeStatusOSD)
6311 {
6312  OSD *osd = GetOSDL();
6313  if (!osd)
6314  {
6315  ReturnOSDLock();
6316  return;
6317  }
6318 
6319  bool hideAll = false;
6320  bool showStatus = false;
6321  bool paused = ContextIsPaused(__FILE__, __LINE__);
6322  bool is_status_disp = osd->IsWindowVisible(OSD_WIN_STATUS);
6323  bool has_prog_info = osd->HasWindow(OSD_WIN_PROGINFO);
6324  bool is_prog_info_disp = osd->IsWindowVisible(OSD_WIN_PROGINFO);
6325 
6326  ReturnOSDLock();
6327 
6328  if (is_status_disp)
6329  {
6330  if (has_prog_info)
6332  else
6333  hideAll = true;
6334  }
6335  else if (is_prog_info_disp && !paused)
6336  {
6337  hideAll = true;
6338  }
6339  else if (IncludeStatusOSD)
6340  {
6341  showStatus = true;
6342  }
6343  else
6344  {
6345  if (has_prog_info)
6347  }
6348 
6349  if (hideAll || showStatus)
6350  emit HideAll();
6351 
6352  if (showStatus)
6353  {
6354  osdInfo info;
6356  {
6357  info.text["title"] = (paused ? tr("Paused") : tr("Position"));
6359  paused ? kOSDTimeout_None : kOSDTimeout_Med);
6360  emit ChangeOSDPositionUpdates(true);
6361  }
6362  else
6363  {
6364  emit ChangeOSDPositionUpdates(false);
6365  }
6366  }
6367  else
6368  {
6369  emit ChangeOSDPositionUpdates(false);
6370  }
6371 }
6372 
6376 void TV::UpdateOSDProgInfo(const char *WhichInfo)
6377 {
6378  InfoMap infoMap;
6380  if (m_player)
6381  m_player->GetCodecDescription(infoMap);
6382 
6383  // Clear previous osd and add new info
6384  emit HideAll();
6385  emit ChangeOSDText(WhichInfo, infoMap, kOSDTimeout_Long);
6386 }
6387 
6388 void TV::UpdateOSDStatus(osdInfo &Info, int Type, OSDTimeout Timeout)
6389 {
6390  OSD *osd = GetOSDL();
6391  if (osd)
6392  {
6394  osd->SetValues(OSD_WIN_STATUS, Info.values, Timeout);
6395  emit ChangeOSDText(OSD_WIN_STATUS, Info.text, Timeout);
6396  if (Type != kOSDFunctionalType_Default)
6397  osd->SetFunctionalWindow(OSD_WIN_STATUS, static_cast<OSDFunctionalType>(Type));
6398  }
6399  ReturnOSDLock();
6400 }
6401 
6402 void TV::UpdateOSDStatus(const QString& Title, const QString& Desc,
6403  const QString& Value, int Type, const QString& Units,
6404  int Position, OSDTimeout Timeout)
6405 {
6406  osdInfo info;
6407  info.values.insert("position", Position);
6408  info.values.insert("relposition", Position);
6409  info.text.insert("title", Title);
6410  info.text.insert("description", Desc);
6411  info.text.insert("value", Value);
6412  info.text.insert("units", Units);
6413  UpdateOSDStatus(info, Type, Timeout);
6414 }
6415 
6416 void TV::UpdateOSDSeekMessage(const QString &Msg, enum OSDTimeout Timeout)
6417 {
6418  LOG(VB_PLAYBACK, LOG_INFO, QString("UpdateOSDSeekMessage(%1, %2)").arg(Msg).arg(Timeout));
6419 
6420  osdInfo info;
6422  {
6424  info.text["title"] = Msg;
6425  UpdateOSDStatus(info, osdtype, Timeout);
6426  emit ChangeOSDPositionUpdates(true);
6427  }
6428 }
6429 
6431 {
6433  return;
6434  QString displayName = CardUtil::GetDisplayName(m_playerContext.GetCardID());
6435  emit ChangeOSDMessage(displayName);
6436 }
6437 
6441 void TV::UpdateOSDSignal(const QStringList &List)
6442 {
6443  OSD *osd = GetOSDL();
6444  if (!osd || m_overlayState.m_browsing || !m_queuedChanNum.isEmpty())
6445  {
6446  if (&m_playerContext.m_lastSignalMsg != &List)
6448  ReturnOSDLock();
6449  m_signalMonitorTimerId = StartTimer(1ms, __LINE__);
6450  return;
6451  }
6452  ReturnOSDLock();
6453 
6455 
6459  infoMap["callsign"].isEmpty())
6460  {
6463  if (m_player)
6464  m_player->GetCodecDescription(infoMap);
6465 
6468  }
6469 
6470  int i = 0;
6471  SignalMonitorList::const_iterator it;
6472  for (it = slist.begin(); it != slist.end(); ++it)
6473  if ("error" == it->GetShortName())
6474  infoMap[QString("error%1").arg(i++)] = it->GetName();
6475  i = 0;
6476  for (it = slist.begin(); it != slist.end(); ++it)
6477  if ("message" == it->GetShortName())
6478  infoMap[QString("message%1").arg(i++)] = it->GetName();
6479 
6480  int sig = 0;
6481  double snr = 0.0;
6482  uint ber = 0xffffffff;
6483  int pos = -1;
6484  int tuned = -1;
6485  QString pat("");
6486  QString pmt("");
6487  QString mgt("");
6488  QString vct("");
6489  QString nit("");
6490  QString sdt("");
6491  QString crypt("");
6492  QString err;
6493  QString msg;
6494  for (it = slist.begin(); it != slist.end(); ++it)
6495  {
6496  if ("error" == it->GetShortName())
6497  {
6498  err = it->GetName();
6499  continue;
6500  }
6501 
6502  if ("message" == it->GetShortName())
6503  {
6504  msg = it->GetName();
6505  LOG(VB_GENERAL, LOG_INFO, "msg: " + msg);
6506  continue;
6507  }
6508 
6509  infoMap[it->GetShortName()] = QString::number(it->GetValue());
6510  if ("signal" == it->GetShortName())
6511  sig = it->GetNormalizedValue(0, 100);
6512  else if ("snr" == it->GetShortName())
6513  snr = it->GetValue();
6514  else if ("ber" == it->GetShortName())
6515  ber = static_cast<uint>(it->GetValue());
6516  else if ("pos" == it->GetShortName())
6517  pos = it->GetValue();
6518  else if ("script" == it->GetShortName())
6519  tuned = it->GetValue();
6520  else if ("seen_pat" == it->GetShortName())
6521  pat = it->IsGood() ? "a" : "_";
6522  else if ("matching_pat" == it->GetShortName())
6523  pat = it->IsGood() ? "A" : pat;
6524  else if ("seen_pmt" == it->GetShortName())
6525  pmt = it->IsGood() ? "m" : "_";
6526  else if ("matching_pmt" == it->GetShortName())
6527  pmt = it->IsGood() ? "M" : pmt;
6528  else if ("seen_mgt" == it->GetShortName())
6529  mgt = it->IsGood() ? "g" : "_";
6530  else if ("matching_mgt" == it->GetShortName())
6531  mgt = it->IsGood() ? "G" : mgt;
6532  else if ("seen_vct" == it->GetShortName())
6533  vct = it->IsGood() ? "v" : "_";
6534  else if ("matching_vct" == it->GetShortName())
6535  vct = it->IsGood() ? "V" : vct;
6536  else if ("seen_nit" == it->GetShortName())
6537  nit = it->IsGood() ? "n" : "_";
6538  else if ("matching_nit" == it->GetShortName())
6539  nit = it->IsGood() ? "N" : nit;
6540  else if ("seen_sdt" == it->GetShortName())
6541  sdt = it->IsGood() ? "s" : "_";
6542  else if ("matching_sdt" == it->GetShortName())
6543  sdt = it->IsGood() ? "S" : sdt;
6544  else if ("seen_crypt" == it->GetShortName())
6545  crypt = it->IsGood() ? "c" : "_";
6546  else if ("matching_crypt" == it->GetShortName())
6547  crypt = it->IsGood() ? "C" : crypt;
6548  }
6549  if (sig)
6550  infoMap["signal"] = QString::number(sig); // use normalized value
6551 
6552  bool allGood = SignalMonitorValue::AllGood(slist);
6553  QString tuneCode;
6554  QString slock = ("1" == infoMap["slock"]) ? "L" : "l";
6555  QString lockMsg = (slock=="L") ? tr("Partial Lock") : tr("No Lock");
6556  QString sigMsg = allGood ? tr("Lock") : lockMsg;
6557 
6558  QString sigDesc = tr("Signal %1%").arg(sig,2);
6559  if (snr > 0.0)
6560  sigDesc += " | " + tr("S/N %1dB").arg(log10(snr), 3, 'f', 1);
6561  if (ber != 0xffffffff)
6562  sigDesc += " | " + tr("BE %1", "Bit Errors").arg(ber, 2);
6563  if ((pos >= 0) && (pos < 100))
6564  sigDesc += " | " + tr("Rotor %1%").arg(pos,2);
6565 
6566  if (tuned == 1)
6567  tuneCode = "t";
6568  else if (tuned == 2)
6569  tuneCode = "F";
6570  else if (tuned == 3)
6571  tuneCode = "T";
6572  else
6573  tuneCode = "_";
6574 
6575  sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8%9) %10")
6576  .arg(tuneCode, slock, pat, pmt, mgt, vct,
6577  nit, sdt, crypt)
6578  .arg(sigMsg);
6579 
6580  if (!err.isEmpty())
6581  sigDesc = err;
6582  else if (!msg.isEmpty())
6583  sigDesc = msg;
6584 
6585  infoMap["description"] = sigDesc;
6587 
6590 
6591  // Turn off lock timer if we have an "All Good" or good PMT
6592  if (allGood || (pmt == "M"))
6593  {
6594  m_lockTimerOn = false;
6596  }
6597 }
6598 
6600 {
6601  bool timed_out = false;
6602 
6604  {
6605  QString input = m_playerContext.m_recorder->GetInput();
6607  timed_out = m_lockTimerOn && m_lockTimer.hasExpired(timeout);
6608  }
6609 
6610  OSD *osd = GetOSDL();
6611 
6612  if (!osd)
6613  {
6614  if (timed_out)
6615  {
6616  LOG(VB_GENERAL, LOG_ERR, LOC +
6617  "You have no OSD, but tuning has already taken too long.");
6618  }
6619  ReturnOSDLock();
6620  return;
6621  }
6622 
6623  bool showing = osd->DialogVisible(OSD_DLG_INFO);
6624  if (!timed_out)
6625  {
6626  if (showing)
6627  emit DialogQuit();
6628  ReturnOSDLock();
6629  return;
6630  }
6631 
6632  if (showing)
6633  {
6634  ReturnOSDLock();
6635  return;
6636  }
6637 
6638  ReturnOSDLock();
6639 
6640  // create dialog...
6641  static QString s_chanUp = GET_KEY("TV Playback", ACTION_CHANNELUP);
6642  static QString s_chanDown = GET_KEY("TV Playback", ACTION_CHANNELDOWN);
6643  static QString s_nextSrc = GET_KEY("TV Playback", "NEXTSOURCE");
6644  static QString s_togCards = GET_KEY("TV Playback", "NEXTINPUT");
6645 
6646  QString message = tr(
6647  "You should have received a channel lock by now. "
6648  "You can continue to wait for a signal, or you "
6649  "can change the channel with %1 or %2, change "
6650  "video source (%3), inputs (%4), etc.")
6651  .arg(s_chanUp, s_chanDown, s_nextSrc, s_togCards);
6652 
6653  emit ChangeOSDDialog({ OSD_DLG_INFO, message, 0ms,
6654  { {tr("OK"), "DIALOG_INFO_CHANNELLOCK_0" } },
6655  { "", "DIALOG_INFO_CHANNELLOCK_0", true } });
6656 }
6657 
6658 bool TV::CalcPlayerSliderPosition(osdInfo &info, bool paddedFields) const
6659 {
6660  bool result = false;
6662  if (m_player)
6663  {
6664  m_player->UpdateSliderInfo(info, paddedFields);
6665  result = true;
6666  }
6667  ReturnPlayerLock();
6668  return result;
6669 }
6670 
6671 void TV::HideOSDWindow(const char *window)
6672 {
6673  OSD *osd = GetOSDL();
6674  if (osd)
6675  osd->HideWindow(window);
6676  ReturnOSDLock();
6677 }
6678 
6680 {
6681  // Make sure the LCD information gets updated shortly
6682  if (m_lcdTimerId)
6684  m_lcdTimerId = StartTimer(1ms, __LINE__);
6685 }
6686 
6688 {
6689  LCD *lcd = LCD::Get();
6690  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
6691  if (!lcd || !m_playerContext.m_playingInfo)
6692  {
6693  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6694  return;
6695  }
6696 
6697  QString title = m_playerContext.m_playingInfo->GetTitle();
6698  QString subtitle = m_playerContext.m_playingInfo->GetSubtitle();
6700 
6701  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6702 
6703  if ((callsign != m_lcdCallsign) || (title != m_lcdTitle) ||
6704  (subtitle != m_lcdSubtitle))
6705  {
6706  lcd->switchToChannel(callsign, title, subtitle);
6707  m_lcdCallsign = callsign;
6708  m_lcdTitle = title;
6709  m_lcdSubtitle = subtitle;
6710  }
6711 }
6712 
6714 {
6715  LCD *lcd = LCD::Get();
6717  return;
6718 
6720  QString dvdName;
6721  QString dvdSerial;
6722  QString mainStatus;
6723  QString subStatus;
6724 
6725  if (!dvd->GetNameAndSerialNum(dvdName, dvdSerial))
6726  dvdName = tr("DVD");
6727 
6728  if (dvd->IsInMenu())
6729  {
6730  mainStatus = tr("Menu");
6731  }
6732  else if (dvd->IsInStillFrame())
6733  {
6734  mainStatus = tr("Still Frame");
6735  }
6736  else
6737  {
6738  int playingTitle = 0;
6739  int playingPart = 0;
6740 
6741  dvd->GetPartAndTitle(playingPart, playingTitle);
6742  int totalParts = dvd->NumPartsInTitle();
6743 
6744  mainStatus = tr("Title: %1 (%2)").arg(playingTitle)
6745  .arg(MythDate::formatTime(dvd->GetTotalTimeOfTitle(), "HH:mm"));
6746  subStatus = tr("Chapter: %1/%2").arg(playingPart).arg(totalParts);
6747  }
6748  if ((dvdName != m_lcdCallsign) || (mainStatus != m_lcdTitle) || (subStatus != m_lcdSubtitle))
6749  {
6750  lcd->switchToChannel(dvdName, mainStatus, subStatus);
6751  m_lcdCallsign = dvdName;
6752  m_lcdTitle = mainStatus;
6753  m_lcdSubtitle = subStatus;
6754  }
6755 }
6756 
6757 bool TV::IsTunable(uint ChanId)
6758 {
6759  int dummy = 0;
6760  TV* tv = AcquireRelease(dummy, true);
6761  if (tv)
6762  {
6763  tv->GetPlayerReadLock();
6764  bool result = !TV::IsTunableOn(tv->GetPlayerContext(), ChanId).empty();
6765  tv->ReturnPlayerLock();
6766  AcquireRelease(dummy, false);
6767  return result;
6768  }
6769 
6770  return !TV::IsTunableOn(nullptr, ChanId).empty();
6771 }
6772 
6774 {
6775  return !IsTunableOn(&m_playerContext, ChanId).empty();
6776 }
6777 
6778 static QString toCommaList(const QVector<uint> &list)
6779 {
6780  QString ret = "";
6781  for (uint i : std::as_const(list))
6782  ret += QString("%1,").arg(i);
6783 
6784  if (!ret.isEmpty())
6785  return ret.left(ret.length()-1);
6786 
6787  return "";
6788 }
6789 
6790 QVector<uint> TV::IsTunableOn(PlayerContext* Context, uint ChanId)
6791 {
6792  QVector<uint> tunable_cards;
6793 
6794  if (!ChanId)
6795  {
6796  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("ChanId (%1) - no").arg(ChanId));
6797  return tunable_cards;
6798  }
6799 
6800  uint mplexid = ChannelUtil::GetMplexID(ChanId);
6801  mplexid = (32767 == mplexid) ? 0 : mplexid;
6802 
6803  uint excluded_input = 0;
6804  if (Context && Context->m_recorder && Context->m_pseudoLiveTVState == kPseudoNormalLiveTV)
6805  excluded_input = Context->GetCardID();
6806 
6807  uint sourceid = ChannelUtil::GetSourceIDForChannel(ChanId);
6808 
6809  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(excluded_input);
6810 
6811  for (auto & input : inputs)
6812  {
6813  if (input.m_sourceId != sourceid)
6814  continue;
6815 
6816  if (input.m_mplexId &&
6817  input.m_mplexId != mplexid)
6818  continue;
6819 
6820  if (!input.m_mplexId && input.m_chanId &&
6821  input.m_chanId != ChanId)
6822  continue;
6823 
6824  tunable_cards.push_back(input.m_inputId);
6825  }
6826 
6827  if (tunable_cards.empty())
6828  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("ChanId (%1) - no").arg(ChanId));
6829  else
6830  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("ChanId (%1) yes { %2 }").arg(ChanId).arg(toCommaList(tunable_cards)));
6831  return tunable_cards;
6832 }
6833 
6834 void TV::Embed(bool Embed, QRect Rect, const QStringList& Data)
6835 {
6836  emit EmbedPlayback(Embed, Rect);
6837  if (Embed)
6838  return;
6839 
6840  emit ResizeScreenForVideo();
6841 
6842  // m_playerBounds is not applicable when switching modes so
6843  // skip this logic in that case.
6844  if (!m_dbUseVideoModes)
6846 
6847  // Restore pause
6849 
6850  if (!m_weDisabledGUI)
6851  {
6852  m_weDisabledGUI = true;
6854  }
6855 
6856  m_ignoreKeyPresses = false;
6857 
6858  // additional data returned by PlaybackBox
6859  if (!Data.isEmpty())
6860  {
6861  ProgramInfo pginfo(Data);
6862  if (pginfo.HasPathname() || pginfo.GetChanID())
6864  }
6865 }
6866 
6867 bool TV::DoSetPauseState(bool Pause)
6868 {
6869  bool waspaused = ContextIsPaused(__FILE__, __LINE__);
6870  float time = 0.0F;
6871  if (Pause ^ waspaused)
6872  time = DoTogglePauseStart();
6873  if (Pause ^ waspaused)
6874  DoTogglePauseFinish(time, false);
6875  return waspaused;
6876 }
6877 
6878 void TV::DoEditSchedule(int EditType, const QString & EditArg)
6879 {
6880  // Prevent nesting of the pop-up UI
6881  if (m_ignoreKeyPresses)
6882  return;
6883 
6884  if ((EditType == kScheduleProgramGuide && !RunProgramGuidePtr) ||
6885  (EditType == kScheduleProgramFinder && !RunProgramFinderPtr) ||
6886  (EditType == kScheduledRecording && !RunScheduleEditorPtr) ||
6887  (EditType == kViewSchedule && !RunViewScheduledPtr) ||
6888  (EditType == kPlaybackBox && !RunPlaybackBoxPtr))
6889  {
6890  return;
6891  }
6892 
6894 
6895  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
6897  {
6898  LOG(VB_GENERAL, LOG_ERR, LOC + "no active ctx playingInfo.");
6899  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6900  ReturnPlayerLock();
6901  return;
6902  }
6903 
6904  // Collect channel info
6905  const ProgramInfo pginfo(*m_playerContext.m_playingInfo);
6906  uint chanid = pginfo.GetChanID();
6907  QString channum = pginfo.GetChanNum();
6908  QDateTime starttime = MythDate::current();
6909  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
6910 
6911  ClearOSD();
6912 
6913  // Pause playback as needed...
6914  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
6915  bool pause = !m_player || (!StateIsLiveTV(GetState()) && !m_dbContinueEmbedded);
6916  if (m_player)
6917  {
6918  pause |= !m_player->GetVideoOutput();
6919  pause |= m_player->IsPaused();
6920  if (!pause)
6921  pause |= (!StateIsLiveTV(GetState()) && m_player->IsNearEnd());
6922  }
6923  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
6924 
6925  LOG(VB_PLAYBACK, LOG_DEBUG, LOC + QString("Pausing player: %1").arg(pause));
6926  m_savedPause = DoSetPauseState(pause);
6927 
6928  // Resize window to the MythTV GUI size
6929  MythDisplay* display = m_mainWindow->GetDisplay();
6930  if (display->UsingVideoModes())
6931  {
6932  bool hide = display->NextModeIsLarger(display->GetGUIResolution());
6933  if (hide)
6934  m_mainWindow->hide();
6935  display->SwitchToGUI(true);
6936  if (hide)
6937  m_mainWindow->Show();
6938  }
6939 
6940  if (!m_dbUseGuiSizeForTv)
6942 #ifdef Q_OS_ANDROID
6943  m_mainWindow->Show();
6944 #else
6945  m_mainWindow->show();
6946 #endif
6947  ReturnPlayerLock();
6948 
6949 
6950  // Actually show the pop-up UI
6951  switch (EditType)
6952  {
6953  case kScheduleProgramGuide:
6954  {
6955  RunProgramGuidePtr(chanid, channum, starttime, this,
6956  !pause, true, m_channelGroupId);
6957  m_ignoreKeyPresses = true;
6958  break;
6959  }
6961  {
6962  RunProgramFinderPtr(this, !pause, true);
6963  m_ignoreKeyPresses = true;
6964  break;
6965  }
6966  case kScheduleProgramList:
6967  {
6968  /*
6969  4 = plPeopleSearch in mythfrontend/proglist.h
6970  This could be expanded to view other program lists...
6971  */
6972  RunProgramListPtr(this, 4, EditArg);
6973  m_ignoreKeyPresses = true;
6974  break;
6975  }
6976  case kScheduledRecording:
6977  {
6978  RunScheduleEditorPtr(&pginfo, reinterpret_cast<void*>(this));
6979  m_ignoreKeyPresses = true;
6980  break;
6981  }
6982  case kViewSchedule:
6983  {
6984  RunViewScheduledPtr(reinterpret_cast<void*>(this), !pause);
6985  m_ignoreKeyPresses = true;
6986  break;
6987  }
6988  case kPlaybackBox:
6989  {
6990  RunPlaybackBoxPtr(reinterpret_cast<void*>(this), !pause);
6991  m_ignoreKeyPresses = true;
6992  break;
6993  }
6994  }
6995 
6996  // We are embedding in a mythui window so assuming no one
6997  // else has disabled painting show the MythUI window again.
6998  if (m_weDisabledGUI)
6999  {
7001  m_weDisabledGUI = false;
7002  }
7003 }
7004 
7005 void TV::EditSchedule(int EditType, const QString& arg)
7006 {
7007  // post the request so the guide will be created in the UI thread
7008  QString message = QString("START_EPG %1 %2").arg(EditType).arg(arg);
7009  auto* me = new MythEvent(message);
7010  QCoreApplication::postEvent(this, me);
7011 }
7012 
7013 void TV::VolumeChange(bool Up, int NewVolume)
7014 {
7016  return;
7017 
7018  if ((m_audioState.m_muteState == kMuteAll) && (Up || NewVolume >= 0))
7019  emit ChangeMuteState();
7020 
7021  emit ChangeVolume(Up, NewVolume);
7022 
7024  {
7025  if (LCD *lcd = LCD::Get())
7026  {
7027  QString appName = tr("Video");
7028 
7029  if (StateIsLiveTV(GetState()))
7030  appName = tr("TV");
7031 
7033  appName = tr("DVD");
7034 
7035  lcd->switchToVolume(appName);
7036  lcd->setVolumeLevel(static_cast<float>(m_audioState.m_volume) / 100);
7037 
7038  if (m_lcdVolumeTimerId)
7040  m_lcdVolumeTimerId = StartTimer(2s, __LINE__);
7041  }
7042  }
7043 }
7044 
7046 {
7047  if (m_playerContext.m_tsNormal == 1.0F)
7048  {
7050  }
7051  else
7052  {
7054  m_playerContext.m_tsNormal = 1.0F;
7055  }
7056  ChangeTimeStretch(0, false);
7057 }
7058 
7059 void TV::ChangeTimeStretch(int Dir, bool AllowEdit)
7060 {
7061  const float kTimeStretchMin = 0.125;
7062  const float kTimeStretchMax = 2.0;
7063  const float kTimeStretchStep = 0.05F;
7064  float new_ts_normal = m_playerContext.m_tsNormal + (kTimeStretchStep * Dir);
7065  m_stretchAdjustment = AllowEdit;
7066 
7067  if (new_ts_normal > kTimeStretchMax &&
7068  m_playerContext.m_tsNormal < kTimeStretchMax)
7069  {
7070  new_ts_normal = kTimeStretchMax;
7071  }
7072  else if (new_ts_normal < kTimeStretchMin &&
7073  m_playerContext.m_tsNormal > kTimeStretchMin)
7074  {
7075  new_ts_normal = kTimeStretchMin;
7076  }
7077 
7078  if (new_ts_normal > kTimeStretchMax ||
7079  new_ts_normal < kTimeStretchMin)
7080  {
7081  return;
7082  }
7083 
7084  m_playerContext.m_tsNormal = kTimeStretchStep * lroundf(new_ts_normal / kTimeStretchStep);
7085 
7086  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7087  if (m_player && !m_player->IsPaused())
7089  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7090 
7092  {
7093  if (!AllowEdit)
7094  {
7096  }
7097  else
7098  {
7099  UpdateOSDStatus(tr("Adjust Time Stretch"), tr("Time Stretch"),
7100  QString::number(static_cast<double>(m_playerContext.m_tsNormal), 'f', 2),
7102  static_cast<int>(m_playerContext.m_tsNormal * (1000 / kTimeStretchMax)),
7104  emit ChangeOSDPositionUpdates(false);
7105  }
7106  }
7107 
7108  SetSpeedChangeTimer(0ms, __LINE__);
7109 }
7110 
7112 {
7113  QString text;
7114 
7115  // increment sleep index, cycle through
7116  if (++m_sleepIndex == s_sleepTimes.size())
7117  m_sleepIndex = 0;
7118 
7119  // set sleep timer to next sleep_index timeout
7120  if (m_sleepTimerId)
7121  {
7123  m_sleepTimerId = 0;
7124  m_sleepTimerTimeout = 0ms;
7125  }
7126 
7127  if (s_sleepTimes[m_sleepIndex].milliseconds != 0ms)
7128  {
7131  }
7132 
7133  text = tr("Sleep ") + " " + s_sleepTimes[m_sleepIndex].dispString;
7134  emit ChangeOSDMessage(text);
7135 }
7136 
7138 {
7140  m_sleepTimerId = 0;
7141 
7142  QString message = tr("MythTV was set to sleep after %1 minutes and will exit in %d seconds.\n"
7143  "Do you wish to continue watching?")
7144  .arg(duration_cast<std::chrono::minutes>(m_sleepTimerTimeout).count());
7145 
7147  { { tr("Yes"), "DIALOG_SLEEP_YES_0" },
7148  { tr("No"), "DIALOG_SLEEP_NO_0" } }});
7149 
7151 }
7152 
7153 void TV::HandleOSDSleep(const QString& Action)
7154 {
7156  return;
7157 
7158  if (Action == "YES")
7159  {
7161  {
7164  }
7166  }
7167  else
7168  {
7169  LOG(VB_GENERAL, LOG_INFO, LOC + "No longer watching TV, exiting");
7170  SetExitPlayer(true, true);
7171  }
7172 }
7173 
7175 {
7178 
7179  LOG(VB_GENERAL, LOG_INFO, LOC + "Sleep timeout reached, exiting player.");
7180 
7181  SetExitPlayer(true, true);
7182 }
7183 
7193 {
7195  m_idleTimerId = 0;
7196 
7197  QString message = tr("MythTV has been idle for %1 minutes and "
7198  "will exit in %d seconds. Are you still watching?")
7199  .arg(duration_cast<std::chrono::minutes>(m_dbIdleTimeout).count());
7200 
7202  { { tr("Yes"), "DIALOG_IDLE_YES_0" },
7203  { tr("No"), "DIALOG_IDLE_NO_0" }}});
7204 
7206 }
7207 
7208 void TV::HandleOSDIdle(const QString& Action)
7209 {
7211  return;
7212 
7213  if (Action == "YES")
7214  {
7215  if (m_idleDialogTimerId)
7216  {
7218  m_idleDialogTimerId = 0;
7219  }
7220  if (m_idleTimerId)
7223  }
7224  else
7225  {
7226  LOG(VB_GENERAL, LOG_INFO, LOC + "No longer watching LiveTV, exiting");
7227  SetExitPlayer(true, true);
7228  }
7229 }
7230 
7232 {
7234  m_idleDialogTimerId = 0;
7235 
7238  {
7239  LOG(VB_GENERAL, LOG_INFO, LOC + "Idle timeout reached, leaving LiveTV");
7240  SetExitPlayer(true, true);
7241  }
7242  ReturnPlayerLock();
7243 }
7244 
7245 // Retrieve the proper MythTVMenu object from The TV object, given its
7246 // id number. This is used to find the original menu again, instead of
7247 // serializing/deserializing the entire MythTVMenu object to/from a
7248 // QVariant.
7250 {
7251  switch (id) {
7252  case kMenuIdPlayback:
7253  return m_playbackMenu;
7255  return m_playbackCompactMenu;
7256  case kMenuIdCutlist:
7257  return m_cutlistMenu;
7258  case kMenuIdCutlistCompact:
7259  return m_cutlistCompactMenu;
7260  default:
7261  return dummy_menubase;
7262  }
7263 }
7264 
7266 void TV::customEvent(QEvent *Event)
7267 {
7269  {
7271  return;
7272  }
7273 
7274  if (Event->type() == MythEvent::kMythUserMessage)
7275  {
7276  auto *me = dynamic_cast<MythEvent*>(Event);
7277  if (me == nullptr)
7278  return;
7279  QString message = me->Message();
7280 
7281  if (message.isEmpty())
7282  return;
7283 
7284  std::chrono::milliseconds timeout = 0ms;
7285  if (me->ExtraDataCount() == 1)
7286  {
7287  auto t = std::chrono::seconds(me->ExtraData(0).toInt());
7288  if (t > 0s && t < 1000s)
7289  timeout = t;
7290  }
7291 
7292  if (timeout > 0ms)
7293  message += " (%d)";
7294 
7295  emit ChangeOSDDialog( { OSD_DLG_CONFIRM, message, timeout });
7296  return;
7297  }
7298 
7300  {
7301  auto *b = reinterpret_cast<UpdateBrowseInfoEvent*>(Event);
7303  return;
7304  }
7305 
7307  {
7308  auto *dce = reinterpret_cast<DialogCompletionEvent*>(Event);
7309  if (dce->GetData().userType() == qMetaTypeId<MythTVMenuNodeTuple>())
7310  {
7311  auto data = dce->GetData().value<MythTVMenuNodeTuple>();
7312  const MythTVMenu& Menu = getMenuFromId(data.m_id);
7313  QDomNode Node = Menu.GetNodeFromPath(data.m_path);
7314  if (dce->GetResult() == -1) // menu exit/back
7315  PlaybackMenuShow(Menu, Node.parentNode(), Node);
7316  else
7317  PlaybackMenuShow(Menu, Node, QDomNode());
7318  }
7319  else
7320  {
7321  OSDDialogEvent(dce->GetResult(), dce->GetResultText(), dce->GetData().toString());
7322  }
7323  return;
7324  }
7325 
7326  // Stop DVD playback cleanly when the DVD is ejected
7327  if (Event->type() == MythMediaEvent::kEventType)
7328  {
7330  TVState state = m_playerContext.GetState();
7331  if (state != kState_WatchingDVD)
7332  {
7333  ReturnPlayerLock();
7334  return;
7335  }
7336 
7337  auto *me = dynamic_cast<MythMediaEvent*>(Event);
7338  if (me == nullptr)
7339  return;
7340  MythMediaDevice *device = me->getDevice();
7341 
7343 
7344  if (device && filename.endsWith(device->getDevicePath()) && (device->getStatus() == MEDIASTAT_OPEN))
7345  {
7346  LOG(VB_GENERAL, LOG_NOTICE, "DVD has been ejected, exiting playback");
7347  PrepareToExitPlayer(__LINE__);
7348  SetExitPlayer(true, true);
7349  }
7350  ReturnPlayerLock();
7351  return;
7352  }
7353 
7354  if (Event->type() != MythEvent::kMythEventMessage)
7355  return;
7356 
7357  uint cardnum = 0;
7358  auto *me = dynamic_cast<MythEvent*>(Event);
7359  if (me == nullptr)
7360  return;
7361  QString message = me->Message();
7362 
7363  // TODO Go through these and make sure they make sense...
7364  QStringList tokens = message.split(" ", Qt::SkipEmptyParts);
7365 
7366  if (me->ExtraDataCount() == 1)
7367  {
7369  int value = me->ExtraData(0).toInt();
7370  if (message == ACTION_SETVOLUME)
7371  VolumeChange(false, value);
7372  else if (message == ACTION_SETAUDIOSYNC)
7373  emit ChangeAudioOffset(0ms, std::chrono::milliseconds(value));
7374  else if (message == ACTION_SETBRIGHTNESS)
7376  else if (message == ACTION_SETCONTRAST)
7378  else if (message == ACTION_SETCOLOUR)
7380  else if (message == ACTION_SETHUE)
7381  emit ChangePictureAttribute(kPictureAttribute_Hue, false, value);
7382  else if (message == ACTION_JUMPCHAPTER)
7383  DoJumpChapter(value);
7384  else if (message == ACTION_SWITCHTITLE)
7385  DoSwitchTitle(value - 1);
7386  else if (message == ACTION_SWITCHANGLE)
7387  DoSwitchAngle(value);
7388  else if (message == ACTION_SEEKABSOLUTE)
7389  DoSeekAbsolute(value, /*honorCutlist*/true);
7390  ReturnPlayerLock();
7391  }
7392 
7393  if (message == ACTION_SCREENSHOT)
7394  {
7395  int width = 0;
7396  int height = 0;
7397  QString filename;
7398 
7399  if (me->ExtraDataCount() >= 2)
7400  {
7401  width = me->ExtraData(0).toInt();
7402  height = me->ExtraData(1).toInt();
7403 
7404  if (me->ExtraDataCount() == 3)
7405  filename = me->ExtraData(2);
7406  }
7407  MythMainWindow::ScreenShot(width, height, filename);
7408  }
7409  else if (message == ACTION_GETSTATUS)
7410  {
7411  GetStatus();
7412  }
7413  else if (message.startsWith("DONE_RECORDING"))
7414  {
7415  std::chrono::seconds seconds = 0s;
7416  //long long frames = 0;
7417  int NUMTOKENS = 4; // Number of tokens expected
7418  if (tokens.size() == NUMTOKENS)
7419  {
7420  cardnum = tokens[1].toUInt();
7421  seconds = std::chrono::seconds(tokens[2].toInt());
7422  //frames = tokens[3].toLongLong();
7423  }
7424  else
7425  {
7426  LOG(VB_GENERAL, LOG_ERR, QString("DONE_RECORDING event received "
7427  "with invalid number of arguments, "
7428  "%1 expected, %2 actual")
7429  .arg(NUMTOKENS-1)
7430  .arg(tokens.size()-1));
7431  return;
7432  }
7433 
7436  {
7437  if (m_playerContext.m_recorder && (cardnum == m_playerContext.GetCardID()))
7438  {
7439  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7440  if (m_player)
7441  {
7443  if (seconds > 0s)
7444  m_player->SetLength(seconds);
7445  }
7446  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7447 
7450  }
7451  }
7453  {
7454  if (m_playerContext.m_recorder && cardnum == m_playerContext.GetCardID() &&
7456  {
7457  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7458  if (m_player)
7459  {
7461  if (seconds > 0s)
7462  m_player->SetLength(seconds);
7463  }
7464  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7465  }
7466  }
7467  ReturnPlayerLock();
7468  }
7469 
7470  if (message.startsWith("ASK_RECORDING "))
7471  {
7472  int timeuntil = 0;
7473  bool hasrec = false;
7474  bool haslater = false;
7475  if (tokens.size() >= 5)
7476  {
7477  cardnum = tokens[1].toUInt();
7478  timeuntil = tokens[2].toInt();
7479  hasrec = (tokens[3].toInt() != 0);
7480  haslater = (tokens[4].toInt() != 0);
7481  }
7482  LOG(VB_GENERAL, LOG_DEBUG,
7483  LOC + message + QString(" hasrec: %1 haslater: %2")
7484  .arg(hasrec).arg(haslater));
7485 
7488  AskAllowRecording(me->ExtraDataList(), timeuntil, hasrec, haslater);
7489 
7490  ReturnPlayerLock();
7491  }
7492 
7493  if (message.startsWith("QUIT_LIVETV"))
7494  {
7495  cardnum = (tokens.size() >= 2) ? tokens[1].toUInt() : 0;
7496 
7498  bool match = m_playerContext.GetCardID() == cardnum;
7499  if (match && m_playerContext.m_recorder)
7500  {
7501  SetLastProgram(nullptr);
7502  m_jumpToProgram = true;
7503  SetExitPlayer(true, false);
7504  }
7505  ReturnPlayerLock();
7506  }
7507 
7508  if (message.startsWith("LIVETV_WATCH"))
7509  {
7510  int watch = 0;
7511  if (tokens.size() >= 3)
7512  {
7513  cardnum = tokens[1].toUInt();
7514  watch = tokens[2].toInt();
7515  }
7516 
7518  if (m_playerContext.GetCardID() == cardnum)
7519  {
7520  if (watch)
7521  {
7522  ProgramInfo pi(me->ExtraDataList());
7523  if (pi.HasPathname() || pi.GetChanID())
7524  {
7527  m_pseudoChangeChanTimerId = StartTimer(0ms, __LINE__);
7528  }
7529  }
7530  else
7531  {
7533  }
7534  }
7535  ReturnPlayerLock();
7536  }
7537 
7538  if (message.startsWith("LIVETV_CHAIN"))
7539  {
7540  QString id;
7541  if ((tokens.size() >= 2) && tokens[1] == "UPDATE")
7542  id = tokens[2];
7543 
7546  m_playerContext.UpdateTVChain(me->ExtraDataList());
7547  ReturnPlayerLock();
7548  }
7549 
7550  if (message.startsWith("EXIT_TO_MENU"))
7551  {
7553  PrepareToExitPlayer(__LINE__);
7554  SetExitPlayer(true, true);
7555  emit DisableEdit(-1);
7556  ReturnPlayerLock();
7557  }
7558 
7559  if (message.startsWith("SIGNAL"))
7560  {
7561  cardnum = (tokens.size() >= 2) ? tokens[1].toUInt() : 0;
7562  const QStringList& signalList = me->ExtraDataList();
7563 
7565  OSD *osd = GetOSDL();
7566  if (osd)
7567  {
7568  if (m_playerContext.m_recorder && (m_playerContext.GetCardID() == cardnum) && !signalList.empty())
7569  {
7570  UpdateOSDSignal(signalList);
7572  }
7573  }
7574  ReturnOSDLock();
7575  ReturnPlayerLock();
7576  }
7577 
7578  if (message.startsWith("NETWORK_CONTROL"))
7579  {
7580  if ((tokens.size() >= 2) &&
7581  (tokens[1] != "ANSWER") && (tokens[1] != "RESPONSE"))
7582  {
7583  QStringList tokens2 = message.split(" ", Qt::SkipEmptyParts);
7584  if ((tokens2.size() >= 2) &&
7585  (tokens2[1] != "ANSWER") && (tokens2[1] != "RESPONSE"))
7586  {
7589  m_networkControlTimerId = StartTimer(1ms, __LINE__);
7590  }
7591  }
7592  }
7593 
7594  if (message.startsWith("START_EPG"))
7595  {
7596  int editType = tokens[1].toInt();
7597  QString arg = message.section(" ", 2, -1);
7598  DoEditSchedule(editType, arg);
7599  }
7600 
7601  if (message.startsWith("COMMFLAG_START") && (tokens.size() >= 2))
7602  {
7603  uint evchanid = 0;
7604  QDateTime evrecstartts;
7605  ProgramInfo::ExtractKey(tokens[1], evchanid, evrecstartts);
7606 
7608  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7609  bool doit = ((m_playerContext.m_playingInfo) &&
7610  (m_playerContext.m_playingInfo->GetChanID() == evchanid) &&
7611  (m_playerContext.m_playingInfo->GetRecordingStartTime() == evrecstartts));
7612  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7613 
7614  if (doit)
7615  {
7616  QString msg = "COMMFLAG_REQUEST ";
7617  msg += ProgramInfo::MakeUniqueKey(evchanid, evrecstartts);
7618  gCoreContext->SendMessage(msg);
7619  }
7620  ReturnPlayerLock();
7621  }
7622 
7623  if (message.startsWith("COMMFLAG_UPDATE") && (tokens.size() >= 3))
7624  {
7625  uint evchanid = 0;
7626  QDateTime evrecstartts;
7627  ProgramInfo::ExtractKey(tokens[1], evchanid, evrecstartts);
7628 
7630  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7631  bool doit = ((m_playerContext.m_playingInfo) &&
7632  (m_playerContext.m_playingInfo->GetChanID() == evchanid) &&
7633  (m_playerContext.m_playingInfo->GetRecordingStartTime() == evrecstartts));
7634  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7635 
7636  if (doit)
7637  {
7638  frm_dir_map_t newMap;
7639  QStringList mark;
7640  QStringList marks = tokens[2].split(",", Qt::SkipEmptyParts);
7641  for (int j = 0; j < marks.size(); j++)
7642  {
7643  mark = marks[j].split(":", Qt::SkipEmptyParts);
7644  if (marks.size() >= 2)
7645  newMap[mark[0].toULongLong()] = static_cast<MarkTypes>(mark[1].toInt());
7646  }
7647  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7648  if (m_player)
7649  m_player->SetCommBreakMap(newMap);
7650  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7651  }
7652  ReturnPlayerLock();
7653  }
7654 
7655  if (message == "NOTIFICATION")
7656  {
7657  if (!GetNotificationCenter())
7658  return;
7659  MythNotification mn(*me);
7661  }
7662 }
7663 
7665 {
7666  BrowseInfo bi = GetBrowsedInfo();
7667  if (bi.m_chanId)
7668  {
7669  InfoMap infoMap;
7670  QDateTime startts = MythDate::fromString(bi.m_startTime);
7671 
7673  RecordingInfo recinfo(bi.m_chanId, startts, false, 0h, &status);
7674  if (RecordingInfo::kFoundProgram == status)
7675  recinfo.QuickRecord();
7676  recinfo.ToMap(infoMap);
7677  infoMap["iconpath"] = ChannelUtil::GetIcon(recinfo.GetChanID());
7678  if ((recinfo.IsVideoFile() || recinfo.IsVideoDVD() ||
7679  recinfo.IsVideoBD()) && recinfo.GetPathname() != recinfo.GetBasename())
7680  {
7681  infoMap["coverartpath"] = VideoMetaDataUtil::GetArtPath(
7682  recinfo.GetPathname(), "Coverart");
7683  infoMap["fanartpath"] = VideoMetaDataUtil::GetArtPath(
7684  recinfo.GetPathname(), "Fanart");
7685  infoMap["bannerpath"] = VideoMetaDataUtil::GetArtPath(
7686  recinfo.GetPathname(), "Banners");
7687  infoMap["screenshotpath"] = VideoMetaDataUtil::GetArtPath(
7688  recinfo.GetPathname(), "Screenshots");
7689  }
7690 
7692  InfoMap map;
7693  map.insert("message_text", tr("Record"));
7695  return;
7696  }
7697 
7698  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7700  {
7701  LOG(VB_GENERAL, LOG_CRIT, LOC + "Unknown recording during live tv.");
7702  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7703  return;
7704  }
7705 
7706  QString cmdmsg("");
7708  {
7710  recInfo.SaveAutoExpire(static_cast<AutoExpireType>(m_dbAutoexpireDefault));
7711  recInfo.ApplyRecordRecGroupChange("Default");
7712  *m_playerContext.m_playingInfo = recInfo;
7713 
7714  cmdmsg = tr("Record");
7717  LOG(VB_RECORD, LOG_INFO, LOC + "Toggling Record on");
7718  }
7719  else
7720  {
7723  recInfo.ApplyRecordRecGroupChange("LiveTV");
7724  *m_playerContext.m_playingInfo = recInfo;
7725 
7726  cmdmsg = tr("Cancel Record");
7729  LOG(VB_RECORD, LOG_INFO, LOC + "Toggling Record off");
7730  }
7731 
7732  QString msg = cmdmsg + " \"" + m_playerContext.m_playingInfo->GetTitle() + "\"";
7733 
7734  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7735 
7736  emit ChangeOSDMessage(msg);
7737 }
7738 
7739 void TV::HandleOSDClosed(int OSDType)
7740 {
7741  switch (OSDType)
7742  {
7746  break;
7748  m_doSmartForward = false;
7749  break;
7751  m_stretchAdjustment = false;
7752  break;
7754  m_audiosyncAdjustment = false;
7755  gCoreContext->SaveSetting("AudioSyncOffset", QString::number(m_audioState.m_audioOffset.count()));
7756  break;
7758  m_subtitleZoomAdjustment = false;
7759  break;
7761  m_subtitleDelayAdjustment = false;
7762  break;
7764  break;
7765  }
7766 }
7767 
7769 {
7771  if ((kAdjustingPicture_Playback == Type))
7772  {
7776  // Filter out range
7778  }
7779  else if ((kAdjustingPicture_Channel == Type) || (kAdjustingPicture_Recording == Type))
7780  {
7785  }
7786 
7787  return ::next_picattr(static_cast<PictureAttributeSupported>(sup), Attr);
7788 }
7789 
7791 {
7793  if (kPictureAttribute_None == attr)
7794  return;
7795 
7796  m_adjustingPicture = Type;
7798 
7799  QString title = toTitleString(Type);
7800 
7801  int value = 99;
7802  if (kAdjustingPicture_Playback == Type)
7803  {
7805  {
7806  value = m_videoColourState.GetValue(attr);
7807  }
7809  {
7810  value = static_cast<int>(m_audioState.m_volume);
7811  title = tr("Adjust Volume");
7812  }
7813  }
7814 
7817 
7818  QString text = toString(attr) + " " + toTypeString(Type);
7819 
7820  UpdateOSDStatus(title, text, QString::number(value),
7822  value * 10, kOSDTimeout_Med);
7823  emit ChangeOSDPositionUpdates(false);
7824 }
7825 
7826 void TV::ShowOSDCutpoint(const QString &Type)
7827 {
7828  if (Type == "EDIT_CUT_POINTS")
7829  {
7830  if (!m_cutlistMenu.IsLoaded())
7831  {
7832  // TODO which translation context to use?
7834  "menu_cutlist.xml", tr("Edit Cut Points"),
7835  metaObject()->className(), "TV Editing");
7836  }
7837 
7838  if (m_cutlistMenu.IsLoaded())
7840  }
7841  else if (Type == "EDIT_CUT_POINTS_COMPACT")
7842  {
7844  {
7845  // TODO which translation context to use?
7847  "menu_cutlist_compact.xml", tr("Edit Cut Points"),
7848  metaObject()->className(), "TV Editing");
7849  }
7850 
7853  }
7854  else if (Type == "EXIT_EDIT_MODE")
7855  {
7856  MythOSDDialogData dialog { OSD_DLG_CUTPOINT, tr("Exit Recording Editor") };
7857  dialog.m_buttons.push_back( { tr("Save Cuts and Exit"), "DIALOG_CUTPOINT_SAVEEXIT_0" } );
7858  dialog.m_buttons.push_back( { tr("Exit Without Saving"), "DIALOG_CUTPOINT_REVERTEXIT_0" } );
7859  dialog.m_buttons.push_back( { tr("Save Cuts"), "DIALOG_CUTPOINT_SAVEMAP_0" } );
7860  dialog.m_buttons.push_back( { tr("Undo Changes"), "DIALOG_CUTPOINT_REVERT_0" } );
7861  dialog.m_back = { "", "DIALOG_CUTPOINT_DONOTHING_0", true };
7862  emit ChangeOSDDialog(dialog);
7863 
7864  InfoMap map;
7865  map.insert("title", tr("Edit"));
7867  }
7868 }
7869 
7870 bool TV::HandleOSDCutpoint(const QString& Action)
7871 {
7872  bool res = true;
7874  return res;
7875 
7876  OSD *osd = GetOSDL();
7877  if (Action == "DONOTHING" && osd)
7878  {
7879  }
7880  else if (osd)
7881  {
7882  QStringList actions(Action);
7883  if (!m_player->HandleProgramEditorActions(actions))
7884  LOG(VB_GENERAL, LOG_ERR, LOC + "Unrecognised cutpoint action");
7885  }
7886  ReturnOSDLock();
7887  return res;
7888 }
7889 
7894 {
7895  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7896  bool isEditing = m_playerContext.m_playingInfo->QueryIsEditing();
7897  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7898 
7899  if (isEditing)
7900  {
7902  return;
7903  }
7904 
7905  emit EnableEdit();
7906 }
7907 
7909 {
7910  bool paused = ContextIsPaused(__FILE__, __LINE__);
7911  if (!paused)
7912  DoTogglePause(true);
7913 
7914  QString message = tr("This program is currently being edited");
7915  QString def = QString("DIALOG_EDITING_CONTINUE_%1").arg(static_cast<int>(paused));
7916  emit ChangeOSDDialog( { OSD_DLG_EDITING, message, 0ms,
7917  { { tr("Continue Editing"), def, false, true },
7918  { tr("Do not edit"), QString("DIALOG_EDITING_STOP_%1").arg(static_cast<int>(paused)) }},
7919  { "", def, true} });
7920 }
7921 
7922 void TV::HandleOSDAlreadyEditing(const QString& Action, bool WasPaused)
7923 {
7925  return;
7926 
7927  bool paused = ContextIsPaused(__FILE__, __LINE__);
7928 
7929  if (Action == "STOP")
7930  {
7931  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
7934  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
7935  if (!WasPaused && paused)
7936  DoTogglePause(true);
7937  }
7938  else // action == "CONTINUE"
7939  {
7940  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
7942  emit EnableEdit();
7943  if (!m_overlayState.m_editing && !WasPaused && paused)
7944  DoTogglePause(false);
7945  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
7946  }
7947 
7948 }
7949 
7950 static void insert_map(InfoMap &infoMap, const InfoMap &newMap)
7951 {
7952  for (auto it = newMap.cbegin(); it != newMap.cend(); ++it)
7953  infoMap.insert(it.key(), *it);
7954 }
7955 
7960 {
7961  OSD *osd = GetOSDL();
7962  if (!m_playerContext.m_recorder || !osd)
7963  {
7964  ReturnOSDLock();
7965  return;
7966  }
7967  ReturnOSDLock();
7968 
7969  QMutexLocker locker(&m_chanEditMapLock);
7970 
7971  // Get the info available from the backend
7972  m_chanEditMap.clear();
7974 
7975  // Update with XDS Info
7977 
7978  // Set proper initial values for channel editor, and make it visible..
7979  osd = GetOSDL();
7980  if (osd)
7981  {
7982  emit ChangeOSDDialog({ OSD_DLG_EDITOR });
7984  }
7985  ReturnOSDLock();
7986 }
7987 
7989 {
7990  OSD *osd = GetOSDL();
7991  if (osd)
7992  {
7993  emit HideAll();
7994  ToggleOSD(true);
7996  }
7997  ReturnOSDLock();
7998 }
7999 
8003 bool TV::HandleOSDChannelEdit(const QString& Action)
8004 {
8005  QMutexLocker locker(&m_chanEditMapLock);
8006  bool hide = false;
8007 
8009  return hide;
8010 
8011  OSD *osd = GetOSDL();
8012  if (osd && Action == "PROBE")
8013  {
8014  InfoMap infoMap;
8015  osd->DialogGetText(infoMap);
8016  ChannelEditAutoFill(infoMap);
8017  insert_map(m_chanEditMap, infoMap);
8019  }
8020  else if (osd && Action == "OK")
8021  {
8022  InfoMap infoMap;
8023  osd->DialogGetText(infoMap);
8024  insert_map(m_chanEditMap, infoMap);
8026  hide = true;
8027  }
8028  else if (osd && Action == "QUIT")
8029  {
8030  hide = true;
8031  }
8032  ReturnOSDLock();
8033  return hide;
8034 }
8035 
8040 {
8041 #if 0
8042  const QString keys[4] = { "XMLTV", "callsign", "channame", "channum", };
8043 #endif
8044 
8045  // fill in uninitialized and unchanged fields from XDS
8046  ChannelEditXDSFill(Info);
8047 }
8048 
8050 {
8051  QMap<QString,bool> modifiable;
8052  modifiable["callsign"] = Info["callsign"].isEmpty();
8053  if (!modifiable["callsign"])
8054  {
8055  QString unsetsign = tr("UNKNOWN%1", "Synthesized callsign");
8056  int unsetcmpl = unsetsign.length() - 2;
8057  unsetsign = unsetsign.left(unsetcmpl);
8058  if (Info["callsign"].left(unsetcmpl) == unsetsign) // was unsetcmpl????
8059  modifiable["callsign"] = true;
8060  }
8061  modifiable["channame"] = Info["channame"].isEmpty();
8062 
8063  const std::array<const QString,2> xds_keys { "callsign", "channame", };
8064  for (const auto & key : xds_keys)
8065  {
8066  if (!modifiable[key])
8067  continue;
8068 
8069  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
8070  QString tmp = m_player->GetXDS(key).toUpper();
8071  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
8072 
8073  if (tmp.isEmpty())
8074  continue;
8075 
8076  if ((key == "callsign") &&
8077  ((tmp.length() > 5) || (tmp.indexOf(" ") >= 0)))
8078  {
8079  continue;
8080  }
8081 
8082  Info[key] = tmp;
8083  }
8084 }
8085 
8086 void TV::OSDDialogEvent(int Result, const QString& Text, QString Action)
8087 {
8089  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("result %1 text %2 action %3")
8090  .arg(QString::number(Result), Text, Action));
8091 
8092  bool hide = true;
8093  if (Result == 100)
8094  hide = false;
8095 
8096  bool handled = true;
8097  if (Action.startsWith("DIALOG_"))
8098  {
8099  Action.remove("DIALOG_");
8100  QStringList desc = Action.split("_");
8101  bool valid = desc.size() == 3;
8102  if (valid && desc[0] == ACTION_JUMPREC)
8103  {
8104  FillOSDMenuJumpRec(desc[1], desc[2].toInt(), Text);
8105  hide = false;
8106  }
8107  else if (valid && desc[0] == "VIDEOEXIT")
8108  {
8109  hide = HandleOSDVideoExit(desc[1]);
8110  }
8111  else if (valid && desc[0] == "SLEEP")
8112  {
8113  HandleOSDSleep(desc[1]);
8114  }
8115  else if (valid && desc[0] == "IDLE")
8116  {
8117  HandleOSDIdle(desc[1]);
8118  }
8119  else if (valid && desc[0] == "INFO")
8120  {
8121  HandleOSDInfo(desc[1]);
8122  }
8123  else if (valid && desc[0] == "EDITING")
8124  {
8125  HandleOSDAlreadyEditing(desc[1], desc[2].toInt() != 0);
8126  }
8127  else if (valid && desc[0] == "ASKALLOW")
8128  {
8129  HandleOSDAskAllow(desc[1]);
8130  }
8131  else if (valid && desc[0] == "EDITOR")
8132  {
8133  hide = HandleOSDChannelEdit(desc[1]);
8134  }
8135  else if (valid && desc[0] == "CUTPOINT")
8136  {
8137  hide = HandleOSDCutpoint(desc[1]);
8138  }
8139  else if ((valid && desc[0] == "DELETE") ||
8140  (valid && desc[0] == "CONFIRM"))
8141  {
8142  }
8143  else if (valid && desc[0] == ACTION_PLAY)
8144  {
8145  DoPlay();
8146  }
8147  else
8148  {
8149  LOG(VB_GENERAL, LOG_ERR, "Unrecognised dialog event.");
8150  }
8151  }
8152  else if (Result < 0)
8153  { // NOLINT(bugprone-branch-clone)
8154  ; // exit dialog
8155  }
8156  else if (HandleTrackAction(Action))
8157  {
8158  ;
8159  }
8160  else if (Action == ACTION_PAUSE)
8161  {
8162  DoTogglePause(true);
8163  }
8164  else if (Action == ACTION_STOP)
8165  {
8166  PrepareToExitPlayer(__LINE__);
8167  SetExitPlayer(true, true);
8168  }
8169  else if (Action == "CANCELPLAYLIST")
8170  {
8171  SetInPlayList(false);
8172  MythEvent xe("CANCEL_PLAYLIST");
8173  gCoreContext->dispatch(xe);
8174  }
8175  else if (Action == ACTION_JUMPFFWD)
8176  {
8177  DoJumpFFWD();
8178  }
8179  else if (Action == ACTION_JUMPRWND)
8180  {
8181  DoJumpRWND();
8182  }
8183  else if (Action == ACTION_SEEKFFWD)
8184  {
8185  DoSeekFFWD();
8186  }
8187  else if (Action == ACTION_SEEKRWND)
8188  {
8189  DoSeekRWND();
8190  }
8191  else if (Action == ACTION_TOGGLEOSDDEBUG)
8192  {
8193  emit ChangeOSDDebug();
8194  }
8195  else if (Action == "TOGGLEMANUALZOOM")
8196  {
8197  SetManualZoom(true, tr("Zoom Mode ON"));
8198  }
8199  else if (Action == ACTION_BOTTOMLINEMOVE)
8200  {
8201  emit ToggleMoveBottomLine();
8202  }
8203  else if (Action == ACTION_BOTTOMLINESAVE)
8204  {
8205  emit SaveBottomLine();
8206  }
8207  else if (Action == "TOGGLESTRETCH")
8208  {
8210  }
8211  else if (Action == ACTION_ENABLEUPMIX)
8212  {
8213  emit ChangeUpmix(true);
8214  }
8215  else if (Action == ACTION_DISABLEUPMIX)
8216  {
8217  emit ChangeUpmix(false);
8218  }
8219  else if (Action.startsWith("ADJUSTSTRETCH"))
8220  {
8221  bool floatRead = false;
8222  float stretch = Action.right(Action.length() - 13).toFloat(&floatRead);
8223  if (floatRead &&
8224  stretch <= 2.0F &&
8225  stretch >= 0.48F)
8226  {
8227  m_playerContext.m_tsNormal = stretch; // alter speed before display
8228  }
8229 
8230  StopFFRew();
8231 
8232  if (ContextIsPaused(__FILE__, __LINE__))
8233  DoTogglePause(true);
8234 
8235  ChangeTimeStretch(0, !floatRead); // just display
8236  }
8237  else if (Action.startsWith("SELECTSCAN_"))
8238  {
8239  OverrideScan(static_cast<FrameScanType>(Action.right(1).toInt()));
8240  }
8241  else if (Action.startsWith(ACTION_TOGGELAUDIOSYNC))
8242  {
8243  emit ChangeAudioOffset(0ms);
8244  }
8245  else if (Action == ACTION_TOGGLESUBTITLEZOOM)
8246  {
8247  emit AdjustSubtitleZoom(0);
8248  }
8249  else if (Action == ACTION_TOGGLESUBTITLEDELAY)
8250  {
8251  emit AdjustSubtitleDelay(0ms);
8252  }
8253  else if (Action == ACTION_TOGGLEVISUALISATION)
8254  {
8255  emit EnableVisualiser(false, true);
8256  }
8257  else if (Action == ACTION_ENABLEVISUALISATION)
8258  {
8259  emit EnableVisualiser(true);
8260  }
8261  else if (Action == ACTION_DISABLEVISUALISATION)
8262  {
8263  emit EnableVisualiser(false);
8264  }
8265  else if (Action.startsWith(ACTION_TOGGLESLEEP))
8266  {
8267  ToggleSleepTimer(Action.left(13));
8268  }
8269  else if (Action.startsWith("TOGGLEPICCONTROLS"))
8270  {
8271  m_adjustingPictureAttribute = static_cast<PictureAttribute>(Action.right(1).toInt() - 1);
8273  }
8274  else if (Action == "TOGGLEASPECT")
8275  {
8276  emit ChangeAspectOverride();
8277  }
8278  else if (Action.startsWith("TOGGLEASPECT"))
8279  {
8280  emit ChangeAspectOverride(static_cast<AspectOverrideMode>(Action.right(1).toInt()));
8281  }
8282  else if (Action == "TOGGLEFILL")
8283  {
8284  emit ChangeAdjustFill();
8285  }
8286  else if (Action.startsWith("TOGGLEFILL"))
8287  {
8288  emit ChangeAdjustFill(static_cast<AdjustFillMode>(Action.right(1).toInt()));
8289  }
8290  else if (Action == "MENU")
8291  {
8292  ShowOSDMenu();
8293  }
8294  else if (Action == "AUTODETECT_FILL")
8295  {
8296  emit ToggleDetectLetterBox();
8297  }
8298  else if (Action == ACTION_GUIDE)
8299  {
8301  }
8302  else if (Action.startsWith("CHANGROUP_") && m_dbUseChannelGroups)
8303  {
8304  if (Action == "CHANGROUP_ALL_CHANNELS")
8305  {
8306  UpdateChannelList(-1);
8307  }
8308  else
8309  {
8310  Action.remove("CHANGROUP_");
8311 
8312  UpdateChannelList(Action.toInt());
8313 
8314  // make sure the current channel is from the selected group
8315  // or tune to the first in the group
8316  QString cur_channum;
8317  QString new_channum;
8319  {
8320  QMutexLocker locker(&m_channelGroupLock);
8322  cur_channum = m_playerContext.m_tvchain->GetChannelName(-1);
8323  new_channum = cur_channum;
8324 
8325  auto it = list.cbegin();
8326  for (; it != list.cend(); ++it)
8327  {
8328  if ((*it).m_chanNum == cur_channum)
8329  {
8330  break;
8331  }
8332  }
8333 
8334  if (it == list.end())
8335  {
8336  // current channel not found so switch to the
8337  // first channel in the group
8338  it = list.begin();
8339  if (it != list.end())
8340  new_channum = (*it).m_chanNum;
8341  }
8342 
8343  LOG(VB_CHANNEL, LOG_INFO, LOC +
8344  QString("Channel Group: '%1'->'%2'")
8345  .arg(cur_channum, new_channum));
8346  }
8347 
8349  {
8350  // Only change channel if new channel != current channel
8351  if (cur_channum != new_channum && !new_channum.isEmpty())
8352  {
8353  m_queuedInput = new_channum;
8354  m_queuedChanNum = new_channum;
8355  m_queuedChanID = 0;
8356  if (!m_queueInputTimerId)
8357  m_queueInputTimerId = StartTimer(10ms, __LINE__);
8358  }
8359 
8360  // Turn off OSD Channel Num so the channel
8361  // changes right away
8363  }
8364  }
8365  }
8366  else if (Action == ACTION_FINDER)
8367  {
8369  }
8370  else if (Action == "SCHEDULE")
8371  {
8373  }
8374  else if (Action == ACTION_VIEWSCHEDULED)
8375  {
8377  }
8378  else if (Action == ACTION_CAST)
8379  {
8380  FillOSDMenuCast();
8381  hide = false;
8382  }
8383  else if (Action.startsWith("JUMPCAST|"))
8384  {
8385  QStringList tokens = Action.split("|");
8386  if (tokens.size() == 3)
8387  FillOSDMenuActorShows(tokens[1], tokens[2].toInt());
8388  else if (tokens.size() == 4)
8389  FillOSDMenuActorShows(tokens[1], tokens[2].toInt(), tokens[3]);
8390 
8391  hide = false;
8392  }
8393  else if (Action.startsWith("VISUALISER"))
8394  {
8395  emit EnableVisualiser(true, false, Action.mid(11));
8396  }
8397  else if (Action.startsWith("3D"))
8398  {
8400  }
8401  else if (HandleJumpToProgramAction(QStringList(Action)))
8402  {
8403  }
8404  else if (StateIsLiveTV(GetState()))
8405  {
8406  if (Action == "TOGGLEBROWSE")
8407  BrowseStart();
8408  else if (Action == "PREVCHAN")
8409  PopPreviousChannel(true);
8410  else if (Action.startsWith("SWITCHTOINPUT_"))
8411  {
8412  m_switchToInputId = Action.mid(14).toUInt();
8414  }
8415  else if (Action == "EDIT")
8416  {
8418  hide = false;
8419  }
8420  else
8421  {
8422  handled = false;
8423  }
8424  }
8425  else
8426  {
8427  handled = false;
8428  }
8429  if (!handled && StateIsPlaying(m_playerContext.GetState()))
8430  {
8431  handled = true;
8434  {
8436  emit GoToMenu("chapter");
8437  else if (Action == ACTION_JUMPTODVDTITLEMENU)
8438  emit GoToMenu("title");
8439  else if (Action == ACTION_JUMPTOPOPUPMENU)
8440  emit GoToMenu("popup");
8441  else
8442  emit GoToMenu("root");
8443  }
8444  else if (Action.startsWith(ACTION_JUMPCHAPTER))
8445  {
8446  int chapter = Action.right(3).toInt();
8447  DoJumpChapter(chapter);
8448  }
8449  else if (Action.startsWith(ACTION_SWITCHTITLE))
8450  {
8451  int title = Action.right(3).toInt();
8452  DoSwitchTitle(title);
8453  }
8454  else if (Action.startsWith(ACTION_SWITCHANGLE))
8455  {
8456  int angle = Action.right(3).toInt();
8457  DoSwitchAngle(angle);
8458  }
8459  else if (Action == "EDIT")
8460  {
8462  hide = false;
8463  }
8464  else if (Action == "TOGGLEAUTOEXPIRE")
8465  {
8466  ToggleAutoExpire();
8467  }
8468  else if (Action.startsWith("TOGGLECOMMSKIP"))
8469  {
8470  SetAutoCommercialSkip(static_cast<CommSkipMode>(Action.right(1).toInt()));
8471  }
8472  else if (Action == "QUEUETRANSCODE")
8473  {
8474  DoQueueTranscode("Default");
8475  }
8476  else if (Action == "QUEUETRANSCODE_AUTO")
8477  {
8478  DoQueueTranscode("Autodetect");
8479  }
8480  else if (Action == "QUEUETRANSCODE_HIGH")
8481  {
8482  DoQueueTranscode("High Quality");
8483  }
8484  else if (Action == "QUEUETRANSCODE_MEDIUM")
8485  {
8486  DoQueueTranscode("Medium Quality");
8487  }
8488  else if (Action == "QUEUETRANSCODE_LOW")
8489  {
8490  DoQueueTranscode("Low Quality");
8491  }
8492  else
8493  {
8494  handled = false;
8495  }
8496  }
8497 
8498  if (!handled)
8499  {
8502  handled = ActiveHandleAction(QStringList(Action), isDVD, isMenuOrStill);
8503  }
8504 
8505  if (!handled)
8506  handled = ActivePostQHandleAction(QStringList(Action));
8507 
8508  if (!handled)
8509  {
8510  LOG(VB_GENERAL, LOG_ERR, LOC +
8511  "Unknown menu action selected: " + Action);
8512  hide = false;
8513  }
8514 
8515  if (hide)
8516  emit DialogQuit();
8517  ReturnPlayerLock();
8518 }
8519 
8520 bool TV::DialogIsVisible(const QString &Dialog)
8521 {
8522  bool visible = false;
8523  OSD *osd = GetOSDL();
8524  if (osd)
8525  visible = osd->DialogVisible(Dialog);
8526  ReturnOSDLock();
8527  return visible;
8528 }
8529 
8530 void TV::HandleOSDInfo(const QString& Action)
8531 {
8533  return;
8534 
8535  if (Action == "CHANNELLOCK")
8536  m_lockTimerOn = false;
8537 }
8538 
8539 // NOLINTBEGIN(cppcoreguidelines-macro-usage)
8540 #define BUTTON(action, text) \
8541  result = Context.AddButton(Menu, active, (action), (text), "", false, "")
8542 #define BUTTON2(action, textActive, textInactive) \
8543  result = Context.AddButton(Menu, active, (action), (textActive), (textInactive), false, "")
8544 #define BUTTON3(action, textActive, textInactive, isMenu) \
8545  result = Context.AddButton(Menu, active, (action), (textActive), (textInactive), (isMenu), "")
8546 // NOLINTEND(cppcoreguidelines-macro-usage)
8547 
8549 {
8550  if (&Context.m_menu == &m_playbackMenu || &Context.m_menu == &m_playbackCompactMenu)
8551  return MenuItemDisplayPlayback(Context, Menu);
8552  if (&Context.m_menu == &m_cutlistMenu || &Context.m_menu == &m_cutlistCompactMenu)
8553  return MenuItemDisplayCutlist(Context, Menu);
8554  return false;
8555 }
8556 
8558 {
8559  MenuCategory category = Context.m_category;
8560  const QString &actionName = Context.m_action;
8561 
8562  bool result = false;
8563  if (category == kMenuCategoryMenu)
8564  {
8565  result = Context.m_menu.Show(Context.m_node, QDomNode(), *this, Menu, false);
8566  if (result && Context.m_visible)
8567  {
8568  QVariant v;
8569  v.setValue(MythTVMenuNodeTuple(Context.m_menu.m_id,
8571  Menu->m_buttons.push_back( { Context.m_menuName, v, true,
8572  Context.m_currentContext != kMenuCurrentDefault });
8573  }
8574  return result;
8575  }
8576 
8577  emit RefreshEditorState();
8578 
8579  if (category == kMenuCategoryItem)
8580  {
8581  bool active = true;
8582  if (actionName == "DIALOG_CUTPOINT_MOVEPREV_0")
8583  {
8588  {
8590  BUTTON2(actionName, tr("Move Previous Cut End Here"), tr("Move Start of Cut Here"));
8591  }
8592  }
8593  else if (actionName == "DIALOG_CUTPOINT_MOVENEXT_0")
8594  {
8599  {
8601  BUTTON2(actionName, tr("Move Next Cut Start Here"), tr("Move End of Cut Here"));
8602  }
8603  }
8604  else if (actionName == "DIALOG_CUTPOINT_CUTTOBEGINNING_0")
8605  {
8607  BUTTON(actionName, tr("Cut to Beginning"));
8608  }
8609  else if (actionName == "DIALOG_CUTPOINT_CUTTOEND_0")
8610  {
8613  {
8614  BUTTON(actionName, tr("Cut to End"));
8615  }
8616  }
8617  else if (actionName == "DIALOG_CUTPOINT_DELETE_0")
8618  {
8619  active = m_editorState.m_frameInDelete;
8620  BUTTON2(actionName, tr("Delete This Cut"), tr("Join Surrounding Cuts"));
8621  }
8622  else if (actionName == "DIALOG_CUTPOINT_NEWCUT_0")
8623  {
8625  BUTTON(actionName, tr("Add New Cut"));
8626  }
8627  else if (actionName == "DIALOG_CUTPOINT_UNDO_0")
8628  {
8629  active = m_editorState.m_hasUndo;
8630  //: %1 is the undo message
8631  QString text = tr("Undo - %1");
8632  result = Context.AddButton(Menu, active, actionName, text, "", false,
8634  }
8635  else if (actionName == "DIALOG_CUTPOINT_REDO_0")
8636  {
8637  active = m_editorState.m_hasRedo;
8638  //: %1 is the redo message
8639  QString text = tr("Redo - %1");
8640  result = Context.AddButton(Menu, active, actionName, text, "", false,
8642  }
8643  else if (actionName == "DIALOG_CUTPOINT_CLEARMAP_0")
8644  {
8645  BUTTON(actionName, tr("Clear Cuts"));
8646  }
8647  else if (actionName == "DIALOG_CUTPOINT_INVERTMAP_0")
8648  {
8649  BUTTON(actionName, tr("Reverse Cuts"));
8650  }
8651  else if (actionName == "DIALOG_CUTPOINT_LOADCOMMSKIP_0")
8652  {
8653  BUTTON(actionName, tr("Load Detected Commercials"));
8654  }
8655  else if (actionName == "DIALOG_CUTPOINT_REVERT_0")
8656  {
8657  BUTTON(actionName, tr("Undo Changes"));
8658  }
8659  else if (actionName == "DIALOG_CUTPOINT_REVERTEXIT_0")
8660  {
8661  BUTTON(actionName, tr("Exit Without Saving"));
8662  }
8663  else if (actionName == "DIALOG_CUTPOINT_SAVEMAP_0")
8664  {
8665  BUTTON(actionName, tr("Save Cuts"));
8666  }
8667  else if (actionName == "DIALOG_CUTPOINT_SAVEEXIT_0")
8668  {
8669  BUTTON(actionName, tr("Save Cuts and Exit"));
8670  }
8671  else
8672  {
8673  // Allow an arbitrary action if it has a translated
8674  // description available to be used as the button text.
8675  // Look in the specified keybinding context as well as the
8676  // Global context.
8677  // XXX This doesn't work well (yet) because a keybinding
8678  // action named "foo" is actually a menu action named
8679  // "DIALOG_CUTPOINT_foo_0".
8680  QString text = m_mainWindow->GetActionText(Context.m_menu.GetKeyBindingContext(), actionName);
8681  if (text.isEmpty())
8682  text = m_mainWindow->GetActionText("Global", actionName);
8683  if (!text.isEmpty())
8684  BUTTON(actionName, text);
8685  }
8686  }
8687 
8688  return result;
8689 }
8690 
8691 // Returns true if at least one item should be displayed.
8693  MythOSDDialogData *Menu)
8694 {
8695  MenuCategory category = Context.m_category;
8696  const QString &actionName = Context.m_action;
8697 
8698  bool result = false;
8699  bool active = true;
8700 
8701  if (category == kMenuCategoryMenu)
8702  {
8703  result = Context.m_menu.Show(Context.m_node, QDomNode(), *this, Menu, false);
8704  if (result && Context.m_visible)
8705  {
8706  QVariant v;
8707  v.setValue(MythTVMenuNodeTuple(Context.m_menu.m_id,
8709  Menu->m_buttons.push_back( { Context.m_menuName, v, true,
8710  Context.m_currentContext != kMenuCurrentDefault } );
8711  }
8712  return result;
8713  }
8714  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
8715  QString prefix;
8716  if (MythTVMenu::MatchesGroup(actionName, "VISUALISER_", category, prefix) &&
8718  {
8719  for (auto & visualiser : m_visualiserState.m_visualiserList)
8720  {
8721  active = m_visualiserState.m_visualiserName == visualiser;
8722  BUTTON(prefix + visualiser, visualiser);
8723  }
8724  }
8725  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLEASPECT", category, prefix))
8726  {
8727  for (int j = kAspect_Off; j < kAspect_END; j++)
8728  {
8729  // swap 14:9 and 16:9
8730  int i {j};
8731  if (kAspect_14_9 == j)
8732  i = kAspect_16_9;
8733  else if (kAspect_16_9 == j)
8734  i = kAspect_14_9;
8735  QString action = prefix + QString::number(i);
8736  active = (m_videoBoundsState.m_aspectOverrideMode == i);
8737  BUTTON(action, toString(static_cast<AspectOverrideMode>(i)));
8738  }
8739  }
8740  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLEFILL", category, prefix))
8741  {
8742  for (int i = kAdjustFill_Off; i < kAdjustFill_END; i++)
8743  {
8744  QString action = prefix + QString::number(i);
8745  active = (m_videoBoundsState.m_adjustFillMode == i);
8746  BUTTON(action, toString(static_cast<AdjustFillMode>(i)));
8747  }
8748  }
8749  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLEPICCONTROLS", category, prefix))
8750  {
8751  for (int i = kPictureAttribute_MIN; i < kPictureAttribute_MAX; i++)
8752  {
8754  {
8755  QString action = prefix + QString::number(i - kPictureAttribute_MIN);
8756  if (static_cast<PictureAttribute>(i) != kPictureAttribute_Range)
8757  BUTTON(action, toString(static_cast<PictureAttribute>(i)));
8758  }
8759  }
8760  }
8761  else if (MythTVMenu::MatchesGroup(actionName, "3D", category, prefix))
8762  {
8764  BUTTON(ACTION_3DNONE, tr("Auto"));
8766  BUTTON(ACTION_3DIGNORE, tr("Ignore"));
8768  BUTTON(ACTION_3DSIDEBYSIDEDISCARD, tr("Discard Side by Side"));
8770  BUTTON(ACTION_3DTOPANDBOTTOMDISCARD, tr("Discard Top and Bottom"));
8771  }
8772  else if (MythTVMenu::MatchesGroup(actionName, "SELECTSCAN_", category, prefix) && m_player)
8773  {
8775  active = (scan == kScan_Detect);
8776  BUTTON("SELECTSCAN_0", ScanTypeToUserString(kScan_Detect));
8777  active = (scan == kScan_Progressive);
8778  BUTTON("SELECTSCAN_3", ScanTypeToUserString(kScan_Progressive));
8779  active = (scan == kScan_Interlaced);
8780  BUTTON("SELECTSCAN_1", ScanTypeToUserString(kScan_Interlaced));
8781  active = (scan == kScan_Intr2ndField);
8783  }
8784  else if (MythTVMenu::MatchesGroup(actionName, "SELECTSUBTITLE_", category, prefix) ||
8785  MythTVMenu::MatchesGroup(actionName, "SELECTRAWTEXT_", category, prefix) ||
8786  MythTVMenu::MatchesGroup(actionName, "SELECTCC708_", category, prefix) ||
8787  MythTVMenu::MatchesGroup(actionName, "SELECTCC608_", category, prefix) ||
8788  MythTVMenu::MatchesGroup(actionName, "SELECTTTC_", category, prefix) ||
8789  MythTVMenu::MatchesGroup(actionName, "SELECTAUDIO_", category, prefix))
8790  {
8791  int i = 0;
8793  if (prefix == "SELECTSUBTITLE_")
8795  else if (prefix == "SELECTRAWTEXT_")
8797  else if (prefix == "SELECTCC708_")
8799  else if (prefix == "SELECTCC608_")
8801  else if (prefix == "SELECTTTC_")
8803  else if (prefix == "SELECTAUDIO_")
8804  {
8806  if (m_tvmTracks[type].size() <= 1)
8807  i = 1; // don't show choices if only 1 audio track
8808  }
8809 
8810  for (; i < m_tvmTracks[type].size(); i++)
8811  {
8812  QString action = prefix + QString::number(i);
8813  active = (i == m_tvmCurtrack[type]);
8814  BUTTON(action, m_tvmTracks[type][i]);
8815  }
8816  }
8817  else if (MythTVMenu::MatchesGroup(actionName, "ADJUSTSTRETCH", category, prefix))
8818  {
8819  struct speed
8820  {
8821  int m_speedX100;
8822  QString m_suffix;
8823  QString m_trans;
8824  };
8825 
8826  static const std::array<const speed,9> s_speeds {{
8827  { 0, "", tr("Adjust")},
8828  { 50, "0.5", tr("0.5x")},
8829  { 90, "0.9", tr("0.9x")},
8830  {100, "1.0", tr("1.0x")},
8831  {110, "1.1", tr("1.1x")},
8832  {120, "1.2", tr("1.2x")},
8833  {130, "1.3", tr("1.3x")},
8834  {140, "1.4", tr("1.4x")},
8835  {150, "1.5", tr("1.5x")},
8836  }};
8837 
8838  for (const auto & speed : s_speeds)
8839  {
8840  QString action = prefix + speed.m_suffix;
8841  active = (m_tvmSpeedX100 == speed.m_speedX100);
8842  BUTTON(action, speed.m_trans);
8843  }
8844  }
8845  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLESLEEP", category, prefix))
8846  {
8847  active = false;
8848  if (m_sleepTimerId)
8849  BUTTON(ACTION_TOGGLESLEEP + "ON", tr("Sleep Off"));
8850  BUTTON(ACTION_TOGGLESLEEP + "30", tr("%n minute(s)", "", 30));
8851  BUTTON(ACTION_TOGGLESLEEP + "60", tr("%n minute(s)", "", 60));
8852  BUTTON(ACTION_TOGGLESLEEP + "90", tr("%n minute(s)", "", 90));
8853  BUTTON(ACTION_TOGGLESLEEP + "120", tr("%n minute(s)", "", 120));
8854  }
8855  else if (MythTVMenu::MatchesGroup(actionName, "CHANGROUP_", category, prefix))
8856  {
8858  {
8859  active = false;
8860  BUTTON("CHANGROUP_ALL_CHANNELS", tr("All Channels"));
8861  ChannelGroupList::const_iterator it;
8862  for (it = m_dbChannelGroups.begin();
8863  it != m_dbChannelGroups.end(); ++it)
8864  {
8865  QString action = prefix + QString::number(it->m_grpId);
8866  active = (static_cast<int>(it->m_grpId) == m_channelGroupId);
8867  BUTTON(action, it->m_name);
8868  }
8869  }
8870  }
8871  else if (MythTVMenu::MatchesGroup(actionName, "TOGGLECOMMSKIP", category, prefix))
8872  {
8874  {
8875  static constexpr std::array<const uint,3> kCasOrd { 0, 2, 1 };
8876  for (uint csm : kCasOrd)
8877  {
8878  const auto mode = static_cast<CommSkipMode>(csm);
8879  QString action = prefix + QString::number(csm);
8880  active = (mode == m_tvmCurSkip);
8881  BUTTON(action, toString(static_cast<CommSkipMode>(csm)));
8882  }
8883  }
8884  }
8885  else if (MythTVMenu::MatchesGroup(actionName, "JUMPTOCHAPTER", category, prefix))
8886  {
8887  if (m_tvmNumChapters &&
8889  {
8890  int size = QString::number(m_tvmNumChapters).size();
8891  for (int i = 0; i < m_tvmNumChapters; i++)
8892  {
8893  QString chapter1 = QString("%1").arg(i+1, size, 10, QChar(48));
8894  QString chapter2 = QString("%1").arg(i+1, 3 , 10, QChar(48));
8895  QString timestr = MythDate::formatTime(m_tvmChapterTimes[i], "HH:mm:ss");
8896  QString desc = chapter1 + QString(" (%1)").arg(timestr);
8897  QString action = prefix + chapter2;
8898  active = (m_tvmCurrentChapter == (i + 1));
8899  BUTTON(action, desc);
8900  }
8901  }
8902  }
8903  else if (MythTVMenu::MatchesGroup(actionName, "SWITCHTOANGLE", category, prefix))
8904  {
8905  if (m_tvmNumAngles > 1)
8906  {
8907  for (int i = 1; i <= m_tvmNumAngles; i++)
8908  {
8909  QString angleIdx = QString("%1").arg(i, 3, 10, QChar(48));
8910  QString desc = GetAngleName(i);
8911  QString action = prefix + angleIdx;
8912  active = (m_tvmCurrentAngle == i);
8913  BUTTON(action, desc);
8914  }
8915  }
8916  }
8917  else if (MythTVMenu::MatchesGroup(actionName, "JUMPTOTITLE", category, prefix))
8918  {
8919  for (int i = 0; i < m_tvmNumTitles; i++)
8920  {
8921  if (GetTitleDuration(i) < 2min) // Ignore < 2 minutes long
8922  continue;
8923 
8924  QString titleIdx = QString("%1").arg(i, 3, 10, QChar(48));
8925  QString desc = GetTitleName(i);
8926  QString action = prefix + titleIdx;
8927  active = (m_tvmCurrentTitle == i);
8928  BUTTON(action, desc);
8929  }
8930  }
8931  else if (MythTVMenu::MatchesGroup(actionName, "SWITCHTOINPUT_", category, prefix))
8932  {
8934  {
8935  uint inputid = m_playerContext.GetCardID();
8936  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(inputid);
8937  QVector <QString> addednames;
8938  addednames += CardUtil::GetDisplayName(inputid);
8939  for (auto & input : inputs)
8940  {
8941  if (input.m_inputId == inputid ||
8942  addednames.contains(input.m_displayName))
8943  continue;
8944  active = false;
8945  addednames += input.m_displayName;
8946  QString action = QString("SWITCHTOINPUT_") +
8947  QString::number(input.m_inputId);
8948  BUTTON(action, input.m_displayName);
8949  }
8950  }
8951  }
8952  else if (MythTVMenu::MatchesGroup(actionName, "SWITCHTOSOURCE_", category, prefix))
8953  {
8955  {
8956  uint inputid = m_playerContext.GetCardID();
8957  InfoMap info;
8959  uint sourceid = info["sourceid"].toUInt();
8960  QMap<uint, bool> sourceids;
8961  std::vector<InputInfo> inputs = RemoteRequestFreeInputInfo(inputid);
8962  for (auto & input : inputs)
8963  {
8964  if (input.m_sourceId == sourceid ||
8965  sourceids[input.m_sourceId])
8966  continue;
8967  active = false;
8968  sourceids[input.m_sourceId] = true;
8969  QString action = QString("SWITCHTOINPUT_") +
8970  QString::number(input.m_inputId);
8971  BUTTON(action, SourceUtil::GetSourceName(input.m_sourceId));
8972  }
8973  }
8974  }
8975  else if (category == kMenuCategoryItem)
8976  {
8977  if (actionName == "TOGGLEAUDIOSYNC")
8978  {
8979  BUTTON(actionName, tr("Adjust Audio Sync"));
8980  }
8981  else if (m_visualiserState.m_canVisualise && (actionName == "DISABLEVISUALISATION"))
8982  {
8983  BUTTON(actionName, tr("None"));
8984  }
8985  else if (actionName == "DISABLEUPMIX")
8986  {
8988  {
8989  active = !m_audioState.m_isUpmixing;
8990  BUTTON(actionName, tr("Disable Audio Upmixer"));
8991  }
8992  }
8993  else if (actionName == "ENABLEUPMIX")
8994  {
8996  {
8997  active = m_audioState.m_isUpmixing;
8998  BUTTON(actionName, tr("Auto Detect"));
8999  }
9000  }
9001  else if (actionName == "AUTODETECT_FILL")
9002  {
9003  if (m_tvmFillAutoDetect)
9004  {
9005  active =
9008  BUTTON(actionName, tr("Auto Detect"));
9009  }
9010  }
9011  else if (actionName == "TOGGLEMANUALZOOM")
9012  {
9013  BUTTON(actionName, tr("Manual Zoom Mode"));
9014  }
9015  else if (actionName == "DISABLESUBS")
9016  {
9018  if (m_tvmSubsHaveSubs)
9019  BUTTON(actionName, tr("Disable Subtitles"));
9020  }
9021  else if (actionName == "ENABLESUBS")
9022  {
9024  if (m_tvmSubsHaveSubs)
9025  BUTTON(actionName, tr("Enable Subtitles"));
9026  }
9027  else if (actionName == "DISABLEFORCEDSUBS")
9028  {
9029  active = !m_tvmSubsForcedOn;
9030  if (!m_tvmTracks[kTrackTypeSubtitle].empty() ||
9031  !m_tvmTracks[kTrackTypeRawText].empty())
9032  {
9033  BUTTON(actionName, tr("Disable Forced Subtitles"));
9034  }
9035  }
9036  else if (actionName == "ENABLEFORCEDSUBS")
9037  {
9038  active = m_tvmSubsForcedOn;
9039  if (!m_tvmTracks[kTrackTypeSubtitle].empty() ||
9040  !m_tvmTracks[kTrackTypeRawText].empty())
9041  {
9042  BUTTON(actionName, tr("Enable Forced Subtitles"));
9043  }
9044  }
9045  else if (actionName == "DISABLEEXTTEXT")
9046  {
9049  BUTTON(actionName, tr("Disable External Subtitles"));
9050  }
9051  else if (actionName == "ENABLEEXTTEXT")
9052  {
9055  BUTTON(actionName, tr("Enable External Subtitles"));
9056  }
9057  else if (actionName == "TOGGLETTM")
9058  {
9059  if (!m_tvmTracks[kTrackTypeTeletextMenu].empty())
9060  BUTTON(actionName, tr("Toggle Teletext Menu"));
9061  }
9062  else if (actionName == "TOGGLESUBZOOM")
9063  {
9065  BUTTON(actionName, tr("Adjust Subtitle Zoom"));
9066  }
9067  else if (actionName == "TOGGLESUBDELAY")
9068  {
9072  {
9073  BUTTON(actionName, tr("Adjust Subtitle Delay"));
9074  }
9075  }
9076  else if (actionName == "PAUSE")
9077  {
9078  active = m_tvmIsPaused;
9079  BUTTON2(actionName, tr("Play"), tr("Pause"));
9080  }
9081  else if (actionName == "TOGGLESTRETCH")
9082  {
9083  BUTTON(actionName, tr("Toggle"));
9084  }
9085  else if (actionName == "TOGGLEBROWSE")
9086  {
9088  BUTTON(actionName, tr("Toggle Browse Mode"));
9089  }
9090  else if (actionName == "CANCELPLAYLIST")
9091  {
9092  if (m_inPlaylist)
9093  BUTTON(actionName, tr("Cancel Playlist"));
9094  }
9095  else if (actionName == "DEBUGOSD")
9096  {
9097  BUTTON(actionName, tr("Playback Data"));
9098  }
9099  else if (actionName == "JUMPFFWD")
9100  {
9101  if (m_tvmJump)
9102  BUTTON(actionName, tr("Jump Ahead"));
9103  }
9104  else if (actionName == "JUMPRWND")
9105  {
9106  if (m_tvmJump)
9107  BUTTON(actionName, tr("Jump Back"));
9108  }
9109  else if (actionName == "JUMPTODVDROOTMENU")
9110  {
9111  if (m_tvmIsBd || m_tvmIsDvd)
9112  {
9113  active = m_tvmIsDvd;
9114  BUTTON2(actionName, tr("DVD Root Menu"), tr("Top menu"));
9115  }
9116  }
9117  else if (actionName == "JUMPTOPOPUPMENU")
9118  {
9119  if (m_tvmIsBd)
9120  BUTTON(actionName, tr("Popup menu"));
9121  }
9122  else if (actionName == "JUMPTODVDTITLEMENU")
9123  {
9124  if (m_tvmIsDvd)
9125  BUTTON(actionName, tr("DVD Title Menu"));
9126  }
9127  else if (actionName == "JUMPTODVDCHAPTERMENU")
9128  {
9129  if (m_tvmIsDvd)
9130  BUTTON(actionName, tr("DVD Chapter Menu"));
9131  }
9132  else if (actionName == "PREVCHAN")
9133  {
9134  if (m_tvmPreviousChan)
9135  BUTTON(actionName, tr("Previous Channel"));
9136  }
9137  else if (actionName == "GUIDE")
9138  {
9139  BUTTON(actionName, tr("Program Guide"));
9140  }
9141  else if (actionName == "FINDER")
9142  {
9143  BUTTON(actionName, tr("Program Finder"));
9144  }
9145  else if (actionName == "VIEWSCHEDULED")
9146  {
9147  BUTTON(actionName, tr("Upcoming Recordings"));
9148  }
9149  else if (actionName == "SCHEDULE")
9150  {
9151  BUTTON(actionName, tr("Edit Recording Schedule"));
9152  }
9153  else if (actionName == "DIALOG_JUMPREC_X_0")
9154  {
9155  BUTTON3(actionName, tr("Recorded Program"), "", true);
9156  QVariant v;
9157  v.setValue(MythTVMenuNodeTuple(Context.m_menu.m_id,
9160  }
9161  else if (actionName == "JUMPPREV")
9162  {
9163  if (m_lastProgram != nullptr)
9164  {
9165  if (m_lastProgram->GetSubtitle().isEmpty())
9166  BUTTON(actionName, m_lastProgram->GetTitle());
9167  else
9168  {
9169  BUTTON(actionName,
9170  QString("%1: %2")
9171  .arg(m_lastProgram->GetTitle(),
9173  }
9174  }
9175  }
9176  else if (actionName == "EDIT")
9177  {
9178  if (m_tvmIsLiveTv || m_tvmIsRecorded ||
9180  {
9181  active = m_tvmIsLiveTv;
9182  BUTTON2(actionName, tr("Edit Channel"), tr("Edit Recording"));
9183  }
9184  }
9185  else if (actionName == "TOGGLEAUTOEXPIRE")
9186  {
9188  {
9189  active = m_tvmIsOn;
9190  BUTTON2(actionName,
9191  tr("Turn Auto-Expire OFF"), tr("Turn Auto-Expire ON"));
9192  }
9193  }
9194  else if (actionName == "QUEUETRANSCODE")
9195  {
9196  if (m_tvmIsRecorded)
9197  {
9198  active = m_tvmTranscoding;
9199  BUTTON2(actionName, tr("Stop Transcoding"), tr("Default"));
9200  }
9201  }
9202  else if (actionName == "QUEUETRANSCODE_AUTO")
9203  {
9204  if (m_tvmIsRecorded)
9205  {
9206  active = m_tvmTranscoding;
9207  BUTTON(actionName, tr("Autodetect"));
9208  }
9209  }
9210  else if (actionName == "QUEUETRANSCODE_HIGH")
9211  {
9212  if (m_tvmIsRecorded)
9213  {
9214  active = m_tvmTranscoding;
9215  BUTTON(actionName, tr("High Quality"));
9216  }
9217  }
9218  else if (actionName == "QUEUETRANSCODE_MEDIUM")
9219  {
9220  if (m_tvmIsRecorded)
9221  {
9222  active = m_tvmTranscoding;
9223  BUTTON(actionName, tr("Medium Quality"));
9224  }
9225  }
9226  else if (actionName == "QUEUETRANSCODE_LOW")
9227  {
9228  if (m_tvmIsRecorded)
9229  {
9230  active = m_tvmTranscoding;
9231  BUTTON(actionName, tr("Low Quality"));
9232  }
9233  }
9234  else if (actionName == ACTION_CAST)
9235  {
9236  if (!m_actors.isEmpty() || !m_guest_stars.isEmpty() ||
9237  !m_guests.isEmpty())
9238  BUTTON(actionName, tr("Cast"));
9239  }
9240  else
9241  {
9242  // Allow an arbitrary action if it has a translated
9243  // description available to be used as the button text.
9244  // Look in the specified keybinding context as well as the
9245  // Global context.
9246  QString text = m_mainWindow->GetActionText(Context.m_menu.GetKeyBindingContext(), actionName);
9247  if (text.isEmpty())
9248  text = m_mainWindow->GetActionText("Global", actionName);
9249  if (!text.isEmpty())
9250  BUTTON(actionName, text);
9251  }
9252  }
9253 
9254  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9255  return result;
9256 }
9257 
9258 void TV::MenuLazyInit(void *Field)
9259 {
9260  if (Field == &m_tvmFreeRecorderCount)
9261  if (m_tvmFreeRecorderCount < 0)
9263 }
9264 
9266 {
9268  if (&Menu != &m_playbackMenu && &Menu != &m_playbackCompactMenu)
9269  return;
9270 
9271  m_tvmAvsync = true;
9272 
9273  m_tvmFillAutoDetect = false;
9274 
9275  m_tvmSpeedX100 = std::lroundf(m_playerContext.m_tsNormal * 100);
9281  m_tvmIsPaused = false;
9286  m_tvmJump = ((m_tvmNumChapters == 0) && !m_tvmIsDvd &&
9290  m_tvmPreviousChan = false;
9291 
9298  m_tvmChapterTimes.clear();
9300 
9301  m_tvmSubsForcedOn = true;
9302  m_tvmSubsHaveSubs = false;
9303 
9304  for (int i = kTrackTypeUnknown ; i < kTrackTypeCount ; ++i)
9305  m_tvmCurtrack[i] = -1;
9306 
9307  if (m_tvmIsLiveTv)
9308  {
9309  QString prev_channum = m_playerContext.GetPreviousChannel();
9310  QString cur_channum = QString();
9312  cur_channum = m_playerContext.m_tvchain->GetChannelName(-1);
9313  if (!prev_channum.isEmpty() && prev_channum != cur_channum)
9314  m_tvmPreviousChan = true;
9315  }
9316 
9317  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9318 
9319  if (m_player && m_player->GetVideoOutput())
9320  {
9321  for (uint i = kTrackTypeUnknown ; i < kTrackTypeCount ; ++i)
9322  {
9323  m_tvmTracks[i] = m_player->GetTracks(i);
9324  if (!m_tvmTracks[i].empty())
9325  m_tvmCurtrack[i] = m_player->GetTrack(i);
9326  }
9328  !m_tvmTracks[kTrackTypeSubtitle].empty() ||
9330  !m_tvmTracks[kTrackTypeCC708].empty() ||
9331  !m_tvmTracks[kTrackTypeCC608].empty() ||
9333  !m_tvmTracks[kTrackTypeRawText].empty();
9335  !m_tvmTracks[kTrackTypeAudio].empty();
9340  if (vo)
9341  {
9343  }
9344  }
9345  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
9350  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
9351 
9352  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9353 }
9354 
9355 void TV::PlaybackMenuDeinit(const MythTVMenu& /*Menu*/)
9356 {
9357  ReturnPlayerLock();
9358 }
9359 
9360 void TV::PlaybackMenuShow(const MythTVMenu &Menu, const QDomNode &Node, const QDomNode &Selected)
9361 {
9362  PlaybackMenuInit(Menu);
9363  bool isPlayback = (&Menu == &m_playbackMenu || &Menu == &m_playbackCompactMenu);
9364  bool isCutlist = (&Menu == &m_cutlistMenu || &Menu == &m_cutlistCompactMenu);
9365  QString text = Menu.Translate(Node.toElement().attribute("text", Menu.GetName()));
9366  const char* windowtitle { "???" };
9367  if (isPlayback)
9368  windowtitle = OSD_DLG_MENU;
9369  else if (isCutlist)
9370  windowtitle = OSD_DLG_CUTPOINT;
9371  MythOSDDialogData menu {windowtitle, text };
9372  Menu.Show(Node, Selected, *this, &menu);
9373  QDomNode parent = Node.parentNode();
9374  if (!parent.parentNode().isNull())
9375  {
9376  QVariant v;
9377  v.setValue(MythTVMenuNodeTuple(Menu.m_id, MythTVMenu::GetPathFromNode(Node)));
9378  menu.m_back = { "", v };
9379  }
9380 
9381  emit ChangeOSDDialog(menu);
9382 
9383  if (isCutlist)
9384  {
9385  // hack to unhide the editbar
9386  InfoMap map;
9387  map.insert("title", tr("Edit"));
9389  }
9390  PlaybackMenuDeinit(Menu);
9391 }
9392 
9394 {
9395  // Playback menu
9396  (void)tr("Playback Menu");
9397  (void)tr("Playback Compact Menu");
9398  (void)tr("Audio");
9399  (void)tr("Select Audio Track");
9400  (void)tr("Visualisation");
9401  (void)tr("Video");
9402  (void)tr("Change Aspect Ratio");
9403  (void)tr("Adjust Fill");
9404  (void)tr("Adjust Picture");
9405  (void)tr("3D");
9406  (void)tr("Advanced");
9407  (void)tr("Video Scan");
9408  (void)tr("Deinterlacer");
9409  (void)tr("Subtitles");
9410  (void)tr("Select Subtitle");
9411  (void)tr("Text Subtitles");
9412  (void)tr("Select ATSC CC");
9413  (void)tr("Select VBI CC");
9414  (void)tr("Select Teletext CC");
9415  (void)tr("Playback");
9416  (void)tr("Adjust Time Stretch");
9417  (void)tr("Picture-in-Picture");
9418  (void)tr("Sleep");
9419  (void)tr("Channel Groups");
9420  (void)tr("Navigate");
9421  (void)tr("Commercial Auto-Skip");
9422  (void)tr("Chapter");
9423  (void)tr("Angle");
9424  (void)tr("Title");
9425  (void)tr("Schedule");
9426  (void)tr("Source");
9427  (void)tr("Jump to Program");
9428  (void)tr("Switch Input");
9429  (void)tr("Switch Source");
9430  (void)tr("Jobs");
9431  (void)tr("Begin Transcoding");
9432  (void)tr("Cast");
9433  (void)tr("Recorded");
9434  (void)tr("Upcoming");
9435 
9436  // Cutlist editor menu
9437  (void)tr("Edit Cut Points");
9438  (void)tr("Edit Cut Points (Compact)");
9439  (void)tr("Cut List Options");
9440 }
9441 
9442 void TV::ShowOSDMenu(bool isCompact)
9443 {
9444  if (!m_playbackMenu.IsLoaded())
9445  {
9447  "menu_playback.xml", tr("Playback Menu"),
9448  metaObject()->className(), "TV Playback");
9450  "menu_playback_compact.xml", tr("Playback Compact Menu"),
9451  metaObject()->className(), "TV Playback");
9452  }
9453 
9454  if (isCompact && m_playbackCompactMenu.IsLoaded())
9456  else if (m_playbackMenu.IsLoaded())
9458 }
9459 
9460 void TV::FillOSDMenuJumpRec(const QString &Category, int Level, const QString &Selected)
9461 {
9462  // bool in_recgroup = !category.isEmpty() && level > 0;
9463  if (Level < 0 || Level > 1)
9464  {
9465  Level = 0;
9466  // in_recgroup = false;
9467  }
9468 
9469  MythOSDDialogData dialog { "osd_jumprec", tr("Recorded Program") };
9470 
9471  QMutexLocker locker(&m_progListsLock);
9472  m_progLists.clear();
9473  std::vector<ProgramInfo*> *infoList = RemoteGetRecordedList(0);
9474  bool LiveTVInAllPrograms = gCoreContext->GetBoolSetting("LiveTVInAllPrograms",false);
9475  if (infoList)
9476  {
9477  QList<QString> titles_seen;
9478 
9479  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
9480  QString currecgroup = m_playerContext.m_playingInfo->GetRecordingGroup();
9481  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
9482 
9483  for (auto *pi : *infoList)
9484  {
9485  if (pi->GetRecordingGroup() != "LiveTV" || LiveTVInAllPrograms ||
9486  pi->GetRecordingGroup() == currecgroup)
9487  {
9488  m_progLists[pi->GetRecordingGroup()].push_front(
9489  new ProgramInfo(*pi));
9490  }
9491  }
9492 
9493  ProgramInfo *lastprog = GetLastProgram();
9494  QMap<QString,ProgramList>::const_iterator Iprog;
9495  for (Iprog = m_progLists.cbegin(); Iprog != m_progLists.cend(); ++Iprog)
9496  {
9497  const ProgramList &plist = *Iprog;
9498  auto progIndex = static_cast<uint>(plist.size());
9499  const QString& group = Iprog.key();
9500 
9501  if (plist[0] && (plist[0]->GetRecordingGroup() != currecgroup))
9502  SetLastProgram(plist[0]);
9503 
9504  if (progIndex == 1 && Level == 0)
9505  {
9506  dialog.m_buttons.push_back( {Iprog.key(), QString("JUMPPROG %1 0").arg(group) });
9507  }
9508  else if (progIndex > 1 && Level == 0)
9509  {
9510  QString act = QString("DIALOG_%1_%2_1")
9511  .arg(ACTION_JUMPREC, group);
9512  dialog.m_buttons.push_back( {group, act, true, Selected == group });
9513  }
9514  else if (Level == 1 && Iprog.key() == Category)
9515  {
9516  for (auto pit = plist.begin(); pit != plist.end(); ++pit)
9517  {
9518  const ProgramInfo *p = *pit;
9519 
9520  if (titles_seen.contains(p->GetTitle()))
9521  continue;
9522 
9523  titles_seen.push_back(p->GetTitle());
9524 
9525  int j = -1;
9526  for (auto *q : plist)
9527  {
9528  j++;
9529 
9530  if (q->GetTitle() != p->GetTitle())
9531  continue;
9532 
9533  dialog.m_buttons.push_back( { q->GetSubtitle().isEmpty() ?
9534  q->GetTitle() : q->GetSubtitle(),
9535  QString("JUMPPROG %1 %2").arg(Iprog.key()).arg(j) });
9536  }
9537  }
9538  }
9539  }
9540  SetLastProgram(lastprog);
9541  delete lastprog;
9542 
9543  while (!infoList->empty())
9544  {
9545  delete infoList->back();
9546  infoList->pop_back();
9547  }
9548  delete infoList;
9549  }
9550 
9551  if (!Category.isEmpty())
9552  {
9553  if (Level == 1)
9554  dialog.m_back = { Category, "DIALOG_" + ACTION_JUMPREC + "_X_0" };
9555  else if (Level == 0)
9556  {
9557  if (m_tvmJumprecBackHack.isValid())
9558  dialog.m_back = { "", m_tvmJumprecBackHack };
9559  else
9560  dialog.m_back = { ACTION_JUMPREC, "DIALOG_MENU_" + ACTION_JUMPREC +"_0" };
9561  }
9562  }
9563 
9564  emit ChangeOSDDialog(dialog);
9565 }
9566 
9568 {
9569  bool recorded = (ProgInfo.GetFilesize() > 0);
9570  QString table = recorded ? "recordedcredits" : "credits";
9571 
9572  m_actors.clear();
9573  m_guest_stars.clear();
9574  m_guests.clear();
9575 
9576  MSqlQuery query(MSqlQuery::InitCon());
9577  query.prepare(QString("SELECT role, people.name,"
9578  " roles.name, people.person FROM %1"
9579  " AS credits"
9580  " LEFT JOIN people ON"
9581  " credits.person = people.person"
9582  " LEFT JOIN roles ON"
9583  " credits.roleid = roles.roleid"
9584  " WHERE credits.chanid = :CHANID"
9585  " AND credits.starttime = :STARTTIME"
9586  " AND role IN ('guest','actor','guest_star')"
9587  " ORDER BY role, priority;").arg(table));
9588 
9589  query.bindValue(":CHANID", ProgInfo.GetChanID());
9590  query.bindValue(":STARTTIME", ProgInfo.GetScheduledStartTime());
9591 
9592  if (query.exec() && query.size() > 0)
9593  {
9594  QStringList plist;
9595  QString role;
9596  QString pname;
9597  QString character;
9598 
9599  while(query.next())
9600  {
9601  role = query.value(0).toString();
9602  /* The people.name, roles.name columns uses utf8_bin collation.
9603  * Qt-MySQL drivers use QVariant::ByteArray for string-type
9604  * MySQL fields marked with the BINARY attribute (those using a
9605  * *_bin collation) and QVariant::String for all others.
9606  * Since QVariant::toString() uses QString::fromAscii()
9607  * (through QVariant::convert()) when the QVariant's type is
9608  * QVariant::ByteArray, we have to use QString::fromUtf8()
9609  * explicitly to prevent corrupting characters.
9610  * The following code should be changed to use the simpler
9611  * toString() approach, as above, if we do a DB update to
9612  * coalesce the people.name values that differ only in case and
9613  * change the collation to utf8_general_ci, to match the
9614  * majority of other columns, or we'll have the same problem in
9615  * reverse.
9616  */
9617  int pid = query.value(3).toInt();
9618  pname = QString::fromUtf8(query.value(1)
9619  .toByteArray().constData()) +
9620  "|" + QString::number(pid);
9621  character = QString::fromUtf8(query.value(2)
9622  .toByteArray().constData());
9623 
9624  if (role == "actor")
9625  m_actors.append(qMakePair(pname, character));
9626  else if (role == "guest_star")
9627  m_guest_stars.append(qMakePair(pname, character));
9628  else if (role == "guest")
9629  m_guests.append(qMakePair(pname, character));
9630  }
9631  }
9632 
9633 }
9634 
9636  const QVector<string_pair> & people)
9637 {
9638  for (const auto & [actor, role] : std::as_const(people))
9639  {
9640  if (role.isEmpty())
9641  {
9642  dialog.m_buttons.push_back( {actor.split('|')[0],
9643  QString("JUMPCAST|%1").arg(actor), true} );
9644  }
9645  else
9646  {
9647  dialog.m_buttons.push_back( {QString("%1 as %2")
9648  .arg(actor.split('|')[0], role),
9649  QString("JUMPCAST|%1").arg(actor), true} );
9650  }
9651  }
9652 }
9653 
9655 {
9656  MythOSDDialogData dialog { "osd_cast", tr("Cast") };
9657  const ProgramInfo pginfo(*m_playerContext.m_playingInfo);
9658 
9662 
9663  emit ChangeOSDDialog(dialog);
9664 }
9665 
9666 void TV::FillOSDMenuActorShows(const QString & actor, int person_id,
9667  const QString & category)
9668 {
9669  MythOSDDialogData dialog { actor, actor };
9670 
9671  if (category.isEmpty())
9672  {
9673  dialog.m_buttons.push_back( {"Recorded",
9674  QString("JUMPCAST|%1|%2|Recorded").arg(actor).arg(person_id) } );
9675  dialog.m_buttons.push_back( {"Upcoming",
9676  QString("JUMPCAST|%1|%2|Upcoming").arg(actor).arg(person_id) } );
9677  emit ChangeOSDDialog(dialog);
9678  return;
9679  }
9680 
9681  if (category == "Upcoming")
9682  {
9684  return;
9685  }
9686 
9687  /*
9688  JUMPCAST|Amanda Burton|133897|Recorded
9689  JUMPCAST|Amanda Burton|133897|Upcoming
9690  */
9691  if (m_progLists.find(actor) == m_progLists.end())
9692  {
9693  QString table = "recordedcredits";
9694  MSqlQuery query(MSqlQuery::InitCon());
9695  query.prepare(QString("SELECT chanid, starttime from %1"
9696  " where person = :PERSON"
9697  " ORDER BY starttime;").arg(table));
9698  query.bindValue(":PERSON", person_id);
9699 
9700  QDateTime starttime;
9701  if (query.exec() && query.size() > 0)
9702  {
9703  while(query.next())
9704  {
9705  int chanid = query.value(0).toInt();
9706  starttime = MythDate::fromString(query.value(1).toString());
9707  auto *pi = new ProgramInfo(chanid, starttime.toUTC());
9708  if (!pi->GetTitle().isEmpty() &&
9709  pi->GetRecordingGroup() != "LiveTV" &&
9710  pi->GetRecordingGroup() != "Deleted")
9711  m_progLists[actor].push_back(pi);
9712  }
9713 
9714  std::stable_sort(m_progLists[actor].begin(),
9715  m_progLists[actor].end(), comp_title);
9716  }
9717  }
9718 
9719  QString show;
9720  int idx = -1;
9721  for (auto & pi : m_progLists[actor])
9722  {
9723  show = pi->GetTitle();
9724  if (show.isEmpty())
9725  continue;
9726  if (!pi->GetSubtitle().isEmpty())
9727  {
9728  show += QString(" %1x%2 %3").arg(pi->GetSeason())
9729  .arg(pi->GetEpisode())
9730  .arg(pi->GetSubtitle());
9731  }
9732 
9733  dialog.m_buttons.push_back( {show,
9734  QString("JUMPPROG %1 %2").arg(actor).arg(++idx) });
9735  }
9736  emit ChangeOSDDialog(dialog);
9737 }
9738 
9740 {
9741  QString message;
9742  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9743  if (m_player)
9744  {
9745  m_player->SetScanOverride(Scan);
9746  message = ScanTypeToUserString(Scan == kScan_Detect ? kScan_Detect :
9748  }
9749  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9750 
9751  if (!message.isEmpty())
9752  emit ChangeOSDMessage(message);
9753 }
9754 
9756 {
9757  QString desc;
9758 
9759  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
9760 
9762  {
9764  desc = tr("Auto-Expire OFF");
9765  }
9766  else
9767  {
9769  desc = tr("Auto-Expire ON");
9770  }
9771 
9772  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
9773 
9774  if (!desc.isEmpty())
9776 }
9777 
9779 {
9780  QString desc;
9781 
9782  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9783  if (m_player)
9784  {
9785  m_player->SetAutoCommercialSkip(SkipMode);
9787  }
9788  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9789 
9790  if (!desc.isEmpty())
9792 }
9793 
9794 void TV::SetManualZoom(bool ZoomON, const QString& Desc)
9795 {
9796  m_zoomMode = ZoomON;
9797  if (ZoomON)
9798  ClearOSD();
9799  if (!Desc.isEmpty())
9801 }
9802 
9803 bool TV::HandleJumpToProgramAction(const QStringList &Actions)
9804 {
9805  TVState state = GetState();
9806  if (IsActionable({ ACTION_JUMPPREV, "PREVCHAN" }, Actions) &&
9807  !StateIsLiveTV(state))
9808  {
9809  PrepareToExitPlayer(__LINE__);
9810  m_jumpToProgram = true;
9811  SetExitPlayer(true, true);
9812  return true;
9813  }
9814 
9815  for (const auto& action : std::as_const(Actions))
9816  {
9817  if (!action.startsWith("JUMPPROG"))
9818  continue;
9819 
9820  bool ok = false;
9821  QString key = action.section(" ",1,-2);
9822  uint index = action.section(" ",-1,-1).toUInt(&ok);
9823  ProgramInfo* proginfo = nullptr;
9824 
9825  if (ok)
9826  {
9827  QMutexLocker locker(&m_progListsLock);
9828  auto pit = m_progLists.find(key);
9829  if (pit != m_progLists.end())
9830  {
9831  const ProgramInfo* tmp = (*pit)[index];
9832  if (tmp)
9833  proginfo = new ProgramInfo(*tmp);
9834  }
9835  }
9836 
9837  if (!proginfo)
9838  {
9839  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Failed to locate jump to program '%1' @ %2")
9840  .arg(key, action.section(" ",-1,-1)));
9841  return true;
9842  }
9843 
9844  PrepToSwitchToRecordedProgram(*proginfo);
9845 
9846  delete proginfo;
9847  return true;
9848  }
9849 
9850  if (!IsActionable(ACTION_JUMPREC, Actions))
9851  return false;
9852 
9853  if (m_dbJumpPreferOsd && (StateIsPlaying(state) || StateIsLiveTV(state)))
9854  {
9855  // TODO I'm not sure this really needs to be asyncronous
9856  auto Jump = [&]()
9857  {
9860  ReturnPlayerLock();
9861  };
9862  QTimer::singleShot(0, this, Jump);
9863  }
9864  else if (RunPlaybackBoxPtr)
9865  {
9867  }
9868  else
9869  {
9870  LOG(VB_GENERAL, LOG_ERR, "Failed to open jump to program GUI");
9871  }
9872 
9873  return true;
9874 }
9875 
9876 void TV::ToggleSleepTimer(const QString& Time)
9877 {
9878  std::chrono::minutes mins { 0min };
9879 
9880  if (Time == ACTION_TOGGLESLEEP + "ON")
9881  {
9882  if (m_sleepTimerId)
9883  {
9885  m_sleepTimerId = 0;
9886  }
9887  else
9888  {
9889  m_sleepTimerTimeout = mins = 60min;
9891  }
9892  }
9893  else
9894  {
9895  if (m_sleepTimerId)
9896  {
9898  m_sleepTimerId = 0;
9899  }
9900 
9901  if (Time.length() > 11)
9902  {
9903  bool intRead = false;
9904  mins = std::chrono::minutes(Time.right(Time.length() - 11).toUInt(&intRead));
9905 
9906  if (intRead)
9907  {
9908  // catch 120 -> 240 mins
9909  if (mins < 30min)
9910  {
9911  mins *= 10;
9912  }
9913  }
9914  else
9915  {
9916  mins = 0min;
9917  LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid time " + Time);
9918  }
9919  }
9920  else
9921  {
9922  LOG(VB_GENERAL, LOG_ERR, LOC + "Invalid time string " + Time);
9923  }
9924 
9925  if (mins > 0min)
9926  {
9927  m_sleepTimerTimeout = mins;
9929  }
9930  }
9931 
9932  QString out;
9933  if (mins != 0min)
9934  out = tr("Sleep") + " " + QString::number(mins.count());
9935  else
9936  out = tr("Sleep") + " " + s_sleepTimes[0].dispString;
9937  emit ChangeOSDMessage(out);
9938 }
9939 
9941 {
9942  QString errorText;
9943 
9944  switch (MsgType)
9945  {
9946  case kNoRecorders:
9947  errorText = tr("MythTV is already using all available "
9948  "inputs for the channel you selected. "
9949  "If you want to watch an in-progress recording, "
9950  "select one from the playback menu. If you "
9951  "want to watch Live TV, cancel one of the "
9952  "in-progress recordings from the delete "
9953  "menu.");
9954  break;
9955  case kNoCurrRec:
9956  errorText = tr("Error: MythTV is using all inputs, "
9957  "but there are no active recordings?");
9958  break;
9959  case kNoTuners:
9960  errorText = tr("MythTV has no capture cards defined. "
9961  "Please run the mythtv-setup program.");
9962  break;
9963  }
9964 
9965  emit ChangeOSDDialog({ OSD_DLG_INFO, errorText, 0ms, {{ tr("OK"), "DIALOG_INFO_X_X" }}});
9966 }
9967 
9972 {
9973  m_lockTimerOn = false;
9974 
9975  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
9977  {
9982  }
9983  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
9984 
9985  // XXX: Get rid of this?
9987 
9990 
9991  m_lockTimerOn = false;
9992 
9993  QString input = m_playerContext.m_recorder->GetInput();
9995 
9996  if (timeout < 0xffffffff)
9997  {
9998  m_lockTimer.start();
9999  m_lockTimerOn = true;
10000  }
10001 
10002  SetSpeedChangeTimer(0ms, __LINE__);
10003 }
10004 
10008 void TV::UnpauseLiveTV(bool Quietly)
10009 {
10011  {
10013  m_playerContext.m_tvchain->JumpTo(-1, 1s);
10014  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10015  if (m_player)
10016  m_player->Play(m_playerContext.m_tsNormal, true, false);
10017  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10020  SetSpeedChangeTimer(0ms, __LINE__);
10021  }
10022 
10023  ITVRestart(true);
10024 
10025  if (m_playerContext.HasPlayer() && !Quietly)
10026  {
10028  UpdateLCD();
10030  }
10031 }
10032 
10036 void TV::ITVRestart(bool IsLive)
10037 {
10038  int chanid = -1;
10039  int sourceid = -1;
10040 
10041  if (ContextIsPaused(__FILE__, __LINE__))
10042  return;
10043 
10044  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10046  {
10047  chanid = static_cast<int>(m_playerContext.m_playingInfo->GetChanID());
10048  sourceid = static_cast<int>(ChannelUtil::GetSourceIDForChannel(static_cast<uint>(chanid)));
10049  }
10050  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10051 
10052  emit RestartITV(static_cast<uint>(chanid), static_cast<uint>(sourceid), IsLive);
10053 }
10054 
10056 {
10057  if (GetState() == kState_WatchingDVD)
10058  DVDJumpForward();
10059  else if (GetNumChapters() > 0)
10060  DoJumpChapter(9999);
10061  else
10062  DoSeek(m_playerContext.m_jumptime, tr("Jump Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
10063 }
10064 
10066 {
10067  DoSeek(m_playerContext.m_fftime, tr("Skip Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
10068 }
10069 
10071 {
10072  if (GetState() == kState_WatchingDVD)
10073  DVDJumpBack();
10074  else if (GetNumChapters() > 0)
10075  DoJumpChapter(-1);
10076  else
10077  DoSeek(-m_playerContext.m_jumptime, tr("Jump Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
10078 }
10079 
10081 {
10082  DoSeek(-m_playerContext.m_rewtime, tr("Jump Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
10083 }
10084 
10085 /* \fn TV::DVDJumpBack(PlayerContext*)
10086  \brief jump to the previous dvd title or chapter
10087 */
10089 {
10090  auto *dvd = dynamic_cast<MythDVDBuffer*>(m_playerContext.m_buffer);
10091  if (!m_playerContext.HasPlayer() || !dvd)
10092  return;
10093 
10095  {
10096  UpdateOSDSeekMessage(tr("Skip Back Not Allowed"), kOSDTimeout_Med);
10097  }
10098  else if (!dvd->StartOfTitle())
10099  {
10100  DoJumpChapter(-1);
10101  }
10102  else
10103  {
10104  std::chrono::seconds titleLength = dvd->GetTotalTimeOfTitle();
10105  std::chrono::seconds chapterLength = dvd->GetChapterLength();
10106  if ((titleLength == chapterLength) && chapterLength > 5min)
10107  {
10108  DoSeek(-m_playerContext.m_jumptime, tr("Jump Back"), /*timeIsOffset*/true, /*honorCutlist*/true);
10109  }
10110  else
10111  {
10112  emit GoToDVDProgram(false);
10113  UpdateOSDSeekMessage(tr("Previous Title"), kOSDTimeout_Med);
10114  }
10115  }
10116 }
10117 
10118 /* \fn TV::DVDJumpForward(PlayerContext*)
10119  * \brief jump to the next dvd title or chapter
10120  */
10122 {
10123  auto *dvd = dynamic_cast<MythDVDBuffer*>(m_playerContext.m_buffer);
10124  if (!m_playerContext.HasPlayer() || !dvd)
10125  return;
10126 
10127  bool in_still = dvd->IsInStillFrame();
10128  bool in_menu = dvd->IsInMenu();
10129  if (in_still && !dvd->NumMenuButtons())
10130  {
10131  dvd->SkipStillFrame();
10132  UpdateOSDSeekMessage(tr("Skip Still Frame"), kOSDTimeout_Med);
10133  }
10134  else if (!dvd->EndOfTitle() && !in_still && !in_menu)
10135  {
10136  DoJumpChapter(9999);
10137  }
10138  else if (!in_still && !in_menu)
10139  {
10140  std::chrono::seconds titleLength = dvd->GetTotalTimeOfTitle();
10141  std::chrono::seconds chapterLength = dvd->GetChapterLength();
10142  std::chrono::seconds currentTime = dvd->GetCurrentTime();
10143  if ((titleLength == chapterLength) && (chapterLength > 5min) &&
10144  (currentTime < (chapterLength - (duration_cast<std::chrono::seconds>(m_playerContext.m_jumptime)))))
10145  {
10146  DoSeek(m_playerContext.m_jumptime, tr("Jump Ahead"), /*timeIsOffset*/true, /*honorCutlist*/true);
10147  }
10148  else
10149  {
10150  emit GoToDVDProgram(true);
10151  UpdateOSDSeekMessage(tr("Next Title"), kOSDTimeout_Med);
10152  }
10153  }
10154 }
10155 
10156 /* \fn TV::IsBookmarkAllowed(const PlayerContext*) const
10157  * \brief Returns true if bookmarks are allowed for the current player.
10158  */
10160 {
10161  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10162 
10163  // Allow bookmark of "Record current LiveTV program"
10166  {
10167  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10168  return false;
10169  }
10170 
10172  {
10173  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10174  return false;
10175  }
10176 
10177  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10178 
10180 }
10181 
10182 /* \fn TV::IsDeleteAllowed() const
10183  * \brief Returns true if the delete menu option should be offered.
10184  */
10186 {
10187  bool allowed = false;
10188 
10189  if (!StateIsLiveTV(GetState()))
10190  {
10191  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10193  allowed = curProgram && curProgram->QueryIsDeleteCandidate(true);
10194  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10195  }
10196 
10197  return allowed;
10198 }
10199 
10201 {
10202  ClearOSD();
10203 
10204  if (!ContextIsPaused(__FILE__, __LINE__))
10205  DoTogglePause(false);
10206 
10207  QString videotype;
10208 
10209  if (StateIsLiveTV(GetState()))
10210  videotype = tr("Live TV");
10212  videotype = tr("this DVD");
10213 
10214  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10215  if (videotype.isEmpty() && m_playerContext.m_playingInfo->IsVideo())
10216  videotype = tr("this Video");
10217  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10218 
10219  if (videotype.isEmpty())
10220  videotype = tr("this recording");
10221 
10222  MythOSDDialogData dialog { OSD_DLG_VIDEOEXIT, tr("You are exiting %1").arg(videotype) };
10223 
10224  dialog.m_buttons.push_back({tr("Exit %1").arg(videotype), ACTION_STOP});
10225 
10226  dialog.m_buttons.push_back({tr("Exit Without Saving"), "DIALOG_VIDEOEXIT_CLEARLASTPLAYEDPOSITION_0"});
10227 
10228  if (IsDeleteAllowed())
10229  dialog.m_buttons.push_back({tr("Delete this recording"), "DIALOG_VIDEOEXIT_CONFIRMDELETE_0"});
10230 
10231  dialog.m_buttons.push_back({tr("Keep watching"), "DIALOG_VIDEOEXIT_KEEPWATCHING_0"});
10232  dialog.m_back = { "", "DIALOG_VIDEOEXIT_KEEPWATCHING_0", true };
10233  emit ChangeOSDDialog(dialog);
10234 
10235  if (m_videoExitDialogTimerId)
10236  KillTimer(m_videoExitDialogTimerId);
10237  m_videoExitDialogTimerId = StartTimer(kVideoExitDialogTimeout, __LINE__);
10238 }
10239 
10240 void TV::ShowOSDPromptDeleteRecording(const QString& Title, bool Force)
10241 {
10242  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10243 
10245  {
10246  // this should only occur when the cat walks on the keyboard.
10247  LOG(VB_GENERAL, LOG_ERR, "It is unsafe to delete at the moment");
10248  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10249  return;
10250  }
10251 
10252  bool paused = ContextIsPaused(__FILE__, __LINE__);
10254  {
10255  LOG(VB_GENERAL, LOG_ERR, "This program cannot be deleted at this time.");
10257  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10258 
10259  OSD *osd = GetOSDL();
10260  if (osd && !osd->DialogVisible())
10261  {
10262  QString message = tr("Cannot delete program ") + QString("%1 ").arg(pginfo.GetTitle());
10263 
10264  if (!pginfo.GetSubtitle().isEmpty())
10265  message += QString("\"%1\" ").arg(pginfo.GetSubtitle());
10266 
10267  if (!pginfo.IsRecording())
10268  {
10269  message += tr("because it is not a recording.");
10270  }
10271  else
10272  {
10273  message += tr("because it is in use by");
10274  QStringList byWho;
10275  pginfo.QueryIsInUse(byWho);
10276  for (int i = 0; (i + 2) < byWho.size(); i += 3)
10277  {
10278  if (byWho[i + 1] == gCoreContext->GetHostName() && byWho[i].contains(kPlayerInUseID))
10279  continue;
10280  if (byWho[i].contains(kRecorderInUseID))
10281  continue;
10282  message += " " + byWho[i+2];
10283  }
10284  }
10285  emit ChangeOSDDialog({OSD_DLG_DELETE, message, 0ms,
10286  {{ tr("OK"), "DIALOG_DELETE_OK_0" }},
10287  { "", "DIALOG_DELETE_OK_0", true }});
10288  }
10289  ReturnOSDLock();
10290  // If the delete prompt is to be displayed at the end of a
10291  // recording that ends in a final cut region, it will get into
10292  // a loop of popping up the OK button while the cut region
10293  // plays. Avoid this.
10294  if (m_player->IsNearEnd() && !paused)
10295  SetExitPlayer(true, true);
10296 
10297  return;
10298  }
10299  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10300 
10301  ClearOSD();
10302 
10303  if (!paused)
10304  DoTogglePause(false);
10305 
10306  InfoMap infoMap;
10308  if (m_player)
10309  m_player->GetCodecDescription(infoMap);
10310  QString message = QString("%1\n%2\n%3")
10311  .arg(Title, infoMap["title"], infoMap["timedate"]);
10312 
10313  OSD *osd = GetOSDL();
10314  if (osd && (!osd->DialogVisible() || Force))
10315  {
10316  MythOSDDialogData dialog { OSD_DLG_VIDEOEXIT, message };
10317  if (Title == "End Of Recording")
10318  {
10319  dialog.m_buttons.push_back({tr("Delete it, but allow it to re-record"), "DIALOG_VIDEOEXIT_DELETEANDRERECORD_0"});
10320  dialog.m_buttons.push_back({tr("Delete it"), "DIALOG_VIDEOEXIT_JUSTDELETE_0"});
10321  dialog.m_buttons.push_back({tr("Save it so I can watch it again"), ACTION_STOP, false, true});
10322  }
10323  else
10324  {
10325  dialog.m_buttons.push_back({tr("Yes, and allow re-record"), "DIALOG_VIDEOEXIT_DELETEANDRERECORD_0"});
10326  dialog.m_buttons.push_back({tr("Yes, delete it"), "DIALOG_VIDEOEXIT_JUSTDELETE_0"});
10327  dialog.m_buttons.push_back({tr("No, keep it"), ACTION_STOP, false, true});
10328  if (!paused)
10329  dialog.m_back = { "", "DIALOG_PLAY_0_0", true };
10330  }
10331 
10332  emit ChangeOSDDialog(dialog);
10333 
10337  }
10338  ReturnOSDLock();
10339 }
10340 
10341 bool TV::HandleOSDVideoExit(const QString& Action)
10342 {
10344  return false;
10345 
10346  bool hide = true;
10347  bool delete_ok = IsDeleteAllowed();
10348 
10349  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10350  bool near_end = m_player && m_player->IsNearEnd();
10351  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10352 
10353  if (Action == "DELETEANDRERECORD" && delete_ok)
10354  {
10355  m_allowRerecord = true;
10356  m_requestDelete = true;
10357  PrepareToExitPlayer(__LINE__);
10358  SetExitPlayer(true, true);
10359  }
10360  else if (Action == "JUSTDELETE" && delete_ok)
10361  {
10362  m_requestDelete = true;
10363  PrepareToExitPlayer(__LINE__);
10364  SetExitPlayer(true, true);
10365  }
10366  else if (Action == "CONFIRMDELETE")
10367  {
10368  hide = false;
10369  ShowOSDPromptDeleteRecording(tr("Are you sure you want to delete:"), true);
10370  }
10371  else if (Action == "KEEPWATCHING" && !near_end)
10372  {
10373  DoTogglePause(true);
10374  }
10375  else if (Action == "CLEARLASTPLAYEDPOSITION")
10376  {
10377  m_clearPosOnExit = true;
10378  PrepareToExitPlayer(__LINE__);
10379  SetExitPlayer(true, true);
10380  }
10381 
10382  return hide;
10383 }
10384 
10386 {
10388  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10389  bool playing = m_player && !m_player->IsPaused();
10390  // Don't bother saving lastplaypos while paused
10391  if (playing)
10392  {
10393  uint64_t framesPlayed = m_player->GetFramesPlayed();
10395  &ProgramInfo::SaveLastPlayPos, framesPlayed);
10396  }
10397  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10398  ReturnPlayerLock();
10399 
10400  m_savePosOnExit = true;
10401 }
10402 
10404 {
10405  QMutexLocker locker(&m_lastProgramLock);
10406 
10407  delete m_lastProgram;
10408 
10409  if (ProgInfo)
10411  else
10412  m_lastProgram = nullptr;
10413 }
10414 
10416 {
10417  QMutexLocker locker(&m_lastProgramLock);
10418  if (m_lastProgram)
10419  return new ProgramInfo(*m_lastProgram);
10420  return nullptr;
10421 }
10422 
10423 QString TV::GetRecordingGroup() const
10424 {
10425  QString ret;
10426 
10428  if (StateIsPlaying(GetState()))
10429  {
10430  m_playerContext.LockPlayingInfo(__FILE__, __LINE__);
10433  m_playerContext.UnlockPlayingInfo(__FILE__, __LINE__);
10434  }
10435  ReturnPlayerLock();
10436  return ret;
10437 }
10438 
10440 {
10441  if (!ProgInfo)
10442  return false;
10443 
10444  bool ret = false;
10447  ReturnPlayerLock();
10448  return ret;
10449 }
10450 
10451 bool TV::ContextIsPaused(const char *File, int Location)
10452 {
10453  bool paused = false;
10454  m_playerContext.LockDeletePlayer(File, Location);
10455  if (m_player)
10456  paused = m_player->IsPaused();
10457  m_playerContext.UnlockDeletePlayer(File, Location);
10458  return paused;
10459 }
10460 
10462 {
10463  m_playerContext.LockDeletePlayer(__FILE__, __LINE__);
10464  if (m_player)
10465  {
10466  m_player->LockOSD();
10467  OSD *osd = m_player->GetOSD();
10468  if (!osd)
10469  {
10470  m_player->UnlockOSD();
10471  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10472  }
10473  return osd;
10474  }
10475  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10476  return nullptr;
10477 }
10478 
10479 void TV::ReturnOSDLock() const
10480 {
10481  if (m_player)
10482  m_player->UnlockOSD();
10483  m_playerContext.UnlockDeletePlayer(__FILE__, __LINE__);
10484 }
10485 
10487 {
10488  m_playerLock.lockForWrite();
10489 }
10490 
10492 {
10493  m_playerLock.lockForRead();
10494 }
10495 
10497 {
10498  m_playerLock.unlock();
10499 }
10500 
10501 void TV::onApplicationStateChange(Qt::ApplicationState State)
10502 {
10503  switch (State)
10504  {
10505  case Qt::ApplicationState::ApplicationSuspended:
10506  {
10507  LOG(VB_GENERAL, LOG_NOTICE, "Exiting playback on app suspecnd");
10508  StopPlayback();
10509  break;
10510  }
10511  default:
10512  break;
10513  }
10514 }
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:1975
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:10501
toCommaList
static QString toCommaList(const QVector< uint > &list)
Definition: tv_play.cpp:6778
MythPlayer::IsNearEnd
bool IsNearEnd(void)
Returns true iff near end of recording.
Definition: mythplayer.cpp:1532
kZoomAspectDown
@ kZoomAspectDown
Definition: videoouttypes.h:56
TV::kEndOfPlaybackCheckFrequency
static const std::chrono::milliseconds kEndOfPlaybackCheckFrequency
Definition: tv_play.h:760
TV::m_tvmCurrentTitle
int m_tvmCurrentTitle
Definition: tv_play.h:730
ACTION_TOGGLETT
#define ACTION_TOGGLETT
Definition: tv_actions.h:100
MythCoreContext::emitTVPlaybackUnpaused
void emitTVPlaybackUnpaused(void)
Definition: mythcorecontext.h:295
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:573
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:2751
TV::InitKeys
static void InitKeys()
Definition: tv_play.cpp:494
TV::StartPlayer
bool StartPlayer(TVState desiredState)
Definition: tv_play.cpp:4762
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:97
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:9778
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:555
TV::m_endOfPlaybackTimerId
volatile int m_endOfPlaybackTimerId
Definition: tv_play.h:685
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:240
OSD::DialogGetText
void DialogGetText(InfoMap &Map)
Definition: osd.cpp:835
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:34
ACTION_SETCONTRAST
#define ACTION_SETCONTRAST
Definition: tv_actions.h:60
TV::~TV
~TV() override
Definition: tv_play.cpp:1226
TV::GetPlayerWriteLock
void GetPlayerWriteLock() const
Definition: tv_play.cpp:10486
TV::StartOsdNavigation
void StartOsdNavigation()
Definition: tv_play.cpp:7988
TV::kSaveLastPlayPosTimeout
static const std::chrono::milliseconds kSaveLastPlayPosTimeout
Definition: tv_play.h:765
TV::m_lastProgramLock
QMutex m_lastProgramLock
Definition: tv_play.h:627
kTrackTypeUnknown
@ kTrackTypeUnknown
Definition: decoderbase.h:29
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:698
TV::IsSameProgram
bool IsSameProgram(const ProgramInfo *ProgInfo) const
Definition: tv_play.cpp:10439
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:4993
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:1525
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:1938
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:1357
TV::m_doSmartForward
bool m_doSmartForward
Definition: tv_play.h:557
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:102
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:10385
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:9803
MythDisplay::GetScreenBounds
QRect GetScreenBounds()
Definition: mythdisplay.cpp:311
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:7231
RemoteGetExistingRecorder
RemoteEncoder * RemoteGetExistingRecorder(const ProgramInfo *pginfo)
Definition: tvremoteutil.cpp:312
LCD::switchToChannel
void switchToChannel(const QString &channum="", const QString &title="", const QString &subtitle="")
Definition: lcddevice.cpp:584
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:1874
TV::IsTunablePriv
bool IsTunablePriv(uint ChanId)
Definition: tv_play.cpp:6773
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:4292
TV::m_playerLock
QReadWriteLock m_playerLock
lock on player and playerActive changes
Definition: tv_play.h:641
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:537
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:10036
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:550
TV::StopFFRew
float StopFFRew()
Definition: tv_play.cpp:5228
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:125
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:9442
TV::SetExitPlayer
void SetExitPlayer(bool SetIt, bool WantsTo)
Definition: tv_play.cpp:2800
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:712
RecordingInfo::kFoundProgram
@ kFoundProgram
Definition: recordinginfo.h:182
kTrackTypeSubtitle
@ kTrackTypeSubtitle
Definition: decoderbase.h:32
ACTION_PAGERIGHT
#define ACTION_PAGERIGHT
Definition: tv_actions.h:12
TV::ShowNoRecorderDialog
void ShowNoRecorderDialog(NoRecorderMsg MsgType=kNoRecorders)
Definition: tv_play.cpp:9940
kZoomLeft
@ kZoomLeft
Definition: videoouttypes.h:53
TV::m_lcdVolumeTimerId
volatile int m_lcdVolumeTimerId
Definition: tv_play.h:680
TV::MenuLazyInit
void MenuLazyInit(void *Field)
Definition: tv_play.cpp:9258
TV::TranslateKeyPressOrGesture
bool TranslateKeyPressOrGesture(const QString &Context, QEvent *Event, QStringList &Actions, bool IsLiveTV, bool AllowJumps=true)
Definition: tv_play.cpp:3281
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:10070
TV::DoPlay
void DoPlay()
Definition: tv_play.cpp:4785
TV::m_ffRewSpeeds
std::vector< int > m_ffRewSpeeds
Definition: tv_play.h:540
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:10423
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:89
MythEditorState::m_totalFrames
uint64_t m_totalFrames
Definition: mythplayerstate.h:156
TV::ConvertScreenPressKeyMap
static QList< QKeyEvent * > ConvertScreenPressKeyMap(const QString &KeyList)
Definition: tv_play.cpp:3216
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:507
TV::StopPlayback
void StopPlayback()
Definition: tv_play.cpp:268
kScheduleProgramFinder
@ kScheduleProgramFinder
Definition: tv_play.h:95
MenuTypeId
MenuTypeId
Definition: mythtvmenu.h:36
TV::GetLastProgram
ProgramInfo * GetLastProgram() const
Definition: tv_play.cpp:10415
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:717
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:10008
TV::DoTogglePauseFinish
void DoTogglePauseFinish(float Time, bool ShowOSD)
Definition: tv_play.cpp:4848
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:2727
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:6376
TV::m_wantsToQuit
bool m_wantsToQuit
True if the user told MythTV to stop playback.
Definition: tv_play.h:547
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:383
JobQueue::ChangeJobCmds
static bool ChangeJobCmds(int jobID, int newCmds)
Definition: jobqueue.cpp:918
TVPlaybackState::HandleTeletextAction
void HandleTeletextAction(const QString &Action, bool &Handled)
TV::HandleTrackAction
bool HandleTrackAction(const QString &Action)
Definition: tv_play.cpp:3095
TV::m_tvmFillAutoDetect
bool m_tvmFillAutoDetect
Definition: tv_play.h:706
TV::SetErrored
void SetErrored()
Definition: tv_play.cpp:2744
TV::m_cutlistMenu
MythTVMenu m_cutlistMenu
Definition: tv_play.h:743
MythOpticalBuffer::IsInMenu
bool IsInMenu(void) const override
Definition: mythopticalbuffer.cpp:9
PlayerContext::IsPlayerPlaying
bool IsPlayerPlaying(void) const
Definition: playercontext.cpp:114
MythPlayer::GetNumAngles
virtual int GetNumAngles(void) const
Definition: mythplayer.h:224
TV::HandleOSDAlreadyEditing
void HandleOSDAlreadyEditing(const QString &Action, bool WasPaused)
Definition: tv_play.cpp:7922
TV::m_keyRepeatTimer
MythTimer m_keyRepeatTimer
Queue of unprocessed key presses.
Definition: tv_play.h:591
SET_NEXT
#define SET_NEXT()
Definition: tv_play.cpp:1955
kPictureAttribute_Colour
@ kPictureAttribute_Colour
Definition: videoouttypes.h:109
OSD::IsWindowVisible
bool IsWindowVisible(const QString &Window)
Definition: osd.cpp:627
TV::DialogIsVisible
bool DialogIsVisible(const QString &Dialog)
Definition: tv_play.cpp:8520
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:716
progress
bool progress
Definition: mythcommflag.cpp:69
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:609
MythPlayerCaptionsUI::GetTrack
int GetTrack(uint Type)
Definition: mythplayercaptionsui.cpp:369
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:630
TV::StartChannelEditMode
void StartChannelEditMode()
Starts channel editing mode.
Definition: tv_play.cpp:7959
TV::m_dbUseVideoModes
bool m_dbUseVideoModes
Definition: tv_play.h:528
MythCoreContext::emitTVPlaybackStopped
void emitTVPlaybackStopped(void)
Definition: mythcorecontext.h:291
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:583
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:1678
MythTVMenuItemContext
Definition: mythtvmenu.h:49
OSD::DialogHandleGesture
bool DialogHandleGesture(MythGestureEvent *Event)
Definition: osd.cpp:712
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:10341
TV::m_dbAutoexpireDefault
uint m_dbAutoexpireDefault
Definition: tv_play.h:523
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:587
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:8086
RemoteEncoder::FrontendReady
void FrontendReady(void)
Definition: remoteencoder.cpp:329
MythPlayerUI::GetCodecDescription
void GetCodecDescription(InfoMap &Map)
Definition: mythplayerui.cpp:852
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:682
kPictureAttributeSupported_Volume
@ kPictureAttributeSupported_Volume
Definition: videoouttypes.h:124
TV::m_savedPause
bool m_savedPause
saved pause state before embedding
Definition: tv_play.h:665
MythAudioState::m_muteState
MuteState m_muteState
Definition: mythplayerstate.h:56
MythCoreContext::emitTVPlaybackPlaying
void emitTVPlaybackPlaying(void)
Definition: mythcorecontext.h:297
TV::ArbSeekWhence
ArbSeekWhence
Definition: tv_play.h:370
ACTION_TOGGLECHANCONTROLS
#define ACTION_TOGGLECHANCONTROLS
Definition: tv_actions.h:21
TV::ShowOSDSleep
void ShowOSDSleep()
Definition: tv_play.cpp:7137
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:6254
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:1550
TV::UpdateOSDSeekMessage
void UpdateOSDSeekMessage(const QString &Msg, enum OSDTimeout Timeout)
Definition: tv_play.cpp:6416
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:1933
TV::StartRecorder
bool StartRecorder(std::chrono::milliseconds MaxWait=-1ms)
Starts recorder, must be called before StartPlayer().
Definition: tv_play.cpp:2325
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:315
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:711
MythMediaBuffer::kLiveTVOpenTimeout
static constexpr std::chrono::milliseconds kLiveTVOpenTimeout
Definition: mythmediabuffer.h:72
TV::RetrieveCast
void RetrieveCast(const ProgramInfo &ProgInfo)
Definition: tv_play.cpp:9567
TV::SleepDialogTimeout
void SleepDialogTimeout()
Definition: tv_play.cpp:7174
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:168
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:8544
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:1036
TV::m_screenPressKeyMapPlayback
QList< QKeyEvent * > m_screenPressKeyMapPlayback
Definition: tv_play.h:617
kDisplayCC708
@ kDisplayCC708
Definition: videoouttypes.h:17
TV::customEvent
void customEvent(QEvent *Event) override
This handles all custom events.
Definition: tv_play.cpp:7266
MythPlayerOverlayUI::LockOSD
void LockOSD()
Definition: mythplayeroverlayui.h:25
TV::m_errorRecoveryTimerId
volatile int m_errorRecoveryTimerId
Definition: tv_play.h:690
OSD::ResetWindow
void ResetWindow(const QString &Window)
Definition: osd.cpp:635
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:4905
MythMainWindow::RestoreScreensaver
static void RestoreScreensaver()
Definition: mythmainwindow.cpp:576
TV::ShowOSDAlreadyEditing
void ShowOSDAlreadyEditing()
Definition: tv_play.cpp:7908
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:338
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:560
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:5390
TV::m_tvmTracks
QStringList m_tvmTracks[kTrackTypeCount]
Definition: tv_play.h:699
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:28
EMBEDRETURNVOID
void(*)(void *, bool) EMBEDRETURNVOID
Definition: tv_play.h:58
TV::m_tvmSpeedX100
int m_tvmSpeedX100
Definition: tv_play.h:709
MythCoreContext::emitTVPlaybackStarted
void emitTVPlaybackStarted(void)
Definition: mythcorecontext.h:290
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:3682
signalmonitorvalue.h
TV::ToggleHandleAction
bool ToggleHandleAction(const QStringList &Actions, bool IsDVD)
Definition: tv_play.cpp:4097
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:4060
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:5463
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:961
TV::ChangeChannel
void ChangeChannel(const ChannelInfoList &Options)
Definition: tv_play.cpp:6233
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:198
MythPlayer::IsErrored
bool IsErrored(void) const
Definition: mythplayer.cpp:1941
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:3792
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:200
ACTION_MENUYELLOW
#define ACTION_MENUYELLOW
Definition: tv_actions.h:79
TV::DoArbSeek
void DoArbSeek(ArbSeekWhence Whence, bool HonorCutlist)
Definition: tv_play.cpp:5128
MythPlayer::GetCurrentFrameCount
uint64_t GetCurrentFrameCount(void) const
Definition: mythplayer.cpp:1731
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:681
TV::StartProgramEditMode
void StartProgramEditMode()
Starts Program Cut Map Editing mode.
Definition: tv_play.cpp:7893
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:3653
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:3730
BUTTON2
#define BUTTON2(action, textActive, textInactive)
Definition: tv_play.cpp:8542
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:2375
MythMediaBuffer::HandleAction
virtual bool HandleAction(const QStringList &, mpeg::chrono::pts)
Definition: mythmediabuffer.h:143
TV::ClearOSD
void ClearOSD()
Definition: tv_play.cpp:6294
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:462
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:5494
TV::ChannelEditXDSFill
void ChannelEditXDSFill(InfoMap &Info)
Definition: tv_play.cpp:8049
TV::m_queuedInput
QString m_queuedInput
Input key presses queued up so far...
Definition: tv_play.h:603
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:1309
TV::ShowLCDDVDInfo
void ShowLCDDVDInfo()
Definition: tv_play.cpp:6713
PlayerContext::m_fftime
std::chrono::seconds m_fftime
Definition: playercontext.h:138
TV::m_tvmState
TVState m_tvmState
Definition: tv_play.h:710
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:2394
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:496
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:5423
MythCoreContext::emitTVPlaybackSought
void emitTVPlaybackSought(qint64 position)
Definition: mythcorecontext.h:292
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:629
ACTION_NEXTPAGE
#define ACTION_NEXTPAGE
Definition: tv_actions.h:96
TV::m_endOfRecording
bool m_endOfRecording
!player->IsPlaying() && StateIsPlaying()
Definition: tv_play.h:554
TV::ChangeTimeStretch
void ChangeTimeStretch(int Dir, bool AllowEdit=true)
Definition: tv_play.cpp:7059
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:529
kNormalAutoExpire
@ kNormalAutoExpire
Definition: programtypes.h:194
TV::StateIsLiveTV
static bool StateIsLiveTV(TVState State)
Definition: tv_play.cpp:1947
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:40
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:5443
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:571
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:686
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:55
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:7664
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:657
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:6834
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:7249
TVPlaybackState::GoToMenu
void GoToMenu(const QString &Menu)
RemoteEncoder
Definition: remoteencoder.h:24
TV::GetTitleName
QString GetTitleName(int Title)
Definition: tv_play.cpp:5484
kPseudoRecording
@ kPseudoRecording
Definition: playercontext.h:44
PlayerContext::IsPlayerErrored
bool IsPlayerErrored(void) const
Definition: playercontext.cpp:108
TV::IsDeleteAllowed
bool IsDeleteAllowed()
Definition: tv_play.cpp:10185
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
TV::HandleOSDCutpoint
bool HandleOSDCutpoint(const QString &Action)
Definition: tv_play.cpp:7870
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:10065
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:105
SET_LAST
#define SET_LAST()
Definition: tv_play.cpp:1956
programtypes.h
TV::m_tvmIsBd
bool m_tvmIsBd
Definition: tv_play.h:718
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:1934
TV::m_dbEndOfRecExitPrompt
bool m_dbEndOfRecExitPrompt
Definition: tv_play.h:525
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:2337
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:621
MythPlayer::GetPlaySpeed
float GetPlaySpeed(void) const
Definition: mythplayer.h:138
MythDisplay::GetGUIResolution
QSize GetGUIResolution()
Definition: mythdisplay.cpp:306
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:5605
AutoDeleteDeque::begin
iterator begin(void)
Definition: autodeletedeque.h:50
TV::SetSpeedChangeTimer
void SetSpeedChangeTimer(std::chrono::milliseconds When, int Line)
Definition: tv_play.cpp:2937
MythMainWindow::GetKey
static QString GetKey(const QString &Context, const QString &Action)
Definition: mythmainwindow.cpp:1318
kZoomAspectUp
@ kZoomAspectUp
Definition: videoouttypes.h:55
TV::m_dbBrowseAllTuners
bool m_dbBrowseAllTuners
Definition: tv_play.h:532
TV::PrepareToExitPlayer
void PrepareToExitPlayer(int Line)
Definition: tv_play.cpp:2761
TV::MenuItemDisplayPlayback
bool MenuItemDisplayPlayback(const MythTVMenuItemContext &Context, MythOSDDialogData *Menu)
Definition: tv_play.cpp:8692
BUTTON
#define BUTTON(action, text)
Definition: tv_play.cpp:8540
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:1546
RecordingInfo::kNoProgram
@ kNoProgram
Definition: recordinginfo.h:181
MythCoreContext::UnregisterForPlayback
void UnregisterForPlayback(QObject *sender)
Definition: mythcorecontext.cpp:1966
insert_map
static void insert_map(InfoMap &infoMap, const InfoMap &newMap)
Definition: tv_play.cpp:7950
TV::ARBSEEK_FORWARD
@ ARBSEEK_FORWARD
Definition: tv_play.h:370
EMBEDRETURNVOIDFINDER
void(*)(TV *, bool, bool) EMBEDRETURNVOIDFINDER
Definition: tv_play.h:60
TV::UpdateOSDInput
void UpdateOSDInput()
Definition: tv_play.cpp:6430
TV::m_sleepIndex
uint m_sleepIndex
Index into sleep_times.
Definition: tv_play.h:582
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:5433
CardUtil::GetInputGroups
static std::vector< uint > GetInputGroups(uint inputid)
Definition: cardutil.cpp:2186
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:5764
TV::HandleOSDSleep
void HandleOSDSleep(const QString &Action)
Definition: tv_play.cpp:7153
TV::HandlePseudoLiveTVTimerEvent
void HandlePseudoLiveTVTimerEvent()
Definition: tv_play.cpp:2903
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:1603
TV::DoSeekRWND
void DoSeekRWND()
Definition: tv_play.cpp:10080
TV::GetStatus
void GetStatus()
Definition: tv_play.cpp:1366
ACTION_ZOOMCOMMIT
#define ACTION_ZOOMCOMMIT
Definition: tv_actions.h:144
TV::m_tvmNumTitles
int m_tvmNumTitles
Definition: tv_play.h:729
LCD::getLCDWidth
int getLCDWidth(void) const
Definition: lcddevice.h:293
TV::m_tvmChapterTimes
QList< std::chrono::seconds > m_tvmChapterTimes
Definition: tv_play.h:726
TVBrowseHelper::BrowseWait
void BrowseWait()
Definition: tvbrowsehelper.cpp:68
TV::m_signalMonitorTimerId
volatile int m_signalMonitorTimerId
Definition: tv_play.h:693
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:535
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:10461
kOSDTimeout_None
@ kOSDTimeout_None
Definition: osd.h:58
TV::DoSwitchAngle
void DoSwitchAngle(int Angle)
Definition: tv_play.cpp:5510
TV::m_channelGroupChannelList
ChannelInfoList m_channelGroupChannelList
Definition: tv_play.h:673
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:1335
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:233
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:1097
mythlogging.h
PictureAttributeSupported
PictureAttributeSupported
Definition: videoouttypes.h:116
TV::m_cutlistCompactMenu
MythTVMenu m_cutlistCompactMenu
Definition: tv_play.h:744
TV::kInputModeTimeout
static const std::chrono::milliseconds kInputModeTimeout
Definition: tv_play.h:752
TV::ChangeSpeed
void ChangeSpeed(int Direction)
Definition: tv_play.cpp:5180
TV::AudioSyncHandleAction
bool AudioSyncHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3707
ACTION_MENURED
#define ACTION_MENURED
Definition: tv_actions.h:77
PlayGroup::GetCount
static int GetCount(void)
Definition: playgroup.cpp:195
TV::DoEditSchedule
void DoEditSchedule(int EditType=kScheduleProgramGuide, const QString &EditArg="")
Definition: tv_play.cpp:6878
kScheduleProgramGuide
@ kScheduleProgramGuide
Definition: tv_play.h:94
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:4883
TV::HandleVideoExitDialogTimerEvent
void HandleVideoExitDialogTimerEvent()
Definition: tv_play.cpp:2878
MythOSDDialogData
Definition: osd.h:64
TV::GetQueuedInputAsInt
int GetQueuedInputAsInt(bool *OK=nullptr, int Base=10) const
Definition: tv_play.cpp:5782
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:1901
TV::ToggleOSD
void ToggleOSD(bool IncludeStatusOSD)
Cycle through the available Info OSDs.
Definition: tv_play.cpp:6310
RemoteRequestFreeInputInfo
std::vector< InputInfo > RemoteRequestFreeInputInfo(uint excluded_input)
Definition: tvremoteutil.cpp:137
TV::FillOSDMenuActorShows
void FillOSDMenuActorShows(const QString &actor, int person_id, const QString &category="")
Definition: tv_play.cpp:9666
TV::m_ffRewRepos
float m_ffRewRepos
Definition: tv_play.h:538
TV::m_chanEditMap
InfoMap m_chanEditMap
Channel Editing initial map.
Definition: tv_play.h:578
TV::kPreviousSource
static const uint kPreviousSource
Definition: tv_play.h:750
ACTION_3DTOPANDBOTTOMDISCARD
#define ACTION_3DTOPANDBOTTOMDISCARD
Definition: tv_actions.h:128
TV::lastProgramStringList
static QStringList lastProgramStringList
Definition: tv_play.h:195
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:1111
RemoteIsBusy
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)
Definition: tvremoteutil.cpp:362
TV::MenuItemDisplay
bool MenuItemDisplay(const MythTVMenuItemContext &Context, MythOSDDialogData *Menu) override
Definition: tv_play.cpp:8548
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:607
TV::m_dbUseChannelGroups
bool m_dbUseChannelGroups
Definition: tv_play.h:533
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:2704
TVPlaybackState::AdjustSubtitleZoom
void AdjustSubtitleZoom(int Delta)
TV::HandleLCDVolumeTimerEvent
void HandleLCDVolumeTimerEvent()
Definition: tv_play.cpp:2670
MythEditorState::m_nextCut
uint64_t m_nextCut
Definition: mythplayerstate.h:155
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:588
ACTION_ENABLEVISUALISATION
#define ACTION_ENABLEVISUALISATION
Definition: tv_actions.h:118
EMBEDRETURNVOIDSCHEDIT
void(*)(const ProgramInfo *, void *) EMBEDRETURNVOIDSCHEDIT
Definition: tv_play.h:62
MythVisualiserState::m_canVisualise
bool m_canVisualise
Definition: mythplayerstate.h:135
TV::SetManualZoom
void SetManualZoom(bool ZoomON, const QString &Desc)
Definition: tv_play.cpp:9794
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:577
TV::HandleEndOfRecordingExitPromptTimerEvent
void HandleEndOfRecordingExitPromptTimerEvent()
Definition: tv_play.cpp:2848
MythCoreContext::SendSystemEvent
void SendSystemEvent(const QString &msg)
Definition: mythcorecontext.cpp:1552
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:2981
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:548
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:5114
TV::m_tvmCurrentAngle
int m_tvmCurrentAngle
Definition: tv_play.h:728
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:534
MythVideoFrame::m_timecode
std::chrono::milliseconds m_timecode
Definition: mythframe.h:130
TV::ShowOSDCutpoint
void ShowOSDCutpoint(const QString &Type)
Definition: tv_play.cpp:7826
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:2685
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:98
TV::m_tvmSubsForcedOn
bool m_tvmSubsForcedOn
Definition: tv_play.h:732
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:292
kAspect_16_9
@ kAspect_16_9
Definition: videoouttypes.h:65
TV::ManualZoomHandleAction
bool ManualZoomHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3576
kTrackTypeTextSubtitle
@ kTrackTypeTextSubtitle
Definition: decoderbase.h:43
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:5473
TV::KillTimer
void KillTimer(int Id)
Definition: tv_play.cpp:2693
TV::m_tvmIsLiveTv
bool m_tvmIsLiveTv
Definition: tv_play.h:720
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:196
RemoteEncoder::ChangeChannel
void ChangeChannel(int channeldirection)
Definition: remoteencoder.cpp:451
EMBEDRETURNVOIDPROGLIST
void(*)(TV *, int, const QString &) EMBEDRETURNVOIDPROGLIST
Definition: tv_play.h:61
kScheduledRecording
@ kScheduledRecording
Definition: tv_play.h:96
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:762
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:126
videometadatautil.h
TV::kKeyRepeatTimeout
static const std::chrono::milliseconds kKeyRepeatTimeout
Definition: tv_play.h:755
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:636
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:36
MythPlayerCaptionsUI::GetTracks
QStringList GetTracks(uint Type)
Definition: mythplayercaptionsui.cpp:316
TV::m_pseudoChangeChanTimerId
volatile int m_pseudoChangeChanTimerId
Definition: tv_play.h:688
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:7192
TV::m_tvmIsVideo
bool m_tvmIsVideo
Definition: tv_play.h:713
ACTION_JUMPTODVDTITLEMENU
#define ACTION_JUMPTODVDTITLEMENU
Definition: tv_actions.h:51
TV::m_dbJumpPreferOsd
bool m_dbJumpPreferOsd
Definition: tv_play.h:526
stringutil.h
showStatus
static void showStatus(void)
Definition: mythfrontend.cpp:691
MythEvent::kUpdateTvProgressEventType
static const Type kUpdateTvProgressEventType
Definition: mythevent.h:81
kNoRecorders
@ kNoRecorders
No free recorders.
Definition: tv_play.h:107
TV::m_playbackCompactMenu
MythTVMenu m_playbackCompactMenu
Definition: tv_play.h:742
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:552
mythmedia.h
kDecodeAllowGPU
@ kDecodeAllowGPU
Definition: mythplayer.h:72
TV::kEndOfPlaybackFirstCheckTimer
static const std::chrono::milliseconds kEndOfPlaybackFirstCheckTimer
Definition: tv_play.h:769
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:757
kStartTVIgnoreProgStart
@ kStartTVIgnoreProgStart
Definition: tv_play.h:117
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:605
TV::m_savePosOnExit
bool m_savePosOnExit
False until first timer event.
Definition: tv_play.h:559
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:9755
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:9360
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:5777
TV::m_savedGuiBounds
QRect m_savedGuiBounds
Definition: tv_play.h:659
TV::MenuItemDisplayCutlist
bool MenuItemDisplayCutlist(const MythTVMenuItemContext &Context, MythOSDDialogData *Menu)
Definition: tv_play.cpp:8557
MythPlayer::PauseDecoder
bool PauseDecoder(void)
Definition: mythplayer.cpp:962
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:2944
MConcurrent::run
void run(const QString &name, Class *object, void(Class::*fn)())
Definition: mconcurrent.h:137
kMenuCategoryMenu
@ kMenuCategoryMenu
Definition: mythtvmenu.h:15
kTrackTypeCC608
@ kTrackTypeCC608
Definition: decoderbase.h:33
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:853
TV::PopPreviousChannel
void PopPreviousChannel(bool ImmediateChange)
Definition: tv_play.cpp:6263
TV::m_queuedTranscode
bool m_queuedTranscode
Definition: tv_play.h:558
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::IsTunable
static bool IsTunable(uint ChanId)
Definition: tv_play.cpp:6757
MythCoreContext::RegisterForPlayback
void RegisterForPlayback(QObject *sender, PlaybackStartCb method)
Definition: mythcorecontext.cpp:1945
TVPlaybackState::DialogQuit
void DialogQuit()
TV::kInputKeysMax
static const uint kInputKeysMax
Definition: tv_play.h:748
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:539
TV::SetLastProgram
void SetLastProgram(const ProgramInfo *ProgInfo)
Definition: tv_play.cpp:10403
TV::m_guest_stars
QVector< string_pair > m_guest_stars
Definition: tv_play.h:574
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:666
get_chanid
static uint get_chanid(const PlayerContext *ctx, uint cardid, const QString &channum)
Definition: tv_play.cpp:6069
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:599
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:679
ACTION_SETBRIGHTNESS
#define ACTION_SETBRIGHTNESS
Definition: tv_actions.h:59
TV::ProcessSmartChannel
bool ProcessSmartChannel(QString &InputStr)
Definition: tv_play.cpp:5873
MythMainWindow::GetPaintWindow
QWidget * GetPaintWindow()
Definition: mythmainwindow.cpp:267
TV::kEndOfRecPromptCheckFrequency
static const std::chrono::milliseconds kEndOfRecPromptCheckFrequency
Definition: tv_play.h:764
TVPlaybackState::ToggleMoveBottomLine
void ToggleMoveBottomLine()
ProgramInfo::GetPlaybackGroup
QString GetPlaybackGroup(void) const
Definition: programinfo.h:421
TV::HandleEndOfPlaybackTimerEvent
void HandleEndOfPlaybackTimerEvent()
Definition: tv_play.cpp:2817
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:5826
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:115
TRANSITION
#define TRANSITION(ASTATE, BSTATE)
Definition: tv_play.cpp:1953
TV::HandleOSDClosed
void HandleOSDClosed(int OSDType)
Definition: tv_play.cpp:7739
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:9265
PlayerContext::IsSameProgram
bool IsSameProgram(const ProgramInfo &p) const
Definition: playercontext.cpp:378
TV::ShowOSDStopWatchingRecording
void ShowOSDStopWatchingRecording()
Definition: tv_play.cpp:10200
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:1821
TV::m_dbAutoSetWatched
bool m_dbAutoSetWatched
Definition: tv_play.h:524
TV::m_switchToRec
RemoteEncoder * m_switchToRec
Main recorder to use after a successful SwitchCards() call.
Definition: tv_play.h:647
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:55
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:59
kPictureAttribute_Hue
@ kPictureAttribute_Hue
Definition: videoouttypes.h:110
clamp
static eu8 clamp(eu8 value, eu8 low, eu8 high)
Definition: pxsup2dast.c:204
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:556
TV::FillOSDMenuJumpRec
void FillOSDMenuJumpRec(const QString &Category="", int Level=0, const QString &Selected="")
Definition: tv_play.cpp:9460
ACTION_ZOOMRIGHT
#define ACTION_ZOOMRIGHT
Definition: tv_actions.h:134
TV::IsBookmarkAllowed
bool IsBookmarkAllowed()
Definition: tv_play.cpp:10159
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:370
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:655
PlayerContext::m_tvchain
LiveTVChain * m_tvchain
Definition: playercontext.h:115
TV::ShowLCDChannelInfo
void ShowLCDChannelInfo()
Definition: tv_play.cpp:6687
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:916
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:10121
TV::HandleOSDAskAllow
void HandleOSDAskAllow(const QString &Action)
Definition: tv_play.cpp:1863
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:10451
TV::m_askAllowLock
QRecursiveMutex m_askAllowLock
Definition: tv_play.h:568
MythDB::getMythDB
static MythDB * getMythDB()
Definition: mythdb.cpp:29
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:3200
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:758
mythmediabuffer.h
TV::GetNumChapters
int GetNumChapters()
Definition: tv_play.cpp:5380
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:8530
kStartTVIgnoreLastPlayPos
@ kStartTVIgnoreLastPlayPos
Definition: tv_play.h:118
TV::m_dbContinueEmbedded
bool m_dbContinueEmbedded
Definition: tv_play.h:530
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:983
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:6658
MythTVMenu::Translate
QString Translate(const QString &Text) const
Definition: mythtvmenu.cpp:118
MythPlayer::JumpChapter
void JumpChapter(int chapter)
Definition: mythplayer.cpp:907
kAspect_14_9
@ kAspect_14_9
Definition: videoouttypes.h:66
TV::ToggleTimeStretch
void ToggleTimeStretch()
Definition: tv_play.cpp:7045
MythPlayer::GetNumChapters
virtual int GetNumChapters(void)
Definition: mythplayer.cpp:1807
TV::HasQueuedInput
bool HasQueuedInput() const
Definition: tv_play.h:337
TV::NextPictureAdjustType
PictureAttribute NextPictureAdjustType(PictureAdjustType Type, PictureAttribute Attr)
Definition: tv_play.cpp:7768
ACTION_UP
static constexpr const char * ACTION_UP
Definition: mythuiactions.h:16
TV::m_dbBrowseAlways
bool m_dbBrowseAlways
Definition: tv_play.h:531
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:910
TV::ActivePostQHandleAction
bool ActivePostQHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:4184
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:8039
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:1947
mythburn.chapterLength
int chapterLength
Definition: mythburn.py:192
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:10479
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:1959
TV::HandleLCDTimerEvent
bool HandleLCDTimerEvent()
Definition: tv_play.cpp:2629
kDisplayTextSubtitle
@ kDisplayTextSubtitle
Definition: videoouttypes.h:18
TV::HideOSDWindow
void HideOSDWindow(const char *window)
Definition: tv_play.cpp:6671
TV::m_ccInputMode
bool m_ccInputMode
Are we in CC/Teletext page/stream selection mode?
Definition: tv_play.h:595
TV::ClearInputQueues
void ClearInputQueues(bool Hideosd)
Clear channel key buffer of input keys.
Definition: tv_play.cpp:5811
TV::HandleOSDChannelEdit
bool HandleOSDChannelEdit(const QString &Action)
Processes channel editing key.
Definition: tv_play.cpp:8003
TV::LiveTV
bool LiveTV(bool ShowDialogs, const ChannelInfoList &Selection)
Starts LiveTV.
Definition: tv_play.cpp:1522
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
AspectOverrideMode
AspectOverrideMode
Definition: videoouttypes.h:60
TV::m_jumpToProgram
bool m_jumpToProgram
Definition: tv_play.h:633
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:10496
kPictureAttributeSupported_None
@ kPictureAttributeSupported_None
Definition: videoouttypes.h:118
ACTION_SETVOLUME
#define ACTION_SETVOLUME
Definition: tv_actions.h:112
Channum
Definition: channelsettings.cpp:81
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:39
kNoFlags
@ kNoFlags
Definition: mythplayer.h:66
TV::ShowOSDPromptDeleteRecording
void ShowOSDPromptDeleteRecording(const QString &Title, bool Force=false)
Definition: tv_play.cpp:10240
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:749
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:1270
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:278
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:401
TV::s_sleepTimes
static const std::vector< SleepTimerInfo > s_sleepTimes
Definition: tv_play.h:580
TV::OverrideScan
void OverrideScan(FrameScanType Scan)
Definition: tv_play.cpp:9739
TV::VolumeChange
void VolumeChange(bool Up, int NewVolume=-1)
Definition: tv_play.cpp:7013
TV::GetCurrentAngle
int GetCurrentAngle()
Definition: tv_play.cpp:5453
TV::m_exitPlayerTimerId
volatile int m_exitPlayerTimerId
Definition: tv_play.h:691
TV::m_lastLockSeenTime
QDateTime m_lastLockSeenTime
Definition: tv_play.h:623
mythmiscutil.h
TV::m_progListsLock
QMutex m_progListsLock
Definition: tv_play.h:570
MythDisplay::NextModeIsLarger
bool NextModeIsLarger(QSize Size)
Check whether the next mode is larger in size than the current mode.
Definition: mythdisplay.cpp:672
TVPlaybackState::ResizeScreenForVideo
void ResizeScreenForVideo(QSize Size={})
MythTVMenu::m_id
MenuTypeId m_id
Definition: mythtvmenu.h:112
kScheduleProgramList
@ kScheduleProgramList
Definition: tv_play.h:99
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:6679
TV::m_subtitleDelayAdjustment
bool m_subtitleDelayAdjustment
True if subtitle delay is turned on.
Definition: tv_play.h:551
ACTION_OSDNAVIGATION
#define ACTION_OSDNAVIGATION
Definition: tv_actions.h:55
ACTION_RIGHT
static constexpr const char * ACTION_RIGHT
Definition: mythuiactions.h:19
TVPlaybackState::ChangeUpmix
void ChangeUpmix(bool Enable, bool Toggle=false)
ACTION_TOGGLEVISUALISATION
#define ACTION_TOGGLEVISUALISATION
Definition: tv_actions.h:117
TV::m_asInputTimerId
volatile int m_asInputTimerId
Definition: tv_play.h:683
RecordingInfo::LoadStatus
LoadStatus
Definition: recordinginfo.h:180
TV::m_dbUseGuiSizeForTv
bool m_dbUseGuiSizeForTv
Definition: tv_play.h:527
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:272
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:5866
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:2410
TV::m_sigMonMode
bool m_sigMonMode
Are we in signal monitoring mode?
Definition: tv_play.h:553
TV::m_ignoreKeyPresses
bool m_ignoreKeyPresses
should we ignore keypresses
Definition: tv_play.h:664
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:7208
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:774
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:672
kTrackTypeVideo
@ kTrackTypeVideo
Definition: decoderbase.h:31
MythMainWindow::PopDrawDisabled
uint PopDrawDisabled()
Definition: mythmainwindow.cpp:992
Name
Definition: channelsettings.cpp:71
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:7005
TV::SwitchSource
void SwitchSource(uint Direction)
Definition: tv_play.cpp:5549
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:738
toTitleString
QString toTitleString(PictureAdjustType type)
Definition: tv.cpp:62
TV::m_tvmIsOn
bool m_tvmIsOn
Definition: tv_play.h:735
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:807
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:622
TV::kErrorRecoveryCheckFrequency
static const std::chrono::milliseconds kErrorRecoveryCheckFrequency
Definition: tv_play.h:763
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:1334
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:41
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:264
TV::m_player
MythPlayerUI * m_player
Definition: tv_play.h:639
MythCoreContext::emitTVPlaybackPaused
void emitTVPlaybackPaused(void)
Definition: mythcorecontext.h:294
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:9971
TVPlaybackState::m_audioState
MythAudioState m_audioState
Definition: tvplaybackstate.h:106
TV::MenuStrings
static void MenuStrings()
Definition: tv_play.cpp:9393
TV::m_lcdCallsign
QString m_lcdCallsign
Definition: tv_play.h:652
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:689
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:9635
TV::DoTogglePauseStart
float DoTogglePauseStart()
Definition: tv_play.cpp:4819
TV::RunViewScheduledPtr
static EMBEDRETURNVOID RunViewScheduledPtr
Definition: tv_play.h:197
kTrackTypeTeletextCaptions
@ kTrackTypeTeletextCaptions
Definition: decoderbase.h:35
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:3028
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:585
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:57
kZoomIn
@ kZoomIn
Definition: videoouttypes.h:45
CardUtil::GetSourceID
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1946
OSD::HideWindow
void HideWindow(const QString &Window) override
Definition: osd.cpp:674
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:650
TV::DiscMenuHandleAction
bool DiscMenuHandleAction(const QStringList &Actions) const
Definition: tv_play.cpp:3776
kPictureAttribute_MAX
@ kPictureAttribute_MAX
Definition: videoouttypes.h:113
TV::m_saveLastPlayPosTimerId
volatile int m_saveLastPlayPosTimerId
Definition: tv_play.h:692
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:6402
TV::m_mainWindow
MythMainWindow * m_mainWindow
Definition: tv_play.h:517
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:671
TV::ToggleSleepTimer
void ToggleSleepTimer()
Definition: tv_play.cpp:7111
TV::UpdateOSDSignal
void UpdateOSDSignal(const QStringList &List)
Updates Signal portion of OSD...
Definition: tv_play.cpp:6441
TV::DoTogglePictureAttribute
void DoTogglePictureAttribute(PictureAdjustType Type)
Definition: tv_play.cpp:7790
RemoteCancelNextRecording
void RemoteCancelNextRecording(uint inputid, bool cancel)
Definition: tvremoteutil.cpp:128
TV::m_weDisabledGUI
bool m_weDisabledGUI
true if this instance disabled MythUI drawing.
Definition: tv_play.h:661
MythPlayer::SetCommBreakMap
void SetCommBreakMap(const frm_dir_map_t &NewMap)
Definition: mythplayer.cpp:1722
TV::NormalSpeed
void NormalSpeed()
Definition: tv_play.cpp:5165
PlayerContext
Definition: playercontext.h:49
TV::GetCurrentChapter
int GetCurrentChapter()
Definition: tv_play.cpp:5398
TV::m_guests
QVector< string_pair > m_guests
Definition: tv_play.h:575
TV::kInitFFRWSpeed
static const int kInitFFRWSpeed
Definition: tv_play.h:747
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:2698
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:2051
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:747
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:1039
MythVideoOutput::HasSoftwareFrames
bool HasSoftwareFrames() const
Definition: mythvideoout.h:86
TV::m_dbPlaybackExitPrompt
int m_dbPlaybackExitPrompt
Definition: tv_play.h:522
OSD::SetValues
void SetValues(const QString &Window, const QHash< QString, int > &Map, OSDTimeout Timeout)
Definition: osd.cpp:151
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:9355
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:618
TV::m_playbackMenu
MythTVMenu m_playbackMenu
Definition: tv_play.h:741
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:628
kStereoscopicModeTopAndBottomDiscard
@ kStereoscopicModeTopAndBottomDiscard
Definition: videoouttypes.h:139
kTrackTypeAudio
@ kTrackTypeAudio
Definition: decoderbase.h:30
TV::m_tvmIsPaused
bool m_tvmIsPaused
Definition: tv_play.h:715
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:1985
TV::DoQueueTranscode
void DoQueueTranscode(const QString &Profile)
Definition: tv_play.cpp:5331
mythcodeccontext.h
TV::DoPlayerSeekToFrame
bool DoPlayerSeekToFrame(uint64_t FrameNum)
Definition: tv_play.cpp:4964
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:291
TV::m_queueInputTimerId
volatile int m_queueInputTimerId
Definition: tv_play.h:684
kTrackTypeRawText
@ kTrackTypeRawText
Definition: decoderbase.h:37
TV::m_tvmCurSkip
CommSkipMode m_tvmCurSkip
Definition: tv_play.h:714
MythMainWindow::ClearKeyContext
void ClearKeyContext(const QString &Context)
Definition: mythmainwindow.cpp:1204
OSD::DialogHandleKeypress
bool DialogHandleKeypress(QKeyEvent *Event)
Definition: osd.cpp:705
MythPlayer::JumpToFrame
virtual bool JumpToFrame(uint64_t frame)
Definition: mythplayer.cpp:886
TVPlaybackState::m_videoColourState
MythVideoColourState m_videoColourState
Definition: tvplaybackstate.h:109
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:842
TV::m_tvmCurtrack
int m_tvmCurtrack[kTrackTypeCount]
Definition: tv_play.h:700
TV::SetFFRew
void SetFFRew(int Index)
Definition: tv_play.cpp:5286
kStartTVInPlayList
@ kStartTVInPlayList
Definition: tv_play.h:114
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:1115
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:5077
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:736
TV::DoJumpChapter
void DoJumpChapter(int Chapter)
Definition: tv_play.cpp:5408
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:727
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:542
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:753
kStereoscopicModeSideBySideDiscard
@ kStereoscopicModeSideBySideDiscard
Definition: videoouttypes.h:138
MythMainWindow::MoveResize
void MoveResize(QRect &Geometry)
Definition: mythmainwindow.cpp:972
ACTION_JUMPTODVDCHAPTERMENU
#define ACTION_JUMPTODVDCHAPTERMENU
Definition: tv_actions.h:50
MythPlayer::GetXDS
QString GetXDS(const QString &key) const
Definition: mythplayer.cpp:1715
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:27
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:521
TV::m_adjustingPictureAttribute
PictureAttribute m_adjustingPictureAttribute
Picture attribute to modify (on arrow left or right)
Definition: tv_play.h:564
TV::GetPlayerReadLock
void GetPlayerReadLock() const
Definition: tv_play.cpp:10491
TV::SetBookmark
void SetBookmark(bool Clear=false)
Definition: tv_play.cpp:4166
TV::CommitQueuedInput
bool CommitQueuedInput()
Definition: tv_play.cpp:5943
TV::FillOSDMenuCast
void FillOSDMenuCast(void)
Definition: tv_play.cpp:9654
MythPlayerCaptionsUI::GetTrackCount
uint GetTrackCount(uint Type)
Definition: mythplayercaptionsui.cpp:323
PlayerContext::m_recorder
RemoteEncoder * m_recorder
Definition: playercontext.h:114
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:885
TV::BrowseHandleAction
bool BrowseHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3531
TV::m_sleepTimerId
int m_sleepTimerId
Timer for turning off playback.
Definition: tv_play.h:584
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:777
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:5253
TV::GetAllowRerecord
bool GetAllowRerecord() const
Returns true if the user told Mythtv to allow re-recording of the show.
Definition: tv_play.h:312
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:616
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:719
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:5787
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:201
TV::m_tvmSubsHaveSubs
bool m_tvmSubsHaveSubs
Definition: tv_play.h:733
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:370
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:101
TV::m_networkControlCommands
MythDeque< QString > m_networkControlCommands
Definition: tv_play.h:676
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:651
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
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:6867
TVPlaybackState::PauseAudioUntilReady
void PauseAudioUntilReady()
ACTION_JUMPPREV
#define ACTION_JUMPPREV
Definition: tv_actions.h:38
TV::DoJumpFFWD
void DoJumpFFWD()
Definition: tv_play.cpp:10055
TV::DoPlayerSeek
bool DoPlayerSeek(float Time)
Definition: tv_play.cpp:4928
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:52
TV::DVDJumpBack
void DVDJumpBack()
Definition: tv_play.cpp:10088
TV::m_tvmCurrentChapter
int m_tvmCurrentChapter
Definition: tv_play.h:725
kZoomHorizontalOut
@ kZoomHorizontalOut
Definition: videoouttypes.h:50
PlayerContext::m_player
MythPlayer * m_player
Definition: playercontext.h:112
MythPlayerUI::EventLoop
virtual void EventLoop()
Definition: mythplayerui.cpp:114
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:344
TV::DoSkipCommercials
void DoSkipCommercials(int Direction)
Definition: tv_play.cpp:5526
MythCoreContext::dispatch
void dispatch(const MythEvent &event)
Definition: mythcorecontext.cpp:1727
MythMainWindow::GetActionText
QString GetActionText(const QString &Context, const QString &Action) const
Definition: mythmainwindow.cpp:1339
LCD::setChannelProgress
void setChannelProgress(const QString &time, float value)
Definition: lcddevice.cpp:470
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:71
TVBrowseHelper::BrowseStart
bool BrowseStart(bool SkipBrowse=false)
Begins channel browsing.
Definition: tvbrowsehelper.cpp:75
TV::m_tvmPreviousChan
bool m_tvmPreviousChan
Definition: tv_play.h:721
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:759
kPictureAttribute_Brightness
@ kPictureAttribute_Brightness
Definition: videoouttypes.h:107
TV::m_audiosyncAdjustment
bool m_audiosyncAdjustment
True if audiosync is turned on.
Definition: tv_play.h:549
MythPlayer::FastForward
virtual bool FastForward(float seconds)
Definition: mythplayer.cpp:833
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:3294
TV::ShowOSDAskAllow
void ShowOSDAskAllow()
Definition: tv_play.cpp:1644
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:126
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:543
TV::Init
bool Init()
Performs instance initialization, returns true on success.
Definition: tv_play.cpp:1144
ACTION_SEEKFFWD
#define ACTION_SEEKFFWD
Definition: tv_actions.h:43
CardUtil::GetStartChannel
static QString GetStartChannel(uint inputid)
Definition: cardutil.cpp:1790
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
TV::RunProgramFinderPtr
static EMBEDRETURNVOIDFINDER RunProgramFinderPtr
Definition: tv_play.h:199
TV::SubtitleDelayHandleAction
bool SubtitleDelayHandleAction(const QStringList &Actions)
Definition: tv_play.cpp:3753
kNoCurrRec
@ kNoCurrRec
No current recordings.
Definition: tv_play.h:108
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:6599
TV::m_adjustingPicture
PictureAdjustType m_adjustingPicture
Picture attribute type to modify.
Definition: tv_play.h:562
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:687
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:1298
TV::m_tvmAvsync
bool m_tvmAvsync
Definition: tv_play.h:703
ProgramInfo::SaveLastPlayPos
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
Definition: programinfo.cpp:2727
TV::ARBSEEK_REWIND
@ ARBSEEK_REWIND
Definition: tv_play.h:370
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:318
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:2154
MythCoreContext::emitTVPlaybackAborted
void emitTVPlaybackAborted(void)
Definition: mythcorecontext.h:296
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:116
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:6790
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:55
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:3250
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:180
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:567
TV::m_tvmNumChapters
int m_tvmNumChapters
Definition: tv_play.h:724
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:863
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:1814
TV
Control TV playback.
Definition: tv_play.h:154
ChannelInfoList
std::vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:131
AskProgramInfo
Definition: tv_play.h:121
kNoTuners
@ kNoTuners
No capture cards configured.
Definition: tv_play.h:109
TV::m_dbChannelFormat
QString m_dbChannelFormat
Definition: tv_play.h:520