MythTV  master
filldata.cpp
Go to the documentation of this file.
1 // POSIX headers
2 #include <unistd.h>
3 
4 // Std C headers
5 #include <cstdlib>
6 #include <ctime>
7 
8 // C++ headers
9 #include <fstream>
10 using namespace std;
11 
12 // Qt headers
13 #include <QTextStream>
14 #include <QDateTime>
15 #include <QFile>
16 #include <QList>
17 #include <QMap>
18 #include <QDir>
19 
20 // MythTV headers
21 #include "mythmiscutil.h"
22 #include "exitcodes.h"
23 #include "mythlogging.h"
24 #include "mythdbcon.h"
25 #include "compat.h"
26 #include "mythdate.h"
27 #include "mythdirs.h"
28 #include "mythdb.h"
29 #include "mythsystemlegacy.h"
30 #include "videosource.h" // for is_grabber..
31 #include "mythcorecontext.h"
32 
33 // filldata headers
34 #include "filldata.h"
35 
36 #define LOC QString("FillData: ")
37 #define LOC_WARN QString("FillData, Warning: ")
38 #define LOC_ERR QString("FillData, Error: ")
39 
40 bool updateLastRunEnd(void)
41 {
42  QDateTime qdtNow = MythDate::current();
43  return gCoreContext->SaveSettingOnHost("mythfilldatabaseLastRunEnd",
44  qdtNow.toString(Qt::ISODate),
45  nullptr);
46 }
47 
49 {
51  QDateTime qdtNow = MythDate::current();
52  return gCoreContext->SaveSettingOnHost("mythfilldatabaseLastRunStart",
53  qdtNow.toString(Qt::ISODate),
54  nullptr);
55 }
56 
57 bool updateLastRunStatus(QString &status)
58 {
59  return gCoreContext->SaveSettingOnHost("mythfilldatabaseLastRunStatus",
60  status,
61  nullptr);
62 }
63 
65 {
66  QDateTime nextSuggestedTime = MythDate::current().addDays(1);
67  return gCoreContext->SaveSettingOnHost("MythFillSuggestedRunTime",
68  nextSuggestedTime.toString(Qt::ISODate),
69  nullptr);
70 }
71 
72 void FillData::SetRefresh(int day, bool set)
73 {
74  if (kRefreshClear == day)
75  {
76  m_refreshAll = set;
77  m_refreshDay.clear();
78  }
79  else if (kRefreshAll == day)
80  {
81  m_refreshAll = set;
82  }
83  else
84  {
85  m_refreshDay[(uint)day] = set;
86  }
87 }
88 
89 // XMLTV stuff
90 bool FillData::GrabDataFromFile(int id, QString &filename)
91 {
92  ChannelInfoList chanlist;
93  QMap<QString, QList<ProgInfo> > proglist;
94 
95  if (!m_xmltvParser.parseFile(filename, &chanlist, &proglist))
96  return false;
97 
98  m_chanData.handleChannels(id, &chanlist);
99  if (proglist.count() == 0)
100  {
101  LOG(VB_GENERAL, LOG_INFO, "No programs found in data.");
102  m_endOfData = true;
103  }
104  else
105  {
106  ProgramData::HandlePrograms(id, proglist);
107  }
108  return true;
109 }
110 
111 bool FillData::GrabData(const Source& source, int offset)
112 {
113  QString xmltv_grabber = source.xmltvgrabber;
114 
115  const QString templatename = "/tmp/mythXXXXXX";
116  const QString tempfilename = createTempFile(templatename);
117  if (templatename == tempfilename)
118  {
119  m_fatalErrors.push_back("Failed to create temporary file.");
120  return false;
121  }
122 
123  QString filename = QString(tempfilename);
124 
125  QString configfile;
126 
127  MSqlQuery query1(MSqlQuery::InitCon());
128  query1.prepare("SELECT configpath FROM videosource"
129  " WHERE sourceid = :ID AND configpath IS NOT NULL");
130  query1.bindValue(":ID", source.id);
131  if (!query1.exec())
132  {
133  MythDB::DBError("FillData::grabData", query1);
134  return false;
135  }
136 
137  if (query1.next())
138  configfile = query1.value(0).toString();
139  else
140  configfile = QString("%1/%2.xmltv").arg(GetConfDir())
141  .arg(source.name);
142 
143  LOG(VB_GENERAL, LOG_INFO,
144  QString("XMLTV config file is: %1").arg(configfile));
145 
146  QString command = QString("nice %1 --config-file '%2' --output %3")
147  .arg(xmltv_grabber).arg(configfile).arg(filename);
148 
149 
150  if (source.xmltvgrabber_prefmethod != "allatonce" || m_noAllAtOnce)
151  {
152  // XMLTV Docs don't recommend grabbing one day at a
153  // time but the current MythTV code is heavily geared
154  // that way so until it is re-written behave as
155  // we always have done.
156  command += QString(" --days 1 --offset %1").arg(offset);
157  }
158 
159  if (!VERBOSE_LEVEL_CHECK(VB_XMLTV, LOG_ANY))
160  command += " --quiet";
161 
162  // Append additional arguments passed to mythfilldatabase
163  // using --graboptions
164  if (!m_grabOptions.isEmpty())
165  {
166  command += m_grabOptions;
167  LOG(VB_XMLTV, LOG_INFO,
168  QString("Using graboptions: %1").arg(m_grabOptions));
169  }
170 
171  QString status = QObject::tr("currently running.");
172 
174  updateLastRunStatus(status);
175 
176  LOG(VB_XMLTV, LOG_INFO, QString("Grabber Command: %1").arg(command));
177 
178  LOG(VB_XMLTV, LOG_INFO,
179  "----------------- Start of XMLTV output -----------------");
180 
181  MythSystemLegacy run_grabber(command, kMSRunShell | kMSStdErr);
182 
183  run_grabber.Run();
184  uint systemcall_status = run_grabber.Wait();
185  bool succeeded = (systemcall_status == GENERIC_EXIT_OK);
186 
187  QByteArray result = run_grabber.ReadAllErr();
188  QTextStream ostream(result);
189  while (!ostream.atEnd())
190  {
191  QString line = ostream.readLine().simplified();
192  LOG(VB_XMLTV, LOG_INFO, line);
193  }
194 
195  LOG(VB_XMLTV, LOG_INFO,
196  "------------------ End of XMLTV output ------------------");
197 
199 
200  status = QObject::tr("Successful.");
201 
202  if (!succeeded)
203  {
204  if (systemcall_status == GENERIC_EXIT_KILLED)
205  {
206  m_interrupted = true;
207  status = QObject::tr("FAILED: XMLTV grabber ran but was interrupted.");
208  LOG(VB_GENERAL, LOG_ERR,
209  QString("XMLTV grabber ran but was interrupted."));
210  }
211  else
212  {
213  status = QObject::tr("FAILED: XMLTV grabber returned error code %1.")
214  .arg(systemcall_status);
215  LOG(VB_GENERAL, LOG_ERR,
216  QString("XMLTV grabber returned error code %1")
217  .arg(systemcall_status));
218  }
219  }
220 
221  updateLastRunStatus(status);
222 
223  succeeded &= GrabDataFromFile(source.id, filename);
224 
225  QFile thefile(filename);
226  thefile.remove();
227 
228  return succeeded;
229 }
230 
236 bool FillData::Run(SourceList &sourcelist)
237 {
238  SourceList::iterator it;
239 
240  QString status;
241  QString querystr;
243  QDateTime GuideDataBefore;
244  QDateTime GuideDataAfter;
245  int failures = 0;
246  int externally_handled = 0;
247  int total_sources = sourcelist.size();
248  int source_channels = 0;
249 
250  QString sidStr = QString("Updating source #%1 (%2) with grabber %3");
251 
252  m_needPostGrabProc = false;
253  int nonewdata = 0;
254 
255  for (it = sourcelist.begin(); it != sourcelist.end(); ++it)
256  {
257  if (!m_fatalErrors.empty())
258  break;
259 
260  QString xmltv_grabber = (*it).xmltvgrabber;
261 
262  if (xmltv_grabber == "datadirect" ||
263  xmltv_grabber == "schedulesdirect1")
264  {
265  LOG(VB_GENERAL, LOG_ERR,
266  QString("Source %1 is configured to use the DataDirect guide"
267  "service from Schedules Direct. That service is no "
268  "longer supported by MythTV. Update to use one of "
269  "the XMLTV grabbers that use the JSON-based guide "
270  "service from Schedules Direct.")
271  .arg((*it).id));
272  continue;
273  }
274 
275  query.prepare("SELECT MAX(endtime) "
276  "FROM program p "
277  "LEFT JOIN channel c ON p.chanid=c.chanid "
278  "WHERE c.deleted IS NULL AND c.sourceid= :SRCID "
279  " AND manualid = 0 AND c.xmltvid != '';");
280  query.bindValue(":SRCID", (*it).id);
281 
282  if (query.exec() && query.next())
283  {
284  if (!query.isNull(0))
285  GuideDataBefore =
286  MythDate::fromString(query.value(0).toString());
287  }
288 
289  m_channelUpdateRun = false;
290  m_endOfData = false;
291 
292  if (xmltv_grabber == "eitonly")
293  {
294  LOG(VB_GENERAL, LOG_INFO,
295  QString("Source %1 configured to use only the "
296  "broadcasted guide data. Skipping.") .arg((*it).id));
297 
298  externally_handled++;
301  continue;
302  }
303  if (xmltv_grabber.trimmed().isEmpty() ||
304  xmltv_grabber == "/bin/true" ||
305  xmltv_grabber == "none")
306  {
307  LOG(VB_GENERAL, LOG_INFO,
308  QString("Source %1 configured with no grabber. Nothing to do.")
309  .arg((*it).id));
310 
311  externally_handled++;
314  continue;
315  }
316 
317  LOG(VB_GENERAL, LOG_INFO, sidStr.arg((*it).id)
318  .arg((*it).name)
319  .arg(xmltv_grabber));
320 
321  query.prepare(
322  "SELECT COUNT(chanid) FROM channel "
323  "WHERE deleted IS NULL AND "
324  " sourceid = :SRCID AND xmltvid != ''");
325  query.bindValue(":SRCID", (*it).id);
326 
327  if (query.exec() && query.next())
328  {
329  source_channels = query.value(0).toInt();
330  if (source_channels > 0)
331  {
332  LOG(VB_GENERAL, LOG_INFO,
333  QString("Found %1 channels for source %2 which use grabber")
334  .arg(source_channels).arg((*it).id));
335  }
336  else
337  {
338  LOG(VB_GENERAL, LOG_INFO,
339  QString("No channels are configured to use grabber."));
340  }
341  }
342  else
343  {
344  source_channels = 0;
345  LOG(VB_GENERAL, LOG_INFO,
346  QString("Can't get a channel count for source id %1")
347  .arg((*it).id));
348  }
349 
350  bool hasprefmethod = false;
351 
352  if (is_grabber_external(xmltv_grabber))
353  {
354  uint flags = kMSRunShell | kMSStdOut;
355  MythSystemLegacy grabber_capabilities_proc(xmltv_grabber,
356  QStringList("--capabilities"),
357  flags);
358  grabber_capabilities_proc.Run(25);
359  if (grabber_capabilities_proc.Wait() != GENERIC_EXIT_OK)
360  {
361  LOG(VB_GENERAL, LOG_ERR,
362  QString("%1 --capabilities failed or we timed out waiting."
363  " You may need to upgrade your xmltv grabber")
364  .arg(xmltv_grabber));
365  }
366  else
367  {
368  QByteArray result = grabber_capabilities_proc.ReadAll();
369  QTextStream ostream(result);
370  QString capabilities;
371  while (!ostream.atEnd())
372  {
373  QString capability
374  = ostream.readLine().simplified();
375 
376  if (capability.isEmpty())
377  continue;
378 
379  capabilities += capability + ' ';
380 
381  if (capability == "baseline")
382  (*it).xmltvgrabber_baseline = true;
383 
384  if (capability == "manualconfig")
385  (*it).xmltvgrabber_manualconfig = true;
386 
387  if (capability == "cache")
388  (*it).xmltvgrabber_cache = true;
389 
390  if (capability == "preferredmethod")
391  hasprefmethod = true;
392  }
393  LOG(VB_GENERAL, LOG_INFO,
394  QString("Grabber has capabilities: %1") .arg(capabilities));
395  }
396  }
397 
398  if (hasprefmethod)
399  {
400  uint flags = kMSRunShell | kMSStdOut;
401  MythSystemLegacy grabber_method_proc(xmltv_grabber,
402  QStringList("--preferredmethod"),
403  flags);
404  grabber_method_proc.Run(15);
405  if (grabber_method_proc.Wait() != GENERIC_EXIT_OK)
406  {
407  LOG(VB_GENERAL, LOG_ERR,
408  QString("%1 --preferredmethod failed or we timed out "
409  "waiting. You may need to upgrade your xmltv "
410  "grabber").arg(xmltv_grabber));
411  }
412  else
413  {
414  QTextStream ostream(grabber_method_proc.ReadAll());
415  (*it).xmltvgrabber_prefmethod =
416  ostream.readLine().simplified();
417 
418  LOG(VB_GENERAL, LOG_INFO, QString("Grabber prefers method: %1")
419  .arg((*it).xmltvgrabber_prefmethod));
420  }
421  }
422 
423  m_needPostGrabProc |= true;
424 
425  if ((*it).xmltvgrabber_prefmethod == "allatonce" && !m_noAllAtOnce)
426  {
427  if (!GrabData(*it, 0))
428  ++failures;
429  }
430  else if ((*it).xmltvgrabber_baseline)
431  {
432 
433  QDate qCurrentDate = MythDate::current().date();
434 
435  // We'll keep grabbing until it returns nothing
436  // Max days currently supported is 21
437  int grabdays = REFRESH_MAX;
438 
439  grabdays = (m_maxDays > 0) ? m_maxDays : grabdays;
440  grabdays = (m_onlyUpdateChannels) ? 1 : grabdays;
441 
442  vector<bool> refresh_request;
443  refresh_request.resize(grabdays, m_refreshAll);
444  if (!m_refreshAll)
445  {
446  // Set up days to grab if all is not specified
447  // If all was specified the vector was initialized
448  // with true in all occurrences.
449  for (int i = 0; i < grabdays; i++)
450  refresh_request[i] = m_refreshDay[i];
451  }
452 
453  for (int i = 0; i < grabdays; i++)
454  {
455  if (!m_fatalErrors.empty())
456  break;
457 
458  // We need to check and see if the current date has changed
459  // since we started in this loop. If it has, we need to adjust
460  // the value of 'i' to compensate for this.
461  if (MythDate::current().date() != qCurrentDate)
462  {
463  QDate newDate = MythDate::current().date();
464  i += (newDate.daysTo(qCurrentDate));
465  if (i < 0)
466  i = 0;
467  qCurrentDate = newDate;
468  }
469 
470  QString prevDate(qCurrentDate.addDays(i-1).toString());
471  QString currDate(qCurrentDate.addDays(i).toString());
472 
473  LOG(VB_GENERAL, LOG_INFO, ""); // add a space between days
474  LOG(VB_GENERAL, LOG_INFO, "Checking day @ " +
475  QString("offset %1, date: %2").arg(i).arg(currDate));
476 
477  bool download_needed = false;
478 
479  if (refresh_request[i])
480  {
481  if ( i == 1 )
482  {
483  LOG(VB_GENERAL, LOG_INFO,
484  "Data Refresh always needed for tomorrow");
485  }
486  else
487  {
488  LOG(VB_GENERAL, LOG_INFO,
489  "Data Refresh needed because of user request");
490  }
491  download_needed = true;
492  }
493  else
494  {
495  // Check to see if we already downloaded data for this date.
496 
497  querystr = "SELECT c.chanid, COUNT(p.starttime) "
498  "FROM channel c "
499  "LEFT JOIN program p ON c.chanid = p.chanid "
500  " AND starttime >= "
501  "DATE_ADD(DATE_ADD(CURRENT_DATE(), "
502  "INTERVAL '%1' DAY), INTERVAL '20' HOUR) "
503  " AND starttime < DATE_ADD(CURRENT_DATE(), "
504  "INTERVAL '%2' DAY) "
505  "WHERE c.deleted IS NULL AND c.sourceid = %3 AND c.xmltvid != '' "
506  "GROUP BY c.chanid;";
507 
508  if (query.exec(querystr.arg(i-1).arg(i).arg((*it).id)) &&
509  query.isActive())
510  {
511  int prevChanCount = 0;
512  int currentChanCount = 0;
513  int previousDayCount = 0;
514  int currentDayCount = 0;
515 
516  LOG(VB_CHANNEL, LOG_INFO,
517  QString("Checking program counts for day %1")
518  .arg(i-1));
519 
520  while (query.next())
521  {
522  if (query.value(1).toInt() > 0)
523  prevChanCount++;
524  previousDayCount += query.value(1).toInt();
525 
526  LOG(VB_CHANNEL, LOG_INFO,
527  QString(" chanid %1 -> %2 programs")
528  .arg(query.value(0).toString())
529  .arg(query.value(1).toInt()));
530  }
531 
532  if (query.exec(querystr.arg(i).arg(i+1).arg((*it).id))
533  && query.isActive())
534  {
535  LOG(VB_CHANNEL, LOG_INFO,
536  QString("Checking program counts for day %1")
537  .arg(i));
538  while (query.next())
539  {
540  if (query.value(1).toInt() > 0)
541  currentChanCount++;
542  currentDayCount += query.value(1).toInt();
543 
544  LOG(VB_CHANNEL, LOG_INFO,
545  QString(" chanid %1 -> %2 programs")
546  .arg(query.value(0).toString())
547  .arg(query.value(1).toInt()));
548  }
549  }
550  else
551  {
552  LOG(VB_GENERAL, LOG_INFO,
553  QString("Data Refresh because we are unable to "
554  "query the data for day %1 to "
555  "determine if we have enough").arg(i));
556  download_needed = true;
557  }
558 
559  if (currentChanCount < (prevChanCount * 0.90))
560  {
561  LOG(VB_GENERAL, LOG_INFO,
562  QString("Data refresh needed because only %1 "
563  "out of %2 channels have at least one "
564  "program listed for day @ offset %3 "
565  "from 8PM - midnight. Previous day "
566  "had %4 channels with data in that "
567  "time period.")
568  .arg(currentChanCount).arg(source_channels)
569  .arg(i).arg(prevChanCount));
570  download_needed = true;
571  }
572  else if (currentDayCount == 0)
573  {
574  LOG(VB_GENERAL, LOG_INFO,
575  QString("Data refresh needed because no data "
576  "exists for day @ offset %1 from 8PM - "
577  "midnight.").arg(i));
578  download_needed = true;
579  }
580  else if (previousDayCount == 0)
581  {
582  LOG(VB_GENERAL, LOG_INFO,
583  QString("Data refresh needed because no data "
584  "exists for day @ offset %1 from 8PM - "
585  "midnight. Unable to calculate how "
586  "much we should have for the current "
587  "day so a refresh is being forced.")
588  .arg(i-1));
589  download_needed = true;
590  }
591  else if (currentDayCount < (currentChanCount * 3))
592  {
593  LOG(VB_GENERAL, LOG_INFO,
594  QString("Data Refresh needed because offset "
595  "day %1 has less than 3 programs "
596  "per channel for the 8PM - midnight "
597  "time window for channels that "
598  "normally have data. "
599  "We want at least %2 programs, but "
600  "only found %3")
601  .arg(i).arg(currentChanCount * 3)
602  .arg(currentDayCount));
603  download_needed = true;
604  }
605  else if (currentDayCount < (previousDayCount / 2))
606  {
607  LOG(VB_GENERAL, LOG_INFO,
608  QString("Data Refresh needed because offset "
609  "day %1 has less than half the number "
610  "of programs as the previous day for "
611  "the 8PM - midnight time window. "
612  "We want at least %2 programs, but "
613  "only found %3").arg(i)
614  .arg(previousDayCount / 2)
615  .arg(currentDayCount));
616  download_needed = true;
617  }
618  }
619  else
620  {
621  LOG(VB_GENERAL, LOG_INFO,
622  QString("Data Refresh needed because we are unable "
623  "to query the data for day @ offset %1 to "
624  "determine how much we should have for "
625  "offset day %2.").arg(i-1).arg(i));
626  download_needed = true;
627  }
628  }
629 
630  if (download_needed)
631  {
632  LOG(VB_GENERAL, LOG_NOTICE,
633  QString("Refreshing data for ") + currDate);
634  if (!GrabData(*it, i))
635  {
636  ++failures;
637  if (!m_fatalErrors.empty() || m_interrupted)
638  {
639  break;
640  }
641  }
642 
643  if (m_endOfData)
644  {
645  LOG(VB_GENERAL, LOG_INFO,
646  "Grabber is no longer returning program data, "
647  "finishing");
648  break;
649  }
650  }
651  else
652  {
653  LOG(VB_GENERAL, LOG_NOTICE,
654  QString("Data is already present for ") + currDate +
655  ", skipping");
656  }
657  }
658  if (!m_fatalErrors.empty())
659  break;
660  }
661  else
662  {
663  LOG(VB_GENERAL, LOG_ERR,
664  QString("Grabbing XMLTV data using ") + xmltv_grabber +
665  " is not supported. You may need to upgrade to"
666  " the latest version of XMLTV.");
667  }
668 
669  if (m_interrupted)
670  {
671  break;
672  }
673 
674  query.prepare("SELECT MAX(endtime) FROM program p "
675  "LEFT JOIN channel c ON p.chanid=c.chanid "
676  "WHERE c.deleted IS NULL AND c.sourceid= :SRCID "
677  "AND manualid = 0 AND c.xmltvid != '';");
678  query.bindValue(":SRCID", (*it).id);
679 
680  if (query.exec() && query.next())
681  {
682  if (!query.isNull(0))
683  GuideDataAfter = MythDate::fromString(query.value(0).toString());
684  }
685 
686  if (GuideDataAfter == GuideDataBefore)
687  {
688  nonewdata++;
689  }
690  }
691 
692  if (!m_fatalErrors.empty())
693  {
694  for (int i = 0; i < m_fatalErrors.size(); i++)
695  {
696  LOG(VB_GENERAL, LOG_CRIT, LOC + "Encountered Fatal Error: " +
697  m_fatalErrors[i]);
698  }
699  return false;
700  }
701 
702  if (m_onlyUpdateChannels && !m_needPostGrabProc)
703  return true;
704 
705  if (failures == 0)
706  {
707  if (nonewdata > 0 &&
708  (total_sources != externally_handled))
709  {
710  status = QObject::tr(
711  "mythfilldatabase ran, but did not insert "
712  "any new data into the Guide for %1 of %2 sources. "
713  "This can indicate a potential grabber failure.")
714  .arg(nonewdata)
715  .arg(total_sources);
716  }
717  else
718  {
719  status = QObject::tr("Successful.");
720  }
721 
722  updateLastRunStatus(status);
723  }
724 
725  return (failures == 0);
726 }
727 
728 /* vim: set expandtab tabstop=4 shiftwidth=4: */
REFRESH_MAX
#define REFRESH_MAX
Definition: filldata.h:18
kMSStdErr
@ kMSStdErr
allow access to stderr
Definition: mythsystem.h:40
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:204
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
MythSystemLegacy::ReadAllErr
QByteArray & ReadAllErr()
Definition: mythsystemlegacy.cpp:402
GENERIC_EXIT_OK
#define GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:10
MSqlQuery::isNull
bool isNull(int field) const
Definition: mythdbcon.h:208
FillData::GrabDataFromFile
bool GrabDataFromFile(int id, QString &filename)
Definition: filldata.cpp:90
SourceList
vector< Source > SourceList
Definition: filldata.h:40
mythdb.h
MythSystemLegacy
Definition: mythsystemlegacy.h:69
updateLastRunStart
bool updateLastRunStart(void)
Definition: filldata.cpp:48
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
arg
arg(title).arg(filename).arg(doDelete))
mythdbcon.h
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythSystemLegacy::ReadAll
QByteArray & ReadAll()
Definition: mythsystemlegacy.cpp:397
MythSystemLegacy::Run
void Run(time_t timeout=0)
Runs a command inside the /bin/sh shell. Returns immediately.
Definition: mythsystemlegacy.cpp:212
mythdirs.h
filldata.h
MythDate::current
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
mythsystemlegacy.h
mythdate.h
mythlogging.h
Source::xmltvgrabber_prefmethod
QString xmltvgrabber_prefmethod
Definition: filldata.h:37
GetConfDir
QString GetConfDir(void)
Definition: mythdirs.cpp:224
updateLastRunEnd
bool updateLastRunEnd(void)
Definition: filldata.cpp:40
FillData::Run
bool Run(SourceList &sourcelist)
Goes through the sourcelist and updates its channels with program info grabbed with the associated gr...
Definition: filldata.cpp:236
Source
Definition: channelsettings.cpp:69
LOC
#define LOC
Definition: filldata.cpp:36
FillData::GrabData
bool GrabData(const Source &source, int offset)
Definition: filldata.cpp:111
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
compat.h
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:179
createTempFile
QString createTempFile(QString name_template, bool dir)
Definition: mythmiscutil.cpp:368
is_grabber_external
static bool is_grabber_external(const QString &grabber)
Definition: videosource.h:29
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:634
Source::id
int id
Definition: filldata.h:28
ChannelInfoList
vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:133
uint
unsigned int uint
Definition: compat.h:140
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:57
Source::name
QString name
Definition: filldata.h:29
kMSRunShell
@ kMSRunShell
run process through shell
Definition: mythsystem.h:41
MythDate::fromString
QDateTime fromString(const QString &dtstr)
Converts kFilename && kISODate formats to QDateTime.
Definition: mythdate.cpp:30
VERBOSE_LEVEL_CHECK
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:14
mythmiscutil.h
mythcorecontext.h
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
MythDate::ISODate
@ ISODate
Default UTC.
Definition: mythdate.h:14
FillData::SetRefresh
void SetRefresh(int day, bool set)
Definition: filldata.cpp:72
ProgramData::HandlePrograms
static void HandlePrograms(uint sourceid, QMap< QString, QList< ProgInfo > > &proglist)
Called from mythfilldatabase to bulk insert data into the program database.
Definition: programdata.cpp:1478
updateLastRunStatus
bool updateLastRunStatus(QString &status)
Definition: filldata.cpp:57
exitcodes.h
query
MSqlQuery query(MSqlQuery::InitCon())
kMSStdOut
@ kMSStdOut
allow access to stdout
Definition: mythsystem.h:39
MythCoreContext::SaveSettingOnHost
bool SaveSettingOnHost(const QString &key, const QString &newValue, const QString &host)
Definition: mythcorecontext.cpp:909
updateNextScheduledRun
bool updateNextScheduledRun()
Definition: filldata.cpp:64
videosource.h
Source::xmltvgrabber
QString xmltvgrabber
Definition: filldata.h:30
MythSystemLegacy::Wait
uint Wait(time_t timeout=0)
Definition: mythsystemlegacy.cpp:242
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
GENERIC_EXIT_KILLED
#define GENERIC_EXIT_KILLED
Process killed or stopped.
Definition: exitcodes.h:23