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 (
const 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 );
1353 QMetaEnum meta = QMetaEnum::fromType<RecStatus::Type>();
1355 nRecStatus = meta.keyToValue(
RecStatus.toLocal8Bit(), &ok);
1371 pPrograms->setStartIndex ( nStartIndex );
1372 pPrograms->setCount ( nCount );
1373 pPrograms->setTotalAvailable( size );
1375 pPrograms->setVersion ( MYTH_BINARY_VERSION );
1376 pPrograms->setProtoVer ( MYTH_PROTO_VERSION );
1382 const QString& sTitle,
1383 const QString& sSubtitle,
1384 const QString& sDescription,
1385 const QString& sCategory,
1386 const QDateTime& StartTime,
1387 const QDateTime& EndTime,
1388 const QString& sSeriesId,
1389 const QString& sProgramId,
1391 const QString& sStation,
1398 const QString& sInetref,
1400 QString sSearchType,
1402 uint nPreferredInput,
1405 const QDateTime& LastRecorded,
1410 QString sRecProfile,
1412 QString sStorageGroup,
1418 bool bAutoTranscode,
1419 bool bAutoMetaLookup,
1425 const QString& AutoExtend)
1427 QDateTime recstartts = StartTime.toUTC();
1428 QDateTime recendts = EndTime.toUTC();
1429 QDateTime lastrects = LastRecorded.toUTC();
1433 if (sType.isEmpty())
1436 if (sSearchType.isEmpty())
1437 sSearchType =
"none";
1439 if (sDupMethod.isEmpty())
1440 sDupMethod =
"subtitleanddescription";
1442 if (sDupIn.isEmpty())
1462 if (sRecProfile.isEmpty())
1463 sRecProfile =
"Default";
1465 if (sRecGroup.isEmpty())
1466 sRecGroup =
"Default";
1468 if (sStorageGroup.isEmpty())
1469 sStorageGroup =
"Default";
1471 if (sPlayGroup.isEmpty())
1472 sPlayGroup =
"Default";
1538 const QString& sTitle,
1539 const QString& sSubtitle,
1540 const QString& sDescription,
1541 const QString& sCategory,
1542 const QDateTime& StartTime,
1543 const QDateTime& EndTime,
1544 const QString& sSeriesId,
1545 const QString& sProgramId,
1547 const QString& sStation,
1553 const QString& sInetref,
1555 QString sSearchType,
1557 uint nPreferredInput,
1564 QString sRecProfile,
1566 QString sStorageGroup,
1572 bool bAutoTranscode,
1573 bool bAutoMetaLookup,
1579 const QString& AutoExtend)
1581 if (nRecordId == 0 )
1582 throw QString(
"Record ID is invalid.");
1589 throw QString(
"Record ID does not exist.");
1591 QDateTime recstartts = StartTime.toUTC();
1592 QDateTime recendts = EndTime.toUTC();
1595 if (sType.isEmpty())
1598 if (sSearchType.isEmpty())
1599 sSearchType =
"none";
1601 if (sDupMethod.isEmpty())
1602 sDupMethod =
"subtitleanddescription";
1604 if (sDupIn.isEmpty())
1615 if (sRecProfile.isEmpty())
1616 sRecProfile =
"Default";
1618 if (sRecGroup.isEmpty())
1619 sRecGroup =
"Default";
1621 if (sStorageGroup.isEmpty())
1622 sStorageGroup =
"Default";
1624 if (sPlayGroup.isEmpty())
1625 sPlayGroup =
"Default";
1627 if (!sTitle.isEmpty())
1630 if (!sSubtitle.isEmpty())
1633 if(!sDescription.isEmpty())
1636 if (!sCategory.isEmpty())
1639 if (!sSeriesId.isEmpty())
1642 if (!sProgramId.isEmpty())
1647 if (!sStation.isEmpty())
1696 if (!AutoExtend.isEmpty())
1703 bool bResult = pRule.
Save();
1710 bool bResult =
false;
1712 if (nRecordId == 0 )
1713 throw QString(
"Record ID does not exist.");
1718 bResult = pRule.
Delete();
1726 bool bResult =
true;
1728 if (nChanId <= 0 || !dStartTime.isValid())
1729 throw QString(
"Program does not exist.");
1734 throw QString(
"Program does not exist.");
1753 const QString &Sort,
1757 if (Sort.toLower() ==
"lastrecorded")
1759 else if (Sort.toLower() ==
"nextrecording")
1761 else if (Sort.toLower() ==
"title")
1763 else if (Sort.toLower() ==
"priority")
1765 else if (Sort.toLower() ==
"type")
1779 nStartIndex = (nStartIndex > 0) ? std::min( nStartIndex, (
int)recList.size() ) : 0;
1780 nCount = (nCount > 0) ? std::min( nCount, (
int)recList.size() ) : recList.size();
1781 int nEndIndex = std::min((nStartIndex + nCount), (
int)recList.size() );
1783 for(
int n = nStartIndex; n < nEndIndex; n++)
1787 if (info !=
nullptr)
1789 V2RecRule *pRecRule = pRecRules->AddNewRecRule();
1797 pRecRules->setStartIndex ( nStartIndex );
1798 pRecRules->setCount ( nCount );
1799 pRecRules->setTotalAvailable( recList.size() );
1801 pRecRules->setVersion ( MYTH_BINARY_VERSION );
1802 pRecRules->setProtoVer ( MYTH_PROTO_VERSION );
1804 while (!recList.empty())
1806 delete recList.back();
1814 const QString& sTemplate,
1817 const QDateTime& StartTime,
1818 bool bMakeOverride )
1821 QDateTime dStartTime = StartTime.toUTC();
1827 throw QString(
"Record ID does not exist.");
1829 else if (!sTemplate.isEmpty())
1832 throw QString(
"Template does not exist.");
1834 else if (nRecordedId > 0)
1839 throw QString(
"Recording does not exist");
1841 else if (nChanId > 0 && dStartTime.isValid())
1846 RecordingInfo info(nChanId, dStartTime,
false, 0h, &status);
1848 throw QString(
"Program does not exist.");
1857 throw QString(
"Invalid request.");
1868 bool bResult =
false;
1870 if (nRecordId == 0 )
1871 throw QString(
"Record ID appears invalid.");
1880 bResult = pRule.
Save();
1888 bool bResult =
false;
1890 if (nRecordId == 0 )
1891 throw QString(
"Record ID appears invalid.");
1900 bResult = pRule.
Save();
1919 uint recordedid = 0;
1930 QMetaEnum meta = QMetaEnum::fromType<RecStatus::Type>();
1932 int value = meta.keyToValue(
RecStatus.toLocal8Bit(), &ok);
1944 const QDateTime &StartTime)
1947 QMetaEnum meta = QMetaEnum::fromType<RecStatus::Type>();
1949 int value = meta.keyToValue(
RecStatus.toLocal8Bit(), &ok);
1964 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
1974 auto enumType =
static_cast<RecordingType>(recType.toInt(&ok, 10));
2012 const QString &sJobName,
2015 QDateTime JobStartTime,
2016 QString sRemoteHost,
2024 LOG(VB_GENERAL, LOG_ERR,
"JobName and RecordedId are required.");
2028 if (sRemoteHost.isEmpty())
2041 if ( sAction ==
"Remove")
2045 LOG(VB_GENERAL, LOG_ERR,
"For Remove, a valid JobId is required.");
2056 if ( sAction !=
"Add")
2058 LOG(VB_GENERAL, LOG_ERR, QString(
"Illegal Action name '%1'. Use: Add, "
2059 "or Remove").arg(sAction));
2066 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been defined.")
2072 sRemoteHost,
false))
2074 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 hasn't been allowed on host %2.")
2075 .arg(sJobName, sRemoteHost));
2079 if (!JobStartTime.isValid())
2080 JobStartTime = QDateTime::currentDateTime();
2085 if (sJobArgs.isNull())
2092 QString(
"Dvr/ManageJobQueue"),
2096 JobStartTime.toUTC());
2100 LOG(VB_GENERAL, LOG_ERR, QString(
"%1 job wasn't queued because of a "
2101 "database error or because it was "
2102 "already running/stopping etc.")
2118 long BookmarkOffset,
2119 const QString &BookmarkOffsetType,
2121 const QString &Description,
2123 const QString &Inetref,
2124 QDate OriginalAirDate,
2128 const QString &SubTitle,
2129 const QString &Title,
2131 const QString &RecGroup )
2136 LOG(VB_GENERAL, LOG_ERR,
"No RecordedId, or no parameters to change.");
2143 if (!ri.GetChanID())
2152 uint64_t position =0;
2154 if (BookmarkOffsetType.toLower() ==
"position")
2156 if (!ri.QueryPositionKeyFrame(&position, BookmarkOffset,
true))
2159 else if (BookmarkOffsetType.toLower() ==
"duration")
2161 if (!ri.QueryDurationKeyFrame(&position, BookmarkOffset,
true))
2165 position = BookmarkOffset;
2167 ri.SaveBookmark(position);
2171 pi.SaveVideoProperties(VID_DAMAGED, Damaged ? VID_DAMAGED : 0);
2178 QString tmp_description;
2179 QString tmp_subtitle;
2183 tmp_description = Description;
2185 tmp_description = ri.GetDescription();
2188 tmp_subtitle = SubTitle;
2190 tmp_subtitle = ri.GetSubtitle();
2195 tmp_title = ri.GetTitle();
2197 ri.ApplyRecordRecTitleChange(tmp_title, tmp_subtitle, tmp_description);
2203 int tmp_episode = 0;
2207 tmp_episode = Episode;
2209 tmp_episode = ri.GetEpisode();
2212 tmp_season = Season;
2214 tmp_season = ri.GetSeason();
2216 pi.SaveSeasonEpisode(tmp_season, tmp_episode);
2220 pi.SaveInetRef(Inetref);
2225 if (!OriginalAirDate.isValid() && !OriginalAirDate.isNull())
2227 LOG(VB_GENERAL, LOG_ERR,
"Need valid OriginalAirDate yyyy-mm-dd.");
2230 ri.ApplyOriginalAirDateChange(OriginalAirDate);
2234 pi.SavePreserve(Preserve);
2240 LOG(VB_GENERAL, LOG_ERR,
"Recording stars can be 0 to 10.");
2243 ri.ApplyStarsChange(
Stars * 0.1);
2247 pi.SaveWatched(Watched);
2250 ri.ApplyRecordRecGroupChange(RecGroup);
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 bool QueryRecordedIdForKey(int &recordedid, uint chanid, const QDateTime &recstartts)
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, const QString &RecGroup)
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)
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".
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, const QString &AutoExtend)
#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 QString RecStatusToDescription(const QString &RecStatus, int RecType, const QDateTime &StartTime)
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 QString RecStatusToString(const QString &RecStatus)
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 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, const QString &AutoExtend)
static uint AudioPropertiesFromNames(const QString &names)
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 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
AutoExtendType autoExtendTypeFromString(const QString &type)
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
AutoExtendType m_autoExtend
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()
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
static V2ProgramList * GetUpcomingList(int StartIndex, int Count, bool ShowAll, int RecordId, const QString &RecStatus)
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)
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)