Go to the documentation of this file.
36 #include "libmythbase/mythversion.h"
67 const QString &sTitleRegEx,
68 const QString &sRecGroup,
69 const QString &sStorageGroup,
70 const QString &sCategory,
76 QMap< QString, ProgramInfo* > recMap;
90 if (bIgnoreLiveTV && (sRecGroup ==
"LiveTV"))
92 bIgnoreLiveTV =
false;
93 LOG(VB_GENERAL, LOG_ERR, QString(
"Setting Ignore%1=false because RecGroup=%1")
97 if (bIgnoreDeleted && (sRecGroup ==
"Deleted"))
99 bIgnoreDeleted =
false;
100 LOG(VB_GENERAL, LOG_ERR, QString(
"Setting Ignore%1=false because RecGroup=%1")
105 sSort, bIgnoreLiveTV, bIgnoreDeleted );
107 QMap< QString, ProgramInfo* >::iterator mit = recMap.begin();
109 for (; mit != recMap.end(); mit = recMap.erase(mit))
119 int nMax = (nCount > 0) ? nCount : progList.
size();
124 QRegularExpression rTitleRegEx
125 { sTitleRegEx, QRegularExpression::CaseInsensitiveOption };
127 for (
auto *pInfo : progList)
129 if (pInfo->IsDeletePending() ||
130 (!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
131 (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
132 (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()) ||
133 (!sCategory.isEmpty() && sCategory != pInfo->GetCategory()))
136 if ((nAvailable < nStartIndex) ||
153 pPrograms->setStartIndex ( nStartIndex );
154 pPrograms->setCount ( nCount );
155 pPrograms->setTotalAvailable( nAvailable );
157 pPrograms->setVersion ( MYTH_BINARY_VERSION );
158 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
170 const QDateTime &sStartTime,
171 const QDateTime &sEndTime,
172 const QString &sTitle,
173 const QString &sSeriesId,
175 const QString &sSort)
177 if (!sStartTime.isNull() && !sStartTime.isValid())
178 throw QString(
"StartTime is invalid");
180 if (!sEndTime.isNull() && !sEndTime.isValid())
181 throw QString(
"EndTime is invalid");
183 const QDateTime& dtStartTime = sStartTime;
184 const QDateTime& dtEndTime = sEndTime;
186 if (!sEndTime.isNull() && dtEndTime < dtStartTime)
187 throw QString(
"EndTime is before StartTime");
197 if (!dtStartTime.isNull())
199 sSQL +=
" AND endtime >= :StartDate ";
200 bindings[
":StartDate"] = dtStartTime;
203 if (!dtEndTime.isNull())
205 sSQL +=
" AND starttime <= :EndDate ";
206 bindings[
":EndDate"] = dtEndTime;
213 clause <<
"recordid = :RecordId";
214 bindings[
":RecordId"] = nRecordId;
217 if (!sTitle.isEmpty())
219 clause <<
"title = :Title";
220 bindings[
":Title"] = sTitle;
223 if (!sSeriesId.isEmpty())
225 clause <<
"seriesid = :SeriesId";
226 bindings[
":SeriesId"] = sSeriesId;
229 if (!clause.isEmpty())
231 sSQL += QString(
" AND (%1) ").arg(clause.join(
" OR "));
234 if (sSort ==
"starttime")
235 sSQL +=
"ORDER BY starttime ";
236 else if (sSort ==
"title")
237 sSQL +=
"ORDER BY title ";
239 sSQL +=
"ORDER BY starttime ";
246 uint nTotalAvailable = (nStartIndex == 0) ? 1 : 0;
248 (
uint)nStartIndex, (
uint)nCount, nTotalAvailable );
256 nCount = (int)progList.
size();
257 int nEndIndex = (int)progList.
size();
259 for(
int n = 0; n < nEndIndex; n++)
270 pPrograms->setStartIndex ( nStartIndex );
271 pPrograms->setCount ( nCount );
272 pPrograms->setTotalAvailable( nTotalAvailable );
274 pPrograms->setVersion ( MYTH_BINARY_VERSION );
275 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
285 int chanid,
const QDateTime &recstarttsRaw)
287 if ((RecordedId <= 0) &&
288 (chanid <= 0 || !recstarttsRaw.isValid()))
289 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
313 throw QString(
"AddRecordedCredits: recordedid %1 does "
314 "not exist.").arg(RecordedId);
317 if (credits ==
nullptr)
318 throw QString(
"AddRecordedCredits: Failed to parse cast from json.");
321 for (
auto & person : *credits)
323 if (!person.InsertDB(query, ri.
GetChanID(),
325 throw QString(
"AddRecordedCredits: Failed to add credit "
326 "%1 to DB").arg(person.toString());
339 QJsonObject root = jsonObj;
340 QJsonObject program = root[
"Program"].toObject();
341 QJsonObject channel = program[
"Channel"].toObject();
342 QJsonObject recording = program[
"Recording"].toObject();
343 QJsonObject cast = program[
"Cast"].toObject();
346 int chanid = channel.value(
"ChanId").toString(
"0").toUInt();
347 QString
hostname = program[
"HostName"].toString(
"");
350 throw QString(
"AddRecordedProgram: chanid %1 does "
351 "not exist.").arg(chanid);
353 pi->m_title = program.value(
"Title").toString(
"");
354 pi->m_subtitle = program.value(
"SubTitle").toString(
"");
355 pi->m_description = program.value(
"Description").toString(
"");
356 pi->m_category = program.value(
"Category").toString(
"");
363 pi->m_airdate = pi->m_originalairdate.year();
364 pi->m_partnumber = program.value(
"PartNumber").toString(
"0").toUInt();
365 pi->m_parttotal = program.value(
"PartTotal").toString(
"0").toUInt();
366 pi->m_syndicatedepisodenumber =
"";
368 (program.value(
"SubPropNames").toString(
""));
370 (program.value(
"AudioPropNames").toString(
""));
372 (program.value(
"VideoPropNames").toString(
""));
373 pi->m_stars = program.value(
"Stars").toString(
"0.0").toFloat();
375 pi->m_seriesId = program.value(
"SeriesId").toString(
"");
376 pi->m_programId = program.value(
"ProgramId").toString(
"");
377 pi->m_inetref = program.value(
"Inetref").toString(
"");
378 pi->m_previouslyshown =
false;
379 pi->m_listingsource = 0;
382 pi->m_season = program.value(
"Season").toString(
"0").toUInt();
383 pi->m_episode = program.value(
"Episode").toString(
"0").toUInt();
384 pi->m_totalepisodes = program.value(
"TotalEpisodes").toString(
"0").toUInt();
386 pi->m_channel = channel.value(
"ChannelName").toString(
"");
388 pi->m_startts = recording.value(
"StartTs").toString(
"");
389 pi->m_endts = recording.value(
"EndTs").toString(
"");
393 pi->m_title_pronounce =
"";
396 pi->m_colorcode =
"";
404 if (!pi->InsertDB(query, chanid,
true))
406 throw QString(
"AddRecordedProgram: "
407 "Failed to add recordedprogram entry.");
412 pi->m_subtitle, pi->m_subtitle,
414 pi->m_season, pi->m_episode,
416 pi->m_syndicatedepisodenumber,
419 channel.value(
"ChanNum").toString(
"0"),
420 channel.value(
"CallSign").toString(
""),
422 recording.value(
"RecGroup").toString(
""),
423 recording.value(
"PlayGroup").toString(
""),
425 recording.value(
"StorageGroup").toString(
""),
433 recording.value(
"Priority").toString(
"0").toInt(),
439 pi->m_originalairdate,
440 program.value(
"Repeat").toString(
"false").toLower() ==
"true",
441 static_cast<RecStatus::Type>(recording.value(
"Status").toString(
"-3").toInt()),
443 recording.value(
"RecordedId").toString(
"0").toInt(),
445 static_cast<RecordingType>(recording.value(
"RecType").toString(
"0").toInt()),
448 channel.value(
"SourceId").toString(
"0").toUInt(),
449 channel.value(
"InputId").toString(
"0").toUInt(),
451 channel.value(
"CommFree").toString(
"false").toLower() ==
"true",
459 recording.value(
"EncoderName").toString(
""));
463 QString
filename = program.value(
"FileName").toString(
"");
465 int idx =
filename.lastIndexOf(
'.');
470 throw QString(
"Failed to create RecordingInfo database entry. "
471 "Non unique starttime?");
494 int chanid,
const QDateTime &recstarttsRaw,
495 bool forceDelete,
bool allowRerecord)
503 int chanid,
const QDateTime &recstarttsRaw,
504 bool forceDelete,
bool allowRerecord)
506 if ((RecordedId <= 0) &&
507 (chanid <= 0 || !recstarttsRaw.isValid()))
508 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
519 QString cmd = QString(
"DELETE_RECORDING %1 %2 %3 %4")
522 forceDelete ?
"FORCE" :
"NO_FORCE",
523 allowRerecord ?
"FORGET" :
"NO_FORGET");
538 int chanid,
const QDateTime &recstarttsRaw)
540 if ((RecordedId <= 0) &&
541 (chanid <= 0 || !recstarttsRaw.isValid()))
542 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
552 QString cmd = QString(
"UNDELETE_RECORDING %1 %2")
571 throw QString(
"RecordedId param is invalid.");
577 QString cmd = QString(
"STOP_RECORDING %1 %2")
585 throw QString(
"RecordedId %1 not found").arg(RecordedId);
595 int chanid,
const QDateTime &recstarttsRaw)
597 if ((RecordedId <= 0) &&
598 (chanid <= 0 || !recstarttsRaw.isValid()))
599 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
623 "RescheduleRecordings");
634 throw QString(
"RecordedId param is invalid.");
639 throw QString(
"RecordedId %1 not found").arg(RecordedId);
652 const QDateTime &recstarttsRaw,
655 if ((RecordedId <= 0) &&
656 (chanid <= 0 || !recstarttsRaw.isValid()))
657 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
681 const QDateTime &recstarttsRaw,
682 const QString &offsettype )
684 if ((RecordedId <= 0) &&
685 (chanid <= 0 || !recstarttsRaw.isValid()))
686 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
699 if (offsettype.toLower() ==
"position"){
705 if (offsettype.toLower() ==
"duration"){
720 const QDateTime &recstarttsRaw,
721 const QString &offsettype,
724 if ((RecordedId <= 0) &&
725 (chanid <= 0 || !recstarttsRaw.isValid()))
726 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
729 throw QString(
"Offset must be >= 0.");
736 uint64_t position = 0;
738 if (offsettype.toLower() ==
"position"){
742 else if (offsettype.toLower() ==
"duration"){
758 const QDateTime &recstarttsRaw,
759 const QString &offsettype )
762 if ((RecordedId <= 0) &&
763 (chanid <= 0 || !recstarttsRaw.isValid()))
764 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
773 if (offsettype.toLower() ==
"position")
775 else if (offsettype.toLower() ==
"duration")
791 const QDateTime &recstarttsRaw,
792 const QString &offsettype )
795 if ((RecordedId <= 0) &&
796 (chanid <= 0 || !recstarttsRaw.isValid()))
797 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
806 if (offsettype.toLower() ==
"position")
808 else if (offsettype.toLower() ==
"duration")
823 const QString &offsettype )
827 throw QString(
"Recorded ID appears invalid.");
833 if (offsettype.toLower() ==
"bytes")
835 else if (offsettype.toLower() ==
"duration")
840 throw QString(
"Type must be 'BYTES' or 'DURATION'.");
858 throw QString(
"Invalid RecordedId %1").arg(RecordedId);
860 QVector<ProgramInfo::MarkupEntry> mapMark;
861 QVector<ProgramInfo::MarkupEntry> mapSeek;
866 for (
const auto& entry : qAsConst(mapMark))
868 DTC::Markup *pMarkup = pMarkupList->AddNewMarkup();
870 pMarkup->setType(typestr);
871 pMarkup->setFrame(entry.frame);
872 if (entry.isDataNull)
873 pMarkup->setData(
"NULL");
875 pMarkup->setData(QString::number(entry.data));
877 for (
const auto& entry : qAsConst(mapSeek))
881 pSeek->setType(typestr);
882 pSeek->setFrame(entry.frame);
883 if (entry.isDataNull)
884 pSeek->setData(
"NULL");
886 pSeek->setData(QString::number(entry.data));
903 throw QString(
"Invalid RecordedId %1").arg(RecordedId);
905 QVector<ProgramInfo::MarkupEntry> mapMark;
906 QVector<ProgramInfo::MarkupEntry> mapSeek;
908 QJsonObject markuplist = jsonObj[
"MarkupList"].toObject();
910 QJsonArray
marks = markuplist[
"Mark"].toArray();
911 for (
const auto & m :
marks)
913 QJsonObject markup = m.toObject();
916 QString typestr = markup.value(
"Type").toString(
"");
918 entry.
frame = markup.value(
"Frame").toString(
"-1").toLongLong();
919 QString data = markup.value(
"Data").toString(
"NULL");
922 entry.
data = data.toLongLong();
924 mapMark.append(entry);
927 QJsonArray seeks = markuplist[
"Seek"].toArray();
928 for (
const auto & m : seeks)
930 QJsonObject markup = m.toObject();
933 QString typestr = markup.value(
"Type").toString(
"");
935 entry.
frame = markup.value(
"Frame").toString(
"-1").toLongLong();
936 QString data = markup.value(
"Data").toString(
"NULL");
939 entry.
data = data.toLongLong();
941 mapSeek.append(entry);
967 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)infoList.size() ) : 0;
968 nCount = (nCount > 0) ? std::min( nCount, (
int)infoList.size() ) : infoList.size();
969 int nEndIndex = std::min((nStartIndex + nCount), (
int)infoList.size() );
971 for(
int n = nStartIndex; n < nEndIndex; n++)
975 if (pInfo !=
nullptr)
987 pPrograms->setStartIndex ( nStartIndex );
988 pPrograms->setCount ( nCount );
989 pPrograms->setTotalAvailable( infoList.size() );
991 pPrograms->setVersion ( MYTH_BINARY_VERSION );
992 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1007 for (
auto * elink : qAsConst(
gTVList))
1009 if (elink !=
nullptr)
1013 pEncoder->setId ( elink->GetInputID() );
1014 pEncoder->setState ( elink->GetState() );
1015 pEncoder->setLocal ( elink->IsLocal() );
1016 pEncoder->setConnected ( elink->IsConnected() );
1017 pEncoder->setSleepStatus ( elink->GetSleepStatus() );
1020 if (pEncoder->
Local())
1023 pEncoder->setHostName( elink->GetHostName() );
1025 for (
const auto & inputInfo : qAsConst(inputInfoList))
1027 if (inputInfo.m_inputId ==
static_cast<uint>(elink->GetInputID()))
1034 switch ( pEncoder->
State() )
1071 for (
const auto & inputInfo : qAsConst(inputInfoList))
1087 query.
prepare(
"SELECT recgroup FROM recgroups WHERE recgroup <> 'Deleted' "
1088 "ORDER BY recgroup");
1097 while (query.
next())
1098 result << query.
value(0).toString();
1112 query.
prepare(
"SELECT DISTINCT category FROM recorded ORDER BY category");
1114 query.
prepare(
"SELECT DISTINCT category FROM program ORDER BY category");
1123 while (query.
next())
1124 result << query.
value(0).toString();
1157 query.
prepare(
"SELECT filterid, description, newruledefault "
1158 "FROM recordfilter ORDER BY filterid");
1162 while (query.
next())
1165 ruleFilter->setId(query.
value(0).toInt());
1166 ruleFilter->setDescription(QObject::tr(query.
value(1).toString()
1167 .toUtf8().constData()));
1182 QString querystr =
"SELECT DISTINCT title FROM recorded "
1183 "WHERE deletepending = 0";
1185 if (!RecGroup.isEmpty())
1186 querystr +=
" AND recgroup = :RECGROUP";
1188 querystr +=
" AND recgroup != 'Deleted'";
1190 querystr +=
" ORDER BY title";
1194 if (!RecGroup.isEmpty())
1204 while (query.
next())
1205 result << query.
value(0).toString();
1218 QString querystr = QString(
1219 "SELECT title, inetref, count(title) as count "
1220 " FROM recorded AS r "
1221 " JOIN recgroups AS g ON r.recgroupid = g.recgroupid "
1222 " WHERE g.recgroup NOT IN ('Deleted', 'LiveTV') "
1223 " AND r.deletepending = 0 "
1224 " GROUP BY title, inetref "
1236 while (query.
next())
1240 pTitleInfo->setTitle(query.
value(0).toString());
1241 pTitleInfo->setInetref(query.
value(1).toString());
1242 pTitleInfo->setCount(query.
value(2).toInt());
1272 for (
auto it = tmpList.begin(); it < tmpList.end(); ++it)
1274 if ((nRecStatus != 0) &&
1275 ((*it)->GetRecordingStatus() != nRecStatus))
1290 else if (bShowAll &&
1306 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recordingList.
size() ) : 0;
1307 nCount = (nCount > 0) ? std::min( nCount, (
int)recordingList.
size() ) : recordingList.
size();
1308 int nEndIndex = std::min((nStartIndex + nCount), (
int)recordingList.
size() );
1310 for(
int n = nStartIndex; n < nEndIndex; n++)
1321 pPrograms->setStartIndex ( nStartIndex );
1322 pPrograms->setCount ( nCount );
1323 pPrograms->setTotalAvailable( recordingList.
size() );
1325 pPrograms->setVersion ( MYTH_BINARY_VERSION );
1326 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1353 for (
auto it = tmpList.begin(); it < tmpList.end(); ++it)
1370 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recordingList.
size() ) : 0;
1371 nCount = (nCount > 0) ? std::min( nCount, (
int)recordingList.
size() ) : recordingList.
size();
1372 int nEndIndex = std::min((nStartIndex + nCount), (
int)recordingList.
size() );
1374 for(
int n = nStartIndex; n < nEndIndex; n++)
1385 pPrograms->setStartIndex ( nStartIndex );
1386 pPrograms->setCount ( nCount );
1387 pPrograms->setTotalAvailable( recordingList.
size() );
1389 pPrograms->setVersion ( MYTH_BINARY_VERSION );
1390 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1396 const QString& sTitle,
1397 const QString& sSubtitle,
1398 const QString& sDescription,
1399 const QString& sCategory,
1400 const QDateTime& recstarttsRaw,
1401 const QDateTime& recendtsRaw,
1402 const QString& sSeriesId,
1403 const QString& sProgramId,
1405 const QString& sStation,
1412 const QString& sInetref,
1414 QString sSearchType,
1416 uint nPreferredInput,
1419 const QDateTime& lastrectsRaw,
1424 QString sRecProfile,
1426 QString sStorageGroup,
1432 bool bAutoTranscode,
1433 bool bAutoMetaLookup,
1440 QDateTime recstartts = recstarttsRaw.toUTC();
1441 QDateTime recendts = recendtsRaw.toUTC();
1442 QDateTime lastrects = lastrectsRaw.toUTC();
1446 if (sType.isEmpty())
1449 if (sSearchType.isEmpty())
1450 sSearchType =
"none";
1452 if (sDupMethod.isEmpty())
1453 sDupMethod =
"subtitleanddescription";
1455 if (sDupIn.isEmpty())
1475 if (sRecProfile.isEmpty())
1476 sRecProfile =
"Default";
1478 if (sRecGroup.isEmpty())
1479 sRecGroup =
"Default";
1481 if (sStorageGroup.isEmpty())
1482 sStorageGroup =
"Default";
1484 if (sPlayGroup.isEmpty())
1485 sPlayGroup =
"Default";
1550 const QString& sTitle,
1551 const QString& sSubtitle,
1552 const QString& sDescription,
1553 const QString& sCategory,
1554 const QDateTime& dStartTimeRaw,
1555 const QDateTime& dEndTimeRaw,
1556 const QString& sSeriesId,
1557 const QString& sProgramId,
1559 const QString& sStation,
1565 const QString& sInetref,
1567 QString sSearchType,
1569 uint nPreferredInput,
1576 QString sRecProfile,
1578 QString sStorageGroup,
1584 bool bAutoTranscode,
1585 bool bAutoMetaLookup,
1592 if (nRecordId == 0 )
1593 throw QString(
"Record ID is invalid.");
1600 throw QString(
"Record ID does not exist.");
1602 QDateTime recstartts = dStartTimeRaw.toUTC();
1603 QDateTime recendts = dEndTimeRaw.toUTC();
1606 if (sType.isEmpty())
1609 if (sSearchType.isEmpty())
1610 sSearchType =
"none";
1612 if (sDupMethod.isEmpty())
1613 sDupMethod =
"subtitleanddescription";
1615 if (sDupIn.isEmpty())
1626 if (sRecProfile.isEmpty())
1627 sRecProfile =
"Default";
1629 if (sRecGroup.isEmpty())
1630 sRecGroup =
"Default";
1632 if (sStorageGroup.isEmpty())
1633 sStorageGroup =
"Default";
1635 if (sPlayGroup.isEmpty())
1636 sPlayGroup =
"Default";
1638 if (!sTitle.isEmpty())
1641 if (!sSubtitle.isEmpty())
1644 if(!sDescription.isEmpty())
1647 if (!sCategory.isEmpty())
1650 if (!sSeriesId.isEmpty())
1653 if (!sProgramId.isEmpty())
1658 if (!sStation.isEmpty())
1711 bool bResult = pRule.
Save();
1718 bool bResult =
false;
1720 if (nRecordId == 0 )
1721 throw QString(
"Record ID does not exist.");
1726 bResult = pRule.
Delete();
1734 bool bResult =
true;
1736 if (nChanId <= 0 || !dStartTime.isValid())
1737 throw QString(
"Program does not exist.");
1742 throw QString(
"Program does not exist.");
1761 const QString &Sort,
1765 if (Sort.toLower() ==
"lastrecorded")
1767 else if (Sort.toLower() ==
"nextrecording")
1769 else if (Sort.toLower() ==
"title")
1771 else if (Sort.toLower() ==
"priority")
1773 else if (Sort.toLower() ==
"type")
1787 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recList.size() ) : 0;
1788 nCount = (nCount > 0) ? std::min( nCount, (
int)recList.size() ) : recList.size();
1789 int nEndIndex = std::min((nStartIndex + nCount), (
int)recList.size() );
1791 for(
int n = nStartIndex; n < nEndIndex; n++)
1795 if (info !=
nullptr)
1805 pRecRules->setStartIndex ( nStartIndex );
1806 pRecRules->setCount ( nCount );
1807 pRecRules->setTotalAvailable( recList.size() );
1809 pRecRules->setVersion ( MYTH_BINARY_VERSION );
1810 pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
1812 while (!recList.empty())
1814 delete recList.back();
1822 const QString& sTemplate,
1825 const QDateTime& dStartTimeRaw,
1826 bool bMakeOverride )
1829 QDateTime dStartTime = dStartTimeRaw.toUTC();
1835 throw QString(
"Record ID does not exist.");
1837 else if (!sTemplate.isEmpty())
1840 throw QString(
"Template does not exist.");
1842 else if (nRecordedId > 0)
1847 throw QString(
"Recording does not exist");
1849 else if (nChanId > 0 && dStartTime.isValid())
1854 RecordingInfo info(nChanId, dStartTime,
false, 0h, &status);
1856 throw QString(
"Program does not exist.");
1865 throw QString(
"Invalid request.");
1876 bool bResult =
false;
1878 if (nRecordId == 0 )
1879 throw QString(
"Record ID appears invalid.");
1888 bResult = pRule.
Save();
1896 bool bResult =
false;
1898 if (nRecordId == 0 )
1899 throw QString(
"Record ID appears invalid.");
1908 bResult = pRule.
Save();
1927 uint recordedid = 0;
1942 const QDateTime &StartTime)
1954 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
1964 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
2002 const QString &sJobName,
2005 QDateTime jobstarttsRaw,
2006 QString sRemoteHost,
2014 LOG(VB_GENERAL, LOG_ERR,
"JobName and RecordedId are required.");
2018 if (sRemoteHost.isEmpty())
2031 if ( sAction ==
"Remove")
2035 LOG(VB_GENERAL, LOG_ERR,
"For Remove, a valid JobId is required.");
2046 if ( sAction !=
"Add")
2048 LOG(VB_GENERAL, LOG_ERR, QString(
"Illegal Action name '%1'. Use: Add, "
2049 "or Remove").arg(sAction));
2056 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been defined.")
2062 sRemoteHost,
false))
2064 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been allowed on host %2.")
2065 .arg(sJobName, sRemoteHost));
2069 if (!jobstarttsRaw.isValid())
2070 jobstarttsRaw = QDateTime::currentDateTime();
2075 if (sJobArgs.isNull())
2082 QString(
"Dvr/ManageJobQueue"),
2086 jobstarttsRaw.toUTC());
2090 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 job wasn't queued because of a "
2091 "database error or because it was "
2092 "already running/stopping etc.")
static QStringList getRecordingsGroups(void)
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
QString DupMethodToDescription(const QString &DupMethod) override
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
bool LoadByProgram(const ProgramInfo *proginfo)
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool SetRecordedMarkup(int RecordedId, const QJsonObject &json) override
void FillProgramInfo(DTC::Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast)
DTC::RecRule * GetRecordSchedule(uint RecordId, const QString &Template, int nRecordedId, int ChanId, const QDateTime &dStartTimeRaw, bool MakeOverride) override
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
DTC::MarkupList * GetRecordedMarkup(int RecordedId) override
static bool QueryRecordedIdForKey(int &recordedid, uint chanid, const QDateTime &recstartts)
void FillRecRuleInfo(DTC::RecRule *pRecRule, RecordingRule *pRule)
void ApplyNeverRecord(void)
Set this program to never be recorded by inserting 'history' for it into the database with a status o...
DTC::RecRuleFilterList * GetRecRuleFilterList() override
void SaveBookmark(uint64_t frame)
Clears any existing bookmark in DB and if frame is greater than 0 sets a new bookmark.
void SetRecordingStatus(RecStatus::Type status)
QString RecStatusToDescription(int RecStatus, int RecType, const QDateTime &StartTime) override
MythScheduler * GetScheduler(void)
int AddRecordedProgram(const QJsonObject &json) override
ProgramInfo * LoadProgramFromProgram(const uint chanid, const QDateTime &starttime)
bool Save(bool sendSig=true)
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())
void ApplyRecordStateChange(RecordingType newstate, bool save=true)
Sets RecordingType of "record", creating "record" if it does not exist.
RecSearchType searchTypeFromString(const QString &type)
QStringList GetProgramCategories(bool OnlyRecorded) override
RecordingDupInType dupInFromString(const QString &type)
static void GetAllScheduled(QStringList &strList, SchedSortColumn sortBy=kSortTitle, bool ascending=true)
Returns all scheduled programs serialized into a QStringList.
Holds information on a TV Program one might wish to record.
void ForgetHistory(void)
Forget the recording of a program so it will be recorded again.
void QueryMarkup(QVector< MarkupEntry > &mapMark, QVector< MarkupEntry > &mapSeek) const
uint GetRecordingID(void) const
bool AllowReRecord(int RecordedId) override
DTC::TitleInfoList * GetTitleInfoList() override
This class is used as a container for messages.
DTC::ProgramList * GetOldRecordedList(bool Descending, int StartIndex, int Count, const QDateTime &StartTime, const QDateTime &EndTime, const QString &Title, const QString &SeriesId, int RecordId, const QString &Sort) override
static QMap< QString, bool > QueryJobsRunning(int type)
bool QueryPositionKeyFrame(uint64_t *keyframe, uint64_t position, bool backwards) const
QVariant value(int i) const
Internal representation of a recording rule, mirrors the record table.
static bool SafeDeleteJob(int jobID, int jobType, int chanid, const QDateTime &recstartts)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
bool QueryKeyFrameDuration(uint64_t *duration, uint64_t keyframe, bool backwards) const
DTC::InputList * GetInputList() override
bool LoadFromRecorded(ProgramList &destination, bool possiblyInProgressRecordingsOnly, const QMap< QString, uint32_t > &inUseMap, const QMap< QString, bool > &isJobRunning, const QMap< QString, ProgramInfo * > &recMap, int sort, const QString &sortBy, bool ignoreLiveTV, bool ignoreDeleted)
void GetAllExpiring(QStringList &strList)
Gets the full list of programs that can expire in expiration order.
DTC::CutList * GetRecordedSeek(int RecordedId, const QString &OffsetType) override
RecordingDupInType m_dupIn
int RecordedIdForPathname(const QString &pathname) override
bool m_isInactive
Recording rule is enabled?
QString RecTypeToString(const QString &RecType) override
DTC::ProgramList * GetExpiringList(int StartIndex, int Count) override
QString DupMethodToString(const QString &DupMethod) override
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
DTC::RecRuleList * GetRecordScheduleList(int StartIndex, int Count, const QString &Sort, bool Descending) override
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
bool IsWatched(void) const
std::vector< DBPerson > DBCredits
static QString toString(RecStatus::Type recstatus, uint id)
Converts "recstatus" into a short (unreadable) string.
static bool InJobRunWindow(QDateTime jobstarttsRaw)
bool IsPreserved(void) const
ProgramInfo::CategoryType string_to_myth_category_type(const QString &category_type)
uint64_t QueryBookmark(void) const
Gets any bookmark position in database, unless the ignore bookmark flag is set.
static QStringList GetNames(void)
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
virtual QMap< QString, ProgramInfo * > GetRecording(void) const =0
QString RecStatusToString(int RecStatus) override
bool Load(bool asTemplate=false)
Load a single rule from the recorded table.
bool StopRecording(int RecordedId) override
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
static bool QueryRecordedIdFromPathname(const QString &pathname, uint &recordedid)
bool IsValid(QString &msg) const
DTC::CutList * GetRecordedCutList(int RecordedId, int ChanId, const QDateTime &recstarttsRaw, const QString &OffsetType) override
DTC::EncoderList * GetEncoderList() override
static QString toDescription(Type recstatus, RecordingType rectype, const QDateTime &recstartts)
Converts "recstatus" into a long human readable description.
bool RescheduleRecordings(void) override
void FillCutList(DTC::CutList *pCutList, RecordingInfo *rInfo, int marktype)
DTC::Program * GetRecorded(int RecordedId, int ChanId, const QDateTime &recstarttsRaw) override
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
bool UnDeleteRecording(int RecordedId, int ChanId, const QDateTime &recstarttsRaw) override
static void DBError(const QString &where, const MSqlQuery &query)
QTime m_findtime
Time for timeslot rules.
RecordingDupMethodType dupMethodFromString(const QString &type)
MarkTypes markTypeFromString(const QString &str)
RecSearchType m_searchType
std::vector< ProgramInfo * > pginfolist_t
RecordingType recTypeFromString(const QString &type)
void FillSeek(DTC::CutList *pCutList, RecordingInfo *rInfo, MarkTypes marktype)
bool RemoveRecorded(int RecordedId, int ChanId, const QDateTime &recstarttsRaw, bool ForceDelete, bool AllowRerecord) override
bool UpdateRecordSchedule(uint RecordId, const QString &Title, const QString &Subtitle, const QString &Description, const QString &Category, const QDateTime &dStartTimeRaw, const QDateTime &dEndTimeRaw, const QString &SeriesId, const QString &ProgramId, int ChanId, const QString &Station, int FindDay, QTime FindTime, bool Inactive, uint Season, uint Episode, const QString &Inetref, QString Type, QString SearchType, int RecPriority, uint PreferredInput, int StartOffset, int EndOffset, QString DupMethod, QString DupIn, bool NewEpisOnly, uint Filter, QString RecProfile, QString RecGroup, QString StorageGroup, QString PlayGroup, bool AutoExpire, int MaxEpisodes, bool MaxNewest, bool AutoCommflag, bool AutoTranscode, bool AutoMetaLookup, bool AutoUserJob1, bool AutoUserJob2, bool AutoUserJob3, bool AutoUserJob4, int Transcoder) override
RecordingDupInType dupInFromStringAndBool(const QString &type, bool newEpisodesOnly)
bool UpdateRecordedWatchedStatus(int RecordedId, int ChanId, const QDateTime &recstarttsRaw, bool Watched) override
QStringList GetPlayGroupList() override
QList< QString > m_parsedParams
int m_findday
Day of the week for once per week etc.
bool AddRecordedCredits(int RecordedId, const QJsonObject &json) override
void ReactivateRecording(void)
Asks the scheduler to restart this recording if possible.
static QReadWriteLock s_inputsLock
void ProgramFlagsFromNames(const QString &names)
QMap< int, EncoderLink * > gTVList
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
bool DeleteRecording(int RecordedId, int ChanId, const QDateTime &recstarttsRaw, bool ForceDelete, bool AllowRerecord) override
QString toDescription(RecordingType rectype)
Converts "rectype" into a human readable description.
int RecordedIdForKey(int ChanId, const QDateTime &recstarttsRaw) override
static uint AudioPropertiesFromNames(const QString &names)
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".
static uint SubtitleTypesFromNames(const QString &names)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
QStringList GetRecStorageGroupList() override
bool AddDontRecordSchedule(int ChanId, const QDateTime &StartTime, bool NeverRecord) override
DTC::ProgramList * GetUpcomingList(int StartIndex, int Count, bool ShowAll, int RecordId, int RecStatus) override
AutoDeleteDeque< ProgramInfo * > ProgramList
QString RecTypeToDescription(const QString &RecType) override
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Holds information on recordings and videos.
bool LoadTemplate(const QString &title, const QString &category="Default", const QString &categoryType="Default")
bool DisableRecordSchedule(uint RecordId) override
int m_recordID
Unique Recording Rule ID.
bool QueryKeyFramePosition(uint64_t *position, uint64_t keyframe, bool backwards) const
static int GetJobTypeFromName(const QString &name)
uint AddRecordSchedule(const QString &Title, const QString &Subtitle, const QString &Description, const QString &Category, const QDateTime &recstarttsRaw, const QDateTime &recendtsRaw, const QString &SeriesId, const QString &ProgramId, int ChanId, const QString &Station, int FindDay, QTime FindTime, int ParentId, bool Inactive, uint Season, uint Episode, const QString &Inetref, QString Type, QString SearchType, int RecPriority, uint PreferredInput, int StartOffset, int EndOffset, const QDateTime &lastrectsRaw, QString DupMethod, QString DupIn, bool NewEpisOnly, uint Filter, QString RecProfile, QString RecGroup, QString StorageGroup, QString PlayGroup, bool AutoExpire, int MaxEpisodes, bool MaxNewest, bool AutoCommflag, bool AutoTranscode, bool AutoMetaLookup, bool AutoUserJob1, bool AutoUserJob2, bool AutoUserJob3, bool AutoUserJob4, int Transcoder) override
bool InsertRecording(const QString &ext, bool force_match=false)
RecordingDupMethodType m_dupMethod
void FillCommBreak(DTC::CutList *pCutList, RecordingInfo *rInfo, int marktype)
bool IsCommercialFlagged(void) const
static int GetJobID(int jobType, uint chanid, const QDateTime &recstartts)
bool ReactivateRecording(int RecordedId, int ChanId, const QDateTime &recstarttsRaw) override
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool RemoveRecordSchedule(uint RecordId) override
static QMap< QString, uint32_t > QueryInUseMap(void)
void SaveWatched(bool watchedFlag)
Set "watched" field in recorded/videometadata to "watchedFlag".
std::deque< RecordingInfo * > RecList
bool IsAutoExpirable(void) const
QStringList GetTitleList(const QString &RecGroup) override
static const std::array< const mark, 16 > marks
void SendUpdateEvent(void) const
Sends event out that the ProgramInfo should be reloaded.
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
void SavePreserve(bool preserveEpisode)
Set "preserve" field in "recorded" table to "preserveEpisode".
QStringList GetRecGroupList() override
bool SetSavedBookmark(int RecordedId, int ChanId, const QDateTime &recstarttsRaw, const QString &OffsetType, long Offset) override
QString DupInToDescription(const QString &DupIn) override
int CreateRecordingGroup(const QString &groupName)
bool LoadFromOldRecorded(ProgramList &destination, const QString &sql, const MSqlBindings &bindings)
bool Delete(bool sendSig=true)
QString DupInToString(const QString &DupIn) override
QString GetHostName(void)
bool GetAllPending(RecList &retList, int recRuleId=0) const
int ManageJobQueue(const QString &Action, const QString &JobName, int JobId, int RecordedId, QDateTime jobstarttsRaw, QString RemoteHost, QString JobArgs) override
void SaveMarkup(const QVector< MarkupEntry > &mapMark, const QVector< MarkupEntry > &mapSeek) const
bool GetBoolSettingOnHost(const QString &key, const QString &host, bool defaultval=false)
DTC::ProgramList * GetConflictList(int StartIndex, int Count, int RecordId) override
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
DTC::CutList * GetRecordedCommBreak(int RecordedId, int ChanId, const QDateTime &recstarttsRaw, const QString &OffsetType) override
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
static QList< InputInfo > GetAllInputInfo(bool virtTuners)
bool QueryDurationKeyFrame(uint64_t *keyframe, uint64_t duration, bool backwards) const
bool EnableRecordSchedule(uint RecordId) override
DTC::ProgramList * GetRecordedList(bool Descending, int StartIndex, int Count, const QString &TitleRegEx, const QString &RecGroup, const QString &StorageGroup, const QString &Category, const QString &Sort, bool IgnoreLiveTV, bool IgnoreDeleted) override
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
void dispatch(const MythEvent &event)
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
long GetSavedBookmark(int RecordedId, int ChanId, const QDateTime &recstarttsRaw, const QString &OffsetType) override
bool m_autoMetadataLookup
bool HasPathname(void) const
static uint VideoPropertiesFromNames(const QString &names)
DBCredits * jsonCastToCredits(const QJsonObject &cast)
QString GetSetting(const QString &key, const QString &defaultval="")
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
void FillInputInfo(DTC::Input *input, const InputInfo &inputInfo)