2 #include <QApplication>
3 #include <QDomDocument>
10 #include <QRegularExpression>
12 #include <QTimerEvent>
15 #include "mythconfig.h"
80 #define round(x) ((int) ((x) + 0.5))
83 #define DEBUG_CHANNEL_PREFIX 0
84 #define DEBUG_ACTIONS 0
86 #define LOC QString("TV::%1(): ").arg(__func__)
88 #define HideOSDWindow(WINDOW) { \
89 OSD *osd = GetOSDL(); \
91 osd->HideWindow(WINDOW); \
113 #ifdef USING_VALGRIND
159 query.
prepare(
"SELECT COUNT(cardid) FROM capturecard;");
163 LOG(VB_RECORD, LOG_INFO,
164 "ConfiguredTunerCards() = " + QString::number(count));
178 static QMutex s_lock;
179 static TV* s_tv =
nullptr;
180 QMutexLocker locker(&s_lock);
192 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Ref count error");
238 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Already have a player");
244 auto flags =
static_cast<PlayerFlags>(playerflags);
277 LOG(VB_GENERAL, LOG_ERR,
LOC +
"StartPlaying() Failed to start player");
282 MaxWait = (MaxWait <= 0) ? 20000 : MaxWait;
283 #ifdef USING_VALGRIND
285 #endif // USING_VALGRIND
294 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
295 QString(
"StartPlaying(): took %1 ms to start player.")
299 LOG(VB_GENERAL, LOG_ERR,
LOC +
"StartPlaying() Failed to start player");
331 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Already have a TV object.");
336 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
339 bool quitAll =
false;
340 bool showDialogs =
true;
341 bool playCompleted =
false;
343 bool startSysEventSent =
false;
344 bool startLivetvEventSent =
false;
357 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed initializing TV");
379 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->Playback() -- begin");
384 else if (!startSysEventSent)
386 startSysEventSent =
true;
390 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->Playback() -- end");
394 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->LiveTV() -- begin");
395 if (!tv->
LiveTV(showDialogs, Selection))
400 else if (!startSysEventSent)
402 startSysEventSent =
true;
403 startLivetvEventSent =
true;
407 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"tv->LiveTV() -- end");
412 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No tuners configured");
414 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No tuners free for live tv");
425 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Entering main playback loop.");
427 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Exiting main playback loop.");
435 curProgram = nextProgram;
449 quitAll |= !playerError.isEmpty();
452 QCoreApplication::processEvents();
456 playCompleted =
true;
466 if (startSysEventSent)
474 list.push_back(allowrerecord ?
"1" :
"0");
475 MythEvent me(
"LOCAL_PBB_DELETE_RECORDINGS", list);
486 else if (startSysEventSent)
489 if (!playerError.isEmpty())
499 if (startLivetvEventSent)
502 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
504 return playCompleted;
514 if (name ==
"playbackbox")
516 else if (name ==
"viewscheduled")
518 else if (name ==
"programguide")
520 else if (name ==
"programfinder")
522 else if (name ==
"scheduleeditor")
529 "Play Program"),
"P");
531 "Stop Program"),
"");
533 "Toggle recording status of current program"),
"R");
535 "Page the program guide back one day"),
"Home");
537 "Page the program guide forward one day"),
"End");
539 "Page the program guide left"),
",,<");
541 "Page the program guide right"),
">,.");
543 "Toggle the current channel as a favorite"),
"?");
545 "Reverse the channel order in the program guide"),
"");
547 "Show the Program Guide"),
"S");
549 "Show the Program Finder"),
"#");
551 "Show the Channel Search"),
"");
552 REG_KEY(
"TV Frontend",
"NEXTFAV", QT_TRANSLATE_NOOP(
"MythControls",
553 "Cycle through channel groups and all channels in the "
554 "program guide."),
"/");
555 REG_KEY(
"TV Frontend",
"CHANUPDATE", QT_TRANSLATE_NOOP(
"MythControls",
556 "Switch channels without exiting guide in Live TV mode."),
"X");
558 "Volume down"),
"[,{,F10,Volume Down");
560 "Volume up"),
"],},F11,Volume Up");
562 "Mute"),
"|,\\,F9,Volume Mute");
563 REG_KEY(
"TV Frontend",
"CYCLEAUDIOCHAN", QT_TRANSLATE_NOOP(
"MythControls",
564 "Cycle audio channels"),
"");
565 REG_KEY(
"TV Frontend",
"RANKINC", QT_TRANSLATE_NOOP(
"MythControls",
566 "Increase program or channel rank"),
"Right");
567 REG_KEY(
"TV Frontend",
"RANKDEC", QT_TRANSLATE_NOOP(
"MythControls",
568 "Decrease program or channel rank"),
"Left");
569 REG_KEY(
"TV Frontend",
"UPCOMING", QT_TRANSLATE_NOOP(
"MythControls",
570 "List upcoming episodes"),
"O");
572 "List scheduled upcoming episodes"),
"");
574 "List previously recorded episodes"),
"");
575 REG_KEY(
"TV Frontend",
"DETAILS", QT_TRANSLATE_NOOP(
"MythControls",
576 "Show details"),
"U");
577 REG_KEY(
"TV Frontend",
"VIEWINPUT", QT_TRANSLATE_NOOP(
"MythControls",
578 "Switch Recording Input view"),
"C");
579 REG_KEY(
"TV Frontend",
"CUSTOMEDIT", QT_TRANSLATE_NOOP(
"MythControls",
580 "Edit Custom Record Rule"),
"");
581 REG_KEY(
"TV Frontend",
"CHANGERECGROUP", QT_TRANSLATE_NOOP(
"MythControls",
582 "Change Recording Group"),
"");
583 REG_KEY(
"TV Frontend",
"CHANGEGROUPVIEW", QT_TRANSLATE_NOOP(
"MythControls",
584 "Change Group View"),
"");
586 "List recorded episodes"),
"");
606 if (selectKeys !=
"?")
609 togBkmKeys = selectKeys;
611 bkmKeys = selectKeys;
615 "Add Bookmark"), bkmKeys);
617 "Toggle Bookmark"), togBkmKeys);
618 REG_KEY(
"TV Playback",
"BACK", QT_TRANSLATE_NOOP(
"MythControls",
619 "Exit or return to DVD menu"),
"Esc");
621 "Playback Compact Menu"),
"Alt+M");
623 "Clear OSD"),
"Backspace");
625 "Pause"),
"P,Space");
627 "Fast Forward"),
"Right");
631 "Arbitrary Seek"),
"*");
633 "Seek to a position in seconds"),
"");
635 "Channel up"),
"Up");
637 "Channel down"),
"Down");
638 REG_KEY(
"TV Playback",
"NEXTFAV", QT_TRANSLATE_NOOP(
"MythControls",
639 "Switch to the next favorite channel"),
"/");
640 REG_KEY(
"TV Playback",
"PREVCHAN", QT_TRANSLATE_NOOP(
"MythControls",
641 "Switch to the previous channel"),
"H");
643 "Jump ahead"),
"PgDown");
645 "Jump back"),
"PgUp");
646 REG_KEY(
"TV Playback",
"INFOWITHCUTLIST", QT_TRANSLATE_NOOP(
"MythControls",
647 "Info utilizing cutlist"),
"");
649 "Jump to bookmark"),
"K");
650 REG_KEY(
"TV Playback",
"FFWDSTICKY", QT_TRANSLATE_NOOP(
"MythControls",
651 "Fast Forward (Sticky) or Forward one second while paused"),
">,.");
652 REG_KEY(
"TV Playback",
"RWNDSTICKY", QT_TRANSLATE_NOOP(
"MythControls",
653 "Rewind (Sticky) or Rewind one second while paused"),
",,<");
654 REG_KEY(
"TV Playback",
"NEXTSOURCE", QT_TRANSLATE_NOOP(
"MythControls",
655 "Next Video Source"),
"Y");
656 REG_KEY(
"TV Playback",
"PREVSOURCE", QT_TRANSLATE_NOOP(
"MythControls",
657 "Previous Video Source"),
"");
658 REG_KEY(
"TV Playback",
"NEXTINPUT", QT_TRANSLATE_NOOP(
"MythControls",
660 REG_KEY(
"TV Playback",
"NEXTCARD", QT_TRANSLATE_NOOP(
"MythControls",
662 REG_KEY(
"TV Playback",
"SKIPCOMMERCIAL", QT_TRANSLATE_NOOP(
"MythControls",
663 "Skip Commercial"),
"Z,End");
664 REG_KEY(
"TV Playback",
"SKIPCOMMBACK", QT_TRANSLATE_NOOP(
"MythControls",
665 "Skip Commercial (Reverse)"),
"Q,Home");
667 "Jump to the start of the recording."),
"Ctrl+B");
668 REG_KEY(
"TV Playback",
"TOGGLEBROWSE", QT_TRANSLATE_NOOP(
"MythControls",
669 "Toggle channel browse mode"),
"O");
671 "Toggle recording status of current program"),
"R");
673 "Toggle the current channel as a favorite"),
"?");
675 "Volume down"),
"[,{,F10,Volume Down");
677 "Volume up"),
"],},F11,Volume Up");
679 "Mute"),
"|,\\,F9,Volume Mute");
681 "Set the volume"),
"");
682 REG_KEY(
"TV Playback",
"CYCLEAUDIOCHAN", QT_TRANSLATE_NOOP(
"MythControls",
683 "Cycle audio channels"),
"");
685 "Toggle audio upmixer"),
"Ctrl+U");
687 QT_TRANSLATE_NOOP(
"MythControls",
"Move BottomLine off screen"),
"L");
689 QT_TRANSLATE_NOOP(
"MythControls",
"Save manual zoom for BottomLine"),
"");
690 REG_KEY(
"TV Playback",
"TOGGLEASPECT", QT_TRANSLATE_NOOP(
"MythControls",
691 "Toggle the video aspect ratio"),
"Ctrl+W");
692 REG_KEY(
"TV Playback",
"TOGGLEFILL", QT_TRANSLATE_NOOP(
"MythControls",
693 "Next Preconfigured Zoom mode"),
"W");
695 "Toggle any captions"),
"T");
697 "Enable any captions"),
"");
699 "Disable any captions"),
"");
700 REG_KEY(
"TV Playback",
"TOGGLETTC", QT_TRANSLATE_NOOP(
"MythControls",
701 "Toggle Teletext Captions"),
"");
702 REG_KEY(
"TV Playback",
"TOGGLESUBTITLE", QT_TRANSLATE_NOOP(
"MythControls",
703 "Toggle Subtitles"),
"");
704 REG_KEY(
"TV Playback",
"TOGGLECC608", QT_TRANSLATE_NOOP(
"MythControls",
705 "Toggle VBI CC"),
"");
706 REG_KEY(
"TV Playback",
"TOGGLECC708", QT_TRANSLATE_NOOP(
"MythControls",
707 "Toggle ATSC CC"),
"");
708 REG_KEY(
"TV Playback",
"TOGGLETTM", QT_TRANSLATE_NOOP(
"MythControls",
709 "Toggle Teletext Menu"),
"");
711 "Toggle External Subtitles"),
"");
713 "Enable External Subtitles"),
"");
715 "Disable External Subtitles"),
"");
716 REG_KEY(
"TV Playback",
"TOGGLERAWTEXT", QT_TRANSLATE_NOOP(
"MythControls",
717 "Toggle Text Subtitles"),
"");
719 REG_KEY(
"TV Playback",
"SELECTAUDIO_0", QT_TRANSLATE_NOOP(
"MythControls",
720 "Play audio track 1"),
"");
721 REG_KEY(
"TV Playback",
"SELECTAUDIO_1", QT_TRANSLATE_NOOP(
"MythControls",
722 "Play audio track 2"),
"");
723 REG_KEY(
"TV Playback",
"SELECTSUBTITLE_0",QT_TRANSLATE_NOOP(
"MythControls",
724 "Display subtitle 1"),
"");
725 REG_KEY(
"TV Playback",
"SELECTSUBTITLE_1",QT_TRANSLATE_NOOP(
"MythControls",
726 "Display subtitle 2"),
"");
727 REG_KEY(
"TV Playback",
"SELECTRAWTEXT_0",QT_TRANSLATE_NOOP(
"MythControls",
728 "Display Text Subtitle 1"),
"");
729 REG_KEY(
"TV Playback",
"SELECTCC608_0", QT_TRANSLATE_NOOP(
"MythControls",
730 "Display VBI CC1"),
"");
731 REG_KEY(
"TV Playback",
"SELECTCC608_1", QT_TRANSLATE_NOOP(
"MythControls",
732 "Display VBI CC2"),
"");
733 REG_KEY(
"TV Playback",
"SELECTCC608_2", QT_TRANSLATE_NOOP(
"MythControls",
734 "Display VBI CC3"),
"");
735 REG_KEY(
"TV Playback",
"SELECTCC608_3", QT_TRANSLATE_NOOP(
"MythControls",
736 "Display VBI CC4"),
"");
737 REG_KEY(
"TV Playback",
"SELECTCC708_0", QT_TRANSLATE_NOOP(
"MythControls",
738 "Display ATSC CC1"),
"");
739 REG_KEY(
"TV Playback",
"SELECTCC708_1", QT_TRANSLATE_NOOP(
"MythControls",
740 "Display ATSC CC2"),
"");
741 REG_KEY(
"TV Playback",
"SELECTCC708_2", QT_TRANSLATE_NOOP(
"MythControls",
742 "Display ATSC CC3"),
"");
743 REG_KEY(
"TV Playback",
"SELECTCC708_3", QT_TRANSLATE_NOOP(
"MythControls",
744 "Display ATSC CC4"),
"");
746 "Enable Forced Subtitles"),
"");
748 "Disable Forced Subtitles"),
"");
750 REG_KEY(
"TV Playback",
"NEXTAUDIO", QT_TRANSLATE_NOOP(
"MythControls",
751 "Next audio track"),
"+");
752 REG_KEY(
"TV Playback",
"PREVAUDIO", QT_TRANSLATE_NOOP(
"MythControls",
753 "Previous audio track"),
"-");
754 REG_KEY(
"TV Playback",
"NEXTSUBTITLE", QT_TRANSLATE_NOOP(
"MythControls",
755 "Next subtitle track"),
"");
756 REG_KEY(
"TV Playback",
"PREVSUBTITLE", QT_TRANSLATE_NOOP(
"MythControls",
757 "Previous subtitle track"),
"");
758 REG_KEY(
"TV Playback",
"NEXTRAWTEXT", QT_TRANSLATE_NOOP(
"MythControls",
759 "Next Text track"),
"");
760 REG_KEY(
"TV Playback",
"PREVRAWTEXT", QT_TRANSLATE_NOOP(
"MythControls",
761 "Previous Text track"),
"");
762 REG_KEY(
"TV Playback",
"NEXTCC608", QT_TRANSLATE_NOOP(
"MythControls",
763 "Next VBI CC track"),
"");
764 REG_KEY(
"TV Playback",
"PREVCC608", QT_TRANSLATE_NOOP(
"MythControls",
765 "Previous VBI CC track"),
"");
766 REG_KEY(
"TV Playback",
"NEXTCC708", QT_TRANSLATE_NOOP(
"MythControls",
767 "Next ATSC CC track"),
"");
768 REG_KEY(
"TV Playback",
"PREVCC708", QT_TRANSLATE_NOOP(
"MythControls",
769 "Previous ATSC CC track"),
"");
770 REG_KEY(
"TV Playback",
"NEXTCC", QT_TRANSLATE_NOOP(
"MythControls",
771 "Next of any captions"),
"");
773 REG_KEY(
"TV Playback",
"NEXTSCAN", QT_TRANSLATE_NOOP(
"MythControls",
774 "Next video scan overidemode"),
"");
775 REG_KEY(
"TV Playback",
"QUEUETRANSCODE", QT_TRANSLATE_NOOP(
"MythControls",
776 "Queue the current recording for transcoding"),
"X");
777 REG_KEY(
"TV Playback",
"SPEEDINC", QT_TRANSLATE_NOOP(
"MythControls",
778 "Increase the playback speed"),
"U");
779 REG_KEY(
"TV Playback",
"SPEEDDEC", QT_TRANSLATE_NOOP(
"MythControls",
780 "Decrease the playback speed"),
"J");
781 REG_KEY(
"TV Playback",
"ADJUSTSTRETCH", QT_TRANSLATE_NOOP(
"MythControls",
782 "Turn on time stretch control"),
"A");
783 REG_KEY(
"TV Playback",
"STRETCHINC", QT_TRANSLATE_NOOP(
"MythControls",
784 "Increase time stretch speed"),
"");
785 REG_KEY(
"TV Playback",
"STRETCHDEC", QT_TRANSLATE_NOOP(
"MythControls",
786 "Decrease time stretch speed"),
"");
787 REG_KEY(
"TV Playback",
"TOGGLESTRETCH", QT_TRANSLATE_NOOP(
"MythControls",
788 "Toggle time stretch speed"),
"");
790 QT_TRANSLATE_NOOP(
"MythControls",
791 "Turn on audio sync adjustment controls"),
"");
793 QT_TRANSLATE_NOOP(
"MythControls",
794 "Set the audio sync adjustment"),
"");
795 REG_KEY(
"TV Playback",
"TOGGLEPICCONTROLS",
796 QT_TRANSLATE_NOOP(
"MythControls",
"Playback picture adjustments"),
799 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture brightness"),
"");
801 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture contrast"),
"");
803 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture color"),
"");
805 QT_TRANSLATE_NOOP(
"MythControls",
"Set the picture hue"),
"");
807 QT_TRANSLATE_NOOP(
"MythControls",
"Recording picture adjustments "
808 "for this channel"),
"Ctrl+G");
810 QT_TRANSLATE_NOOP(
"MythControls",
"Recording picture adjustments "
811 "for this recorder"),
"G");
812 REG_KEY(
"TV Playback",
"CYCLECOMMSKIPMODE",
813 QT_TRANSLATE_NOOP(
"MythControls",
"Cycle Commercial Skip mode"),
816 "Show the Program Guide"),
"S");
818 "Show the Program Finder"),
"#");
820 "Toggle the Sleep Timer"),
"F8");
824 "Jump to previously played recording"),
"");
826 "Display menu of recorded programs to jump to"),
"");
828 "Display scheduled recording list"),
"");
830 "Display previously recorded episodes"),
"");
832 "Monitor Signal Quality"),
"Alt+F7");
834 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the DVD Root Menu"),
"");
836 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the Popup Menu"),
"");
838 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the DVD Chapter Menu"),
"");
840 QT_TRANSLATE_NOOP(
"MythControls",
"Jump to the DVD Title Menu"),
"");
842 QT_TRANSLATE_NOOP(
"MythControls",
"Exit Show without any prompts"),
845 "Jump to a chapter"),
"");
847 "Switch title"),
"");
849 "Switch angle"),
"");
851 "OSD Navigation"),
"");
853 "Zoom mode - shift up"),
"");
855 "Zoom mode - shift down"),
"");
857 "Zoom mode - shift left"),
"");
859 "Zoom mode - shift right"),
"");
861 QT_TRANSLATE_NOOP(
"MythControls",
862 "Zoom mode - increase aspect ratio"),
"");
864 QT_TRANSLATE_NOOP(
"MythControls",
865 "Zoom mode - decrease aspect ratio"),
"");
867 "Zoom mode - zoom in"),
"");
869 "Zoom mode - zoom out"),
"");
871 QT_TRANSLATE_NOOP(
"MythControls",
872 "Zoom mode - vertical zoom in"),
"8");
874 QT_TRANSLATE_NOOP(
"MythControls",
875 "Zoom mode - vertical zoom out"),
"2");
877 QT_TRANSLATE_NOOP(
"MythControls",
878 "Zoom mode - horizontal zoom in"),
"6");
880 QT_TRANSLATE_NOOP(
"MythControls",
881 "Zoom mode - horizontal zoom out"),
"4");
883 "Zoom mode - quit and abandon changes"),
"");
885 "Zoom mode - commit changes"),
"");
891 "Menu Green"),
"F3");
893 "Menu Yellow"),
"F4");
905 "Clear editing cut points"),
"C,Q,Home");
907 "Invert Begin/End cut points"),
"I");
911 "Load cuts from detected commercials"),
"Z,End");
913 "Jump to the next cut point"),
"PgDown");
915 "Jump to the previous cut point"),
"PgUp");
917 "Jump back 10x the normal amount"),
",,<");
919 "Jump forward 10x the normal amount"),
">,.");
921 "Cut point editor compact menu"),
"Alt+M");
925 "Next Page"),
"Down");
927 "Previous Page"),
"Up");
929 "Next Subpage"),
"Right");
931 "Previous Subpage"),
"Left");
933 "Toggle Teletext"),
"T");
937 "Menu Green"),
"F3");
939 "Menu Yellow"),
"F4");
943 "Menu White"),
"F6");
945 QT_TRANSLATE_NOOP(
"MythControls",
"Toggle Background"),
"F7");
947 "Reveal hidden Text"),
"F8");
951 QT_TRANSLATE_NOOP(
"MythControls",
"Toggle audio visualisation"),
"");
955 QT_TRANSLATE_NOOP(
"MythControls",
"Toggle OSD playback information"),
"");
959 QT_TRANSLATE_NOOP(
"MythControls",
"Auto 3D"),
"");
961 QT_TRANSLATE_NOOP(
"MythControls",
"Ignore 3D"),
"");
963 QT_TRANSLATE_NOOP(
"MythControls",
"Discard 3D Side by Side"),
"");
965 QT_TRANSLATE_NOOP(
"MythControls",
"Discard 3D Top and Bottom"),
"");
1019 { tr(
"Off",
"Sleep timer"), 0 },
1020 { tr(
"30m",
"Sleep timer"), 30*60 },
1021 { tr(
"1h",
"Sleep timer"), 60*60 },
1022 { tr(
"1h30m",
"Sleep timer"), 90*60 },
1023 { tr(
"2h",
"Sleep timer"), 120*60}
1040 m_mainWindow(MainWindow)
1043 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Creating TV object");
1046 QObject::setObjectName(
"TV");
1063 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Finished creating TV object");
1068 QMap<QString,QString> kv;
1069 kv[
"LiveTVIdleTimeout"] =
"0";
1070 kv[
"BrowseMaxForward"] =
"240";
1071 kv[
"PlaybackExitPrompt"] =
"0";
1072 kv[
"AutomaticSetWatched"] =
"0";
1073 kv[
"EndOfRecordingExitPrompt"] =
"0";
1074 kv[
"JumpToProgramOSD"] =
"1";
1075 kv[
"GuiSizeForTV"] =
"0";
1076 kv[
"UseVideoModes"] =
"0";
1077 kv[
"ClearSavedPosition"] =
"1";
1078 kv[
"JobsRunOnRecordHost"] =
"0";
1079 kv[
"ContinueEmbeddedTVPlay"] =
"0";
1080 kv[
"UseFixedWindowSize"] =
"1";
1081 kv[
"RunFrontendInWindow"] =
"0";
1082 kv[
"PersistentBrowseMode"] =
"0";
1083 kv[
"BrowseAllTuners"] =
"0";
1084 kv[
"ChannelOrdering"] =
"channum";
1086 kv[
"CustomFilters"] =
"";
1087 kv[
"ChannelFormat"] =
"<num> <sign>";
1089 kv[
"TryUnflaggedSkip"] =
"0";
1091 kv[
"ChannelGroupDefault"] =
"-1";
1092 kv[
"BrowseChannelGroup"] =
"0";
1093 kv[
"SmartForward"] =
"0";
1094 kv[
"FFRewReposTime"] =
"100";
1095 kv[
"FFRewReverse"] =
"1";
1097 kv[
"BrowseChannelGroup"] =
"0";
1098 kv[
"ChannelGroupDefault"] =
"-1";
1099 kv[
"ChannelGroupRememberLast"] =
"0";
1101 kv[
"VbiFormat"] =
"";
1102 kv[
"DecodeVBIFormat"] =
"";
1105 kv[
"PlaybackScreenPressKeyMap"] =
"P,Up,Z,],Left,Return,Return,Right,A,Down,Q,[";
1106 kv[
"LiveTVScreenPressKeyMap"] =
"P,Up,Z,S,Left,Return,Return,Right,A,Down,Q,F";
1108 constexpr std::array<const int,8> ff_rew_def { 3, 5, 10, 20, 30, 60, 120, 180 };
1109 for (
size_t i = 0; i < ff_rew_def.size(); i++)
1110 kv[QString(
"FFRewSpeed%1").arg(i)] = QString::number(ff_rew_def[i]);
1117 QString db_channel_ordering;
1121 uint db_browse_max_forward = kv[
"BrowseMaxForward"].toUInt() * 60;
1134 db_channel_ordering = kv[
"ChannelOrdering"];
1146 QString beVBI = kv[
"VbiFormat"];
1147 QString feVBI = kv[
"DecodeVBIFormat"];
1164 for (
size_t i = 0; i <
sizeof(ff_rew_def)/
sizeof(ff_rew_def[0]); i++)
1165 m_ffRewSpeeds.push_back(kv[QString(
"FFRewSpeed%1").arg(i)].toInt());
1182 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
1186 LOG(VB_GENERAL, LOG_ERR,
LOC +
"No MythMainWindow");
1207 fullscreen |= (0 == gui_width && 0 == gui_height);
1222 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Created TvPlayWindow.");
1233 QCoreApplication::processEvents();
1258 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
1264 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
1285 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"-- lock");
1314 lcd->setFunctionLEDs(
FUNC_TV,
false);
1316 lcd->switchToTime();
1324 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
1334 QCoreApplication::processEvents();
1410 .toUTC().toString(
"yyyy-MM-ddThh:mm:ssZ"));
1421 if (!info.
text[
"totalchapters"].isEmpty())
1423 QList<long long> chapters;
1426 for (
long long chapter : qAsConst(chapters))
1427 var << QVariant(chapter);
1428 status.insert(
"chaptertimes", var);
1435 int currenttrack = -1;
1438 for (
int i = 0; i < list.size(); i++)
1440 if (i == currenttrack)
1441 status.insert(
"currentsubtitletrack", list[i]);
1442 tracks.insert(
"SELECTSUBTITLE_" + QString::number(i), list[i]);
1449 for (
int i = 0; i < list.size(); i++)
1451 if (i == currenttrack)
1452 status.insert(
"currentsubtitletrack", list[i]);
1453 tracks.insert(
"SELECTTTC_" + QString::number(i), list[i]);
1460 for (
int i = 0; i < list.size(); i++)
1462 if (i == currenttrack)
1463 status.insert(
"currentsubtitletrack", list[i]);
1464 tracks.insert(
"SELECTCC708_" + QString::number(i), list[i]);
1471 for (
int i = 0; i < list.size(); i++)
1473 if (i == currenttrack)
1474 status.insert(
"currentsubtitletrack", list[i]);
1475 tracks.insert(
"SELECTCC608_" + QString::number(i), list[i]);
1482 for (
int i = 0; i < list.size(); i++)
1484 if (i == currenttrack)
1485 status.insert(
"currentsubtitletrack", list[i]);
1486 tracks.insert(
"SELECTRAWTEXT_" + QString::number(i), list[i]);
1492 status.insert(
"currentsubtitletrack", tr(
"External Subtitles"));
1496 status.insert(
"totalsubtitletracks", tracks.size());
1497 if (!tracks.isEmpty())
1498 status.insert(
"subtitletracks", tracks);
1503 for (
int i = 0; i < list.size(); i++)
1505 if (i == currenttrack)
1506 status.insert(
"currentaudiotrack", list[i]);
1507 tracks.insert(
"SELECTAUDIO_" + QString::number(i), list[i]);
1510 status.insert(
"totalaudiotracks", tracks.size());
1511 if (!tracks.isEmpty())
1512 status.insert(
"audiotracks", tracks);
1536 for (
auto tit =info.
text.cbegin(); tit != info.
text.cend(); ++tit)
1537 status.insert(tit.key(), tit.value());
1539 QHashIterator<QString,int> vit(info.
values);
1540 while (vit.hasNext())
1543 status.insert(vit.key(), vit.value());
1571 LOG(VB_GENERAL, LOG_INFO, QString(
"Using Idle Timer. %1 minutes").
arg(
m_dbIdleTimeout * (1.0 / 60000.0)));
1592 else if (!Selection.empty())
1594 for (
const auto & ci : Selection)
1596 uint chanid = ci.m_chanId;
1597 QString channum = ci.m_chanNum;
1598 if (!chanid || channum.isEmpty())
1602 if (chanid && !channum.isEmpty() && !cards.isEmpty())
1640 if (!info->GetChanID())
1647 QString key = info->MakeUniqueKey();
1652 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"AskAllowRecording -- " +
1653 QString(
"adding '%1'").
arg(info->m_title));
1661 LOG(VB_GENERAL, LOG_INFO,
LOC +
"-- " +
1662 QString(
"removing '%1'").
arg(info->GetTitle()));
1666 delete (*it).m_info;
1683 QString single_rec = tr(
"MythTV wants to record \"%1\" on %2 in %d seconds. Do you want to:");
1685 QString record_watch = tr(
"Record and watch while it records");
1686 QString let_record1 = tr(
"Let it record and go back to the Main Menu");
1687 QString let_recordm = tr(
"Let them record and go back to the Main Menu");
1688 QString record_later1 = tr(
"Record it later, I want to watch TV");
1689 QString record_laterm = tr(
"Record them later, I want to watch TV");
1690 QString do_not_record1= tr(
"Don't let it record, I want to watch TV");
1691 QString do_not_recordm= tr(
"Don't let them record, I want to watch TV");
1696 QMap<QString,AskProgramInfo>::iterator next = it;
1700 if ((*it).m_expiry <= timeNow)
1703 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"-- " +
1704 QString(
"removing '%1'").
arg((*it).m_info->m_title));
1706 delete (*it).m_info;
1718 (*it).m_isInSameInputGroup = (*it).m_isConflicting =
true;
1723 bool busy_input_grps_loaded =
false;
1724 vector<uint> busy_input_grps;
1731 (*it).m_isInSameInputGroup =
1732 (cardid == (*it).m_info->GetInputID());
1734 if ((*it).m_isInSameInputGroup)
1738 if (!busy_input_grps_loaded)
1741 busy_input_grps_loaded =
true;
1744 vector<uint> input_grps =
1747 for (
uint grp : input_grps)
1749 if (
find(busy_input_grps.begin(), busy_input_grps.end(),
1750 grp) != busy_input_grps.end())
1752 (*it).m_isInSameInputGroup =
true;
1762 if (!(*it).m_isInSameInputGroup)
1763 (*it).m_isConflicting =
false;
1764 else if (cardid == (*it).m_info->GetInputID())
1765 (*it).m_isConflicting =
true;
1767 (*it).m_isConflicting =
true;
1769 (busy_input.
m_mplexId == (*it).m_info->QueryMplexID())) ||
1771 (busy_input.
m_chanId == (*it).m_info->GetChanID())))
1772 (*it).m_isConflicting =
false;
1774 (*it).m_isConflicting =
true;
1776 conflict_count += (*it).m_isConflicting ? 1 : 0;
1783 if (conflict_count == 0)
1785 LOG(VB_GENERAL, LOG_INFO,
LOC +
"The scheduler wants to make "
1786 "a non-conflicting recording.");
1790 else if (conflict_count == 1 && ((*it).m_info->GetInputID() == cardid))
1793 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"UpdateOSDAskAllowDialog -- " +
1801 .replace(
"<num>", (*it).m_info->GetChanNum())
1802 .replace(
"<sign>", (*it).m_info->GetChannelSchedulingID())
1803 .replace(
"<name>", (*it).m_info->GetChannelName());
1805 message = single_rec.arg((*it).m_info->GetTitle()).arg(
channel);
1808 timeuntil =
static_cast<int>(
MythDate::current().secsTo((*it).m_expiry) * 1000);
1810 dialog.m_buttons.push_back({ record_watch,
"DIALOG_ASKALLOW_WATCH_0",
false, !((*it).m_hasRec)} );
1811 dialog.m_buttons.push_back({ let_record1,
"DIALOG_ASKALLOW_EXIT_0" });
1812 dialog.m_buttons.push_back({ ((*it).m_hasLater) ? record_later1 : do_not_record1,
1813 "DIALOG_ASKALLOW_CANCELRECORDING_0",
false, ((*it).m_hasRec) });
1818 if (conflict_count > 1)
1821 "MythTV wants to record these programs in %d seconds:");
1825 bool has_rec =
false;
1828 if (!(*it).m_isConflicting)
1831 QString
title = (*it).m_info->GetTitle();
1832 if ((
title.length() < 10) && !(*it).m_info->GetSubtitle().isEmpty())
1833 title +=
": " + (*it).m_info->GetSubtitle();
1834 if (
title.length() > 20)
1839 .replace(
"<num>", (*it).m_info->GetChanNum())
1840 .replace(
"<sign>", (*it).m_info->GetChannelSchedulingID())
1841 .replace(
"<name>", (*it).m_info->GetChannelName());
1843 if (conflict_count > 1)
1850 message = single_rec.arg((*it).m_info->GetTitle()).arg(
channel);
1851 has_rec = (*it).m_hasRec;
1855 if (conflict_count > 1)
1858 message += tr(
"Do you want to:");
1861 bool all_have_later =
true;
1862 timeuntil = 9999999;
1865 if ((*it).m_isConflicting)
1867 all_have_later &= (*it).m_hasLater;
1870 timeuntil = std::min(timeuntil, std::max(
tmp, 0));
1873 timeuntil = (9999999 == timeuntil) ? 0 : timeuntil;
1875 if (conflict_count > 1)
1879 { let_recordm,
"DIALOG_ASKALLOW_EXIT_0",
false,
true },
1880 { all_have_later ? record_laterm : do_not_recordm,
"DIALOG_ASKALLOW_CANCELCONFLICTING_0" }
1887 { let_record1,
"DIALOG_ASKALLOW_EXIT_0",
false, !has_rec},
1888 { all_have_later ? record_later1 : do_not_record1,
"DIALOG_ASKALLOW_CANCELRECORDING_0",
false, has_rec}
1901 LOG(VB_GENERAL, LOG_ERR,
"allowrecordingbox : askAllowLock is locked");
1905 if (
Action ==
"CANCELRECORDING")
1910 else if (
Action ==
"CANCELCONFLICTING")
1914 if (pgm.m_isConflicting)
1918 else if (
Action ==
"WATCH")
1981 #define TRANSITION(ASTATE,BSTATE) ((ctxState == (ASTATE)) && (desiredNextState == (BSTATE)))
1983 #define SET_NEXT() do { nextState = desiredNextState; changed = true; } while(false)
1984 #define SET_LAST() do { nextState = ctxState; changed = true; } while(false)
1988 QByteArray msg_arr = msg.toLatin1();
1989 QString msg_i18n = TV::tr(msg_arr.constData());
1990 QByteArray msg_i18n_arr = msg_i18n.toLatin1();
1991 return (msg_arr == msg_i18n_arr) ? msg_i18n : msg;
2006 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Called after fatal error detected.");
2010 bool changed =
false;
2016 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Warning, called with no state to change to.");
2024 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Attempting to change from %1 to %2")
2029 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Attempting to set to an error state!");
2054 QString channum =
"";
2058 QStringList reclist;
2062 "WHERE chanid = :CHANID");
2067 channum = QString::number(chanid);
2070 QString::number(chanid));
2075 if (!reclist.empty())
2090 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Spawning LiveTV Recorder -- begin");
2092 if (chanid && !channum.isEmpty())
2097 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
"Spawning LiveTV Recorder -- end");
2101 LOG(VB_GENERAL, LOG_ERR,
LOC +
"LiveTV not successfully started");
2115 LOG(VB_GENERAL, LOG_INFO,
LOC +
2116 QString(
"playbackURL(%1) inputtype(%2)")
2121 playbackURL,
false,
true,
2135 LOG(VB_GENERAL, LOG_ERR,
LOC +
"LiveTV not successfully started");
2189 LOG(VB_GENERAL, LOG_ERR,
LOC +
2190 "Couldn't find recorder for in-progress recording");
2209 QString message =
"COMMFLAG_REQUEST ";
2224 TV::tr(
"TV Player" ),
2251 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Unknown state transition: %1 to %2")
2256 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Changing from %1 to %2")
2267 LOG(VB_GENERAL, LOG_INFO,
LOC +
"State is LiveTV");
2269 LOG(VB_GENERAL, LOG_INFO,
LOC +
"UpdateOSDInput done");
2271 LOG(VB_GENERAL, LOG_INFO,
LOC +
"UpdateLCD done");
2273 LOG(VB_GENERAL, LOG_INFO,
LOC +
"ITVRestart done");
2279 QString msg = tr(
"%1 Settings")
2332 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Main UI disabled.");
2335 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
" -- end");
2350 MaxWait = (MaxWait <= 0) ? 40000 : MaxWait;
2353 bool recording =
false;
2357 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Invalid Remote Encoder");
2365 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Lost contact with backend");
2369 std::this_thread::sleep_for(std::chrono::microseconds(5));
2375 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Timed out waiting for recorder to start");
2379 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Took %1 ms to start recorder.").
arg(
t.elapsed()));
2398 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- begin");
2412 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"Stopping ring buffer");
2423 LOG(VB_PLAYBACK, LOG_INFO,
LOC +
"stopping recorder");
2428 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC +
"-- end");
2433 const int timer_id =
Event->timerId();
2441 bool handled =
true;
2502 if (!netCmd.isEmpty())
2527 LOG(VB_PLAYBACK, LOG_ERR,
LOC +
"Last Program File does not exist");
2644 LOG(VB_GENERAL, LOG_WARNING,
LOC + QString(
"Unknown timer: %1").
arg(timer_id));
2654 QString lcd_time_string;
2655 bool showProgress =
true;
2672 lcd_time_string = info.
text[
"playedtime"] +
" / " + info.
text[
"totaltime"];
2674 if (lcd_time_string.length() >
static_cast<int>(lcd->
getLCDWidth()))
2675 lcd_time_string.remove(
' ');
2705 int timer = startTimer(Interval);
2707 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Failed to start timer on line %1 of %2").
arg(Line).
arg(__FILE__));
2724 auto StateChange = [&]()
2742 QTimer::singleShot(0,
this, StateChange);
2747 auto InputChange = [&]()
2759 QTimer::singleShot(0,
this, InputChange);
2771 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Switching to program: %1")
2790 bool allow_set_before_end =
2798 bool allow_clear_at_end =
2809 bool clear_lastplaypos =
false;
2810 if (at_end && allow_clear_at_end)
2815 clear_lastplaypos =
true;
2817 else if (!at_end && allow_set_before_end)
2853 bool is_playing =
false;
2938 bool restartTimer =
false;
2944 restartTimer =
true;
2948 LOG(VB_CHANNEL, LOG_INFO,
"REC_PROGRAM -- channel change");
2992 if ((
Event->type() == QEvent::Resize))
2998 if ( (QEvent::KeyPress ==
Event->type() || QEvent::KeyRelease ==
Event->type())
3000 return TVPlaybackState::eventFilter(Object,
Event);
3002 QScopedPointer<QEvent> sNewEvent(
nullptr);
3006 if (QEvent::KeyPress ==
Event->type())
3021 switch (
Event->type())
3024 case QEvent::UpdateRequest:
3028 return TVPlaybackState::eventFilter(Object,
Event);
3031 return TVPlaybackState::eventFilter(Object,
Event);
3038 if (
Event ==
nullptr)
3039 return TVPlaybackState::event(
Event);
3041 if (QEvent::Resize ==
Event->type())
3043 const auto *qre =
dynamic_cast<const QResizeEvent*
>(
Event);
3046 return TVPlaybackState::event(
Event);
3052 if (QEvent::KeyPress ==
Event->type())
3054 const auto * ke =
dynamic_cast<QKeyEvent*
>(
Event);
3057 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"keypress: %1 '%2'")
3058 .
arg(ke->key()).arg(ke->text()));
3066 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"mythgesture: g:%1 pos:%2,%3 b:%4")
3067 .
arg(ge->GetGesture()).arg(ge->GetPosition().x())
3068 .arg(ge->GetPosition().y()).arg(ge->GetButton()));
3072 bool handled =
false;
3081 switch (
Event->type())
3084 case QEvent::UpdateRequest:
3091 return QObject::event(
Event);
3096 bool handled =
true;
3151 else if (
Action.startsWith(
"TOGGLE"))
3161 else if (
Action.startsWith(
"SELECT"))
3170 else if (
Action.startsWith(
"NEXT") ||
Action.startsWith(
"PREV"))
3172 int dir = (
Action.startsWith(
"NEXT")) ? +1 : -1;
3176 else if (
Action.endsWith(
"CC"))
3199 QStringList::const_iterator it;
3200 for (it = actions.begin(); it != actions.end(); ++it)
3202 if ((*it).startsWith(
"SYSEVENT") ||
3215 QList<QKeyEvent> keyPressList;
3217 QStringList stringKeyList = KeyList.split(
',');
3218 for (
const auto & str : qAsConst(stringKeyList))
3220 QKeySequence keySequence(str);
3221 for(i = 0; i < keySequence.count(); i++)
3223 uint keynum =
static_cast<uint>(keySequence[
static_cast<uint>(i)]);
3224 QKeyEvent keyEvent(QEvent::None, keynum & ~Qt::KeyboardModifierMask,
3225 static_cast<Qt::KeyboardModifiers
>(keynum & Qt::KeyboardModifierMask));
3226 keyPressList.append(keyEvent);
3234 QKeyEvent keyEvent(QEvent::None, Qt::Key_Escape, Qt::NoModifier);
3235 keyPressList.append(keyEvent);
3238 return keyPressList;
3242 QStringList &Actions,
bool IsLiveTV)
3244 if (
Event && Context ==
"TV Playback")
3251 (
Event->GetButton() == Qt::LeftButton))
3255 QPoint pos =
Event->GetPosition();
3257 const int widthDivider = 4;
3258 int w4 = size.width() / widthDivider;
3259 region = pos.x() / w4;
3260 int h3 = size.height() / 3;
3261 region += (pos.y() / h3) * widthDivider;
3273 QStringList &Actions,
bool IsLiveTV,
bool AllowJumps)
3277 if (QEvent::KeyPress ==
Event->type())
3287 if (
Event ==
nullptr)
3293 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"ignoreKeys: %1").
arg(ignoreKeys));
3304 auto* eKeyEvent =
dynamic_cast<QKeyEvent*
>(
Event);
3306 if (eKeyEvent->key() <= 0)
3309 switch(eKeyEvent->nativeScanCode())
3312 keycode = Qt::Key_MediaPause;
3320 auto *key =
new QKeyEvent(QEvent::KeyPress, keycode, eKeyEvent->modifiers());
3321 QCoreApplication::postEvent(
this, key);
3327 QStringList actions;
3328 bool handled =
false;
3329 bool alreadyTranslatedPlayback =
false;
3337 alreadyTranslatedPlayback =
true;
3339 if (handled || actions.isEmpty())
3342 bool esc =
IsActionable({
"ESCAPE",
"BACK" }, actions);
3353 if (QEvent::KeyPress ==
Event->type())
3355 auto *qke =
dynamic_cast<QKeyEvent*
>(
Event);
3418 if (QEvent::KeyPress ==
Event->type())
3420 auto *qke =
dynamic_cast<QKeyEvent*
>(
Event);
3423 const QString txt = qke->text();
3427 (void)txt.toInt(&ok, 16);
3428 if (ok || txt==
"_" || txt==
"-" || txt==
"#" || txt==
".")
3439 QStringList tt_actions;
3442 if (!handled && !tt_actions.isEmpty())
3444 for (
int i = 0; i < tt_actions.size(); i++)
3456 if (!alreadyTranslatedPlayback)
3459 alreadyTranslatedPlayback =
true;
3462 if (!handled && !actions.isEmpty())
3464 for (
int i = 0; i < actions.size(); i++)
3473 if (!alreadyTranslatedPlayback)
3476 if (handled || actions.isEmpty())
3484 if (QEvent::KeyPress ==
Event->type())
3500 for (
int i = 0; i < actions.size(); ++i)
3501 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"handled(%1) actions[%2](%3)")
3503 #endif // DEBUG_ACTIONS
3510 for (
int i = 0; i < actions.size() && !handled; i++)
3512 QString
action = actions[i];
3514 int val =
action.toInt(&ok);
3532 bool handled =
true;
3553 for (
const auto&
action : qAsConst(Actions))
3564 static const QStringList passthrough =
3567 ACTION_MUTEAUDIO,
"CYCLEAUDIOCHAN",
"BOTTOMLINEMOVE",
"BOTTOMLINESAVE",
"TOGGLEASPECT"
3577 bool endmanualzoom =
false;
3578 bool handled =
true;
3579 bool updateOSD =
true;
3608 endmanualzoom =
true;
3612 endmanualzoom =
true;
3619 static const QStringList passthrough =
3627 QString msg = tr(
"Zoom Committed");
3631 msg = endmanualzoom ? tr(
"Zoom Ignored") :
3636 else if (endmanualzoom)
3683 bool handled =
true;
3708 bool handled =
true;
3731 bool handled =
true;
3754 bool handled =
true;
3781 pts =
static_cast<int64_t
>(frame->
m_timecode * 90);
3789 bool IsDVD,
bool IsDVDStillFrame)
3791 bool handled =
true;
3795 else if (
IsActionable(
"SKIPCOMMBACK", Actions) && !IsDVD)
3797 else if (
IsActionable(
"QUEUETRANSCODE", Actions) && !IsDVD)
3799 else if (
IsActionable(
"QUEUETRANSCODE_AUTO", Actions) && !IsDVD)
3801 else if (
IsActionable(
"QUEUETRANSCODE_HIGH", Actions) && !IsDVD)
3803 else if (
IsActionable(
"QUEUETRANSCODE_MEDIUM", Actions) && !IsDVD)
3805 else if (
IsActionable(
"QUEUETRANSCODE_LOW", Actions) && !IsDVD)
3811 else if (
IsActionable(
"SPEEDINC", Actions) && !IsDVDStillFrame)
3813 else if (
IsActionable(
"SPEEDDEC", Actions) && !IsDVDStillFrame)
3817 else if (
IsActionable(
"CYCLECOMMSKIPMODE",Actions) && !IsDVD)
3873 DoSeek(0, tr(
"Jump to Beginning"),
false,
true);
3932 bool visible =
false;
3998 else if (
IsActionable({
"INFO",
"INFOWITHCUTLIST" }, Actions))
4013 for (
auto it = Actions.cbegin(); it != Actions.cend() && !handled; ++it)
4022 bool handled =
false;
4026 for (
int i = 0; i < Actions.size() && !handled; i++)
4028 QString
action = Actions[i];
4030 int val =
action.toInt(&ok);
4059 bool handled =
true;
4138 info.
text[
"title"] = tr(
"Position");
4146 bool handled =
true;
4172 else if (
IsActionable(
"NEXTSOURCE", Actions) && islivetv)
4174 else if (
IsActionable(
"PREVSOURCE", Actions) && islivetv)
4176 else if (
IsActionable(
"NEXTINPUT", Actions) && islivetv)
4180 else if (
IsActionable(
"PREVCHAN", Actions) && islivetv)
4254 #ifdef DEBUG_ACTIONS
4255 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"(%1) ignoreKeys: %2").
arg(
Command).
arg(ignoreKeys));
4260 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Ignoring network control command because ignoreKeys is set");
4264 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
4265 QStringList tokens =
Command.split(
" ", QString::SkipEmptyParts);
4267 QStringList tokens =
Command.split(
" ", Qt::SkipEmptyParts);
4269 if (tokens.size() < 2)
4271 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Not enough tokens in network control command " + QString(
"'%1'").
arg(
Command));
4283 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4284 "Ignoring network control command\n\t\t\t" +
4285 QString(
"because dialog is waiting for a response"));
4289 if (tokens[1] !=
"QUERY")
4292 if (tokens.size() == 3 && tokens[1] ==
"CHANID")
4298 else if (tokens.size() == 3 && tokens[1] ==
"CHANNEL")
4302 if (tokens[2] ==
"UP")
4304 else if (tokens[2] ==
"DOWN")
4306 else if (tokens[2].contains(QRegularExpression(R
"(^[-\.\d_#]+$)")))
4310 else if (tokens.size() == 3 && tokens[1] ==
"SPEED")
4314 if (tokens[2] ==
"0x")
4321 else if (tokens[2] ==
"normal")
4331 float tmpSpeed = 1.0F;
4334 if (tokens[2].contains(QRegularExpression(R
"(^\-*(\d*\.)?\d+x$)")))
4336 QString speed = tokens[2].left(tokens[2].length()-1);
4337 tmpSpeed = speed.toFloat(&ok);
4341 QRegularExpression re { R
"(^(\-*\d+)\/(\d+)x$)" };
4342 auto match = re.match(tokens[2]);
4343 if (match.hasMatch())
4345 QStringList matches = match.capturedTexts();
4346 int numerator = matches[1].toInt(&ok);
4347 int denominator = matches[2].toInt(&ok);
4349 if (ok && denominator != 0)
4350 tmpSpeed =
static_cast<float>(numerator) /
static_cast<float>(denominator);
4358 float searchSpeed = fabs(tmpSpeed);
4363 if (tmpSpeed == 0.0F)
4371 else if (tmpSpeed == 1.0F)
4390 else if (tmpSpeed > 1)
4398 else if (0.48F <= tmpSpeed && tmpSpeed <= 2.0F)
4406 LOG(VB_GENERAL, LOG_WARNING, QString(
"Couldn't find %1 speed. Setting Speed to 1x")
4407 .
arg(
static_cast<double>(searchSpeed)));
4414 LOG(VB_GENERAL, LOG_ERR, QString(
"Found an unknown speed of %1").
arg(tokens[2]));
4418 else if (tokens.size() == 2 && tokens[1] ==
"STOP")
4432 if (tokens[2] ==
"BEGINNING")
4434 DoSeek(0, tr(
"Jump to Beginning"),
false,
true);
4436 else if (tokens[2] ==
"FORWARD")
4440 else if (tokens[2] ==
"BACKWARD")
4444 else if ((tokens[2] ==
"POSITION" ||
4445 tokens[2] ==
"POSITIONWITHCUTLIST") &&
4446 (tokens.size() == 4) &&
4447 (tokens[3].contains(QRegularExpression(
"^\\d+$"))))
4449 DoSeekAbsolute(tokens[3].toInt(), tokens[2] ==
"POSITIONWITHCUTLIST");
4452 else if (tokens.size() >= 3 && tokens[1] ==
"SUBTITLES")
4455 uint track = tokens[2].toUInt(&ok);
4467 uint size =
static_cast<uint>(subs.size());
4470 if (track >=
start && track < finish)
4479 finish =
start + size;
4480 if (track >=
start && track < finish)
4489 finish =
start + size;
4490 if (track >=
start && track < finish)
4499 finish =
start + size;
4500 if (track >=
start && track < finish)
4509 finish =
start + size;
4510 if (track >=
start && track < finish)
4519 finish =
start + size;
4520 if (track >=
start && track < finish)
4528 else if (tokens.size() >= 3 && tokens[1] ==
"VOLUME")
4530 QRegularExpression re {
"(\\d+)%" };
4531 auto match = re.match(tokens[2]);
4532 if (match.hasMatch())
4534 QStringList matches = match.capturedTexts();
4536 LOG(VB_GENERAL, LOG_INFO, QString(
"Set Volume to %1%").
arg(matches[1]));
4539 int vol = matches[1].toInt(&ok);
4543 if (0 <= vol && vol <= 100)
4547 else if (tokens.size() >= 3 && tokens[1] ==
"QUERY")
4549 if (tokens[2] ==
"POSITION")
4564 QRegularExpression re {
"Play (.*)x" };
4566 if (match.hasMatch())
4568 QStringList matches = match.capturedTexts();
4569 speedStr = QString(
"%1x").arg(matches[1]);
4581 QString infoStr =
"";
4605 infoStr =
"Recorded";
4613 QString bufferFilename =
4615 if ((infoStr ==
"Recorded") || (infoStr ==
"LiveTV"))
4617 infoStr += QString(
" %1 %2 %3 %4 %5 %6 %7")
4618 .arg(info.
text[
"description"])
4624 .arg(bufferFilename)
4629 QString position = info.
text[
"description"].section(
" ",0,0);
4630 infoStr += QString(
" %1 %2 %3 %4 %5")
4633 .arg(bufferFilename)
4638 infoStr += QString(
" Subtitles:");
4643 infoStr += QString(
" *0:[None]*");
4645 infoStr += QString(
" 0:[None]");
4650 for (
int i = 0; i < subs.size(); i++)
4653 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4655 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4660 for (
int i = 0; i < subs.size(); i++)
4663 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4665 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4670 for (
int i = 0; i < subs.size(); i++)
4673 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4675 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4680 for (
int i = 0; i < subs.size(); i++)
4683 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4685 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4690 for (
int i = 0; i < subs.size(); i++)
4693 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4695 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4700 for (
int i = 0; i < subs.size(); i++)
4703 infoStr += QString(
" *%1:[%2]*").arg(n).arg(subs[i]);
4705 infoStr += QString(
" %1:[%2]").arg(n).arg(subs[i]);
4711 QString message = QString(
"NETWORK_CONTROL ANSWER %1").arg(infoStr);
4715 else if (tokens[2] ==
"VOLUME")
4718 QString message = QString(
"NETWORK_CONTROL ANSWER %1").arg(infoStr);
4728 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Elapsed time since TV constructor was called: %1 ms")
4736 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Created player."));
4741 LOG(VB_GENERAL, LOG_CRIT,
LOC + QString(
"Failed to create player."));
4744 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"(%1) -- end %2")
4850 bool paused =
false;
4872 bool ignore =
false;
4873 bool paused =
false;
4898 if (Time > -0.001F && Time < +0.001F)
4901 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1 seconds").
arg(
static_cast<double>(Time)));
4922 else if (Time < 0.0F)
4934 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"%1").
arg(FrameNum));
4960 const int kRewind = 4;
4961 const int kForward = 8;
4962 const int kSticky = 16;
4963 const int kSlippery = 32;
4964 const int kRelative = 64;
4965 const int kAbsolute = 128;
4966 const int kIgnoreCutlist = 256;
4967 const int kWhenceMask = 3;
4972 flags =
ARBSEEK_END | kForward | kSticky | kAbsolute;
4978 flags =
ARBSEEK_SET | kRewind | kSticky | kAbsolute;
4984 int direction = (flags & kRewind) ? -1 : 1;
4993 QString message = (flags & kRewind) ? tr(
"Rewind") :
4995 if (flags & kAbsolute)
4997 float time = direction;
4998 DoSeek(time, message,
true, (flags & kIgnoreCutlist) == 0);
5005 uint64_t targetRel = frameRel +
static_cast<uint64_t
>(direction);
5006 if (frameRel == 0 && direction < 0)
5010 if (targetRel > maxRel)
5019 else if (flags & kSticky)
5023 else if (flags & kRewind)
5043 void TV::DoSeek(
float Time,
const QString &Msg,
bool TimeIsOffset,
bool HonorCutlist)
5048 bool limitkeys =
false;
5066 auto time =
static_cast<uint64_t
>(Time);
5088 DoSeek(Seconds, tr(
"Jump To"),
false, HonorCutlist);
5100 int64_t time = (int(seek / 100) * 3600) + ((seek % 100) * 60);
5104 DoSeek(time, tr(
"Jump Ahead"),
true, HonorCutlist);
5108 DoSeek(-time, tr(
"Jump Back"),
true, HonorCutlist);
5121 DoSeek(std::max(0.0F, dur -
static_cast<float>(time)), tr(
"Jump To"),
false, HonorCutlist);
5159 case 4: speed = 16.0F; mesg = tr(
"Speed 16X");
break;
5160 case 3: speed = 8.0F; mesg = tr(
"Speed 8X");
break;
5161 case 2: speed = 3.0F; mesg = tr(
"Speed 3X");
break;
5162 case 1: speed = 2.0F; mesg = tr(
"Speed 2X");
break;
5164 case -1: speed = 1.0F / 3; mesg = tr(
"Speed 1/3X");
break;
5165 case -2: speed = 1.0F / 8; mesg = tr(
"Speed 1/8X");
break;
5166 case -3: speed = 1.0F / 16; mesg = tr(
"Speed 1/16X");
break;