5 #include <QCoreApplication>
6 #include <QWaitCondition>
46 #define LOC QString("PlaybackBox: ")
47 #define LOC_WARN QString("PlaybackBox Warning: ")
48 #define LOC_ERR QString("PlaybackBox Error: ")
79 return (dt1 < dt2 ? 1 : -1);
93 return (dt1 > dt2 ? 1 : -1);
215 const QRegExp &prefixes)
220 QString sTitle = title;
222 sTitle.remove(prefixes);
250 sortprefix.sprintf(
"+%03u", 1000 - recpriority);
252 sortprefix.sprintf(
"-%03u", -recpriority);
254 sTitle = sortprefix +
'-' + sTitle;
261 QString state(
"normal");
281 QString job =
"default";
292 job =
"commflagging";
299 QString job =
"default";
313 const ProgramInfo &pginfo,
const QString &groupname)
316 if (groupname != pginfo.
GetTitle().toLower())
323 if (subtitle.trimmed().isEmpty())
332 list.push_back(QString::number(pginfo.
GetChanID()));
334 list.push_back(QString() );
335 list.push_back(QString());
339 QStringList &list,
uint &chanid, QDateTime &recstartts)
347 chanid = list[0].toUInt();
355 if (!chanid || !recstartts.isValid())
356 LOG(VB_GENERAL, LOG_ERR,
LOC +
"extract_one_del() invalid entry");
358 return chanid && recstartts.isValid();
366 mainStack,
"playbackbox", (
TV *)player, showTV);
377 TV *player,
bool showTV)
379 m_prefixes(QObject::tr(
"^(The |A |An )")),
380 m_titleChaff(
" \\(.*\\)$"),
384 m_watchListAutoExpire(
false),
385 m_watchListMaxAge(60), m_watchListBlackOut(2),
388 m_groupDisplayName(
ProgramInfo::i18n(
"All Programs")),
389 m_recGroup(
"All Programs"),
390 m_watchGroupName(tr(
"Watch List")),
391 m_watchGroupLabel(m_watchGroupName.toLower()),
392 m_viewMask(VIEW_TITLES),
397 m_doToggleMenu(
true),
401 m_op_on_playlist(
false),
402 m_programInfoCache(this), m_playingSomething(
false),
410 m_usingGroupSelector(
false),
411 m_groupSelected(
false),
412 m_passwordEntered(
false)
435 "DisplayGroupDefaultViewMask",
500 QString message = QString(
"PLAYBACKBOX_EXITING");
524 LOG(VB_GENERAL, LOG_ERR,
LOC +
525 "Theme is missing critical theme elements.");
567 "titlesubtitle|shortdate|starttime");
610 QString label = tr(
"Password for group '%1':").arg(newRecGroup);
615 connect(pwd, SIGNAL(haveResult(QString)),
617 connect(pwd, SIGNAL(
Exiting(
void)),
636 if (password == grouppass)
639 qApp->postEvent(
this,
new MythEvent(
"DISPLAY_RECGROUP",
653 const QString &grouplabel)
659 infoMap[
"title"] = grouplabel;
666 if (!groupname.isEmpty() && !
m_progLists[groupname].empty())
678 else if (
m_artImage[kArtworkFanart]->GetFilename() != fn)
690 QString desc = tr(
"There is/are %n recording(s) in this display group",
693 if (countInGroup > 1)
696 float groupSize = 0.0;
709 groupSize += filesize;
713 desc += tr(
", which consume %1");
714 desc += tr(
"GB",
"GigaBytes");
716 desc = desc.arg(groupSize / 1024.0 / 1024.0 / 1024.0, 0,
'f', 2);
719 infoMap[
"description"] = desc;
720 infoMap[
"rec_count"] = QString(
"%1").arg(countInGroup);
729 ratingState->
Reset();
749 bool force_preview_reload)
765 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
766 QString(
"UpdateUIListItem called with a title unknown "
767 "to us in m_recordingList\n\t\t\t%1")
772 static const char *
disp_flags[] = {
"playlist",
"watched",
"preserve",
773 "cutlist",
"autoexpire",
"editing",
774 "bookmark",
"inuse",
"transcoded" };
778 bool disp_flag_stat[
sizeof(
disp_flags)/
sizeof(
char*)];
795 bool is_sel,
bool force_preview_reload)
812 pginfo->
ToMap(infoMap);
820 if (groupname == pginfo->
GetTitle().toLower())
821 item->
SetText(tempSubTitle,
"titlesubtitle");
842 if (oldimgfile.isEmpty() || force_preview_reload)
849 pginfo->
ToMap(infoMap);
878 if (arthost.isEmpty())
907 if (item->
GetText(
"is_item_initialized").isNull())
909 QMap<AudioProps, QString> audioFlags;
915 QMap<VideoProps, QString> videoFlags;
921 QMap<SubtitleTypes, QString> subtitleFlags;
935 pginfo->
ToMap(infoMap);
940 if (groupname == pginfo->
GetTitle().toLower())
941 item->
SetText(tempSubTitle,
"titlesubtitle");
950 QMap<AudioProps, QString>::iterator ait;
951 for (ait = audioFlags.begin(); ait != audioFlags.end(); ++ait)
957 QMap<VideoProps, QString>::iterator vit;
958 for (vit = videoFlags.begin(); vit != videoFlags.end(); ++vit)
964 QMap<SubtitleTypes, QString>::iterator sit;
965 for (sit = subtitleFlags.begin(); sit != subtitleFlags.end(); ++sit)
974 item->
SetText(
"yes",
"is_item_initialized");
1002 qVariantValue<ProgramInfo*>(sel_item->
GetData());
1021 if (list.size() < 5)
1023 LOG(VB_GENERAL, LOG_ERR,
"HandlePreviewEvent() -- too few args");
1024 for (
uint i = 0; i < (
uint) list.size(); i++)
1026 LOG(VB_GENERAL, LOG_INFO, QString(
"%1: %2")
1027 .arg(i).arg(list[i]));
1032 const QString piKey = list[0];
1033 const QString previewFile = list[1];
1034 const QString message = list[2];
1037 for (
uint i = 4; i < (
uint) list.size(); i++)
1039 QString token = list[i];
1050 QString tokens(
"\n\t\t\ttokens: ");
1051 for (
uint i = 4; i < (
uint) list.size(); i++)
1052 tokens += list[i] +
", ";
1053 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1054 "Ignoring PREVIEW_SUCCESS, no matcing token" + tokens);
1058 if (previewFile.isEmpty())
1060 LOG(VB_GENERAL, LOG_ERR,
LOC +
1061 "Ignoring PREVIEW_SUCCESS, no preview file.");
1073 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
1074 "Ignoring PREVIEW_SUCCESS, item no longer on screen.");
1079 LOG(VB_GUI, LOG_INFO,
LOC + QString(
"Loading preview %1,\n\t\t\tmsg %2")
1080 .arg(previewFile).arg(message));
1082 item->
SetImage(previewFile,
"preview",
true);
1101 QMap <QString, int>::iterator it;
1102 QMap <QString, int> iconMap;
1119 for (it = iconMap.begin(); it != iconMap.end(); ++it)
1142 bool haveIcon =
false;
1143 if (pginfo && iconState)
1145 for (it = iconMap.begin(); it != iconMap.end(); ++it)
1158 if (iconState && !haveIcon)
1170 if (pginfo && iconState)
1172 for (it = iconMap.begin(); it != iconMap.end(); ++it)
1185 if (iconState && !haveIcon)
1193 if (pginfo && iconState)
1195 for (it = iconMap.begin(); it != iconMap.end(); ++it)
1208 if (iconState && !haveIcon)
1218 if (pginfo && iconState)
1220 for (it = iconMap.begin(); it != iconMap.end(); ++it)
1233 if (iconState && !haveIcon)
1258 if (!freereportText && !usedProgress && !
GetChild(
"diskspacetotal") &&
1268 usageMap[
"diskspacetotal"] = locale.toString((freeSpaceTotal / 1024.0),
1270 usageMap[
"diskspaceused"] = locale.toString((freeSpaceUsed / 1024.0),
1272 usageMap[
"diskspacefree"] = locale.toString(
1273 ((freeSpaceTotal - freeSpaceUsed) / 1024.0),
1277 if (freeSpaceTotal > 0.0)
1278 perc = (100.0 * freeSpaceUsed) / freeSpaceTotal;
1280 usageMap[
"diskspacepercentused"] = QString::number((
int)perc);
1281 usageMap[
"diskspacepercentfree"] = QString::number(100 - (
int)perc);
1283 QString
size = locale.toString(((freeSpaceTotal - freeSpaceUsed) / 1024.0),
1286 QString usestr = tr(
"%1% used, %2 GB free",
"Diskspace")
1287 .arg(QString::number((
int)perc))
1291 freereportText->
SetText(usestr);
1295 usedProgress->
SetTotal((
int)freeSpaceTotal);
1296 usedProgress->
SetUsed((
int)freeSpaceUsed);
1317 QString key = (*it);
1318 QString
tmp = (key ==
"All Programs") ?
"All" : key;
1339 int best_pref = INT_MAX, sel_idx = 0;
1340 QStringList::iterator it;
1343 QString groupname = (*it);
1347 m_groupList,
"", qVariantFromValue(groupname.toLower()));
1349 int pref = groupPreferences.indexOf(groupname.toLower());
1350 if ((pref >= 0) && (pref < best_pref))
1357 QString displayName = groupname;
1358 if (displayName.isEmpty())
1367 item->
SetText(groupname,
"groupname");
1368 item->
SetText(displayName,
"name");
1371 int count =
m_progLists[groupname.toLower()].size();
1372 item->
SetText(QString::number(count),
"reccount");
1390 QString groupname = sel_item->
GetData().toString();
1391 QString grouplabel = sel_item->
GetText();
1406 ProgramMap::iterator pmit =
m_progLists.find(groupname);
1413 for (; it != progList.
end(); ++it)
1416 (*it)->GetAvailableStatus() ==
asDeleted)
1425 if (!progList.
empty())
1430 tr(
"There are no recordings available") :
1431 tr(
"There are no recordings in your current view");
1440 QStringList &groupSelPref, QStringList &itemSelPref,
1441 QStringList &itemTopPref)
1447 groupSelPref.push_back(prefSelGroup->
GetData().toString());
1453 groupSelPref.push_back(prefSelGroup->
GetData().toString());
1457 for (
int i = curPos; (i >= 0) && (i < recordingList->GetCount()); i++)
1461 itemSelPref.push_back(groupSelPref.front());
1464 for (
int i = curPos; (i >= 0) && (i < recordingList->GetCount()); i--)
1468 itemSelPref.push_back(groupSelPref.front());
1473 for (
int i = topPos + 1; i >= topPos - 1; i--)
1475 if (i >= 0 && i < recordingList->GetCount())
1482 itemTopPref.push_front(groupSelPref.front());
1486 itemTopPref.push_back(groupSelPref.front());
1497 const QStringList &groupSelPref,
const QStringList &itemSelPref,
1498 const QStringList &itemTopPref)
1503 if (!prefSelGroup ||
1504 !groupSelPref.contains(prefSelGroup->
GetData().toString()) ||
1505 !itemSelPref.contains(prefSelGroup->
GetData().toString()))
1511 QString groupname = prefSelGroup->
GetData().toString();
1515 for (
uint i = 0; i+1 < (
uint)itemSelPref.size(); i+=2)
1517 if (itemSelPref[i] != groupname)
1520 const QString key = itemSelPref[i+1];
1528 i = itemSelPref.size();
1536 for (
uint i = 0; i+1 < (
uint)itemTopPref.size(); i+=2)
1538 if (itemTopPref[i] != groupname)
1541 const QString key = itemTopPref[i+1];
1549 i = itemTopPref.size();
1558 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Reselect success (%1,%2)")
1559 .arg(sel).arg(top));
1566 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Reselect failure (%1,%2)")
1567 .arg(sel).arg(top));
1577 QStringList groupSelPref, itemSelPref, itemTopPref;
1579 groupSelPref, itemSelPref, itemTopPref))
1588 QMap<QString, AvailableStatusType> asCache;
1595 for (; it != end; ++it)
1597 asKey = (*it)->MakeUniqueKey();
1598 asCache[asKey] = (*it)->GetAvailableStatus();
1617 QMap<QString, QString> sortedList;
1618 QMap<int, QString> searchRule;
1619 QMap<int, int> recidEpisodes;
1630 query.
prepare(
"SELECT recordid,title FROM record "
1631 "WHERE search > 0 AND search != :MANUAL;");
1636 while (query.
next())
1638 QString tmpTitle = query.
value(1).toString();
1640 searchRule[query.
value(0).toInt()] = tmpTitle;
1645 vector<ProgramInfo*> list;
1648 vector<ProgramInfo*>::const_iterator it = list.begin();
1649 for ( ; it != list.end(); ++it)
1651 if ((*it)->IsDeletePending())
1684 if (asCache.contains(asKey))
1693 QString tmpTitle = tr(
"Live TV");
1694 sortedList[tmpTitle.toLower()] = tmpTitle;
1696 m_progLists[tmpTitle.toLower()].setAutoDelete(
false);
1707 sTitle = sTitle.toLower();
1709 if (!sortedList.contains(sTitle))
1710 sortedList[sTitle] = p->
GetTitle();
1711 m_progLists[sortedList[sTitle].toLower()].push_front(p);
1712 m_progLists[sortedList[sTitle].toLower()].setAutoDelete(
false);
1724 .setAutoDelete(
false);
1740 QString tmpTitle = QString(
"(%1)")
1742 sortedList[tmpTitle.toLower()] = tmpTitle;
1744 m_progLists[tmpTitle.toLower()].setAutoDelete(
false);
1754 LOG(VB_FILE, LOG_INFO, QString(
"Auto-expire off: %1")
1760 LOG(VB_FILE, LOG_INFO,
1761 QString(
"Marked as 'watched': %1")
1777 LOG(VB_FILE, LOG_INFO,
1778 QString(
"Not the earliest: %1")
1787 if (sortedList.empty())
1789 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"SortedList is Empty");
1800 if (episodeSort ==
"OrigAirDate")
1802 QMap<QString, ProgramList>::Iterator Iprog;
1805 if (!Iprog.key().isEmpty())
1807 std::stable_sort((*Iprog).begin(), (*Iprog).end(),
1814 else if (episodeSort ==
"Id")
1816 QMap<QString, ProgramList>::Iterator Iprog;
1819 if (!Iprog.key().isEmpty())
1821 std::stable_sort((*Iprog).begin(), (*Iprog).end(),
1828 else if (episodeSort ==
"Date")
1830 QMap<QString, ProgramList>::iterator it;
1833 if (!it.key().isEmpty())
1835 std::stable_sort((*it).begin(), (*it).end(),
1842 else if (episodeSort ==
"Season")
1844 QMap<QString, ProgramList>::iterator it;
1847 if (!it.key().isEmpty())
1849 std::stable_sort((*it).begin(), (*it).end(),
1862 QMap<int, int> recType;
1863 QMap<int, int> maxEpisodes;
1864 QMap<int, int> avgDelay;
1865 QMap<int, int> spanHours;
1866 QMap<int, int> delHours;
1867 QMap<int, int> nextHours;
1870 query.
prepare(
"SELECT recordid, type, maxepisodes, avg_delay, "
1871 "next_record, last_record, last_delete FROM record;");
1875 while (query.
next())
1877 int recid = query.
value(0).toInt();
1878 recType[recid] = query.
value(1).toInt();
1879 maxEpisodes[recid] = query.
value(2).toInt();
1880 avgDelay[recid] = query.
value(3).toInt();
1882 QDateTime next_record =
1884 QDateTime last_record =
1886 QDateTime last_delete =
1890 spanHours[recid] = 1000;
1891 if (last_record.isValid() && next_record.isValid())
1893 last_record.secsTo(next_record) / 3600 + 1;
1896 delHours[recid] = 1000;
1897 if (last_delete.isValid())
1898 delHours[recid] = last_delete.secsTo(now) / 3600 + 1;
1901 if (next_record.isValid())
1902 nextHours[recid] = now.secsTo(next_record) / 3600 + 1;
1909 int recid = (*pit)->GetRecordingRuleID();
1910 int avgd = avgDelay[recid];
1916 if (spanHours[recid] == 0)
1918 spanHours[recid] = 1000;
1919 delHours[recid] = 1000;
1923 if (!(*pit)->GetRecordingRuleID() || maxEpisodes[recid] > 0)
1924 (*pit)->SetRecordingPriority2(0);
1927 (*pit)->SetRecordingPriority2(
1928 (recidEpisodes[(*pit)->GetRecordingRuleID()] - 1) *
1933 if (nextHours[recid] > 0 && nextHours[recid] < baseValue * 3)
1935 (*pit)->SetRecordingPriority2(
1936 (*pit)->GetRecordingPriority2() +
1937 (baseValue * 3 - nextHours[recid]) / 3);
1940 int hrs = (*pit)->GetScheduledEndTime().secsTo(now) / 3600;
1947 (*pit)->SetRecordingPriority2(
1948 (*pit)->GetRecordingPriority2() + 42 - hrs);
1952 (*pit)->SetRecordingPriority2(
1953 (*pit)->GetRecordingPriority2() + abs((hrs % 24) - 12) * 2);
1956 if (spanHours[recid] < 50 ||
1961 (*pit)->SetRecordingPriority2(
wlDeleted);
1962 LOG(VB_FILE, LOG_INFO,
1963 QString(
"Recently deleted daily: %1")
1964 .arg((*pit)->GetTitle()));
1970 LOG(VB_FILE, LOG_INFO, QString(
"Daily interval: %1")
1971 .arg((*pit)->GetTitle()));
1973 if (maxEpisodes[recid] > 0)
1975 (*pit)->SetRecordingPriority2(
1976 (*pit)->GetRecordingPriority2() +
1977 (baseValue / 2) + (hrs / 24));
1981 (*pit)->SetRecordingPriority2(
1982 (*pit)->GetRecordingPriority2() +
1983 (baseValue / 5) + hrs);
1988 else if (nextHours[recid] ||
1994 (*pit)->SetRecordingPriority2(
wlDeleted);
1995 LOG(VB_FILE, LOG_INFO,
1996 QString(
"Recently deleted weekly: %1")
1997 .arg((*pit)->GetTitle()));
2003 LOG(VB_FILE, LOG_INFO, QString(
"Weekly interval: %1")
2004 .arg((*pit)->GetTitle()));
2006 if (maxEpisodes[recid] > 0)
2008 (*pit)->SetRecordingPriority2(
2009 (*pit)->GetRecordingPriority2() +
2010 (baseValue / 2) + (hrs / 24));
2014 (*pit)->SetRecordingPriority2(
2015 (*pit)->GetRecordingPriority2() +
2016 (baseValue / 3) + (baseValue * hrs / 24 / 4));
2025 (*pit)->SetRecordingPriority2(
wlDeleted);
2034 (*pit)->SetRecordingPriority2(
2035 (*pit)->GetRecordingPriority2() +
2036 baseValue * (36 - hrs) / 36);
2041 if (maxEpisodes[recid] > 0)
2043 (*pit)->SetRecordingPriority2(
2044 (*pit)->GetRecordingPriority2() +
2045 (baseValue / 2) + (hrs / 24));
2049 (*pit)->SetRecordingPriority2(
2050 (*pit)->GetRecordingPriority2() +
2051 (baseValue / 3) + (baseValue * hrs / 24 / 4));
2056 (*pit)->SetRecordingPriority2(
2057 (*pit)->GetRecordingPriority2() +
2062 (*pit)->SetRecordingPriority2(
2063 (*pit)->GetRecordingPriority2() +
2071 int delaypct = avgd / 3 + 67;
2075 (*pit)->SetRecordingPriority2(
2076 (*pit)->GetRecordingPriority2() * (200 - delaypct) / 100);
2078 else if (avgd > 100)
2080 (*pit)->SetRecordingPriority2(
2081 (*pit)->GetRecordingPriority2() * 100 / delaypct);
2084 LOG(VB_FILE, LOG_INFO, QString(
" %1 %2 %3")
2087 .arg((*pit)->GetRecordingPriority2())
2088 .arg((*pit)->GetTitle()));
2101 (!sortedList.values().contains(tr(
"Live TV"))))
2117 query.
prepare(
"SELECT distinct recgroup from recorded WHERE "
2118 "deletepending = 0 ORDER BY recgroup");
2122 while (query.
next())
2124 name = query.
value(0).toString();
2125 if (name !=
"Deleted" && name !=
"LiveTV")
2142 QStringList::const_iterator it =
m_playList.begin();
2155 groupSelPref, itemSelPref, itemTopPref);
2168 while (!tmp.empty())
2172 tmp.removeAll(tmp[i]);
2180 QCoreApplication::postEvent(
2195 PlayX(*pginfo,
false,
false);
2209 PlayX(*pginfo,
true,
false);
2213 bool ignoreBookmark,
2214 bool underNetworkControl)
2218 Play(pginfo,
false, ignoreBookmark, underNetworkControl);
2226 ignoreBookmark ?
"1" :
"0");
2228 underNetworkControl ?
"1" :
"0");
2252 LOG(VB_GENERAL, LOG_ERR, QString(
"deleteSelected(%1) -- failed ")
2254 QString(
"availability status: %1 ")
2258 tr(
"This recording is already being deleted"));
2265 LOG(VB_GENERAL, LOG_ERR, QString(
"deleteSelected(%1) -- failed ")
2267 QString(
"delete candidate: %1 in use by %2")
2270 if (byWho.isEmpty())
2273 tr(
"This recording is already being deleted"));
2278 tr(
"This recording is currently in use by:") +
"\n" +
2312 pginfo = qVariantValue<ProgramInfo *>(item->
GetData());
2354 if (which ==
"groupmenu")
2372 else if (which ==
"actionmenu")
2384 QString label = tr(
"Group List Menu");
2425 bool inPlaylist,
bool ignoreBookmark,
bool underNetworkControl)
2427 bool playCompleted =
false;
2466 QCoreApplication::postEvent(
2482 return playCompleted;
2486 uint chanid,
const QDateTime &recstartts,
2487 bool forgetHistory,
bool forceMetadataDelete)
2494 if (!forceMetadataDelete &&
2504 if (!forceMetadataDelete)
2510 forceMetadataDelete, forgetHistory);
2540 label = tr(
"Are you sure you want to delete:");
break;
2542 label = tr(
"Recording file does not exist.\n"
2543 "Are you sure you want to delete:");
2546 label = tr(
"Are you sure you want to stop:");
break;
2570 const char *tmpslot = NULL;
2576 tmpmessage = tr(
"Yes, and allow re-record");
2584 tmpmessage = tr(
"Yes, delete it");
2585 tmpslot = SLOT(
Delete());
2588 tmpmessage = tr(
"Yes, delete it");
2592 tmpmessage = tr(
"Yes, stop recording");
2606 tmpmessage = tr(
"Yes, delete it and the remaining %1 list items")
2607 .arg(other_delete_cnt);
2616 tmpmessage = tr(
"No, keep it");
2620 tmpmessage = tr(
"No, continue recording");
2628 tmpmessage = tr(
"No, and keep the remaining %1 list items")
2629 .arg(other_delete_cnt);
2649 tr(
"This recording is currently in "
2650 "use by:") +
"\n" + byWho);
2655 tr(
"This recording is currently "
2661 tr(
"This recording is currently being "
2662 "deleted and is unavailable"));
2666 tr(
"This recording has been "
2667 "deleted and is unavailable"));
2671 tr(
"The file for this recording can "
2676 tr(
"The file for this recording is "
2681 tr(
"This recording is not yet "
2688 QString label = tr(
"There is %n item(s) in the playlist. Actions affect "
2689 "all items in the playlist",
"",
m_playList.size());
2693 menu->AddItem(tr(
"Play"), SLOT(
doPlayList()));
2700 menu->AddItem(tr(
"Toggle playlist for this Category/Title"),
2703 menu->AddItem(tr(
"Toggle playlist for this Group"),
2707 menu->AddItem(tr(
"Toggle playlist for this recording"),
2713 menu->AddItem(tr(
"Delete, and allow re-record"),
2721 QString label = tr(
"There is %n item(s) in the playlist. Actions affect "
2722 "all items in the playlist",
"",
m_playList.size());
2738 QString label = tr(
"There is %n item(s) in the playlist. Actions affect "
2739 "all items in the playlist",
"",
m_playList.size());
2745 QStringList::Iterator it;
2747 bool isTranscoding =
true;
2748 bool isFlagging =
true;
2749 bool isMetadataLookup =
true;
2750 bool isRunningUserJob1 =
true;
2751 bool isRunningUserJob2 =
true;
2752 bool isRunningUserJob3 =
true;
2753 bool isRunningUserJob4 =
true;
2763 isTranscoding =
false;
2771 isMetadataLookup =
false;
2775 isRunningUserJob1 =
false;
2779 isRunningUserJob2 =
false;
2783 isRunningUserJob3 =
false;
2787 isRunningUserJob4 =
false;
2788 if (!isTranscoding && !isFlagging && !isRunningUserJob1 &&
2789 !isRunningUserJob2 && !isRunningUserJob3 && !isRunningUserJob4)
2804 if (!isMetadataLookup)
2810 if (!command.isEmpty())
2814 if (!isRunningUserJob1)
2815 menu->AddItem(tr(
"Begin") +
' ' + jobTitle,
2818 menu->AddItem(tr(
"Stop") +
' ' + jobTitle,
2823 if (!command.isEmpty())
2827 if (!isRunningUserJob2)
2828 menu->AddItem(tr(
"Begin") +
' ' + jobTitle,
2831 menu->AddItem(tr(
"Stop") +
' ' + jobTitle,
2836 if (!command.isEmpty())
2840 if (!isRunningUserJob3)
2841 menu->AddItem(tr(
"Begin") +
' ' + jobTitle,
2844 menu->AddItem(tr(
"Stop") +
' ' + jobTitle,
2849 if (!command.isEmpty())
2853 if (!isRunningUserJob4)
2854 menu->AddItem(QString(
"%1 %2").arg(tr(
"Begin")).arg(jobTitle),
2857 menu->AddItem(QString(
"%1 %2").arg(tr(
"Stop")).arg(jobTitle),
2934 tr(
"Disable Auto Expire") : tr(
"Enable Auto Expire");
2936 tr(
"Do not preserve this episode") : tr(
"Preserve this episode");
3006 tr(
"Stop Transcoding"), tr(
"Begin Transcoding"),
3007 tr(
"Stop Commercial Detection"), tr(
"Begin Commercial Detection"),
3008 tr(
"Stop Metadata Lookup"), tr(
"Begin Metadata Lookup"),
3014 const char *myslots[14] =
3025 for (
uint i = 0; i <
sizeof(
add) /
sizeof(
bool); i++)
3030 QString stop_desc = desc[i*2+0];
3031 QString start_desc = desc[i*2+1];
3033 if (start_desc.toUInt())
3036 "UserJobDesc"+start_desc, tr(
"User Job") +
" #" + start_desc);
3037 stop_desc = tr(
"Stop") +
' ' + jobTitle;
3038 start_desc = tr(
"Begin") +
' ' + jobTitle;
3044 const char *slot = myslots[i * 2 + (running ? 0 : 1)];
3047 menu->
AddItem((running) ? stop_desc : start_desc, slot, submenu);
3055 QString label = tr(
"Transcoding profiles");
3059 menu->
AddItem(tr(
"Default"), qVariantFromValue(-1));
3060 menu->
AddItem(tr(
"Autodetect"), qVariantFromValue(0));
3063 query.
prepare(
"SELECT r.name, r.id "
3064 "FROM recordingprofiles r, profilegroups p "
3065 "WHERE p.name = 'Transcoders' "
3066 "AND r.profilegroup = p.id "
3067 "AND r.name != 'RTjpeg/MPEG4' "
3068 "AND r.name != 'MPEG2' ");
3076 while (query.
next())
3078 QString transcoder_name = query.
value(0).toString();
3079 int transcoder_id = query.
value(1).toInt();
3082 if (transcoder_name ==
"High Quality")
3083 transcoder_name = tr(
"High Quality");
3084 else if (transcoder_name ==
"Medium Quality")
3085 transcoder_name = tr(
"Medium Quality");
3086 else if (transcoder_name ==
"Low Quality")
3087 transcoder_name = tr(
"Low Quality");
3089 menu->
AddItem(transcoder_name, qVariantFromValue(transcoder_id));
3114 tr(
"Recording file cannot be found") :
3116 tr(
"Recording file contains no data") :
3117 tr(
"Recording Options");
3141 bool sameProgram =
false;
3209 QString timedate = QString(
"%1 - %2")
3221 int maxll = max(title.length(), 20);
3222 if (extra.length() > maxll)
3223 extra = extra.left(maxll - 3) +
"...";
3226 return QString(
"\n%1%2\n%3").arg(title).arg(extra).arg(timedate);
3231 QStringList::Iterator it;
3347 QStringList::Iterator it;
3363 "",
"", jobHost, jobFlags);
3371 QStringList::Iterator it;
3406 QString forceDeleteStr(
"0");
3408 QStringList::const_iterator it;
3416 list.push_back(QString::number(tmpItem->
GetChanID()));
3418 list.push_back(forceDeleteStr);
3419 list.push_back(forgetHistory ?
"1" :
"0");
3439 QDateTime recstartts;
3447 QDateTime recstartts;
3464 QCoreApplication::postEvent(
this, e);
3481 QDateTime recstartts;
3485 LOG(VB_GENERAL, LOG_ERR,
LOC +
3486 QString(
"FindProgramInUILists(%1) called with invalid key").arg(key));
3492 uint chanid,
const QDateTime &recstartts,
3501 if (recgroup !=
"LiveTV")
3503 swap( _it[0], _it[1]);
3504 swap(_end[0], _end[1]);
3507 for (
uint i = 0; i < 2; i++)
3510 for (; it != end; ++it)
3512 if ((*it)->GetRecordingStartTime() == recstartts &&
3513 (*it)->GetChanID() == chanid)
3608 for (; it != end; ++it)
3610 if (*it && ((*it)->GetAvailableStatus() ==
asAvailable))
3648 QStringList tmpList;
3649 QStringList::Iterator it;
3654 for (it = tmpList.begin(); it != tmpList.end(); ++it )
3694 QStringList tokens = command.simplified().split(
" ");
3696 if (tokens.size() >= 4 && (tokens[1] ==
"PLAY" || tokens[1] ==
"RESUME"))
3698 if (tokens.size() == 6 && tokens[2] ==
"PROGRAM")
3700 int clientID = tokens[5].toInt();
3702 LOG(VB_GENERAL, LOG_INFO,
LOC +
3703 QString(
"NetworkControl: Trying to %1 program '%2' @ '%3'")
3704 .arg(tokens[1]).arg(tokens[3]).arg(tokens[4]));
3708 LOG(VB_GENERAL, LOG_ERR,
LOC +
3709 "NetworkControl: Already playing");
3711 QString msg = QString(
3712 "NETWORK_CONTROL RESPONSE %1 ERROR: Unable to play, "
3713 "player is already playing another recording.")
3721 uint chanid = tokens[3].toUInt();
3727 QString msg = QString(
"NETWORK_CONTROL RESPONSE %1 OK")
3734 PlayX(pginfo,
true,
true);
3738 QString message = QString(
"NETWORK_CONTROL RESPONSE %1 "
3739 "ERROR: Could not find recording for "
3740 "chanid %2 @ %3").arg(clientID)
3741 .arg(tokens[3]).arg(tokens[4]);
3752 if ((event->key() == Qt::Key_LaunchMedia) &&
3753 (event->modifiers() ==
3754 (Qt::ShiftModifier |
3755 Qt::ControlModifier |
3758 Qt::KeypadModifier)))
3772 bool handled =
false;
3773 QStringList actions;
3777 for (
int i = 0; i < actions.size() && !handled; ++i)
3779 QString
action = actions[i];
3782 if (action == ACTION_1 || action ==
"HELP")
3784 else if (action ==
"MENU")
3788 else if (action ==
"NEXTFAV")
3795 else if (action ==
"TOGGLEFAV")
3800 else if (action == ACTION_TOGGLERECORD)
3805 else if (action == ACTION_PAGERIGHT)
3817 if (!nextGroup.isEmpty())
3820 else if (action == ACTION_PAGELEFT)
3832 if (!nextGroup.isEmpty())
3835 else if (action ==
"CHANGERECGROUP")
3837 else if (action ==
"CHANGEGROUPVIEW")
3839 else if (action ==
"EDIT")
3843 if (action ==
"DELETE")
3845 else if (action == ACTION_PLAYBACK)
3847 else if (action ==
"DETAILS" || action ==
"INFO")
3849 else if (action ==
"CUSTOMEDIT")
3851 else if (action ==
"UPCOMING")
3853 else if (action == ACTION_VIEWSCHEDULED)
3877 QString resultid = dce->
GetId();
3879 if (resultid ==
"transcode" && dce->
GetResult() >= 0)
3885 QString message = me->
Message();
3887 if (message.left(21) ==
"RECORDING_LIST_CHANGE")
3889 QStringList tokens = message.simplified().split(
" ");
3891 QDateTime recstartts;
3892 if (tokens.size() >= 4)
3894 chanid = tokens[2].toUInt();
3898 if ((tokens.size() >= 2) && tokens[1] ==
"UPDATE")
3901 if (evinfo.HasPathname() || evinfo.GetChanID())
3904 else if (chanid && recstartts.isValid() && (tokens[1] ==
"ADD"))
3913 else if (chanid && recstartts.isValid() && (tokens[1] ==
"DELETE"))
3915 if (chanid && recstartts.isValid())
3923 else if (message.left(15) ==
"NETWORK_CONTROL")
3925 QStringList tokens = message.simplified().split(
" ");
3926 if ((tokens[1] !=
"ANSWER") && (tokens[1] !=
"RESPONSE"))
3933 QKeyEvent *keyevent;
3934 Qt::KeyboardModifiers modifiers =
3936 Qt::ControlModifier |
3940 keyevent =
new QKeyEvent(QEvent::KeyPress,
3941 Qt::Key_LaunchMedia, modifiers);
3945 keyevent =
new QKeyEvent(QEvent::KeyRelease,
3946 Qt::Key_LaunchMedia, modifiers);
3951 else if (message.left(16) ==
"UPDATE_FILE_SIZE")
3953 QStringList tokens = message.simplified().split(
" ");
3956 QDateTime recstartts;
3957 uint64_t filesize = 0ULL;
3958 if (tokens.size() >= 4)
3960 chanid = tokens[1].toUInt();
3962 filesize = tokens[3].toLongLong(&ok);
3964 if (chanid && recstartts.isValid() && ok)
3967 chanid, recstartts, filesize);
3970 else if (message ==
"UPDATE_UI_LIST")
3980 else if (message ==
"UPDATE_USAGE_UI")
3984 else if (message ==
"RECONNECT_SUCCESS")
3988 else if (message ==
"LOCAL_PBB_DELETE_RECORDINGS")
4003 list.push_back(QString::number(pginfo->
GetChanID()));
4006 list.push_back(forceDeleteStr);
4007 list.push_back(forgetHistoryStr);
4009 "LOCAL_PBB_DELETE_RECORDINGS");
4021 else if (message ==
"DELETE_SUCCESSES")
4025 else if (message ==
"DELETE_FAILURES")
4053 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4054 "Delete failures not handled due to "
4055 "pre-existing popup.");
4063 else if (message ==
"PREVIEW_SUCCESS")
4067 else if (message ==
"PREVIEW_FAILED" && me->
ExtraDataCount() >= 5)
4079 const uint kMaxUIWaitTime = 10000;
4081 QString key = list[0];
4086 uint64_t fs = list[3].toULongLong();
4088 tm.setHMS(list[4].toUInt(), list[5].toUInt(),
4089 list[6].toUInt(), list[7].toUInt());
4090 QTime now = QTime::currentTime();
4091 int time_elapsed = tm.msecsTo(now);
4092 if (time_elapsed < 0)
4093 time_elapsed += 24 * 60 * 60 * 1000;
4104 if ((
uint)time_elapsed >= kMaxUIWaitTime)
4113 ((
uint)time_elapsed < kMaxUIWaitTime))
4131 QCoreApplication::postEvent(
4135 if (old_avail != availableStatus)
4138 else if ((message ==
"PLAY_PLAYLIST") && !
m_playListPlay.empty())
4153 Play(*pginfo,
true,
false,
false);
4155 else if ((message ==
"SET_PLAYBACK_URL") && (me->
ExtraDataCount() == 2))
4162 else if ((message ==
"FOUND_ARTWORK") && (me->
ExtraDataCount() >= 5))
4169 if (!pikey.isEmpty())
4181 else if (!group.isEmpty() &&
4191 else if (message ==
"EXIT_TO_MENU" ||
4192 message ==
"CANCEL_PLAYLIST")
4196 else if ((message ==
"DISPLAY_RECGROUP") &&
4208 uint chanid,
const QDateTime &recstartts)
4212 LOG(VB_GENERAL, LOG_WARNING,
LOC +
4213 QString(
"Failed to remove %1:%2, reloading list")
4214 .arg(chanid).arg(recstartts.toString(
Qt::ISODate)));
4222 groupname = sel_item->
GetData().toString();
4228 while (pit != (*git).end())
4230 if ((*pit)->GetChanID() == chanid &&
4231 (*pit)->GetRecordingStartTime() == recstartts)
4233 if (!git.key().isEmpty() && git.key() == groupname)
4237 qVariantFromValue(*pit));
4241 if (item_cur && (item_by_data == item_cur))
4251 pit = (*git).erase(pit);
4261 if (!groupname.isEmpty() && (git.key() == groupname))
4270 sel_item = next_item;
4273 groupname = sel_item->
GetData().toString();
4314 uint chanid,
const QDateTime &recstartts, uint64_t filesize)
4326 QCoreApplication::postEvent(
this,
new MythEvent(
"UPDATE_UI_LIST"));
4365 QStringList groupNames;
4366 QStringList displayNames;
4368 QStringList displayGroups;
4375 uint totalItems = 0;
4378 displayNames.append(QString(
"------- %1 -------").arg(tr(
"Groups")));
4379 groupNames.append(
"");
4382 query.
prepare(
"SELECT recgroup, COUNT(title) FROM recorded "
4383 "WHERE deletepending = 0 AND watched <= :WATCHED "
4384 "GROUP BY recgroup");
4388 while (query.
next())
4390 dispGroup = query.
value(0).toString();
4391 items = query.
value(1).toInt();
4394 (dispGroup !=
"Deleted"))
4395 totalItems +=
items;
4397 groupNames.append(dispGroup);
4399 dispGroup = (dispGroup ==
"Default") ? tr(
"Default") : dispGroup;
4400 dispGroup = (dispGroup ==
"Deleted") ? tr(
"Deleted") : dispGroup;
4401 dispGroup = (dispGroup ==
"LiveTV") ? tr(
"Live TV") : dispGroup;
4403 displayNames.append(tr(
"%1 [%n item(s)]", 0, items).arg(dispGroup));
4410 displayNames.push_front(tr(
"%1 [%n item(s)]", 0, totalItems)
4412 groupNames.push_front(
"All Programs");
4416 query.
prepare(
"SELECT DISTINCT category, COUNT(title) FROM recorded "
4417 "WHERE deletepending = 0 AND watched <= :WATCHED "
4418 "GROUP BY category");
4422 int unknownCount = 0;
4423 while (query.
next())
4425 items = query.
value(1).toInt();
4426 dispGroup = query.
value(0).toString();
4427 if (dispGroup.isEmpty())
4429 unknownCount +=
items;
4430 dispGroup = tr(
"Unknown");
4432 else if (dispGroup == tr(
"Unknown"))
4433 unknownCount +=
items;
4436 (dispGroup != tr(
"Unknown")))
4438 displayGroups += tr(
"%1 [%n item(s)]", 0, items).arg(dispGroup);
4439 groups += dispGroup;
4445 if (unknownCount > 0)
4447 dispGroup = tr(
"Unknown");
4448 items = unknownCount;
4449 displayGroups += tr(
"%1 [%n item(s)]", 0, items).arg(dispGroup);
4450 groups += dispGroup;
4457 displayNames.append(QString(
"------- %1 -------").arg(tr(
"Categories")));
4458 groupNames.append(
"");
4460 displayGroups.sort();
4461 QStringList::iterator it;
4462 for (it = displayGroups.begin(); it != displayGroups.end(); ++it)
4463 displayNames.append(*it);
4464 for (it = groups.begin(); it != groups.end(); ++it)
4465 groupNames.append(*it);
4467 QString label = tr(
"Change Filter");
4470 displayNames, groupNames,
4473 if (recGroupPopup->
Create())
4477 connect(recGroupPopup, SIGNAL(result(QString)),
4479 connect(recGroupPopup, SIGNAL(
Exiting()),
4484 delete recGroupPopup;
4500 QString newRecGroup = recGroup;
4502 if (newRecGroup.isEmpty())
4509 newRecGroup =
"Default";
4511 newRecGroup =
"All Programs";
4513 newRecGroup =
"LiveTV";
4515 newRecGroup =
"Deleted";
4549 query.
prepare(
"SELECT recgroup, password FROM recgrouppassword "
4550 "WHERE password IS NOT NULL AND password <> '';");
4554 while (query.
next())
4556 QString recgroup = query.
value(0).toString();
4559 recgroup =
"Default";
4561 recgroup =
"All Programs";
4563 recgroup =
"LiveTV";
4565 recgroup =
"Deleted";
4591 "SELECT recgroup, COUNT(title) FROM recorded "
4592 "WHERE deletepending = 0 GROUP BY recgroup ORDER BY recgroup");
4594 QStringList displayNames(tr(
"Add New"));
4595 QStringList groupNames(
"addnewgroup");
4600 while (query.
next())
4602 QString dispGroup = query.
value(0).toString();
4603 groupNames.push_back(dispGroup);
4605 if (dispGroup ==
"Default")
4606 dispGroup = tr(
"Default");
4607 else if (dispGroup ==
"LiveTV")
4608 dispGroup = tr(
"Live TV");
4609 else if (dispGroup ==
"Deleted")
4610 dispGroup = tr(
"Deleted");
4612 displayNames.push_back(tr(
"%1 [%n item(s)]",
"", query.
value(1).toInt())
4616 QString label = tr(
"Select Recording Group") +
4625 connect(rgChanger, SIGNAL(result(QString)), SLOT(
setRecGroup(QString)));
4649 QStringList groupNames(tr(
"Default"));
4650 QStringList displayNames(
"Default");
4653 QStringList::const_iterator it = list.begin();
4654 for (; it != list.end(); ++it)
4656 displayNames.push_back(*it);
4657 groupNames.push_back(*it);
4660 QString label = tr(
"Select Playback Group") +
4669 connect(pgChanger, SIGNAL(result(QString)),
4680 QStringList::Iterator it;
4697 QStringList::Iterator it;
4719 if (editMetadata->
Create())
4721 connect(editMetadata, SIGNAL(result(
const QString &,
const QString &,
4722 const QString &,
const QString &,
uint,
uint)), SLOT(
4724 const QString &,
const QString &,
uint,
uint)));
4728 delete editMetadata;
4732 const QString &newSubtitle,
4733 const QString &newDescription,
4734 const QString &newInetref,
4750 if (groupname == pginfo->
GetTitle().toLower() &&
4757 QString tempSubTitle = newTitle;
4758 if (!newSubtitle.trimmed().isEmpty())
4759 tempSubTitle = QString(
"%1 - \"%2\"")
4760 .arg(tempSubTitle).arg(newSubtitle);
4766 if (newSeason > 0 || newEpisode > 0)
4770 seasone = QString(
"s%1e%2")
4773 seasonx = QString(
"%1x%2")
4778 item->
SetText(tempSubTitle,
"titlesubtitle");
4779 item->
SetText(newTitle,
"title");
4780 item->
SetText(newSubtitle,
"subtitle");
4781 item->
SetText(newInetref,
"inetref");
4782 item->
SetText(seasonx,
"00x00");
4783 item->
SetText(seasone,
"s00e00");
4784 item->
SetText(season,
"season");
4785 item->
SetText(episode,
"episode");
4786 if (newDescription != NULL)
4787 item->
SetText(newDescription,
"description");
4800 newRecGroup = newRecGroup.simplified();
4802 if (newRecGroup.isEmpty())
4805 if (newRecGroup ==
"addnewgroup")
4811 popupStack, tr(
"New Recording Group"));
4813 connect(newgroup, SIGNAL(haveResult(QString)),
4829 QStringList::const_iterator it;
4837 (newRecGroup !=
"LiveTV"))
4842 (newRecGroup ==
"LiveTV"))
4875 if (newPlayGroup.isEmpty() || !tmpItem)
4878 if (newPlayGroup == tr(
"Default"))
4879 newPlayGroup =
"Default";
4883 QStringList::Iterator it;
4912 QString recgroup = item->
GetData().toString();
4920 connect(pwChanger, SIGNAL(result(
const QString &)),
4932 query.
prepare(
"DELETE FROM recgrouppassword "
4933 "WHERE recgroup = :RECGROUP ;");
4940 if (!newPassword.isEmpty())
4942 query.
prepare(
"INSERT INTO recgrouppassword "
4943 "(recgroup, password) VALUES "
4944 "( :RECGROUP , :PASSWD )");
4946 query.
bindValue(
":PASSWD", newPassword);
4959 const QStringList &list,
const QStringList &
data,
4960 const QString &selected)
4962 m_List(list), m_Data(data), m_selected(selected)
4977 LOG(VB_GENERAL, LOG_ERR,
LOC +
4978 "Theme is missing 'groups' button list.");
4985 for (
int i = 0; i <
m_List.size(); ++i)
4988 qVariantFromValue(
m_Data.at(i)));
5008 if (item->
GetData().toString().isEmpty())
5011 QString group = item->
GetData().toString();
5021 m_parentScreen(parentscreen), m_viewMask(viewMask)
5037 connect(checkBox, SIGNAL(toggled(
bool)),
5046 connect(checkBox, SIGNAL(toggled(
bool)),
5055 connect(checkBox, SIGNAL(toggled(
bool)),
5066 connect(checkBox, SIGNAL(toggled(
bool)),
5076 connect(checkBox, SIGNAL(toggled(
bool)),
5087 connect(checkBox, SIGNAL(toggled(
bool)),
5097 connect(checkBox, SIGNAL(toggled(
bool)),
5102 connect(savebutton, SIGNAL(Clicked()), SLOT(
SaveChanges()));
5119 m_oldPassword(oldpassword)
5136 LOG(VB_GENERAL, LOG_ERR,
LOC +
5137 "Window 'passwordchanger' is missing required elements.");
5195 LOG(VB_GENERAL, LOG_ERR,
LOC +
5196 "Window 'editmetadata' is missing required elements.");
5216 connect(okButton, SIGNAL(Clicked()), SLOT(
SaveChanges()));
5227 QString newRecDescription = NULL;
5228 QString newRecInetref = NULL;
5229 uint newRecSeason = 0, newRecEpisode = 0;
5236 if (newRecTitle.isEmpty())
5239 emit
result(newRecTitle, newRecSubtitle, newRecDescription,
5240 newRecInetref, newRecSeason, newRecEpisode);
5262 LOG(VB_GENERAL, LOG_ERR,
LOC +
5263 "Window 'iconhelp' is missing required elements.");
5269 addItem(
"commflagged", tr(
"Commercials are flagged"));
5270 addItem(
"cutlist", tr(
"An editing cutlist is present"));
5271 addItem(
"autoexpire", tr(
"The program is able to auto-expire"));
5272 addItem(
"processing", tr(
"Commercials are being flagged"));
5273 addItem(
"bookmark", tr(
"A bookmark is set"));
5275 addItem(
"inuse", tr(
"Recording is in use"));
5276 addItem(
"transcoded", tr(
"Recording has been transcoded"));
5279 addItem(
"mono", tr(
"Recording is in Mono"));
5280 addItem(
"stereo", tr(
"Recording is in Stereo"));
5281 addItem(
"surround", tr(
"Recording is in Surround Sound"));
5282 addItem(
"dolby", tr(
"Recording is in Dolby Surround Sound"));
5284 addItem(
"cc", tr(
"Recording is Closed Captioned"));
5285 addItem(
"subtitles", tr(
"Recording has Subtitles Available"));
5286 addItem(
"onscreensub", tr(
"Recording is Subtitled"));
5288 addItem(
"hd1080", tr(
"Recording is in 1080i/p High Definition"));
5289 addItem(
"hd720", tr(
"Recording is in 720p High Definition"));
5290 addItem(
"hdtv", tr(
"Recording is in High Definition"));
5291 addItem(
"widescreen", tr(
"Recording is Widescreen"));
5292 addItem(
"avchd", tr(
"Recording is in HD using H.264 codec"));
5294 addItem(
"watched", tr(
"Recording has been watched"));