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