8#include <QCoreApplication>
53#define LOC QString("PlaybackBox: ")
54#define LOC_WARN QString("PlaybackBox Warning: ")
55#define LOC_ERR QString("PlaybackBox Error: ")
85 return (dt1 < dt2 ? 1 : -1);
98 return (dt1 > dt2 ? 1 : -1);
138 int eIndex = synd.indexOf(
'E');
139 if (synd.isEmpty() || !synd.startsWith(
'S') || (eIndex == -1))
147 bool okSeason {
false };
148 bool okEpisode {
false };
149#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
150 season = synd.midRef(1, eIndex - 1).toInt(&okSeason);
151 episode = synd.midRef(eIndex + 1).toInt(&okEpisode);
153 season = QStringView(synd).mid(1, eIndex - 1).toInt(&okSeason);
154 episode = QStringView(synd).mid(eIndex + 1).toInt(&okEpisode);
157 return okSeason && okEpisode;
170 if (a_season == 0 || b_season == 0)
172 if (a_season != b_season)
173 return (a_season < b_season ? 1 : -1);
174 if (a_episode == 0 && b_episode == 0)
176 return (a_episode < b_episode ? 1 : -1);
189 if (a_season == 0 || b_season == 0)
191 if (a_season != b_season)
192 return (a_season > b_season ? 1 : -1);
193 if (a_episode == 0 && b_episode == 0)
195 return (a_episode > b_episode ? 1 : -1);
271 QString sTitle = sortTitle.isEmpty()
272 ? title : sortTitle +
" - " + title;
301 sortprefix = QString(
"+%1").arg(1000 - recpriority, 3, 10, QChar(
'0'));
303 sortprefix = QString(
"-%1").arg(-recpriority, 3, 10, QChar(
'0'));
305 sTitle = sortprefix +
'-' + sTitle;
312 QString state(
"normal");
328 if ((state ==
"normal" || state ==
"running") &&
339 QString job =
"default";
352 job =
"commflagging";
372 const ProgramInfo &pginfo,
const QString &groupname)
375 if (groupname != pginfo.
GetTitle().toLower())
382 if (subtitle.trimmed().isEmpty())
392 list.push_back(QString() );
393 list.push_back(QString());
404 recordingID = list[0].toUInt();
410 if (recordingID == 0U) {
411 LOG(VB_GENERAL, LOG_ERR,
LOC +
"extract_one_del() invalid entry");
421 auto *pbb =
new PlaybackBox(mainStack,
"playbackbox", (
TV *)player, showTV);
435 m_groupDisplayName(
ProgramInfo::i18n(
"All Programs")),
436 m_recGroup(
"All Programs"),
437 m_watchGroupName(tr(
"Watch List")),
438 m_watchGroupLabel(m_watchGroupName.toLower()),
441 m_programInfoCache(this),
462 std::chrono::days(2));
467 "DisplayGroupDefaultViewMask",
509 (displayCat &&
m_recGroup !=
"All Programs") ?
"category" :
"recgroup";
562 LOG(VB_GENERAL, LOG_ERR,
LOC +
563 "Theme is missing critical theme elements.");
624 "titlesubtitle|shortdate|starttime");
672 QString label = tr(
"Password for group '%1':").arg(newRecGroup);
710 const QString &grouplabel)
716 infoMap[
"title"] = grouplabel;
723 if (!groupname.isEmpty() && !
m_progLists[groupname].empty())
748 if (countInGroup >= 1)
751 float groupSize = 0.0;
753 for (
auto *
info : group)
757 uint64_t filesize =
info->GetFilesize();
764 groupSize += filesize;
768 desc = tr(
"There is/are %n recording(s) in this display "
769 "group, which consume(s) %1 GiB.",
"", countInGroup)
770 .arg(groupSize / 1024.0F / 1024.0F / 1024.0F, 0,
'f', 2);
774 desc = tr(
"There is no recording in this display group.");
777 infoMap[
"description"] = desc;
778 infoMap[
"rec_count"] = QString(
"%1").arg(countInGroup);
787 ratingState->
Reset();
807 bool force_preview_reload)
823 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
824 QString(
"UpdateUIListItem called with a title unknown "
825 "to us in m_recordingList\n\t\t\t%1")
832 "playlist",
"watched",
"preserve",
833 "cutlist",
"autoexpire",
"editing",
834 "bookmark",
"inuse",
"transcoded"
839 std::array<bool,
disp_flags.size()> disp_flag_stat {};
849 disp_flag_stat[8] = ((pginfo->
GetProgramFlags() & FL_TRANSCODED) != 0U);
851 for (
size_t i = 0; i <
disp_flags.size(); ++i)
857 bool is_sel,
bool force_preview_reload)
874 pginfo->ToMap(infoMap);
882 if (groupname == pginfo->GetTitle().toLower())
884 item->
SetText(tempSubTitle,
"titlesubtitle");
888 "titlesubtitlefull");
905 QString
rating = QString::number(pginfo->GetStars(10));
910 if (oldimgfile.isEmpty() || force_preview_reload)
917 pginfo->CalculateProgress(pginfo->QueryLastPlayPos());
919 pginfo->ToMap(infoMap);
953 if (arthost.isEmpty())
960 pginfo->GetInetRef(), pginfo->GetSeason(),
982 if (item->
GetText(
"is_item_initialized").isNull())
984 QMap<AudioProps, QString> audioFlags;
985 audioFlags[AUD_DOLBY] =
"dolby";
986 audioFlags[AUD_SURROUND] =
"surround";
987 audioFlags[AUD_STEREO] =
"stereo";
988 audioFlags[AUD_MONO] =
"mono";
990 QMap<VideoProps, QString> codecFlags;
991 codecFlags[VID_MPEG2] =
"mpeg2";
992 codecFlags[VID_AVC] =
"avc";
993 codecFlags[VID_HEVC] =
"hevc";
995 QMap<SubtitleProps, QString> subtitleFlags;
996 subtitleFlags[SUB_SIGNED] =
"deafsigned";
997 subtitleFlags[SUB_ONSCREEN] =
"onscreensub";
998 subtitleFlags[SUB_NORMAL] =
"subtitles";
999 subtitleFlags[SUB_HARDHEAR] =
"cc";
1009 pginfo->ToMap(infoMap);
1014 if (groupname == pginfo->GetTitle().toLower())
1016 item->
SetText(tempSubTitle,
"titlesubtitle");
1020 "titlesubtitlefull");
1025 item->
DisplayState(QString::number(pginfo->GetStars(10)),
1030 QMap<AudioProps, QString>::iterator ait;
1031 for (ait = audioFlags.begin(); ait != audioFlags.end(); ++ait)
1033 if (pginfo->GetAudioProperties() & ait.key())
1037 uint props = pginfo->GetVideoProperties();
1039 QMap<VideoProps, QString>::iterator cit;
1040 for (cit = codecFlags.begin(); cit != codecFlags.end(); ++cit)
1042 if (props & cit.key())
1049 if (props & VID_PROGRESSIVE)
1054 if (props & VID_1080)
1061 if (props & VID_1080)
1064 if (props & VID_720)
1066 if (!(props & (VID_4K | VID_1080 | VID_720)))
1068 if (props & VID_HDTV)
1070 else if (props & VID_WIDESCREEN)
1076 QMap<SubtitleProps, QString>::iterator sit;
1077 for (sit = subtitleFlags.begin(); sit != subtitleFlags.end(); ++sit)
1079 if (pginfo->GetSubtitleType() & sit.key())
1083 item->
DisplayState(pginfo->GetCategoryTypeString(),
"categorytype");
1086 item->
SetText(
"yes",
"is_item_initialized");
1103 const auto watchedPercent = pginfo->GetWatchedPercent();
1105 item->
SetProgress1(0, showProgress ? 100 : 0, watchedPercent);
1106 item->
SetProgress2(0, 100, pginfo->GetRecordedPercent());
1113 if (token.isEmpty())
1120 (
asAvailable == sel_pginfo->GetAvailableStatus()))
1136 if (list.size() < 5)
1138 LOG(VB_GENERAL, LOG_ERR,
"HandlePreviewEvent() -- too few args");
1139 for (
uint i = 0; i < (
uint) list.size(); i++)
1141 LOG(VB_GENERAL, LOG_INFO, QString(
"%1: %2")
1142 .arg(i).arg(list[i]));
1147 uint recordingID = list[0].toUInt();
1148 const QString& previewFile = list[1];
1149 const QString& message = list[2];
1152 for (
uint i = 4; i < (
uint) list.size(); i++)
1154 const QString& token = list[i];
1165 QString tokens(
"\n\t\t\ttokens: ");
1166 for (
uint i = 4; i < (
uint) list.size(); i++)
1167 tokens += list[i] +
", ";
1168 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1169 "Ignoring PREVIEW_SUCCESS, no matcing token" + tokens);
1173 if (previewFile.isEmpty())
1175 LOG(VB_GENERAL, LOG_ERR,
LOC +
1176 "Ignoring PREVIEW_SUCCESS, no preview file.");
1188 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1189 "Ignoring PREVIEW_SUCCESS, item no longer on screen.");
1194 LOG(VB_GUI, LOG_INFO,
LOC + QString(
"Loading preview %1,\n\t\t\tmsg %2")
1195 .arg(previewFile, message));
1197 item->
SetImage(previewFile,
"preview",
true);
1211 uint32_t flags = FL_NONE;
1216 QMap <QString, int>::iterator it;
1219 iconMap[
"commflagged"] = FL_COMMFLAG;
1220 iconMap[
"cutlist"] = FL_CUTLIST;
1221 iconMap[
"autoexpire"] = FL_AUTOEXP;
1222 iconMap[
"processing"] = FL_COMMPROCESSING;
1223 iconMap[
"editing"] = FL_EDITING;
1224 iconMap[
"bookmark"] = FL_BOOKMARK;
1225 iconMap[
"inuse"] = (FL_INUSERECORDING |
1228 iconMap[
"transcoded"] = FL_TRANSCODED;
1229 iconMap[
"watched"] = FL_WATCHED;
1230 iconMap[
"preserved"] = FL_PRESERVED;
1238 iconImage->
SetVisible((flags & (*it)) != 0U);
1252 iconMap[
"1dolby"] = AUD_DOLBY;
1253 iconMap[
"2surround"] = AUD_SURROUND;
1254 iconMap[
"3stereo"] = AUD_STEREO;
1258 bool haveIcon =
false;
1259 if (pginfo && iconState)
1274 if (iconState && !haveIcon)
1279 if (pginfo && iconState)
1284 if (props & VID_PROGRESSIVE)
1287 iconMap[
"hd1080p"] = VID_1080;
1292 iconMap[
"hd1080i"] = VID_1080;
1297 iconMap[
"widescreen"] = VID_WIDESCREEN;
1312 if (iconState && !haveIcon)
1315 iconMap[
"damaged"] = VID_DAMAGED;
1319 if (pginfo && iconState)
1334 if (iconState && !haveIcon)
1337 iconMap[
"deafsigned"] = SUB_SIGNED;
1338 iconMap[
"onscreensub"] = SUB_ONSCREEN;
1339 iconMap[
"subtitles"] = SUB_NORMAL;
1344 if (pginfo && iconState)
1359 if (iconState && !haveIcon)
1384 if (!freereportText && !usedProgress && !
GetChild(
"diskspacetotal") &&
1394 usageMap[
"diskspacetotal"] = locale.toString((freeSpaceTotal / 1024.0),
1396 usageMap[
"diskspaceused"] = locale.toString((freeSpaceUsed / 1024.0),
1398 usageMap[
"diskspacefree"] = locale.toString(
1399 ((freeSpaceTotal - freeSpaceUsed) / 1024.0),
1403 if (freeSpaceTotal > 0.0)
1404 perc = (100.0 * freeSpaceUsed) / freeSpaceTotal;
1406 usageMap[
"diskspacepercentused"] = QString::number((
int)perc);
1407 usageMap[
"diskspacepercentfree"] = QString::number(100 - (
int)perc);
1409 QString size = locale.toString(((freeSpaceTotal - freeSpaceUsed) / 1024.0),
1412 QString usestr = tr(
"%1% used, %2 GB free",
"Diskspace")
1413 .arg(QString::number((
int)perc),
1417 freereportText->
SetText(usestr);
1421 usedProgress->
SetTotal((
int)freeSpaceTotal);
1422 usedProgress->
SetUsed((
int)freeSpaceUsed);
1445 const QString& key = (*it);
1446 QString tmp = (key ==
"All Programs") ?
"All" : key;
1453 QVariant::fromValue(key));
1457 item->SetText(name);
1469 int best_pref = INT_MAX;
1472 QStringList::iterator it;
1475 const QString& groupname = (*it);
1478 QVariant::fromValue(groupname.toLower()));
1480 int pref = groupPreferences.indexOf(groupname.toLower());
1481 if ((pref >= 0) && (pref < best_pref))
1488 QString displayName = groupname;
1489 if (displayName.isEmpty())
1498 item->SetText(groupname,
"groupname");
1499 item->SetText(displayName,
"name");
1500 item->SetText(displayName);
1502 int count =
m_progLists[groupname.toLower()].size();
1503 item->SetText(QString::number(count),
"reccount");
1520 QVariant::fromValue(Iqs->first));
1521 item->SetText(Iqs->first);
1529 QString newRecGroup = sel_item->
GetData().toString();
1545 if (!nextGroup.isEmpty())
1554 QString groupname = sel_item->
GetData().toString();
1555 QString grouplabel = sel_item->
GetText();
1569 ProgramMap::iterator pmit =
m_progLists.find(groupname);
1575 for (
auto & prog : progList)
1578 prog->GetAvailableStatus() ==
asDeleted)
1587 if (!progList.
empty())
1594 tr(
"There are no recordings available") :
1595 tr(
"There are no recordings in your current view");
1603 if (grouplabel.startsWith(
"Watch List") ||
1604 grouplabel.startsWith(
"All Programs"))
1611 if (pginfo ==
nullptr)
1625 if (!item->
GetText().isEmpty())
1634 QStringList &groupSelPref, QStringList &itemSelPref,
1635 QStringList &itemTopPref)
1641 groupSelPref.push_back(prefSelGroup->
GetData().toString());
1643 i < groupList->GetCount(); i++)
1647 groupSelPref.push_back(prefSelGroup->
GetData().toString());
1651 for (
int i = curPos; (i >= 0) && (i < recordingList->GetCount()); i++)
1655 itemSelPref.push_back(groupSelPref.front());
1656 itemSelPref.push_back(QString::number(pginfo->GetRecordingID()));
1658 for (
int i = curPos; (i >= 0) && (i < recordingList->GetCount()); i--)
1662 itemSelPref.push_back(groupSelPref.front());
1663 itemSelPref.push_back(QString::number(pginfo->GetRecordingID()));
1667 for (
int i = topPos + 1; i >= topPos - 1; i--)
1669 if (i >= 0 && i < recordingList->GetCount())
1675 itemTopPref.push_front(QString::number(pginfo->GetRecordingID()));
1676 itemTopPref.push_front(groupSelPref.front());
1680 itemTopPref.push_back(groupSelPref.front());
1681 itemTopPref.push_back(QString::number(pginfo->GetRecordingID()));
1691 const QStringList &groupSelPref,
const QStringList &itemSelPref,
1692 const QStringList &itemTopPref)
1697 if (!prefSelGroup ||
1698 !groupSelPref.contains(prefSelGroup->
GetData().toString()) ||
1699 !itemSelPref.contains(prefSelGroup->
GetData().toString()))
1705 QString groupname = prefSelGroup->
GetData().toString();
1709 for (
uint i = 0; i+1 < (
uint)itemSelPref.size(); i+=2)
1711 if (itemSelPref[i] != groupname)
1714 uint recordingID = itemSelPref[i+1].toUInt();
1719 if (pginfo && (pginfo->GetRecordingID() == recordingID))
1722 i = itemSelPref.size();
1730 for (
uint i = 0; i+1 < (
uint)itemTopPref.size(); i+=2)
1732 if (itemTopPref[i] != groupname)
1735 uint recordingID = itemTopPref[i+1].toUInt();
1740 if (pginfo && (pginfo->GetRecordingID() == recordingID))
1743 i = itemTopPref.size();
1752 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Reselect success (%1,%2)")
1753 .arg(sel).arg(top));
1760 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Reselect failure (%1,%2)")
1761 .arg(sel).arg(top));
1771 QStringList groupSelPref;
1772 QStringList itemSelPref;
1773 QStringList itemTopPref;
1775 groupSelPref, itemSelPref, itemTopPref))
1784 QMap<uint, AvailableStatusType> asCache;
1790 uint asRecordingID = prog->GetRecordingID();
1791 asCache[asRecordingID] = prog->GetAvailableStatus();
1810 bool isAllProgsGroup = (
m_recGroup ==
"All Programs");
1811 QMap<QString, QString> sortedList;
1812 QMap<int, QString> searchRule;
1813 QMap<int, QDateTime> recidLastEventTime;
1814 QMap<int, ProgramInfo*> recidWatchListProgram;
1825 query.
prepare(
"SELECT recordid,title FROM record "
1826 "WHERE search > 0 AND search != :MANUAL;");
1831 while (query.
next())
1833 QString tmpTitle = query.
value(1).toString();
1835 searchRule[query.
value(0).toInt()] = tmpTitle;
1841 bool isUnknownCategory = (
m_recGroup == tr(
"Unknown"));
1842 bool isDeletedGroup = (
m_recGroup ==
"Deleted");
1843 bool isLiveTvGroup = (
m_recGroup ==
"LiveTV");
1845 std::vector<ProgramInfo*> list;
1848 for (
auto *
p : list)
1850 if (
p->IsDeletePending())
1855 const QString& pRecgroup(
p->GetRecordingGroup());
1856 const bool isLiveTVProg(pRecgroup ==
"LiveTV");
1863 if (pRecgroup ==
"Deleted")
1867 if (!isDeletedGroup)
1872 !isLiveTvGroup && isLiveTVProg)
1881 else if (isCategoryFilter)
1884 if (isUnknownCategory ? !
p->GetCategory().isEmpty()
1889 else if (!isAllProgsGroup && pRecgroup !=
m_recGroup)
1894 if (
p->GetTitle().isEmpty())
1895 p->SetTitle(tr(
"_NO_TITLE_"));
1902 uint asRecordingID =
p->GetRecordingID();
1903 if (asCache.contains(asRecordingID))
1904 p->SetAvailableStatus(asCache[asRecordingID],
"UpdateUILists");
1910 QString tmpTitle = tr(
"Live TV");
1911 sortedList[tmpTitle.toLower()] = tmpTitle;
1913 m_progLists[tmpTitle.toLower()].setAutoDelete(
false);
1921 p->GetTitle(),
p->GetSortTitle(),
m_viewMask, titleSort,
1922 p->GetRecordingPriority());
1923 sTitle = sTitle.toLower();
1925 if (!sortedList.contains(sTitle))
1926 sortedList[sTitle] =
p->GetTitle();
1927 m_progLists[sortedList[sTitle].toLower()].push_front(
p);
1928 m_progLists[sortedList[sTitle].toLower()].setAutoDelete(
false);
1933 !pRecgroup.isEmpty() && !isLiveTVProg)
1935 sortedList[pRecgroup.toLower()] = pRecgroup;
1937 m_progLists[pRecgroup.toLower()].setAutoDelete(
false);
1943 QString catl =
p->GetCategory().toLower();
1944 sortedList[catl] =
p->GetCategory();
1950 !searchRule[
p->GetRecordingRuleID()].isEmpty() &&
1951 p->GetTitle() != searchRule[
p->GetRecordingRuleID()])
1953 QString tmpTitle = QString(
"(%1)")
1954 .arg(searchRule[
p->GetRecordingRuleID()]);
1955 sortedList[tmpTitle.toLower()] = tmpTitle;
1957 m_progLists[tmpTitle.toLower()].setAutoDelete(
false);
1961 !isLiveTVProg && pRecgroup !=
"Deleted")
1963 int rid =
p->GetRecordingRuleID();
1964 auto letIt = recidLastEventTime.find(rid);
1965 if (letIt == recidLastEventTime.end() || *letIt < p->GetLastModifiedTime())
1967 recidLastEventTime[rid] =
p->GetLastModifiedTime();
1973 LOG(VB_FILE, LOG_INFO, QString(
"Auto-expire off: %1")
1974 .arg(
p->GetTitle()));
1976 else if (
p->IsWatched())
1979 LOG(VB_FILE, LOG_INFO,
1980 QString(
"Marked as 'watched': %1")
1981 .arg(
p->GetTitle()));
1985 auto wlpIt = recidWatchListProgram.find(rid);
1986 if (wlpIt == recidWatchListProgram.end())
1988 recidWatchListProgram[rid] =
p;
1992 (*wlpIt)->SetRecordingPriority2(
wlEarlier);
1993 LOG(VB_FILE, LOG_INFO,
1994 QString(
"Not the earliest: %1")
1995 .arg((*wlpIt)->GetTitle()));
1997 recidWatchListProgram[rid] =
p;
2002 LOG(VB_FILE, LOG_INFO,
2003 QString(
"Not the earliest: %1")
2004 .arg(
p->GetTitle()));
2012 for (
auto *
p : std::as_const(recidWatchListProgram))
2021 if (sortedList.empty())
2023 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"SortedList is Empty");
2027 if (!isAllProgsGroup)
2039 if (episodeSort ==
"OrigAirDate")
2041 QMap<QString, ProgramList>::Iterator Iprog;
2044 if (!Iprog.key().isEmpty())
2046 std::stable_sort((*Iprog).begin(), (*Iprog).end(),
2053 else if (episodeSort ==
"Id")
2055 QMap<QString, ProgramList>::Iterator Iprog;
2058 if (!Iprog.key().isEmpty())
2060 std::stable_sort((*Iprog).begin(), (*Iprog).end(),
2067 else if (episodeSort ==
"Date")
2069 QMap<QString, ProgramList>::iterator it;
2072 if (!it.key().isEmpty())
2074 std::stable_sort((*it).begin(), (*it).end(),
2081 else if (episodeSort ==
"Season")
2083 QMap<QString, ProgramList>::iterator it;
2086 if (!it.key().isEmpty())
2088 std::stable_sort((*it).begin(), (*it).end(),
2099 query.
prepare(
"SELECT recordid, last_delete FROM record;");
2103 while (query.
next())
2105 int recid = query.
value(0).toInt();
2107 QDateTime last_delete =
2110 if (last_delete.isValid())
2112 auto it = recidLastEventTime.find(recid);
2113 if (it != recidLastEventTime.end() && last_delete > *it)
2115 recidLastEventTime[recid] = last_delete;
2124 int recid = (*pit)->GetRecordingRuleID();
2126 (*pit)->SetRecordingPriority2(recidLastEventTime[recid].toSecsSinceEpoch()/60);
2128 LOG(VB_FILE, LOG_INFO, QString(
" %1 %2 %3")
2131 .arg((*pit)->GetRecordingPriority2())
2132 .arg((*pit)->GetTitle()));
2146 !sortedList.contains(tr(
"Live TV")))
2162 query.
prepare(
"SELECT distinct recgroup from recorded WHERE "
2163 "deletepending = 0 ORDER BY recgroup");
2167 while (query.
next())
2169 name = query.
value(0).toString();
2170 if (name !=
"Deleted" && name !=
"LiveTV" && !name.startsWith(
'.'))
2184 for (
auto it = sortedList.keyValueBegin();
2185 it != sortedList.keyValueEnd(); ++it)
2187 first = (*it).first.at(0).toUpper();
2208 groupSelPref, itemSelPref, itemTopPref);
2221 while (!tmp.isEmpty())
2223 unsigned int i =
MythRandom(0, tmp.size() - 1);
2225 tmp.removeAll(tmp[i]);
2233 QCoreApplication::postEvent(
2247 const bool ignoreBookmark =
false;
2248 const bool ignoreProgStart =
false;
2249 const bool ignoreLastPlayPos =
false;
2250 const bool underNetworkControl =
false;
2252 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos,
2253 underNetworkControl);
2266 const bool ignoreBookmark =
false;
2267 const bool ignoreProgStart =
true;
2268 const bool ignoreLastPlayPos =
true;
2269 const bool underNetworkControl =
false;
2271 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos,
2272 underNetworkControl);
2285 const bool ignoreBookmark =
true;
2286 const bool ignoreProgStart =
true;
2287 const bool ignoreLastPlayPos =
true;
2288 const bool underNetworkControl =
false;
2290 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos,
2291 underNetworkControl);
2304 const bool ignoreBookmark =
true;
2305 const bool ignoreProgStart =
true;
2306 const bool ignoreLastPlayPos =
false;
2307 const bool underNetworkControl =
false;
2309 PlayX(*pginfo, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos,
2310 underNetworkControl);
2314 bool ignoreBookmark,
2315 bool ignoreProgStart,
2316 bool ignoreLastPlayPos,
2317 bool underNetworkControl)
2321 Play(pginfo,
false, ignoreBookmark, ignoreProgStart, ignoreLastPlayPos, underNetworkControl);
2368 LOG(VB_GENERAL, LOG_ERR, QString(
"deleteSelected(%1) -- failed ")
2370 QString(
"availability status: %1 ")
2371 .arg(pginfo->GetAvailableStatus()));
2374 tr(
"This recording is already being deleted"));
2376 else if (!pginfo->QueryIsDeleteCandidate())
2379 pginfo->QueryIsInUse(byWho);
2381 LOG(VB_GENERAL, LOG_ERR, QString(
"deleteSelected(%1) -- failed ")
2383 QString(
"delete candidate: %1 in use by %2")
2384 .arg(pginfo->QueryIsDeleteCandidate()).arg(byWho));
2386 if (byWho.isEmpty())
2389 tr(
"This recording is already being deleted"));
2394 tr(
"This recording is currently in use by:") +
"\n" +
2442 if (which ==
"groupmenu")
2462 else if (which ==
"actionmenu")
2476 QString label = tr(
"Group List Menu");
2517 bool inPlaylist,
bool ignoreBookmark,
bool ignoreProgStart,
2518 bool ignoreLastPlayPos,
bool underNetworkControl)
2520 bool playCompleted =
false;
2548 ignoreProgStart =
true;
2564 QCoreApplication::postEvent(
2571 return playCompleted;
2575 bool forceMetadataDelete)
2582 if (!forceMetadataDelete &&
2592 if (!forceMetadataDelete)
2597 forceMetadataDelete, forgetHistory);
2627 label = tr(
"Are you sure you want to delete:");
break;
2629 label = tr(
"Recording file does not exist.\n"
2630 "Are you sure you want to delete:");
2633 label = tr(
"Are you sure you want to stop:");
break;
2640 if (delItem !=
nullptr)
2690 tr(
"Yes, delete it and the remaining %1 list items")
2699 nullptr, !defaultIsYes);
2703 nullptr, !defaultIsYes);
2710 tr(
"No, and keep the remaining %1 list items")
2711 .arg(other_delete_cnt),
2731 tr(
"This recording is currently in "
2732 "use by:") +
"\n" + byWho);
2738 tr(
"This recording is currently "
2745 tr(
"This recording is currently being "
2746 "deleted and is unavailable"));
2751 tr(
"This recording has been "
2752 "deleted and is unavailable"));
2757 tr(
"The file for this recording can "
2763 tr(
"The file for this recording is "
2769 tr(
"This recording is not yet "
2776 QString label = tr(
"There is %n item(s) in the playlist. Actions affect "
2777 "all items in the playlist",
"",
m_playList.size());
2789 menu->AddItem(tr(
"Toggle playlist for this Category/Title"),
2794 menu->AddItem(tr(
"Toggle playlist for this Group"),
2800 menu->AddItem(tr(
"Toggle playlist for this recording"),
2807 menu->AddItem(tr(
"Delete, and allow re-record"),
2815 QString label = tr(
"There is %n item(s) in the playlist. Actions affect "
2816 "all items in the playlist",
"",
m_playList.size());
2833 QString label = tr(
"There is %n item(s) in the playlist. Actions affect "
2834 "all items in the playlist",
"",
m_playList.size());
2840 QList<uint>::Iterator it;
2841 bool isTranscoding =
true;
2842 bool isFlagging =
true;
2843 bool isMetadataLookup =
true;
2844 bool isRunningUserJob1 =
true;
2845 bool isRunningUserJob2 =
true;
2846 bool isRunningUserJob3 =
true;
2847 bool isRunningUserJob4 =
true;
2857 isTranscoding =
false;
2865 isMetadataLookup =
false;
2869 isRunningUserJob1 =
false;
2873 isRunningUserJob2 =
false;
2877 isRunningUserJob3 =
false;
2881 isRunningUserJob4 =
false;
2882 if (!isTranscoding && !isFlagging && !isRunningUserJob1 &&
2883 !isRunningUserJob2 && !isRunningUserJob3 && !isRunningUserJob4)
2898 if (!isMetadataLookup)
2904 if (!command.isEmpty())
2908 if (!isRunningUserJob1)
2910 menu->AddItem(tr(
"Begin") +
' ' + jobTitle,
2915 menu->AddItem(tr(
"Stop") +
' ' + jobTitle,
2921 if (!command.isEmpty())
2925 if (!isRunningUserJob2)
2927 menu->AddItem(tr(
"Begin") +
' ' + jobTitle,
2932 menu->AddItem(tr(
"Stop") +
' ' + jobTitle,
2938 if (!command.isEmpty())
2942 if (!isRunningUserJob3)
2944 menu->AddItem(tr(
"Begin") +
' ' + jobTitle,
2949 menu->AddItem(tr(
"Stop") +
' ' + jobTitle,
2955 if (!command.isEmpty())
2959 if (!isRunningUserJob4)
2961 menu->AddItem(QString(
"%1 %2").arg(tr(
"Begin"), jobTitle),
2966 menu->AddItem(QString(
"%1 %2").arg(tr(
"Stop"), jobTitle),
3039 menu->AddItem(tr(
"Play from last played position"),
3042 menu->AddItem(tr(
"Play from bookmark"),
3044 menu->AddItem(tr(
"Play from beginning"),
3047 menu->AddItem(tr(
"Clear last played position"),
3063 tr(
"Disable Auto Expire") : tr(
"Enable Auto Expire");
3065 tr(
"Do not preserve this episode") : tr(
"Preserve this episode");
3086 menu->AddItem(tr(
"Edit Recording Schedule"),
3100static const std::array<const int,kMaxJobs>
kJobs
3131 const std::array<const bool,kMaxJobs> add
3141 const std::array<const QString,kMaxJobs*2> desc
3144 tr(
"Stop Transcoding"), tr(
"Begin Transcoding"),
3145 tr(
"Stop Commercial Detection"), tr(
"Begin Commercial Detection"),
3146 tr(
"Stop Metadata Lookup"), tr(
"Begin Metadata Lookup"),
3153 for (
size_t i = 0; i <
kMaxJobs; i++)
3158 QString stop_desc = desc[(i*2)+0];
3159 QString start_desc = desc[(i*2)+1];
3161 if (start_desc.toUInt())
3164 "UserJobDesc"+start_desc, tr(
"User Job") +
" #" + start_desc);
3165 stop_desc = tr(
"Stop") +
' ' + jobTitle;
3166 start_desc = tr(
"Begin") +
' ' + jobTitle;
3174 menu->AddItem(running ? stop_desc : start_desc,
3175 kMySlots[(i * 2) + (running ? 0 : 1)], submenu);
3183 QString label = tr(
"Transcoding profiles");
3187 menu->AddItemV(tr(
"Default"), QVariant::fromValue(-1));
3188 menu->AddItemV(tr(
"Autodetect"), QVariant::fromValue(0));
3191 query.
prepare(
"SELECT r.name, r.id "
3192 "FROM recordingprofiles r, profilegroups p "
3193 "WHERE p.name = 'Transcoders' "
3194 "AND r.profilegroup = p.id "
3195 "AND r.name != 'RTjpeg/MPEG4' "
3196 "AND r.name != 'MPEG2' ");
3204 while (query.
next())
3206 QString transcoder_name = query.
value(0).toString();
3207 int transcoder_id = query.
value(1).toInt();
3210 if (transcoder_name ==
"High Quality")
3211 transcoder_name = tr(
"High Quality");
3212 else if (transcoder_name ==
"Medium Quality")
3213 transcoder_name = tr(
"Medium Quality");
3214 else if (transcoder_name ==
"Low Quality")
3215 transcoder_name = tr(
"Low Quality");
3217 menu->AddItemV(transcoder_name, QVariant::fromValue(transcoder_id));
3242 label = tr(
"Recording file cannot be found");
3244 label = tr(
"Recording file contains no data");
3246 tr(
"Recording Options");
3288 bool sameProgram =
false;
3375 QString timedate = QString(
"%1 - %2")
3389 return QString(
"\n%1%2\n%3").arg(title, extra, timedate);
3394 QList<uint>::Iterator it;
3452 QList<uint>::Iterator it;
3457 if (pginfo !=
nullptr)
3528 "",
"", jobHost, jobFlags);
3535 QList<uint>::Iterator it;
3570 QString forceDeleteStr(
"0");
3581 list.push_back(forceDeleteStr);
3582 list.push_back(forgetHistory ?
"1" :
"0");
3603 uint recordingID = 0;
3610 uint recordingID = 0;
3626 QCoreApplication::postEvent(
this, e);
3634 QString title = pginfo->
GetTitle().toLower();
3666 const QString& recgroup)
3669 std::array<ProgramList::iterator,2> _it {
3671 std::array<ProgramList::iterator,2> _end {
3674 if (recgroup !=
"LiveTV")
3676 swap( _it[0], _it[1]);
3677 swap(_end[0], _end[1]);
3680 for (
uint i = 0; i < 2; i++)
3683 const auto& end = _end[i];
3684 for (; it != end; ++it)
3686 if ((*it)->GetRecordingID() == recordingID)
3709 pginfo->SaveWatched(on);
3750 pginfo->SavePreserve(on);
3769 for (
auto *pl : std::as_const(
m_progLists[groupname]))
3771 if (pl && (pl->GetAvailableStatus() ==
asAvailable))
3845 QStringList tokens = command.simplified().split(
" ");
3847 if (tokens.size() >= 4 && (tokens[1] ==
"PLAY" || tokens[1] ==
"RESUME"))
3849 if (tokens.size() == 6 && tokens[2] ==
"PROGRAM")
3851 int clientID = tokens[5].toInt();
3853 LOG(VB_GENERAL, LOG_INFO,
LOC +
3854 QString(
"NetworkControl: Trying to %1 program '%2' @ '%3'")
3855 .arg(tokens[1], tokens[3], tokens[4]));
3859 LOG(VB_GENERAL, LOG_ERR,
LOC +
3860 "NetworkControl: Already playing");
3862 QString msg = QString(
3863 "NETWORK_CONTROL RESPONSE %1 ERROR: Unable to play, "
3864 "player is already playing another recording.")
3872 uint chanid = tokens[3].toUInt();
3878 QString msg = QString(
"NETWORK_CONTROL RESPONSE %1 OK")
3885 const bool ignoreBookmark = (tokens[1] ==
"PLAY");
3886 const bool ignoreProgStart =
true;
3887 const bool ignoreLastPlayPos =
true;
3888 const bool underNetworkControl =
true;
3889 PlayX(pginfo, ignoreBookmark, ignoreProgStart,
3890 ignoreLastPlayPos, underNetworkControl);
3894 QString message = QString(
"NETWORK_CONTROL RESPONSE %1 "
3895 "ERROR: Could not find recording for "
3897 .arg(tokens[5], tokens[3], tokens[4]);
3908 if ((event->key() == Qt::Key_LaunchMedia) &&
3909 (event->modifiers() ==
3910 (Qt::ShiftModifier |
3911 Qt::ControlModifier |
3914 Qt::KeypadModifier)))
3928 QStringList actions;
3932 for (
int i = 0; i < actions.size() && !handled; ++i)
3934 const QString&
action = actions[i];
3941 else if (
action ==
"MENU")
3945 else if (
action ==
"NEXTFAV")
3952 else if (
action ==
"TOGGLEFAV")
3978 if (!nextGroup.isEmpty())
3981 else if (
action ==
"NEXTVIEW")
3988 else if (
action ==
"PREVVIEW")
4003 else if (
action ==
"CHANGERECGROUP")
4007 else if (
action ==
"CHANGEGROUPVIEW")
4011 else if (
action ==
"EDIT")
4023 else if (
action ==
"CUSTOMEDIT")
4025 else if (
action ==
"GUIDE")
4027 else if (
action ==
"UPCOMING")
4056 QString resultid = dce->
GetId();
4058 if (resultid ==
"transcode" && dce->GetResult() >= 0)
4063 auto *me =
dynamic_cast<MythEvent *
>(event);
4067 const QString& message = me->
Message();
4069 if (message.startsWith(
"RECORDING_LIST_CHANGE"))
4071 QStringList tokens = message.simplified().split(
" ");
4072 uint recordingID = 0;
4073 if (tokens.size() >= 3)
4074 recordingID = tokens[2].toUInt();
4076 if ((tokens.size() >= 2) && tokens[1] ==
"UPDATE")
4086 else if (recordingID && (tokens[1] ==
"ADD"))
4095 else if (recordingID && (tokens[1] ==
"DELETE"))
4104 else if (message.startsWith(
"NETWORK_CONTROL"))
4106 QStringList tokens = message.simplified().split(
" ");
4107 if ((tokens[1] !=
"ANSWER") && (tokens[1] !=
"RESPONSE"))
4114 Qt::KeyboardModifiers modifiers =
4116 Qt::ControlModifier |
4120 auto *keyevent =
new QKeyEvent(QEvent::KeyPress,
4121 Qt::Key_LaunchMedia, modifiers);
4124 keyevent =
new QKeyEvent(QEvent::KeyRelease,
4125 Qt::Key_LaunchMedia, modifiers);
4129 else if (message.startsWith(
"UPDATE_FILE_SIZE"))
4131 QStringList tokens = message.simplified().split(
" ");
4132 if (tokens.size() >= 3)
4135 uint recordingID = tokens[1].toUInt();
4136 uint64_t filesize = tokens[2].toLongLong(&ok);
4142 recordingID, filesize,
4147 else if (message ==
"UPDATE_UI_LIST")
4159 else if (message.startsWith(
"UPDATE_UI_ITEM"))
4161 QStringList tokens = message.simplified().split(
" ");
4162 if (tokens.size() < 3)
4165 uint recordingID = tokens[1].toUInt();
4171 else if (message ==
"UPDATE_USAGE_UI")
4175 else if (message ==
"RECONNECT_SUCCESS")
4179 else if (message ==
"LOCAL_PBB_DELETE_RECORDINGS")
4182 for (
uint i = 0; i+2 < (
uint)me->ExtraDataList().size(); i+=3)
4184 uint recordingID = me->ExtraDataList()[i+0].toUInt();
4190 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4191 QString(
"LOCAL_PBB_DELETE_RECORDINGS - "
4192 "No matching recording %1")
4197 QString forceDeleteStr = me->ExtraDataList()[i+1];
4198 QString forgetHistoryStr = me->ExtraDataList()[i+2];
4201 list.push_back(forceDeleteStr);
4202 list.push_back(forgetHistoryStr);
4204 "LOCAL_PBB_DELETE_RECORDINGS");
4216 else if (message ==
"DELETE_SUCCESSES")
4220 else if (message ==
"DELETE_FAILURES")
4222 if (me->ExtraDataList().size() < 3)
4225 for (
uint i = 0; i+2 < (
uint)me->ExtraDataList().size(); i += 3)
4228 me->ExtraDataList()[i+0].toUInt());
4236 bool forceDelete = me->ExtraDataList()[1].toUInt() != 0U;
4245 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4246 "Delete failures not handled due to "
4247 "pre-existing popup.");
4254 else if (message ==
"PREVIEW_SUCCESS")
4258 else if (message ==
"PREVIEW_FAILED" && me->ExtraDataCount() >= 5)
4260 for (
uint i = 4; i < (
uint) me->ExtraDataCount(); i++)
4262 const QString& token = me->ExtraData(i);
4268 else if (message ==
"AVAILABILITY" && me->ExtraDataCount() == 8)
4270 static constexpr std::chrono::milliseconds kMaxUIWaitTime = 10s;
4271 QStringList list = me->ExtraDataList();
4272 uint recordingID = list[0].toUInt();
4275 uint64_t fs = list[3].toULongLong();
4277 tm.setHMS(list[4].toUInt(), list[5].toUInt(),
4278 list[6].toUInt(), list[7].toUInt());
4279 QTime now = QTime::currentTime();
4280 auto time_elapsed = std::chrono::milliseconds(tm.msecsTo(now));
4281 if (time_elapsed < 0ms)
4282 time_elapsed += 24h;
4293 if (time_elapsed >= kMaxUIWaitTime)
4302 (time_elapsed < kMaxUIWaitTime))
4312 const bool ignoreBookmark =
false;
4313 const bool ignoreProgStart =
false;
4314 const bool ignoreLastPlayPos =
true;
4315 const bool underNetworkControl =
false;
4317 ignoreBookmark, ignoreProgStart, ignoreLastPlayPos,
4318 underNetworkControl);
4326 QCoreApplication::postEvent(
4330 if (old_avail != availableStatus)
4333 else if ((message ==
"PLAY_PLAYLIST") && !
m_playListPlay.empty())
4347 const bool ignoreBookmark =
false;
4348 const bool ignoreProgStart =
true;
4349 const bool ignoreLastPlayPos =
true;
4350 const bool underNetworkControl =
false;
4352 Play(*pginfo,
true, ignoreBookmark, ignoreProgStart,
4353 ignoreLastPlayPos, underNetworkControl);
4355 else if ((message ==
"SET_PLAYBACK_URL") && (me->ExtraDataCount() == 2))
4357 uint recordingID = me->ExtraData(0).toUInt();
4360 info->SetPathname(me->ExtraData(1));
4362 else if ((message ==
"FOUND_ARTWORK") && (me->ExtraDataCount() >= 5))
4365 uint recordingID = me->ExtraData(3).toUInt();
4366 const QString& group = me->ExtraData(4);
4367 const QString& fn = me->ExtraData(5);
4381 else if (!group.isEmpty() &&
4391 else if (message ==
"EXIT_TO_MENU" ||
4392 message ==
"CANCEL_PLAYLIST")
4407 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4408 QString(
"Failed to remove %1, reloading list")
4417 groupname = sel_item->
GetData().toString();
4422 auto pit = (*git).begin();
4423 while (pit != (*git).end())
4425 if ((*pit)->GetRecordingID() == recordingID)
4427 if (!git.key().isEmpty() && git.key() == groupname)
4431 QVariant::fromValue(*pit));
4435 if (item_cur && (item_by_data == item_cur))
4445 pit = (*git).erase(pit);
4455 if (!groupname.isEmpty() && (git.key() == groupname))
4464 sel_item = next_item;
4467 groupname = sel_item->
GetData().toString();
4496 if (pginfo ==
nullptr)
4506 QCoreApplication::postEvent(
this,
new MythEvent(
"UPDATE_UI_LIST"));
4513 if (helpPopup->Create())
4523 if (viewPopup->Create())
4545 QStringList groupNames;
4546 QStringList displayNames;
4548 QStringList displayGroups;
4554 uint totalItems = 0;
4557 displayNames.append(QString(
"------- %1 -------").arg(tr(
"Groups")));
4558 groupNames.append(
"");
4561 query.
prepare(
"SELECT recgroup, COUNT(title) FROM recorded "
4562 "WHERE deletepending = 0 AND watched <= :WATCHED "
4563 "GROUP BY recgroup");
4567 while (query.
next())
4569 QString dispGroup = query.
value(0).toString();
4573 (dispGroup !=
"Deleted"))
4574 totalItems += items;
4576 groupNames.append(dispGroup);
4578 dispGroup = (dispGroup ==
"Default") ? tr(
"Default") : dispGroup;
4579 dispGroup = (dispGroup ==
"Deleted") ? tr(
"Deleted") : dispGroup;
4580 dispGroup = (dispGroup ==
"LiveTV") ? tr(
"Live TV") : dispGroup;
4582 displayNames.append(tr(
"%1 [%n item(s)]",
nullptr, items).arg(dispGroup));
4589 displayNames.push_front(tr(
"%1 [%n item(s)]",
nullptr, totalItems)
4591 groupNames.push_front(
"All Programs");
4595 query.
prepare(
"SELECT DISTINCT category, COUNT(title) FROM recorded "
4596 "WHERE deletepending = 0 AND watched <= :WATCHED "
4597 "GROUP BY category");
4601 int unknownCount = 0;
4602 while (query.
next())
4605 QString dispGroup = query.
value(0).toString();
4606 if (dispGroup.isEmpty())
4608 unknownCount += items;
4609 dispGroup = tr(
"Unknown");
4611 else if (dispGroup == tr(
"Unknown"))
4613 unknownCount += items;
4617 (dispGroup != tr(
"Unknown")))
4619 displayGroups += tr(
"%1 [%n item(s)]",
nullptr, items).arg(dispGroup);
4620 groups += dispGroup;
4626 if (unknownCount > 0)
4628 QString dispGroup = tr(
"Unknown");
4629 uint items = unknownCount;
4630 displayGroups += tr(
"%1 [%n item(s)]",
nullptr, items).arg(dispGroup);
4631 groups += dispGroup;
4638 displayNames.append(QString(
"------- %1 -------").arg(tr(
"Categories")));
4639 groupNames.append(
"");
4641 displayGroups.sort();
4642 QStringList::iterator it;
4643 for (it = displayGroups.begin(); it != displayGroups.end(); ++it)
4644 displayNames.append(*it);
4645 for (it = groups.begin(); it != groups.end(); ++it)
4646 groupNames.append(*it);
4648 QString label = tr(
"Change Filter");
4653 if (recGroupPopup->Create())
4665 delete recGroupPopup;
4682 QString newRecGroup = recGroup;
4684 if (newRecGroup.isEmpty())
4691 newRecGroup =
"Default";
4693 newRecGroup =
"All Programs";
4695 newRecGroup =
"LiveTV";
4697 newRecGroup =
"Deleted";
4729 query.
prepare(
"SELECT recgroup, password FROM recgroups "
4730 "WHERE password IS NOT NULL AND password <> '';");
4734 while (query.
next())
4736 QString recgroup = query.
value(0).toString();
4739 recgroup =
"Default";
4741 recgroup =
"All Programs";
4743 recgroup =
"LiveTV";
4745 recgroup =
"Deleted";
4773 "SELECT g.recgroup, COUNT(r.title) FROM recgroups g "
4774 "LEFT JOIN recorded r ON g.recgroupid=r.recgroupid AND r.deletepending = 0 "
4775 "WHERE g.recgroupid != 2 AND g.recgroupid != 3 "
4776 "GROUP BY g.recgroupid ORDER BY g.recgroup");
4778 QStringList displayNames(tr(
"Add New"));
4779 QStringList groupNames(
"addnewgroup");
4784 while (query.
next())
4786 QString dispGroup = query.
value(0).toString();
4787 groupNames.push_back(dispGroup);
4789 if (dispGroup ==
"Default")
4790 dispGroup = tr(
"Default");
4791 else if (dispGroup ==
"LiveTV")
4792 dispGroup = tr(
"Live TV");
4793 else if (dispGroup ==
"Deleted")
4794 dispGroup = tr(
"Deleted");
4796 displayNames.push_back(tr(
"%1 [%n item(s)]",
"", query.
value(1).toInt())
4800 QString label = tr(
"Select Recording Group") +
4806 if (rgChanger->Create())
4836 QStringList groupNames(tr(
"Default"));
4837 QStringList displayNames(
"Default");
4840 groupNames.reserve(1 + list.size());
4841 displayNames.reserve(1 + list.size());
4842 for (
const auto& name : std::as_const(list))
4844 displayNames.push_back(name);
4845 groupNames.push_back(name);
4848 QString label = tr(
"Select Playback Group") +
4854 if (pgChanger->Create())
4868 QList<uint>::Iterator it;
4873 if (tmpItem !=
nullptr)
4885 QList<uint>::Iterator it;
4890 if (tmpItem !=
nullptr)
4908 if (editMetadata->Create())
4916 delete editMetadata;
4921 const QString &newSubtitle,
4922 const QString &newDescription,
4923 const QString &newInetref,
4939 if (groupname == pginfo->GetTitle().toLower() &&
4940 newTitle != pginfo->GetTitle())
4946 QString tempSubTitle = newTitle;
4947 if (!newSubtitle.trimmed().isEmpty())
4948 tempSubTitle = QString(
"%1 - \"%2\"")
4949 .arg(tempSubTitle, newSubtitle);
4955 if (newSeason > 0 || newEpisode > 0)
4959 seasone = QString(
"s%1e%2")
4962 seasonx = QString(
"%1x%2")
4967 item->
SetText(tempSubTitle,
"titlesubtitle");
4968 item->
SetText(newTitle,
"title");
4969 item->
SetText(newSubtitle,
"subtitle");
4970 item->
SetText(newInetref,
"inetref");
4971 item->
SetText(seasonx,
"00x00");
4972 item->
SetText(seasone,
"s00e00");
4973 item->
SetText(season,
"season");
4974 item->
SetText(episode,
"episode");
4975 if (newDescription !=
nullptr)
4976 item->
SetText(newDescription,
"description");
4979 pginfo->SaveInetRef(newInetref);
4980 pginfo->SaveSeasonEpisode(newSeason, newEpisode);
4989 newRecGroup = newRecGroup.simplified();
4991 if (newRecGroup.isEmpty())
4994 if (newRecGroup ==
"addnewgroup")
5000 tr(
"New Recording Group"));
5005 if (newgroup->Create())
5025 if ((
p->GetRecordingGroup() ==
"LiveTV") &&
5026 (newRecGroup !=
"LiveTV"))
5028 p->SaveAutoExpire(defaultAutoExpire);
5030 else if ((
p->GetRecordingGroup() !=
"LiveTV") &&
5031 (newRecGroup ==
"LiveTV"))
5049 if ((
p->GetRecordingGroup() ==
"LiveTV") && (newRecGroup !=
"LiveTV"))
5050 p->SaveAutoExpire(defaultAutoExpire);
5051 else if ((
p->GetRecordingGroup() !=
"LiveTV") && (newRecGroup ==
"LiveTV"))
5064 if (newPlayGroup.isEmpty() || !tmpItem)
5067 if (newPlayGroup == tr(
"Default"))
5068 newPlayGroup =
"Default";
5072 QList<uint>::Iterator it;
5105 if (pwChanger->Create())
5121 query.
prepare(
"UPDATE recgroups SET password = :PASSWD WHERE "
5122 "recgroup = :RECGROUP");
5124 query.
bindValue(
":PASSWD", newPassword);
5130 if (newPassword.isEmpty())
5149 LOG(VB_GENERAL, LOG_ERR,
LOC +
5150 "Theme is missing 'groups' button list.");
5157 for (
int i = 0; i <
m_list.size(); ++i)
5160 QVariant::fromValue(
m_data.at(i)));
5180 if (item->
GetData().toString().isEmpty())
5183 QString group = item->
GetData().toString();
5291 LOG(VB_GENERAL, LOG_ERR,
LOC +
5292 "Window 'passwordchanger' is missing required elements.");
5355 LOG(VB_GENERAL, LOG_ERR,
LOC +
5356 "Window 'editmetadata' is missing required elements.");
5397 QString newRecDescription =
nullptr;
5398 QString newRecInetref =
nullptr;
5399 uint newRecSeason = 0;
5400 uint newRecEpisode = 0;
5407 if (newRecTitle.isEmpty())
5410 emit
result(newRecTitle, newRecSubtitle, newRecDescription,
5411 newRecInetref, newRecSeason, newRecEpisode);
5421 "recording online..."),
5449 lookup->SetSubtype(
type);
5451 lookup->SetAllowGeneric(
true);
5452 lookup->SetHandleImages(
false);
5460 lookup->SetAutomatic(
false);
5509 Qt::QueuedConnection);
5511 if (resultsdialog->Create())
5524 if (!mfsr || !mfsr->m_result)
5542 QString title = tr(
"No match found for this recording. You can "
5543 "try entering a TVDB/TMDB number, season, and "
5544 "episode manually.");
5548 if (okPopup->Create())
5564 LOG(VB_GENERAL, LOG_ERR,
LOC +
5565 "Window 'iconhelp' is missing required elements.");
5571 addItem(
"watched", tr(
"Recording has been watched"));
5572 addItem(
"commflagged", tr(
"Commercials are flagged"));
5573 addItem(
"cutlist", tr(
"An editing cutlist is present"));
5574 addItem(
"autoexpire", tr(
"The program is able to auto-expire"));
5575 addItem(
"processing", tr(
"Commercials are being flagged"));
5576 addItem(
"bookmark", tr(
"A bookmark is set"));
5578 addItem(
"inuse", tr(
"Recording is in use"));
5579 addItem(
"transcoded", tr(
"Recording has been transcoded"));
5582 addItem(
"mono", tr(
"Recording is in Mono"));
5583 addItem(
"stereo", tr(
"Recording is in Stereo"));
5584 addItem(
"surround", tr(
"Recording is in Surround Sound"));
5585 addItem(
"dolby", tr(
"Recording is in Dolby Surround Sound"));
5587 addItem(
"cc", tr(
"Recording is Closed Captioned"));
5588 addItem(
"subtitles", tr(
"Recording has Subtitles Available"));
5589 addItem(
"onscreensub", tr(
"Recording is Subtitled"));
5591 addItem(
"SD", tr(
"Recording is in Standard Definition"));
5592 addItem(
"widescreen", tr(
"Recording is Widescreen"));
5593 addItem(
"hdtv", tr(
"Recording is in High Definition"));
5594 addItem(
"hd720", tr(
"Recording is in 720p High Definition"));
5595 addItem(
"hd1080i", tr(
"Recording is in 1080i High Definition"));
5596 addItem(
"hd1080p", tr(
"Recording is in 1080p High Definition"));
5597 addItem(
"uhd4Ki", tr(
"Recording is in 4k(interlaced) UHD resolution"));
5598 addItem(
"uhd4Kp", tr(
"Recording is in 4k UHD resolution"));
5599 addItem(
"mpeg2", tr(
"Recording is using MPEG-2 codec"));
5600 addItem(
"avchd", tr(
"Recording is using AVC/H.264 codec"));
5601 addItem(
"hevc", tr(
"Recording is using HEVC/H.265 codec"));
5610 item->DisplayState(state,
"icons");
5615 QDateTime now = QDateTime::currentDateTime();
5619 QMap<int, JobQueueEntry> jobs;
5622 for (
const auto& job : std::as_const(jobs))
5624 m_jobs.insert(qMakePair(job.chanid, job.recstartts), job);
5631 const QDateTime &recstartts)
5634 QList<JobQueueEntry> values = m_jobs.values(qMakePair(chanid, recstartts));
5635 auto end = values.cend();
5636 for (
auto iter = values.cbegin(); iter != end; ++iter)
5638 if (iter->type == jobType)
5645 const QDateTime &recstartts)
5648 QList<JobQueueEntry> values = m_jobs.values(qMakePair(chanid, recstartts));
5649 auto end = values.cend();
5650 for (
auto iter = values.cbegin(); iter != end; ++iter)
5652 if (iter->type == jobType)
5659 const QDateTime &recstartts)
5661 return IsJobQueued(jobType, chanid, recstartts) ||
5662 IsJobRunning(jobType, chanid, recstartts);
5665#include "moc_playbackbox.cpp"
bool Create(void) override
PlaybackBox * m_parentScreen
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
static const Type kEventType
bool Create(void) override
void AcceptItem(MythUIButtonListItem *item)
static bool ChangeJobCmds(int jobID, int newCmds)
static int GetJobsInQueue(QMap< int, JobQueueEntry > &jobs, int findJobs=JOB_LIST_NOT_DONE)
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())
static bool IsJobStatusQueued(int status)
static bool IsJobQueuedOrRunning(int jobType, uint chanid, const QDateTime &recstartts)
static bool IsJobStatusRunning(int status)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Dialog asking for user confirmation.
void SaveBoolSetting(const QString &key, bool newValue)
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
T GetDurSetting(const QString &key, T defaultval=T::zero())
void dispatch(const MythEvent &event)
int GetNumSetting(const QString &key, int defaultval=0)
QString GetMasterHostName(void)
bool GetBoolSetting(const QString &key, bool defaultval=false)
static void DBError(const QString &where, const MSqlQuery &query)
Basic menu dialog, message and a list of options.
void Closed(QString, int)
bool Create(void) override
This class is used as a container for messages.
const QString & Message() const
static const Type kMythEventMessage
MythScreenStack * GetMainStack()
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
MythScreenStack * GetStack(const QString &Stackname)
void addListener(QObject *listener)
Add a listener to the observable.
void removeListener(QObject *listener)
Remove a listener to the observable.
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Screen in which all other widgets are contained and rendered.
void LoadInBackground(const QString &message="")
void BuildFocusList(void)
MythUIType * GetFocusWidget(void) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool SetFocusWidget(MythUIType *widget=nullptr)
Dialog prompting the user to enter a text string.
bool Create(void) override
A checkbox widget supporting three check states - on,off,half and two conditions - selected and unsel...
void SetCheckState(MythUIStateType::StateType state)
virtual void SetTextFromMap(const InfoMap &infoMap)
virtual void ResetMap(const InfoMap &infoMap)
Image widget, displays a single image or multiple images in sequence.
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
void Reset(void) override
Reset the image back to the default defined in the theme.
void Set(int start, int total, int used)
A widget for offering a range of numerical values where only the the bounding values and interval are...
void SetRange(int low, int high, int step, uint pageMultiple=5)
Set the lower and upper bounds of the spinbox, the interval and page amount.
void SetValue(int val) override
int GetIntValue(void) const override
This widget is used for grouping other widgets for display when a particular named state is called.
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
bool DisplayState(const QString &name)
A text entry and edit widget.
void SetPassword(bool isPassword)
QString GetText(void) const
void SetText(const QString &text, bool moveCursor=true)
void SetMaxLength(int length)
All purpose text widget, displays a text string.
virtual void SetText(const QString &text)
void SetCanTakeFocus(bool set=true)
Set whether this widget can take focus.
virtual void SetVisible(bool visible)
void SetEnabled(bool enable)
MythUIType * GetChild(const QString &name) const
Get a named child of this UIType.
MythUIButton * m_okButton
MythUITextEdit * m_newPasswordEdit
bool Create(void) override
MythUITextEdit * m_oldPasswordEdit
void OldPasswordChanged(void)
void result(const QString &)
static QStringList GetNames(void)
QString GetPreviewImage(const ProgramInfo &pginfo, bool check_availability=true)
void DeleteRecording(uint recordingID, bool forceDelete, bool forgetHistory)
QString LocateArtwork(const QString &inetref, uint season, VideoArtworkType type, const ProgramInfo *pginfo, const QString &groupname=nullptr)
void DeleteRecordings(const QStringList &list)
uint64_t GetFreeSpaceTotalMB(void) const
void StopRecording(const ProgramInfo &pginfo)
void CheckAvailability(const ProgramInfo &pginfo, CheckAvailabilityType cat=kCheckForCache)
void UndeleteRecording(uint recordingID)
void ForceFreeSpaceUpdate(void)
uint64_t GetFreeSpaceUsedMB(void) const
bool IsJobQueued(int jobType, uint chanid, const QDateTime &recstartts)
static constexpr std::chrono::milliseconds kInvalidateTimeMs
bool IsJobRunning(int jobType, uint chanid, const QDateTime &recstartts)
bool IsJobQueuedOrRunning(int jobType, uint chanid, const QDateTime &recstartts)
void stopPlaylistUserJob2()
MythUIImage * m_previewImage
void UpdateUIGroupList(const QStringList &groupPreferences)
~PlaybackBox(void) override
void setRecGroup(QString newRecGroup)
void stopPlaylistUserJob4()
QList< uint > m_playList
list of selected items "play list"
void changeProfileAndTranscode(int id)
QString extract_commflag_state(const ProgramInfo &pginfo)
void doPlaylistBeginUserJob4()
void toggleLiveTVView(bool setOn)
std::array< QTimer *, kNumArtImages > m_artTimer
QString extract_job_state(const ProgramInfo &pginfo)
void doPlaylistBeginUserJob3()
static std::array< PlaybackBoxCb, kMaxJobs *2 > kMySlots
bool Create(void) override
void doPlaylistBeginUserJob2()
void ShowActionPopup(const ProgramInfo &pginfo)
void saveViewChanges(void)
bool m_playingSomething
playingSomething is set to true iff a full screen recording is playing
void toggleTitleView(bool setOn)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool IsUsageUIVisible(void) const
void updateRecGroup(MythUIButtonListItem *sel_item)
void stopPlaylistFlagging()
void SelectNextRecGroup(void)
void Load(void) override
Load data which will ultimately be displayed on-screen or used to determine what appears on-screen (S...
QString m_watchGroupLabel
int m_allOrder
allOrder controls the ordering of the "All Programs" list
void ShowRecordedEpisodes()
void HandleRecordingAddEvent(const ProgramInfo &evinfo)
void ScheduleUpdateUIList(void)
void toggleWatchedView(bool setOn)
void ItemLoaded(MythUIButtonListItem *item)
void customEvent(QEvent *event) override
void PlaylistDelete(bool forgetHistory=false)
void doPlaylistWatchedSetOff()
void doPlaylistJobQueueJob(int jobType, int jobFlags=0)
void ItemVisible(MythUIButtonListItem *item)
void UpdateUIRecGroupList(void)
void saveRecMetadata(const QString &newTitle, const QString &newSubtitle, const QString &newDescription, const QString &newInetref, uint season, uint episode)
void ItemSelected(MythUIButtonListItem *item)
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
void DeleteIgnoreAllRemaining(void)
void toggleCategoryView(bool setOn)
void ShowDeletePopup(DeletePopupType type)
void ShowGroupPopup(void)
void stopPlaylistLookup()
QStringList m_playerSelectedNewShow
std::chrono::hours m_watchListBlackOut
adjust exclusion of a title from the Watch List after a delete
void doPlaylistExpireSetOn()
MythMenu * createStorageMenu()
QStringList m_delList
Recording[s] currently selected for deletion.
void ShowRecGroupChanger(bool use_playlist=false)
Used to change the recording group of a program or playlist.
ProgramInfo * FindProgramInUILists(const ProgramInfo &pginfo)
void showViewChanger(void)
void stopPlaylistUserJob3()
void togglePlayListItem(void)
MythUIProgressBar * m_watchedProgress
static QString CreateProgramInfoString(const ProgramInfo &pginfo)
QSet< QString > m_previewTokens
Outstanding preview image requests.
bool m_needUpdate
Does the recording list need to be refilled.
MythUIProgressBar * m_recordedProgress
void selected(MythUIButtonListItem *item)
void DeleteForceAllRemaining(void)
void processNetworkControlCommand(const QString &command)
MythMenu * createTranscodingProfilesMenu()
class PlaybackBox::PbbJobQueue m_jobQueue
void doBeginTranscoding()
void stopPlaylistUserJob1()
void stopPlaylistJobQueueJob(int jobType)
int m_progsInDB
total number of recordings in DB
void doPlaylistBeginUserJob1()
ProgramMap m_progLists
lists of programs by page
QStringList m_titleList
list of pages
void updateRecList(MythUIButtonListItem *sel_item)
MythMenu * createRecordingMenu()
static void * RunPlaybackBox(void *player, bool showTV)
MythUIText * m_noRecordingsText
MythScreenStack * m_popupStack
MythMenu * createPlaylistJobMenu()
void displayRecGroup(const QString &newRecGroup="")
static constexpr int kNumArtImages
QList< uint > m_playListPlay
list of items being played.
void toggleRecGroupView(bool setOn)
void showRecGroupPasswordChanger()
int m_watchListMaxAge
add 1 to the Watch List scord up to this many days
void doPlaylistExpireSetting(bool turnOn)
void setGroupFilter(const QString &newRecGroup)
void PlaylistDeleteForgetHistory(void)
void doAllowRerecord()
Callback function when Allow Re-record is pressed in Watch Recordings.
void doPlaylistWatchedSetOn()
std::deque< QString > m_networkControlCommands
void RemoveProgram(uint recordingID, bool forgetHistory, bool forceMetadataDelete)
void showMetadataEditor()
void deleteSelected(MythUIButtonListItem *item)
MythDialogBox * m_menuDialog
void popupClosed(const QString &which, int result)
void toggleWatchListView(bool setOn)
void groupSelectorClosed(void)
void togglePreserveEpisode()
void PlayFromLastPlayPos()
QString m_currentGroup
Group currently selected.
void doJobQueueJob(int jobType, int jobFlags=0)
void togglePlayListTitle(void)
void doPlaylistBeginLookup()
MythMenu * createPlaylistStorageMenu()
void ShowPlayGroupChanger(bool use_playlist=false)
Used to change the play group of a program or playlist.
bool m_watchListStart
use the Watch List as the initial view
PlaybackBox(MythScreenStack *parent, const QString &name, TV *player=nullptr, bool showTV=false)
MythMenu * createPlayFromMenu()
std::array< MythUIImage *, kNumArtImages > m_artImage
QString m_curGroupPassword
MythUIButtonList * m_recordingList
void HandleRecordingRemoveEvent(uint recordingID)
void ShowPlayGroupChangerNoPlaylist(void)
ProgramInfoCache m_programInfoCache
MythUIButtonList * m_groupList
void ShowRecGroupChangerNoPlaylist(void)
QMap< QString, QString > m_recGroupPwCache
MythMenu * createPlaylistMenu()
void checkPassword(const QString &password)
bool m_watchListAutoExpire
exclude recording not marked for auto-expire from the Watch List
QString getRecGroupPassword(const QString &recGroup)
void SetItemIcons(MythUIButtonListItem *item, ProgramInfo *pginfo)
void toggleSearchView(bool setOn)
bool Play(const ProgramInfo &rec, bool inPlaylist, bool ignoreBookmark, bool ignoreProgStart, bool ignoreLastPlayPos, bool underNetworkControl)
void playSelectedPlaylist(bool Random)
void PlayX(const ProgramInfo &pginfo, bool ignoreBookmark, bool ignoreProgStart, bool ignoreLastPlayPos, bool underNetworkControl)
void stopPlaylistTranscoding()
MythUIButtonList * m_groupAlphaList
void doPlaylistBeginFlagging()
void ShowRecGroupChangerUsePlaylist(void)
void processNetworkControlCommands(void)
void fillRecGroupPasswordCache(void)
void UpdateUIListItem(ProgramInfo *pginfo, bool force_preview_reload)
MythUIButtonList * m_recgroupList
void selectUIGroupsAlphabet(MythUIButtonListItem *item)
void doPlaylistBeginTranscoding()
void passwordClosed(void)
QMap< QString, QString > m_recGroupType
void ShowPlayGroupChangerUsePlaylist(void)
bool m_alwaysShowWatchedProgress
void updateGroupInfo(const QString &groupname, const QString &grouplabel)
void DeleteForgetHistory(void)
PlaybackBoxHelper m_helper
Main helper thread.
ProgramInfo * GetCurrentProgram(void) const override
void doPlaylistAllowRerecord()
void HandlePreviewEvent(const QStringList &list)
Updates the UI properties for a new preview file.
static void ShowAvailabilityPopup(const ProgramInfo &pginfo)
friend class PlaybackBoxListItem
void ShowMenu(void) override
void doPlaylistWatchedSetting(bool turnOn)
void doPlaylistExpireSetOff()
void doCreateTranscodingProfilesMenu()
QString m_artHostOverride
bool m_usingGroupSelector
void toggleView(PlaybackBox::ViewMask itemMask, bool setOn)
void setPlayGroup(QString newPlayGroup)
void updateIcons(const ProgramInfo *pginfo=nullptr)
void DisplayPopupMenu(void)
QString m_groupDisplayName
void PlaylistDeleteKeepHistory(void)
QMap< QString, QString > m_groupAlphabet
MythMenu * createJobMenu()
int m_listOrder
listOrder controls the ordering of the recordings in the list
void HandleUpdateItemEvent(uint recordingId, uint flags)
void SetRecGroupPassword(const QString &newPassword)
static void AddListener(QObject *listener)
Request notifications when a preview event is generated.
static void RemoveListener(QObject *listener)
Stop receiving notifications when a preview event is generated.
void GetOrdered(std::vector< ProgramInfo * > &list, bool newest_first=false)
void Add(const ProgramInfo &pginfo)
Adds a ProgramInfo to the cache.
bool Remove(uint recordingID)
Marks a ProgramInfo in the cache for deletion on the next call to Refresh().
bool IsLoadInProgress(void) const
void Refresh(void)
Refreshed the cache.
void UpdateFileSize(uint recordingID, uint64_t filesize, UpdateStates flags)
Updates a ProgramInfo in the cache.
void ScheduleLoad(bool updateUI=true)
ProgramInfoCache::UpdateStates Update(const ProgramInfo &pginfo)
Updates a ProgramInfo in the cache.
void WaitForLoadToComplete(void) const
ProgramInfo * GetRecordingInfo(uint recordingID) const
Holds information on recordings and videos.
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
void SetAvailableStatus(AvailableStatusType status, const QString &where)
bool IsInUsePlaying(void) const
void SetFlagging(bool flagging)
bool HasPathname(void) const
bool QueryIsInUse(QStringList &byWho) const
Returns true if Program is in use.
uint GetVideoProperties(void) const
bool IsAutoExpirable(void) const
bool IsPreserved(void) const
QString toString(Verbosity v=kLongDescription, const QString &sep=":", const QString &grp="\"") const
QString GetCategoryTypeString(void) const
Returns catType as a string.
AutoExpireType QueryAutoExpire(void) const
Returns "autoexpire" field from "recorded" table.
uint GetEpisode(void) const
uint GetSubtitleType(void) const
void SaveWatched(bool watchedFlag)
Set "watched" field in recorded/videometadata to "watchedFlag".
QString GetProgramID(void) const
void SetEditing(bool editing)
QString GetRecordingGroup(void) const
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".
uint GetRecordingID(void) const
QString GetInetRef(void) const
void SetRecordingStatus(RecStatus::Type status)
AvailableStatusType GetAvailableStatus(void) const
bool HasCutlist(void) const
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...
uint GetAudioProperties(void) const
QString GetHostname(void) const
virtual void SetFilesize(uint64_t sz)
void UpdateLastDelete(bool setTime) const
Set or unset the record.last_delete field.
bool IsBookmarkSet(void) const
QString GetSyndicatedEpisode(void) const
QString GetPlaybackGroup(void) const
QString GetDescription(void) const
QString GetTitle(void) const
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
QString GetSortTitle(void) const
static QString i18n(const QString &msg)
Translations for play,recording, & storage groups +.
QDate GetOriginalAirDate(void) const
int GetRecordingPriority2(void) const
virtual uint64_t GetFilesize(void) const
void ToStringList(QStringList &list) const
Serializes ProgramInfo into a QStringList which can be passed over a socket.
QString GetPlaybackURL(bool checkMaster=false, bool forceCheckLocal=false)
Returns filename or URL to be used to play back this recording.
bool IsWatched(void) const
bool IsPathSet(void) const
uint32_t GetProgramFlags(void) const
RecStatus::Type GetRecordingStatus(void) const
bool IsLastPlaySet(void) const
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
QString GetSubtitle(void) const
void SaveBookmark(uint64_t frame)
Clears any existing bookmark in DB and if frame is greater than 0 sets a new bookmark.
uint GetSeason(void) const
void SetPathname(const QString &pn)
Holds information on a TV Program one might wish to record.
void ApplyRecordPlayGroupChange(const QString &newplaygroup)
Sets the recording group, both in this RecordingInfo and in the database.
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
void ApplyRecordRecTitleChange(const QString &newTitle, const QString &newSubtitle, const QString &newDescription)
Sets the recording title, subtitle, and description both in this RecordingInfo and in the database.
void ApplyRecordRecGroupChange(const QString &newrecgroup)
Sets the recording group, both in this RecordingInfo and in the database.
static const QRegularExpression kReSearchTypeName
void ApplyTranscoderProfileChangeById(int id)
Internal representation of a recording rule, mirrors the record table.
bool LoadTemplate(const QString &title, const QString &category="Default", const QString &categoryType="Default")
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
virtual int IncrRef(void)
Increments reference count.
virtual void EditScheduled(void)
Creates a dialog for editing the recording schedule.
virtual void ShowDetails(void) const
Show the Program Details screen.
void customEvent(QEvent *event) override
virtual void EditCustom(void)
Creates a dialog for creating a custom recording rule.
virtual void ShowUpcomingScheduled(void) const
Show the upcoming recordings for this recording rule.
virtual void ShowGuide(void) const
Show the program guide.
virtual void ShowUpcoming(void) const
Show the upcoming recordings for this title.
virtual void ShowPrevious(void) const
Show the previous recordings for this recording rule.
void RequestEmbedding(bool Embed, const QRect &Rect={}, const QStringList &Data={})
QString GetRecordingGroup() const
static bool StartTV(ProgramInfo *TVRec, uint Flags, const ChannelInfoList &Selection=ChannelInfoList())
Start playback of media.
bool IsSameProgram(const ProgramInfo *ProgInfo) const
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
static QMap< QString, QString > iconMap
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MythMainWindow * GetMythMainWindow(void)
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
void ShowNotification(const QString &msg, const QString &from, const QString &detail, const VNMask visibility, const MythNotification::Priority priority)
Convenience inline random number generator functions.
static MythThemedMenu * menu
QHash< QString, QString > InfoMap
static constexpr const char * ACTION_1
void run(const QString &name, Class *object, void(Class::*fn)())
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
@ kDateTimeFull
Default local time.
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
@ kTime
Default local time.
@ kDateShort
Default local time.
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
uint32_t MythRandom()
generate 32 random bits
QString intToPaddedString(int n, int width=2)
Creates a zero padded string representation of an integer.
def rating(profile, smoonURL, gate)
static bool comp_programid_less_than(const ProgramInfo *a, const ProgramInfo *b)
static int comp_season_rev(const ProgramInfo *a, const ProgramInfo *b)
static PlaybackBox::ViewMask m_viewMaskToggle(PlaybackBox::ViewMask mask, PlaybackBox::ViewMask toggle)
static bool save_position(const MythUIButtonList *groupList, const MythUIButtonList *recordingList, QStringList &groupSelPref, QStringList &itemSelPref, QStringList &itemTopPref)
static bool comp_season_less_than(const ProgramInfo *a, const ProgramInfo *b)
static const std::array< const uint, 3 > s_artDelay
static int comp_programid(const ProgramInfo *a, const ProgramInfo *b)
static int comp_recordDate_rev(const ProgramInfo *a, const ProgramInfo *b)
static bool comp_recpriority2_less_than(const ProgramInfo *a, const ProgramInfo *b)
static QString construct_sort_title(QString title, const QString &sortTitle, PlaybackBox::ViewMask viewmask, PlaybackBox::ViewTitleSort sortType, int recpriority)
static void push_onto_del(QStringList &list, const ProgramInfo &pginfo)
static int comp_season(const ProgramInfo *a, const ProgramInfo *b)
static bool extract_one_del(QStringList &list, uint &recordingID)
static bool comp_originalAirDate_less_than(const ProgramInfo *a, const ProgramInfo *b)
static int comp_recordDate(const ProgramInfo *a, const ProgramInfo *b)
static bool comp_programid_rev_less_than(const ProgramInfo *a, const ProgramInfo *b)
static bool comp_originalAirDate_rev_less_than(const ProgramInfo *a, const ProgramInfo *b)
static int comp_originalAirDate(const ProgramInfo *a, const ProgramInfo *b)
static bool comp_season_rev_less_than(const ProgramInfo *a, const ProgramInfo *b)
static void restore_position(MythUIButtonList *groupList, MythUIButtonList *recordingList, const QStringList &groupSelPref, const QStringList &itemSelPref, const QStringList &itemTopPref)
static bool retrieve_SeasonEpisode(int &season, int &episode, const ProgramInfo *prog)
static const std::array< const std::string, 9 > disp_flags
static bool comp_recordDate_rev_less_than(const ProgramInfo *a, const ProgramInfo *b)
static int comp_programid_rev(const ProgramInfo *a, const ProgramInfo *b)
static QString extract_subtitle(const ProgramInfo &pginfo, const QString &groupname)
static bool comp_recordDate_less_than(const ProgramInfo *a, const ProgramInfo *b)
static int comp_originalAirDate_rev(const ProgramInfo *a, const ProgramInfo *b)
static int comp_recpriority2(const ProgramInfo *a, const ProgramInfo *b)
static const std::array< const int, kMaxJobs > kJobs
static QString extract_main_state(const ProgramInfo &pginfo, const TV *player)
static const QString sLocation
static constexpr uint8_t kArtworkCoverTimeout
static constexpr uint8_t kArtworkBannerTimeout
static constexpr size_t kMaxJobs
static constexpr uint16_t kArtworkFanTimeout
@ kCheckForPlaylistAction
AutoDeleteDeque< ProgramInfo * > ProgramList
TVState
TVState is an enumeration of the states used by TV and TVRec.
@ kState_None
None State, this is the initial state in both TV and TVRec, it indicates that we are ready to change ...
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
#define ACTION_VIEWSCHEDULED
#define ACTION_TOGGLERECORD
#define ACTION_LISTRECORDEDEPISODES
#define ACTION_PREVRECORDED
@ kStartTVIgnoreLastPlayPos
@ kStartTVIgnoreProgStart
@ kStartTVByNetworkCommand