2 #include <QApplication>
3 #include <QDomDocument>
9 #include <QRegularExpression>
11 #include <QTimerEvent>
14 #include "mythconfig.h"
79 #define round(x) ((int) ((x) + 0.5))
82 #define DEBUG_CHANNEL_PREFIX 0
83 #define DEBUG_ACTIONS 0
85 #define LOC QString("TV::%1(): ").arg(__func__)
87 #define HideOSDWindow(WINDOW) { \
88 OSD *osd = GetOSDL(); \
90 osd->HideWindow(WINDOW); \
101 query.
prepare(
"SELECT COUNT(cardid) FROM capturecard;");
103 count = query.
value(0).toInt();
105 LOG(VB_RECORD, LOG_INFO,
106 "ConfiguredTunerCards() = " + QString::number(count));
120 static QMutex s_lock;
121 static TV* s_tv =
nullptr;
122 QMutexLocker locker(&s_lock);
134 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Ref count error");
180 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Already have a player");
186 auto flags =
static_cast<PlayerFlags>(playerflags);
219 LOG(VB_GENERAL, LOG_ERR,
LOC +
"StartPlaying() Failed to start player");
224 MaxWait = (MaxWait <= 0ms) ? 20s : MaxWait;
225 #ifdef USING_VALGRIND
226 MaxWait = std::chrono::milliseconds::max();
227 #endif // USING_VALGRIND
236 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
237 QString(
"StartPlaying(): took %1 ms to start player.")
238 .arg(
t.elapsed().count()));
241 LOG(VB_GENERAL, LOG_ERR,
LOC +
"StartPlaying() Failed to start player");
273 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Already have a TV object.");
278 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
281 bool quitAll =
false;
282 bool showDialogs =
true;
283 bool playCompleted =
false;
285 bool startSysEventSent =
false;
286 bool startLivetvEventSent =
false;
299 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed initializing TV");
321 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->Playback() -- begin");
326 else if (!startSysEventSent)
328 startSysEventSent =
true;
332 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->Playback() -- end");
336 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->LiveTV() -- begin");
337 if (!tv->
LiveTV(showDialogs, Selection))
342 else if (!startSysEventSent)
344 startSysEventSent =
true;
345 startLivetvEventSent =
true;
349 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->LiveTV() -- end");
354 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No tuners configured");
356 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No tuners free for live tv");
367 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Entering main playback loop.");
369 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Exiting main playback loop.");
377 curProgram = nextProgram;
391 quitAll |= !playerError.isEmpty();
394 QCoreApplication::processEvents();
398 playCompleted =
true;
408 if (startSysEventSent)
416 list.push_back(allowrerecord ?
"1" :
"0");
417 MythEvent me(
"LOCAL_PBB_DELETE_RECORDINGS", list);
428 else if (startSysEventSent)
431 if (!playerError.isEmpty())
441 if (startLivetvEventSent)
444 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
446 return playCompleted;
456 if (name ==
"playbackbox")
458 else if (name ==
"viewscheduled")
460 else if (name ==
"programguide")
462 else if (name ==
"programfinder")
464 else if (name ==
"scheduleeditor")
471 "Play Program"),
"P");
473 "Stop Program"),
"");
475 "Toggle recording status of current program"),
"R");
477 "Page the program guide back one day"),
"Home");
479 "Page the program guide forward one day"),
"End");
481 "Page the program guide left"),
",,<");
483 "Page the program guide right"),
">,.");
485 "Toggle the current channel as a favorite"),
"?");
487 "Reverse the channel order in the program guide"),
"");
489 "Show the Program Guide"),
"S");
491 "Show the Program Finder"),
"#");
493 "Show the Channel Search"),
"");
494 REG_KEY(
"TV Frontend",
"NEXTFAV", QT_TRANSLATE_NOOP(
"MythControls",
495 "Cycle through channel groups and all channels in the "
496 "program guide."),
"/");
497 REG_KEY(
"TV Frontend",
"CHANUPDATE", QT_TRANSLATE_NOOP(
"MythControls",
498 "Switch channels without exiting guide in Live TV mode."),
"X");
500 "Volume down"),
"[,{,F10,Volume Down");
502 "Volume up"),
"],},F11,Volume Up");
504 "Mute"),
"|,\\,F9,Volume Mute");
505 REG_KEY(
"TV Frontend",
"CYCLEAUDIOCHAN", QT_TRANSLATE_NOOP(
"MythControls",
506 "Cycle audio channels"),
"");
507 REG_KEY(
"TV Frontend",
"RANKINC", QT_TRANSLATE_NOOP(
"MythControls",
508 "Increase program or channel rank"),
"Right");
509 REG_KEY(
"TV Frontend",
"RANKDEC", QT_TRANSLATE_NOOP(
"MythControls",
510 "Decrease program or channel rank"),
"Left");
511 REG_KEY(
"TV Frontend",
"UPCOMING", QT_TRANSLATE_NOOP(
"MythControls",
512 "List upcoming episodes"),
"O");
514 "List scheduled upcoming episodes"),
"");
516 "List previously recorded episodes"),
"");
517 REG_KEY(
"TV Frontend",
"DETAILS", QT_TRANSLATE_NOOP(
"MythControls",
518 "Show details"),
"U");
519 REG_KEY(
"TV Frontend",
"VIEWINPUT", QT_TRANSLATE_NOOP(
"MythControls",
520 "Switch Recording Input view"),
"C");
521 REG_KEY(
"TV Frontend",
"CUSTOMEDIT", QT_TRANSLATE_NOOP(
"MythControls",
522 "Edit Custom Record Rule"),
"");
523 REG_KEY(
"TV Frontend",
"CHANGERECGROUP", QT_TRANSLATE_NOOP(
"MythControls",
524 "Change Recording Group"),
"");
525 REG_KEY(
"TV Frontend",
"CHANGEGROUPVIEW", QT_TRANSLATE_NOOP(
"MythControls",
526 "Change Group View"),
"");
528 "List recorded episodes"),
"");
548 if (selectKeys !=
"?")
551 togBkmKeys = selectKeys;
553 bkmKeys = selectKeys;
557 "Add Bookmark"), bkmKeys);
559 "Toggle Bookmark"), togBkmKeys);
560 REG_KEY(
"TV Playback",
"BACK", QT_TRANSLATE_NOOP(
"MythControls",
561 "Exit or return to DVD menu"),
"Esc");
563 "Playback Compact Menu"),
"Alt+M");
565 "Clear OSD"),
"Backspace");
567 "Pause"),
"P,Space");
569 "Fast Forward"),
"Right");
573 "Arbitrary Seek"),
"*");
575 "Seek to a position in seconds"),
"");
577 "Channel up"),
"Up");
579 "Channel down"),
"Down");
580 REG_KEY(
"TV Playback",
"NEXTFAV", QT_TRANSLATE_NOOP(
"MythControls",
581 "Switch to the next favorite channel"),
"/");
582 REG_KEY(
"TV Playback",
"PREVCHAN", QT_TRANSLATE_NOOP(
"MythControls",
583 "Switch to the previous channel"),
"H");
585 "Jump ahead"),
"PgDown");
587 "Jump back"),
"PgUp");
588 REG_KEY(
"TV Playback",
"INFOWITHCUTLIST", QT_TRANSLATE_NOOP(
"MythControls",
589 "Info utilizing cutlist"),
"");
591 "Jump to bookmark"),
"K");
592 REG_KEY(
"TV Playback",
"FFWDSTICKY", QT_TRANSLATE_NOOP(
"MythControls",
593 "Fast Forward (Sticky) or Forward one second while paused"),
">,.");
594 REG_KEY(
"TV Playback",
"RWNDSTICKY", QT_TRANSLATE_NOOP(
"MythControls",
595 "Rewind (Sticky) or Rewind one second while paused"),
",,<");
596 REG_KEY(
"TV Playback",
"NEXTSOURCE", QT_TRANSLATE_NOOP(
"MythControls",
597 "Next Video Source"),
"Y");
598 REG_KEY(
"TV Playback",
"PREVSOURCE", QT_TRANSLATE_NOOP(
"MythControls",
599 "Previous Video Source"),
"");
600 REG_KEY(
"TV Playback",
"NEXTINPUT", QT_TRANSLATE_NOOP(
"MythControls",
602 REG_KEY(
"TV Playback",
"NEXTCARD", QT_TRANSLATE_NOOP(
"MythControls",
604 REG_KEY(
"TV Playback",
"SKIPCOMMERCIAL", QT_TRANSLATE_NOOP(
"MythControls",
605 "Skip Commercial"),
"Z,End");
606 REG_KEY(
"TV Playback",
"SKIPCOMMBACK", QT_TRANSLATE_NOOP(
"MythControls",
607 "Skip Commercial (Reverse)"),
"Q,Home");
609 "Jump to the start of the recording."),
"Ctrl+B");
610 REG_KEY(
"TV Playback",
"TOGGLEBROWSE", QT_TRANSLATE_NOOP(
"MythControls",
611 "Toggle channel browse mode"),
"O");
613 "Toggle recording status of current program"),
"R");
615 "Toggle the current channel as a favorite"),
"?");
617 "Volume down"),
"[,{,F10,Volume Down");
619 "Volume up"),
"],},F11,Volume Up");
621 "Mute"),
"|,\\,F9,Volume Mute");
623 "Set the volume"),
"");
624 REG_KEY(
"TV Playback",
"CYCLEAUDIOCHAN", QT_TRANSLATE_NOOP(
"MythControls",
625 "Cycle audio channels"),
"");
627 "Toggle audio upmixer"),
"Ctrl+U");
629 QT_TRANSLATE_NOOP(
"MythControls",
"Move BottomLine off screen"),
"L");
631 QT_TRANSLATE_NOOP(
"MythControls",
"Save manual zoom for BottomLine"),
"");
632 REG_KEY(
"TV Playback",
"TOGGLEASPECT", QT_TRANSLATE_NOOP(
"MythControls",
633 "Toggle the video aspect ratio"),
"Ctrl+W");
634 REG_KEY(
"TV Playback",
"TOGGLEFILL", QT_TRANSLATE_NOOP(
"MythControls",
635 "Next Preconfigured Zoom mode"),
"W");
637 "Toggle any captions"),
"T");
639 "Enable any captions"),
"");
641 "Disable any captions"),
"");
642 REG_KEY(
"TV Playback",
"TOGGLETTC", QT_TRANSLATE_NOOP(
"MythControls",
643 "Toggle Teletext Captions"),
"");
644 REG_KEY(
"TV Playback",
"TOGGLESUBTITLE", QT_TRANSLATE_NOOP(
"MythControls",
645 "Toggle Subtitles"),
"");
646 REG_KEY(
"TV Playback",
"TOGGLECC608", QT_TRANSLATE_NOOP(
"MythControls",
647 "Toggle VBI CC"),
"");
648 REG_KEY(
"TV Playback",
"TOGGLECC708", QT_TRANSLATE_NOOP(
"MythControls",
649 "Toggle ATSC CC"),
"");
650 REG_KEY(
"TV Playback",
"TOGGLETTM", QT_TRANSLATE_NOOP(
"MythControls",
651 "Toggle Teletext Menu"),
"");
653 "Toggle External Subtitles"),
"");
655 "Enable External Subtitles"),
"");
657 "Disable External Subtitles"),
"");
658 REG_KEY(
"TV Playback",
"TOGGLERAWTEXT", QT_TRANSLATE_NOOP(
"MythControls",
659 "Toggle Text Subtitles"),
"");
661 REG_KEY(
"TV Playback",
"SELECTAUDIO_0", QT_TRANSLATE_NOOP(
"MythControls",
662 "Play audio track 1"),
"");
663 REG_KEY(
"TV Playback",
"SELECTAUDIO_1", QT_TRANSLATE_NOOP(
"MythControls",
664 "Play audio track 2"),
"");
665 REG_KEY(
"TV Playback",
"SELECTSUBTITLE_0",QT_TRANSLATE_NOOP(
"MythControls",
666 "Display subtitle 1"),
"");
667 REG_KEY(
"TV Playback",
"SELECTSUBTITLE_1",QT_TRANSLATE_NOOP(
"MythControls",
668 "Display subtitle 2"),
"");
669 REG_KEY(
"TV Playback",
"SELECTRAWTEXT_0",QT_TRANSLATE_NOOP(
"MythControls",
670 "Display Text Subtitle 1"),
"");
671 REG_KEY(
"TV Playback",
"SELECTCC608_0", QT_TRANSLATE_NOOP(
"MythControls",
672 "Display VBI CC1"),
"");
673 REG_KEY(
"TV Playback",
"SELECTCC608_1", QT_TRANSLATE_NOOP(
"MythControls",
674 "Display VBI CC2"),
"");
675 REG_KEY(
"TV Playback",
"SELECTCC608_2", QT_TRANSLATE_NOOP(
"MythControls",
676 "Display VBI CC3"),
"");
677 REG_KEY(
"TV Playback",
"SELECTCC608_3", QT_TRANSLATE_NOOP(
"MythControls",
678 "Display VBI CC4"),
"");
679 REG_KEY(
"TV Playback",
"SELECTCC708_0", QT_TRANSLATE_NOOP(
"MythControls",
680 "Display ATSC CC1"),
"");
681 REG_KEY(
"TV Playback",
"SELECTCC708_1", QT_TRANSLATE_NOOP(
"MythControls",
682 "Display ATSC CC2"),
"");
683 REG_KEY(
"TV Playback",
"SELECTCC708_2", QT_TRANSLATE_NOOP(
"MythControls",
684 "Display ATSC CC3"),
"");
685 REG_KEY(
"TV Playback",
"SELECTCC708_3", QT_TRANSLATE_NOOP(
"MythControls",
686 "Display ATSC CC4"),
"");
688 "Enable Forced Subtitles"),
"");
690 "Disable Forced Subtitles"),
"");
692 REG_KEY(
"TV Playback",
"NEXTAUDIO", QT_TRANSLATE_NOOP(
"MythControls",
693 "Next audio track"),
"+");
694 REG_KEY(
"TV Playback",
"PREVAUDIO", QT_TRANSLATE_NOOP(
"MythControls",
695 "Previous audio track"),
"-");
696 REG_KEY(
"TV Playback",
"NEXTSUBTITLE", QT_TRANSLATE_NOOP(
"MythControls",
697 "Next subtitle track"),
"");
698 REG_KEY(
"TV Playback",
"PREVSUBTITLE", QT_TRANSLATE_NOOP(
"MythControls",
699 "Previous subtitle track"),
"");
700 REG_KEY(
"TV Playback",
"NEXTRAWTEXT", QT_TRANSLATE_NOOP(
"MythControls",
701 "Next Text track"),
"");
702 REG_KEY(
"TV Playback",
"PREVRAWTEXT", QT_TRANSLATE_NOOP(
"MythControls",
703 "Previous Text track"),
"");
704 REG_KEY(
"TV Playback",
"NEXTCC608", QT_TRANSLATE_NOOP(
"MythControls",
705 "Next VBI CC track"),
"");
706 REG_KEY(
"TV Playback",
"PREVCC608", QT_TRANSLATE_NOOP(
"MythControls",
707 "Previous VBI CC track"),
"");
708 REG_KEY(
"TV Playback",
"NEXTCC708", QT_TRANSLATE_NOOP(
"MythControls",
709 "Next ATSC CC track"),
"");
710 REG_KEY(
"TV Playback",
"PREVCC708", QT_TRANSLATE_NOOP(
"MythControls",
711 "Previous ATSC CC track"),
"");
712 REG_KEY(
"TV Playback",
"NEXTCC", QT_TRANSLATE_NOOP(
"MythControls",
713 "Next of any captions"),
"");
715 REG_KEY(
"TV Playback",
"NEXTSCAN", QT_TRANSLATE_NOOP(
"MythControls",
716 "Next video scan overidemode"),
"");
717 REG_KEY(
"TV Playback",
"QUEUETRANSCODE", QT_TRANSLATE_NOOP(
"MythControls",
718 "Queue the current recording for transcoding"),
"X");
719 REG_KEY(
"TV Playback",
"SPEEDINC", QT_TRANSLATE_NOOP(
"MythControls",
720 "Increase the playback speed"),
"U");
721 REG_KEY(
"TV Playback",
"SPEEDDEC", QT_TRANSLATE_NOOP(
"MythControls",
722 "Decrease the playback speed"),
"J");
723 REG_KEY(
"TV Playback",
"ADJUSTSTRETCH", QT_TRANSLATE_NOOP(
"MythControls",
724 "Turn on time stretch control"),
"A");
725 REG_KEY(
"TV Playback",
"STRETCHINC", QT_TRANSLATE_NOOP(
"MythControls",
726 "Increase time stretch speed"),
"");
727 REG_KEY(
"TV Playback",
"STRETCHDEC", QT_TRANSLATE_NOOP(
"MythControls",
728 "Decrease time stretch speed"),
"");
729 REG_KEY(
"TV Playback",
"TOGGLESTRETCH", QT_TRANSLATE_NOOP(
"MythControls",
730 "Toggle time stretch speed"),
"");
732 QT_TRANSLATE_NOOP(
"MythControls",
733 "Turn on audio sync adjustment controls"),
"");
735 QT_TRANSLATE_NOOP(
"MythControls",
736 "Set the audio sync adjustment"),
"");
737 REG_KEY(
"TV Playback",
"TOGGLEPICCONTROLS",
738 QT_TRANSLATE_NOOP(
"MythControls",
"Playback picture adjustments"),
741 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture brightness"),
"");
743 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture contrast"),
"");
745 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture color"),
"");
747 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture hue"),
"");
749 QT_TRANSLATE_NOOP(
"MythControls",
"Recording picture adjustments "
750 "for this channel"),
"Ctrl+G");
752 QT_TRANSLATE_NOOP(
"MythControls",
"Recording picture adjustments "
753 "for this recorder"),
"G");
754 REG_KEY(
"TV Playback",
"CYCLECOMMSKIPMODE",
755 QT_TRANSLATE_NOOP(
"MythControls",
"Cycle Commercial Skip mode"),
758 "Show the Program Guide"),
"S");
760 "Show the Program Finder"),
"#");
762 "Toggle the Sleep Timer"),
"F8");
766 "Jump to previously played recording"),
"");
768 "Display menu of recorded programs to jump to"),
"");
770 "Display scheduled recording list"),
"");
772 "Display previously recorded episodes"),
"");
774 "Monitor Signal Quality"),
"Alt+F7");
776 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the DVD Root Menu"),
"");
778 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the Popup Menu"),
"");
780 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the DVD Chapter Menu"),
"");
782 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the DVD Title Menu"),
"");
784 QT_TRANSLATE_NOOP(
"MythControls",
"Exit Show without any prompts"),
787 "Jump to a chapter"),
"");
789 "Switch title"),
"");
791 "Switch angle"),
"");
793 "OSD Navigation"),
"");
795 "Zoom mode - shift up"),
"");
797 "Zoom mode - shift down"),
"");
799 "Zoom mode - shift left"),
"");
801 "Zoom mode - shift right"),
"");
803 QT_TRANSLATE_NOOP(
"MythControls",
804 "Zoom mode - increase aspect ratio"),
"");
806 QT_TRANSLATE_NOOP(
"MythControls",
807 "Zoom mode - decrease aspect ratio"),
"");
809 "Zoom mode - zoom in"),
"");
811 "Zoom mode - zoom out"),
"");
813 QT_TRANSLATE_NOOP(
"MythControls",
814 "Zoom mode - vertical zoom in"),
"8");
816 QT_TRANSLATE_NOOP(
"MythControls",
817 "Zoom mode - vertical zoom out"),
"2");
819 QT_TRANSLATE_NOOP(
"MythControls",
820 "Zoom mode - horizontal zoom in"),
"6");
822 QT_TRANSLATE_NOOP(
"MythControls",
823 "Zoom mode - horizontal zoom out"),
"4");
825 "Zoom mode - quit and abandon changes"),
"");
827 "Zoom mode - commit changes"),
"");
833 "Menu Green"),
"F3");
835 "Menu Yellow"),
"F4");
847 "Clear editing cut points"),
"C,Q,Home");
849 "Invert Begin/End cut points"),
"I");
853 "Load cuts from detected commercials"),
"Z,End");
855 "Jump to the next cut point"),
"PgDown");
857 "Jump to the previous cut point"),
"PgUp");
859 "Jump back 10x the normal amount"),
",,<");
861 "Jump forward 10x the normal amount"),
">,.");
863 "Cut point editor compact menu"),
"Alt+M");
867 "Next Page"),
"Down");
869 "Previous Page"),
"Up");
871 "Next Subpage"),
"Right");
873 "Previous Subpage"),
"Left");
875 "Toggle Teletext"),
"T");
879 "Menu Green"),
"F3");
881 "Menu Yellow"),
"F4");
885 "Menu White"),
"F6");
887 QT_TRANSLATE_NOOP(
"MythControls",
"Toggle Background"),
"F7");
889 "Reveal hidden Text"),
"F8");
893 QT_TRANSLATE_NOOP(
"MythControls",
"Toggle audio visualisation"),
"");
897 QT_TRANSLATE_NOOP(
"MythControls",
"Toggle OSD playback information"),
"");
901 QT_TRANSLATE_NOOP(
"MythControls",
"Auto 3D"),
"");
903 QT_TRANSLATE_NOOP(
"MythControls",
"Ignore 3D"),
"");
905 QT_TRANSLATE_NOOP(
"MythControls",
"Discard 3D Side by Side"),
"");
907 QT_TRANSLATE_NOOP(
"MythControls",
"Discard 3D Top and Bottom"),
"");
961 { tr(
"Off",
"Sleep timer"), 0min },
962 { tr(
"30m",
"Sleep timer"), 30min },
963 { tr(
"1h",
"Sleep timer"), 60min },
964 { tr(
"1h30m",
"Sleep timer"), 90min },
965 { tr(
"2h",
"Sleep timer"), 120min }
982 m_mainWindow(MainWindow)
985 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Creating TV object");
987 QObject::setObjectName(
"TV");
1004 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Finished creating TV object");
1009 QMap<QString,QString> kv;
1010 kv[
"LiveTVIdleTimeout"] =
"0";
1011 kv[
"BrowseMaxForward"] =
"240";
1012 kv[
"PlaybackExitPrompt"] =
"0";
1013 kv[
"AutomaticSetWatched"] =
"0";
1014 kv[
"EndOfRecordingExitPrompt"] =
"0";
1015 kv[
"JumpToProgramOSD"] =
"1";
1016 kv[
"GuiSizeForTV"] =
"0";
1017 kv[
"UseVideoModes"] =
"0";
1018 kv[
"ClearSavedPosition"] =
"1";
1019 kv[
"JobsRunOnRecordHost"] =
"0";
1020 kv[
"ContinueEmbeddedTVPlay"] =
"0";
1021 kv[
"UseFixedWindowSize"] =
"1";
1022 kv[
"RunFrontendInWindow"] =
"0";
1023 kv[
"PersistentBrowseMode"] =
"0";
1024 kv[
"BrowseAllTuners"] =
"0";
1025 kv[
"ChannelOrdering"] =
"channum";
1027 kv[
"CustomFilters"] =
"";
1028 kv[
"ChannelFormat"] =
"<num> <sign>";
1030 kv[
"TryUnflaggedSkip"] =
"0";
1032 kv[
"ChannelGroupDefault"] =
"-1";
1033 kv[
"BrowseChannelGroup"] =
"0";
1034 kv[
"SmartForward"] =
"0";
1035 kv[
"FFRewReposTime"] =
"100";
1036 kv[
"FFRewReverse"] =
"1";
1038 kv[
"BrowseChannelGroup"] =
"0";
1039 kv[
"ChannelGroupDefault"] =
"-1";
1040 kv[
"ChannelGroupRememberLast"] =
"0";
1042 kv[
"VbiFormat"] =
"";
1043 kv[
"DecodeVBIFormat"] =
"";
1046 kv[
"PlaybackScreenPressKeyMap"] =
"P,Up,Z,],Left,Return,Return,Right,A,Down,Q,[";
1047 kv[
"LiveTVScreenPressKeyMap"] =
"P,Up,Z,S,Left,Return,Return,Right,A,Down,Q,F";
1049 constexpr std::array<const int,8> ff_rew_def { 3, 5, 10, 20, 30, 60, 120, 180 };
1050 for (
size_t i = 0; i < ff_rew_def.size(); i++)
1051 kv[QString(
"FFRewSpeed%1").arg(i)] = QString::number(ff_rew_def[i]);
1058 QString db_channel_ordering;
1060 m_dbIdleTimeout = std::chrono::minutes(kv[
"LiveTVIdleTimeout"].toUInt());
1061 auto db_browse_max_forward = std::chrono::minutes(kv[
"BrowseMaxForward"].toUInt());
1073 db_channel_ordering = kv[
"ChannelOrdering"];
1083 QString beVBI = kv[
"VbiFormat"];
1084 QString feVBI = kv[
"DecodeVBIFormat"];
1101 for (
size_t i = 0; i <
sizeof(ff_rew_def)/
sizeof(ff_rew_def[0]); i++)
1102 m_ffRewSpeeds.push_back(kv[QString(
"FFRewSpeed%1").arg(i)].toInt());
1119 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
1123 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No MythMainWindow");
1144 fullscreen |= (0 == gui_width && 0 == gui_height);
1159 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Created TvPlayWindow.");
1170 QCoreApplication::processEvents();
1195 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
1201 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
1222 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"-- lock");
1255 lcd->setFunctionLEDs(
FUNC_TV,
false);
1257 lcd->switchToTime();
1265 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
1275 QCoreApplication::processEvents();
1351 .toUTC().toString(
"yyyy-MM-ddThh:mm:ssZ"));
1362 if (!info.
text[
"totalchapters"].isEmpty())
1364 QList<std::chrono::seconds> chapters;
1367 for (std::chrono::seconds chapter : qAsConst(chapters))
1368 var << QVariant((
long long)chapter.count());
1369 status.insert(
"chaptertimes", var);
1376 int currenttrack = -1;
1379 for (
int i = 0; i < list.size(); i++)
1381 if (i == currenttrack)
1382 status.insert(
"currentsubtitletrack", list[i]);
1383 tracks.insert(
"SELECTSUBTITLE_" + QString::number(i), list[i]);
1390 for (
int i = 0; i < list.size(); i++)
1392 if (i == currenttrack)
1393 status.insert(
"currentsubtitletrack", list[i]);
1394 tracks.insert(
"SELECTTTC_" + QString::number(i), list[i]);
1401 for (
int i = 0; i < list.size(); i++)
1403 if (i == currenttrack)
1404 status.insert(
"currentsubtitletrack", list[i]);
1405 tracks.insert(
"SELECTCC708_" + QString::number(i), list[i]);
1412 for (
int i = 0; i < list.size(); i++)
1414 if (i == currenttrack)
1415 status.insert(
"currentsubtitletrack", list[i]);
1416 tracks.insert(
"SELECTCC608_" + QString::number(i), list[i]);
1423 for (
int i = 0; i < list.size(); i++)
1425 if (i == currenttrack)
1426 status.insert(
"currentsubtitletrack", list[i]);
1427 tracks.insert(
"SELECTRAWTEXT_" + QString::number(i), list[i]);
1433 status.insert(
"currentsubtitletrack", tr(
"External Subtitles"));
1437 status.insert(
"totalsubtitletracks", tracks.size());
1438 if (!tracks.isEmpty())
1439 status.insert(
"subtitletracks", tracks);
1444 for (
int i = 0; i < list.size(); i++)
1446 if (i == currenttrack)
1447 status.insert(
"currentaudiotrack", list[i]);
1448 tracks.insert(
"SELECTAUDIO_" + QString::number(i), list[i]);
1451 status.insert(
"totalaudiotracks", tracks.size());
1452 if (!tracks.isEmpty())
1453 status.insert(
"audiotracks", tracks);
1477 for (
auto tit =info.
text.cbegin(); tit != info.
text.cend(); ++tit)
1478 status.insert(tit.key(), tit.value());
1480 QHashIterator<QString,int> vit(info.
values);
1481 while (vit.hasNext())
1484 status.insert(vit.key(), vit.value());
1512 LOG(VB_GENERAL, LOG_INFO, QString(
"Using Idle Timer. %1 minutes")
1534 else if (!Selection.empty())
1536 for (
const auto & ci : Selection)
1538 uint chanid = ci.m_chanId;
1539 QString channum = ci.m_chanNum;
1540 if (!chanid || channum.isEmpty())
1544 if (chanid && !channum.isEmpty() && !cards.isEmpty())
1582 if (!info->GetChanID())
1589 QString key = info->MakeUniqueKey();
1594 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"AskAllowRecording -- " +
1595 QString(
"adding '%1'").arg(info->m_title));
1603 LOG(VB_GENERAL, LOG_INFO,
LOC +
"-- " +
1604 QString(
"removing '%1'").arg(info->GetTitle()));
1608 delete (*it).m_info;
1625 QString single_rec = tr(
"MythTV wants to record \"%1\" on %2 in %d seconds. Do you want to:");
1627 QString record_watch = tr(
"Record and watch while it records");
1628 QString let_record1 = tr(
"Let it record and go back to the Main Menu");
1629 QString let_recordm = tr(
"Let them record and go back to the Main Menu");
1630 QString record_later1 = tr(
"Record it later, I want to watch TV");
1631 QString record_laterm = tr(
"Record them later, I want to watch TV");
1632 QString do_not_record1= tr(
"Don't let it record, I want to watch TV");
1633 QString do_not_recordm= tr(
"Don't let them record, I want to watch TV");
1638 QMap<QString,AskProgramInfo>::iterator next = it;
1642 if ((*it).m_expiry <= timeNow)
1645 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"-- " +
1646 QString(
"removing '%1'").arg((*it).m_info->m_title));
1648 delete (*it).m_info;
1653 std::chrono::milliseconds timeuntil = 0ms;
1660 (*it).m_isInSameInputGroup = (*it).m_isConflicting =
true;
1665 bool busy_input_grps_loaded =
false;
1666 vector<uint> busy_input_grps;
1673 (*it).m_isInSameInputGroup =
1674 (cardid == (*it).m_info->GetInputID());
1676 if ((*it).m_isInSameInputGroup)
1680 if (!busy_input_grps_loaded)
1683 busy_input_grps_loaded =
true;
1686 vector<uint> input_grps =
1689 for (
uint grp : input_grps)
1691 if (
find(busy_input_grps.begin(), busy_input_grps.end(),
1692 grp) != busy_input_grps.end())
1694 (*it).m_isInSameInputGroup =
true;
1704 if (!(*it).m_isInSameInputGroup)
1705 (*it).m_isConflicting =
false;
1706 else if (cardid == (*it).m_info->GetInputID())
1707 (*it).m_isConflicting =
true;
1709 (*it).m_isConflicting =
true;
1711 (busy_input.
m_mplexId == (*it).m_info->QueryMplexID())) ||
1713 (busy_input.
m_chanId == (*it).m_info->GetChanID())))
1714 (*it).m_isConflicting =
false;
1716 (*it).m_isConflicting =
true;
1718 conflict_count += (*it).m_isConflicting ? 1 : 0;
1725 if (conflict_count == 0)
1727 LOG(VB_GENERAL, LOG_INFO,
LOC +
"The scheduler wants to make "
1728 "a non-conflicting recording.");
1732 else if (conflict_count == 1 && ((*it).m_info->GetInputID() == cardid))
1735 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"UpdateOSDAskAllowDialog -- " +
1743 .replace(
"<num>", (*it).m_info->GetChanNum())
1744 .replace(
"<sign>", (*it).m_info->GetChannelSchedulingID())
1745 .replace(
"<name>", (*it).m_info->GetChannelName());
1747 message = single_rec.arg((*it).m_info->GetTitle()).arg(channel);
1752 dialog.m_buttons.push_back({ record_watch,
"DIALOG_ASKALLOW_WATCH_0",
false, !((*it).m_hasRec)} );
1753 dialog.m_buttons.push_back({ let_record1,
"DIALOG_ASKALLOW_EXIT_0" });
1754 dialog.m_buttons.push_back({ ((*it).m_hasLater) ? record_later1 : do_not_record1,
1755 "DIALOG_ASKALLOW_CANCELRECORDING_0",
false, ((*it).m_hasRec) });
1760 if (conflict_count > 1)
1763 "MythTV wants to record these programs in %d seconds:");
1767 bool has_rec =
false;
1770 if (!(*it).m_isConflicting)
1773 QString title = (*it).m_info->GetTitle();
1774 if ((title.length() < 10) && !(*it).m_info->GetSubtitle().isEmpty())
1775 title +=
": " + (*it).m_info->GetSubtitle();
1776 if (title.length() > 20)
1777 title = title.left(17) +
"...";
1781 .replace(
"<num>", (*it).m_info->GetChanNum())
1782 .replace(
"<sign>", (*it).m_info->GetChannelSchedulingID())
1783 .replace(
"<name>", (*it).m_info->GetChannelName());
1785 if (conflict_count > 1)
1787 message += tr(
"\"%1\" on %2").arg(title).arg(channel);
1792 message = single_rec.arg((*it).m_info->GetTitle()).arg(channel);
1793 has_rec = (*it).m_hasRec;
1797 if (conflict_count > 1)
1800 message += tr(
"Do you want to:");
1803 bool all_have_later =
true;
1804 timeuntil = 9999999ms;
1807 if ((*it).m_isConflicting)
1809 all_have_later &= (*it).m_hasLater;
1814 timeuntil = (9999999ms == timeuntil) ? 0ms : timeuntil;
1816 if (conflict_count > 1)
1820 { let_recordm,
"DIALOG_ASKALLOW_EXIT_0",
false,
true },
1821 { all_have_later ? record_laterm : do_not_recordm,
"DIALOG_ASKALLOW_CANCELCONFLICTING_0" }
1828 { let_record1,
"DIALOG_ASKALLOW_EXIT_0",
false, !has_rec},
1829 { all_have_later ? record_later1 : do_not_record1,
"DIALOG_ASKALLOW_CANCELRECORDING_0",
false, has_rec}
1842 LOG(VB_GENERAL, LOG_ERR,
"allowrecordingbox : askAllowLock is locked");
1846 if (
Action ==
"CANCELRECORDING")
1851 else if (
Action ==
"CANCELCONFLICTING")
1855 if (pgm.m_isConflicting)
1859 else if (
Action ==
"WATCH")
1922 #define TRANSITION(ASTATE,BSTATE) ((ctxState == (ASTATE)) && (desiredNextState == (BSTATE)))
1924 #define SET_NEXT() do { nextState = desiredNextState; changed = true; } while(false)
1925 #define SET_LAST() do { nextState = ctxState; changed = true; } while(false)
1929 QByteArray msg_arr = msg.toLatin1();
1930 QString msg_i18n = TV::tr(msg_arr.constData());
1931 QByteArray msg_i18n_arr = msg_i18n.toLatin1();
1932 return (msg_arr == msg_i18n_arr) ? msg_i18n : msg;
1947 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Called after fatal error detected.");
1951 bool changed =
false;
1957 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Warning, called with no state to change to.");
1965 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Attempting to change from %1 to %2")
1970 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Attempting to set to an error state!");
1995 QString channum =
"";
1999 QStringList reclist;
2002 query.
prepare(
"SELECT channum FROM channel "
2003 "WHERE chanid = :CHANID");
2006 channum = query.
value(0).toString();
2008 channum = QString::number(chanid);
2011 QString::number(chanid));
2016 if (!reclist.empty())
2031 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Spawning LiveTV Recorder -- begin");
2033 if (chanid && !channum.isEmpty())
2038 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Spawning LiveTV Recorder -- end");
2042 LOG(VB_GENERAL, LOG_ERR,
LOC +
"LiveTV not successfully started");
2056 LOG(VB_GENERAL, LOG_INFO,
LOC +
2057 QString(
"playbackURL(%1) inputtype(%2)")
2062 playbackURL,
false,
true,
2076 LOG(VB_GENERAL, LOG_ERR,
LOC +
"LiveTV not successfully started");
2130 LOG(VB_GENERAL, LOG_ERR,
LOC +
2131 "Couldn't find recorder for in-progress recording");
2150 QString message =
"COMMFLAG_REQUEST ";
2165 TV::tr(
"TV Player" ),
2192 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Unknown state transition: %1 to %2")
2197 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Changing from %1 to %2")
2208 LOG(VB_GENERAL, LOG_INFO,
LOC +
"State is LiveTV");
2210 LOG(VB_GENERAL, LOG_INFO,
LOC +
"UpdateOSDInput done");
2212 LOG(VB_GENERAL, LOG_INFO,
LOC +
"UpdateLCD done");
2214 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ITVRestart done");
2220 QString msg = tr(
"%1 Settings")
2273 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Main UI disabled.");
2276 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
" -- end");
2291 MaxWait = (MaxWait <= 0ms) ? 40s : MaxWait;
2294 bool recording =
false;
2298 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid Remote Encoder");
2306 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Lost contact with backend");
2310 std::this_thread::sleep_for(5us);
2316 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Timed out waiting for recorder to start");
2320 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Took %1 ms to start recorder.")
2321 .arg(
t.elapsed().count()));
2340 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
2354 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Stopping ring buffer");
2365 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"stopping recorder");
2370 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
2375 const int timer_id =
Event->timerId();
2383 bool handled =
true;
2444 if (!netCmd.isEmpty())
2469 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
"Last Program File does not exist");
2586 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Unknown timer: %1").arg(timer_id));
2596 QString lcd_time_string;
2597 bool showProgress =
true;
2614 lcd_time_string = info.
text[
"playedtime"] +
" / " + info.
text[
"totaltime"];
2616 if (lcd_time_string.length() >
static_cast<int>(lcd->
getLCDWidth()))
2617 lcd_time_string.remove(
' ');
2647 int timer = startTimer(Interval);
2649 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to start timer on line %1 of %2").arg(Line).arg(__FILE__));
2666 auto StateChange = [&]()
2684 QTimer::singleShot(0,
this, StateChange);
2689 auto InputChange = [&]()
2701 QTimer::singleShot(0,
this, InputChange);
2713 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Switching to program: %1")
2732 bool allow_set_before_end =
2740 bool allow_clear_at_end =
2751 bool clear_lastplaypos =
false;
2752 if (at_end && allow_clear_at_end)
2757 clear_lastplaypos =
true;
2759 else if (!at_end && allow_set_before_end)
2795 bool is_playing =
false;
2880 bool restartTimer =
false;
2886 restartTimer =
true;
2890 LOG(VB_CHANNEL, LOG_INFO,
"REC_PROGRAM -- channel change");
2934 if ((
Event->type() == QEvent::Resize))
2940 if ( (QEvent::KeyPress ==
Event->type() || QEvent::KeyRelease ==
Event->type())
2942 return TVPlaybackState::eventFilter(Object,
Event);
2944 QScopedPointer<QEvent> sNewEvent(
nullptr);
2948 if (QEvent::KeyPress ==
Event->type())
2963 switch (
Event->type())
2966 case QEvent::UpdateRequest:
2970 return TVPlaybackState::eventFilter(Object,
Event);
2973 return TVPlaybackState::eventFilter(Object,
Event);
2980 if (
Event ==
nullptr)
2981 return TVPlaybackState::event(
Event);
2983 if (QEvent::Resize ==
Event->type())
2985 const auto *qre =
dynamic_cast<const QResizeEvent*
>(
Event);
2988 return TVPlaybackState::event(
Event);
2994 if (QEvent::KeyPress ==
Event->type())
2996 const auto * ke =
dynamic_cast<QKeyEvent*
>(
Event);
2999 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"keypress: %1 '%2'")
3000 .arg(ke->key()).arg(ke->text()));
3008 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"mythgesture: g:%1 pos:%2,%3 b:%4")
3009 .arg(ge->GetGesture()).arg(ge->GetPosition().x())
3010 .arg(ge->GetPosition().y()).arg(ge->GetButton()));
3014 bool handled =
false;
3023 switch (
Event->type())
3026 case QEvent::UpdateRequest:
3033 return QObject::event(
Event);
3038 bool handled =
true;
3093 else if (
Action.startsWith(
"TOGGLE"))
3103 else if (
Action.startsWith(
"SELECT"))
3112 else if (
Action.startsWith(
"NEXT") ||
Action.startsWith(
"PREV"))
3114 int dir = (
Action.startsWith(
"NEXT")) ? +1 : -1;
3118 else if (
Action.endsWith(
"CC"))
3141 QStringList::const_iterator it;
3142 for (it = actions.begin(); it != actions.end(); ++it)
3144 if ((*it).startsWith(
"SYSEVENT") ||
3157 QList<QKeyEvent*> keyPressList;
3159 QStringList stringKeyList = KeyList.split(
',');
3160 for (
const auto & str : qAsConst(stringKeyList))
3162 QKeySequence keySequence(str);
3163 for(i = 0; i < keySequence.count(); i++)
3165 uint keynum =
static_cast<uint>(keySequence[
static_cast<uint>(i)]);
3166 auto * keyEvent =
new QKeyEvent(QEvent::None, keynum & ~Qt::KeyboardModifierMask,
3167 static_cast<Qt::KeyboardModifiers
>(keynum & Qt::KeyboardModifierMask));
3168 keyPressList.append(keyEvent);
3176 auto * keyEvent =
new QKeyEvent(QEvent::None, Qt::Key_Escape, Qt::NoModifier);
3177 keyPressList.append(keyEvent);
3180 return keyPressList;
3184 QStringList &Actions,
bool IsLiveTV)
3186 if (
Event && Context ==
"TV Playback")
3193 (
Event->GetButton() == Qt::LeftButton))
3197 QPoint pos =
Event->GetPosition();
3199 const int widthDivider = 4;
3200 int w4 = size.width() / widthDivider;
3201 region = pos.x() / w4;
3202 int h3 = size.height() / 3;
3203 region += (pos.y() / h3) * widthDivider;
3215 QStringList &Actions,
bool IsLiveTV,
bool AllowJumps)
3219 if (QEvent::KeyPress ==
Event->type())
3229 if (
Event ==
nullptr)
3235 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"ignoreKeys: %1").arg(ignoreKeys));
3246 auto* eKeyEvent =
dynamic_cast<QKeyEvent*
>(
Event);
3248 if (eKeyEvent->key() <= 0)
3251 switch(eKeyEvent->nativeScanCode())
3254 keycode = Qt::Key_MediaPause;
3262 auto *key =
new QKeyEvent(QEvent::KeyPress, keycode, eKeyEvent->modifiers());
3263 QCoreApplication::postEvent(
this, key);
3269 QStringList actions;
3270 bool handled =
false;
3271 bool alreadyTranslatedPlayback =
false;
3279 alreadyTranslatedPlayback =
true;
3281 if (handled || actions.isEmpty())
3284 bool esc =
IsActionable({
"ESCAPE",
"BACK" }, actions);
3295 if (QEvent::KeyPress ==
Event->type())
3297 auto *qke =
dynamic_cast<QKeyEvent*
>(
Event);
3355 if (QEvent::KeyPress ==
Event->type())
3357 auto *qke =
dynamic_cast<QKeyEvent*
>(
Event);
3360 const QString txt = qke->text();
3364 (void)txt.toInt(&ok, 16);
3365 if (ok || txt==
"_" || txt==
"-" || txt==
"#" || txt==
".")
3376 QStringList tt_actions;
3379 if (!handled && !tt_actions.isEmpty())
3381 for (
int i = 0; i < tt_actions.size(); i++)
3393 if (!alreadyTranslatedPlayback)
3396 alreadyTranslatedPlayback =
true;
3399 if (!handled && !actions.isEmpty())
3401 for (
int i = 0; i < actions.size(); i++)
3410 if (!alreadyTranslatedPlayback)
3413 if (handled || actions.isEmpty())
3421 if (QEvent::KeyPress ==
Event->type())
3437 for (
int i = 0; i < actions.size(); ++i)
3438 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"handled(%1) actions[%2](%3)")
3439 .arg(handled).arg(i).arg(actions[i]));
3440 #endif // DEBUG_ACTIONS
3447 for (
int i = 0; i < actions.size() && !handled; i++)
3449 QString
action = actions[i];
3451 int val =
action.toInt(&ok);
3469 bool handled =
true;
3490 for (
const auto&
action : qAsConst(Actions))
3501 static const QStringList passthrough =
3504 ACTION_MUTEAUDIO,
"CYCLEAUDIOCHAN",
"BOTTOMLINEMOVE",
"BOTTOMLINESAVE",
"TOGGLEASPECT"
3514 bool endmanualzoom =
false;
3515 bool handled =
true;
3516 bool updateOSD =
true;
3545 endmanualzoom =
true;
3549 endmanualzoom =
true;
3556 static const QStringList passthrough =
3564 QString msg = tr(
"Zoom Committed");
3568 msg = endmanualzoom ? tr(
"Zoom Ignored") :
3573 else if (endmanualzoom)
3620 bool handled =
true;
3645 bool handled =
true;
3668 bool handled =
true;
3691 bool handled =
true;
3726 bool IsDVD,
bool IsDVDStillFrame)
3728 bool handled =
true;
3732 else if (
IsActionable(
"SKIPCOMMBACK", Actions) && !IsDVD)
3734 else if (
IsActionable(
"QUEUETRANSCODE", Actions) && !IsDVD)
3736 else if (
IsActionable(
"QUEUETRANSCODE_AUTO", Actions) && !IsDVD)
3738 else if (
IsActionable(
"QUEUETRANSCODE_HIGH", Actions) && !IsDVD)
3740 else if (
IsActionable(
"QUEUETRANSCODE_MEDIUM", Actions) && !IsDVD)
3742 else if (
IsActionable(
"QUEUETRANSCODE_LOW", Actions) && !IsDVD)
3748 else if (
IsActionable(
"SPEEDINC", Actions) && !IsDVDStillFrame)
3750 else if (
IsActionable(
"SPEEDDEC", Actions) && !IsDVDStillFrame)
3754 else if (
IsActionable(
"CYCLECOMMSKIPMODE",Actions) && !IsDVD)
3810 DoSeek(0, tr(
"Jump to Beginning"),
false,
true);
3834 std::chrono::milliseconds rate =
m_sigMonMode ? 0ms : 100ms;
3869 bool visible =
false;
3935 else if (
IsActionable({
"INFO",
"INFOWITHCUTLIST" }, Actions))
3950 for (
auto it = Actions.cbegin(); it != Actions.cend() && !handled; ++it)
3959 bool handled =
false;
3963 for (
int i = 0; i < Actions.size() && !handled; i++)
3965 QString
action = Actions[i];
3967 int val =
action.toInt(&ok);
3996 bool handled =
true;
4075 info.
text[
"title"] = tr(
"Position");
4083 bool handled =
true;
4109 else if (
IsActionable(
"NEXTSOURCE", Actions) && islivetv)
4111 else if (
IsActionable(
"PREVSOURCE", Actions) && islivetv)
4113 else if (
IsActionable(
"NEXTINPUT", Actions) && islivetv)
4117 else if (
IsActionable(
"PREVCHAN", Actions) && islivetv)
4171 #ifdef DEBUG_ACTIONS
4172 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"(%1) ignoreKeys: %2").arg(
Command).arg(ignoreKeys));
4177 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Ignoring network control command because ignoreKeys is set");
4181 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
4182 QStringList tokens =
Command.split(
" ", QString::SkipEmptyParts);
4184 QStringList tokens =
Command.split(
" ", Qt::SkipEmptyParts);
4186 if (tokens.size() < 2)
4188 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Not enough tokens in network control command " + QString(
"'%1'").arg(
Command));
4200 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4201 "Ignoring network control command\n\t\t\t" +
4202 QString(
"because dialog is waiting for a response"));
4206 if (tokens[1] !=
"QUERY")
4209 if (tokens.size() == 3 && tokens[1] ==
"CHANID")
4215 else if (tokens.size() == 3 && tokens[1] ==
"CHANNEL")
4219 if (tokens[2] ==
"UP")
4221 else if (tokens[2] ==
"DOWN")
4223 else if (tokens[2].contains(QRegularExpression(R
"(^[-\.\d_#]+$)")))
4227 else if (tokens.size() == 3 && tokens[1] ==
"SPEED")
4231 if (tokens[2] ==
"0x")
4238 else if (tokens[2] ==
"normal")
4248 float tmpSpeed = 1.0F;
4251 if (tokens[2].contains(QRegularExpression(R
"(^\-*(\d*\.)?\d+x$)")))
4253 QString speed = tokens[2].left(tokens[2].length()-1);
4254 tmpSpeed = speed.toFloat(&ok);
4258 QRegularExpression re { R
"(^(\-*\d+)\/(\d+)x$)" };
4259 auto match = re.match(tokens[2]);
4260 if (match.hasMatch())
4262 QStringList matches = match.capturedTexts();
4263 int numerator = matches[1].toInt(&ok);
4264 int denominator = matches[2].toInt(&ok);
4266 if (ok && denominator != 0)
4267 tmpSpeed =
static_cast<float>(numerator) /
static_cast<float>(denominator);
4275 float searchSpeed = fabs(tmpSpeed);
4280 if (tmpSpeed == 0.0F)
4288 else if (tmpSpeed == 1.0F)
4307 else if (tmpSpeed > 1)
4315 else if (0.48F <= tmpSpeed && tmpSpeed <= 2.0F)
4323 LOG(VB_GENERAL, LOG_WARNING, QString(
"Couldn't find %1 speed. Setting Speed to 1x")
4324 .arg(
static_cast<double>(searchSpeed)));
4331 LOG(VB_GENERAL, LOG_ERR, QString(
"Found an unknown speed of %1").arg(tokens[2]));
4335 else if (tokens.size() == 2 && tokens[1] ==
"STOP")
4349 if (tokens[2] ==
"BEGINNING")
4351 DoSeek(0, tr(
"Jump to Beginning"),
false,
true);
4353 else if (tokens[2] ==
"FORWARD")
4357 else if (tokens[2] ==
"BACKWARD")
4361 else if ((tokens[2] ==
"POSITION" ||
4362 tokens[2] ==
"POSITIONWITHCUTLIST") &&
4363 (tokens.size() == 4) &&
4364 (tokens[3].contains(QRegularExpression(
"^\\d+$"))))
4366 DoSeekAbsolute(tokens[3].toInt(), tokens[2] ==
"POSITIONWITHCUTLIST");
4369 else if (tokens.size() >= 3 && tokens[1] ==
"SUBTITLES")
4372 uint track = tokens[2].toUInt(&ok);
4384 uint size =
static_cast<uint>(subs.size());
4387 if (track >=
start && track < finish)
4396 finish =
start + size;
4397 if (track >=
start && track < finish)
4406 finish =
start + size;
4407 if (track >=
start && track < finish)
4416 finish =
start + size;
4417 if (track >=
start && track < finish)
4426 finish =
start + size;
4427 if (track >=
start && track < finish)
4436 finish =
start + size;
4437 if (track >=
start && track < finish)
4445 else if (tokens.size() >= 3 && tokens[1] ==
"VOLUME")
4447 QRegularExpression re {
"(\\d+)%?" };
4448 auto match = re.match(tokens[2]);
4449 if (match.hasMatch())
4451 QStringList matches = match.capturedTexts();
4453 LOG(VB_GENERAL, LOG_INFO, QString(
"Set Volume to %1%").arg(matches[1]));
4456 int vol = matches[1].toInt(&ok);
4460 if (0 <= vol && vol <= 100)
4464 else if (tokens.size() >= 3 && tokens[1] ==
"QUERY")
4466 if (tokens[2] ==
"POSITION")
4481 QRegularExpression re {
"Play (.*)x" };
4483 if (match.hasMatch())
4485 QStringList matches = match.capturedTexts();
4486 speedStr = QString(
"%1x").arg(matches[1]);
4498 QString infoStr =
"";
4522 infoStr =
"Recorded";
4530 QString bufferFilename =
4532 if ((infoStr ==
"Recorded") || (infoStr ==
"LiveTV"))
4534 infoStr += QString(
" %1 %2 %3 %4 %5 %6 %7")
4535 .arg(info.
text[
"description"])
4541 .arg(bufferFilename)
4546 QString position = info.
text[
"description"].section(
" ",0,0);
4547 infoStr += QString(
" %1 %2 %3 %4 %5")
4550 .arg(bufferFilename)
4555 infoStr += QString(
" Subtitles:");
4560 infoStr += QString(
" *0:[None]*");
4562 infoStr += QString(
" 0:[None]");
4567 for (
int i = 0; i < subs.size(); i++)
4570 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4572 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4577 for (
int i = 0; i < subs.size(); i++)
4580 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4582 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4587 for (
int i = 0; i < subs.size(); i++)
4590 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4592 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4597 for (
int i = 0; i < subs.size(); i++)
4600 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4602 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4607 for (
int i = 0; i < subs.size(); i++)
4610 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4612 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4617 for (
int i = 0; i < subs.size(); i++)
4620 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4622 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4628 QString message = QString(
"NETWORK_CONTROL ANSWER %1").arg(infoStr);
4632 else if (tokens[2] ==
"VOLUME")
4635 QString message = QString(
"NETWORK_CONTROL ANSWER %1").arg(infoStr);
4644 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"(%1) -- begin").arg(
StateToString(desiredState)));
4651 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Created player."));
4656 LOG(VB_GENERAL, LOG_CRIT,
LOC + QString(
"Failed to create player."));
4659 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"(%1) -- end %2")
4660 .arg(
StateToString(desiredState)).arg((ok) ?
"ok" :
"error"));
4765 bool paused =
false;
4787 bool ignore =
false;
4788 bool paused =
false;
4813 if (Time > -0.001F && Time < +0.001F)
4816 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1 seconds").arg(
static_cast<double>(Time)));
4837 else if (Time < 0.0F)
4849 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1").arg(FrameNum));
4875 const int kRewind = 4;
4876 const int kForward = 8;
4877 const int kSticky = 16;
4878 const int kSlippery = 32;
4879 const int kRelative = 64;
4880 const int kAbsolute = 128;
4881 const int kIgnoreCutlist = 256;
4882 const int kWhenceMask = 3;
4887 flags =
ARBSEEK_END | kForward | kSticky | kAbsolute;
4893 flags =
ARBSEEK_SET | kRewind | kSticky | kAbsolute;
4899 int direction = (flags & kRewind) ? -1 : 1;
4908 QString message = (flags & kRewind) ? tr(
"Rewind") :
4910 if (flags & kAbsolute)
4912 float time = direction;
4913 DoSeek(time, message,
true, (flags & kIgnoreCutlist) == 0);
4920 uint64_t targetRel = frameRel +
static_cast<uint64_t
>(direction);
4921 if (frameRel == 0 && direction < 0)
4925 if (targetRel > maxRel)
4934 else if (flags & kSticky)
4938 else if (flags & kRewind)
4958 void TV::DoSeek(
float Time,
const QString &Msg,
bool TimeIsOffset,
bool HonorCutlist)
4963 bool limitkeys =
false;
5003 DoSeek(Seconds, tr(
"Jump To"),
false, HonorCutlist);
5015 int64_t time = (int(seek / 100) * 3600) + ((seek % 100) * 60);
5019 DoSeek(time, tr(
"Jump Ahead"),
true, HonorCutlist);
5023 DoSeek(-time, tr(
"Jump Back"),
true, HonorCutlist);
5036 DoSeek(std::max(0.0F, dur -
static_cast<float>(time)), tr(
"Jump To"),
false, HonorCutlist);
5074 case 4: speed = 16.0F; mesg = tr(
"Speed 16X");
break;
5075 case 3: speed = 8.0F; mesg = tr(
"Speed 8X");
break;
5076 case 2: speed = 3.0F; mesg = tr(
"Speed 3X");
break;
5077 case 1: speed = 2.0F; mesg = tr(
"Speed 2X");
break;
5079 case -1: speed = 1.0F / 3; mesg = tr(
"Speed 1/3X");
break;
5080 case -2: speed = 1.0F / 8; mesg = tr(
"Speed 1/8X");
break;
5081 case -3: speed = 1.0F / 16; mesg = tr(
"Speed 1/16X");
break;
5168 auto index =
static_cast<size_t>(Index);