Go to the documentation of this file.
30 #include "libmythbase/mythversion.h"
55 qRegisterMetaType<V2ProgramList*>(
"V2ProgramList");
56 qRegisterMetaType<V2Program*>(
"V2Program");
57 qRegisterMetaType<V2CutList*>(
"V2CutList");
58 qRegisterMetaType<V2Cutting*>(
"V2Cutting");
59 qRegisterMetaType<V2MarkupList*>(
"V2MarkupList");
60 qRegisterMetaType<V2Markup*>(
"V2Markup");
61 qRegisterMetaType<V2EncoderList*>(
"V2EncoderList");
62 qRegisterMetaType<V2Encoder*>(
"V2Encoder");
63 qRegisterMetaType<V2InputList*>(
"V2InputList");
64 qRegisterMetaType<V2Input*>(
"V2Input");
65 qRegisterMetaType<V2RecRuleFilterList*>(
"V2RecRuleFilterList");
66 qRegisterMetaType<V2RecRuleFilter*>(
"V2RecRuleFilter");
67 qRegisterMetaType<V2TitleInfoList*>(
"V2TitleInfoList");
68 qRegisterMetaType<V2TitleInfo*>(
"V2TitleInfo");
69 qRegisterMetaType<V2RecRule*>(
"V2RecRule");
70 qRegisterMetaType<V2RecRuleList*>(
"V2RecRuleList");
71 qRegisterMetaType<V2ChannelInfo*>(
"V2ChannelInfo");
72 qRegisterMetaType<V2RecordingInfo*>(
"V2RecordingInfo");
73 qRegisterMetaType<V2ArtworkInfoList*>(
"V2ArtworkInfoList");
74 qRegisterMetaType<V2ArtworkInfo*>(
"V2ArtworkInfo");
75 qRegisterMetaType<V2CastMemberList*>(
"V2CastMemberList");
76 qRegisterMetaType<V2CastMember*>(
"V2CastMember");
98 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)infoList.size() ) : 0;
99 nCount = (nCount > 0) ? std::min( nCount, (
int)infoList.size() ) : infoList.size();
100 int nEndIndex = std::min((nStartIndex + nCount), (
int)infoList.size() );
102 for(
int n = nStartIndex; n < nEndIndex; n++)
106 if (pInfo !=
nullptr)
108 V2Program *pProgram = pPrograms->AddNewProgram();
118 pPrograms->setStartIndex ( nStartIndex );
119 pPrograms->setCount ( nCount );
120 pPrograms->setTotalAvailable( infoList.size() );
122 pPrograms->setVersion ( MYTH_BINARY_VERSION );
123 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
131 const QString &sTitleRegEx,
132 const QString &sRecGroup,
133 const QString &sStorageGroup,
134 const QString &sCategory,
135 const QString &sSort,
158 bIncRecording =
true;
160 QMap< QString, ProgramInfo* > recMap;
174 if (bIgnoreLiveTV && (sRecGroup ==
"LiveTV"))
176 bIgnoreLiveTV =
false;
177 LOG(VB_GENERAL, LOG_ERR, QString(
"Setting Ignore%1=false because RecGroup=%1")
181 if (bIgnoreDeleted && (sRecGroup ==
"Deleted"))
183 bIgnoreDeleted =
false;
184 LOG(VB_GENERAL, LOG_ERR, QString(
"Setting Ignore%1=false because RecGroup=%1")
189 sSort, bIgnoreLiveTV, bIgnoreDeleted );
191 QMap< QString, ProgramInfo* >::iterator mit = recMap.begin();
193 for (; mit != recMap.end(); mit = recMap.erase(mit))
204 int nMax = (nCount > 0) ? nCount : progList.
size();
209 QRegularExpression rTitleRegEx
210 { sTitleRegEx, QRegularExpression::CaseInsensitiveOption };
212 for (
auto *pInfo : progList)
214 if (pInfo->IsDeletePending() ||
215 (!sTitleRegEx.isEmpty() && !pInfo->GetTitle().contains(rTitleRegEx)) ||
216 (!sRecGroup.isEmpty() && sRecGroup != pInfo->GetRecordingGroup()) ||
217 (!sStorageGroup.isEmpty() && sStorageGroup != pInfo->GetStorageGroup()) ||
218 (!sCategory.isEmpty() && sCategory != pInfo->GetCategory()))
221 if ((nAvailable < nStartIndex) ||
231 V2Program *pProgram = pPrograms->AddNewProgram();
232 V2FillProgramInfo( pProgram, pInfo, bIncChannel, bDetails, bIncCast, bIncArtWork, bIncRecording );
237 pPrograms->setStartIndex ( nStartIndex );
238 pPrograms->setCount ( nCount );
239 pPrograms->setTotalAvailable( nAvailable );
241 pPrograms->setVersion ( MYTH_BINARY_VERSION );
242 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
254 const QDateTime &sStartTime,
255 const QDateTime &sEndTime,
256 const QString &sTitle,
257 const QString &sSeriesId,
259 const QString &sSort)
261 if (!sStartTime.isNull() && !sStartTime.isValid())
262 throw QString(
"StartTime is invalid");
264 if (!sEndTime.isNull() && !sEndTime.isValid())
265 throw QString(
"EndTime is invalid");
267 const QDateTime& dtStartTime = sStartTime;
268 const QDateTime& dtEndTime = sEndTime;
270 if (!sEndTime.isNull() && dtEndTime < dtStartTime)
271 throw QString(
"EndTime is before StartTime");
281 if (!dtStartTime.isNull())
283 sSQL +=
" AND endtime >= :StartDate ";
284 bindings[
":StartDate"] = dtStartTime;
287 if (!dtEndTime.isNull())
289 sSQL +=
" AND starttime <= :EndDate ";
290 bindings[
":EndDate"] = dtEndTime;
297 clause <<
"recordid = :RecordId";
298 bindings[
":RecordId"] = nRecordId;
301 if (!sTitle.isEmpty())
303 clause <<
"title = :Title";
304 bindings[
":Title"] = sTitle;
307 if (!sSeriesId.isEmpty())
309 clause <<
"seriesid = :SeriesId";
310 bindings[
":SeriesId"] = sSeriesId;
313 if (!clause.isEmpty())
315 sSQL += QString(
" AND (%1) ").arg(clause.join(
" OR "));
318 if (sSort ==
"starttime")
319 sSQL +=
"ORDER BY starttime ";
320 else if (sSort ==
"title")
321 sSQL +=
"ORDER BY title ";
323 sSQL +=
"ORDER BY starttime ";
330 uint nTotalAvailable = (nStartIndex == 0) ? 1 : 0;
332 (
uint)nStartIndex, (
uint)nCount, nTotalAvailable );
340 nCount = (int)progList.
size();
341 int nEndIndex = (int)progList.
size();
343 for(
int n = 0; n < nEndIndex; n++)
347 V2Program *pProgram = pPrograms->AddNewProgram();
354 pPrograms->setStartIndex ( nStartIndex );
355 pPrograms->setCount ( nCount );
356 pPrograms->setTotalAvailable( nTotalAvailable );
358 pPrograms->setVersion ( MYTH_BINARY_VERSION );
359 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
369 int chanid,
const QDateTime &StartTime)
371 if ((RecordedId <= 0) &&
372 (chanid <= 0 || !StartTime.isValid()))
373 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
394 QJsonDocument jsonDoc = QJsonDocument::fromJson(Cast.toUtf8());
398 throw QString(
"AddRecordedCredits: recordedid %1 does "
399 "not exist.").arg(RecordedId);
402 if (credits ==
nullptr)
403 throw QString(
"AddRecordedCredits: Failed to parse cast from json.");
406 for (
auto & person : *credits)
408 if (!person.InsertDB(query, ri.
GetChanID(),
410 throw QString(
"AddRecordedCredits: Failed to add credit "
411 "%1 to DB").arg(person.toString());
423 QJsonDocument doc = QJsonDocument::fromJson(Program.toUtf8());
424 QJsonObject program = doc.object();
425 QJsonObject channel = program[
"Channel"].toObject();
426 QJsonObject recording = program[
"Recording"].toObject();
427 QJsonObject cast = program[
"Cast"].toObject();
430 int chanid = channel.value(
"ChanId").toVariant().toString().toUInt();
432 QString
hostname = program[
"HostName"].toString(
"");
435 throw QString(
"AddRecordedProgram: chanid %1 does "
436 "not exist.").arg(chanid);
438 pi->m_title = program.value(
"Title").toString(
"");
439 pi->m_subtitle = program.value(
"SubTitle").toString(
"");
440 pi->m_description = program.value(
"Description").toString(
"");
441 pi->m_category = program.value(
"Category").toString(
"");
448 pi->m_airdate = pi->m_originalairdate.year();
449 pi->m_partnumber = program.value(
"PartNumber").toString(
"0").toUInt();
450 pi->m_parttotal = program.value(
"PartTotal").toString(
"0").toUInt();
451 pi->m_syndicatedepisodenumber =
"";
453 (program.value(
"SubPropNames").toString(
""));
455 (program.value(
"AudioPropNames").toString(
""));
457 (program.value(
"VideoPropNames").toString(
""));
458 pi->m_stars = program.value(
"Stars").toVariant().toString().toFloat();
460 pi->m_seriesId = program.value(
"SeriesId").toString(
"");
461 pi->m_programId = program.value(
"ProgramId").toString(
"");
462 pi->m_inetref = program.value(
"Inetref").toString(
"");
463 pi->m_previouslyshown =
false;
464 pi->m_listingsource = 0;
467 pi->m_season = program.value(
"Season").toVariant()
468 .toString().toUInt();
469 pi->m_episode = program.value(
"Episode").toVariant()
470 .toString().toUInt();
471 pi->m_totalepisodes = program.value(
"TotalEpisodes").toVariant()
472 .toString().toUInt();
474 pi->m_channel = channel.value(
"ChannelName").toString(
"");
476 pi->m_startts = recording.value(
"StartTs").toString(
"");
477 pi->m_endts = recording.value(
"EndTs").toString(
"");
481 pi->m_title_pronounce =
"";
484 pi->m_colorcode =
"";
492 if (!pi->InsertDB(query, chanid,
true))
494 throw QString(
"AddRecordedProgram: "
495 "Failed to add recordedprogram entry.");
500 pi->m_subtitle, pi->m_subtitle,
502 pi->m_season, pi->m_episode,
504 pi->m_syndicatedepisodenumber,
507 channel.value(
"ChanNum").toString(
"0"),
508 channel.value(
"CallSign").toString(
""),
510 recording.value(
"RecGroup").toString(
""),
511 recording.value(
"PlayGroup").toString(
""),
513 recording.value(
"StorageGroup").toString(
""),
521 recording.value(
"Priority").toString(
"0").toInt(),
527 pi->m_originalairdate,
528 program.value(
"Repeat").toString(
"false").toLower() ==
"true",
531 recording.value(
"RecordedId").toString(
"0").toInt(),
533 static_cast<RecordingType>(recording.value(
"RecType").toInt()),
536 channel.value(
"SourceId").toVariant().toString().toUInt(),
537 channel.value(
"InputId").toVariant().toString().toUInt(),
539 channel.value(
"CommFree").toBool(),
547 recording.value(
"EncoderName").toString(
""));
551 QString
filename = program.value(
"FileName").toString(
"");
553 int idx =
filename.lastIndexOf(
'.');
558 throw QString(
"Failed to create RecordingInfo database entry. "
559 "Non unique starttime?");
582 int chanid,
const QDateTime &StartTime,
583 bool forceDelete,
bool allowRerecord)
591 int chanid,
const QDateTime &StartTime,
592 bool forceDelete,
bool allowRerecord)
594 if ((RecordedId <= 0) &&
595 (chanid <= 0 || !StartTime.isValid()))
596 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
607 QString cmd = QString(
"DELETE_RECORDING %1 %2 %3 %4")
610 forceDelete ?
"FORCE" :
"NO_FORCE",
611 allowRerecord ?
"FORGET" :
"NO_FORGET");
626 int chanid,
const QDateTime &StartTime)
628 if ((RecordedId <= 0) &&
629 (chanid <= 0 || !StartTime.isValid()))
630 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
640 QString cmd = QString(
"UNDELETE_RECORDING %1 %2")
659 throw QString(
"RecordedId param is invalid.");
665 QString cmd = QString(
"STOP_RECORDING %1 %2")
673 throw QString(
"RecordedId %1 not found").arg(RecordedId);
683 int chanid,
const QDateTime &StartTime)
685 if ((RecordedId <= 0) &&
686 (chanid <= 0 || !StartTime.isValid()))
687 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
711 "RescheduleRecordings");
722 throw QString(
"RecordedId param is invalid.");
727 throw QString(
"RecordedId %1 not found").arg(RecordedId);
740 const QDateTime &StartTime,
743 LOG(VB_GENERAL, LOG_WARNING,
"Deprecated, use Dvr/UpdateRecordedMetadata.");
745 if ((RecordedId <= 0) &&
746 (chanid <= 0 || !StartTime.isValid()))
747 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
771 const QDateTime &StartTime,
772 const QString &offsettype )
774 if ((RecordedId <= 0) &&
775 (chanid <= 0 || !StartTime.isValid()))
776 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
789 if (offsettype.toLower() ==
"position"){
795 if (offsettype.toLower() ==
"duration"){
813 const QDateTime &StartTime,
814 const QString &offsettype )
816 if (RecordedId == -1)
819 if ((RecordedId <= 0) &&
820 (chanid <= 0 || !StartTime.isValid()))
821 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
834 if (offsettype.toLower() ==
"position"){
840 if (offsettype.toLower() ==
"duration"){
855 const QDateTime &StartTime,
856 const QString &offsettype,
859 LOG(VB_GENERAL, LOG_WARNING,
"Deprecated, use Dvr/UpdateRecordedMetadata.");
861 if ((RecordedId <= 0) &&
862 (chanid <= 0 || !StartTime.isValid()))
863 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
866 throw QString(
"Offset must be >= 0.");
873 uint64_t position = 0;
875 if (offsettype.toLower() ==
"position"){
879 else if (offsettype.toLower() ==
"duration"){
896 const QDateTime &StartTime,
897 const QString &offsettype,
900 if ((RecordedId <= 0) &&
901 (chanid <= 0 || !StartTime.isValid()))
902 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
905 throw QString(
"Offset must be >= 0.");
912 uint64_t position = 0;
914 if (offsettype.toLower() ==
"position"){
918 else if (offsettype.toLower() ==
"duration"){
930 const QDateTime &StartTime,
931 const QString &offsettype )
934 if ((RecordedId <= 0) &&
935 (chanid <= 0 || !StartTime.isValid()))
936 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
945 if (offsettype.toLower() ==
"position")
947 else if (offsettype.toLower() ==
"duration")
963 const QDateTime &StartTime,
964 const QString &offsettype )
967 if ((RecordedId <= 0) &&
968 (chanid <= 0 || !StartTime.isValid()))
969 throw QString(
"Recorded ID or Channel ID and StartTime appears invalid.");
978 if (offsettype.toLower() ==
"position")
980 else if (offsettype.toLower() ==
"duration")
995 const QString &offsettype )
999 throw QString(
"Recorded ID appears invalid.");
1005 if (offsettype.toLower() ==
"bytes")
1007 else if (offsettype.toLower() ==
"duration")
1012 throw QString(
"Type must be 'BYTES' or 'DURATION'.");
1030 throw QString(
"Invalid RecordedId %1").arg(RecordedId);
1032 QVector<ProgramInfo::MarkupEntry> mapMark;
1033 QVector<ProgramInfo::MarkupEntry> mapSeek;
1038 for (
const auto& entry : qAsConst(mapMark))
1040 V2Markup *pMarkup = pMarkupList->AddNewMarkup();
1042 pMarkup->setType(typestr);
1043 pMarkup->setFrame(entry.frame);
1044 if (entry.isDataNull)
1045 pMarkup->setData(
"NULL");
1047 pMarkup->setData(QString::number(entry.data));
1049 for (
auto entry : qAsConst(mapSeek))
1051 V2Markup *pSeek = pMarkupList->AddNewSeek();
1053 pSeek->setType(typestr);
1054 pSeek->setFrame(entry.frame);
1055 if (entry.isDataNull)
1056 pSeek->setData(
"NULL");
1058 pSeek->setData(QString::number(entry.data));
1075 throw QString(
"Invalid RecordedId %1").arg(RecordedId);
1077 QVector<ProgramInfo::MarkupEntry> mapMark;
1078 QVector<ProgramInfo::MarkupEntry> mapSeek;
1080 QJsonDocument doc = QJsonDocument::fromJson(MarkupList.toUtf8());
1081 QJsonObject markuplist = doc.object();
1083 QJsonArray
marks = markuplist[
"Mark"].toArray();
1084 for (
const auto & m :
marks)
1086 QJsonObject markup = m.toObject();
1089 QString typestr = markup.value(
"Type").toString(
"");
1091 entry.
frame = markup.value(
"Frame").toVariant()
1092 .toString().toLongLong();
1093 QString data = markup.value(
"Data").toString(
"NULL");
1096 entry.
data = data.toLongLong();
1098 mapMark.append(entry);
1101 QJsonArray seeks = markuplist[
"Seek"].toArray();
1102 for (
const auto & m : seeks)
1104 QJsonObject markup = m.toObject();
1107 QString typestr = markup.value(
"Type").toString(
"");
1109 entry.
frame = markup.value(
"Frame").toVariant().toString().toLongLong();
1110 QString data = markup.value(
"Data").toString(
"NULL");
1113 entry.
data = data.toLongLong();
1115 mapSeek.append(entry);
1143 for (
const auto & inputInfo : qAsConst(inputInfoList))
1145 V2Input *input = pList->AddNewInput();
1159 query.
prepare(
"SELECT recgroup FROM recgroups WHERE recgroup <> 'Deleted' "
1160 "ORDER BY recgroup");
1169 while (query.
next())
1170 result << query.
value(0).toString();
1184 query.
prepare(
"SELECT DISTINCT category FROM recorded ORDER BY category");
1186 query.
prepare(
"SELECT DISTINCT category FROM program ORDER BY category");
1195 while (query.
next())
1196 result << query.
value(0).toString();
1229 query.
prepare(
"SELECT filterid, description, newruledefault "
1230 "FROM recordfilter ORDER BY filterid");
1234 while (query.
next())
1237 ruleFilter->setId(query.
value(0).toInt());
1238 ruleFilter->setDescription(QObject::tr(query.
value(1).toString()
1239 .toUtf8().constData()));
1254 QString querystr =
"SELECT DISTINCT title FROM recorded "
1255 "WHERE deletepending = 0";
1257 if (!RecGroup.isEmpty())
1258 querystr +=
" AND recgroup = :RECGROUP";
1260 querystr +=
" AND recgroup != 'Deleted'";
1262 querystr +=
" ORDER BY title";
1266 if (!RecGroup.isEmpty())
1276 while (query.
next())
1277 result << query.
value(0).toString();
1290 QString querystr = QString(
1291 "SELECT title, inetref, count(title) as count "
1292 " FROM recorded AS r "
1293 " JOIN recgroups AS g ON r.recgroupid = g.recgroupid "
1294 " WHERE g.recgroup NOT IN ('Deleted', 'LiveTV') "
1295 " AND r.deletepending = 0 "
1296 " GROUP BY title, inetref "
1308 while (query.
next())
1310 V2TitleInfo *pTitleInfo = pTitleInfos->AddNewTitleInfo();
1312 pTitleInfo->setTitle(query.
value(0).toString());
1313 pTitleInfo->setInetref(query.
value(1).toString());
1314 pTitleInfo->setCount(query.
value(2).toInt());
1333 pPrograms->setStartIndex ( nStartIndex );
1334 pPrograms->setCount ( nCount );
1335 pPrograms->setTotalAvailable( size );
1337 pPrograms->setVersion ( MYTH_BINARY_VERSION );
1338 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1357 pPrograms->setStartIndex ( nStartIndex );
1358 pPrograms->setCount ( nCount );
1359 pPrograms->setTotalAvailable( size );
1361 pPrograms->setVersion ( MYTH_BINARY_VERSION );
1362 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1368 const QString& sTitle,
1369 const QString& sSubtitle,
1370 const QString& sDescription,
1371 const QString& sCategory,
1372 const QDateTime& StartTime,
1373 const QDateTime& EndTime,
1374 const QString& sSeriesId,
1375 const QString& sProgramId,
1377 const QString& sStation,
1384 const QString& sInetref,
1386 QString sSearchType,
1388 uint nPreferredInput,
1391 const QDateTime& LastRecorded,
1396 QString sRecProfile,
1398 QString sStorageGroup,
1404 bool bAutoTranscode,
1405 bool bAutoMetaLookup,
1412 QDateTime recstartts = StartTime.toUTC();
1413 QDateTime recendts = EndTime.toUTC();
1414 QDateTime lastrects = LastRecorded.toUTC();
1418 if (sType.isEmpty())
1421 if (sSearchType.isEmpty())
1422 sSearchType =
"none";
1424 if (sDupMethod.isEmpty())
1425 sDupMethod =
"subtitleanddescription";
1427 if (sDupIn.isEmpty())
1447 if (sRecProfile.isEmpty())
1448 sRecProfile =
"Default";
1450 if (sRecGroup.isEmpty())
1451 sRecGroup =
"Default";
1453 if (sStorageGroup.isEmpty())
1454 sStorageGroup =
"Default";
1456 if (sPlayGroup.isEmpty())
1457 sPlayGroup =
"Default";
1522 const QString& sTitle,
1523 const QString& sSubtitle,
1524 const QString& sDescription,
1525 const QString& sCategory,
1526 const QDateTime& StartTime,
1527 const QDateTime& EndTime,
1528 const QString& sSeriesId,
1529 const QString& sProgramId,
1531 const QString& sStation,
1537 const QString& sInetref,
1539 QString sSearchType,
1541 uint nPreferredInput,
1548 QString sRecProfile,
1550 QString sStorageGroup,
1556 bool bAutoTranscode,
1557 bool bAutoMetaLookup,
1564 if (nRecordId == 0 )
1565 throw QString(
"Record ID is invalid.");
1572 throw QString(
"Record ID does not exist.");
1574 QDateTime recstartts = StartTime.toUTC();
1575 QDateTime recendts = EndTime.toUTC();
1578 if (sType.isEmpty())
1581 if (sSearchType.isEmpty())
1582 sSearchType =
"none";
1584 if (sDupMethod.isEmpty())
1585 sDupMethod =
"subtitleanddescription";
1587 if (sDupIn.isEmpty())
1598 if (sRecProfile.isEmpty())
1599 sRecProfile =
"Default";
1601 if (sRecGroup.isEmpty())
1602 sRecGroup =
"Default";
1604 if (sStorageGroup.isEmpty())
1605 sStorageGroup =
"Default";
1607 if (sPlayGroup.isEmpty())
1608 sPlayGroup =
"Default";
1610 if (!sTitle.isEmpty())
1613 if (!sSubtitle.isEmpty())
1616 if(!sDescription.isEmpty())
1619 if (!sCategory.isEmpty())
1622 if (!sSeriesId.isEmpty())
1625 if (!sProgramId.isEmpty())
1630 if (!sStation.isEmpty())
1683 bool bResult = pRule.
Save();
1690 bool bResult =
false;
1692 if (nRecordId == 0 )
1693 throw QString(
"Record ID does not exist.");
1698 bResult = pRule.
Delete();
1706 bool bResult =
true;
1708 if (nChanId <= 0 || !dStartTime.isValid())
1709 throw QString(
"Program does not exist.");
1714 throw QString(
"Program does not exist.");
1733 const QString &Sort,
1737 if (Sort.toLower() ==
"lastrecorded")
1739 else if (Sort.toLower() ==
"nextrecording")
1741 else if (Sort.toLower() ==
"title")
1743 else if (Sort.toLower() ==
"priority")
1745 else if (Sort.toLower() ==
"type")
1759 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recList.size() ) : 0;
1760 nCount = (nCount > 0) ? std::min( nCount, (
int)recList.size() ) : recList.size();
1761 int nEndIndex = std::min((nStartIndex + nCount), (
int)recList.size() );
1763 for(
int n = nStartIndex; n < nEndIndex; n++)
1767 if (info !=
nullptr)
1769 V2RecRule *pRecRule = pRecRules->AddNewRecRule();
1777 pRecRules->setStartIndex ( nStartIndex );
1778 pRecRules->setCount ( nCount );
1779 pRecRules->setTotalAvailable( recList.size() );
1781 pRecRules->setVersion ( MYTH_BINARY_VERSION );
1782 pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
1784 while (!recList.empty())
1786 delete recList.back();
1794 const QString& sTemplate,
1797 const QDateTime& StartTime,
1798 bool bMakeOverride )
1801 QDateTime dStartTime = StartTime.toUTC();
1807 throw QString(
"Record ID does not exist.");
1809 else if (!sTemplate.isEmpty())
1812 throw QString(
"Template does not exist.");
1814 else if (nRecordedId > 0)
1819 throw QString(
"Recording does not exist");
1821 else if (nChanId > 0 && dStartTime.isValid())
1826 RecordingInfo info(nChanId, dStartTime,
false, 0h, &status);
1828 throw QString(
"Program does not exist.");
1837 throw QString(
"Invalid request.");
1848 bool bResult =
false;
1850 if (nRecordId == 0 )
1851 throw QString(
"Record ID appears invalid.");
1860 bResult = pRule.
Save();
1868 bool bResult =
false;
1870 if (nRecordId == 0 )
1871 throw QString(
"Record ID appears invalid.");
1880 bResult = pRule.
Save();
1899 uint recordedid = 0;
1914 const QDateTime &StartTime)
1926 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
1936 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
1974 const QString &sJobName,
1977 QDateTime JobStartTime,
1978 QString sRemoteHost,
1986 LOG(VB_GENERAL, LOG_ERR,
"JobName and RecordedId are required.");
1990 if (sRemoteHost.isEmpty())
2003 if ( sAction ==
"Remove")
2007 LOG(VB_GENERAL, LOG_ERR,
"For Remove, a valid JobId is required.");
2018 if ( sAction !=
"Add")
2020 LOG(VB_GENERAL, LOG_ERR, QString(
"Illegal Action name '%1'. Use: Add, "
2021 "or Remove").arg(sAction));
2028 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been defined.")
2034 sRemoteHost,
false))
2036 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been allowed on host %2.")
2037 .arg(sJobName, sRemoteHost));
2041 if (!JobStartTime.isValid())
2042 JobStartTime = QDateTime::currentDateTime();
2047 if (sJobArgs.isNull())
2054 QString(
"Dvr/ManageJobQueue"),
2058 JobStartTime.toUTC());
2062 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 job wasn't queued because of a "
2063 "database error or because it was "
2064 "already running/stopping etc.")
2080 long BookmarkOffset,
2081 const QString &BookmarkOffsetType,
2083 const QString &Description,
2085 const QString &Inetref,
2086 QDate OriginalAirDate,
2090 const QString &SubTitle,
2091 const QString &Title,
2097 LOG(VB_GENERAL, LOG_ERR,
"No RecordedId, or no parameters to change.");
2104 if (!ri.GetChanID())
2113 uint64_t position =0;
2115 if (BookmarkOffsetType.toLower() ==
"position")
2117 if (!ri.QueryPositionKeyFrame(&position, BookmarkOffset,
true))
2120 else if (BookmarkOffsetType.toLower() ==
"duration")
2122 if (!ri.QueryDurationKeyFrame(&position, BookmarkOffset,
true))
2126 position = BookmarkOffset;
2128 ri.SaveBookmark(position);
2132 pi.SaveVideoProperties(VID_DAMAGED, Damaged ? VID_DAMAGED : 0);
2139 QString tmp_description;
2140 QString tmp_subtitle;
2144 tmp_description = Description;
2146 tmp_description = ri.GetDescription();
2149 tmp_subtitle = SubTitle;
2151 tmp_subtitle = ri.GetSubtitle();
2156 tmp_title = ri.GetTitle();
2158 ri.ApplyRecordRecTitleChange(tmp_title, tmp_subtitle, tmp_description);
2164 int tmp_episode = 0;
2168 tmp_episode = Episode;
2170 tmp_episode = ri.GetEpisode();
2173 tmp_season = Season;
2175 tmp_season = ri.GetSeason();
2177 pi.SaveSeasonEpisode(tmp_season, tmp_episode);
2181 pi.SaveInetRef(Inetref);
2185 if (!OriginalAirDate.isValid())
2187 LOG(VB_GENERAL, LOG_ERR,
"Need valid OriginalAirDate yyyy-mm-dd.");
2190 ri.ApplyOriginalAirDateChange(OriginalAirDate);
2194 pi.SavePreserve(Preserve);
2200 LOG(VB_GENERAL, LOG_ERR,
"Recording stars can be 0 to 10.");
2203 ri.ApplyStarsChange(
Stars * 0.1);
2207 pi.SaveWatched(Watched);
bool HAS_PARAMv2(const QString &p)
static QStringList getRecordingsGroups(void)
static uint GetRecgroupID(const QString &recGroup)
Temporary helper during transition from string to ID.
static bool AllowReRecord(int RecordedId)
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.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
static QString RecStatusToString(int RecStatus)
static bool QueryRecordedIdForKey(int &recordedid, uint chanid, const QDateTime &recstartts)
static V2CutList * GetRecordedSeek(int RecordedId, const QString &OffsetType)
void ApplyNeverRecord(void)
Set this program to never be recorded by inserting 'history' for it into the database with a status o...
static int RecordedIdForPathname(const QString &Pathname)
static QStringList GetPlayGroupList()
void V2FillProgramInfo(V2Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast, bool bIncArtwork, bool bIncRecording)
static V2ProgramList * GetUpcomingList(int StartIndex, int Count, bool ShowAll, int RecordId, int RecStatus)
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)
MythScheduler * GetScheduler(void)
static V2RecRule * GetRecordSchedule(uint RecordId, const QString &Template, int RecordedId, int ChanId, const QDateTime &StartTime, bool MakeOverride)
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.
int FillUpcomingList(QVariantList &list, QObject *parent, int &nStartIndex, int &nCount, bool bShowAll, int nRecordId, int nRecStatus)
RecSearchType searchTypeFromString(const QString &type)
V2ProgramList * 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, bool IncChannel, bool Details, bool IncCast, bool IncArtWork, bool IncRecording)
void V2FillCommBreak(V2CutList *pCutList, ProgramInfo *rInfo, int marktype)
RecordingDupInType dupInFromString(const QString &type)
static bool DeleteRecording(int RecordedId, int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
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
This class is used as a container for messages.
static QMap< QString, bool > QueryJobsRunning(int type)
bool QueryPositionKeyFrame(uint64_t *keyframe, uint64_t position, bool backwards) const
QVariant value(int i) const
Used to expire recordings to make space for new recordings.
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.
static QString DupInToString(const QString &DupIn)
void SaveCommFlagged(CommFlagStatus flag)
Set "commflagged" field in "recorded" table to "flag".
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static V2RecRuleFilterList * GetRecRuleFilterList()
bool QueryKeyFrameDuration(uint64_t *duration, uint64_t keyframe, bool backwards) const
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.
static QString RecTypeToDescription(const QString &RecType)
static long GetSavedBookmark(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
static bool SetSavedBookmark(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType, long Offset)
RecordingDupInType m_dupIn
bool m_isInactive
Recording rule is enabled?
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
static QStringList GetProgramCategories(bool OnlyRecorded)
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
bool IsWatched(void) const
static V2ProgramList * GetConflictList(int StartIndex, int Count, int RecordId)
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)
static bool EnableRecordSchedule(uint RecordId)
virtual QMap< QString, ProgramInfo * > GetRecording(void) const =0
bool Load(bool asTemplate=false)
Load a single rule from the recorded table.
static bool DisableRecordSchedule(uint RecordId)
void V2FillInputInfo(V2Input *input, const InputInfo &inputInfo)
static void RegisterCustomTypes()
static bool AddDontRecordSchedule(int ChanId, const QDateTime &StartTime, bool NeverRecord)
static bool UnDeleteRecording(int RecordedId, int ChanId, const QDateTime &StartTime)
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
void V2FillRecRuleInfo(V2RecRule *pRecRule, RecordingRule *pRule)
static QString toDescription(Type recstatus, RecordingType rectype, const QDateTime &recstartts)
Converts "recstatus" into a long human readable description.
void FillEncoderList(QVariantList &list, QObject *parent)
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
static V2Program * GetRecorded(int RecordedId, int ChanId, const QDateTime &StartTime)
static void DBError(const QString &where, const MSqlQuery &query)
void V2FillSeek(V2CutList *pCutList, RecordingInfo *rInfo, MarkTypes marktype)
QTime m_findtime
Time for timeslot rules.
RecordingDupMethodType dupMethodFromString(const QString &type)
MarkTypes markTypeFromString(const QString &str)
static bool UpdateRecordedWatchedStatus(int RecordedId, int ChanId, const QDateTime &StartTime, bool Watched)
RecSearchType m_searchType
std::vector< ProgramInfo * > pginfolist_t
RecordingType recTypeFromString(const QString &type)
static V2RecRuleList * GetRecordScheduleList(int StartIndex, int Count, const QString &Sort, bool Descending)
RecordingDupInType dupInFromStringAndBool(const QString &type, bool newEpisodesOnly)
static QStringList GetRecStorageGroupList()
static bool SetLastPlayPos(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType, long Offset)
static V2MarkupList * GetRecordedMarkup(int RecordedId)
int m_findday
Day of the week for once per week etc.
void ReactivateRecording(void)
Asks the scheduler to restart this recording if possible.
static V2ProgramList * GetExpiringList(int StartIndex, int Count)
void ProgramFlagsFromNames(const QString &names)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static QString DupMethodToString(const QString &DupMethod)
QString toDescription(RecordingType rectype)
Converts "rectype" into a human readable description.
int V2CreateRecordingGroup(const QString &groupName)
static uint AudioPropertiesFromNames(const QString &names)
static uint AddRecordSchedule(const QString &Title, const QString &Subtitle, const QString &Description, const QString &Category, const QDateTime &StartTime, const QDateTime &EndTime, 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 &LastRecorded, 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)
void SaveAutoExpire(AutoExpireType autoExpire, bool updateDelete=false)
Set "autoexpire" field in "recorded" table to "autoExpire".
static V2ProgramList * GetOldRecordedList(bool Descending, int StartIndex, int Count, const QDateTime &StartTime, const QDateTime &EndTime, const QString &Title, const QString &SeriesId, int RecordId, const QString &Sort)
static bool RemoveRecordSchedule(uint RecordId)
static uint SubtitleTypesFromNames(const QString &names)
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
static bool RescheduleRecordings(void)
static QStringList GetTitleList(const QString &RecGroup)
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")
int m_recordID
Unique Recording Rule ID.
bool QueryKeyFramePosition(uint64_t *position, uint64_t keyframe, bool backwards) const
static bool ReactivateRecording(int RecordedId, int ChanId, const QDateTime &StartTime)
static QString RecTypeToString(const QString &RecType)
static bool UpdateRecordSchedule(uint RecordId, const QString &Title, const QString &Subtitle, const QString &Description, const QString &Category, const QDateTime &StartTime, const QDateTime &EndTime, 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)
static long GetLastPlayPos(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
static int GetJobTypeFromName(const QString &name)
bool InsertRecording(const QString &ext, bool force_match=false)
RecordingDupMethodType m_dupMethod
bool IsCommercialFlagged(void) const
static bool AddRecordedCredits(int RecordedId, const QString &Cast)
static int GetJobID(int jobType, uint chanid, const QDateTime &recstartts)
static bool StopRecording(int RecordedId)
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
void V2FillCutList(V2CutList *pCutList, ProgramInfo *rInfo, int marktype)
static V2EncoderList * GetEncoderList()
static V2TitleInfoList * GetTitleInfoList()
static QMap< QString, uint32_t > QueryInUseMap(void)
void SaveWatched(bool watchedFlag)
Set "watched" field in recorded/videometadata to "watchedFlag".
static QString DupInToDescription(const QString &DupIn)
std::deque< RecordingInfo * > RecList
bool IsAutoExpirable(void) const
static V2InputList * GetInputList()
static const std::array< const mark, 16 > marks
void SendUpdateEvent(void) const
Sends event out that the ProgramInfo should be reloaded.
void SavePreserve(bool preserveEpisode)
Set "preserve" field in "recorded" table to "preserveEpisode".
static QString DupMethodToDescription(const QString &DupMethod)
static QStringList GetRecGroupList()
bool UpdateRecordedMetadata(uint RecordedId, bool AutoExpire, long BookmarkOffset, const QString &BookmarkOffsetType, bool Damaged, const QString &Description, uint Episode, const QString &Inetref, QDate OriginalAirDate, bool Preserve, uint Season, uint Stars, const QString &SubTitle, const QString &Title, bool Watched)
static int RecordedIdForKey(int ChanId, const QDateTime &StartTime)
bool LoadFromOldRecorded(ProgramList &destination, const QString &sql, const MSqlBindings &bindings)
bool Delete(bool sendSig=true)
static V2CutList * GetRecordedCommBreak(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
QString GetHostName(void)
void SaveMarkup(const QVector< MarkupEntry > &mapMark, const QVector< MarkupEntry > &mapSeek) const
uint64_t QueryLastPlayPos(void) const
Gets any lastplaypos position in database, unless the ignore lastplaypos flag is set.
bool GetBoolSettingOnHost(const QString &key, const QString &host, bool defaultval=false)
static V2CutList * GetRecordedCutList(int RecordedId, int ChanId, const QDateTime &StartTime, const QString &OffsetType)
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
RecordingRule * GetRecordingRule(void)
Returns the "record" field, creating it if necessary.
bool QueryDurationKeyFrame(uint64_t *keyframe, uint64_t duration, bool backwards) const
static bool RemoveRecorded(int RecordedId, int ChanId, const QDateTime &StartTime, bool ForceDelete, bool AllowRerecord)
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(DVR_HANDLE, V2Dvr::staticMetaObject, &V2Dvr::RegisterCustomTypes)) void V2Dvr
static void RescheduleMatch(uint recordid, uint sourceid, uint mplexid, const QDateTime &maxstarttime, const QString &why)
void dispatch(const MythEvent &event)
static QString RecStatusToDescription(int RecStatus, int RecType, const QDateTime &StartTime)
bool m_autoMetadataLookup
static int AddRecordedProgram(const QString &Program)
bool HasPathname(void) const
static uint VideoPropertiesFromNames(const QString &names)
int ManageJobQueue(const QString &Action, const QString &JobName, int JobId, int RecordedId, QDateTime JobStartTime, QString RemoteHost, QString JobArgs)
void SaveLastPlayPos(uint64_t frame)
TODO Move to RecordingInfo.
DBCredits * V2jsonCastToCredits(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.
static bool SetRecordedMarkup(int RecordedId, const QString &MarkupList)