16 #include <QTextStream>
34 #define LOC QString("FillData: ")
35 #define LOC_WARN QString("FillData, Warning: ")
36 #define LOC_ERR QString("FillData, Error: ")
91 QMap<QString, QList<ProgInfo> > proglist;
99 if (proglist.count() != 0)
101 LOG(VB_GENERAL, LOG_INFO,
"Skipping program guide updates");
106 if (proglist.count() == 0)
108 LOG(VB_GENERAL, LOG_INFO,
"No programs found in data.");
123 const QString templatename =
"/tmp/mythXXXXXX";
125 if (templatename == tempfilename)
131 QString
filename = QString(tempfilename);
136 query1.
prepare(
"SELECT configpath FROM videosource"
137 " WHERE sourceid = :ID AND configpath IS NOT NULL");
146 configfile = query1.
value(0).toString();
148 configfile = QString(
"%1/%2.xmltv").arg(
GetConfDir(), source.
name);
150 LOG(VB_GENERAL, LOG_INFO,
151 QString(
"XMLTV config file is: %1").arg(configfile));
153 QString command = QString(
"nice %1 --config-file '%2' --output %3")
154 .arg(xmltv_grabber, configfile,
filename);
158 command +=
" --list-channels";
166 command += QString(
" --days 1 --offset %1").arg(offset);
170 command +=
" --quiet";
177 LOG(VB_XMLTV, LOG_INFO,
181 QString status = QObject::tr(
"currently running.");
186 LOG(VB_XMLTV, LOG_INFO, QString(
"Grabber Command: %1").arg(command));
188 LOG(VB_XMLTV, LOG_INFO,
189 "----------------- Start of XMLTV output -----------------");
194 uint systemcall_status = run_grabber.
Wait();
198 QTextStream ostream(result);
199 while (!ostream.atEnd())
201 QString line = ostream.readLine().simplified();
202 LOG(VB_XMLTV, LOG_INFO, line);
205 LOG(VB_XMLTV, LOG_INFO,
206 "------------------ End of XMLTV output ------------------");
210 status = QObject::tr(
"Successful.");
217 status = QObject::tr(
"FAILED: XMLTV grabber ran but was interrupted.");
218 LOG(VB_GENERAL, LOG_ERR,
219 QString(
"XMLTV grabber ran but was interrupted."));
223 status = QObject::tr(
"FAILED: XMLTV grabber returned error code %1.")
224 .arg(systemcall_status);
225 LOG(VB_GENERAL, LOG_ERR,
226 QString(
"XMLTV grabber returned error code %1")
227 .arg(systemcall_status));
248 DataSourceList::iterator it;
253 QDateTime GuideDataBefore;
254 QDateTime GuideDataAfter;
256 int externally_handled = 0;
257 int total_sources = sourcelist.size();
258 int source_channels = 0;
260 QString sidStr = QString(
"Updating source #%1 (%2) with grabber %3");
265 for (it = sourcelist.begin(); it != sourcelist.end(); ++it)
270 QString xmltv_grabber = (*it).xmltvgrabber;
272 if (xmltv_grabber ==
"datadirect" ||
273 xmltv_grabber ==
"schedulesdirect1")
275 LOG(VB_GENERAL, LOG_ERR,
276 QString(
"Source %1 is configured to use the DataDirect guide"
277 "service from Schedules Direct. That service is no "
278 "longer supported by MythTV. Update to use one of "
279 "the XMLTV grabbers that use the JSON-based guide "
280 "service from Schedules Direct.")
285 query.
prepare(
"SELECT MAX(endtime) "
287 "LEFT JOIN channel c ON p.chanid=c.chanid "
288 "WHERE c.deleted IS NULL AND c.sourceid= :SRCID "
289 " AND manualid = 0 AND c.xmltvid != '';");
302 if (xmltv_grabber ==
"eitonly")
304 LOG(VB_GENERAL, LOG_INFO,
305 QString(
"Source %1 configured to use only the "
306 "broadcasted guide data. Skipping.") .arg((*it).id));
308 externally_handled++;
313 if (xmltv_grabber.trimmed().isEmpty() ||
314 xmltv_grabber ==
"/bin/true" ||
315 xmltv_grabber ==
"none")
317 LOG(VB_GENERAL, LOG_INFO,
318 QString(
"Source %1 configured with no grabber. Nothing to do.")
321 externally_handled++;
327 LOG(VB_GENERAL, LOG_INFO, sidStr.arg(QString::number((*it).id),
332 "SELECT COUNT(chanid) FROM channel "
333 "WHERE deleted IS NULL AND "
334 " sourceid = :SRCID AND xmltvid != ''");
339 source_channels = query.
value(0).toInt();
340 if (source_channels > 0)
342 LOG(VB_GENERAL, LOG_INFO,
343 QString(
"Found %1 channels for source %2 which use grabber")
344 .arg(source_channels).arg((*it).id));
348 LOG(VB_GENERAL, LOG_INFO,
349 QString(
"No channels are configured to use grabber (none have XMLTVIDs)."));
355 LOG(VB_GENERAL, LOG_INFO,
356 QString(
"Can't get a channel count for source id %1")
360 bool hasprefmethod =
false;
366 QStringList(
"--capabilities"),
368 grabber_capabilities_proc.
Run(25s);
371 LOG(VB_GENERAL, LOG_ERR,
372 QString(
"%1 --capabilities failed or we timed out waiting."
373 " You may need to upgrade your xmltv grabber")
374 .arg(xmltv_grabber));
378 QByteArray result = grabber_capabilities_proc.
ReadAll();
379 QTextStream ostream(result);
380 QString capabilities;
381 while (!ostream.atEnd())
384 = ostream.readLine().simplified();
386 if (capability.isEmpty())
389 capabilities += capability +
' ';
391 if (capability ==
"baseline")
392 (*it).xmltvgrabber_baseline =
true;
394 if (capability ==
"manualconfig")
395 (*it).xmltvgrabber_manualconfig =
true;
397 if (capability ==
"cache")
398 (*it).xmltvgrabber_cache =
true;
400 if (capability ==
"apiconfig")
401 (*it).xmltvgrabber_apiconfig =
true;
403 if (capability ==
"lineups")
404 (*it).xmltvgrabber_lineups =
true;
406 if (capability ==
"preferredmethod")
407 hasprefmethod =
true;
409 LOG(VB_GENERAL, LOG_INFO,
410 QString(
"Grabber has capabilities: %1") .arg(capabilities));
418 QStringList(
"--preferredmethod"),
420 grabber_method_proc.
Run(15s);
423 LOG(VB_GENERAL, LOG_ERR,
424 QString(
"%1 --preferredmethod failed or we timed out "
425 "waiting. You may need to upgrade your xmltv "
426 "grabber").arg(xmltv_grabber));
430 QTextStream ostream(grabber_method_proc.
ReadAll());
431 (*it).xmltvgrabber_prefmethod =
432 ostream.readLine().simplified();
434 LOG(VB_GENERAL, LOG_INFO, QString(
"Grabber prefers method: %1")
435 .arg((*it).xmltvgrabber_prefmethod));
446 else if ((*it).xmltvgrabber_baseline)
458 std::vector<bool> refresh_request;
465 for (
int i = 0; i < grabdays; i++)
469 for (
int i = 0; i < grabdays; i++)
480 i += (newDate.daysTo(qCurrentDate));
482 qCurrentDate = newDate;
485 QString currDate(qCurrentDate.addDays(i).toString());
487 LOG(VB_GENERAL, LOG_INFO,
"");
488 LOG(VB_GENERAL, LOG_INFO,
"Checking day @ " +
489 QString(
"offset %1, date: %2").arg(i).arg(currDate));
491 bool download_needed =
false;
493 if (refresh_request[i])
497 LOG(VB_GENERAL, LOG_INFO,
498 "Data Refresh always needed for tomorrow");
502 LOG(VB_GENERAL, LOG_INFO,
503 "Data Refresh needed because of user request");
505 download_needed =
true;
511 querystr =
"SELECT c.chanid, COUNT(p.starttime) "
513 "LEFT JOIN program p ON c.chanid = p.chanid "
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;";
522 if (query.
exec(querystr.arg(i-1).arg(i).arg((*it).id)) &&
525 int prevChanCount = 0;
526 int currentChanCount = 0;
527 int previousDayCount = 0;
528 int currentDayCount = 0;
530 LOG(VB_CHANNEL, LOG_INFO,
531 QString(
"Checking program counts for day %1")
536 if (query.
value(1).toInt() > 0)
538 previousDayCount += query.
value(1).toInt();
540 LOG(VB_CHANNEL, LOG_INFO,
541 QString(
" chanid %1 -> %2 programs")
542 .arg(query.
value(0).toString())
543 .arg(query.
value(1).toInt()));
546 if (query.
exec(querystr.arg(i).arg(i+1).arg((*it).id))
549 LOG(VB_CHANNEL, LOG_INFO,
550 QString(
"Checking program counts for day %1")
554 if (query.
value(1).toInt() > 0)
556 currentDayCount += query.
value(1).toInt();
558 LOG(VB_CHANNEL, LOG_INFO,
559 QString(
" chanid %1 -> %2 programs")
560 .arg(query.
value(0).toString())
561 .arg(query.
value(1).toInt()));
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;
573 if (currentChanCount < (prevChanCount * 0.90))
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 "
582 .arg(currentChanCount).arg(source_channels)
583 .arg(i).arg(prevChanCount));
584 download_needed =
true;
586 else if (currentDayCount == 0)
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;
594 else if (previousDayCount == 0)
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.")
603 download_needed =
true;
605 else if (currentDayCount < (currentChanCount * 3))
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 "
615 .arg(i).arg(currentChanCount * 3)
616 .arg(currentDayCount));
617 download_needed =
true;
619 else if (currentDayCount < (previousDayCount / 2))
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;
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;
646 LOG(VB_GENERAL, LOG_NOTICE,
647 QString(
"Refreshing data for ") + currDate);
659 LOG(VB_GENERAL, LOG_INFO,
660 "Grabber is no longer returning program data, "
667 LOG(VB_GENERAL, LOG_NOTICE,
668 QString(
"Data is already present for ") + currDate +
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.");
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 != '';");
700 if (GuideDataAfter == GuideDataBefore)
710 LOG(VB_GENERAL, LOG_CRIT,
LOC +
"Encountered Fatal Error: " +
error);
721 (total_sources != externally_handled))
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.")
732 status = QObject::tr(
"Successful.");
738 return (failures == 0);