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