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