21 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
22 #include <QStringConverter>
24 #include <QTextStream>
30 #include "libmythbase/mythconfig.h"
36 #include "libmythbase/mythversion.h"
59 qRegisterMetaType<Preformat*>(
"Preformat");
60 qRegisterMetaType<V2MachineInfo*>(
"V2MachineInfo");
61 qRegisterMetaType<V2BackendStatus*>(
"V2BackendStatus");
62 qRegisterMetaType<V2Encoder*>(
"V2Encoder");
63 qRegisterMetaType<V2Program*>(
"V2Program");
64 qRegisterMetaType<V2Frontend*>(
"V2Frontend");
65 qRegisterMetaType<V2StorageGroup*>(
"V2StorageGroup");
66 qRegisterMetaType<V2Job*>(
"V2Job");
67 qRegisterMetaType<V2ChannelInfo*>(
"V2ChannelInfo");
68 qRegisterMetaType<V2RecordingInfo*>(
"V2RecordingInfo");
69 qRegisterMetaType<V2ArtworkInfoList*>(
"V2ArtworkInfoList");
70 qRegisterMetaType<V2ArtworkInfo*>(
"V2ArtworkInfo");
71 qRegisterMetaType<V2CastMemberList*>(
"V2CastMemberList");
72 qRegisterMetaType<V2CastMember*>(
"V2CastMember");
73 qRegisterMetaType<V2Input*>(
"V2Input");
74 qRegisterMetaType<V2Backend*>(
"V2Backend");
102 QDomDocument doc(
"Status" );
104 QDomProcessingInstruction encoding =
105 doc.createProcessingInstruction(
"xml",
106 R
"(version="1.0" encoding="UTF-8")");
107 doc.appendChild(encoding);
110 pResult->setmimetype(
"application/xml");
111 pResult->setbuffer(doc.toString());
118 QDomDocument doc(
"Status" );
121 QTextStream stream( &html );
124 pResult->setmimetype(
"text/html");
125 pResult->setbuffer(html);
148 pStatus->setVersion ( MYTH_BINARY_VERSION );
149 pStatus->setProtoVer ( MYTH_PROTO_VERSION );
169 backend = pStatus->AddNewBackend();
171 backend->setName(thisHost);
176 backend->setType(
"Master");
177 QStringList backends;
179 for (
const QString&
hostname : qAsConst(backends))
184 backend = pStatus->AddNewBackend();
186 backend->setType(
"Slave");
196 backend->setType(
"Slave");
199 backend = pStatus->AddNewBackend();
200 backend->setName(masterhost);
201 backend->setIP(masterip);
202 backend->setType(
"Master");
206 QMap<int, JobQueueEntry> jobs;
207 QMap<int, JobQueueEntry>::Iterator it;
213 for (it = jobs.begin(); it != jobs.end(); ++it)
215 ProgramInfo pginfo((*it).chanid, (*it).recstartts);
219 V2Job * pJob = pStatus->AddNewJob();
221 pJob->setId( (*it).id );
222 pJob->setChanId((*it).chanid );
223 pJob->setStartTime( (*it).recstartts);
224 pJob->setStartTs( (*it).startts );
225 pJob->setInsertTime((*it).inserttime);
226 pJob->setType( (*it).type );
228 pJob->setCmds( (*it).cmds );
229 pJob->setFlags( (*it).flags );
230 pJob->setStatus( (*it).status );
232 pJob->setStatusTime( (*it).statustime);
233 pJob->setSchedRunTime( (*it).schedruntime);
234 pJob->setArgs( (*it).args );
235 if ((*it).hostname.isEmpty())
236 pJob->setHostName( QObject::tr(
"master"));
238 pJob->setHostName((*it).hostname);
239 pJob->setComment((*it).comment);
249 if (rgdAverages[0] != -1)
251 pMachineInfo->setLoadAvg1(rgdAverages[0]);
252 pMachineInfo->setLoadAvg2(rgdAverages[1]);
253 pMachineInfo->setLoadAvg3(rgdAverages[2]);
257 QDateTime GuideDataThrough;
259 query.
prepare(
"SELECT MAX(endtime) FROM program WHERE manualid = 0;");
264 pMachineInfo->setGuideStart
266 pMachineInfo->setGuideEnd(
268 pMachineInfo->setGuideStatus(
272 pMachineInfo->setGuideNext(
276 if (!GuideDataThrough.isNull())
279 pMachineInfo->setGuideThru(GuideDataThrough);
280 pMachineInfo->setGuideDays(qdtNow.daysTo(GuideDataThrough));
285 if ((!info_script.isEmpty()) && (info_script !=
"none"))
292 LOG(VB_GENERAL, LOG_ERR,
293 QString(
"Error running miscellaneous "
294 "status information script: %1").arg(info_script));
297 QByteArray input = ms.
ReadAll();
298 pStatus->setMiscellaneous(QString(input));
314 QStringList::const_iterator sit = strlist.cbegin();
315 while (sit != strlist.cend())
318 directory = *(sit++);
319 isLocalstr = *(sit++);
323 long long iTotal = (*(sit++)).toLongLong();
324 long long iUsed = (*(sit++)).toLongLong();;
325 long long iAvail = iTotal - iUsed;
331 group->setId(QString(fsID));
332 group->setTotal((
int)(iTotal>>10));
333 group->setUsed((
int)(iUsed>>10));
334 group->setFree((
int)(iAvail>>10));
335 group->setDirectory(directory);
339 long long iLiveTV = -1;
340 long long iDeleted = -1;
341 long long iExpirable = -1;
343 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
344 " WHERE recgroup = :RECGROUP;");
349 iLiveTV = query.
value(0).toLongLong();
354 iDeleted = query.
value(0).toLongLong();
356 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
357 " WHERE autoexpire = 1 "
358 " AND recgroup NOT IN ('LiveTV', 'Deleted');");
361 iExpirable = query.
value(0).toLongLong();
363 group->setLiveTV( (
int)(iLiveTV>>20) );
364 group->setDeleted( (
int)(iDeleted>>20) );
365 group->setExpirable ( (
int)(iExpirable>>20) );
377 QDomElement root = pDoc->createElement(
"Status");
378 pDoc->appendChild(root);
382 root.setAttribute(
"time" ,
384 root.setAttribute(
"ISODate" , qdtNow.toString(
Qt::ISODate) );
385 root.setAttribute(
"version" , MYTH_BINARY_VERSION );
386 root.setAttribute(
"protoVer", MYTH_PROTO_VERSION );
390 QDomElement encoders = pDoc->createElement(
"Encoders");
391 root.appendChild(encoders);
400 if (elink !=
nullptr)
402 TVState state = elink->GetState();
403 isLocal = elink->IsLocal();
405 QDomElement encoder = pDoc->createElement(
"Encoder");
406 encoders.appendChild(encoder);
408 encoder.setAttribute(
"id" , elink->GetInputID() );
409 encoder.setAttribute(
"local" ,
static_cast<int>(isLocal));
410 encoder.setAttribute(
"connected" ,
static_cast<int>(elink->IsConnected()));
411 encoder.setAttribute(
"state" , state );
412 encoder.setAttribute(
"sleepstatus" , elink->GetSleepStatus() );
418 encoder.setAttribute(
"hostname", elink->GetHostName());
420 encoder.setAttribute(
"devlabel",
423 if (elink->IsConnected())
451 encoders.setAttribute(
"count", numencoders);
455 QDomElement scheduled = pDoc->createElement(
"Scheduled");
456 root.appendChild(scheduled);
463 unsigned int iNum = 10;
464 unsigned int iNumRecordings = 0;
466 auto itProg = recordingList.begin();
467 for (; (itProg != recordingList.end()) && iNumRecordings < iNum; ++itProg)
470 ((*itProg)->GetRecordingStartTime() >=
478 while (!recordingList.empty())
482 recordingList.pop_back();
485 scheduled.setAttribute(
"count", iNumRecordings);
489 QDomElement frontends = pDoc->createElement(
"Frontends");
490 root.appendChild(frontends);
493 "urn:schemas-mythtv-org:service:MythFrontend:1");
501 frontends.setAttribute(
"count", map.size() );
502 for (
const auto & entry : qAsConst(map))
504 QDomElement fe = pDoc->createElement(
"Frontend");
505 frontends.appendChild(fe);
506 QUrl url(entry->m_sLocation);
507 fe.setAttribute(
"name", url.host());
508 fe.setAttribute(
"url", url.toString(QUrl::RemovePath));
515 QDomElement backends = pDoc->createElement(
"Backends");
516 root.appendChild(backends);
526 QDomElement mbe = pDoc->createElement(
"Backend");
527 backends.appendChild(mbe);
528 mbe.setAttribute(
"type",
"Master");
529 mbe.setAttribute(
"name", masterhost);
530 mbe.setAttribute(
"url" , masterip +
":" + QString::number(masterport));
534 "urn:schemas-mythtv-org:device:SlaveMediaServer:1");
538 QString ipaddress = QString();
547 for (
const auto & entry : qAsConst(map))
549 QUrl url(entry->m_sLocation);
550 if (url.host() != ipaddress)
553 QDomElement mbe = pDoc->createElement(
"Backend");
554 backends.appendChild(mbe);
555 mbe.setAttribute(
"type",
"Slave");
556 mbe.setAttribute(
"name", url.host());
557 mbe.setAttribute(
"url" , url.toString(QUrl::RemovePath));
563 backends.setAttribute(
"count", numbes);
567 QDomElement queue = pDoc->createElement(
"JobQueue");
568 root.appendChild(queue);
570 QMap<int, JobQueueEntry> jobs;
571 QMap<int, JobQueueEntry>::Iterator it;
577 for (it = jobs.begin(); it != jobs.end(); ++it)
579 ProgramInfo pginfo((*it).chanid, (*it).recstartts);
583 QDomElement job = pDoc->createElement(
"Job");
584 queue.appendChild(job);
586 job.setAttribute(
"id" , (*it).id );
587 job.setAttribute(
"chanId" , (*it).chanid );
588 job.setAttribute(
"startTime" ,
590 job.setAttribute(
"startTs" , (*it).startts );
591 job.setAttribute(
"insertTime",
593 job.setAttribute(
"type" , (*it).type );
594 job.setAttribute(
"cmds" , (*it).cmds );
595 job.setAttribute(
"flags" , (*it).flags );
596 job.setAttribute(
"status" , (*it).status );
597 job.setAttribute(
"statusTime",
599 job.setAttribute(
"schedTime" ,
601 job.setAttribute(
"args" , (*it).args );
603 if ((*it).hostname.isEmpty())
604 job.setAttribute(
"hostname", QObject::tr(
"master"));
606 job.setAttribute(
"hostname",(*it).hostname);
608 QDomText textNode = pDoc->createTextNode((*it).comment);
609 job.appendChild(textNode);
614 queue.setAttribute(
"count", jobs.size() );
618 QDomElement mInfo = pDoc->createElement(
"MachineInfo");
619 QDomElement storage = pDoc->createElement(
"Storage" );
620 QDomElement load = pDoc->createElement(
"Load" );
621 QDomElement guide = pDoc->createElement(
"Guide" );
623 root.appendChild (mInfo );
624 mInfo.appendChild(storage);
625 mInfo.appendChild(load );
626 mInfo.appendChild(guide );
643 QList<QDomElement> fsXML;
644 QStringList::const_iterator sit = strlist.cbegin();
645 while (sit != strlist.cend())
648 directory = *(sit++);
649 isLocalstr = *(sit++);
653 long long iTotal = (*(sit++)).toLongLong();
654 long long iUsed = (*(sit++)).toLongLong();;
655 long long iAvail = iTotal - iUsed;
660 QDomElement group = pDoc->createElement(
"Group");
662 group.setAttribute(
"id" , fsID );
663 group.setAttribute(
"total", (
int)(iTotal>>10) );
664 group.setAttribute(
"used" , (
int)(iUsed>>10) );
665 group.setAttribute(
"free" , (
int)(iAvail>>10) );
666 group.setAttribute(
"dir" , directory );
670 long long iLiveTV = -1;
671 long long iDeleted = -1;
672 long long iExpirable = -1;
674 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
675 " WHERE recgroup = :RECGROUP;");
680 iLiveTV = query.
value(0).toLongLong();
685 iDeleted = query.
value(0).toLongLong();
687 query.
prepare(
"SELECT SUM(filesize) FROM recorded "
688 " WHERE autoexpire = 1 "
689 " AND recgroup NOT IN ('LiveTV', 'Deleted');");
692 iExpirable = query.
value(0).toLongLong();
694 group.setAttribute(
"livetv", (
int)(iLiveTV>>20) );
695 group.setAttribute(
"deleted", (
int)(iDeleted>>20) );
696 group.setAttribute(
"expirable", (
int)(iExpirable>>20) );
703 storage.appendChild(total);
704 int num_elements = fsXML.size();
705 for (
int fs_index = 0; fs_index < num_elements; fs_index++)
707 storage.appendChild(fsXML[fs_index]);
713 load.setAttribute(
"avg1", 0);
714 load.setAttribute(
"avg2", 1);
715 load.setAttribute(
"avg3", 2);
718 if (rgdAverages[0] != -1)
720 load.setAttribute(
"avg1", rgdAverages[0]);
721 load.setAttribute(
"avg2", rgdAverages[1]);
722 load.setAttribute(
"avg3", rgdAverages[2]);
728 QDateTime GuideDataThrough;
731 query.
prepare(
"SELECT MAX(endtime) FROM program WHERE manualid = 0;");
738 guide.setAttribute(
"start",
740 guide.setAttribute(
"end",
742 guide.setAttribute(
"status",
746 guide.setAttribute(
"next",
750 if (!GuideDataThrough.isNull())
752 guide.setAttribute(
"guideThru",
754 guide.setAttribute(
"guideDays", qdtNow.daysTo(GuideDataThrough));
760 if ((!info_script.isEmpty()) && (info_script !=
"none"))
762 QDomElement misc = pDoc->createElement(
"Miscellaneous");
763 root.appendChild(misc);
770 LOG(VB_GENERAL, LOG_ERR,
771 QString(
"Error running miscellaneous "
772 "status information script: %1").arg(info_script));
776 QByteArray input = ms.
ReadAll();
778 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
779 QStringList
output = QString(input).split(
'\n',
780 QString::SkipEmptyParts);
782 QStringList
output = QString(input).split(
'\n',
786 for (
const auto & line : qAsConst(
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";
1392 os <<
" Job Queue is currently empty.\r\n\r\n";
1394 os <<
" </div>\r\n\r\n ";
1411 os <<
"<div class=\"content\">\r\n"
1412 <<
" <h2 class=\"status\">Machine Information</h2>\r\n";
1416 QDomNode node = info.namedItem(
"Load" );
1420 QDomElement e = node.toElement();
1424 double dAvg1 = e.attribute(
"avg1" ,
"0" ).toDouble();
1425 double dAvg2 = e.attribute(
"avg2" ,
"0" ).toDouble();
1426 double dAvg3 = e.attribute(
"avg3" ,
"0" ).toDouble();
1428 os <<
" <div class=\"loadstatus\">\r\n"
1429 <<
" This machine's load average:"
1430 <<
"\r\n <ul>\r\n <li>"
1431 <<
"1 Minute: " << dAvg1 <<
"</li>\r\n"
1432 <<
" <li>5 Minutes: " << dAvg2 <<
"</li>\r\n"
1433 <<
" <li>15 Minutes: " << dAvg3
1434 <<
"</li>\r\n </ul>\r\n"
1440 node = info.namedItem(
"Storage" );
1441 QDomElement storage = node.toElement();
1442 node = storage.firstChild();
1447 while (!node.isNull())
1449 QDomElement g = node.toElement();
1451 if (!g.isNull() && g.tagName() ==
"Group")
1453 QString
id = g.attribute(
"id",
"" );
1457 int nFree = g.attribute(
"free" ,
"0" ).toInt();
1458 int nTotal = g.attribute(
"total",
"0" ).toInt();
1459 int nUsed = g.attribute(
"used" ,
"0" ).toInt();
1460 int nLiveTV = g.attribute(
"livetv" ,
"0" ).toInt();
1461 int nDeleted = g.attribute(
"deleted",
"0" ).toInt();
1462 int nExpirable = g.attribute(
"expirable" ,
"0" ).toInt();
1463 QString nDir = g.attribute(
"dir" ,
"" );
1465 nDir.replace(
",",
", ");
1467 os <<
" Disk Usage Summary:<br />\r\n";
1470 os <<
" <li>Total Disk Space:\r\n"
1473 os <<
" <li>Total Space: ";
1474 sRep = QString(
"%L1").arg(nTotal) +
" MB";
1475 os << sRep <<
"</li>\r\n";
1477 os <<
" <li>Space Used: ";
1478 sRep = QString(
"%L1").arg(nUsed) +
" MB";
1479 os << sRep <<
"</li>\r\n";
1481 os <<
" <li>Space Free: ";
1482 sRep = QString(
"%L1").arg(nFree) +
" MB";
1483 os << sRep <<
"</li>\r\n";
1485 if ((nLiveTV + nDeleted + nExpirable) > 0)
1487 os <<
" <li>Space Available "
1488 "After Auto-expire: ";
1489 sRep = QString(
"%L1").arg(nUsed) +
" MB";
1490 sRep = QString(
"%L1").arg(nFree + nLiveTV +
1491 nDeleted + nExpirable) +
" MB";
1492 os << sRep <<
"\r\n";
1494 os <<
" <li>Space Used by LiveTV: ";
1495 sRep = QString(
"%L1").arg(nLiveTV) +
" MB";
1496 os << sRep <<
"</li>\r\n";
1497 os <<
" <li>Space Used by "
1498 "Deleted Recordings: ";
1499 sRep = QString(
"%L1").arg(nDeleted) +
" MB";
1500 os << sRep <<
"</li>\r\n";
1501 os <<
" <li>Space Used by "
1502 "Auto-expirable Recordings: ";
1503 sRep = QString(
"%L1").arg(nExpirable) +
" MB";
1504 os << sRep <<
"</li>\r\n";
1517 node = node.nextSibling();
1521 node = storage.firstChild();
1523 os <<
" Disk Usage Details:<br />\r\n";
1527 while (!node.isNull())
1529 QDomElement g = node.toElement();
1531 if (!g.isNull() && g.tagName() ==
"Group")
1533 int nFree = g.attribute(
"free" ,
"0" ).toInt();
1534 int nTotal = g.attribute(
"total",
"0" ).toInt();
1535 int nUsed = g.attribute(
"used" ,
"0" ).toInt();
1536 QString nDir = g.attribute(
"dir" ,
"" );
1537 QString
id = g.attribute(
"id" ,
"" );
1539 nDir.replace(
",",
", ");
1545 os <<
" <li>MythTV Drive #" <<
id <<
":"
1549 if (nDir.contains(
','))
1550 os <<
" <li>Directories: ";
1552 os <<
" <li>Directory: ";
1554 os << nDir <<
"</li>\r\n";
1556 os <<
" <li>Total Space: ";
1557 sRep = QString(
"%L1").arg(nTotal) +
" MB";
1558 os << sRep <<
"</li>\r\n";
1560 os <<
" <li>Space Used: ";
1561 sRep = QString(
"%L1").arg(nUsed) +
" MB";
1562 os << sRep <<
"</li>\r\n";
1564 os <<
" <li>Space Free: ";
1565 sRep = QString(
"%L1").arg(nFree) +
" MB";
1566 os << sRep <<
"</li>\r\n";
1574 node = node.nextSibling();
1581 node = info.namedItem(
"Guide" );
1585 QDomElement e = node.toElement();
1589 int nDays = e.attribute(
"guideDays",
"0" ).toInt();
1590 QString sStart = e.attribute(
"start" ,
"" );
1591 QString sEnd = e.attribute(
"end" ,
"" );
1592 QString sStatus = e.attribute(
"status" ,
"" );
1594 QString sNext = next.isNull() ?
"" :
1600 QDomText text = e.firstChild().toText();
1607 sMsg = text.nodeValue();
1609 os <<
" Last mythfilldatabase run started on " << sStart
1615 os <<
"ended on " << sEnd <<
". ";
1617 os << sStatus <<
"<br />\r\n";
1619 if (!next.isNull() && next >= lastrunstart)
1621 os <<
" Suggested next mythfilldatabase run: "
1622 << sNext <<
".<br />\r\n";
1627 os <<
" There's guide data until "
1631 os <<
" " << QObject::tr(
"(%n day(s))",
"", nDays);
1636 os <<
" <strong>WARNING</strong>: is mythfilldatabase running?";
1639 os <<
" There's <strong>no guide data</strong> available! "
1640 <<
"Have you run mythfilldatabase?";
1643 os <<
"\r\n </div>\r\n";
1655 QDomNodeList nodes = info.elementsByTagName(
"Information");
1656 uint count = nodes.count();
1662 os <<
"<div class=\"content\">\r\n"
1663 <<
" <h2 class=\"status\">Miscellaneous</h2>\r\n";
1664 for (
unsigned int i = 0; i < count; i++)
1666 QDomNode node = nodes.item(i);
1670 QDomElement e = node.toElement();
1674 display = e.attribute(
"display",
"");
1678 if (display.isEmpty())
1683 if (display.contains(
"<p>", Qt::CaseInsensitive) ||
1684 display.contains(
"<br", Qt::CaseInsensitive))
1690 linebreak =
"<br />\r\n";
1692 os <<
" " << display << linebreak;
1706 if ((pDoc ==
nullptr) || (pInfo ==
nullptr))
1711 QDomElement program = pDoc->createElement(
"Program" );
1712 node.appendChild( program );
1714 program.setAttribute(
"startTime" ,
1717 program.setAttribute(
"title" , pInfo->
GetTitle() );
1718 program.setAttribute(
"subTitle" , pInfo->
GetSubtitle());
1719 program.setAttribute(
"category" , pInfo->
GetCategory());
1721 program.setAttribute(
"repeat" ,
static_cast<int>(pInfo->
IsRepeat()));
1726 program.setAttribute(
"seriesId" , pInfo->
GetSeriesID() );
1727 program.setAttribute(
"programId" , pInfo->
GetProgramID() );
1728 program.setAttribute(
"stars" , pInfo->
GetStars() );
1729 program.setAttribute(
"fileSize" ,
1731 program.setAttribute(
"lastModified",
1734 program.setAttribute(
"hostname" , pInfo->
GetHostname() );
1737 program.setAttribute(
1740 QDomText textNode = pDoc->createTextNode( pInfo->
GetDescription() );
1741 program.appendChild( textNode );
1749 QDomElement channel = pDoc->createElement(
"Channel" );
1750 program.appendChild( channel );
1759 QDomElement recording = pDoc->createElement(
"Recording" );
1760 program.appendChild( recording );
1762 recording.setAttribute(
"recStatus" ,
1764 recording.setAttribute(
"recPriority" ,
1766 recording.setAttribute(
"recStartTs" ,
1768 recording.setAttribute(
"recEndTs" ,
1773 recording.setAttribute(
"recordId" ,
1775 recording.setAttribute(
"recGroup" ,
1777 recording.setAttribute(
"playGroup" ,
1779 recording.setAttribute(
"recType" ,
1781 recording.setAttribute(
"dupInType" ,
1783 recording.setAttribute(
"dupMethod" ,
1785 recording.setAttribute(
"encoderId" ,
1788 recording.setAttribute(
"recProfile" ,
1815 channel.setAttribute(
"chanId" , pInfo->
GetChanID() );
1816 channel.setAttribute(
"chanNum" , pInfo->
GetChanNum());
1823 channel.setAttribute(
"chanFilters",
1825 channel.setAttribute(
"sourceId" , pInfo->
GetSourceID() );
1826 channel.setAttribute(
"inputId" , pInfo->
GetInputID() );
1827 channel.setAttribute(
"commFree" ,