21#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
22#include <QStringConverter>
36#include "libmythbase/mythversion.h"
60 qRegisterMetaType<Preformat*>(
"Preformat");
61 qRegisterMetaType<V2MachineInfo*>(
"V2MachineInfo");
62 qRegisterMetaType<V2BackendStatus*>(
"V2BackendStatus");
63 qRegisterMetaType<V2Encoder*>(
"V2Encoder");
64 qRegisterMetaType<V2Program*>(
"V2Program");
65 qRegisterMetaType<V2Frontend*>(
"V2Frontend");
66 qRegisterMetaType<V2StorageGroup*>(
"V2StorageGroup");
67 qRegisterMetaType<V2Job*>(
"V2Job");
68 qRegisterMetaType<V2ChannelInfo*>(
"V2ChannelInfo");
69 qRegisterMetaType<V2RecordingInfo*>(
"V2RecordingInfo");
70 qRegisterMetaType<V2ArtworkInfoList*>(
"V2ArtworkInfoList");
71 qRegisterMetaType<V2ArtworkInfo*>(
"V2ArtworkInfo");
72 qRegisterMetaType<V2CastMemberList*>(
"V2CastMemberList");
73 qRegisterMetaType<V2CastMember*>(
"V2CastMember");
74 qRegisterMetaType<V2Input*>(
"V2Input");
75 qRegisterMetaType<V2Backend*>(
"V2Backend");
103 QDomDocument doc(
"Status" );
105 QDomProcessingInstruction encoding =
106 doc.createProcessingInstruction(
"xml",
107 R
"(version="1.0" encoding="UTF-8")");
108 doc.appendChild(encoding);
111 pResult->setmimetype(
"application/xml");
112 pResult->setbuffer(doc.toString());
119 QDomDocument doc(
"Status" );
122 QTextStream stream( &html );
125 pResult->setmimetype(
"text/html");
126 pResult->setbuffer(html);
149 pStatus->setVersion ( MYTH_BINARY_VERSION );
150 pStatus->setProtoVer ( MYTH_PROTO_VERSION );
173 backend = pStatus->AddNewBackend();
175 backend->setName(thisHost);
180 backend->setType(
"Master");
181 QStringList backends;
183 for (
const QString&
hostname : std::as_const(backends))
188 backend = pStatus->AddNewBackend();
190 backend->setType(
"Slave");
200 backend->setType(
"Slave");
203 backend = pStatus->AddNewBackend();
204 backend->setName(masterhost);
205 backend->setIP(masterip);
206 backend->setType(
"Master");
210 QMap<int, JobQueueEntry> jobs;
211 QMap<int, JobQueueEntry>::Iterator it;
217 for (it = jobs.begin(); it != jobs.end(); ++it)
219 ProgramInfo pginfo((*it).chanid, (*it).recstartts);
223 V2Job * pJob = pStatus->AddNewJob();
225 pJob->setId( (*it).id );
226 pJob->setChanId((*it).chanid );
227 pJob->setStartTime( (*it).recstartts);
228 pJob->setStartTs( (*it).startts );
229 pJob->setInsertTime((*it).inserttime);
230 pJob->setType( (*it).type );
232 pJob->setCmds( (*it).cmds );
233 pJob->setFlags( (*it).flags );
234 pJob->setStatus( (*it).status );
236 pJob->setStatusTime( (*it).statustime);
237 pJob->setSchedRunTime( (*it).schedruntime);
238 pJob->setArgs( (*it).args );
239 if ((*it).hostname.isEmpty())
240 pJob->setHostName( QObject::tr(
"master"));
242 pJob->setHostName((*it).hostname);
243 pJob->setComment((*it).comment);
253 if (rgdAverages[0] != -1)
255 pMachineInfo->setLoadAvg1(rgdAverages[0]);
256 pMachineInfo->setLoadAvg2(rgdAverages[1]);
257 pMachineInfo->setLoadAvg3(rgdAverages[2]);
261 QDateTime GuideDataThrough;
263 query.
prepare(
"SELECT MAX(endtime) FROM program WHERE manualid = 0;");
268 pMachineInfo->setGuideStart
270 pMachineInfo->setGuideEnd(
272 pMachineInfo->setGuideStatus(
276 pMachineInfo->setGuideNext(
280 if (!GuideDataThrough.isNull())
283 pMachineInfo->setGuideThru(GuideDataThrough);
284 pMachineInfo->setGuideDays(qdtNow.daysTo(GuideDataThrough));
289 if ((!info_script.isEmpty()) && (info_script !=
"none"))
296 LOG(VB_GENERAL, LOG_ERR,
297 QString(
"Error running miscellaneous "
298 "status information script: %1").arg(info_script));
301 QByteArray input = ms.
ReadAll();
302 pStatus->setMiscellaneous(QString(input));
318 QStringList::const_iterator sit = strlist.cbegin();
319 while (sit != strlist.cend())
322 directory = *(sit++);
323 isLocalstr = *(sit++);
327 long long iTotal = (*(sit++)).toLongLong();
328 long long iUsed = (*(sit++)).toLongLong();;
329 long long iAvail = iTotal - iUsed;
335 group->setId(QString(fsID));
336 group->setTotal((
int)(iTotal>>10));
337 group->setUsed((
int)(iUsed>>10));
338 group->setFree((
int)(iAvail>>10));
339 group->setDirectory(directory);
343 long long iLiveTV = -1;
344 long long iDeleted = -1;
345 long long iExpirable = -1;
347 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
348 " WHERE recgroup = :RECGROUP;");
353 iLiveTV = query.
value(0).toLongLong();
358 iDeleted = query.
value(0).toLongLong();
360 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
361 " WHERE autoexpire = 1 "
362 " AND recgroup NOT IN ('LiveTV', 'Deleted');");
365 iExpirable = query.
value(0).toLongLong();
367 group->setLiveTV( (
int)(iLiveTV>>20) );
368 group->setDeleted( (
int)(iDeleted>>20) );
369 group->setExpirable ( (
int)(iExpirable>>20) );
381 QDomElement root = pDoc->createElement(
"Status");
382 pDoc->appendChild(root);
386 root.setAttribute(
"time" ,
388 root.setAttribute(
"ISODate" , qdtNow.toString(
Qt::ISODate) );
389 root.setAttribute(
"version" , MYTH_BINARY_VERSION );
390 root.setAttribute(
"protoVer", MYTH_PROTO_VERSION );
394 QDomElement encoders = pDoc->createElement(
"Encoders");
395 root.appendChild(encoders);
404 if (elink !=
nullptr)
406 TVState state = elink->GetState();
407 isLocal = elink->IsLocal();
409 QDomElement encoder = pDoc->createElement(
"Encoder");
410 encoders.appendChild(encoder);
412 encoder.setAttribute(
"id" , elink->GetInputID() );
413 encoder.setAttribute(
"local" ,
static_cast<int>(isLocal));
414 encoder.setAttribute(
"connected" ,
static_cast<int>(elink->IsConnected()));
415 encoder.setAttribute(
"state" , state );
416 encoder.setAttribute(
"sleepstatus" , elink->GetSleepStatus() );
422 encoder.setAttribute(
"hostname", elink->GetHostName());
424 encoder.setAttribute(
"devlabel",
427 if (elink->IsConnected())
455 encoders.setAttribute(
"count", numencoders);
459 QDomElement scheduled = pDoc->createElement(
"Scheduled");
460 root.appendChild(scheduled);
467 unsigned int iNum = 10;
468 unsigned int iNumRecordings = 0;
470 auto itProg = recordingList.begin();
471 for (; (itProg != recordingList.end()) && iNumRecordings < iNum; ++itProg)
474 ((*itProg)->GetRecordingStartTime() >=
482 while (!recordingList.empty())
486 recordingList.pop_back();
489 scheduled.setAttribute(
"count", iNumRecordings);
493 QDomElement frontends = pDoc->createElement(
"Frontends");
494 root.appendChild(frontends);
497 "urn:schemas-mythtv-org:service:MythFrontend:1");
505 frontends.setAttribute(
"count", map.size() );
506 for (
const auto & entry : std::as_const(map))
508 QDomElement fe = pDoc->createElement(
"Frontend");
509 frontends.appendChild(fe);
510 QUrl url(entry->m_sLocation);
511 fe.setAttribute(
"name", url.host());
512 fe.setAttribute(
"url", url.toString(QUrl::RemovePath));
519 QDomElement backends = pDoc->createElement(
"Backends");
520 root.appendChild(backends);
530 QDomElement mbe = pDoc->createElement(
"Backend");
531 backends.appendChild(mbe);
532 mbe.setAttribute(
"type",
"Master");
533 mbe.setAttribute(
"name", masterhost);
534 mbe.setAttribute(
"url" , masterip +
":" + QString::number(masterport));
538 "urn:schemas-mythtv-org:device:SlaveMediaServer:1");
542 QString ipaddress = QString();
551 for (
const auto & entry : std::as_const(map))
553 QUrl url(entry->m_sLocation);
554 if (url.host() != ipaddress)
557 QDomElement mbe = pDoc->createElement(
"Backend");
558 backends.appendChild(mbe);
559 mbe.setAttribute(
"type",
"Slave");
560 mbe.setAttribute(
"name", url.host());
561 mbe.setAttribute(
"url" , url.toString(QUrl::RemovePath));
567 backends.setAttribute(
"count", numbes);
571 QDomElement queue = pDoc->createElement(
"JobQueue");
572 root.appendChild(queue);
574 QMap<int, JobQueueEntry> jobs;
575 QMap<int, JobQueueEntry>::Iterator it;
581 for (it = jobs.begin(); it != jobs.end(); ++it)
583 ProgramInfo pginfo((*it).chanid, (*it).recstartts);
587 QDomElement job = pDoc->createElement(
"Job");
588 queue.appendChild(job);
590 job.setAttribute(
"id" , (*it).id );
591 job.setAttribute(
"chanId" , (*it).chanid );
592 job.setAttribute(
"startTime" ,
594 job.setAttribute(
"startTs" , (*it).startts );
595 job.setAttribute(
"insertTime",
597 job.setAttribute(
"type" , (*it).type );
598 job.setAttribute(
"cmds" , (*it).cmds );
599 job.setAttribute(
"flags" , (*it).flags );
600 job.setAttribute(
"status" , (*it).status );
601 job.setAttribute(
"statusTime",
603 job.setAttribute(
"schedTime" ,
605 job.setAttribute(
"args" , (*it).args );
607 if ((*it).hostname.isEmpty())
608 job.setAttribute(
"hostname", QObject::tr(
"master"));
610 job.setAttribute(
"hostname",(*it).hostname);
612 QDomText textNode = pDoc->createTextNode((*it).comment);
613 job.appendChild(textNode);
618 queue.setAttribute(
"count", jobs.size() );
622 QDomElement mInfo = pDoc->createElement(
"MachineInfo");
623 QDomElement storage = pDoc->createElement(
"Storage" );
624 QDomElement load = pDoc->createElement(
"Load" );
625 QDomElement guide = pDoc->createElement(
"Guide" );
627 root.appendChild (mInfo );
628 mInfo.appendChild(storage);
629 mInfo.appendChild(load );
630 mInfo.appendChild(guide );
647 QList<QDomElement> fsXML;
648 QStringList::const_iterator sit = strlist.cbegin();
649 while (sit != strlist.cend())
652 directory = *(sit++);
653 isLocalstr = *(sit++);
657 long long iTotal = (*(sit++)).toLongLong();
658 long long iUsed = (*(sit++)).toLongLong();;
659 long long iAvail = iTotal - iUsed;
664 QDomElement group = pDoc->createElement(
"Group");
666 group.setAttribute(
"id" , fsID );
667 group.setAttribute(
"total", (
int)(iTotal>>10) );
668 group.setAttribute(
"used" , (
int)(iUsed>>10) );
669 group.setAttribute(
"free" , (
int)(iAvail>>10) );
670 group.setAttribute(
"dir" , directory );
674 long long iLiveTV = -1;
675 long long iDeleted = -1;
676 long long iExpirable = -1;
678 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
679 " WHERE recgroup = :RECGROUP;");
684 iLiveTV = query.
value(0).toLongLong();
689 iDeleted = query.
value(0).toLongLong();
691 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
692 " WHERE autoexpire = 1 "
693 " AND recgroup NOT IN ('LiveTV', 'Deleted');");
696 iExpirable = query.
value(0).toLongLong();
698 group.setAttribute(
"livetv", (
int)(iLiveTV>>20) );
699 group.setAttribute(
"deleted", (
int)(iDeleted>>20) );
700 group.setAttribute(
"expirable", (
int)(iExpirable>>20) );
709 storage.appendChild(total);
710 int num_elements = fsXML.size();
711 for (
int fs_index = 0; fs_index < num_elements; fs_index++)
713 storage.appendChild(fsXML[fs_index]);
719 load.setAttribute(
"avg1", 0);
720 load.setAttribute(
"avg2", 1);
721 load.setAttribute(
"avg3", 2);
724 if (rgdAverages[0] != -1)
726 load.setAttribute(
"avg1", rgdAverages[0]);
727 load.setAttribute(
"avg2", rgdAverages[1]);
728 load.setAttribute(
"avg3", rgdAverages[2]);
734 QDateTime GuideDataThrough;
737 query.
prepare(
"SELECT MAX(endtime) FROM program WHERE manualid = 0;");
744 guide.setAttribute(
"start",
746 guide.setAttribute(
"end",
748 guide.setAttribute(
"status",
752 guide.setAttribute(
"next",
756 if (!GuideDataThrough.isNull())
758 guide.setAttribute(
"guideThru",
760 guide.setAttribute(
"guideDays", qdtNow.daysTo(GuideDataThrough));
766 if ((!info_script.isEmpty()) && (info_script !=
"none"))
768 QDomElement misc = pDoc->createElement(
"Miscellaneous");
769 root.appendChild(misc);
776 LOG(VB_GENERAL, LOG_ERR,
777 QString(
"Error running miscellaneous "
778 "status information script: %1").arg(info_script));
782 QByteArray input = ms.
ReadAll();
784 QStringList
output = QString(input).split(
'\n',
786 for (
const auto & line : std::as_const(
output))
788 QDomElement
info = pDoc->createElement(
"Information");
790 QStringList list = line.split(
"[]:[]");
791 unsigned int size = list.size();
792 unsigned int hasAttributes = 0;
794 if ((size > 0) && (!list[0].isEmpty()))
796 info.setAttribute(
"display", list[0]);
799 if ((size > 1) && (!list[1].isEmpty()))
801 info.setAttribute(
"name", list[1]);
804 if ((size > 2) && (!list[2].isEmpty()))
806 info.setAttribute(
"value", list[2]);
810 if (hasAttributes > 0)
811 misc.appendChild(
info);
822#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
823 os.setCodec(
"UTF-8");
825 os.setEncoding(QStringConverter::Utf8);
830 QDomElement docElem = pDoc->documentElement();
832 os <<
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
833 <<
"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n"
834 <<
"<html xmlns=\"http://www.w3.org/1999/xhtml\""
835 <<
" xml:lang=\"en\" lang=\"en\">\r\n"
837 <<
" <meta http-equiv=\"Content-Type\""
838 <<
"content=\"text/html; charset=UTF-8\" />\r\n"
839 <<
" <link rel=\"stylesheet\" href=\"/css/Status.css\" type=\"text/css\">\r\n"
840 <<
" <title>MythTV Status - "
844 << docElem.attribute(
"version", MYTH_BINARY_VERSION ) <<
"</title>\r\n"
846 <<
"<body bgcolor=\"#fff\">\r\n"
847 <<
"<div class=\"status\">\r\n"
848 <<
" <h1 class=\"status\">MythTV Status</h1>\r\n";
852 QDomNode node = docElem.namedItem(
"Encoders" );
859 node = docElem.namedItem(
"Scheduled" );
866 node = docElem.namedItem(
"Frontends" );
873 node = docElem.namedItem(
"Backends" );
880 node = docElem.namedItem(
"JobQueue" );
887 node = docElem.namedItem(
"MachineInfo" );
894 node = docElem.namedItem(
"Miscellaneous" );
899 os <<
"\r\n</div>\r\n</body>\r\n</html>\r\n";
909 int nNumEncoders = 0;
911 if (encoders.isNull())
914 os <<
" <div class=\"content\">\r\n"
915 <<
" <h2 class=\"status\">Encoder Status</h2>\r\n";
917 QDomNode node = encoders.firstChild();
919 while (!node.isNull())
921 QDomElement e = node.toElement();
925 if (e.tagName() ==
"Encoder")
927 QString sIsLocal = (e.attribute(
"local" ,
"remote" )==
"1")
928 ?
"local" :
"remote";
929 QString sCardId = e.attribute(
"id" ,
"0" );
930 QString sHostName = e.attribute(
"hostname" ,
"Unknown");
931 bool bConnected=
static_cast<bool>(e.attribute(
"connected",
"0" ).toInt());
933 bool bIsLowOnFreeSpace=
static_cast<bool>(e.attribute(
"lowOnFreeSpace",
"0").toInt());
935 QString sDevlabel = e.attribute(
"devlabel",
"[ UNKNOWN ]");
937 os <<
" Encoder " << sCardId <<
" " << sDevlabel
938 <<
" is " << sIsLocal <<
" on " << sHostName;
940 if ((sIsLocal ==
"remote") && !bConnected)
947 os <<
" (currently asleep).<br />";
949 os <<
" (currently not connected).<br />";
951 node = node.nextSibling();
962 os <<
" and is watching Live TV";
967 os <<
" and is recording";
971 os <<
" and is not recording.";
977 QDomNode tmpNode = e.namedItem(
"Program" );
979 if (!tmpNode.isNull())
981 QDomElement program = tmpNode.toElement();
983 if (!program.isNull())
985 os <<
" '" << program.attribute(
"title",
"Unknown" ) <<
"'";
989 tmpNode = program.namedItem(
"Channel" );
991 if (!tmpNode.isNull())
993 QDomElement channel = tmpNode.toElement();
995 if (!channel.isNull())
997 << channel.attribute(
"callSign",
"unknown" );
1002 tmpNode = program.namedItem(
"Recording" );
1004 if (!tmpNode.isNull())
1006 QDomElement recording = tmpNode.toElement();
1008 if (!recording.isNull())
1011 recording.attribute(
"recEndTs",
"" ));
1013 os <<
". This recording ";
1019 os <<
"scheduled to end at "
1029 if (bIsLowOnFreeSpace)
1031 os <<
" <strong>WARNING</strong>:"
1032 <<
" This backend is low on free disk space!";
1039 node = node.nextSibling();
1042 os <<
" </div>\r\n\r\n";
1044 return( nNumEncoders );
1055 if (scheduled.isNull())
1058 int nNumRecordings= scheduled.attribute(
"count",
"0" ).toInt();
1060 os <<
" <div class=\"content\">\r\n"
1061 <<
" <h2 class=\"status\">Schedule</h2>\r\n";
1063 if (nNumRecordings == 0)
1065 os <<
" There are no shows scheduled for recording.\r\n"
1070 os <<
" The next " << nNumRecordings <<
" show" << (nNumRecordings == 1 ?
"" :
"s" )
1071 <<
" that " << (nNumRecordings == 1 ?
"is" :
"are")
1072 <<
" scheduled for recording:\r\n";
1074 os <<
" <div class=\"schedule\">\r\n";
1078 QDomNode node = scheduled.firstChild();
1080 while (!node.isNull())
1082 QDomElement e = node.toElement();
1086 QDomNode recNode = e.namedItem(
"Recording" );
1087 QDomNode chanNode = e.namedItem(
"Channel" );
1089 if ((e.tagName() ==
"Program") && !recNode.isNull() &&
1092 QDomElement r = recNode.toElement();
1093 QDomElement c = chanNode.toElement();
1095 QString sTitle = e.attribute(
"title" ,
"" );
1096 QString sSubTitle = e.attribute(
"subTitle",
"" );
1102 int nPreRollSecs = r.attribute(
"preRollSeconds",
"0" ).toInt();
1103 int nEncoderId = r.attribute(
"encoderId" ,
"0" ).toInt();
1104 QString sProfile = r.attribute(
"recProfile" ,
"" );
1105 QString sChanName = c.attribute(
"channelName" ,
"" );
1108 QDomText text = e.firstChild().toText();
1110 sDesc = text.nodeValue();
1114 int nTotalSecs = qdtNow.secsTo( recStartTs ) - nPreRollSecs;
1120 int nTotalDays = nTotalSecs / 86400;
1121 int nTotalHours = (nTotalSecs / 3600)
1122 - (nTotalDays * 24);
1123 int nTotalMins = (nTotalSecs / 60) % 60;
1125 QString sTimeToStart =
"in";
1127 sTimeToStart += QObject::tr(
" %n day(s),",
"", nTotalDays );
1128 sTimeToStart += QObject::tr(
" %n hour(s) and",
"", nTotalHours);
1129 sTimeToStart += QObject::tr(
" %n minute(s)",
"", nTotalMins);
1131 if ( nTotalHours == 0 && nTotalMins == 0)
1132 sTimeToStart = QObject::tr(
"within one minute",
"Recording starting");
1134 if ( nTotalSecs < 0)
1135 sTimeToStart = QObject::tr(
"soon",
"Recording starting");
1139 os <<
" <a href=\"#\">";
1147 os <<
"Encoder " << nEncoderId <<
" - ";
1149 os << sChanName <<
" - " << sTitle <<
"<br />"
1150 <<
"<span><strong>" << sTitle <<
"</strong> ("
1154 if ( !sSubTitle.isEmpty())
1155 os <<
"<em>" << sSubTitle <<
"</em><br /><br />";
1157 if ( airDate.isValid())
1159 os <<
"Orig. Airdate: "
1165 os << sDesc <<
"<br /><br />"
1166 <<
"This recording will start " << sTimeToStart
1167 <<
" using encoder " << nEncoderId <<
" with the '"
1168 << sProfile <<
"' profile.</span></a><hr />\r\n";
1172 node = node.nextSibling();
1174 os <<
" </div>\r\n";
1175 os <<
" </div>\r\n\r\n";
1177 return( nNumRecordings );
1186 if (frontends.isNull())
1189 int nNumFES= frontends.attribute(
"count",
"0" ).toInt();
1195 os <<
" <div class=\"content\">\r\n"
1196 <<
" <h2 class=\"status\">Frontends</h2>\r\n";
1198 QDomNode node = frontends.firstChild();
1199 while (!node.isNull())
1201 QDomElement e = node.toElement();
1205 QString name = e.attribute(
"name" ,
"" );
1206 QString url = e.attribute(
"url" ,
"" );
1207 os << name <<
" (<a href=\"" << url <<
"\">Status page</a>)<br />";
1210 node = node.nextSibling();
1213 os <<
" </div>\r\n\r\n";
1224 if (backends.isNull())
1227 int nNumBES= backends.attribute(
"count",
"0" ).toInt();
1233 os <<
" <div class=\"content\">\r\n"
1234 <<
" <h2 class=\"status\">Other Backends</h2>\r\n";
1236 QDomNode node = backends.firstChild();
1237 while (!node.isNull())
1239 QDomElement e = node.toElement();
1243 QString
type = e.attribute(
"type",
"" );
1244 QString name = e.attribute(
"name" ,
"" );
1245 QString url = e.attribute(
"url" ,
"" );
1246 os <<
type <<
": " << name <<
" (<a href=\"" << url <<
"\">Status page</a>)<br />";
1249 node = node.nextSibling();
1252 os <<
" </div>\r\n\r\n";
1266 int nNumJobs= jobs.attribute(
"count",
"0" ).toInt();
1268 os <<
" <div class=\"content\">\r\n"
1269 <<
" <h2 class=\"status\">Job Queue</h2>\r\n";
1273 QString statusColor;
1276 os <<
" Jobs currently in Queue or recently ended:\r\n<br />"
1277 <<
" <div class=\"schedule\">\r\n";
1280 QDomNode node = jobs.firstChild();
1282 while (!node.isNull())
1284 QDomElement e = node.toElement();
1288 QDomNode progNode = e.namedItem(
"Program" );
1290 if ((e.tagName() ==
"Job") && !progNode.isNull() )
1292 QDomElement
p = progNode.toElement();
1294 QDomNode recNode =
p.namedItem(
"Recording" );
1295 QDomNode chanNode =
p.namedItem(
"Channel" );
1297 QDomElement r = recNode.toElement();
1298 QDomElement c = chanNode.toElement();
1300 int nType = e.attribute(
"type" ,
"0" ).toInt();
1301 int nStatus = e.attribute(
"status",
"0" ).toInt();
1306 statusColor =
" class=\"jobaborted\"";
1311 statusColor =
" class=\"joberrored\"";
1312 jobColor =
" class=\"joberrored\"";
1316 statusColor =
" class=\"jobfinished\"";
1317 jobColor =
" class=\"jobfinished\"";
1321 statusColor =
" class=\"jobrunning\"";
1322 jobColor =
" class=\"jobrunning\"";
1326 statusColor =
" class=\"jobqueued\"";
1327 jobColor =
" class=\"jobqueued\"";
1331 QString sTitle =
p.attribute(
"title" ,
"" );
1332 QString sSubTitle =
p.attribute(
"subTitle",
"" );
1338 QString sHostname = e.attribute(
"hostname",
"master" );
1339 QString sComment =
"";
1341 QDomText text = e.firstChild().toText();
1343 sComment = text.nodeValue();
1345 os <<
"<a href=\"javascript:void(0)\">"
1349 << sTitle <<
" - <font" << jobColor <<
">"
1351 <<
"<span><strong>" << sTitle <<
"</strong> ("
1355 if (!sSubTitle.isEmpty())
1356 os <<
"<em>" << sSubTitle <<
"</em><br /><br />";
1362 os <<
"Scheduled Run Time: "
1369 os <<
"Status: <font" << statusColor <<
">"
1377 if ( nStatus != JOB_QUEUED)
1378 os <<
"Host: " << sHostname <<
"<br />";
1380 if (!sComment.isEmpty())
1381 os <<
"<br />Comments:<br />" << sComment <<
"<br />";
1383 os <<
"</span></a><hr />\r\n";
1387 node = node.nextSibling();
1389 os <<
" </div>\r\n";
1393 os <<
" Job Queue is currently empty.\r\n\r\n";
1396 os <<
" </div>\r\n\r\n ";
1413 os <<
"<div class=\"content\">\r\n"
1414 <<
" <h2 class=\"status\">Machine Information</h2>\r\n";
1418 QDomNode node =
info.namedItem(
"Load" );
1422 QDomElement e = node.toElement();
1426 double dAvg1 = e.attribute(
"avg1" ,
"0" ).toDouble();
1427 double dAvg2 = e.attribute(
"avg2" ,
"0" ).toDouble();
1428 double dAvg3 = e.attribute(
"avg3" ,
"0" ).toDouble();
1430 os <<
" <div class=\"loadstatus\">\r\n"
1431 <<
" This machine's load average:"
1432 <<
"\r\n <ul>\r\n <li>"
1433 <<
"1 Minute: " << dAvg1 <<
"</li>\r\n"
1434 <<
" <li>5 Minutes: " << dAvg2 <<
"</li>\r\n"
1435 <<
" <li>15 Minutes: " << dAvg3
1436 <<
"</li>\r\n </ul>\r\n"
1442 node =
info.namedItem(
"Storage" );
1443 QDomElement storage = node.toElement();
1444 node = storage.firstChild();
1449 while (!node.isNull())
1451 QDomElement g = node.toElement();
1453 if (!g.isNull() && g.tagName() ==
"Group")
1455 QString
id = g.attribute(
"id",
"" );
1459 int nFree = g.attribute(
"free" ,
"0" ).toInt();
1460 int nTotal = g.attribute(
"total",
"0" ).toInt();
1461 int nUsed = g.attribute(
"used" ,
"0" ).toInt();
1462 int nLiveTV = g.attribute(
"livetv" ,
"0" ).toInt();
1463 int nDeleted = g.attribute(
"deleted",
"0" ).toInt();
1464 int nExpirable = g.attribute(
"expirable" ,
"0" ).toInt();
1465 QString nDir = g.attribute(
"dir" ,
"" );
1467 nDir.replace(
",",
", ");
1469 os <<
" Disk Usage Summary:<br />\r\n";
1472 os <<
" <li>Total Disk Space:\r\n"
1475 os <<
" <li>Total Space: ";
1476 sRep = QString(
"%L1").arg(nTotal) +
" MB";
1477 os << sRep <<
"</li>\r\n";
1479 os <<
" <li>Space Used: ";
1480 sRep = QString(
"%L1").arg(nUsed) +
" MB";
1481 os << sRep <<
"</li>\r\n";
1483 os <<
" <li>Space Free: ";
1484 sRep = QString(
"%L1").arg(nFree) +
" MB";
1485 os << sRep <<
"</li>\r\n";
1487 if ((nLiveTV + nDeleted + nExpirable) > 0)
1489 os <<
" <li>Space Available "
1490 "After Auto-expire: ";
1491 sRep = QString(
"%L1").arg(nUsed) +
" MB";
1492 sRep = QString(
"%L1").arg(nFree + nLiveTV +
1493 nDeleted + nExpirable) +
" MB";
1494 os << sRep <<
"\r\n";
1496 os <<
" <li>Space Used by LiveTV: ";
1497 sRep = QString(
"%L1").arg(nLiveTV) +
" MB";
1498 os << sRep <<
"</li>\r\n";
1499 os <<
" <li>Space Used by "
1500 "Deleted Recordings: ";
1501 sRep = QString(
"%L1").arg(nDeleted) +
" MB";
1502 os << sRep <<
"</li>\r\n";
1503 os <<
" <li>Space Used by "
1504 "Auto-expirable Recordings: ";
1505 sRep = QString(
"%L1").arg(nExpirable) +
" MB";
1506 os << sRep <<
"</li>\r\n";
1519 node = node.nextSibling();
1523 node = storage.firstChild();
1525 os <<
" Disk Usage Details:<br />\r\n";
1529 while (!node.isNull())
1531 QDomElement g = node.toElement();
1533 if (!g.isNull() && g.tagName() ==
"Group")
1535 int nFree = g.attribute(
"free" ,
"0" ).toInt();
1536 int nTotal = g.attribute(
"total",
"0" ).toInt();
1537 int nUsed = g.attribute(
"used" ,
"0" ).toInt();
1538 QString nDir = g.attribute(
"dir" ,
"" );
1539 QString
id = g.attribute(
"id" ,
"" );
1541 nDir.replace(
",",
", ");
1547 os <<
" <li>MythTV Drive #" <<
id <<
":"
1551 if (nDir.contains(
','))
1552 os <<
" <li>Directories: ";
1554 os <<
" <li>Directory: ";
1556 os << nDir <<
"</li>\r\n";
1558 os <<
" <li>Total Space: ";
1559 sRep = QString(
"%L1").arg(nTotal) +
" MB";
1560 os << sRep <<
"</li>\r\n";
1562 os <<
" <li>Space Used: ";
1563 sRep = QString(
"%L1").arg(nUsed) +
" MB";
1564 os << sRep <<
"</li>\r\n";
1566 os <<
" <li>Space Free: ";
1567 sRep = QString(
"%L1").arg(nFree) +
" MB";
1568 os << sRep <<
"</li>\r\n";
1576 node = node.nextSibling();
1583 node =
info.namedItem(
"Guide" );
1587 QDomElement e = node.toElement();
1591 int nDays = e.attribute(
"guideDays",
"0" ).toInt();
1592 QString sStart = e.attribute(
"start" ,
"" );
1593 QString sEnd = e.attribute(
"end" ,
"" );
1594 QString sStatus = e.attribute(
"status" ,
"" );
1596 QString sNext = next.isNull() ?
"" :
1602 QDomText text = e.firstChild().toText();
1609 sMsg = text.nodeValue();
1611 os <<
" Last mythfilldatabase run started on " << sStart
1617 os <<
"ended on " << sEnd <<
". ";
1619 os << sStatus <<
"<br />\r\n";
1621 if (!next.isNull() && next >= lastrunstart)
1623 os <<
" Suggested next mythfilldatabase run: "
1624 << sNext <<
".<br />\r\n";
1629 os <<
" There's guide data until "
1633 os <<
" " << QObject::tr(
"(%n day(s))",
"", nDays);
1638 os <<
" <strong>WARNING</strong>: is mythfilldatabase running?";
1642 os <<
" There's <strong>no guide data</strong> available! "
1643 <<
"Have you run mythfilldatabase?";
1647 os <<
"\r\n </div>\r\n";
1659 QDomNodeList nodes =
info.elementsByTagName(
"Information");
1660 uint count = nodes.count();
1666 os <<
"<div class=\"content\">\r\n"
1667 <<
" <h2 class=\"status\">Miscellaneous</h2>\r\n";
1668 for (
unsigned int i = 0; i < count; i++)
1670 QDomNode node = nodes.item(i);
1674 QDomElement e = node.toElement();
1678 display = e.attribute(
"display",
"");
1682 if (display.isEmpty())
1687 if (display.contains(
"<p>", Qt::CaseInsensitive) ||
1688 display.contains(
"<br", Qt::CaseInsensitive))
1695 linebreak =
"<br />\r\n";
1698 os <<
" " << display << linebreak;
1712 if ((pDoc ==
nullptr) || (pInfo ==
nullptr))
1717 QDomElement program = pDoc->createElement(
"Program" );
1718 node.appendChild( program );
1720 program.setAttribute(
"startTime" ,
1723 program.setAttribute(
"title" , pInfo->
GetTitle() );
1724 program.setAttribute(
"subTitle" , pInfo->
GetSubtitle());
1725 program.setAttribute(
"category" , pInfo->
GetCategory());
1727 program.setAttribute(
"repeat" ,
static_cast<int>(pInfo->
IsRepeat()));
1732 program.setAttribute(
"seriesId" , pInfo->
GetSeriesID() );
1733 program.setAttribute(
"programId" , pInfo->
GetProgramID() );
1734 program.setAttribute(
"stars" , pInfo->
GetStars() );
1735 program.setAttribute(
"fileSize" ,
1737 program.setAttribute(
"lastModified",
1740 program.setAttribute(
"hostname" , pInfo->
GetHostname() );
1743 program.setAttribute(
1746 QDomText textNode = pDoc->createTextNode( pInfo->
GetDescription() );
1747 program.appendChild( textNode );
1755 QDomElement channel = pDoc->createElement(
"Channel" );
1756 program.appendChild( channel );
1765 QDomElement recording = pDoc->createElement(
"Recording" );
1766 program.appendChild( recording );
1768 recording.setAttribute(
"recStatus" ,
1770 recording.setAttribute(
"recPriority" ,
1772 recording.setAttribute(
"recStartTs" ,
1774 recording.setAttribute(
"recEndTs" ,
1779 recording.setAttribute(
"recordId" ,
1781 recording.setAttribute(
"recGroup" ,
1783 recording.setAttribute(
"playGroup" ,
1785 recording.setAttribute(
"recType" ,
1787 recording.setAttribute(
"dupInType" ,
1789 recording.setAttribute(
"dupMethod" ,
1791 recording.setAttribute(
"encoderId" ,
1794 recording.setAttribute(
"recProfile" ,
1821 channel.setAttribute(
"chanId" , pInfo->
GetChanID() );
1822 channel.setAttribute(
"chanNum" , pInfo->
GetChanNum());
1829 channel.setAttribute(
"chanFilters",
1831 channel.setAttribute(
"sourceId" , pInfo->
GetSourceID() );
1832 channel.setAttribute(
"inputId" , pInfo->
GetInputID() );
1833 channel.setAttribute(
"commFree" ,
QMap< int, EncoderLink * > gTVList
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
static int GetJobsInQueue(QMap< int, JobQueueEntry > &jobs, int findJobs=JOB_LIST_NOT_DONE)
static QString JobText(int jobType)
static QString StatusText(int status)
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.
void BackendQueryDiskSpace(QStringList &strlist, bool consolidated, bool allHosts)
void GetActiveBackends(QStringList &hosts)
PlaybackSock * GetMediaServerByHostname(const QString &hostname)
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
QString GetHostName(void)
QString GetSetting(const QString &key, const QString &defaultval="")
int GetMasterServerStatusPort(void)
Returns the Master Backend status port If no master server status port has been defined in the databa...
bool IsMasterHost(void)
is this the same host as the master
int GetNumSetting(const QString &key, int defaultval=0)
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
QString GetMasterHostName(void)
bool IsMasterBackend(void)
is this the actual MBE process
bool GetBoolSetting(const QString &key, bool defaultval=false)
uint Wait(std::chrono::seconds timeout=0s)
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
void setIP(const QString &lip)
QString getIP(void) const
Holds information on recordings and videos.
float GetStars(void) const
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
uint GetRecordingRuleID(void) const
RecordingDupMethodType GetDuplicateCheckMethod(void) const
What should be compared to determine if two programs are the same?
QString GetSeriesID(void) const
QString GetCategoryTypeString(void) const
Returns catType as a string.
QString GetProgramID(void) const
QString GetRecordingGroup(void) const
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
QString GetChannelPlaybackFilters(void) const
RecordingDupInType GetDuplicateCheckSource(void) const
Where should we check for duplicates?
bool IsRepeat(void) const
QString GetHostname(void) const
uint GetSourceID(void) const
QString GetPlaybackGroup(void) const
QString GetDescription(void) const
QDateTime GetLastModifiedTime(void) const
QString GetChannelName(void) const
This is the channel name in the local market, i.e.
QString GetTitle(void) const
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
bool IsCommercialFree(void) const
int GetRecordingPriority(void) const
QDate GetOriginalAirDate(void) const
uint GetInputID(void) const
virtual uint64_t GetFilesize(void) const
uint32_t GetProgramFlags(void) const
RecStatus::Type GetRecordingStatus(void) const
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
QString GetSubtitle(void) const
QString GetCategory(void) const
RecordingType GetRecordingRuleType(void) const
QString GetChannelSchedulingID(void) const
This is the unique programming identifier of a channel.
Holds information on a TV Program one might wish to record.
QString GetProgramRecordingProfile(void) const
Returns recording profile name that will be, or was used, for this program, creating "record" field i...
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
void GetEntryMap(EntryMap &map)
Returns a copy of the EntryMap.
static SSDPCache * Instance()
SSDPCacheEntries * Find(const QString &sURI)
Finds the SSDPCacheEntries in the cache, returns nullptr when absent.
MainServer * GetMainServer()
bool GetAllPending(RecList &retList, int recRuleId=0) const
static QReadWriteLock s_inputsLock
static QList< QHostAddress > g_IPAddrList
V2StorageGroup * AddNewStorageGroup()
static void PrintStatus(QTextStream &os, QDomDocument *pDoc)
static void FillChannelInfo(QDomElement &channel, ProgramInfo *pInfo, bool bDetails=true)
QMap< int, EncoderLink * > * m_pEncoders
static int PrintBackends(QTextStream &os, const QDomElement &backends)
static void FillProgramInfo(QDomDocument *pDoc, QDomNode &node, ProgramInfo *pInfo, bool bIncChannel=true, bool bDetails=true)
static int PrintEncoderStatus(QTextStream &os, const QDomElement &encoders)
MainServer * m_pMainServer
static int PrintMiscellaneousInfo(QTextStream &os, const QDomElement &info)
Preformat * GetStatusHTML()
static int PrintFrontends(QTextStream &os, const QDomElement &frontends)
static int PrintScheduled(QTextStream &os, const QDomElement &scheduled)
static int PrintMachineInfo(QTextStream &os, const QDomElement &info)
void FillStatusXML(QDomDocument *pDoc)
void FillDriveSpace(V2MachineInfo *pMachineInfo)
static int PrintJobQueue(QTextStream &os, const QDomElement &jobs)
static void RegisterCustomTypes()
V2BackendStatus * GetBackendStatus()
@ GENERIC_EXIT_OK
Exited with no error.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
loadArray getLoadAvgs(void)
Returns the system load averages.
std::array< double, 3 > loadArray
std::deque< RecordingInfo * > RecList
@ kMSStdOut
allow access to stdout
@ kMSRunShell
run process through shell
const char * GetMythSourceVersion()
const char * GetMythSourcePath()
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
@ kDateTimeFull
Default local time.
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
@ kDateFull
Default local time.
@ kTime
Default local time.
@ kAddYear
Add year to string if not included.
@ kDateShort
Default local time.
@ kDatabase
Default UTC, database format.
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
QMap< QString, DeviceLocation * > EntryMap
Key == Unique Service Name (USN)
SleepStatus
SleepStatus is an enumeration of the awake/sleep status of a slave.
@ sStatus_Asleep
A slave is considered asleep when it is not awake and not undefined.
@ sStatus_Undefined
A slave's sleep status is undefined when it has never connected to the master backend or is not able ...
TVState
TVState is an enumeration of the states used by TV and TVRec.
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
void FillEncoderList(QVariantList &list, QObject *parent)
void FillFrontendList(QVariantList &list, QObject *parent, bool OnLine)
void V2FillProgramInfo(V2Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast, bool bIncArtwork, bool bIncRecording)
int FillUpcomingList(QVariantList &list, QObject *parent, int &nStartIndex, int &nCount, bool bShowAll, int nRecordId, int nRecStatus, const QString &Sort, const QString &RecGroup)
static QDateTime setting_to_qdatetime(const char *setting)
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(STATUS_HANDLE, V2Status::staticMetaObject, &V2Status::RegisterCustomTypes)) void V2Status
static QString setting_to_localtime(const char *setting)