MythTV  0.28pre
httpstatus.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 <QTextStream>
21 #include <QRegExp>
22 #include <QLocale>
23 
24 // MythTV headers
25 #include "httpstatus.h"
26 
27 #include "mythcorecontext.h"
28 #include "mythversion.h"
29 #include "mythdbcon.h"
30 #include "compat.h"
31 #include "mythconfig.h"
32 #include "autoexpire.h"
33 #include "tv.h"
34 #include "encoderlink.h"
35 #include "scheduler.h"
36 #include "mainserver.h"
37 #include "cardutil.h"
38 #include "mythsystemlegacy.h"
39 #include "exitcodes.h"
40 #include "jobqueue.h"
41 #include "upnp.h"
42 #include "mythdate.h"
43 
45 //
47 
48 HttpStatus::HttpStatus( QMap<int, EncoderLink *> *tvList, Scheduler *sched,
49  AutoExpire *expirer, bool bIsMaster )
50  : HttpServerExtension( "HttpStatus" , QString())
51 {
53  m_pSched = sched;
55  m_bIsMaster = bIsMaster;
56 
57  m_nPreRollSeconds = gCoreContext->GetNumSetting("RecordPreRoll", 0);
58 
59  m_pMainServer = NULL;
60 }
61 
63 //
65 
67 {
68 }
69 
71 //
73 
75 {
76  if (sURI == "Status" ) return( HSM_GetStatusHTML );
77  if (sURI == "GetStatusHTML" ) return( HSM_GetStatusHTML );
78  if (sURI == "GetStatus" ) return( HSM_GetStatusXML );
79  if (sURI == "xml" ) return( HSM_GetStatusXML );
80 
81  return( HSM_Unknown );
82 }
83 
85 //
87 
89 {
90  return QStringList( "/Status" );
91 }
92 
94 //
96 
98 {
99  try
100  {
101  if (pRequest)
102  {
103  if ((pRequest->m_sBaseUrl != "/Status" ) &&
104  (pRequest->m_sResourceUrl != "/Status" ))
105  {
106  return( false );
107  }
108 
109  switch( GetMethod( pRequest->m_sMethod ))
110  {
111  case HSM_GetStatusXML : GetStatusXML ( pRequest ); return true;
112  case HSM_GetStatusHTML : GetStatusHTML ( pRequest ); return true;
113 
114  default:
115  {
116  pRequest->m_eResponseType = ResponseTypeHTML;
117  pRequest->m_nResponseStatus = 200;
118 
119  break;
120  }
121  }
122  }
123  }
124  catch( ... )
125  {
126  LOG(VB_GENERAL, LOG_ERR,
127  "HttpStatus::ProcessRequest() - Unexpected Exception");
128  }
129 
130  return( false );
131 }
132 
134 //
136 
138 {
139  QDomDocument doc( "Status" );
140 
141  // UTF-8 is the default, but good practice to specify it anyway
142  QDomProcessingInstruction encoding =
143  doc.createProcessingInstruction("xml",
144  "version=\"1.0\" encoding=\"UTF-8\"");
145  doc.appendChild(encoding);
146 
147  FillStatusXML( &doc );
148 
149  pRequest->m_eResponseType = ResponseTypeXML;
150  pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
151 
152  QTextStream stream( &pRequest->m_response );
153  stream.setCodec("UTF-8"); // Otherwise locale default is used.
154  stream << doc.toString();
155 }
156 
158 //
160 
162 {
163  pRequest->m_eResponseType = ResponseTypeHTML;
164  pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
165 
166  QDomDocument doc( "Status" );
167 
168  FillStatusXML( &doc );
169 
170  QTextStream stream( &pRequest->m_response );
171  PrintStatus( stream, &doc );
172 }
173 
174 static QString setting_to_localtime(const char *setting)
175 {
176  QString origDateString = gCoreContext->GetSetting(setting);
177  QDateTime origDate = MythDate::fromString(origDateString);
179 }
180 
181 void HttpStatus::FillStatusXML( QDomDocument *pDoc )
182 {
183  QDateTime qdtNow = MythDate::current();
184 
185  // Add Root Node.
186 
187  QDomElement root = pDoc->createElement("Status");
188  pDoc->appendChild(root);
189 
190  root.setAttribute("date" , MythDate::toString(
192  root.setAttribute("time" ,
194  root.setAttribute("ISODate" , qdtNow.toString(Qt::ISODate) );
195  root.setAttribute("version" , MYTH_BINARY_VERSION );
196  root.setAttribute("protoVer", MYTH_PROTO_VERSION );
197 
198  // Add all encoders, if any
199 
200  QDomElement encoders = pDoc->createElement("Encoders");
201  root.appendChild(encoders);
202 
203  int numencoders = 0;
204  bool isLocal = true;
205 
206  QMap<int, EncoderLink *>::Iterator iter = m_pEncoders->begin();
207 
208  for (; iter != m_pEncoders->end(); ++iter)
209  {
210  EncoderLink *elink = *iter;
211 
212  if (elink != NULL)
213  {
214  TVState state = elink->GetState();
215  isLocal = elink->IsLocal();
216 
217  QDomElement encoder = pDoc->createElement("Encoder");
218  encoders.appendChild(encoder);
219 
220  encoder.setAttribute("id" , elink->GetInputID() );
221  encoder.setAttribute("local" , isLocal );
222  encoder.setAttribute("connected" , elink->IsConnected() );
223  encoder.setAttribute("state" , state );
224  encoder.setAttribute("sleepstatus" , elink->GetSleepStatus() );
225  //encoder.setAttribute("lowOnFreeSpace", elink->isLowOnFreeSpace());
226 
227  if (isLocal)
228  encoder.setAttribute("hostname", gCoreContext->GetHostName());
229  else
230  encoder.setAttribute("hostname", elink->GetHostName());
231 
232  encoder.setAttribute("devlabel",
234 
235  if (elink->IsConnected())
236  numencoders++;
237 
238  switch (state)
239  {
243  {
244  ProgramInfo *pInfo = elink->GetRecording();
245 
246  if (pInfo)
247  {
248  FillProgramInfo(pDoc, encoder, pInfo);
249  delete pInfo;
250  }
251 
252  break;
253  }
254 
255  default:
256  break;
257  }
258  }
259  }
260 
261  encoders.setAttribute("count", numencoders);
262 
263  // Add upcoming shows
264 
265  QDomElement scheduled = pDoc->createElement("Scheduled");
266  root.appendChild(scheduled);
267 
268  RecList recordingList;
269 
270  if (m_pSched)
271  m_pSched->GetAllPending(recordingList);
272 
273  unsigned int iNum = 10;
274  unsigned int iNumRecordings = 0;
275 
276  RecConstIter itProg = recordingList.begin();
277  for (; (itProg != recordingList.end()) && iNumRecordings < iNum; ++itProg)
278  {
279  if (((*itProg)->GetRecordingStatus() <= RecStatus::WillRecord) &&
280  ((*itProg)->GetRecordingStartTime() >=
282  {
283  iNumRecordings++;
284  FillProgramInfo(pDoc, scheduled, *itProg);
285  }
286  }
287 
288  while (!recordingList.empty())
289  {
290  ProgramInfo *pginfo = recordingList.back();
291  delete pginfo;
292  recordingList.pop_back();
293  }
294 
295  scheduled.setAttribute("count", iNumRecordings);
296 
297  // Add known frontends
298 
299  QDomElement frontends = pDoc->createElement("Frontends");
300  root.appendChild(frontends);
301 
303  "urn:schemas-mythtv-org:service:MythFrontend:1");
304  if (fes)
305  {
306  EntryMap map;
307  fes->GetEntryMap(map);
308  fes->DecrRef();
309  fes = NULL;
310 
311  frontends.setAttribute( "count", map.size() );
312  for (EntryMap::iterator it = map.begin(); it != map.end(); ++it)
313  {
314  QDomElement fe = pDoc->createElement("Frontend");
315  frontends.appendChild(fe);
316  QUrl url((*it)->m_sLocation);
317  fe.setAttribute("name", url.host());
318  fe.setAttribute("url", url.toString(QUrl::RemovePath));
319  (*it)->DecrRef();
320  }
321  }
322 
323  // Other backends
324 
325  QDomElement backends = pDoc->createElement("Backends");
326  root.appendChild(backends);
327 
328  int numbes = 0;
330  {
331  numbes++;
332  QString masterhost = gCoreContext->GetMasterHostName();
333  QString masterip = gCoreContext->GetMasterServerIP();
334  int masterport = gCoreContext->GetMasterServerStatusPort();
335 
336  QDomElement mbe = pDoc->createElement("Backend");
337  backends.appendChild(mbe);
338  mbe.setAttribute("type", "Master");
339  mbe.setAttribute("name", masterhost);
340  mbe.setAttribute("url" , masterip + ":" + masterport);
341  }
342 
344  "urn:schemas-mythtv-org:device:SlaveMediaServer:1");
345  if (sbes)
346  {
347 
348  QString ipaddress = QString();
349  if (!UPnp::g_IPAddrList.isEmpty())
350  ipaddress = UPnp::g_IPAddrList.at(0).toString();
351 
352  EntryMap map;
353  sbes->GetEntryMap(map);
354  sbes->DecrRef();
355  sbes = NULL;
356 
357  for (EntryMap::iterator it = map.begin(); it != map.end(); ++it)
358  {
359  QUrl url((*it)->m_sLocation);
360  if (url.host() != ipaddress)
361  {
362  numbes++;
363  QDomElement mbe = pDoc->createElement("Backend");
364  backends.appendChild(mbe);
365  mbe.setAttribute("type", "Slave");
366  mbe.setAttribute("name", url.host());
367  mbe.setAttribute("url" , url.toString(QUrl::RemovePath));
368  }
369  (*it)->DecrRef();
370  }
371  }
372 
373  backends.setAttribute("count", numbes);
374 
375  // Add Job Queue Entries
376 
377  QDomElement jobqueue = pDoc->createElement("JobQueue");
378  root.appendChild(jobqueue);
379 
380  QMap<int, JobQueueEntry> jobs;
381  QMap<int, JobQueueEntry>::Iterator it;
382 
386 
387  for (it = jobs.begin(); it != jobs.end(); ++it)
388  {
389  ProgramInfo pginfo((*it).chanid, (*it).recstartts);
390  if (!pginfo.GetChanID())
391  continue;
392 
393  QDomElement job = pDoc->createElement("Job");
394  jobqueue.appendChild(job);
395 
396  job.setAttribute("id" , (*it).id );
397  job.setAttribute("chanId" , (*it).chanid );
398  job.setAttribute("startTime" ,
399  (*it).recstartts.toString(Qt::ISODate));
400  job.setAttribute("startTs" , (*it).startts );
401  job.setAttribute("insertTime",
402  (*it).inserttime.toString(Qt::ISODate));
403  job.setAttribute("type" , (*it).type );
404  job.setAttribute("cmds" , (*it).cmds );
405  job.setAttribute("flags" , (*it).flags );
406  job.setAttribute("status" , (*it).status );
407  job.setAttribute("statusTime",
408  (*it).statustime.toString(Qt::ISODate));
409  job.setAttribute("schedTime" ,
410  (*it).schedruntime.toString(Qt::ISODate));
411  job.setAttribute("args" , (*it).args );
412 
413  if ((*it).hostname.isEmpty())
414  job.setAttribute("hostname", QObject::tr("master"));
415  else
416  job.setAttribute("hostname",(*it).hostname);
417 
418  QDomText textNode = pDoc->createTextNode((*it).comment);
419  job.appendChild(textNode);
420 
421  FillProgramInfo(pDoc, job, &pginfo);
422  }
423 
424  jobqueue.setAttribute( "count", jobs.size() );
425 
426  // Add Machine information
427 
428  QDomElement mInfo = pDoc->createElement("MachineInfo");
429  QDomElement storage = pDoc->createElement("Storage" );
430  QDomElement load = pDoc->createElement("Load" );
431  QDomElement guide = pDoc->createElement("Guide" );
432 
433  root.appendChild (mInfo );
434  mInfo.appendChild(storage);
435  mInfo.appendChild(load );
436  mInfo.appendChild(guide );
437 
438  // drive space ---------------------
439 
440  QStringList strlist;
441  QString dirs;
442  QString hostname;
443  QString directory;
444  QString isLocalstr;
445  QString fsID;
446  QString ids;
447  long long iTotal = -1, iUsed = -1, iAvail = -1;
448 
449  if (m_pMainServer)
451 
452  QDomElement total;
453 
454  // Make a temporary list to hold the per-filesystem elements so that the
455  // total is always the first element.
456  QList<QDomElement> fsXML;
457  QStringList::const_iterator sit = strlist.begin();
458  while (sit != strlist.end())
459  {
460  hostname = *(sit++);
461  directory = *(sit++);
462  isLocalstr = *(sit++);
463  fsID = *(sit++);
464  ++sit; // ignore dirID
465  ++sit; // ignore blocksize
466  iTotal = (*(sit++)).toLongLong();
467  iUsed = (*(sit++)).toLongLong();;
468  iAvail = iTotal - iUsed;
469 
470  if (fsID == "-2")
471  fsID = "total";
472 
473  QDomElement group = pDoc->createElement("Group");
474 
475  group.setAttribute("id" , fsID );
476  group.setAttribute("total", (int)(iTotal>>10) );
477  group.setAttribute("used" , (int)(iUsed>>10) );
478  group.setAttribute("free" , (int)(iAvail>>10) );
479  group.setAttribute("dir" , directory );
480 
481  if (fsID == "total")
482  {
483  long long iLiveTV = -1, iDeleted = -1, iExpirable = -1;
484  MSqlQuery query(MSqlQuery::InitCon());
485  query.prepare("SELECT SUM(filesize) FROM recorded "
486  " WHERE recgroup = :RECGROUP;");
487 
488  query.bindValue(":RECGROUP", "LiveTV");
489  if (query.exec() && query.next())
490  {
491  iLiveTV = query.value(0).toLongLong();
492  }
493  query.bindValue(":RECGROUP", "Deleted");
494  if (query.exec() && query.next())
495  {
496  iDeleted = query.value(0).toLongLong();
497  }
498  query.prepare("SELECT SUM(filesize) FROM recorded "
499  " WHERE autoexpire = 1 "
500  " AND recgroup NOT IN ('LiveTV', 'Deleted');");
501  if (query.exec() && query.next())
502  {
503  iExpirable = query.value(0).toLongLong();
504  }
505  group.setAttribute("livetv", (int)(iLiveTV>>20) );
506  group.setAttribute("deleted", (int)(iDeleted>>20) );
507  group.setAttribute("expirable", (int)(iExpirable>>20) );
508  total = group;
509  }
510  else
511  fsXML << group;
512  }
513 
514  storage.appendChild(total);
515  int num_elements = fsXML.size();
516  for (int fs_index = 0; fs_index < num_elements; fs_index++)
517  {
518  storage.appendChild(fsXML[fs_index]);
519  }
520 
521  // load average ---------------------
522 
523 #ifdef Q_OS_ANDROID
524  load.setAttribute("avg1", 0);
525  load.setAttribute("avg2", 1);
526  load.setAttribute("avg3", 2);
527 #else
528  double rgdAverages[3];
529 
530  if (getloadavg(rgdAverages, 3) != -1)
531  {
532  load.setAttribute("avg1", rgdAverages[0]);
533  load.setAttribute("avg2", rgdAverages[1]);
534  load.setAttribute("avg3", rgdAverages[2]);
535  }
536 #endif
537 
538  // Guide Data ---------------------
539 
540  QDateTime GuideDataThrough;
541 
542  MSqlQuery query(MSqlQuery::InitCon());
543  query.prepare("SELECT MAX(endtime) FROM program WHERE manualid = 0;");
544 
545  if (query.exec() && query.next())
546  {
547  GuideDataThrough = MythDate::fromString(query.value(0).toString());
548  }
549 
550  guide.setAttribute("start",
551  setting_to_localtime("mythfilldatabaseLastRunStart"));
552  guide.setAttribute("end",
553  setting_to_localtime("mythfilldatabaseLastRunEnd"));
554  guide.setAttribute("status",
555  gCoreContext->GetSetting("mythfilldatabaseLastRunStatus"));
556  if (gCoreContext->GetNumSetting("MythFillGrabberSuggestsTime", 0))
557  {
558  guide.setAttribute("next",
559  gCoreContext->GetSetting("MythFillSuggestedRunTime"));
560  }
561 
562  if (!GuideDataThrough.isNull())
563  {
564  guide.setAttribute("guideThru",
565  QDateTime(GuideDataThrough).toString(Qt::ISODate));
566  guide.setAttribute("guideDays", qdtNow.daysTo(GuideDataThrough));
567  }
568 
569  QDomText dataDirectMessage =
570  pDoc->createTextNode(gCoreContext->GetSetting("DataDirectMessage"));
571  guide.appendChild(dataDirectMessage);
572 
573  // Add Miscellaneous information
574 
575  QString info_script = gCoreContext->GetSetting("MiscStatusScript");
576  if ((!info_script.isEmpty()) && (info_script != "none"))
577  {
578  QDomElement misc = pDoc->createElement("Miscellaneous");
579  root.appendChild(misc);
580 
582  MythSystemLegacy ms(info_script, flags);
583  ms.Run(10);
584  if (ms.Wait() != GENERIC_EXIT_OK)
585  {
586  LOG(VB_GENERAL, LOG_ERR,
587  QString("Error running miscellaneous "
588  "status information script: %1").arg(info_script));
589  return;
590  }
591 
592  QByteArray input = ms.ReadAll();
593 
594  QStringList output = QString(input).split('\n',
595  QString::SkipEmptyParts);
596 
597  QStringList::iterator iter;
598  for (iter = output.begin(); iter != output.end(); ++iter)
599  {
600  QDomElement info = pDoc->createElement("Information");
601 
602  QStringList list = (*iter).split("[]:[]");
603  unsigned int size = list.size();
604  unsigned int hasAttributes = 0;
605 
606  if ((size > 0) && (!list[0].isEmpty()))
607  {
608  info.setAttribute("display", list[0]);
609  hasAttributes++;
610  }
611  if ((size > 1) && (!list[1].isEmpty()))
612  {
613  info.setAttribute("name", list[1]);
614  hasAttributes++;
615  }
616  if ((size > 2) && (!list[2].isEmpty()))
617  {
618  info.setAttribute("value", list[2]);
619  hasAttributes++;
620  }
621 
622  if (hasAttributes > 0)
623  misc.appendChild(info);
624  }
625  }
626 }
627 
629 //
631 
632 void HttpStatus::PrintStatus( QTextStream &os, QDomDocument *pDoc )
633 {
634  os.setCodec("UTF-8");
635 
636  QDateTime qdtNow = MythDate::current();
637 
638  QDomElement docElem = pDoc->documentElement();
639 
640  os << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
641  << "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n"
642  << "<html xmlns=\"http://www.w3.org/1999/xhtml\""
643  << " xml:lang=\"en\" lang=\"en\">\r\n"
644  << "<head>\r\n"
645  << " <meta http-equiv=\"Content-Type\""
646  << "content=\"text/html; charset=UTF-8\" />\r\n"
647  << " <link rel=\"stylesheet\" href=\"/css/Status.css\" type=\"text/css\">\r\n"
648  << " <title>MythTV Status - "
649  << docElem.attribute( "date", MythDate::toString(qdtNow, MythDate::kDateShort) )
650  << " "
651  << docElem.attribute( "time", MythDate::toString(qdtNow, MythDate::kTime) ) << " - "
652  << docElem.attribute( "version", MYTH_BINARY_VERSION ) << "</title>\r\n"
653  << "</head>\r\n"
654  << "<body bgcolor=\"#fff\">\r\n"
655  << "<div class=\"status\">\r\n"
656  << " <h1 class=\"status\">MythTV Status</h1>\r\n";
657 
658  // encoder information ---------------------
659 
660  QDomNode node = docElem.namedItem( "Encoders" );
661 
662  if (!node.isNull())
663  PrintEncoderStatus( os, node.toElement() );
664 
665  // upcoming shows --------------------------
666 
667  node = docElem.namedItem( "Scheduled" );
668 
669  if (!node.isNull())
670  PrintScheduled( os, node.toElement());
671 
672  // Frontends
673 
674  node = docElem.namedItem( "Frontends" );
675 
676  if (!node.isNull())
677  PrintFrontends (os, node.toElement());
678 
679  // Backends
680 
681  node = docElem.namedItem( "Backends" );
682 
683  if (!node.isNull())
684  PrintBackends (os, node.toElement());
685 
686  // Job Queue Entries -----------------------
687 
688  node = docElem.namedItem( "JobQueue" );
689 
690  if (!node.isNull())
691  PrintJobQueue( os, node.toElement());
692 
693  // Machine information ---------------------
694 
695  node = docElem.namedItem( "MachineInfo" );
696 
697  if (!node.isNull())
698  PrintMachineInfo( os, node.toElement());
699 
700  // Miscellaneous information ---------------
701 
702  node = docElem.namedItem( "Miscellaneous" );
703 
704  if (!node.isNull())
705  PrintMiscellaneousInfo( os, node.toElement());
706 
707  os << "\r\n</div>\r\n</body>\r\n</html>\r\n";
708 
709 }
710 
712 //
714 
715 int HttpStatus::PrintEncoderStatus( QTextStream &os, QDomElement encoders )
716 {
717  int nNumEncoders = 0;
718 
719  if (encoders.isNull())
720  return 0;
721 
722  os << " <div class=\"content\">\r\n"
723  << " <h2 class=\"status\">Encoder Status</h2>\r\n";
724 
725  QDomNode node = encoders.firstChild();
726 
727  while (!node.isNull())
728  {
729  QDomElement e = node.toElement();
730 
731  if (!e.isNull())
732  {
733  if (e.tagName() == "Encoder")
734  {
735  QString sIsLocal = (e.attribute( "local" , "remote" )== "1")
736  ? "local" : "remote";
737  QString sCardId = e.attribute( "id" , "0" );
738  QString sHostName = e.attribute( "hostname" , "Unknown");
739  bool bConnected= e.attribute( "connected", "0" ).toInt();
740 
741  bool bIsLowOnFreeSpace=e.attribute( "lowOnFreeSpace", "0").toInt();
742 
743  QString sDevlabel = e.attribute( "devlabel", "[ UNKNOWN ]");
744 
745  os << " Encoder " << sCardId << " " << sDevlabel
746  << " is " << sIsLocal << " on " << sHostName;
747 
748  if ((sIsLocal == "remote") && !bConnected)
749  {
750  SleepStatus sleepStatus =
751  (SleepStatus) e.attribute("sleepstatus",
752  QString((int)sStatus_Undefined)).toInt();
753 
754  if (sleepStatus == sStatus_Asleep)
755  os << " (currently asleep).<br />";
756  else
757  os << " (currently not connected).<br />";
758 
759  node = node.nextSibling();
760  continue;
761  }
762 
763  nNumEncoders++;
764 
765  TVState encState = (TVState) e.attribute( "state", "0").toInt();
766 
767  switch( encState )
768  {
770  os << " and is watching Live TV";
771  break;
772 
775  os << " and is recording";
776  break;
777 
778  default:
779  os << " and is not recording.";
780  break;
781  }
782 
783  // Display first Program Element listed under the encoder
784 
785  QDomNode tmpNode = e.namedItem( "Program" );
786 
787  if (!tmpNode.isNull())
788  {
789  QDomElement program = tmpNode.toElement();
790 
791  if (!program.isNull())
792  {
793  os << " '" << program.attribute( "title", "Unknown" ) << "'";
794 
795  // Get Channel information
796 
797  tmpNode = program.namedItem( "Channel" );
798 
799  if (!tmpNode.isNull())
800  {
801  QDomElement channel = tmpNode.toElement();
802 
803  if (!channel.isNull())
804  os << " on "
805  << channel.attribute( "callSign", "unknown" );
806  }
807 
808  // Get Recording Information (if any)
809 
810  tmpNode = program.namedItem( "Recording" );
811 
812  if (!tmpNode.isNull())
813  {
814  QDomElement recording = tmpNode.toElement();
815 
816  if (!recording.isNull())
817  {
818  QDateTime endTs = MythDate::fromString(
819  recording.attribute( "recEndTs", "" ));
820 
821  os << ". This recording ";
822  if (endTs < MythDate::current())
823  os << "was ";
824  else
825  os << "is ";
826 
827  os << "scheduled to end at "
828  << MythDate::toString(endTs,
830  }
831  }
832  }
833 
834  os << ".";
835  }
836 
837  if (bIsLowOnFreeSpace)
838  {
839  os << " <strong>WARNING</strong>:"
840  << " This backend is low on free disk space!";
841  }
842 
843  os << "<br />\r\n";
844  }
845  }
846 
847  node = node.nextSibling();
848  }
849 
850  os << " </div>\r\n\r\n";
851 
852  return( nNumEncoders );
853 }
854 
856 //
858 
859 int HttpStatus::PrintScheduled( QTextStream &os, QDomElement scheduled )
860 {
861  QDateTime qdtNow = MythDate::current();
862 
863  if (scheduled.isNull())
864  return( 0 );
865 
866  int nNumRecordings= scheduled.attribute( "count", "0" ).toInt();
867 
868  os << " <div class=\"content\">\r\n"
869  << " <h2 class=\"status\">Schedule</h2>\r\n";
870 
871  if (nNumRecordings == 0)
872  {
873  os << " There are no shows scheduled for recording.\r\n"
874  << " </div>\r\n";
875  return( 0 );
876  }
877 
878  os << " The next " << nNumRecordings << " show" << (nNumRecordings == 1 ? "" : "s" )
879  << " that " << (nNumRecordings == 1 ? "is" : "are")
880  << " scheduled for recording:\r\n";
881 
882  os << " <div class=\"schedule\">\r\n";
883 
884  // Iterate through all scheduled programs
885 
886  QDomNode node = scheduled.firstChild();
887 
888  while (!node.isNull())
889  {
890  QDomElement e = node.toElement();
891 
892  if (!e.isNull())
893  {
894  QDomNode recNode = e.namedItem( "Recording" );
895  QDomNode chanNode = e.namedItem( "Channel" );
896 
897  if ((e.tagName() == "Program") && !recNode.isNull() &&
898  !chanNode.isNull())
899  {
900  QDomElement r = recNode.toElement();
901  QDomElement c = chanNode.toElement();
902 
903  QString sTitle = e.attribute( "title" , "" );
904  QString sSubTitle = e.attribute( "subTitle", "" );
905  QDateTime airDate = MythDate::fromString( e.attribute( "airdate" ,"" ));
906  QDateTime startTs = MythDate::fromString( e.attribute( "startTime" ,"" ));
907  QDateTime endTs = MythDate::fromString( e.attribute( "endTime" ,"" ));
908  QDateTime recStartTs = MythDate::fromString( r.attribute( "recStartTs","" ));
909 // QDateTime recEndTs = MythDate::fromString( r.attribute( "recEndTs" ,"" ));
910  int nPreRollSecs = r.attribute( "preRollSeconds", "0" ).toInt();
911  int nEncoderId = r.attribute( "encoderId" , "0" ).toInt();
912  QString sProfile = r.attribute( "recProfile" , "" );
913  QString sChanName = c.attribute( "channelName" , "" );
914  QString sDesc = "";
915 
916  QDomText text = e.firstChild().toText();
917  if (!text.isNull())
918  sDesc = text.nodeValue();
919 
920  // Build Time to recording start.
921 
922  int nTotalSecs = qdtNow.secsTo( recStartTs ) - nPreRollSecs;
923 
924  //since we're not displaying seconds
925 
926  nTotalSecs -= 60;
927 
928  int nTotalDays = nTotalSecs / 86400;
929  int nTotalHours = (nTotalSecs / 3600)
930  - (nTotalDays * 24);
931  int nTotalMins = (nTotalSecs / 60) % 60;
932 
933  QString sTimeToStart = "in";
934 
935  sTimeToStart += QObject::tr(" %n day(s),", "", nTotalDays );
936  sTimeToStart += QObject::tr(" %n hour(s) and", "", nTotalHours);
937  sTimeToStart += QObject::tr(" %n minute(s)", "", nTotalMins);
938 
939  if ( nTotalHours == 0 && nTotalMins == 0)
940  sTimeToStart = QObject::tr("within one minute", "Recording starting");
941 
942  if ( nTotalSecs < 0)
943  sTimeToStart = QObject::tr("soon", "Recording starting");
944 
945  // Output HTML
946 
947  os << " <a href=\"#\">";
948  os << MythDate::toString(recStartTs.addSecs(-nPreRollSecs),
950  MythDate::kSimplify) << " "
951  << MythDate::toString(recStartTs.addSecs(-nPreRollSecs),
952  MythDate::kTime) << " - ";
953 
954  if (nEncoderId > 0)
955  os << "Encoder " << nEncoderId << " - ";
956 
957  os << sChanName << " - " << sTitle << "<br />"
958  << "<span><strong>" << sTitle << "</strong> ("
959  << MythDate::toString(startTs, MythDate::kTime) << "-"
960  << MythDate::toString(endTs, MythDate::kTime) << ")<br />";
961 
962  if ( !sSubTitle.isEmpty())
963  os << "<em>" << sSubTitle << "</em><br /><br />";
964 
965  if ( airDate.isValid())
966  os << "Orig. Airdate: "
969  << "<br /><br />";
970 
971  os << sDesc << "<br /><br />"
972  << "This recording will start " << sTimeToStart
973  << " using encoder " << nEncoderId << " with the '"
974  << sProfile << "' profile.</span></a><hr />\r\n";
975  }
976  }
977 
978  node = node.nextSibling();
979  }
980  os << " </div>\r\n";
981  os << " </div>\r\n\r\n";
982 
983  return( nNumRecordings );
984 }
985 
987 //
989 
990 int HttpStatus::PrintFrontends( QTextStream &os, QDomElement frontends )
991 {
992  if (frontends.isNull())
993  return( 0 );
994 
995  int nNumFES= frontends.attribute( "count", "0" ).toInt();
996 
997  if (nNumFES < 1)
998  return( 0 );
999 
1000 
1001  os << " <div class=\"content\">\r\n"
1002  << " <h2 class=\"status\">Frontends</h2>\r\n";
1003 
1004  QDomNode node = frontends.firstChild();
1005  while (!node.isNull())
1006  {
1007  QDomElement e = node.toElement();
1008 
1009  if (!e.isNull())
1010  {
1011  QString name = e.attribute( "name" , "" );
1012  QString url = e.attribute( "url" , "" );
1013  os << name << "&nbsp(<a href=\"" << url << "\">Status page</a>)<br />";
1014  }
1015 
1016  node = node.nextSibling();
1017  }
1018 
1019  os << " </div>\r\n\r\n";
1020 
1021  return nNumFES;
1022 }
1023 
1025 //
1027 
1028 int HttpStatus::PrintBackends( QTextStream &os, QDomElement backends )
1029 {
1030  if (backends.isNull())
1031  return( 0 );
1032 
1033  int nNumBES= backends.attribute( "count", "0" ).toInt();
1034 
1035  if (nNumBES < 1)
1036  return( 0 );
1037 
1038 
1039  os << " <div class=\"content\">\r\n"
1040  << " <h2 class=\"status\">Other Backends</h2>\r\n";
1041 
1042  QDomNode node = backends.firstChild();
1043  while (!node.isNull())
1044  {
1045  QDomElement e = node.toElement();
1046 
1047  if (!e.isNull())
1048  {
1049  QString type = e.attribute( "type", "" );
1050  QString name = e.attribute( "name" , "" );
1051  QString url = e.attribute( "url" , "" );
1052  os << type << ": " << name << "&nbsp(<a href=\"" << url << "\">Status page</a>)<br />";
1053  }
1054 
1055  node = node.nextSibling();
1056  }
1057 
1058  os << " </div>\r\n\r\n";
1059 
1060  return nNumBES;
1061 }
1062 
1064 //
1066 
1067 int HttpStatus::PrintJobQueue( QTextStream &os, QDomElement jobs )
1068 {
1069  if (jobs.isNull())
1070  return( 0 );
1071 
1072  int nNumJobs= jobs.attribute( "count", "0" ).toInt();
1073 
1074  os << " <div class=\"content\">\r\n"
1075  << " <h2 class=\"status\">Job Queue</h2>\r\n";
1076 
1077  if (nNumJobs != 0)
1078  {
1079  QString statusColor;
1080  QString jobColor;
1081 
1082  os << " Jobs currently in Queue or recently ended:\r\n<br />"
1083  << " <div class=\"schedule\">\r\n";
1084 
1085 
1086  QDomNode node = jobs.firstChild();
1087 
1088  while (!node.isNull())
1089  {
1090  QDomElement e = node.toElement();
1091 
1092  if (!e.isNull())
1093  {
1094  QDomNode progNode = e.namedItem( "Program" );
1095 
1096  if ((e.tagName() == "Job") && !progNode.isNull() )
1097  {
1098  QDomElement p = progNode.toElement();
1099 
1100  QDomNode recNode = p.namedItem( "Recording" );
1101  QDomNode chanNode = p.namedItem( "Channel" );
1102 
1103  QDomElement r = recNode.toElement();
1104  QDomElement c = chanNode.toElement();
1105 
1106  int nType = e.attribute( "type" , "0" ).toInt();
1107  int nStatus = e.attribute( "status", "0" ).toInt();
1108 
1109  switch( nStatus )
1110  {
1111  case JOB_ABORTED:
1112  statusColor = " class=\"jobaborted\"";
1113  jobColor = "";
1114  break;
1115 
1116  case JOB_ERRORED:
1117  statusColor = " class=\"joberrored\"";
1118  jobColor = " class=\"joberrored\"";
1119  break;
1120 
1121  case JOB_FINISHED:
1122  statusColor = " class=\"jobfinished\"";
1123  jobColor = " class=\"jobfinished\"";
1124  break;
1125 
1126  case JOB_RUNNING:
1127  statusColor = " class=\"jobrunning\"";
1128  jobColor = " class=\"jobrunning\"";
1129  break;
1130 
1131  default:
1132  statusColor = " class=\"jobqueued\"";
1133  jobColor = " class=\"jobqueued\"";
1134  break;
1135  }
1136 
1137  QString sTitle = p.attribute( "title" , "" ); //.replace(QRegExp("\""), "&quot;");
1138  QString sSubTitle = p.attribute( "subTitle", "" );
1139  QDateTime startTs = MythDate::fromString( p.attribute( "startTime" ,"" ));
1140  QDateTime endTs = MythDate::fromString( p.attribute( "endTime" ,"" ));
1141  QDateTime recStartTs = MythDate::fromString( r.attribute( "recStartTs","" ));
1142  QDateTime statusTime = MythDate::fromString( e.attribute( "statusTime","" ));
1143  QDateTime schedRunTime = MythDate::fromString( e.attribute( "schedTime","" ));
1144  QString sHostname = e.attribute( "hostname", "master" );
1145  QString sComment = "";
1146 
1147  QDomText text = e.firstChild().toText();
1148  if (!text.isNull())
1149  sComment = text.nodeValue();
1150 
1151  os << "<a href=\"javascript:void(0)\">"
1152  << MythDate::toString(recStartTs, MythDate::kDateFull |
1154  << " - "
1155  << sTitle << " - <font" << jobColor << ">"
1156  << JobQueue::JobText( nType ) << "</font><br />"
1157  << "<span><strong>" << sTitle << "</strong> ("
1158  << MythDate::toString(startTs, MythDate::kTime) << "-"
1159  << MythDate::toString(endTs, MythDate::kTime) << ")<br />";
1160 
1161  if (!sSubTitle.isEmpty())
1162  os << "<em>" << sSubTitle << "</em><br /><br />";
1163 
1164  os << "Job: " << JobQueue::JobText( nType ) << "<br />";
1165 
1166  if (schedRunTime > MythDate::current())
1167  os << "Scheduled Run Time: "
1168  << MythDate::toString(schedRunTime,
1171  << "<br />";
1172 
1173  os << "Status: <font" << statusColor << ">"
1174  << JobQueue::StatusText( nStatus )
1175  << "</font><br />"
1176  << "Status Time: "
1177  << MythDate::toString(statusTime, MythDate::kDateFull |
1179  << "<br />";
1180 
1181  if ( nStatus != JOB_QUEUED)
1182  os << "Host: " << sHostname << "<br />";
1183 
1184  if (!sComment.isEmpty())
1185  os << "<br />Comments:<br />" << sComment << "<br />";
1186 
1187  os << "</span></a><hr />\r\n";
1188  }
1189  }
1190 
1191  node = node.nextSibling();
1192  }
1193  os << " </div>\r\n";
1194  }
1195  else
1196  os << " Job Queue is currently empty.\r\n\r\n";
1197 
1198  os << " </div>\r\n\r\n ";
1199 
1200  return( nNumJobs );
1201 
1202 }
1203 
1205 //
1207 
1208 int HttpStatus::PrintMachineInfo( QTextStream &os, QDomElement info )
1209 {
1210  QString sRep;
1211 
1212  if (info.isNull())
1213  return( 0 );
1214 
1215  os << "<div class=\"content\">\r\n"
1216  << " <h2 class=\"status\">Machine Information</h2>\r\n";
1217 
1218  // load average ---------------------
1219 
1220  QDomNode node = info.namedItem( "Load" );
1221 
1222  if (!node.isNull())
1223  {
1224  QDomElement e = node.toElement();
1225 
1226  if (!e.isNull())
1227  {
1228  double dAvg1 = e.attribute( "avg1" , "0" ).toDouble();
1229  double dAvg2 = e.attribute( "avg2" , "0" ).toDouble();
1230  double dAvg3 = e.attribute( "avg3" , "0" ).toDouble();
1231 
1232  os << " <div class=\"loadstatus\">\r\n"
1233  << " This machine's load average:"
1234  << "\r\n <ul>\r\n <li>"
1235  << "1 Minute: " << dAvg1 << "</li>\r\n"
1236  << " <li>5 Minutes: " << dAvg2 << "</li>\r\n"
1237  << " <li>15 Minutes: " << dAvg3
1238  << "</li>\r\n </ul>\r\n"
1239  << " </div>\r\n";
1240  }
1241  }
1242 
1243  // local drive space ---------------------
1244  node = info.namedItem( "Storage" );
1245  QDomElement storage = node.toElement();
1246  node = storage.firstChild();
1247 
1248  // Loop once until we find id == "total". This should be first, but a loop
1249  // separate from the per-filesystem details loop ensures total is first,
1250  // regardless.
1251  while (!node.isNull())
1252  {
1253  QDomElement g = node.toElement();
1254 
1255  if (!g.isNull() && g.tagName() == "Group")
1256  {
1257  QString id = g.attribute("id", "" );
1258 
1259  if (id == "total")
1260  {
1261  int nFree = g.attribute("free" , "0" ).toInt();
1262  int nTotal = g.attribute("total", "0" ).toInt();
1263  int nUsed = g.attribute("used" , "0" ).toInt();
1264  int nLiveTV = g.attribute("livetv" , "0" ).toInt();
1265  int nDeleted = g.attribute("deleted", "0" ).toInt();
1266  int nExpirable = g.attribute("expirable" , "0" ).toInt();
1267  QString nDir = g.attribute("dir" , "" );
1268 
1269  nDir.replace(QRegExp(","), ", ");
1270 
1271  os << " Disk Usage Summary:<br />\r\n";
1272  os << " <ul>\r\n";
1273 
1274  os << " <li>Total Disk Space:\r\n"
1275  << " <ul>\r\n";
1276  QLocale c(QLocale::C);
1277 
1278  os << " <li>Total Space: ";
1279  sRep = c.toString(nTotal) + " MB";
1280  os << sRep << "</li>\r\n";
1281 
1282  os << " <li>Space Used: ";
1283  sRep = c.toString(nUsed) + " MB";
1284  os << sRep << "</li>\r\n";
1285 
1286  os << " <li>Space Free: ";
1287  sRep = c.toString(nFree) + " MB";
1288  os << sRep << "</li>\r\n";
1289 
1290  if ((nLiveTV + nDeleted + nExpirable) > 0)
1291  {
1292  os << " <li>Space Available "
1293  "After Auto-expire: ";
1294  sRep = c.toString(nFree + nLiveTV +
1295  nDeleted + nExpirable) + " MB";
1296  os << sRep << "\r\n";
1297  os << " <ul>\r\n";
1298  os << " <li>Space Used by LiveTV: ";
1299  sRep = c.toString(nLiveTV) + " MB";
1300  os << sRep << "</li>\r\n";
1301  os << " <li>Space Used by "
1302  "Deleted Recordings: ";
1303  sRep = c.toString(nDeleted) + " MB";
1304  os << sRep << "</li>\r\n";
1305  os << " <li>Space Used by "
1306  "Auto-expirable Recordings: ";
1307  sRep = c.toString(nExpirable) + " MB";
1308  os << sRep << "</li>\r\n";
1309  os << " </ul>\r\n";
1310  os << " </li>\r\n";
1311  }
1312 
1313  os << " </ul>\r\n"
1314  << " </li>\r\n";
1315 
1316  os << " </ul>\r\n";
1317  break;
1318  }
1319  }
1320 
1321  node = node.nextSibling();
1322  }
1323 
1324  // Loop again to handle per-filesystem details.
1325  node = storage.firstChild();
1326 
1327  os << " Disk Usage Details:<br />\r\n";
1328  os << " <ul>\r\n";
1329 
1330 
1331  while (!node.isNull())
1332  {
1333  QDomElement g = node.toElement();
1334 
1335  if (!g.isNull() && g.tagName() == "Group")
1336  {
1337  int nFree = g.attribute("free" , "0" ).toInt();
1338  int nTotal = g.attribute("total", "0" ).toInt();
1339  int nUsed = g.attribute("used" , "0" ).toInt();
1340  QString nDir = g.attribute("dir" , "" );
1341  QString id = g.attribute("id" , "" );
1342 
1343  nDir.replace(QRegExp(","), ", ");
1344 
1345 
1346  if (id != "total")
1347  {
1348 
1349  os << " <li>MythTV Drive #" << id << ":"
1350  << "\r\n"
1351  << " <ul>\r\n";
1352 
1353  if (nDir.contains(','))
1354  os << " <li>Directories: ";
1355  else
1356  os << " <li>Directory: ";
1357 
1358  os << nDir << "</li>\r\n";
1359 
1360  QLocale c(QLocale::C);
1361 
1362  os << " <li>Total Space: ";
1363  sRep = c.toString(nTotal) + " MB";
1364  os << sRep << "</li>\r\n";
1365 
1366  os << " <li>Space Used: ";
1367  sRep = c.toString(nUsed) + " MB";
1368  os << sRep << "</li>\r\n";
1369 
1370  os << " <li>Space Free: ";
1371  sRep = c.toString(nFree) + " MB";
1372  os << sRep << "</li>\r\n";
1373 
1374  os << " </ul>\r\n"
1375  << " </li>\r\n";
1376  }
1377 
1378  }
1379 
1380  node = node.nextSibling();
1381  }
1382 
1383  os << " </ul>\r\n";
1384 
1385  // Guide Info ---------------------
1386 
1387  node = info.namedItem( "Guide" );
1388 
1389  if (!node.isNull())
1390  {
1391  QDomElement e = node.toElement();
1392 
1393  if (!e.isNull())
1394  {
1395  int nDays = e.attribute( "guideDays", "0" ).toInt();
1396  QString sStart = e.attribute( "start" , "" );
1397  QString sEnd = e.attribute( "end" , "" );
1398  QString sStatus = e.attribute( "status" , "" );
1399  QDateTime next = MythDate::fromString( e.attribute( "next" , "" ));
1400  QString sNext = next.isNull() ? "" :
1402  QString sMsg = "";
1403 
1404  QDateTime thru = MythDate::fromString( e.attribute( "guideThru", "" ));
1405 
1406  QDomText text = e.firstChild().toText();
1407 
1408  QString mfdblrs =
1409  gCoreContext->GetSetting("mythfilldatabaseLastRunStart");
1410  QDateTime lastrunstart = MythDate::fromString(mfdblrs);
1411 
1412  if (!text.isNull())
1413  sMsg = text.nodeValue();
1414 
1415  os << " Last mythfilldatabase run started on " << sStart
1416  << " and ";
1417 
1418  if (sEnd < sStart)
1419  os << "is ";
1420  else
1421  os << "ended on " << sEnd << ". ";
1422 
1423  os << sStatus << "<br />\r\n";
1424 
1425  if (!next.isNull() && next >= lastrunstart)
1426  {
1427  os << " Suggested next mythfilldatabase run: "
1428  << sNext << ".<br />\r\n";
1429  }
1430 
1431  if (!thru.isNull())
1432  {
1433  os << " There's guide data until "
1435 
1436  if (nDays > 0)
1437  os << " " << QObject::tr("(%n day(s))", "", nDays);
1438 
1439  os << ".";
1440 
1441  if (nDays <= 3)
1442  os << " <strong>WARNING</strong>: is mythfilldatabase running?";
1443  }
1444  else
1445  os << " There's <strong>no guide data</strong> available! "
1446  << "Have you run mythfilldatabase?";
1447 
1448  if (!sMsg.isEmpty())
1449  os << "<br />\r\n DataDirect Status: " << sMsg;
1450  }
1451  }
1452  os << "\r\n </div>\r\n";
1453 
1454  return( 1 );
1455 }
1456 
1457 int HttpStatus::PrintMiscellaneousInfo( QTextStream &os, QDomElement info )
1458 {
1459  if (info.isNull())
1460  return( 0 );
1461 
1462  // Miscellaneous information
1463 
1464  QDomNodeList nodes = info.elementsByTagName("Information");
1465  uint count = nodes.count();
1466  if (count > 0)
1467  {
1468  QString display, linebreak;
1469  //QString name, value;
1470  os << "<div class=\"content\">\r\n"
1471  << " <h2 class=\"status\">Miscellaneous</h2>\r\n";
1472  for (unsigned int i = 0; i < count; i++)
1473  {
1474  QDomNode node = nodes.item(i);
1475  if (node.isNull())
1476  continue;
1477 
1478  QDomElement e = node.toElement();
1479  if (e.isNull())
1480  continue;
1481 
1482  display = e.attribute("display", "");
1483  //name = e.attribute("name", "");
1484  //value = e.attribute("value", "");
1485 
1486  if (display.isEmpty())
1487  continue;
1488 
1489  // Only include HTML line break if display value doesn't already
1490  // contain breaks.
1491  if (display.contains("<p>", Qt::CaseInsensitive) ||
1492  display.contains("<br", Qt::CaseInsensitive))
1493  {
1494  // matches <BR> or <br /
1495  linebreak = "\r\n";
1496  }
1497  else
1498  linebreak = "<br />\r\n";
1499 
1500  os << " " << display << linebreak;
1501  }
1502  os << "</div>\r\n";
1503  }
1504 
1505  return( 1 );
1506 }
1507 
1508 void HttpStatus::FillProgramInfo(QDomDocument *pDoc,
1509  QDomNode &node,
1510  ProgramInfo *pInfo,
1511  bool bIncChannel /* = true */,
1512  bool bDetails /* = true */)
1513 {
1514  if ((pDoc == NULL) || (pInfo == NULL))
1515  return;
1516 
1517  // Build Program Element
1518 
1519  QDomElement program = pDoc->createElement( "Program" );
1520  node.appendChild( program );
1521 
1522  program.setAttribute( "startTime" ,
1524  program.setAttribute( "endTime" , pInfo->GetScheduledEndTime(MythDate::ISODate));
1525  program.setAttribute( "title" , pInfo->GetTitle() );
1526  program.setAttribute( "subTitle" , pInfo->GetSubtitle());
1527  program.setAttribute( "category" , pInfo->GetCategory());
1528  program.setAttribute( "catType" , pInfo->GetCategoryTypeString());
1529  program.setAttribute( "repeat" , pInfo->IsRepeat() );
1530 
1531  if (bDetails)
1532  {
1533 
1534  program.setAttribute( "seriesId" , pInfo->GetSeriesID() );
1535  program.setAttribute( "programId" , pInfo->GetProgramID() );
1536  program.setAttribute( "stars" , pInfo->GetStars() );
1537  program.setAttribute( "fileSize" ,
1538  QString::number( pInfo->GetFilesize() ));
1539  program.setAttribute( "lastModified",
1541  program.setAttribute( "programFlags", pInfo->GetProgramFlags() );
1542  program.setAttribute( "hostname" , pInfo->GetHostname() );
1543 
1544  if (pInfo->GetOriginalAirDate().isValid())
1545  program.setAttribute(
1546  "airdate", pInfo->GetOriginalAirDate().toString());
1547 
1548  QDomText textNode = pDoc->createTextNode( pInfo->GetDescription() );
1549  program.appendChild( textNode );
1550 
1551  }
1552 
1553  if ( bIncChannel )
1554  {
1555  // Build Channel Child Element
1556 
1557  QDomElement channel = pDoc->createElement( "Channel" );
1558  program.appendChild( channel );
1559 
1560  FillChannelInfo( channel, pInfo, bDetails );
1561  }
1562 
1563  // Build Recording Child Element
1564 
1565  if ( pInfo->GetRecordingStatus() != RecStatus::Unknown )
1566  {
1567  QDomElement recording = pDoc->createElement( "Recording" );
1568  program.appendChild( recording );
1569 
1570  recording.setAttribute( "recStatus" ,
1571  pInfo->GetRecordingStatus() );
1572  recording.setAttribute( "recPriority" ,
1573  pInfo->GetRecordingPriority() );
1574  recording.setAttribute( "recStartTs" ,
1576  recording.setAttribute( "recEndTs" ,
1578 
1579  if (bDetails)
1580  {
1581  recording.setAttribute( "recordId" ,
1582  pInfo->GetRecordingRuleID() );
1583  recording.setAttribute( "recGroup" ,
1584  pInfo->GetRecordingGroup() );
1585  recording.setAttribute( "playGroup" ,
1586  pInfo->GetPlaybackGroup() );
1587  recording.setAttribute( "recType" ,
1588  pInfo->GetRecordingRuleType() );
1589  recording.setAttribute( "dupInType" ,
1590  pInfo->GetDuplicateCheckSource() );
1591  recording.setAttribute( "dupMethod" ,
1592  pInfo->GetDuplicateCheckMethod() );
1593  recording.setAttribute( "encoderId" ,
1594  pInfo->GetInputID() );
1595  const RecordingInfo ri(*pInfo);
1596  recording.setAttribute( "recProfile" ,
1598  //recording.setAttribute( "preRollSeconds", m_nPreRollSeconds );
1599  }
1600  }
1601 }
1602 
1604 //
1606 
1607 void HttpStatus::FillChannelInfo( QDomElement &channel,
1608  ProgramInfo *pInfo,
1609  bool bDetails /* = true */ )
1610 {
1611  if (pInfo)
1612  {
1613 /*
1614  QString sHostName = gCoreContext->GetHostName();
1615  QString sPort = gCoreContext->GetSettingOnHost( "BackendStatusPort",
1616  sHostName);
1617  QString sIconURL = QString( "http://%1:%2/getChannelIcon?ChanId=%3" )
1618  .arg( sHostName )
1619  .arg( sPort )
1620  .arg( pInfo->chanid );
1621 */
1622 
1623  channel.setAttribute( "chanId" , pInfo->GetChanID() );
1624  channel.setAttribute( "chanNum" , pInfo->GetChanNum());
1625  channel.setAttribute( "callSign" , pInfo->GetChannelSchedulingID());
1626  //channel.setAttribute( "iconURL" , sIconURL );
1627  channel.setAttribute( "channelName", pInfo->GetChannelName());
1628 
1629  if (bDetails)
1630  {
1631  channel.setAttribute( "chanFilters",
1632  pInfo->GetChannelPlaybackFilters() );
1633  channel.setAttribute( "sourceId" , pInfo->GetSourceID() );
1634  channel.setAttribute( "inputId" , pInfo->GetInputID() );
1635  channel.setAttribute( "commFree" ,
1636  (pInfo->IsCommercialFree()) ? 1 : 0 );
1637  }
1638  }
1639 }
1640 
1641 
1642 
1643 
1644 // vim:set shiftwidth=4 tabstop=4 expandtab:
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:785
void Run(time_t timeout=0)
Runs a command inside the /bin/sh shell. Returns immediately.
QString GetPlaybackGroup(void) const
Definition: programinfo.h:399
void FillProgramInfo(QDomDocument *pDoc, QDomNode &node, ProgramInfo *pInfo, bool bIncChannel=true, bool bDetails=true)
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:884
QString GetHostname(void) const
Definition: programinfo.h:400
QDateTime GetLastModifiedTime(void) const
Definition: programinfo.h:408
RecordingDupMethodType GetDuplicateCheckMethod(void) const
What should be compared to determine if two programs are the same?
Definition: programinfo.h:439
QString GetChannelPlaybackFilters(void) const
Definition: programinfo.h:366
QString m_sBaseUrl
Definition: httprequest.h:122
Watching LiveTV is the state for when we are watching a recording and the user has control over the c...
Definition: tv.h:63
static QString setting_to_localtime(const char *setting)
Definition: httpstatus.cpp:174
allow access to stdout
Definition: mythsystem.h:39
QMap< QString, DeviceLocation * > EntryMap
Key == Unique Service Name (USN)
Definition: ssdpcache.h:28
QString GetCategory(void) const
Definition: programinfo.h:348
Default local time.
Definition: mythdate.h:17
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
Definition: cardutil.cpp:1767
QVariant value(int i) const
Definition: mythdbcon.h:182
static QString JobText(int jobType)
Definition: jobqueue.cpp:1105
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
QString GetProgramRecordingProfile(void) const
Returns recording profile name that will be, or was used, for this program, creating "record" field i...
QString m_sMethod
Definition: httprequest.h:124
QStringMap m_mapRespHeaders
Definition: httprequest.h:148
Holds information on a TV Program one might wish to record.
Definition: recordinginfo.h:34
long m_nResponseStatus
Definition: httprequest.h:147
Watching Recording is the state for when we are watching an in progress recording, but the user does not have control over the channel and recorder to use.
Definition: tv.h:80
unsigned int uint
Definition: compat.h:136
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString GetSeriesID(void) const
Definition: programinfo.h:414
AutoExpire * m_pExpirer
Definition: httpstatus.h:48
uint GetRecordingRuleID(void) const
Definition: programinfo.h:429
RecordingDupInType GetDuplicateCheckSource(void) const
Where should we check for duplicates?
Definition: programinfo.h:435
void FillStatusXML(QDomDocument *pDoc)
Definition: httpstatus.cpp:181
TVState
TVState is an enumeration of the states used by TV and TVRec.
Definition: tv.h:50
QString m_sResourceUrl
Definition: httprequest.h:123
QDateTime GetRecordingStartTime(void) const
Approximate time the recording started.
Definition: programinfo.h:383
static int GetJobsInQueue(QMap< int, JobQueueEntry > &jobs, int findJobs=JOB_LIST_NOT_DONE)
Definition: jobqueue.cpp:1267
QString GetChanNum(void) const
This is the channel "number", in the form 1, 1_2, 1-2, 1#1, etc.
Definition: programinfo.h:355
RecList::const_iterator RecConstIter
Definition: mythscheduler.h:16
unsigned char r
Definition: ParseText.cpp:339
void GetStatusXML(HTTPRequest *pRequest)
Definition: httpstatus.cpp:137
uint32_t GetProgramFlags(void) const
Definition: programinfo.h:447
QString GetCategoryTypeString(void) const
Returns catType as a string.
QDateTime GetScheduledStartTime(void) const
The scheduled start time of program.
Definition: programinfo.h:369
QString GetMasterServerIP(void)
void FillChannelInfo(QDomElement &channel, ProgramInfo *pInfo, bool bDetails=true)
int PrintScheduled(QTextStream &os, QDomElement scheduled)
Definition: httpstatus.cpp:859
Holds information on recordings and videos.
Definition: programinfo.h:66
bool IsRepeat(void) const
Definition: programinfo.h:461
QString GetProgramID(void) const
Definition: programinfo.h:415
void GetEntryMap(EntryMap &)
Returns a copy of the EntryMap.
Definition: ssdpcache.cpp:84
Recording Only is a TVRec only state for when we are recording a program, but there is no one current...
Definition: tv.h:84
QDateTime GetScheduledEndTime(void) const
The scheduled end time of the program.
Definition: programinfo.h:376
int PrintJobQueue(QTextStream &os, QDomElement jobs)
int PrintMiscellaneousInfo(QTextStream &os, QDomElement info)
int PrintMachineInfo(QTextStream &os, QDomElement info)
const char * name
Definition: ParseText.cpp:338
int PrintEncoderStatus(QTextStream &os, QDomElement encoders)
Definition: httpstatus.cpp:715
Default local time.
Definition: mythdate.h:18
float GetStars(void) const
Definition: programinfo.h:421
bool ProcessRequest(HTTPRequest *pRequest)
Definition: httpstatus.cpp:97
virtual ~HttpStatus()
Definition: httpstatus.cpp:66
HttpStatus(QMap< int, EncoderLink * > *tvList, Scheduler *sched, AutoExpire *expirer, bool bIsMaster)
Definition: httpstatus.cpp:48
run process through shell
Definition: mythsystem.h:41
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
QString GetSetting(const QString &key, const QString &defaultval="")
QByteArray & ReadAll()
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
static QString StatusText(int status)
Definition: jobqueue.cpp:1124
virtual QStringList GetBasePaths()
Definition: httpstatus.cpp:88
Default local time.
Definition: mythdate.h:16
QDateTime GetRecordingEndTime(void) const
Approximate time the recording should have ended, did end, or is intended to end. ...
Definition: programinfo.h:391
virtual uint64_t GetFilesize(void) const
int PrintFrontends(QTextStream &os, QDomElement frontends)
Definition: httpstatus.cpp:990
QString GetMasterHostName(void)
SleepStatus
SleepStatus is an enumeration of the awake/sleep status of a slave.
Definition: tv.h:96
void BackendQueryDiskSpace(QStringList &strlist, bool consolidated, bool allHosts)
__u32 flags
Definition: videodev2.h:1053
string hostname
Definition: caa.py:17
bool GetAllPending(RecList &retList, int recRuleId=0) const
Definition: scheduler.cpp:1718
ResponseType m_eResponseType
Definition: httprequest.h:144
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:542
Do Today/Yesterday/Tomorrow transform.
Definition: mythdate.h:22
int m_nPreRollSeconds
Definition: httpstatus.h:51
QMap< int, EncoderLink * > * m_pEncoders
Definition: httpstatus.h:47
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:72
A slave is considered asleep when it is not awake and not undefined.
Definition: tv.h:103
uint Wait(time_t timeout=0)
void GetStatusHTML(HTTPRequest *pRequest)
Definition: httpstatus.cpp:161
int PrintBackends(QTextStream &os, QDomElement backends)
QString GetChannelName(void) const
This is the channel name in the local market, i.e.
Definition: programinfo.h:365
PictureAttribute next(PictureAttributeSupported supported, PictureAttribute attribute)
int GetNumSetting(const QString &key, int defaultval=0)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:810
voidpf stream
Definition: ioapi.h:136
QString GetRecordingGroup(void) const
Definition: programinfo.h:398
MainServer * m_pMainServer
Definition: httpstatus.h:49
bool IsCommercialFree(void) const
Definition: programinfo.h:453
static const char * toString(OMX_AUDIO_DDPBITSTREAMID id)
void PrintStatus(QTextStream &os, QDomDocument *pDoc)
Definition: httpstatus.cpp:632
Used to expire recordings to make space for new recordings.
Definition: autoexpire.h:62
AutoExpire * expirer
Default local time.
Definition: mythdate.h:19
A slave&#39;s sleep status is undefined when it has never connected to the master backend or is not able ...
Definition: tv.h:116
QBuffer m_response
Definition: httprequest.h:152
GLint GLenum GLsizei GLint GLenum GLenum type
QString GetDescription(void) const
Definition: programinfo.h:344
Default UTC, database format.
Definition: mythdate.h:23
RecStatus::Type GetRecordingStatus(void) const
Definition: programinfo.h:426
HttpStatusMethod
Definition: httpstatus.h:21
RecordingType GetRecordingRuleType(void) const
Definition: programinfo.h:431
int GetMasterServerStatusPort(void)
Scheduler * sched
Add year to string if not included.
Definition: mythdate.h:21
HttpStatusMethod GetMethod(const QString &sURI)
Definition: httpstatus.cpp:74
std::deque< RecordingInfo * > RecList
Definition: mythscheduler.h:10
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:610
static SSDPCacheEntries * Find(const QString &sURI)
Definition: ssdp.h:129
Scheduler * m_pSched
Definition: httpstatus.h:46
uint GetChanID(void) const
This is the unique key used in the database to locate tuning information.
Definition: programinfo.h:351
int GetRecordingPriority(void) const
Definition: programinfo.h:419
bool IsMasterBackend(void)
is this the actual MBE process
GLuint program
JobQueue * jobqueue
static QList< QHostAddress > g_IPAddrList
Definition: upnp.h:107
QString GetSubtitle(void) const
Definition: programinfo.h:343
QString GetHostName(void)
uint GetSourceID(void) const
Definition: programinfo.h:442
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:34
QDate GetOriginalAirDate(void) const
Definition: programinfo.h:407
QMap< int, EncoderLink * > tvList
Default UTC.
Definition: mythdate.h:14
uint GetInputID(void) const
Definition: programinfo.h:443
QString GetChannelSchedulingID(void) const
This is the unique programming identifier of a channel.
Definition: programinfo.h:362
QString GetTitle(void) const
Definition: programinfo.h:342
bool m_bIsMaster
Definition: httpstatus.h:50
MYTH_GLsizeiptr size
unsigned char g
Definition: ParseText.cpp:339