138 "object.item.videoItem" )
165 pRequest->m_nRequestedCount = 0;
174 QObject::tr(
"All Recordings"),
188 QObject::tr(
"Movies"),
202 QObject::tr(
"Title"),
232 QObject::tr(
"Genre"),
246 QObject::tr(
"Channel"),
260 QObject::tr(
"Recording Group"),
284 const IDTokenMap& tokens,
const QString& currentToken)
286 if (currentToken.isEmpty())
288 LOG(VB_GENERAL, LOG_ERR, QString(
"UPnpCDSTV::LoadMetadata: Final "
289 "token missing from id: %1")
295 if (tokens[currentToken].isEmpty())
306 pResults->
Add(container);
310 LOG(VB_GENERAL, LOG_ERR, QString(
"UPnpCDSTV::LoadMetadata: Requested "
311 "object cannot be found: %1")
314 else if (currentToken ==
"recording")
318 else if (currentToken ==
"title")
320 return LoadTitles(pRequest, pResults, tokens);
322 else if (currentToken ==
"date")
324 return LoadDates(pRequest, pResults, tokens);
326 else if (currentToken ==
"genre")
328 return LoadGenres(pRequest, pResults, tokens);
330 else if (currentToken ==
"recgroup")
334 else if (currentToken ==
"channel")
338 else if (currentToken ==
"movie")
340 return LoadMovies(pRequest, pResults, tokens);
344 LOG(VB_GENERAL, LOG_ERR,
345 QString(
"UPnpCDSTV::LoadMetadata(): "
346 "Unhandled metadata request for '%1'.").arg(currentToken));
358 const IDTokenMap& tokens,
const QString& currentToken)
360 if (currentToken.isEmpty() || currentToken ==
m_sExtensionId.toLower())
367 if (currentToken ==
"title")
369 if (!tokens[
"title"].isEmpty())
371 return LoadTitles(pRequest, pResults, tokens);
373 if (currentToken ==
"date")
375 if (!tokens[
"date"].isEmpty())
377 return LoadDates(pRequest, pResults, tokens);
379 if (currentToken ==
"genre")
381 if (!tokens[
"genre"].isEmpty())
383 return LoadGenres(pRequest, pResults, tokens);
385 if (currentToken ==
"recgroup")
387 if (!tokens[
"recgroup"].isEmpty())
391 if (currentToken ==
"channel")
393 if (tokens[
"channel"].toInt() > 0)
397 if (currentToken ==
"movie")
399 return LoadMovies(pRequest, pResults, tokens);
401 if (currentToken ==
"recording")
405 LOG(VB_GENERAL, LOG_ERR,
406 QString(
"UPnpCDSTV::LoadChildren(): "
407 "Unhandled metadata request for '%1'.").arg(currentToken));
452 LOG(VB_UPNP, LOG_INFO,
453 "UPnpCDSTv::IsBrowseRequestForUs - Not sure... Calling base class.");
536 QString sql =
"SELECT SQL_CALC_FOUND_ROWS "
537 "r.title, r.inetref, r.recordedid, COUNT(*) "
539 "LEFT JOIN recgroups g ON r.recgroup=g.recgroup "
543 "LIMIT :OFFSET,:COUNT";
547 query.
prepare(sql.arg(whereString));
558 QString sTitle = query.
value(0).toString();
559 QString sInetRef = query.
value(1).toString();
560 int nRecordingID = query.
value(2).toInt();
561 int nTitleCount = query.
value(3).toInt();
572 pContainer->
SetPropValue(
"description", QObject::tr(
"%n Episode(s)",
"", nTitleCount));
573 pContainer->
SetPropValue(
"longdescription", QObject::tr(
"%n Episode(s)",
"", nTitleCount));
582 pResults->
Add(pContainer);
588 newTokens.insert(
"recording", QString::number(nRecordingID));
595 if (query.
size() > 0)
599 query.
prepare(
"SELECT FOUND_ROWS()");
623 QString sql =
"SELECT SQL_CALC_FOUND_ROWS "
624 "r.starttime, COUNT(r.recordedid) "
626 "LEFT JOIN recgroups g ON g.recgroup=r.recgroup "
628 "GROUP BY DATE(CONVERT_TZ(r.starttime, 'UTC', 'SYSTEM')) "
629 "ORDER BY r.starttime DESC "
630 "LIMIT :OFFSET,:COUNT";
634 query.
prepare(sql.arg(whereString));
645 QDate dtDate = query.
value(0).toDate();
646 int nRecCount = query.
value(1).toInt();
656 pResults->
Add(pContainer);
662 if (query.
size() > 0)
666 query.
prepare(
"SELECT FOUND_ROWS()");
690 QString sql =
"SELECT SQL_CALC_FOUND_ROWS "
691 "r.category, COUNT(r.recordedid) "
693 "LEFT JOIN recgroups g ON g.recgroup=r.recgroup "
695 "GROUP BY r.category "
696 "ORDER BY r.category "
697 "LIMIT :OFFSET,:COUNT";
701 query.
prepare(sql.arg(whereString));
712 QString sGenre = query.
value(0).toString();
713 int nRecCount = query.
value(1).toInt();
716 QString sDisplayGenre = sGenre.isEmpty() ? QObject::tr(
"No Genre") : sGenre;
717 sGenre = sGenre.isEmpty() ?
"MYTH_NO_GENRE" : sGenre;
727 pResults->
Add(pContainer);
733 if (query.
size() > 0)
737 query.
prepare(
"SELECT FOUND_ROWS()");
761 QString sql =
"SELECT SQL_CALC_FOUND_ROWS "
762 "r.recgroupid, g.displayname, g.recgroup, COUNT(r.recordedid) "
764 "LEFT JOIN recgroups g ON g.recgroup=r.recgroup "
766 "GROUP BY r.recgroup "
767 "ORDER BY g.displayname "
768 "LIMIT :OFFSET,:COUNT";
773 query.
prepare(sql.arg(whereString));
787 QString sDisplayName = query.
value(1).toString();
788 QString sName = query.
value(2).toString();
789 int nRecCount = query.
value(3).toInt();
793 sDisplayName.isEmpty() ? sName : sDisplayName,
799 pResults->
Add(pContainer);
805 if (query.
size() > 0)
809 query.
prepare(
"SELECT FOUND_ROWS()");
833 QString sql =
"SELECT SQL_CALC_FOUND_ROWS "
834 "r.chanid, c.channum, c.name, COUNT(r.recordedid) "
836 "JOIN channel c ON c.chanid=r.chanid "
837 "LEFT JOIN recgroups g ON g.recgroup=r.recgroup "
839 "GROUP BY c.channum "
840 "ORDER BY LPAD(CAST(c.channum AS UNSIGNED), 10, 0), "
841 " LPAD(c.channum, 10, 0)"
842 "LIMIT :OFFSET,:COUNT";
847 query.
prepare(sql.arg(whereString));
859 int nChanID = query.
value(0).toInt();
860 QString sChanNum = query.
value(1).toString();
861 QString sName = query.
value(2).toString();
862 int nRecCount = query.
value(3).toInt();
864 QString sFullName = QString(
"%1 %2").arg(sChanNum, sName);
874 pResults->
Add(pContainer);
880 if (query.
size() > 0)
884 query.
prepare(
"SELECT FOUND_ROWS()");
899 tokens[
"category_type"] =
"movie";
943 if (tokens[
"recording"].toInt() > 0)
953 QString sql =
"SELECT SQL_CALC_FOUND_ROWS "
954 "r.chanid, r.starttime, r.endtime, r.title, "
955 "r.subtitle, r.description, r.category, "
956 "r.hostname, r.recgroup, r.filesize, "
957 "r.basename, r.progstart, r.progend, "
958 "r.storagegroup, r.inetref, "
959 "p.category_type, c.callsign, c.channum, "
960 "p.episode, p.totalepisodes, p.season, "
961 "r.programid, r.seriesid, r.recordid, "
962 "c.default_authority, c.name, "
963 "r.recordedid, r.transcoded, p.videoprop+0, p.audioprop+0, "
964 "f.video_codec, f.audio_codec, f.fps, f.width, f.height, "
967 "LEFT JOIN channel c ON r.chanid=c.chanid "
968 "LEFT JOIN recordedprogram p ON p.chanid=r.chanid "
969 " AND p.starttime=r.progstart "
970 "LEFT JOIN recgroups g ON r.recgroup=g.recgroup "
971 "LEFT JOIN recordedfile f ON r.recordedid=f.recordedid "
974 "LIMIT :OFFSET,:COUNT";
977 QString orderByString =
"ORDER BY r.starttime DESC, r.title";
979 if (!tokens[
"title"].isEmpty())
980 orderByString =
"ORDER BY p.season, p.episode, r.starttime ASC";
985 query.
prepare(sql.arg(whereString, orderByString));
997 int nChanid = query.
value( 0).toInt();
1000 QString sTitle = query.
value( 3).toString();
1001 QString sSubtitle = query.
value( 4).toString();
1002 QString sDescription = query.
value( 5).toString();
1003 QString sCategory = query.
value( 6).toString();
1004 QString sHostName = query.
value( 7).toString();
1006 uint64_t nFileSize = query.
value( 9).toULongLong();
1007 QString sBaseName = query.
value(10).toString();
1009 QDateTime dtProgStart =
1011 QDateTime dtProgEnd =
1013 QString sStorageGrp = query.
value(13).toString();
1015 QString sInetRef = query.
value(14).toString();
1016 QString sCatType = query.
value(15).toString();
1017 QString sCallsign = query.
value(16).toString();
1018 QString sChanNum = query.
value(17).toString();
1020 int nEpisode = query.
value(18).toInt();
1021 int nEpisodeTotal = query.
value(19).toInt();
1022 int nSeason = query.
value(20).toInt();
1024 QString sProgramId = query.
value(21).toString();
1025 QString sSeriesId = query.
value(22).toString();
1026 int nRecordId = query.
value(23).toInt();
1028 QString sDefaultAuthority = query.
value(24).toString();
1029 QString sChanName = query.
value(25).toString();
1031 int nRecordedId = query.
value(26).toInt();
1033 bool bTranscoded = query.
value(27).toBool();
1034 int nVideoProps = query.
value(28).toInt();
1037 QString sVideoCodec = query.
value(30).toString();
1038 QString sAudioCodec = query.
value(31).toString();
1039 double dVideoFrameRate = query.
value(32).toDouble();
1040 int nVideoWidth = query.
value(33).toInt();
1041 int nVideoHeight = query.
value(34).toInt();
1042 QString sContainer = query.
value(35).toString();
1059 URIBase.setScheme(
"http");
1069 QString sRefIDBase = QString(
"%1/Recording").arg(
m_sExtensionId);
1072 QString sRefId = QString(
"%1=%2")
1074 .arg( nRecordedId );
1094 if (!sSubtitle.isEmpty())
1097 pItem->
SetPropValue(
"description", sDescription.left(128).append(
" ..."));
1098 pItem->
SetPropValue(
"longDescription", sDescription );
1102 pItem->
SetPropValue(
"channelID" , sChanNum,
"DIGITAL");
1106 int nChanNum = sChanNum.toInt();
1108 pItem->
SetPropValue(
"channelNr" , QString::number(nChanNum) );
1110 if (sCatType !=
"movie")
1120 if ( nEpisode > 0 || nSeason > 0 )
1122 pItem->
SetPropValue(
"episodeNumber" , QString::number(nEpisode));
1123 pItem->
SetPropValue(
"episodeCount" , QString::number(nEpisodeTotal));
1128 auto msecs = std::chrono::milliseconds(dtProgEnd.toMSecsSinceEpoch() - dtProgStart.toMSecsSinceEpoch());
1132 pItem->
SetPropValue(
"srsRecordScheduleID" , QString::number(nRecordId));
1134 if (!sSeriesId.isEmpty())
1138 QString sIdType =
"mythtv.org_XMLTV";
1139 if (sSeriesId.contains(sDefaultAuthority))
1140 sIdType =
"mythtv.org_EIT";
1145 if (!sProgramId.isEmpty())
1149 QString sIdType =
"mythtv.org_XMLTV";
1150 if (sProgramId.contains(sDefaultAuthority))
1151 sIdType =
"mythtv.org_EIT";
1153 pItem->
SetPropValue(
"programID", sProgramId, sIdType );
1172 QString sFilePath = sg.
FindFile(sBaseName);
1195 std::chrono::milliseconds nDurationMS { 0ms };
1207 if (nDurationMS == 0ms)
1209 auto uiStart = std::chrono::milliseconds(dtStartTime.toMSecsSinceEpoch());
1210 auto uiEnd = std::chrono::milliseconds(dtEndTime.toMSecsSinceEpoch());
1211 nDurationMS = (uiEnd - uiStart);
1212 nDurationMS = std::max(0ms, nDurationMS);
1218 QSize resolution = QSize(nVideoWidth, nVideoHeight);
1222 if (sContainer.isEmpty())
1225 if (sMimeType ==
"video/mp2p")
1228 sContainer =
"MPEG2-PS";
1230 sContainer =
"MPEG2-TS";
1232 else if (sMimeType ==
"video/mp2t")
1234 sMimeType =
"video/mp2p";
1235 sContainer =
"MPEG2-TS";
1240 if (sVideoCodec.isEmpty())
1242 if (sMimeType ==
"video/mp2p" || sMimeType ==
"video/mp2t")
1243 sVideoCodec = (nVideoProps & VID_AVC) ?
"H264" :
"MPEG2VIDEO";
1244 else if (sMimeType ==
"video/mp4")
1245 sVideoCodec =
"MPEG4";
1251 if (sMimeType ==
"video/mp2t" || sMimeType ==
"video/mp2p")
1252 sMimeType =
"video/mpeg";
1254 QUrl resURI = URIBase;
1256 resURI.setPath(
"/Content/GetRecording");
1257 resQuery.addQueryItem(
"RecordedId", QString::number(nRecordedId));
1258 resURI.setQuery(resQuery);
1272 if (nDurationMS > 0ms)
1274 if (nVideoHeight > 0 && nVideoWidth > 0)
1275 pRes->
AddAttribute (
"resolution" , QString(
"%1x%2").arg(nVideoWidth).arg(nVideoHeight) );
1276 pRes->
AddAttribute (
"size" , QString::number( nFileSize) );
1283 QUrl previewURI = URIBase;
1284 QUrlQuery previewQuery;
1285 previewURI.setPath(
"/Content/GetPreviewImage");
1286 previewQuery.addQueryItem(
"RecordedId", QString::number(nRecordedId));
1287 previewQuery.addQueryItem(
"Width",
"160");
1288 previewQuery.addQueryItem(
"Format",
"JPG");
1289 previewURI.setQuery(previewQuery);
1293 pItem->
AddResource( sProtocol, previewURI.toEncoded());
1298 if (!sInetRef.isEmpty())
1303 pResults->
Add( pItem );
1309 if (query.
size() > 0)
1313 query.
prepare(
"SELECT FOUND_ROWS()");
1325 int nSeason,
const QUrl& URIBase)
1327 QUrl artURI = URIBase;
1328 artURI.setPath(
"/Content/GetRecordingArtwork");
1329 QUrlQuery artQuery(artURI.query());
1330 artQuery.addQueryItem(
"Inetref", sInetRef);
1331 artQuery.addQueryItem(
"Season", QString::number(nSeason));
1332 artURI.setQuery(artQuery);
1346 QUrl thumbURI = artURI;
1347 QUrlQuery thumbQuery(thumbURI.query());
1348 thumbQuery.addQueryItem(
"Type",
"screenshot");
1349 thumbQuery.addQueryItem(
"Width",
"160");
1350 thumbQuery.addQueryItem(
"Height",
"160");
1351 thumbURI.setQuery(thumbQuery);
1355 QUrl smallURI = artURI;
1356 QUrlQuery smallQuery(smallURI.query());
1357 smallQuery.addQueryItem(
"Type",
"coverart");
1358 smallQuery.addQueryItem(
"Width",
"640");
1359 smallQuery.addQueryItem(
"Height",
"480");
1360 smallURI.setQuery(smallQuery);
1364 QUrl mediumURI = artURI;
1365 QUrlQuery mediumQuery(mediumURI.query());
1366 mediumQuery.addQueryItem(
"Type",
"coverart");
1367 mediumQuery.addQueryItem(
"Width",
"1024");
1368 mediumQuery.addQueryItem(
"Height",
"768");
1369 mediumURI.setQuery(mediumQuery);
1374 QUrl largeURI = artURI;
1375 QUrlQuery largeQuery(largeURI.query());
1376 largeQuery.addQueryItem(
"Type",
"fanart");
1377 largeURI.setQuery(largeQuery);
1379 QList<Property*> propList = pItem->
GetProperties(
"albumArtURI");
1380 if (propList.size() >= 4)
1385 pProp->
SetValue(mediumURI.toEncoded());
1387 pProp->
AddAttribute(
"xmlns:dlna",
"urn:schemas-dlna-org:metadata-1-0");
1390 pProp = propList.at(1);
1393 pProp->
SetValue(thumbURI.toEncoded());
1395 pProp->
AddAttribute(
"xmlns:dlna",
"urn:schemas-dlna-org:metadata-1-0");
1398 pProp = propList.at(2);
1401 pProp->
SetValue(smallURI.toEncoded());
1403 pProp->
AddAttribute(
"xmlns:dlna",
"urn:schemas-dlna-org:metadata-1-0");
1406 pProp = propList.at(3);
1409 pProp->
SetValue(largeURI.toEncoded());
1411 pProp->
AddAttribute(
"xmlns:dlna",
"urn:schemas-dlna-org:metadata-1-0");
1415 if (pItem->
m_sClass.startsWith(
"object.item.videoItem"))
1420 "image/jpeg", QSize(1024, 768));
1421 pItem->
AddResource( sProtocol, mediumURI.toEncoded());
1429 "image/jpeg", QSize(640, 480));
1430 pItem->
AddResource( sProtocol, smallURI.toEncoded());
1433 "image/jpeg", QSize(1920, 1080));
1434 pItem->
AddResource( sProtocol, largeURI.toEncoded());
1453 clauses.append(
"g.password=''");
1458 clauses.append(QString(
"g.recgroup != '%1'").arg(liveTVGroup));
1460 clauses.append(QString(
"g.recgroup != '%1'").arg(deletedGroup));
1462 if (tokens[
"recording"].toInt() > 0)
1463 clauses.append(
"r.recordedid=:RECORDED_ID");
1464 if (!tokens[
"date"].isEmpty())
1465 clauses.append(
"DATE(CONVERT_TZ(r.starttime, 'UTC', 'SYSTEM'))=:DATE");
1466 if (!tokens[
"genre"].isEmpty())
1467 clauses.append(
"r.category=:GENRE");
1468 if (!tokens[
"recgroup"].isEmpty())
1469 clauses.append(
"r.recgroup=:RECGROUP");
1470 if (!tokens[
"title"].isEmpty())
1471 clauses.append(
"r.title=:TITLE");
1472 if (!tokens[
"channel"].isEmpty())
1473 clauses.append(
"r.chanid=:CHANNEL");
1475 if (!tokens[
"category_type"].isEmpty())
1476 clauses.append(
"p.category_type=:CATTYPE");
1478 QString whereString;
1479 if (!clauses.isEmpty())
1481 whereString =
" WHERE ";
1482 whereString.append(clauses.join(
" AND "));
1495 if (tokens[
"recording"].toInt() > 0)
1496 query.
bindValue(
":RECORDED_ID", tokens[
"recording"]);
1497 if (!tokens[
"date"].isEmpty())
1498 query.
bindValue(
":DATE", tokens[
"date"]);
1499 if (!tokens[
"genre"].isEmpty())
1500 query.
bindValue(
":GENRE", tokens[
"genre"] ==
"MYTH_NO_GENRE" ?
"" : tokens[
"genre"]);
1501 if (!tokens[
"recgroup"].isEmpty())
1502 query.
bindValue(
":RECGROUP", tokens[
"recgroup"]);
1503 if (!tokens[
"title"].isEmpty())
1504 query.
bindValue(
":TITLE", tokens[
"title"]);
1505 if (tokens[
"channel"].toInt() > 0)
1506 query.
bindValue(
":CHANNEL", tokens[
"channel"]);
1507 if (!tokens[
"category_type"].isEmpty())
1508 query.
bindValue(
":CATTYPE", tokens[
"category_type"]);
static CDSObject * CreateContainer(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
uint32_t GetChildCount(void) const
Return the number of children in this container.
void SetChildCount(uint32_t nCount)
Allows the caller to set childCount without having to load children.
static CDSObject * CreateVideoItem(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
Resource * AddResource(const QString &sProtocol, const QString &sURI)
CDSObject * AddChild(CDSObject *pChild)
static CDSObject * CreateAlbum(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
static CDSObject * CreateMovieGenre(const QString &sId, const QString &sTitle, const QString &sParentId, CDSObject *pObject=nullptr)
CDSObject * GetChild(const QString &sID)
void SetPropValue(const QString &sName, const QString &sValue, const QString &type="")
QList< Property * > GetProperties(const QString &sName)
void SetChildContainerCount(uint32_t nCount)
Allows the caller to set childContainerCount without having to load children.
static QString TestMimeType(const QString &sFileName)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
int GetBackendStatusPort(void)
Returns the locally defined backend status port.
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
void SetRecordingStartTime(const QDateTime &dt)
std::chrono::milliseconds QueryTotalDuration(void) const
If present this loads the total duration in milliseconds of the main video stream from recordedmarkup...
void SetChanID(uint _chanid)
void AddAttribute(const QString &sName, const QString &sValue)
void SetValue(const QString &value)
Holds information on a TV Program one might wish to record.
static QString GetRecgroupString(uint recGroupID)
Temporary helper during transition from string to ID.
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
void AddAttribute(const QString &sName, const QString &sValue)
QString FindFile(const QString &filename)
void Add(CDSObject *pObject)
virtual CDSObject * GetRoot()
static QString CreateIDString(const QString &RequestId, const QString &Name, int Value)
virtual bool IsBrowseRequestForUs(UPnpCDSRequest *pRequest)
virtual bool IsSearchRequestForUs(UPnpCDSRequest *pRequest)
CDSShortCutList m_shortcuts
uint16_t m_nRequestedCount
uint16_t m_nStartingIndex
bool IsSearchRequestForUs(UPnpCDSRequest *pRequest) override
static bool LoadRecGroups(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens)
bool LoadChildren(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens, const QString ¤tToken) override
Fetch the children of the container identified in the request.
bool LoadMetadata(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens, const QString ¤tToken) override
Fetch just the metadata for the item identified in the request.
static void BindValues(MSqlQuery &query, IDTokenMap tokens)
void CreateRoot() override
static bool LoadDates(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens)
bool LoadTitles(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens)
static bool LoadGenres(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens)
static bool LoadChannels(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, const IDTokenMap &tokens)
QStringMap m_mapBackendIp
static QString BuildWhereClause(QStringList clauses, IDTokenMap tokens)
QMap< QString, int > m_mapBackendPort
bool LoadRecordings(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, IDTokenMap tokens)
static void PopulateArtworkURIS(CDSObject *pItem, const QString &sInetRef, int nSeason, const QUrl &URIBase)
bool IsBrowseRequestForUs(UPnpCDSRequest *pRequest) override
bool LoadMovies(const UPnpCDSRequest *pRequest, UPnpCDSExtensionResults *pResults, IDTokenMap tokens)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
QString ProtocolInfoString(UPNPProtocol::TransferProtocol protocol, const QString &mimeType, const QSize resolution, double videoFrameRate, const QString &container, const QString &videoCodec, const QString &audioCodec, bool isTranscoded)
Create a properly formatted string for the 4th field of res@protocolInfo.
QDateTime as_utc(const QDateTime &old_dt)
Returns copy of QDateTime with TimeSpec set to UTC.
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
@ kDateFull
Default local time.
@ kAutoYear
Add year only if different from current year.
QString resDurationFormat(std::chrono::milliseconds msec)
res@duration Format B.2.1.4 res@duration - UPnP ContentDirectory Service 2008, 2013
QString NamedDayFormat(const QDateTime &dateTime)
Named-Day Format.
QString DurationFormat(std::chrono::milliseconds msec)
Duration Format.
QString DateTimeFormat(const QDateTime &dateTime)
Date-Time Format.
QMap< QString, QString > IDTokenMap