MythTV  master
v2status.cpp
Go to the documentation of this file.
1 // Program Name: httpstatus.cpp
3 //
4 // Purpose - Html & XML status HttpServerExtension
5 //
6 // Created By : David Blain Created On : Oct. 24, 2005
7 // Modified By : Modified On:
8 //
10 
11 // POSIX headers
12 #include <unistd.h>
13 
14 // ANSI C headers
15 #include <cmath>
16 #include <cstdio>
17 #include <cstdlib>
18 
19 // Qt headers
20 #include <QtGlobal>
21 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
22 #include <QStringConverter>
23 #endif
24 #include <QTextStream>
25 
26 // MythTV headers
27 #include "libmythbase/compat.h"
28 #include "libmythbase/exitcodes.h"
30 #include "libmythbase/mythconfig.h"
32 #include "libmythbase/mythdate.h"
33 #include "libmythbase/mythdbcon.h"
36 #include "libmythbase/mythversion.h"
37 #include "libmythtv/cardutil.h"
38 #include "libmythtv/jobqueue.h"
39 #include "libmythtv/tv.h"
40 #include "libmythtv/tv_rec.h"
41 #include "libmythupnp/upnp.h"
42 
43 // MythBackend
44 #include "autoexpire.h"
45 #include "backendcontext.h"
46 #include "encoderlink.h"
47 #include "mainserver.h"
48 #include "scheduler.h"
49 #include "v2backendStatus.h"
50 #include "v2serviceUtil.h"
51 #include "v2status.h"
52 
53 // This will be initialised in a thread safe manner on first use
55  (STATUS_HANDLE, V2Status::staticMetaObject, &V2Status::RegisterCustomTypes))
56 
58 {
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");
75 }
76 
78 {
79  m_pEncoders = &gTVList; // extern
80  m_pSched = dynamic_cast<Scheduler*>(gCoreContext->GetScheduler());
81  if (m_pSched)
84  m_nPreRollSeconds = gCoreContext->GetNumSetting("RecordPreRoll", 0);
85 }
86 
87 // HTML
89 {
90  return GetStatusHTML();
91 }
92 
93 // XML
95 {
96  return GetStatus();
97 }
98 
99 // XML
101 {
102  QDomDocument doc( "Status" );
103  // UTF-8 is the default, but good practice to specify it anyway
104  QDomProcessingInstruction encoding =
105  doc.createProcessingInstruction("xml",
106  R"(version="1.0" encoding="UTF-8")");
107  doc.appendChild(encoding);
108  FillStatusXML( &doc );
109  auto *pResult = new Preformat();
110  pResult->setmimetype("application/xml");
111  pResult->setbuffer(doc.toString());
112  return pResult;
113 }
114 
115 // HTML
117 {
118  QDomDocument doc( "Status" );
119  FillStatusXML( &doc );
120  QString html;
121  QTextStream stream( &html );
122  PrintStatus( stream, &doc );
123  auto *pResult = new Preformat();
124  pResult->setmimetype("text/html");
125  pResult->setbuffer(html);
126  return pResult;
127 }
128 
129 static QString setting_to_localtime(const char *setting)
130 {
131  QString origDateString = gCoreContext->GetSetting(setting);
132  QDateTime origDate = MythDate::fromString(origDateString);
134 }
135 
136 static QDateTime setting_to_qdatetime(const char *setting)
137 {
138  QString origDateString = gCoreContext->GetSetting(setting);
139  QDateTime origDate = MythDate::fromString(origDateString);
140  return origDate;
141 }
142 
143 // Standardized version of GetStatus that supports xml, json, etc.
145 {
146  auto* pStatus = new V2BackendStatus();
147  pStatus->setAsOf ( MythDate::current() );
148  pStatus->setVersion ( MYTH_BINARY_VERSION );
149  pStatus->setProtoVer ( MYTH_PROTO_VERSION );
150  // Encoders
151  FillEncoderList(pStatus->GetEncoders(), pStatus);
152  // Upcoming recordings
153  int nStartIndex = 0;
154  int nCount = 10;
155  // Scheduled Recordings
156  FillUpcomingList(pStatus->GetScheduled(), pStatus,
157  nStartIndex,
158  nCount,
159  true, // bShowAll,
160  -1, // nRecordId,
161  -999); // nRecStatus )
162  // Frontends
163  FillFrontendList(pStatus->GetFrontends(), pStatus,
164  false); // OnLine)
165  // Backends
166  V2Backend *backend {nullptr};
167 
168  // Add this host
169  backend = pStatus->AddNewBackend();
170  QString thisHost = gCoreContext->GetHostName();
171  backend->setName(thisHost);
172  backend->setIP(gCoreContext->GetBackendServerIP());
173 
174  if (m_pMainServer)
175  {
176  backend->setType("Master");
177  QStringList backends;
178  m_pMainServer->GetActiveBackends(backends);
179  for (const QString& hostname : qAsConst(backends))
180  {
181  if (hostname != thisHost)
182  {
184  backend = pStatus->AddNewBackend();
185  backend->setName(hostname);
186  backend->setType("Slave");
187  if (pSock)
188  {
189  backend->setIP(pSock->getIP());
190  }
191  }
192  }
193  }
194  else
195  {
196  backend->setType("Slave");
197  QString masterhost = gCoreContext->GetMasterHostName();
198  QString masterip = gCoreContext->GetMasterServerIP();
199  backend = pStatus->AddNewBackend();
200  backend->setName(masterhost);
201  backend->setIP(masterip);
202  backend->setType("Master");
203  }
204 
205  // Add Job Queue Entries
206  QMap<int, JobQueueEntry> jobs;
207  QMap<int, JobQueueEntry>::Iterator it;
208 
212 
213  for (it = jobs.begin(); it != jobs.end(); ++it)
214  {
215  ProgramInfo pginfo((*it).chanid, (*it).recstartts);
216  if (!pginfo.GetChanID())
217  continue;
218 
219  V2Job * pJob = pStatus->AddNewJob();
220 
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 );
227  pJob->setLocalizedJobName( JobQueue::JobText((*it).type) );
228  pJob->setCmds( (*it).cmds );
229  pJob->setFlags( (*it).flags );
230  pJob->setStatus( (*it).status );
231  pJob->setLocalizedStatus( JobQueue::StatusText((*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"));
237  else
238  pJob->setHostName((*it).hostname);
239  pJob->setComment((*it).comment);
240  V2Program *pProgram = pJob->Program();
241  V2FillProgramInfo( pProgram, &pginfo, true, false, false);
242  }
243 
244  // Machine Info
245  V2MachineInfo *pMachineInfo = pStatus->MachineInfo();
246  FillDriveSpace(pMachineInfo);
247  // load average
248  loadArray rgdAverages = getLoadAvgs();
249  if (rgdAverages[0] != -1)
250  {
251  pMachineInfo->setLoadAvg1(rgdAverages[0]);
252  pMachineInfo->setLoadAvg2(rgdAverages[1]);
253  pMachineInfo->setLoadAvg3(rgdAverages[2]);
254  }
255 
256  // Guide Data
257  QDateTime GuideDataThrough;
258  MSqlQuery query(MSqlQuery::InitCon());
259  query.prepare("SELECT MAX(endtime) FROM program WHERE manualid = 0;");
260  if (query.exec() && query.next())
261  {
262  GuideDataThrough = MythDate::fromString(query.value(0).toString());
263  }
264  pMachineInfo->setGuideStart
265  (setting_to_qdatetime("mythfilldatabaseLastRunStart"));
266  pMachineInfo->setGuideEnd(
267  setting_to_qdatetime("mythfilldatabaseLastRunEnd"));
268  pMachineInfo->setGuideStatus(
269  gCoreContext->GetSetting("mythfilldatabaseLastRunStatus"));
270  if (gCoreContext->GetBoolSetting("MythFillGrabberSuggestsTime", false))
271  {
272  pMachineInfo->setGuideNext(
273  gCoreContext->GetSetting("MythFillSuggestedRunTime"));
274  }
275 
276  if (!GuideDataThrough.isNull())
277  {
278  QDateTime qdtNow = MythDate::current();
279  pMachineInfo->setGuideThru(GuideDataThrough);
280  pMachineInfo->setGuideDays(qdtNow.daysTo(GuideDataThrough));
281  }
282 
283  // Add Miscellaneous information
284  QString info_script = gCoreContext->GetSetting("MiscStatusScript");
285  if ((!info_script.isEmpty()) && (info_script != "none"))
286  {
287  uint flags = kMSRunShell | kMSStdOut;
288  MythSystemLegacy ms(info_script, flags);
289  ms.Run(10s);
290  if (ms.Wait() != GENERIC_EXIT_OK)
291  {
292  LOG(VB_GENERAL, LOG_ERR,
293  QString("Error running miscellaneous "
294  "status information script: %1").arg(info_script));
295  }
296 
297  QByteArray input = ms.ReadAll();
298  pStatus->setMiscellaneous(QString(input));
299  }
300  return pStatus;
301 }
302 
304 {
305  QStringList strlist;
306  QString hostname;
307  QString directory;
308  QString isLocalstr;
309  QString fsID;
310 
311  if (m_pMainServer)
313 
314  QStringList::const_iterator sit = strlist.cbegin();
315  while (sit != strlist.cend())
316  {
317  hostname = *(sit++);
318  directory = *(sit++);
319  isLocalstr = *(sit++);
320  fsID = *(sit++);
321  ++sit; // ignore dirID
322  ++sit; // ignore blocksize
323  long long iTotal = (*(sit++)).toLongLong();
324  long long iUsed = (*(sit++)).toLongLong();;
325  long long iAvail = iTotal - iUsed;
326 
327  if (fsID == "-2")
328  fsID = "total";
329 
330  V2StorageGroup* group = pMachineInfo->AddNewStorageGroup();
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);
336 
337  if (fsID == "total")
338  {
339  long long iLiveTV = -1;
340  long long iDeleted = -1;
341  long long iExpirable = -1;
342  MSqlQuery query(MSqlQuery::InitCon());
343  query.prepare("SELECT SUM(filesize) FROM recorded "
344  " WHERE recgroup = :RECGROUP;");
345 
346  query.bindValue(":RECGROUP", "LiveTV");
347  if (query.exec() && query.next())
348  {
349  iLiveTV = query.value(0).toLongLong();
350  }
351  query.bindValue(":RECGROUP", "Deleted");
352  if (query.exec() && query.next())
353  {
354  iDeleted = query.value(0).toLongLong();
355  }
356  query.prepare("SELECT SUM(filesize) FROM recorded "
357  " WHERE autoexpire = 1 "
358  " AND recgroup NOT IN ('LiveTV', 'Deleted');");
359  if (query.exec() && query.next())
360  {
361  iExpirable = query.value(0).toLongLong();
362  }
363  group->setLiveTV( (int)(iLiveTV>>20) );
364  group->setDeleted( (int)(iDeleted>>20) );
365  group->setExpirable ( (int)(iExpirable>>20) );
366  }
367  }
368 
369 }
370 
371 void V2Status::FillStatusXML( QDomDocument *pDoc )
372 {
373  QDateTime qdtNow = MythDate::current();
374 
375  // Add Root Node.
376 
377  QDomElement root = pDoc->createElement("Status");
378  pDoc->appendChild(root);
379 
380  root.setAttribute("date" , MythDate::toString(
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 );
387 
388  // Add all encoders, if any
389 
390  QDomElement encoders = pDoc->createElement("Encoders");
391  root.appendChild(encoders);
392 
393  int numencoders = 0;
394  bool isLocal = true;
395 
396  TVRec::s_inputsLock.lockForRead();
397 
398  for (auto * elink : qAsConst(*m_pEncoders))
399  {
400  if (elink != nullptr)
401  {
402  TVState state = elink->GetState();
403  isLocal = elink->IsLocal();
404 
405  QDomElement encoder = pDoc->createElement("Encoder");
406  encoders.appendChild(encoder);
407 
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() );
413  //encoder.setAttribute("lowOnFreeSpace", elink->isLowOnFreeSpace());
414 
415  if (isLocal)
416  encoder.setAttribute("hostname", gCoreContext->GetHostName());
417  else
418  encoder.setAttribute("hostname", elink->GetHostName());
419 
420  encoder.setAttribute("devlabel",
421  CardUtil::GetDeviceLabel(elink->GetInputID()) );
422 
423  if (elink->IsConnected())
424  numencoders++;
425 
426  switch (state)
427  {
431  {
432  ProgramInfo *pInfo = elink->GetRecording();
433 
434  if (pInfo)
435  {
436  FillProgramInfo(pDoc, encoder, pInfo);
437  delete pInfo;
438  }
439 
440  break;
441  }
442 
443  default:
444  break;
445  }
446  }
447  }
448 
449  TVRec::s_inputsLock.unlock();
450 
451  encoders.setAttribute("count", numencoders);
452 
453  // Add upcoming shows
454 
455  QDomElement scheduled = pDoc->createElement("Scheduled");
456  root.appendChild(scheduled);
457 
458  RecList recordingList;
459 
460  if (m_pSched)
461  m_pSched->GetAllPending(recordingList);
462 
463  unsigned int iNum = 10;
464  unsigned int iNumRecordings = 0;
465 
466  auto itProg = recordingList.begin();
467  for (; (itProg != recordingList.end()) && iNumRecordings < iNum; ++itProg)
468  {
469  if (((*itProg)->GetRecordingStatus() <= RecStatus::WillRecord) &&
470  ((*itProg)->GetRecordingStartTime() >=
472  {
473  iNumRecordings++;
474  FillProgramInfo(pDoc, scheduled, *itProg);
475  }
476  }
477 
478  while (!recordingList.empty())
479  {
480  ProgramInfo *pginfo = recordingList.back();
481  delete pginfo;
482  recordingList.pop_back();
483  }
484 
485  scheduled.setAttribute("count", iNumRecordings);
486 
487  // Add known frontends
488 
489  QDomElement frontends = pDoc->createElement("Frontends");
490  root.appendChild(frontends);
491 
493  "urn:schemas-mythtv-org:service:MythFrontend:1");
494  if (fes)
495  {
496  EntryMap map;
497  fes->GetEntryMap(map);
498  fes->DecrRef();
499  fes = nullptr;
500 
501  frontends.setAttribute( "count", map.size() );
502  for (const auto & entry : qAsConst(map))
503  {
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));
509  entry->DecrRef();
510  }
511  }
512 
513  // Other backends
514 
515  QDomElement backends = pDoc->createElement("Backends");
516  root.appendChild(backends);
517 
518  int numbes = 0;
520  {
521  numbes++;
522  QString masterhost = gCoreContext->GetMasterHostName();
523  QString masterip = gCoreContext->GetMasterServerIP();
524  int masterport = gCoreContext->GetMasterServerStatusPort();
525 
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));
531  }
532 
534  "urn:schemas-mythtv-org:device:SlaveMediaServer:1");
535  if (sbes)
536  {
537 
538  QString ipaddress = QString();
539  if (!UPnp::g_IPAddrList.isEmpty())
540  ipaddress = UPnp::g_IPAddrList.at(0).toString();
541 
542  EntryMap map;
543  sbes->GetEntryMap(map);
544  sbes->DecrRef();
545  sbes = nullptr;
546 
547  for (const auto & entry : qAsConst(map))
548  {
549  QUrl url(entry->m_sLocation);
550  if (url.host() != ipaddress)
551  {
552  numbes++;
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));
558  }
559  entry->DecrRef();
560  }
561  }
562 
563  backends.setAttribute("count", numbes);
564 
565  // Add Job Queue Entries
566 
567  QDomElement queue = pDoc->createElement("JobQueue");
568  root.appendChild(queue);
569 
570  QMap<int, JobQueueEntry> jobs;
571  QMap<int, JobQueueEntry>::Iterator it;
572 
576 
577  for (it = jobs.begin(); it != jobs.end(); ++it)
578  {
579  ProgramInfo pginfo((*it).chanid, (*it).recstartts);
580  if (!pginfo.GetChanID())
581  continue;
582 
583  QDomElement job = pDoc->createElement("Job");
584  queue.appendChild(job);
585 
586  job.setAttribute("id" , (*it).id );
587  job.setAttribute("chanId" , (*it).chanid );
588  job.setAttribute("startTime" ,
589  (*it).recstartts.toString(Qt::ISODate));
590  job.setAttribute("startTs" , (*it).startts );
591  job.setAttribute("insertTime",
592  (*it).inserttime.toString(Qt::ISODate));
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",
598  (*it).statustime.toString(Qt::ISODate));
599  job.setAttribute("schedTime" ,
600  (*it).schedruntime.toString(Qt::ISODate));
601  job.setAttribute("args" , (*it).args );
602 
603  if ((*it).hostname.isEmpty())
604  job.setAttribute("hostname", QObject::tr("master"));
605  else
606  job.setAttribute("hostname",(*it).hostname);
607 
608  QDomText textNode = pDoc->createTextNode((*it).comment);
609  job.appendChild(textNode);
610 
611  FillProgramInfo(pDoc, job, &pginfo);
612  }
613 
614  queue.setAttribute( "count", jobs.size() );
615 
616  // Add Machine information
617 
618  QDomElement mInfo = pDoc->createElement("MachineInfo");
619  QDomElement storage = pDoc->createElement("Storage" );
620  QDomElement load = pDoc->createElement("Load" );
621  QDomElement guide = pDoc->createElement("Guide" );
622 
623  root.appendChild (mInfo );
624  mInfo.appendChild(storage);
625  mInfo.appendChild(load );
626  mInfo.appendChild(guide );
627 
628  // drive space ---------------------
629 
630  QStringList strlist;
631  QString hostname;
632  QString directory;
633  QString isLocalstr;
634  QString fsID;
635 
636  if (m_pMainServer)
638 
639  QDomElement total;
640 
641  // Make a temporary list to hold the per-filesystem elements so that the
642  // total is always the first element.
643  QList<QDomElement> fsXML;
644  QStringList::const_iterator sit = strlist.cbegin();
645  while (sit != strlist.cend())
646  {
647  hostname = *(sit++);
648  directory = *(sit++);
649  isLocalstr = *(sit++);
650  fsID = *(sit++);
651  ++sit; // ignore dirID
652  ++sit; // ignore blocksize
653  long long iTotal = (*(sit++)).toLongLong();
654  long long iUsed = (*(sit++)).toLongLong();;
655  long long iAvail = iTotal - iUsed;
656 
657  if (fsID == "-2")
658  fsID = "total";
659 
660  QDomElement group = pDoc->createElement("Group");
661 
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 );
667 
668  if (fsID == "total")
669  {
670  long long iLiveTV = -1;
671  long long iDeleted = -1;
672  long long iExpirable = -1;
673  MSqlQuery query(MSqlQuery::InitCon());
674  query.prepare("SELECT SUM(filesize) FROM recorded "
675  " WHERE recgroup = :RECGROUP;");
676 
677  query.bindValue(":RECGROUP", "LiveTV");
678  if (query.exec() && query.next())
679  {
680  iLiveTV = query.value(0).toLongLong();
681  }
682  query.bindValue(":RECGROUP", "Deleted");
683  if (query.exec() && query.next())
684  {
685  iDeleted = query.value(0).toLongLong();
686  }
687  query.prepare("SELECT SUM(filesize) FROM recorded "
688  " WHERE autoexpire = 1 "
689  " AND recgroup NOT IN ('LiveTV', 'Deleted');");
690  if (query.exec() && query.next())
691  {
692  iExpirable = query.value(0).toLongLong();
693  }
694  group.setAttribute("livetv", (int)(iLiveTV>>20) );
695  group.setAttribute("deleted", (int)(iDeleted>>20) );
696  group.setAttribute("expirable", (int)(iExpirable>>20) );
697  total = group;
698  }
699  else
700  fsXML << group;
701  }
702 
703  storage.appendChild(total);
704  int num_elements = fsXML.size();
705  for (int fs_index = 0; fs_index < num_elements; fs_index++)
706  {
707  storage.appendChild(fsXML[fs_index]);
708  }
709 
710  // load average ---------------------
711 
712 #ifdef Q_OS_ANDROID
713  load.setAttribute("avg1", 0);
714  load.setAttribute("avg2", 1);
715  load.setAttribute("avg3", 2);
716 #else
717  loadArray rgdAverages = getLoadAvgs();
718  if (rgdAverages[0] != -1)
719  {
720  load.setAttribute("avg1", rgdAverages[0]);
721  load.setAttribute("avg2", rgdAverages[1]);
722  load.setAttribute("avg3", rgdAverages[2]);
723  }
724 #endif
725 
726  // Guide Data ---------------------
727 
728  QDateTime GuideDataThrough;
729 
730  MSqlQuery query(MSqlQuery::InitCon());
731  query.prepare("SELECT MAX(endtime) FROM program WHERE manualid = 0;");
732 
733  if (query.exec() && query.next())
734  {
735  GuideDataThrough = MythDate::fromString(query.value(0).toString());
736  }
737 
738  guide.setAttribute("start",
739  setting_to_localtime("mythfilldatabaseLastRunStart"));
740  guide.setAttribute("end",
741  setting_to_localtime("mythfilldatabaseLastRunEnd"));
742  guide.setAttribute("status",
743  gCoreContext->GetSetting("mythfilldatabaseLastRunStatus"));
744  if (gCoreContext->GetBoolSetting("MythFillGrabberSuggestsTime", false))
745  {
746  guide.setAttribute("next",
747  gCoreContext->GetSetting("MythFillSuggestedRunTime"));
748  }
749 
750  if (!GuideDataThrough.isNull())
751  {
752  guide.setAttribute("guideThru",
753  GuideDataThrough.toString(Qt::ISODate));
754  guide.setAttribute("guideDays", qdtNow.daysTo(GuideDataThrough));
755  }
756 
757  // Add Miscellaneous information
758 
759  QString info_script = gCoreContext->GetSetting("MiscStatusScript");
760  if ((!info_script.isEmpty()) && (info_script != "none"))
761  {
762  QDomElement misc = pDoc->createElement("Miscellaneous");
763  root.appendChild(misc);
764 
765  uint flags = kMSRunShell | kMSStdOut;
766  MythSystemLegacy ms(info_script, flags);
767  ms.Run(10s);
768  if (ms.Wait() != GENERIC_EXIT_OK)
769  {
770  LOG(VB_GENERAL, LOG_ERR,
771  QString("Error running miscellaneous "
772  "status information script: %1").arg(info_script));
773  return;
774  }
775 
776  QByteArray input = ms.ReadAll();
777 
778 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
779  QStringList output = QString(input).split('\n',
780  QString::SkipEmptyParts);
781 #else
782  QStringList output = QString(input).split('\n',
783  Qt::SkipEmptyParts);
784 #endif
785 
786  for (const auto & line : qAsConst(output))
787  {
788  QDomElement info = pDoc->createElement("Information");
789 
790  QStringList list = line.split("[]:[]");
791  unsigned int size = list.size();
792  unsigned int hasAttributes = 0;
793 
794  if ((size > 0) && (!list[0].isEmpty()))
795  {
796  info.setAttribute("display", list[0]);
797  hasAttributes++;
798  }
799  if ((size > 1) && (!list[1].isEmpty()))
800  {
801  info.setAttribute("name", list[1]);
802  hasAttributes++;
803  }
804  if ((size > 2) && (!list[2].isEmpty()))
805  {
806  info.setAttribute("value", list[2]);
807  hasAttributes++;
808  }
809 
810  if (hasAttributes > 0)
811  misc.appendChild(info);
812  }
813  }
814 }
815 
817 //
819 
820 void V2Status::PrintStatus( QTextStream &os, QDomDocument *pDoc )
821 {
822 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
823  os.setCodec("UTF-8");
824 #else
825  os.setEncoding(QStringConverter::Utf8);
826 #endif
827 
828  QDateTime qdtNow = MythDate::current();
829 
830  QDomElement docElem = pDoc->documentElement();
831 
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"
836  << "<head>\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 - "
841  << docElem.attribute( "date", MythDate::toString(qdtNow, MythDate::kDateShort) )
842  << " "
843  << docElem.attribute( "time", MythDate::toString(qdtNow, MythDate::kTime) ) << " - "
844  << docElem.attribute( "version", MYTH_BINARY_VERSION ) << "</title>\r\n"
845  << "</head>\r\n"
846  << "<body bgcolor=\"#fff\">\r\n"
847  << "<div class=\"status\">\r\n"
848  << " <h1 class=\"status\">MythTV Status</h1>\r\n";
849 
850  // encoder information ---------------------
851 
852  QDomNode node = docElem.namedItem( "Encoders" );
853 
854  if (!node.isNull())
855  PrintEncoderStatus( os, node.toElement() );
856 
857  // upcoming shows --------------------------
858 
859  node = docElem.namedItem( "Scheduled" );
860 
861  if (!node.isNull())
862  PrintScheduled( os, node.toElement());
863 
864  // Frontends
865 
866  node = docElem.namedItem( "Frontends" );
867 
868  if (!node.isNull())
869  PrintFrontends (os, node.toElement());
870 
871  // Backends
872 
873  node = docElem.namedItem( "Backends" );
874 
875  if (!node.isNull())
876  PrintBackends (os, node.toElement());
877 
878  // Job Queue Entries -----------------------
879 
880  node = docElem.namedItem( "JobQueue" );
881 
882  if (!node.isNull())
883  PrintJobQueue( os, node.toElement());
884 
885  // Machine information ---------------------
886 
887  node = docElem.namedItem( "MachineInfo" );
888 
889  if (!node.isNull())
890  PrintMachineInfo( os, node.toElement());
891 
892  // Miscellaneous information ---------------
893 
894  node = docElem.namedItem( "Miscellaneous" );
895 
896  if (!node.isNull())
897  PrintMiscellaneousInfo( os, node.toElement());
898 
899  os << "\r\n</div>\r\n</body>\r\n</html>\r\n";
900 
901 }
902 
904 //
906 
907 int V2Status::PrintEncoderStatus( QTextStream &os, const QDomElement& encoders )
908 {
909  int nNumEncoders = 0;
910 
911  if (encoders.isNull())
912  return 0;
913 
914  os << " <div class=\"content\">\r\n"
915  << " <h2 class=\"status\">Encoder Status</h2>\r\n";
916 
917  QDomNode node = encoders.firstChild();
918 
919  while (!node.isNull())
920  {
921  QDomElement e = node.toElement();
922 
923  if (!e.isNull())
924  {
925  if (e.tagName() == "Encoder")
926  {
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());
932 
933  bool bIsLowOnFreeSpace=static_cast<bool>(e.attribute( "lowOnFreeSpace", "0").toInt());
934 
935  QString sDevlabel = e.attribute( "devlabel", "[ UNKNOWN ]");
936 
937  os << " Encoder " << sCardId << " " << sDevlabel
938  << " is " << sIsLocal << " on " << sHostName;
939 
940  if ((sIsLocal == "remote") && !bConnected)
941  {
942  SleepStatus sleepStatus =
943  (SleepStatus) e.attribute("sleepstatus",
944  QString::number(sStatus_Undefined)).toInt();
945 
946  if (sleepStatus == sStatus_Asleep)
947  os << " (currently asleep).<br />";
948  else
949  os << " (currently not connected).<br />";
950 
951  node = node.nextSibling();
952  continue;
953  }
954 
955  nNumEncoders++;
956 
957  TVState encState = (TVState) e.attribute( "state", "0").toInt();
958 
959  switch( encState )
960  {
962  os << " and is watching Live TV";
963  break;
964 
967  os << " and is recording";
968  break;
969 
970  default:
971  os << " and is not recording.";
972  break;
973  }
974 
975  // Display first Program Element listed under the encoder
976 
977  QDomNode tmpNode = e.namedItem( "Program" );
978 
979  if (!tmpNode.isNull())
980  {
981  QDomElement program = tmpNode.toElement();
982 
983  if (!program.isNull())
984  {
985  os << " '" << program.attribute( "title", "Unknown" ) << "'";
986 
987  // Get Channel information
988 
989  tmpNode = program.namedItem( "Channel" );
990 
991  if (!tmpNode.isNull())
992  {
993  QDomElement channel = tmpNode.toElement();
994 
995  if (!channel.isNull())
996  os << " on "
997  << channel.attribute( "callSign", "unknown" );
998  }
999 
1000  // Get Recording Information (if any)
1001 
1002  tmpNode = program.namedItem( "Recording" );
1003 
1004  if (!tmpNode.isNull())
1005  {
1006  QDomElement recording = tmpNode.toElement();
1007 
1008  if (!recording.isNull())
1009  {
1010  QDateTime endTs = MythDate::fromString(
1011  recording.attribute( "recEndTs", "" ));
1012 
1013  os << ". This recording ";
1014  if (endTs < MythDate::current())
1015  os << "was ";
1016  else
1017  os << "is ";
1018 
1019  os << "scheduled to end at "
1020  << MythDate::toString(endTs,
1021  MythDate::kTime);
1022  }
1023  }
1024  }
1025 
1026  os << ".";
1027  }
1028 
1029  if (bIsLowOnFreeSpace)
1030  {
1031  os << " <strong>WARNING</strong>:"
1032  << " This backend is low on free disk space!";
1033  }
1034 
1035  os << "<br />\r\n";
1036  }
1037  }
1038 
1039  node = node.nextSibling();
1040  }
1041 
1042  os << " </div>\r\n\r\n";
1043 
1044  return( nNumEncoders );
1045 }
1046 
1048 //
1050 
1051 int V2Status::PrintScheduled( QTextStream &os, const QDomElement& scheduled )
1052 {
1053  QDateTime qdtNow = MythDate::current();
1054 
1055  if (scheduled.isNull())
1056  return( 0 );
1057 
1058  int nNumRecordings= scheduled.attribute( "count", "0" ).toInt();
1059 
1060  os << " <div class=\"content\">\r\n"
1061  << " <h2 class=\"status\">Schedule</h2>\r\n";
1062 
1063  if (nNumRecordings == 0)
1064  {
1065  os << " There are no shows scheduled for recording.\r\n"
1066  << " </div>\r\n";
1067  return( 0 );
1068  }
1069 
1070  os << " The next " << nNumRecordings << " show" << (nNumRecordings == 1 ? "" : "s" )
1071  << " that " << (nNumRecordings == 1 ? "is" : "are")
1072  << " scheduled for recording:\r\n";
1073 
1074  os << " <div class=\"schedule\">\r\n";
1075 
1076  // Iterate through all scheduled programs
1077 
1078  QDomNode node = scheduled.firstChild();
1079 
1080  while (!node.isNull())
1081  {
1082  QDomElement e = node.toElement();
1083 
1084  if (!e.isNull())
1085  {
1086  QDomNode recNode = e.namedItem( "Recording" );
1087  QDomNode chanNode = e.namedItem( "Channel" );
1088 
1089  if ((e.tagName() == "Program") && !recNode.isNull() &&
1090  !chanNode.isNull())
1091  {
1092  QDomElement r = recNode.toElement();
1093  QDomElement c = chanNode.toElement();
1094 
1095  QString sTitle = e.attribute( "title" , "" );
1096  QString sSubTitle = e.attribute( "subTitle", "" );
1097  QDateTime airDate = MythDate::fromString( e.attribute( "airdate" ,"" ));
1098  QDateTime startTs = MythDate::fromString( e.attribute( "startTime" ,"" ));
1099  QDateTime endTs = MythDate::fromString( e.attribute( "endTime" ,"" ));
1100  QDateTime recStartTs = MythDate::fromString( r.attribute( "recStartTs","" ));
1101 // QDateTime recEndTs = MythDate::fromString( r.attribute( "recEndTs" ,"" ));
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" , "" );
1106  QString sDesc = "";
1107 
1108  QDomText text = e.firstChild().toText();
1109  if (!text.isNull())
1110  sDesc = text.nodeValue();
1111 
1112  // Build Time to recording start.
1113 
1114  int nTotalSecs = qdtNow.secsTo( recStartTs ) - nPreRollSecs;
1115 
1116  //since we're not displaying seconds
1117 
1118  nTotalSecs -= 60;
1119 
1120  int nTotalDays = nTotalSecs / 86400;
1121  int nTotalHours = (nTotalSecs / 3600)
1122  - (nTotalDays * 24);
1123  int nTotalMins = (nTotalSecs / 60) % 60;
1124 
1125  QString sTimeToStart = "in";
1126 
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);
1130 
1131  if ( nTotalHours == 0 && nTotalMins == 0)
1132  sTimeToStart = QObject::tr("within one minute", "Recording starting");
1133 
1134  if ( nTotalSecs < 0)
1135  sTimeToStart = QObject::tr("soon", "Recording starting");
1136 
1137  // Output HTML
1138 
1139  os << " <a href=\"#\">";
1140  os << MythDate::toString(recStartTs.addSecs(-nPreRollSecs),
1142  MythDate::kSimplify) << " "
1143  << MythDate::toString(recStartTs.addSecs(-nPreRollSecs),
1144  MythDate::kTime) << " - ";
1145 
1146  if (nEncoderId > 0)
1147  os << "Encoder " << nEncoderId << " - ";
1148 
1149  os << sChanName << " - " << sTitle << "<br />"
1150  << "<span><strong>" << sTitle << "</strong> ("
1151  << MythDate::toString(startTs, MythDate::kTime) << "-"
1152  << MythDate::toString(endTs, MythDate::kTime) << ")<br />";
1153 
1154  if ( !sSubTitle.isEmpty())
1155  os << "<em>" << sSubTitle << "</em><br /><br />";
1156 
1157  if ( airDate.isValid())
1158  {
1159  os << "Orig. Airdate: "
1162  << "<br /><br />";
1163  }
1164 
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";
1169  }
1170  }
1171 
1172  node = node.nextSibling();
1173  }
1174  os << " </div>\r\n";
1175  os << " </div>\r\n\r\n";
1176 
1177  return( nNumRecordings );
1178 }
1179 
1181 //
1183 
1184 int V2Status::PrintFrontends( QTextStream &os, const QDomElement& frontends )
1185 {
1186  if (frontends.isNull())
1187  return( 0 );
1188 
1189  int nNumFES= frontends.attribute( "count", "0" ).toInt();
1190 
1191  if (nNumFES < 1)
1192  return( 0 );
1193 
1194 
1195  os << " <div class=\"content\">\r\n"
1196  << " <h2 class=\"status\">Frontends</h2>\r\n";
1197 
1198  QDomNode node = frontends.firstChild();
1199  while (!node.isNull())
1200  {
1201  QDomElement e = node.toElement();
1202 
1203  if (!e.isNull())
1204  {
1205  QString name = e.attribute( "name" , "" );
1206  QString url = e.attribute( "url" , "" );
1207  os << name << "&nbsp(<a href=\"" << url << "\">Status page</a>)<br />";
1208  }
1209 
1210  node = node.nextSibling();
1211  }
1212 
1213  os << " </div>\r\n\r\n";
1214 
1215  return nNumFES;
1216 }
1217 
1219 //
1221 
1222 int V2Status::PrintBackends( QTextStream &os, const QDomElement& backends )
1223 {
1224  if (backends.isNull())
1225  return( 0 );
1226 
1227  int nNumBES= backends.attribute( "count", "0" ).toInt();
1228 
1229  if (nNumBES < 1)
1230  return( 0 );
1231 
1232 
1233  os << " <div class=\"content\">\r\n"
1234  << " <h2 class=\"status\">Other Backends</h2>\r\n";
1235 
1236  QDomNode node = backends.firstChild();
1237  while (!node.isNull())
1238  {
1239  QDomElement e = node.toElement();
1240 
1241  if (!e.isNull())
1242  {
1243  QString type = e.attribute( "type", "" );
1244  QString name = e.attribute( "name" , "" );
1245  QString url = e.attribute( "url" , "" );
1246  os << type << ": " << name << "&nbsp(<a href=\"" << url << "\">Status page</a>)<br />";
1247  }
1248 
1249  node = node.nextSibling();
1250  }
1251 
1252  os << " </div>\r\n\r\n";
1253 
1254  return nNumBES;
1255 }
1256 
1258 //
1260 
1261 int V2Status::PrintJobQueue( QTextStream &os, const QDomElement& jobs )
1262 {
1263  if (jobs.isNull())
1264  return( 0 );
1265 
1266  int nNumJobs= jobs.attribute( "count", "0" ).toInt();
1267 
1268  os << " <div class=\"content\">\r\n"
1269  << " <h2 class=\"status\">Job Queue</h2>\r\n";
1270 
1271  if (nNumJobs != 0)
1272  {
1273  QString statusColor;
1274  QString jobColor;
1275 
1276  os << " Jobs currently in Queue or recently ended:\r\n<br />"
1277  << " <div class=\"schedule\">\r\n";
1278 
1279 
1280  QDomNode node = jobs.firstChild();
1281 
1282  while (!node.isNull())
1283  {
1284  QDomElement e = node.toElement();
1285 
1286  if (!e.isNull())
1287  {
1288  QDomNode progNode = e.namedItem( "Program" );
1289 
1290  if ((e.tagName() == "Job") && !progNode.isNull() )
1291  {
1292  QDomElement p = progNode.toElement();
1293 
1294  QDomNode recNode = p.namedItem( "Recording" );
1295  QDomNode chanNode = p.namedItem( "Channel" );
1296 
1297  QDomElement r = recNode.toElement();
1298  QDomElement c = chanNode.toElement();
1299 
1300  int nType = e.attribute( "type" , "0" ).toInt();
1301  int nStatus = e.attribute( "status", "0" ).toInt();
1302 
1303  switch( nStatus )
1304  {
1305  case JOB_ABORTED:
1306  statusColor = " class=\"jobaborted\"";
1307  jobColor = "";
1308  break;
1309 
1310  case JOB_ERRORED:
1311  statusColor = " class=\"joberrored\"";
1312  jobColor = " class=\"joberrored\"";
1313  break;
1314 
1315  case JOB_FINISHED:
1316  statusColor = " class=\"jobfinished\"";
1317  jobColor = " class=\"jobfinished\"";
1318  break;
1319 
1320  case JOB_RUNNING:
1321  statusColor = " class=\"jobrunning\"";
1322  jobColor = " class=\"jobrunning\"";
1323  break;
1324 
1325  default:
1326  statusColor = " class=\"jobqueued\"";
1327  jobColor = " class=\"jobqueued\"";
1328  break;
1329  }
1330 
1331  QString sTitle = p.attribute( "title" , "" ); //.replace("\"", "&quot;");
1332  QString sSubTitle = p.attribute( "subTitle", "" );
1333  QDateTime startTs = MythDate::fromString( p.attribute( "startTime" ,"" ));
1334  QDateTime endTs = MythDate::fromString( p.attribute( "endTime" ,"" ));
1335  QDateTime recStartTs = MythDate::fromString( r.attribute( "recStartTs","" ));
1336  QDateTime statusTime = MythDate::fromString( e.attribute( "statusTime","" ));
1337  QDateTime schedRunTime = MythDate::fromString( e.attribute( "schedTime","" ));
1338  QString sHostname = e.attribute( "hostname", "master" );
1339  QString sComment = "";
1340 
1341  QDomText text = e.firstChild().toText();
1342  if (!text.isNull())
1343  sComment = text.nodeValue();
1344 
1345  os << "<a href=\"javascript:void(0)\">"
1346  << MythDate::toString(recStartTs, MythDate::kDateFull |
1348  << " - "
1349  << sTitle << " - <font" << jobColor << ">"
1350  << JobQueue::JobText( nType ) << "</font><br />"
1351  << "<span><strong>" << sTitle << "</strong> ("
1352  << MythDate::toString(startTs, MythDate::kTime) << "-"
1353  << MythDate::toString(endTs, MythDate::kTime) << ")<br />";
1354 
1355  if (!sSubTitle.isEmpty())
1356  os << "<em>" << sSubTitle << "</em><br /><br />";
1357 
1358  os << "Job: " << JobQueue::JobText( nType ) << "<br />";
1359 
1360  if (schedRunTime > MythDate::current())
1361  {
1362  os << "Scheduled Run Time: "
1363  << MythDate::toString(schedRunTime,
1366  << "<br />";
1367  }
1368 
1369  os << "Status: <font" << statusColor << ">"
1370  << JobQueue::StatusText( nStatus )
1371  << "</font><br />"
1372  << "Status Time: "
1373  << MythDate::toString(statusTime, MythDate::kDateFull |
1375  << "<br />";
1376 
1377  if ( nStatus != JOB_QUEUED)
1378  os << "Host: " << sHostname << "<br />";
1379 
1380  if (!sComment.isEmpty())
1381  os << "<br />Comments:<br />" << sComment << "<br />";
1382 
1383  os << "</span></a><hr />\r\n";
1384  }
1385  }
1386 
1387  node = node.nextSibling();
1388  }
1389  os << " </div>\r\n";
1390  }
1391  else
1392  os << " Job Queue is currently empty.\r\n\r\n";
1393 
1394  os << " </div>\r\n\r\n ";
1395 
1396  return( nNumJobs );
1397 
1398 }
1399 
1401 //
1403 
1404 int V2Status::PrintMachineInfo( QTextStream &os, const QDomElement& info )
1405 {
1406  QString sRep;
1407 
1408  if (info.isNull())
1409  return( 0 );
1410 
1411  os << "<div class=\"content\">\r\n"
1412  << " <h2 class=\"status\">Machine Information</h2>\r\n";
1413 
1414  // load average ---------------------
1415 
1416  QDomNode node = info.namedItem( "Load" );
1417 
1418  if (!node.isNull())
1419  {
1420  QDomElement e = node.toElement();
1421 
1422  if (!e.isNull())
1423  {
1424  double dAvg1 = e.attribute( "avg1" , "0" ).toDouble();
1425  double dAvg2 = e.attribute( "avg2" , "0" ).toDouble();
1426  double dAvg3 = e.attribute( "avg3" , "0" ).toDouble();
1427 
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"
1435  << " </div>\r\n";
1436  }
1437  }
1438 
1439  // local drive space ---------------------
1440  node = info.namedItem( "Storage" );
1441  QDomElement storage = node.toElement();
1442  node = storage.firstChild();
1443 
1444  // Loop once until we find id == "total". This should be first, but a loop
1445  // separate from the per-filesystem details loop ensures total is first,
1446  // regardless.
1447  while (!node.isNull())
1448  {
1449  QDomElement g = node.toElement();
1450 
1451  if (!g.isNull() && g.tagName() == "Group")
1452  {
1453  QString id = g.attribute("id", "" );
1454 
1455  if (id == "total")
1456  {
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" , "" );
1464 
1465  nDir.replace(",", ", ");
1466 
1467  os << " Disk Usage Summary:<br />\r\n";
1468  os << " <ul>\r\n";
1469 
1470  os << " <li>Total Disk Space:\r\n"
1471  << " <ul>\r\n";
1472 
1473  os << " <li>Total Space: ";
1474  sRep = QString("%L1").arg(nTotal) + " MB";
1475  os << sRep << "</li>\r\n";
1476 
1477  os << " <li>Space Used: ";
1478  sRep = QString("%L1").arg(nUsed) + " MB";
1479  os << sRep << "</li>\r\n";
1480 
1481  os << " <li>Space Free: ";
1482  sRep = QString("%L1").arg(nFree) + " MB";
1483  os << sRep << "</li>\r\n";
1484 
1485  if ((nLiveTV + nDeleted + nExpirable) > 0)
1486  {
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";
1493  os << " <ul>\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";
1505  os << " </ul>\r\n";
1506  os << " </li>\r\n";
1507  }
1508 
1509  os << " </ul>\r\n"
1510  << " </li>\r\n";
1511 
1512  os << " </ul>\r\n";
1513  break;
1514  }
1515  }
1516 
1517  node = node.nextSibling();
1518  }
1519 
1520  // Loop again to handle per-filesystem details.
1521  node = storage.firstChild();
1522 
1523  os << " Disk Usage Details:<br />\r\n";
1524  os << " <ul>\r\n";
1525 
1526 
1527  while (!node.isNull())
1528  {
1529  QDomElement g = node.toElement();
1530 
1531  if (!g.isNull() && g.tagName() == "Group")
1532  {
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" , "" );
1538 
1539  nDir.replace(",", ", ");
1540 
1541 
1542  if (id != "total")
1543  {
1544 
1545  os << " <li>MythTV Drive #" << id << ":"
1546  << "\r\n"
1547  << " <ul>\r\n";
1548 
1549  if (nDir.contains(','))
1550  os << " <li>Directories: ";
1551  else
1552  os << " <li>Directory: ";
1553 
1554  os << nDir << "</li>\r\n";
1555 
1556  os << " <li>Total Space: ";
1557  sRep = QString("%L1").arg(nTotal) + " MB";
1558  os << sRep << "</li>\r\n";
1559 
1560  os << " <li>Space Used: ";
1561  sRep = QString("%L1").arg(nUsed) + " MB";
1562  os << sRep << "</li>\r\n";
1563 
1564  os << " <li>Space Free: ";
1565  sRep = QString("%L1").arg(nFree) + " MB";
1566  os << sRep << "</li>\r\n";
1567 
1568  os << " </ul>\r\n"
1569  << " </li>\r\n";
1570  }
1571 
1572  }
1573 
1574  node = node.nextSibling();
1575  }
1576 
1577  os << " </ul>\r\n";
1578 
1579  // Guide Info ---------------------
1580 
1581  node = info.namedItem( "Guide" );
1582 
1583  if (!node.isNull())
1584  {
1585  QDomElement e = node.toElement();
1586 
1587  if (!e.isNull())
1588  {
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" , "" );
1593  QDateTime next = MythDate::fromString( e.attribute( "next" , "" ));
1594  QString sNext = next.isNull() ? "" :
1596  QString sMsg = "";
1597 
1598  QDateTime thru = MythDate::fromString( e.attribute( "guideThru", "" ));
1599 
1600  QDomText text = e.firstChild().toText();
1601 
1602  QString mfdblrs =
1603  gCoreContext->GetSetting("mythfilldatabaseLastRunStart");
1604  QDateTime lastrunstart = MythDate::fromString(mfdblrs);
1605 
1606  if (!text.isNull())
1607  sMsg = text.nodeValue();
1608 
1609  os << " Last mythfilldatabase run started on " << sStart
1610  << " and ";
1611 
1612  if (sEnd < sStart)
1613  os << "is ";
1614  else
1615  os << "ended on " << sEnd << ". ";
1616 
1617  os << sStatus << "<br />\r\n";
1618 
1619  if (!next.isNull() && next >= lastrunstart)
1620  {
1621  os << " Suggested next mythfilldatabase run: "
1622  << sNext << ".<br />\r\n";
1623  }
1624 
1625  if (!thru.isNull())
1626  {
1627  os << " There's guide data until "
1629 
1630  if (nDays > 0)
1631  os << " " << QObject::tr("(%n day(s))", "", nDays);
1632 
1633  os << ".";
1634 
1635  if (nDays <= 3)
1636  os << " <strong>WARNING</strong>: is mythfilldatabase running?";
1637  }
1638  else
1639  os << " There's <strong>no guide data</strong> available! "
1640  << "Have you run mythfilldatabase?";
1641  }
1642  }
1643  os << "\r\n </div>\r\n";
1644 
1645  return( 1 );
1646 }
1647 
1648 int V2Status::PrintMiscellaneousInfo( QTextStream &os, const QDomElement& info )
1649 {
1650  if (info.isNull())
1651  return( 0 );
1652 
1653  // Miscellaneous information
1654 
1655  QDomNodeList nodes = info.elementsByTagName("Information");
1656  uint count = nodes.count();
1657  if (count > 0)
1658  {
1659  QString display;
1660  QString linebreak;
1661  //QString name, value;
1662  os << "<div class=\"content\">\r\n"
1663  << " <h2 class=\"status\">Miscellaneous</h2>\r\n";
1664  for (unsigned int i = 0; i < count; i++)
1665  {
1666  QDomNode node = nodes.item(i);
1667  if (node.isNull())
1668  continue;
1669 
1670  QDomElement e = node.toElement();
1671  if (e.isNull())
1672  continue;
1673 
1674  display = e.attribute("display", "");
1675  //name = e.attribute("name", "");
1676  //value = e.attribute("value", "");
1677 
1678  if (display.isEmpty())
1679  continue;
1680 
1681  // Only include HTML line break if display value doesn't already
1682  // contain breaks.
1683  if (display.contains("<p>", Qt::CaseInsensitive) ||
1684  display.contains("<br", Qt::CaseInsensitive))
1685  {
1686  // matches <BR> or <br /
1687  linebreak = "\r\n";
1688  }
1689  else
1690  linebreak = "<br />\r\n";
1691 
1692  os << " " << display << linebreak;
1693  }
1694  os << "</div>\r\n";
1695  }
1696 
1697  return( 1 );
1698 }
1699 
1700 void V2Status::FillProgramInfo(QDomDocument *pDoc,
1701  QDomNode &node,
1702  ProgramInfo *pInfo,
1703  bool bIncChannel /* = true */,
1704  bool bDetails /* = true */)
1705 {
1706  if ((pDoc == nullptr) || (pInfo == nullptr))
1707  return;
1708 
1709  // Build Program Element
1710 
1711  QDomElement program = pDoc->createElement( "Program" );
1712  node.appendChild( program );
1713 
1714  program.setAttribute( "startTime" ,
1716  program.setAttribute( "endTime" , pInfo->GetScheduledEndTime(MythDate::ISODate));
1717  program.setAttribute( "title" , pInfo->GetTitle() );
1718  program.setAttribute( "subTitle" , pInfo->GetSubtitle());
1719  program.setAttribute( "category" , pInfo->GetCategory());
1720  program.setAttribute( "catType" , pInfo->GetCategoryTypeString());
1721  program.setAttribute( "repeat" , static_cast<int>(pInfo->IsRepeat()));
1722 
1723  if (bDetails)
1724  {
1725 
1726  program.setAttribute( "seriesId" , pInfo->GetSeriesID() );
1727  program.setAttribute( "programId" , pInfo->GetProgramID() );
1728  program.setAttribute( "stars" , pInfo->GetStars() );
1729  program.setAttribute( "fileSize" ,
1730  QString::number( pInfo->GetFilesize() ));
1731  program.setAttribute( "lastModified",
1733  program.setAttribute( "programFlags", pInfo->GetProgramFlags() );
1734  program.setAttribute( "hostname" , pInfo->GetHostname() );
1735 
1736  if (pInfo->GetOriginalAirDate().isValid())
1737  program.setAttribute(
1738  "airdate", pInfo->GetOriginalAirDate().toString());
1739 
1740  QDomText textNode = pDoc->createTextNode( pInfo->GetDescription() );
1741  program.appendChild( textNode );
1742 
1743  }
1744 
1745  if ( bIncChannel )
1746  {
1747  // Build Channel Child Element
1748 
1749  QDomElement channel = pDoc->createElement( "Channel" );
1750  program.appendChild( channel );
1751 
1752  FillChannelInfo( channel, pInfo, bDetails );
1753  }
1754 
1755  // Build Recording Child Element
1756 
1757  if ( pInfo->GetRecordingStatus() != RecStatus::Unknown )
1758  {
1759  QDomElement recording = pDoc->createElement( "Recording" );
1760  program.appendChild( recording );
1761 
1762  recording.setAttribute( "recStatus" ,
1763  pInfo->GetRecordingStatus() );
1764  recording.setAttribute( "recPriority" ,
1765  pInfo->GetRecordingPriority() );
1766  recording.setAttribute( "recStartTs" ,
1768  recording.setAttribute( "recEndTs" ,
1770 
1771  if (bDetails)
1772  {
1773  recording.setAttribute( "recordId" ,
1774  pInfo->GetRecordingRuleID() );
1775  recording.setAttribute( "recGroup" ,
1776  pInfo->GetRecordingGroup() );
1777  recording.setAttribute( "playGroup" ,
1778  pInfo->GetPlaybackGroup() );
1779  recording.setAttribute( "recType" ,
1780  pInfo->GetRecordingRuleType() );
1781  recording.setAttribute( "dupInType" ,
1782  pInfo->GetDuplicateCheckSource() );
1783  recording.setAttribute( "dupMethod" ,
1784  pInfo->GetDuplicateCheckMethod() );
1785  recording.setAttribute( "encoderId" ,
1786  pInfo->GetInputID() );
1787  const RecordingInfo ri(*pInfo);
1788  recording.setAttribute( "recProfile" ,
1790  //recording.setAttribute( "preRollSeconds", m_nPreRollSeconds );
1791  }
1792  }
1793 }
1794 
1796 //
1798 
1799 void V2Status::FillChannelInfo( QDomElement &channel,
1800  ProgramInfo *pInfo,
1801  bool bDetails /* = true */ )
1802 {
1803  if (pInfo)
1804  {
1805 /*
1806  QString sHostName = gCoreContext->GetHostName();
1807  QString sPort = gCoreContext->GetSettingOnHost( "BackendStatusPort",
1808  sHostName);
1809  QString sIconURL = QString( "http://%1:%2/getChannelIcon?ChanId=%3" )
1810  .arg( sHostName )
1811  .arg( sPort )
1812  .arg( pInfo->chanid );
1813 */
1814 
1815  channel.setAttribute( "chanId" , pInfo->GetChanID() );
1816  channel.setAttribute( "chanNum" , pInfo->GetChanNum());
1817  channel.setAttribute( "callSign" , pInfo->GetChannelSchedulingID());
1818  //channel.setAttribute( "iconURL" , sIconURL );
1819  channel.setAttribute( "channelName", pInfo->GetChannelName());
1820 
1821  if (bDetails)
1822  {
1823  channel.setAttribute( "chanFilters",
1824  pInfo->GetChannelPlaybackFilters() );
1825  channel.setAttribute( "sourceId" , pInfo->GetSourceID() );
1826  channel.setAttribute( "inputId" , pInfo->GetInputID() );
1827  channel.setAttribute( "commFree" ,
1828  (pInfo->IsCommercialFree()) ? 1 : 0 );
1829  }
1830  }
1831 }
1832 
1833 
1834 
1835 
1836 // vim:set shiftwidth=4 tabstop=4 expandtab:
setting_to_localtime
static QString setting_to_localtime(const char *setting)
Definition: v2status.cpp:129
Scheduler
Definition: scheduler.h:45
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:811
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
Scheduler::GetMainServer
MainServer * GetMainServer()
Definition: scheduler.h:104
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:84
tv.h
V2Status::PrintMiscellaneousInfo
static int PrintMiscellaneousInfo(QTextStream &os, const QDomElement &info)
Definition: v2status.cpp:1648
MythCoreContext::GetMasterHostName
QString GetMasterHostName(void)
Definition: mythcorecontext.cpp:806
ProgramInfo::GetFilesize
virtual uint64_t GetFilesize(void) const
Definition: programinfo.cpp:6345
backendcontext.h
CardUtil::GetDeviceLabel
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
Definition: cardutil.cpp:2625
V2FillProgramInfo
void V2FillProgramInfo(V2Program *pProgram, ProgramInfo *pInfo, bool bIncChannel, bool bDetails, bool bIncCast, bool bIncArtwork, bool bIncRecording)
Definition: v2serviceUtil.cpp:33
ReferenceCounter::DecrRef
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
Definition: referencecounter.cpp:125
ProgramInfo::GetHostname
QString GetHostname(void) const
Definition: programinfo.h:421
MythCoreContext::GetScheduler
MythScheduler * GetScheduler(void)
Definition: mythcorecontext.cpp:1874
V2Status::m_pSched
Scheduler * m_pSched
Definition: v2status.h:60
MythSystemLegacy
Definition: mythsystemlegacy.h:67
V2Status::PrintJobQueue
static int PrintJobQueue(QTextStream &os, const QDomElement &jobs)
Definition: v2status.cpp:1261
SleepStatus
SleepStatus
SleepStatus is an enumeration of the awake/sleep status of a slave.
Definition: tv.h:97
FillUpcomingList
int FillUpcomingList(QVariantList &list, QObject *parent, int &nStartIndex, int &nCount, bool bShowAll, int nRecordId, int nRecStatus)
Definition: v2serviceUtil.cpp:763
RecordingInfo
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:35
V2Status::FillProgramInfo
static void FillProgramInfo(QDomDocument *pDoc, QDomNode &node, ProgramInfo *pInfo, bool bIncChannel=true, bool bDetails=true)
Definition: v2status.cpp:1700
ProgramInfo::GetChannelName
QString GetChannelName(void) const
This is the channel name in the local market, i.e.
Definition: programinfo.h:386
ProgramInfo::GetChanNum
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:376
MainServer::BackendQueryDiskSpace
void BackendQueryDiskSpace(QStringList &strlist, bool consolidated, bool allHosts)
Definition: mainserver.cpp:5169
getLoadAvgs
loadArray getLoadAvgs(void)
Returns the system load averages.
Definition: mythmiscutil.cpp:175
V2Status::PrintBackends
static int PrintBackends(QTextStream &os, const QDomElement &backends)
Definition: v2status.cpp:1222
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:205
mythdbcon.h
SSDP::Find
static SSDPCacheEntries * Find(const QString &sURI)
Definition: ssdp.h:132
ProgramInfo::GetChannelSchedulingID
QString GetChannelSchedulingID(void) const
This is the unique programming identifier of a channel.
Definition: programinfo.h:383
ProgramInfo::GetCategory
QString GetCategory(void) const
Definition: programinfo.h:369
RecStatus::Unknown
@ Unknown
Definition: recordingstatus.h:32
mythhttpmetaservice.h
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:617
JOB_LIST_NOT_DONE
@ JOB_LIST_NOT_DONE
Definition: jobqueue.h:71
V2Status::FillDriveSpace
void FillDriveSpace(V2MachineInfo *pMachineInfo)
Definition: v2status.cpp:303
ProgramInfo::GetScheduledEndTime
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:397
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MythSystemLegacy::ReadAll
QByteArray & ReadAll()
Definition: mythsystemlegacy.cpp:402
V2Status::Status
Preformat * Status()
Definition: v2status.cpp:88
V2Status::GetBackendStatus
V2BackendStatus * GetBackendStatus()
Definition: v2status.cpp:144
SSDPCacheEntries::GetEntryMap
void GetEntryMap(EntryMap &map)
Returns a copy of the EntryMap.
Definition: ssdpcache.cpp:93
V2Job::Program
QObject Program
Definition: v2backendStatus.h:124
ProgramInfo::GetRecordingEndTime
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end.
Definition: programinfo.h:412
GENERIC_EXIT_OK
@ GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:11
ProgramInfo::GetProgramFlags
uint32_t GetProgramFlags(void) const
Definition: programinfo.h:470
ProgramInfo::GetRecordingGroup
QString GetRecordingGroup(void) const
Definition: programinfo.h:419
ProgramInfo::GetRecordingPriority
int GetRecordingPriority(void) const
Definition: programinfo.h:440
V2Status::m_bIsMaster
bool m_bIsMaster
Definition: v2status.h:63
scheduler.h
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:14
MythCoreContext::GetMasterServerStatusPort
int GetMasterServerStatusPort(void)
Returns the Master Backend status port If no master server status port has been defined in the databa...
Definition: mythcorecontext.cpp:992
ProgramInfo::GetRecordingStartTime
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:404
FillFrontendList
void FillFrontendList(QVariantList &list, QObject *parent, bool OnLine)
Definition: v2serviceUtil.cpp:837
MainServer::GetMediaServerByHostname
PlaybackSock * GetMediaServerByHostname(const QString &hostname)
Definition: mainserver.cpp:7994
mythsystemlegacy.h
kState_WatchingRecording
@ kState_WatchingRecording
Watching Recording is the state for when we are watching an in progress recording,...
Definition: tv.h:80
JobQueue::JobText
static QString JobText(int jobType)
Definition: jobqueue.cpp:1111
ProgramInfo::IsRepeat
bool IsRepeat(void) const
Definition: programinfo.h:487
RecStatus::WillRecord
@ WillRecord
Definition: recordingstatus.h:31
RecordingInfo::GetProgramRecordingProfile
QString GetProgramRecordingProfile(void) const
Returns recording profile name that will be, or was used, for this program, creating "record" field i...
Definition: recordinginfo.cpp:492
MythCoreContext::IsMasterBackend
bool IsMasterBackend(void)
is this the actual MBE process
Definition: mythcorecontext.cpp:694
V2MachineInfo
Definition: v2backendStatus.h:68
JobQueue::GetJobsInQueue
static int GetJobsInQueue(QMap< int, JobQueueEntry > &jobs, int findJobs=JOB_LIST_NOT_DONE)
Definition: jobqueue.cpp:1275
mythdate.h
autoexpire.h
upnp.h
V2BackendStatus
Definition: v2backendStatus.h:139
ProgramInfo::GetScheduledStartTime
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:390
ProgramInfo::GetRecordingStatus
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:447
v2serviceUtil.h
hardwareprofile.config.p
p
Definition: config.py:33
MythCoreContext::GetMasterServerIP
QString GetMasterServerIP(void)
Returns the Master Backend IP address If the address is an IPv6 address, the scope Id is removed.
Definition: mythcorecontext.cpp:965
FillEncoderList
void FillEncoderList(QVariantList &list, QObject *parent)
Definition: v2serviceUtil.cpp:700
ProgramInfo::GetTitle
QString GetTitle(void) const
Definition: programinfo.h:361
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:549
ProgramInfo::GetDescription
QString GetDescription(void) const
Definition: programinfo.h:365
compat.h
MythCoreContext::GetBackendServerIP
QString GetBackendServerIP(void)
Returns the IP address of the locally defined backend IP.
Definition: mythcorecontext.cpp:1003
STATUS_HANDLE
#define STATUS_HANDLE
Definition: v2status.h:35
V2MachineInfo::AddNewStorageGroup
V2StorageGroup * AddNewStorageGroup()
Definition: v2backendStatus.h:89
ProgramInfo::GetSourceID
uint GetSourceID(void) const
Definition: programinfo.h:462
EntryMap
QMap< QString, DeviceLocation * > EntryMap
Key == Unique Service Name (USN)
Definition: ssdpcache.h:29
MythSystemLegacy::Wait
uint Wait(std::chrono::seconds timeout=0s)
Definition: mythsystemlegacy.cpp:243
MythDate::kDateShort
@ kDateShort
Default local time.
Definition: mythdate.h:20
V2Status::PrintStatus
static void PrintStatus(QTextStream &os, QDomDocument *pDoc)
Definition: v2status.cpp:820
sStatus_Asleep
@ sStatus_Asleep
A slave is considered asleep when it is not awake and not undefined.
Definition: tv.h:104
loadArray
std::array< double, 3 > loadArray
Definition: mythmiscutil.h:22
ProgramInfo::GetPlaybackGroup
QString GetPlaybackGroup(void) const
Definition: programinfo.h:420
jobqueue.h
ProgramInfo::GetChannelPlaybackFilters
QString GetChannelPlaybackFilters(void) const
Definition: programinfo.h:387
V2Status::GetStatusHTML
Preformat * GetStatusHTML()
Definition: v2status.cpp:116
TVRec::s_inputsLock
static QReadWriteLock s_inputsLock
Definition: tv_rec.h:433
V2Status::m_nPreRollSeconds
int m_nPreRollSeconds
Definition: v2status.h:64
SSDPCacheEntries
Definition: ssdpcache.h:35
uint
unsigned int uint
Definition: compat.h:81
V2Status::GetStatus
Preformat * GetStatus()
Definition: v2status.cpp:100
gTVList
QMap< int, EncoderLink * > gTVList
Definition: backendcontext.cpp:7
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
ProgramInfo::GetSeriesID
QString GetSeriesID(void) const
Definition: programinfo.h:435
V2Status::RegisterCustomTypes
static void RegisterCustomTypes()
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:911
MythHTTPService
Definition: mythhttpservice.h:19
V2Status::PrintEncoderStatus
static int PrintEncoderStatus(QTextStream &os, const QDomElement &encoders)
Definition: v2status.cpp:907
PlaybackSock
Definition: playbacksock.h:27
ProgramInfo::GetOriginalAirDate
QDate GetOriginalAirDate(void) const
Definition: programinfo.h:428
V2Status::xml
Preformat * xml()
Definition: v2status.cpp:94
Q_GLOBAL_STATIC_WITH_ARGS
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(STATUS_HANDLE, V2Status::staticMetaObject, &V2Status::RegisterCustomTypes)) void V2Status
Definition: v2status.cpp:54
kMSRunShell
@ kMSRunShell
run process through shell
Definition: mythsystem.h:43
V2Status::m_pEncoders
QMap< int, EncoderLink * > * m_pEncoders
Definition: v2status.h:61
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
MythDate::kSimplify
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:26
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:905
ProgramInfo::GetDuplicateCheckMethod
RecordingDupMethodType GetDuplicateCheckMethod(void) const
What should be compared to determine if two programs are the same?
Definition: programinfo.h:459
ProgramInfo::GetInputID
uint GetInputID(void) const
Definition: programinfo.h:463
sStatus_Undefined
@ sStatus_Undefined
A slave's sleep status is undefined when it has never connected to the master backend or is not able ...
Definition: tv.h:117
ProgramInfo::GetChanID
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:372
V2Backend
Definition: v2backendStatus.h:23
ProgramInfo::GetRecordingRuleType
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:451
ProgramInfo
Holds information on recordings and videos.
Definition: programinfo.h:67
setting_to_qdatetime
static QDateTime setting_to_qdatetime(const char *setting)
Definition: v2status.cpp:136
v2backendStatus.h
mythmiscutil.h
TVState
TVState
TVState is an enumeration of the states used by TV and TVRec.
Definition: tv.h:50
MythDate::kAddYear
@ kAddYear
Add year to string if not included.
Definition: mythdate.h:25
ProgramInfo::GetLastModifiedTime
QDateTime GetLastModifiedTime(void) const
Definition: programinfo.h:429
mythcorecontext.h
cardutil.h
ProgramInfo::GetCategoryTypeString
QString GetCategoryTypeString(void) const
Returns catType as a string.
Definition: programinfo.cpp:1887
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:887
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:17
V2Job
Definition: v2backendStatus.h:103
V2Status::FillChannelInfo
static void FillChannelInfo(QDomElement &channel, ProgramInfo *pInfo, bool bDetails=true)
Definition: v2status.cpp:1799
RecList
std::deque< RecordingInfo * > RecList
Definition: mythscheduler.h:12
V2Status::PrintScheduled
static int PrintScheduled(QTextStream &os, const QDomElement &scheduled)
Definition: v2status.cpp:1051
V2Program
Definition: v2programAndChannel.h:105
tv_rec.h
kState_WatchingLiveTV
@ kState_WatchingLiveTV
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:63
ProgramInfo::GetDuplicateCheckSource
RecordingDupInType GetDuplicateCheckSource(void) const
Where should we check for duplicates?
Definition: programinfo.h:455
mainserver.h
MythDate::kDatabase
@ kDatabase
Default UTC, database format.
Definition: mythdate.h:27
MythDate::kDateFull
@ kDateFull
Default local time.
Definition: mythdate.h:19
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:837
Scheduler::GetAllPending
bool GetAllPending(RecList &retList, int recRuleId=0) const
Definition: scheduler.cpp:1741
JOB_LIST_RECENT
@ JOB_LIST_RECENT
Definition: jobqueue.h:73
Preformat
Definition: preformat.h:19
ProgramInfo::GetProgramID
QString GetProgramID(void) const
Definition: programinfo.h:436
V2Status::PrintFrontends
static int PrintFrontends(QTextStream &os, const QDomElement &frontends)
Definition: v2status.cpp:1184
MythSystemLegacy::Run
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
Definition: mythsystemlegacy.cpp:213
MythCoreContext::IsMasterHost
bool IsMasterHost(void)
is this the same host as the master
Definition: mythcorecontext.cpp:658
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
V2Status::m_pMainServer
MainServer * m_pMainServer
Definition: v2status.h:62
MythDate::kDateTimeFull
@ kDateTimeFull
Default local time.
Definition: mythdate.h:23
PlaybackSock::getIP
QString getIP(void) const
Definition: playbacksock.h:60
V2StorageGroup
Definition: v2backendStatus.h:46
MythDate::kTime
@ kTime
Default local time.
Definition: mythdate.h:22
ProgramInfo::GetRecordingRuleID
uint GetRecordingRuleID(void) const
Definition: programinfo.h:449
exitcodes.h
JOB_LIST_ERROR
@ JOB_LIST_ERROR
Definition: jobqueue.h:72
UPnp::g_IPAddrList
static QList< QHostAddress > g_IPAddrList
Definition: upnp.h:110
MainServer::GetActiveBackends
void GetActiveBackends(QStringList &hosts)
Definition: mainserver.cpp:5083
V2Status::FillStatusXML
void FillStatusXML(QDomDocument *pDoc)
Definition: v2status.cpp:371
V2Status::V2Status
V2Status()
Definition: v2status.cpp:77
kMSStdOut
@ kMSStdOut
allow access to stdout
Definition: mythsystem.h:41
output
#define output
Definition: synaesthesia.cpp:220
kState_RecordingOnly
@ kState_RecordingOnly
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:84
ProgramInfo::IsCommercialFree
bool IsCommercialFree(void) const
Definition: programinfo.h:477
PlaybackSock::setIP
void setIP(const QString &lip)
Definition: playbacksock.h:59
MythHTTPMetaService
Definition: mythhttpmetaservice.h:10
v2status.h
JobQueue::StatusText
static QString StatusText(int status)
Definition: jobqueue.cpp:1134
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:897
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:836
ProgramInfo::GetSubtitle
QString GetSubtitle(void) const
Definition: programinfo.h:363
ProgramInfo::GetStars
float GetStars(void) const
Definition: programinfo.h:442
V2Status::PrintMachineInfo
static int PrintMachineInfo(QTextStream &os, const QDomElement &info)
Definition: v2status.cpp:1404