Go to the documentation of this file.
35 #include "libmythbase/mythversion.h"
66 const QString &sTitleRegEx,
67 const QString &sRecGroup,
68 const QString &sStorageGroup,
69 const QString &sCategory,
75 QMap< QString, ProgramInfo* > recMap;
89 if (bIgnoreLiveTV && (sRecGroup ==
"LiveTV"))
91 bIgnoreLiveTV =
false;
92 LOG(VB_GENERAL, LOG_ERR, QString(
"Setting Ignore%1=false because RecGroup=%1")
96 if (bIgnoreDeleted && (sRecGroup ==
"Deleted"))
98 bIgnoreDeleted =
false;
99 LOG(VB_GENERAL, LOG_ERR, QString(
"Setting Ignore%1=false because RecGroup=%1")
104 sSort, bIgnoreLiveTV, bIgnoreDeleted );
106 QMap< QString, ProgramInfo* >::iterator mit = recMap.begin();
108 for (; mit != recMap.end(); mit = recMap.erase(mit))
118 int nMax = (nCount > 0) ? nCount : progList.
size();
123 QRegularExpression rTitleRegEx
124 { sTitleRegEx, QRegularExpression::CaseInsensitiveOption };
126 for (
auto *pInfo : progList)
128 if (pInfo->IsDeletePending() ||
129 (!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
130 (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
131 (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()) ||
132 (!sCategory.isEmpty() && sCategory != pInfo->GetCategory()))
135 if ((nAvailable < nStartIndex) ||
152 pPrograms->setStartIndex ( nStartIndex );
153 pPrograms->setCount ( nCount );
154 pPrograms->setTotalAvailable( nAvailable );
156 pPrograms->setVersion ( MYTH_BINARY_VERSION );
157 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
169 const QDateTime &sStartTime,
170 const QDateTime &sEndTime,
171 const QString &sTitle,
172 const QString &sSeriesId,
174 const QString &sSort)
176 if (!sStartTime.isNull() && !sStartTime.isValid())
177 throw QString(
"StartTime is invalid");
179 if (!sEndTime.isNull() && !sEndTime.isValid())
180 throw QString(
"EndTime is invalid");
182 const QDateTime& dtStartTime = sStartTime;
183 const QDateTime& dtEndTime = sEndTime;
185 if (!sEndTime.isNull() && dtEndTime < dtStartTime)
186 throw QString(
"EndTime is before StartTime");
196 if (!dtStartTime.isNull())
198 sSQL +=
" AND endtime >= :StartDate ";
199 bindings[
":StartDate"] = dtStartTime;
202 if (!dtEndTime.isNull())
204 sSQL +=
" AND starttime <= :EndDate ";
205 bindings[
":EndDate"] = dtEndTime;
212 clause <<
"recordid = :RecordId";
213 bindings[
":RecordId"] = nRecordId;
216 if (!sTitle.isEmpty())
218 clause <<
"title = :Title";
219 bindings[
":Title"] = sTitle;
222 if (!sSeriesId.isEmpty())
224 clause <<
"seriesid = :SeriesId";
225 bindings[
":SeriesId"] = sSeriesId;
228 if (!clause.isEmpty())
230 sSQL += QString(
" AND (%1) ").arg(clause.join(
" OR "));
233 if (sSort ==
"starttime")
234 sSQL +=
"ORDER BY starttime ";
235 else if (sSort ==
"title")
236 sSQL +=
"ORDER BY title ";
238 sSQL +=
"ORDER BY starttime ";
245 uint nTotalAvailable = (nStartIndex == 0) ? 1 : 0;
247 (
uint)nStartIndex, (
uint)nCount, nTotalAvailable );
255 nCount = (int)progList.
size();
256 int nEndIndex = (int)progList.
size();
258 for(
int n = 0; n < nEndIndex; n++)
269 pPrograms->setStartIndex ( nStartIndex );
270 pPrograms->setCount ( nCount );
271 pPrograms->setTotalAvailable( nTotalAvailable );
273 pPrograms->setVersion ( MYTH_BINARY_VERSION );
274 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
284 int chanid,
const QDateTime &recstarttsRaw)
286 if ((RecordedId <= 0) &&
287 (chanid <= 0 || !recstarttsRaw.isValid()))
288 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
312 throw QString(
"AddRecordedCredits: recordedid %1 does "
313 "not exist.").arg(RecordedId);
316 if (credits ==
nullptr)
317 throw QString(
"AddRecordedCredits: Failed to parse cast from json.");
320 for (
auto & person : *credits)
322 if (!person.InsertDB(query, ri.
GetChanID(),
324 throw QString(
"AddRecordedCredits: Failed to add credit "
325 "%1 to DB").arg(person.toString());
338 QJsonObject root = jsonObj;
339 QJsonObject program = root[
"Program"].toObject();
340 QJsonObject channel = program[
"Channel"].toObject();
341 QJsonObject recording = program[
"Recording"].toObject();
342 QJsonObject cast = program[
"Cast"].toObject();
345 int chanid = channel.value(
"ChanId").toString(
"0").toUInt();
346 QString
hostname = program[
"HostName"].toString(
"");
349 throw QString(
"AddRecordedProgram: chanid %1 does "
350 "not exist.").arg(chanid);
352 pi->m_title = program.value(
"Title").toString(
"");
353 pi->m_subtitle = program.value(
"SubTitle").toString(
"");
354 pi->m_description = program.value(
"Description").toString(
"");
355 pi->m_category = program.value(
"Category").toString(
"");
362 pi->m_airdate = pi->m_originalairdate.year();
363 pi->m_partnumber = program.value(
"PartNumber").toString(
"0").toUInt();
364 pi->m_parttotal = program.value(
"PartTotal").toString(
"0").toUInt();
365 pi->m_syndicatedepisodenumber =
"";
367 (program.value(
"SubPropNames").toString(
""));
369 (program.value(
"AudioPropNames").toString(
""));
371 (program.value(
"VideoPropNames").toString(
""));
372 pi->m_stars = program.value(
"Stars").toString(
"0.0").toFloat();
374 pi->m_seriesId = program.value(
"SeriesId").toString(
"");
375 pi->m_programId = program.value(
"ProgramId").toString(
"");
376 pi->m_inetref = program.value(
"Inetref").toString(
"");
377 pi->m_previouslyshown =
false;
378 pi->m_listingsource = 0;
381 pi->m_season = program.value(
"Season").toString(
"0").toUInt();
382 pi->m_episode = program.value(
"Episode").toString(
"0").toUInt();
383 pi->m_totalepisodes = program.value(
"TotalEpisodes").toString(
"0").toUInt();
385 pi->m_channel = channel.value(
"ChannelName").toString(
"");
387 pi->m_startts = recording.value(
"StartTs").toString(
"");
388 pi->m_endts = recording.value(
"EndTs").toString(
"");
392 pi->m_title_pronounce =
"";
395 pi->m_colorcode =
"";
403 if (!pi->InsertDB(query, chanid,
true))
405 throw QString(
"AddRecordedProgram: "
406 "Failed to add recordedprogram entry.");
411 pi->m_subtitle, pi->m_subtitle,
413 pi->m_season, pi->m_episode,
415 pi->m_syndicatedepisodenumber,
418 channel.value(
"ChanNum").toString(
"0"),
419 channel.value(
"CallSign").toString(
""),
421 recording.value(
"RecGroup").toString(
""),
422 recording.value(
"PlayGroup").toString(
""),
424 recording.value(
"StorageGroup").toString(
""),
432 recording.value(
"Priority").toString(
"0").toInt(),
438 pi->m_originalairdate,
439 program.value(
"Repeat").toString(
"false").toLower() ==
"true",
440 static_cast<RecStatus::Type>(recording.value(
"Status").toString(
"-3").toInt()),
442 recording.value(
"RecordedId").toString(
"0").toInt(),
444 static_cast<RecordingType>(recording.value(
"RecType").toString(
"0").toInt()),
447 channel.value(
"SourceId").toString(
"0").toUInt(),
448 channel.value(
"InputId").toString(
"0").toUInt(),
450 channel.value(
"CommFree").toString(
"false").toLower() ==
"true",
458 recording.value(
"EncoderName").toString(
""));
462 QString
filename = program.value(
"FileName").toString(
"");
464 int idx =
filename.lastIndexOf(
'.');
469 throw QString(
"Failed to create RecordingInfo database entry. "
470 "Non unique starttime?");
493 int chanid,
const QDateTime &recstarttsRaw,
494 bool forceDelete,
bool allowRerecord)
502 int chanid,
const QDateTime &recstarttsRaw,
503 bool forceDelete,
bool allowRerecord)
505 if ((RecordedId <= 0) &&
506 (chanid <= 0 || !recstarttsRaw.isValid()))
507 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
518 QString cmd = QString(
"DELETE_RECORDING %1 %2 %3 %4")
521 forceDelete ?
"FORCE" :
"NO_FORCE",
522 allowRerecord ?
"FORGET" :
"NO_FORGET");
537 int chanid,
const QDateTime &recstarttsRaw)
539 if ((RecordedId <= 0) &&
540 (chanid <= 0 || !recstarttsRaw.isValid()))
541 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
551 QString cmd = QString(
"UNDELETE_RECORDING %1 %2")
570 throw QString(
"RecordedId param is invalid.");
576 QString cmd = QString(
"STOP_RECORDING %1 %2")
584 throw QString(
"RecordedId %1 not found").arg(RecordedId);
594 int chanid,
const QDateTime &recstarttsRaw)
596 if ((RecordedId <= 0) &&
597 (chanid <= 0 || !recstarttsRaw.isValid()))
598 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
622 "RescheduleRecordings");
633 throw QString(
"RecordedId param is invalid.");
638 throw QString(
"RecordedId %1 not found").arg(RecordedId);
651 const QDateTime &recstarttsRaw,
654 if ((RecordedId <= 0) &&
655 (chanid <= 0 || !recstarttsRaw.isValid()))
656 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
680 const QDateTime &recstarttsRaw,
681 const QString &offsettype )
683 if ((RecordedId <= 0) &&
684 (chanid <= 0 || !recstarttsRaw.isValid()))
685 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
698 if (offsettype.toLower() ==
"position"){
704 if (offsettype.toLower() ==
"duration"){
719 const QDateTime &recstarttsRaw,
720 const QString &offsettype,
723 if ((RecordedId <= 0) &&
724 (chanid <= 0 || !recstarttsRaw.isValid()))
725 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
728 throw QString(
"Offset must be >= 0.");
735 uint64_t position = 0;
737 if (offsettype.toLower() ==
"position"){
741 else if (offsettype.toLower() ==
"duration"){
757 const QDateTime &recstarttsRaw,
758 const QString &offsettype )
761 if ((RecordedId <= 0) &&
762 (chanid <= 0 || !recstarttsRaw.isValid()))
763 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
772 if (offsettype.toLower() ==
"position")
774 else if (offsettype.toLower() ==
"duration")
790 const QDateTime &recstarttsRaw,
791 const QString &offsettype )
794 if ((RecordedId <= 0) &&
795 (chanid <= 0 || !recstarttsRaw.isValid()))
796 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
805 if (offsettype.toLower() ==
"position")
807 else if (offsettype.toLower() ==
"duration")
822 const QString &offsettype )
826 throw QString(
"Recorded ID appears invalid.");
832 if (offsettype.toLower() ==
"bytes")
834 else if (offsettype.toLower() ==
"duration")
839 throw QString(
"Type must be 'BYTES' or 'DURATION'.");
857 throw QString(
"Invalid RecordedId %1").arg(RecordedId);
859 QVector<ProgramInfo::MarkupEntry> mapMark;
860 QVector<ProgramInfo::MarkupEntry> mapSeek;
865 for (
const auto& entry : qAsConst(mapMark))
867 DTC::Markup *pMarkup = pMarkupList->AddNewMarkup();
869 pMarkup->setType(typestr);
870 pMarkup->setFrame(entry.frame);
871 if (entry.isDataNull)
872 pMarkup->setData(
"NULL");
874 pMarkup->setData(QString::number(entry.data));
876 for (
const auto& entry : qAsConst(mapSeek))
880 pSeek->setType(typestr);
881 pSeek->setFrame(entry.frame);
882 if (entry.isDataNull)
883 pSeek->setData(
"NULL");
885 pSeek->setData(QString::number(entry.data));
902 throw QString(
"Invalid RecordedId %1").arg(RecordedId);
904 QVector<ProgramInfo::MarkupEntry> mapMark;
905 QVector<ProgramInfo::MarkupEntry> mapSeek;
907 QJsonObject markuplist = jsonObj[
"MarkupList"].toObject();
909 QJsonArray
marks = markuplist[
"Mark"].toArray();
910 for (
const auto & m :
marks)
912 QJsonObject markup = m.toObject();
915 QString typestr = markup.value(
"Type").toString(
"");
917 entry.
frame = markup.value(
"Frame").toString(
"-1").toLongLong();
918 QString data = markup.value(
"Data").toString(
"NULL");
921 entry.
data = data.toLongLong();
923 mapMark.append(entry);
926 QJsonArray seeks = markuplist[
"Seek"].toArray();
927 for (
const auto & m : seeks)
929 QJsonObject markup = m.toObject();
932 QString typestr = markup.value(
"Type").toString(
"");
934 entry.
frame = markup.value(
"Frame").toString(
"-1").toLongLong();
935 QString data = markup.value(
"Data").toString(
"NULL");
938 entry.
data = data.toLongLong();
940 mapSeek.append(entry);
966 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)infoList.size() ) : 0;
967 nCount = (nCount > 0) ? std::min( nCount, (
int)infoList.size() ) : infoList.size();
968 int nEndIndex = std::min((nStartIndex + nCount), (
int)infoList.size() );
970 for(
int n = nStartIndex; n < nEndIndex; n++)
974 if (pInfo !=
nullptr)
986 pPrograms->setStartIndex ( nStartIndex );
987 pPrograms->setCount ( nCount );
988 pPrograms->setTotalAvailable( infoList.size() );
990 pPrograms->setVersion ( MYTH_BINARY_VERSION );
991 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1006 for (
auto * elink : qAsConst(
gTVList))
1008 if (elink !=
nullptr)
1012 pEncoder->setId ( elink->GetInputID() );
1013 pEncoder->setState ( elink->GetState() );
1014 pEncoder->setLocal ( elink->IsLocal() );
1015 pEncoder->setConnected ( elink->IsConnected() );
1016 pEncoder->setSleepStatus ( elink->GetSleepStatus() );
1019 if (pEncoder->
Local())
1022 pEncoder->setHostName( elink->GetHostName() );
1024 for (
const auto & inputInfo : qAsConst(inputInfoList))
1026 if (inputInfo.m_inputId ==
static_cast<uint>(elink->GetInputID()))
1033 switch ( pEncoder->
State() )
1070 for (
const auto & inputInfo : qAsConst(inputInfoList))
1086 query.
prepare(
"SELECT recgroup FROM recgroups WHERE recgroup <> 'Deleted' "
1087 "ORDER BY recgroup");
1096 while (query.
next())
1097 result << query.
value(0).toString();
1111 query.
prepare(
"SELECT DISTINCT category FROM recorded ORDER BY category");
1113 query.
prepare(
"SELECT DISTINCT category FROM program ORDER BY category");
1122 while (query.
next())
1123 result << query.
value(0).toString();
1156 query.
prepare(
"SELECT filterid, description, newruledefault "
1157 "FROM recordfilter ORDER BY filterid");
1161 while (query.
next())
1164 ruleFilter->setId(query.
value(0).toInt());
1165 ruleFilter->setDescription(QObject::tr(query.
value(1).toString()
1166 .toUtf8().constData()));
1181 QString querystr =
"SELECT DISTINCT title FROM recorded "
1182 "WHERE deletepending = 0";
1184 if (!RecGroup.isEmpty())
1185 querystr +=
" AND recgroup = :RECGROUP";
1187 querystr +=
" AND recgroup != 'Deleted'";
1189 querystr +=
" ORDER BY title";
1193 if (!RecGroup.isEmpty())
1203 while (query.
next())
1204 result << query.
value(0).toString();
1217 QString querystr = QString(
1218 "SELECT title, inetref, count(title) as count "
1219 " FROM recorded AS r "
1220 " JOIN recgroups AS g ON r.recgroupid = g.recgroupid "
1221 " WHERE g.recgroup NOT IN ('Deleted', 'LiveTV') "
1222 " AND r.deletepending = 0 "
1223 " GROUP BY title, inetref "
1235 while (query.
next())
1239 pTitleInfo->setTitle(query.
value(0).toString());
1240 pTitleInfo->setInetref(query.
value(1).toString());
1241 pTitleInfo->setCount(query.
value(2).toInt());
1271 for (
auto it = tmpList.begin(); it < tmpList.end(); ++it)
1273 if ((nRecStatus != 0) &&
1274 ((*it)->GetRecordingStatus() != nRecStatus))
1289 else if (bShowAll &&
1305 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recordingList.
size() ) : 0;
1306 nCount = (nCount > 0) ? std::min( nCount, (
int)recordingList.
size() ) : recordingList.
size();
1307 int nEndIndex = std::min((nStartIndex + nCount), (
int)recordingList.
size() );
1309 for(
int n = nStartIndex; n < nEndIndex; n++)
1320 pPrograms->setStartIndex ( nStartIndex );
1321 pPrograms->setCount ( nCount );
1322 pPrograms->setTotalAvailable( recordingList.
size() );
1324 pPrograms->setVersion ( MYTH_BINARY_VERSION );
1325 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1352 for (
auto it = tmpList.begin(); it < tmpList.end(); ++it)
1369 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recordingList.
size() ) : 0;
1370 nCount = (nCount > 0) ? std::min( nCount, (
int)recordingList.
size() ) : recordingList.
size();
1371 int nEndIndex = std::min((nStartIndex + nCount), (
int)recordingList.
size() );
1373 for(
int n = nStartIndex; n < nEndIndex; n++)
1384 pPrograms->setStartIndex ( nStartIndex );
1385 pPrograms->setCount ( nCount );
1386 pPrograms->setTotalAvailable( recordingList.
size() );
1388 pPrograms->setVersion ( MYTH_BINARY_VERSION );
1389 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1395 const QString& sTitle,
1396 const QString& sSubtitle,
1397 const QString& sDescription,
1398 const QString& sCategory,
1399 const QDateTime& recstarttsRaw,
1400 const QDateTime& recendtsRaw,
1401 const QString& sSeriesId,
1402 const QString& sProgramId,
1404 const QString& sStation,
1411 const QString& sInetref,
1413 QString sSearchType,
1415 uint nPreferredInput,
1418 const QDateTime& lastrectsRaw,
1423 QString sRecProfile,
1425 QString sStorageGroup,
1431 bool bAutoTranscode,
1432 bool bAutoMetaLookup,
1439 QDateTime recstartts = recstarttsRaw.toUTC();
1440 QDateTime recendts = recendtsRaw.toUTC();
1441 QDateTime lastrects = lastrectsRaw.toUTC();
1445 if (sType.isEmpty())
1448 if (sSearchType.isEmpty())
1449 sSearchType =
"none";
1451 if (sDupMethod.isEmpty())
1452 sDupMethod =
"subtitleanddescription";
1454 if (sDupIn.isEmpty())
1474 if (sRecProfile.isEmpty())
1475 sRecProfile =
"Default";
1477 if (sRecGroup.isEmpty())
1478 sRecGroup =
"Default";
1480 if (sStorageGroup.isEmpty())
1481 sStorageGroup =
"Default";
1483 if (sPlayGroup.isEmpty())
1484 sPlayGroup =
"Default";
1549 const QString& sTitle,
1550 const QString& sSubtitle,
1551 const QString& sDescription,
1552 const QString& sCategory,
1553 const QDateTime& dStartTimeRaw,
1554 const QDateTime& dEndTimeRaw,
1555 const QString& sSeriesId,
1556 const QString& sProgramId,
1558 const QString& sStation,
1564 const QString& sInetref,
1566 QString sSearchType,
1568 uint nPreferredInput,
1575 QString sRecProfile,
1577 QString sStorageGroup,
1583 bool bAutoTranscode,
1584 bool bAutoMetaLookup,
1591 if (nRecordId == 0 )
1592 throw QString(
"Record ID is invalid.");
1599 throw QString(
"Record ID does not exist.");
1601 QDateTime recstartts = dStartTimeRaw.toUTC();
1602 QDateTime recendts = dEndTimeRaw.toUTC();
1605 if (sType.isEmpty())
1608 if (sSearchType.isEmpty())
1609 sSearchType =
"none";
1611 if (sDupMethod.isEmpty())
1612 sDupMethod =
"subtitleanddescription";
1614 if (sDupIn.isEmpty())
1625 if (sRecProfile.isEmpty())
1626 sRecProfile =
"Default";
1628 if (sRecGroup.isEmpty())
1629 sRecGroup =
"Default";
1631 if (sStorageGroup.isEmpty())
1632 sStorageGroup =
"Default";
1634 if (sPlayGroup.isEmpty())
1635 sPlayGroup =
"Default";
1637 if (!sTitle.isEmpty())
1640 if (!sSubtitle.isEmpty())
1643 if(!sDescription.isEmpty())
1646 if (!sCategory.isEmpty())
1649 if (!sSeriesId.isEmpty())
1652 if (!sProgramId.isEmpty())
1657 if (!sStation.isEmpty())
1710 bool bResult = pRule.
Save();
1717 bool bResult =
false;
1719 if (nRecordId == 0 )
1720 throw QString(
"Record ID does not exist.");
1725 bResult = pRule.
Delete();
1733 bool bResult =
true;
1735 if (nChanId <= 0 || !dStartTime.isValid())
1736 throw QString(
"Program does not exist.");
1741 throw QString(
"Program does not exist.");
1760 const QString &Sort,
1764 if (Sort.toLower() ==
"lastrecorded")
1766 else if (Sort.toLower() ==
"nextrecording")
1768 else if (Sort.toLower() ==
"title")
1770 else if (Sort.toLower() ==
"priority")
1772 else if (Sort.toLower() ==
"type")
1786 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recList.size() ) : 0;
1787 nCount = (nCount > 0) ? std::min( nCount, (
int)recList.size() ) : recList.size();
1788 int nEndIndex = std::min((nStartIndex + nCount), (
int)recList.size() );
1790 for(
int n = nStartIndex; n < nEndIndex; n++)
1794 if (info !=
nullptr)
1804 pRecRules->setStartIndex ( nStartIndex );
1805 pRecRules->setCount ( nCount );
1806 pRecRules->setTotalAvailable( recList.size() );
1808 pRecRules->setVersion ( MYTH_BINARY_VERSION );
1809 pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
1811 while (!recList.empty())
1813 delete recList.back();
1821 const QString& sTemplate,
1824 const QDateTime& dStartTimeRaw,
1825 bool bMakeOverride )
1828 QDateTime dStartTime = dStartTimeRaw.toUTC();
1834 throw QString(
"Record ID does not exist.");
1836 else if (!sTemplate.isEmpty())
1839 throw QString(
"Template does not exist.");
1841 else if (nRecordedId > 0)
1846 throw QString(
"Recording does not exist");
1848 else if (nChanId > 0 && dStartTime.isValid())
1853 RecordingInfo info(nChanId, dStartTime,
false, 0h, &status);
1855 throw QString(
"Program does not exist.");
1864 throw QString(
"Invalid request.");
1875 bool bResult =
false;
1877 if (nRecordId == 0 )
1878 throw QString(
"Record ID appears invalid.");
1887 bResult = pRule.
Save();
1895 bool bResult =
false;
1897 if (nRecordId == 0 )
1898 throw QString(
"Record ID appears invalid.");
1907 bResult = pRule.
Save();
1926 uint recordedid = 0;
1941 const QDateTime &StartTime)
1953 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
1963 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
2001 const QString &sJobName,
2004 QDateTime jobstarttsRaw,
2005 QString sRemoteHost,
2013 LOG(VB_GENERAL, LOG_ERR,
"JobName and RecordedId are required.");
2017 if (sRemoteHost.isEmpty())
2030 if ( sAction ==
"Remove")
2034 LOG(VB_GENERAL, LOG_ERR,
"For Remove, a valid JobId is required.");
2045 if ( sAction !=
"Add")
2047 LOG(VB_GENERAL, LOG_ERR, QString(
"Illegal Action name '%1'. Use: Add, "
2048 "or Remove").arg(sAction));
2055 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been defined.")
2061 sRemoteHost,
false))
2063 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been allowed on host %2.")
2064 .arg(sJobName, sRemoteHost));
2068 if (!jobstarttsRaw.isValid())
2069 jobstarttsRaw = QDateTime::currentDateTime();
2074 if (sJobArgs.isNull())
2081 QString(
"Dvr/ManageJobQueue"),
2085 jobstarttsRaw.toUTC());
2089 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 job wasn't queued because of a "
2090 "database error or because it was "
2091 "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
static QList< InputInfo > GetAllInputInfo()
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.
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)