15 #include <QTextStream>
33 #define LOC QString("FillData: ")
34 #define LOC_WARN QString("FillData, Warning: ")
35 #define LOC_ERR QString("FillData, Error: ")
90 QMap<QString, QList<ProgInfo> > proglist;
98 if (proglist.count() != 0)
100 LOG(VB_GENERAL, LOG_INFO,
"Skipping program guide updates");
105 if (proglist.count() == 0)
107 LOG(VB_GENERAL, LOG_INFO,
"No programs found in data.");
122 const QString templatename =
"/tmp/mythXXXXXX";
124 if (templatename == tempfilename)
130 QString
filename = QString(tempfilename);
135 query1.
prepare(
"SELECT configpath FROM videosource"
136 " WHERE sourceid = :ID AND configpath IS NOT NULL");
145 configfile = query1.
value(0).toString();
147 configfile = QString(
"%1/%2.xmltv").arg(
GetConfDir(), source.
name);
149 LOG(VB_GENERAL, LOG_INFO,
150 QString(
"XMLTV config file is: %1").arg(configfile));
152 QString command = QString(
"nice %1 --config-file '%2' --output %3")
153 .arg(xmltv_grabber, configfile,
filename);
157 command +=
" --list-channels";
165 command += QString(
" --days 1 --offset %1").arg(offset);
169 command +=
" --quiet";
176 LOG(VB_XMLTV, LOG_INFO,
180 QString status = QObject::tr(
"currently running.");
185 LOG(VB_XMLTV, LOG_INFO, QString(
"Grabber Command: %1").arg(command));
187 LOG(VB_XMLTV, LOG_INFO,
188 "----------------- Start of XMLTV output -----------------");
193 uint systemcall_status = run_grabber.
Wait();
197 QTextStream ostream(result);
198 while (!ostream.atEnd())
200 QString line = ostream.readLine().simplified();
201 LOG(VB_XMLTV, LOG_INFO, line);
204 LOG(VB_XMLTV, LOG_INFO,
205 "------------------ End of XMLTV output ------------------");
209 status = QObject::tr(
"Successful.");
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."));
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));
247 DataSourceList::iterator it;
252 QDateTime GuideDataBefore;
253 QDateTime GuideDataAfter;
255 int externally_handled = 0;
256 int total_sources = sourcelist.size();
257 int source_channels = 0;
259 QString sidStr = QString(
"Updating source #%1 (%2) with grabber %3");
264 for (it = sourcelist.begin(); it != sourcelist.end(); ++it)
269 QString xmltv_grabber = (*it).xmltvgrabber;
271 if (xmltv_grabber ==
"datadirect" ||
272 xmltv_grabber ==
"schedulesdirect1")
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.")
284 query.
prepare(
"SELECT MAX(endtime) "
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 != '';");
301 if (xmltv_grabber ==
"eitonly")
303 LOG(VB_GENERAL, LOG_INFO,
304 QString(
"Source %1 configured to use only the "
305 "broadcasted guide data. Skipping.") .arg((*it).id));
307 externally_handled++;
312 if (xmltv_grabber.trimmed().isEmpty() ||
313 xmltv_grabber ==
"/bin/true" ||
314 xmltv_grabber ==
"none")
316 LOG(VB_GENERAL, LOG_INFO,
317 QString(
"Source %1 configured with no grabber. Nothing to do.")
320 externally_handled++;
326 LOG(VB_GENERAL, LOG_INFO, sidStr.arg(QString::number((*it).id),
331 "SELECT COUNT(chanid) FROM channel "
332 "WHERE deleted IS NULL AND "
333 " sourceid = :SRCID AND xmltvid != ''");
338 source_channels = query.
value(0).toInt();
339 if (source_channels > 0)
341 LOG(VB_GENERAL, LOG_INFO,
342 QString(
"Found %1 channels for source %2 which use grabber")
343 .arg(source_channels).arg((*it).id));
347 LOG(VB_GENERAL, LOG_INFO,
348 QString(
"No channels are configured to use grabber."));
354 LOG(VB_GENERAL, LOG_INFO,
355 QString(
"Can't get a channel count for source id %1")
359 bool hasprefmethod =
false;
365 QStringList(
"--capabilities"),
367 grabber_capabilities_proc.
Run(25s);
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));
377 QByteArray result = grabber_capabilities_proc.
ReadAll();
378 QTextStream ostream(result);
379 QString capabilities;
380 while (!ostream.atEnd())
383 = ostream.readLine().simplified();
385 if (capability.isEmpty())
388 capabilities += capability +
' ';
390 if (capability ==
"baseline")
391 (*it).xmltvgrabber_baseline =
true;
393 if (capability ==
"manualconfig")
394 (*it).xmltvgrabber_manualconfig =
true;
396 if (capability ==
"cache")
397 (*it).xmltvgrabber_cache =
true;
399 if (capability ==
"apiconfig")
400 (*it).xmltvgrabber_apiconfig =
true;
402 if (capability ==
"lineups")
403 (*it).xmltvgrabber_lineups =
true;
405 if (capability ==
"preferredmethod")
406 hasprefmethod =
true;
408 LOG(VB_GENERAL, LOG_INFO,
409 QString(
"Grabber has capabilities: %1") .arg(capabilities));
417 QStringList(
"--preferredmethod"),
419 grabber_method_proc.
Run(15s);
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));
429 QTextStream ostream(grabber_method_proc.
ReadAll());
430 (*it).xmltvgrabber_prefmethod =
431 ostream.readLine().simplified();
433 LOG(VB_GENERAL, LOG_INFO, QString(
"Grabber prefers method: %1")
434 .arg((*it).xmltvgrabber_prefmethod));
445 else if ((*it).xmltvgrabber_baseline)
457 std::vector<bool> refresh_request;
464 for (
int i = 0; i < grabdays; i++)
468 for (
int i = 0; i < grabdays; i++)
479 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);