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