00001
00002 #include <unistd.h>
00003
00004
00005 #include <iostream>
00006 using namespace std;
00007
00008
00009 #include <QCoreApplication>
00010 #include <QFileInfo>
00011
00012
00013 #include "exitcodes.h"
00014 #include "mythcontext.h"
00015 #include "mythdb.h"
00016 #include "mythversion.h"
00017 #include "mythmiscutil.h"
00018 #include "mythtranslation.h"
00019
00020 #include "mythconfig.h"
00021
00022
00023 #include "commandlineparser.h"
00024 #include "scheduledrecording.h"
00025 #include "remoteutil.h"
00026 #include "videosource.h"
00027 #include "dbcheck.h"
00028 #include "mythsystemevent.h"
00029 #include "mythlogging.h"
00030
00031
00032 #include "filldata.h"
00033 namespace
00034 {
00035 void cleanup()
00036 {
00037 delete gContext;
00038 gContext = NULL;
00039
00040 }
00041
00042 class CleanupGuard
00043 {
00044 public:
00045 typedef void (*CleanupFunc)();
00046
00047 public:
00048 CleanupGuard(CleanupFunc cleanFunction) :
00049 m_cleanFunction(cleanFunction) {}
00050
00051 ~CleanupGuard()
00052 {
00053 m_cleanFunction();
00054 }
00055
00056 private:
00057 CleanupFunc m_cleanFunction;
00058 };
00059 }
00060
00061 int main(int argc, char *argv[])
00062 {
00063 FillData fill_data;
00064 int fromfile_id = 1;
00065 int fromfile_offset = 0;
00066 QString fromfile_name;
00067 bool from_xawfile = false;
00068 int fromxawfile_id = 1;
00069 QString fromxawfile_name;
00070 bool from_file = false;
00071 bool mark_repeats = true;
00072
00073 bool usingDataDirect = false;
00074 bool grab_data = true;
00075
00076 bool export_iconmap = false;
00077 bool import_iconmap = false;
00078 bool reset_iconmap = false;
00079 bool reset_iconmap_icons = false;
00080 QString import_icon_data_filename("iconmap.xml");
00081 QString export_icon_data_filename("iconmap.xml");
00082
00083 bool update_icon_data = false;
00084
00085 bool from_dd_file = false;
00086 int sourceid = -1;
00087 QString fromddfile_lineupid;
00088
00089 MythFillDatabaseCommandLineParser cmdline;
00090 if (!cmdline.Parse(argc, argv))
00091 {
00092 cmdline.PrintHelp();
00093 return GENERIC_EXIT_INVALID_CMDLINE;
00094 }
00095
00096 if (cmdline.toBool("showhelp"))
00097 {
00098 cmdline.PrintHelp();
00099 return GENERIC_EXIT_OK;
00100 }
00101
00102 if (cmdline.toBool("showversion"))
00103 {
00104 cmdline.PrintVersion();
00105 return GENERIC_EXIT_OK;
00106 }
00107
00108 QCoreApplication a(argc, argv);
00109 QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHFILLDATABASE);
00110
00111 myth_nice(19);
00112
00113 int retval;
00114 if ((retval = cmdline.ConfigureLogging()) != GENERIC_EXIT_OK)
00115 return retval;
00116
00117 if (cmdline.toBool("manual"))
00118 {
00119 cout << "###\n";
00120 cout << "### Running in manual channel configuration mode.\n";
00121 cout << "### This will ask you questions about every channel.\n";
00122 cout << "###\n";
00123 fill_data.chan_data.interactive = true;
00124 }
00125
00126 if (cmdline.toBool("update"))
00127 {
00128 if (cmdline.toBool("manual"))
00129 {
00130 cerr << "--update and --manual cannot be used simultaneously"
00131 << endl;
00132 return GENERIC_EXIT_INVALID_CMDLINE;
00133 }
00134 fill_data.chan_data.non_us_updating = true;
00135 }
00136
00137 if (cmdline.toBool("preset"))
00138 {
00139 cout << "###\n";
00140 cout << "### Running in preset channel configuration mode.\n";
00141 cout << "### This will assign channel ";
00142 cout << "preset numbers to every channel.\n";
00143 cout << "###\n";
00144 fill_data.chan_data.channel_preset = true;
00145 }
00146
00147 if (cmdline.toBool("file"))
00148 {
00149
00150 if (!cmdline.toBool("sourceid") ||
00151 !cmdline.toBool("xmlfile"))
00152 {
00153 cerr << "The --file option must be used in combination" << endl
00154 << "with both --sourceid and --xmlfile." << endl;
00155 return GENERIC_EXIT_INVALID_CMDLINE;
00156 }
00157
00158 fromfile_id = cmdline.toInt("sourceid");
00159 fromfile_name = cmdline.toString("xmlfile");
00160
00161 LOG(VB_GENERAL, LOG_INFO,
00162 "Bypassing grabbers, reading directly from file");
00163 from_file = true;
00164 }
00165
00166 if (cmdline.toBool("ddfile"))
00167 {
00168
00169 if (!cmdline.toBool("sourceid") ||
00170 !cmdline.toBool("offset") ||
00171 !cmdline.toBool("lineupid") ||
00172 !cmdline.toBool("xmlfile"))
00173 {
00174 cerr << "The --dd-file option must be used in combination" << endl
00175 << "with each of --sourceid, --offset, --lineupid," << endl
00176 << "and --xmlfile." << endl;
00177 return GENERIC_EXIT_INVALID_CMDLINE;
00178 }
00179
00180 fromfile_id = cmdline.toInt("sourceid");
00181 fromfile_offset = cmdline.toInt("offset");
00182 fromddfile_lineupid = cmdline.toInt("lineupid");
00183 fromfile_name = cmdline.toString("xmlfile");
00184
00185 LOG(VB_GENERAL, LOG_INFO,
00186 "Bypassing grabbers, reading directly from file");
00187 from_dd_file = true;
00188 }
00189
00190 if (cmdline.toBool("xawchannels"))
00191 {
00192
00193 if (!cmdline.toBool("sourceid") ||
00194 !cmdline.toBool("xawtvrcfile"))
00195 {
00196 cerr << "The --xawchannels option must be used in combination"
00197 << endl
00198 << "with both --sourceid and --xawtvrcfile" << endl;
00199 }
00200
00201 fromxawfile_id = cmdline.toInt("sourceid");
00202 fromxawfile_name = cmdline.toString("xawtvrcfile");
00203
00204 LOG(VB_GENERAL, LOG_INFO, "Reading channels from xawtv configfile");
00205 from_xawfile = true;
00206 }
00207
00208 if (cmdline.toBool("dochannelupdates"))
00209 fill_data.chan_data.channel_updates = true;
00210 if (cmdline.toBool("removechannels"))
00211 fill_data.chan_data.remove_new_channels = true;
00212 if (cmdline.toBool("nofilterchannels"))
00213 fill_data.chan_data.filter_new_channels = false;
00214 if (!cmdline.GetPassthrough().isEmpty())
00215 fill_data.graboptions = " " + cmdline.GetPassthrough();
00216 if (cmdline.toBool("sourceid"))
00217 sourceid = cmdline.toInt("sourceid");
00218 if (cmdline.toBool("cardtype"))
00219 {
00220 if (!cmdline.toBool("sourceid"))
00221 {
00222 cerr << "The --cardtype option must be used in combination" << endl
00223 << "with a --sourceid option." << endl;
00224 return GENERIC_EXIT_INVALID_CMDLINE;
00225 }
00226
00227 fill_data.chan_data.cardtype = cmdline.toString("cardtype")
00228 .trimmed().toUpper();
00229 }
00230 if (cmdline.toBool("maxdays") && cmdline.toInt("maxdays") > 0)
00231 {
00232 fill_data.maxDays = cmdline.toInt("maxdays");
00233 if (fill_data.maxDays == 1)
00234 fill_data.SetRefresh(0, true);
00235 }
00236
00237 if (cmdline.toBool("refreshtoday"))
00238 cmdline.SetValue("refresh",
00239 cmdline.toStringList("refresh") << "today");
00240 if (cmdline.toBool("dontrefreshtomorrow"))
00241 cmdline.SetValue("refresh",
00242 cmdline.toStringList("refresh") << "nottomorrow");
00243 if (cmdline.toBool("refreshsecond"))
00244 cmdline.SetValue("refresh",
00245 cmdline.toStringList("refresh") << "second");
00246 if (cmdline.toBool("refreshall"))
00247 cmdline.SetValue("refresh",
00248 cmdline.toStringList("refresh") << "all");
00249 if (cmdline.toBool("refreshday"))
00250 cmdline.SetValue("refresh",
00251 cmdline.toStringList("refresh") <<
00252 cmdline.toStringList("refreshday"));
00253
00254 QStringList sl = cmdline.toStringList("refresh");
00255 if (!sl.isEmpty())
00256 {
00257 QStringList::const_iterator i = sl.constBegin();
00258 for (; i != sl.constEnd(); ++i)
00259 {
00260 QString warn = QString("Invalid entry in --refresh list: %1")
00261 .arg(*i);
00262
00263 bool enable = (*i).contains("not") ? false : true;
00264
00265 if ((*i).contains("today"))
00266 fill_data.SetRefresh(0, enable);
00267 else if ((*i).contains("tomorrow"))
00268 fill_data.SetRefresh(1, enable);
00269 else if ((*i).contains("second"))
00270 fill_data.SetRefresh(2, enable);
00271 else if ((*i).contains("all"))
00272 fill_data.SetRefresh(FillData::kRefreshAll, enable);
00273 else if ((*i).contains("-"))
00274 {
00275 bool ok;
00276 QStringList r = (*i).split("-");
00277
00278 uint lower = r[0].toUInt(&ok);
00279 if (!ok)
00280 {
00281 cerr << warn.toLocal8Bit().constData() << endl;
00282 return false;
00283 }
00284
00285 uint upper = r[1].toUInt(&ok);
00286 if (!ok)
00287 {
00288 cerr << warn.toLocal8Bit().constData() << endl;
00289 return false;
00290 }
00291
00292 if (lower > upper)
00293 {
00294 cerr << warn.toLocal8Bit().constData() << endl;
00295 return false;
00296 }
00297
00298 for (uint j = lower; j <= upper; ++j)
00299 fill_data.SetRefresh(j, true);
00300 }
00301 else
00302 {
00303 bool ok;
00304 uint day = (*i).toUInt(&ok);
00305 if (!ok)
00306 {
00307 cerr << warn.toLocal8Bit().constData() << endl;
00308 return false;
00309 }
00310
00311 fill_data.SetRefresh(day, true);
00312 }
00313 }
00314 }
00315
00316 if (cmdline.toBool("dontrefreshtba"))
00317 fill_data.refresh_tba = false;
00318 if (cmdline.toBool("ddgraball"))
00319 {
00320 fill_data.SetRefresh(FillData::kRefreshClear, false);
00321 fill_data.dd_grab_all = true;
00322 }
00323 if (cmdline.toBool("onlychannels"))
00324 fill_data.only_update_channels = true;
00325
00326 mark_repeats = cmdline.toBool("markrepeats");
00327 if (cmdline.toBool("exporticonmap"))
00328 export_icon_data_filename = cmdline.toString("exporticonmap");
00329 if (cmdline.toBool("importiconmap"))
00330 import_icon_data_filename = cmdline.toString("importiconmap");
00331 if (cmdline.toBool("updateiconmap"))
00332 {
00333 update_icon_data = true;
00334 grab_data = false;
00335 }
00336 if (cmdline.toBool("reseticonmap"))
00337 {
00338 reset_iconmap = true;
00339 grab_data = false;
00340 if (cmdline.toString("reseticonmap") == "all")
00341 reset_iconmap_icons = true;
00342 }
00343
00344 CleanupGuard callCleanup(cleanup);
00345
00346 gContext = new MythContext(MYTH_BINARY_VERSION);
00347 if (!gContext->Init(false))
00348 {
00349 LOG(VB_GENERAL, LOG_ERR, "Failed to init MythContext, exiting.");
00350 return GENERIC_EXIT_NO_MYTHCONTEXT;
00351 }
00352
00353 setHttpProxy();
00354
00355 MythTranslation::load("mythfrontend");
00356
00357 if (!UpgradeTVDatabaseSchema(false))
00358 {
00359 LOG(VB_GENERAL, LOG_ERR, "Incorrect database schema");
00360 return GENERIC_EXIT_DB_OUTOFDATE;
00361 }
00362
00363 if (!grab_data)
00364 {
00365 }
00366 else if (from_xawfile)
00367 {
00368 fill_data.readXawtvChannels(fromxawfile_id, fromxawfile_name);
00369 }
00370 else if (from_file)
00371 {
00372 QString status = QObject::tr("currently running.");
00373 QDateTime GuideDataBefore, GuideDataAfter;
00374
00375 MSqlQuery query(MSqlQuery::InitCon());
00376 updateLastRunStart(query);
00377 updateLastRunStatus(query, status);
00378
00379 query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c "
00380 "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID "
00381 "AND manualid = 0 AND c.xmltvid != '';");
00382 query.bindValue(":SRCID", fromfile_id);
00383
00384 if (query.exec() && query.next())
00385 {
00386 if (!query.isNull(0))
00387 GuideDataBefore =
00388 QDateTime::fromString(query.value(0).toString(),
00389 Qt::ISODate);
00390 }
00391
00392 if (!fill_data.GrabDataFromFile(fromfile_id, fromfile_name))
00393 {
00394 return GENERIC_EXIT_NOT_OK;
00395 }
00396
00397 updateLastRunEnd(query);
00398
00399 query.prepare("SELECT MAX(endtime) FROM program p LEFT JOIN channel c "
00400 "ON p.chanid=c.chanid WHERE c.sourceid= :SRCID "
00401 "AND manualid = 0 AND c.xmltvid != '';");
00402 query.bindValue(":SRCID", fromfile_id);
00403
00404 if (query.exec() && query.next())
00405 {
00406 if (!query.isNull(0))
00407 GuideDataAfter =
00408 QDateTime::fromString(query.value(0).toString(),
00409 Qt::ISODate);
00410 }
00411
00412 if (GuideDataAfter == GuideDataBefore)
00413 status = QObject::tr("mythfilldatabase ran, but did not insert "
00414 "any new data into the Guide. This can indicate a "
00415 "potential problem with the XML file used for the update.");
00416 else
00417 status = QObject::tr("Successful.");
00418
00419 updateLastRunStatus(query, status);
00420 }
00421 else if (from_dd_file)
00422 {
00423 fill_data.GrabDataFromDDFile(
00424 fromfile_id, fromfile_offset, fromfile_name, fromddfile_lineupid);
00425 }
00426 else
00427 {
00428 SourceList sourcelist;
00429
00430 MSqlQuery sourcequery(MSqlQuery::InitCon());
00431 QString where = "";
00432
00433 if (sourceid != -1)
00434 {
00435 LOG(VB_GENERAL, LOG_INFO,
00436 QString("Running for sourceid %1 ONLY because --sourceid "
00437 "was given on command-line").arg(sourceid));
00438 where = QString("WHERE sourceid = %1").arg(sourceid);
00439 }
00440
00441 QString querystr = QString("SELECT sourceid,name,xmltvgrabber,userid,"
00442 "password,lineupid "
00443 "FROM videosource ") + where +
00444 QString(" ORDER BY sourceid;");
00445
00446 if (sourcequery.exec(querystr))
00447 {
00448 if (sourcequery.size() > 0)
00449 {
00450 while (sourcequery.next())
00451 {
00452 Source newsource;
00453
00454 newsource.id = sourcequery.value(0).toInt();
00455 newsource.name = sourcequery.value(1).toString();
00456 newsource.xmltvgrabber = sourcequery.value(2).toString();
00457 newsource.userid = sourcequery.value(3).toString();
00458 newsource.password = sourcequery.value(4).toString();
00459 newsource.lineupid = sourcequery.value(5).toString();
00460
00461 newsource.xmltvgrabber_baseline = false;
00462 newsource.xmltvgrabber_manualconfig = false;
00463 newsource.xmltvgrabber_cache = false;
00464 newsource.xmltvgrabber_prefmethod = "";
00465
00466 sourcelist.push_back(newsource);
00467 usingDataDirect |=
00468 is_grabber_datadirect(newsource.xmltvgrabber);
00469 }
00470 }
00471 else
00472 {
00473 LOG(VB_GENERAL, LOG_ERR,
00474 "There are no channel sources defined, did you run "
00475 "the setup program?");
00476 return GENERIC_EXIT_SETUP_ERROR;
00477 }
00478 }
00479 else
00480 {
00481 MythDB::DBError("loading channel sources", sourcequery);
00482 return GENERIC_EXIT_DB_ERROR;
00483 }
00484
00485 if (!fill_data.Run(sourcelist))
00486 LOG(VB_GENERAL, LOG_ERR, "Failed to fetch some program info");
00487 else
00488 LOG(VB_GENERAL, LOG_NOTICE, "Data fetching complete.");
00489 }
00490
00491 if (fill_data.only_update_channels && !fill_data.need_post_grab_proc)
00492 {
00493 return GENERIC_EXIT_OK;
00494 }
00495
00496 if (reset_iconmap)
00497 {
00498 fill_data.icon_data.ResetIconMap(reset_iconmap_icons);
00499 }
00500
00501 if (import_iconmap)
00502 {
00503 fill_data.icon_data.ImportIconMap(import_icon_data_filename);
00504 }
00505
00506 if (export_iconmap)
00507 {
00508 fill_data.icon_data.ExportIconMap(export_icon_data_filename);
00509 }
00510
00511 if (update_icon_data)
00512 {
00513 MSqlQuery query(MSqlQuery::InitCon());
00514 query.prepare("SELECT sourceid FROM videosource ORDER BY sourceid");
00515 if (!query.exec())
00516 {
00517 MythDB::DBError("Querying sources", query);
00518 return GENERIC_EXIT_DB_ERROR;
00519 }
00520
00521 while (query.next())
00522 fill_data.icon_data.UpdateSourceIcons(query.value(0).toInt());
00523 }
00524
00525 if (grab_data)
00526 {
00527 LOG(VB_GENERAL, LOG_INFO, "Adjusting program database end times.");
00528 int update_count = ProgramData::fix_end_times();
00529 if (update_count == -1)
00530 LOG(VB_GENERAL, LOG_ERR, "fix_end_times failed!");
00531 else
00532 LOG(VB_GENERAL, LOG_INFO,
00533 QString(" %1 replacements made").arg(update_count));
00534 }
00535
00536 if (grab_data)
00537 {
00538 LOG(VB_GENERAL, LOG_INFO, "Marking generic episodes.");
00539
00540 MSqlQuery query(MSqlQuery::InitCon());
00541 query.prepare("UPDATE program SET generic = 1 WHERE "
00542 "((programid = '' AND subtitle = '' AND description = '') OR "
00543 " (programid <> '' AND category_type = 'series' AND "
00544 " program.programid LIKE '%0000'));");
00545
00546 if (!query.exec())
00547 MythDB::DBError("mark generic", query);
00548 else
00549 LOG(VB_GENERAL, LOG_INFO,
00550 QString(" Found %1").arg(query.numRowsAffected()));
00551 }
00552
00553 if (grab_data)
00554 {
00555 LOG(VB_GENERAL, LOG_INFO, "Extending non-unique programids "
00556 "with multiple parts.");
00557
00558 int found = 0;
00559 MSqlQuery sel(MSqlQuery::InitCon());
00560 sel.prepare("SELECT DISTINCT programid, partnumber, parttotal "
00561 "FROM program WHERE partnumber > 0 AND parttotal > 0 AND "
00562 "programid LIKE '%0000'");
00563 if (sel.exec())
00564 {
00565 MSqlQuery repl(MSqlQuery::InitCon());
00566 repl.prepare("UPDATE program SET programid = :NEWID "
00567 "WHERE programid = :OLDID AND "
00568 "partnumber = :PARTNUM AND "
00569 "parttotal = :PARTTOTAL");
00570
00571 while (sel.next())
00572 {
00573 QString orig_programid = sel.value(0).toString();
00574 QString new_programid = orig_programid.left(10);
00575 int partnum, parttotal;
00576 QString part;
00577
00578 partnum = sel.value(1).toInt();
00579 parttotal = sel.value(2).toInt();
00580
00581 part.setNum(parttotal);
00582 new_programid.append(part.rightJustified(2, '0'));
00583 part.setNum(partnum);
00584 new_programid.append(part.rightJustified(2, '0'));
00585
00586 LOG(VB_GENERAL, LOG_INFO,
00587 QString(" %1 -> %2 (part %3 of %4)")
00588 .arg(orig_programid).arg(new_programid)
00589 .arg(partnum).arg(parttotal));
00590
00591 repl.bindValue(":NEWID", new_programid);
00592 repl.bindValue(":OLDID", orig_programid);
00593 repl.bindValue(":PARTNUM", partnum);
00594 repl.bindValue(":PARTTOTAL", parttotal);
00595 if (!repl.exec())
00596 {
00597 LOG(VB_GENERAL, LOG_INFO,
00598 QString("Fudging programid from '%1' to '%2'")
00599 .arg(orig_programid)
00600 .arg(new_programid));
00601 }
00602 else
00603 found += repl.numRowsAffected();
00604 }
00605 }
00606
00607 LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(found));
00608 }
00609
00610 if (mark_repeats)
00611 {
00612 LOG(VB_GENERAL, LOG_INFO, "Marking repeats.");
00613
00614 int newEpiWindow = gCoreContext->GetNumSetting( "NewEpisodeWindow", 14);
00615
00616 MSqlQuery query(MSqlQuery::InitCon());
00617 query.prepare("UPDATE program SET previouslyshown = 1 "
00618 "WHERE previouslyshown = 0 "
00619 "AND originalairdate is not null "
00620 "AND (to_days(starttime) - to_days(originalairdate)) "
00621 " > :NEWWINDOW;");
00622 query.bindValue(":NEWWINDOW", newEpiWindow);
00623
00624 if (query.exec())
00625 LOG(VB_GENERAL, LOG_INFO,
00626 QString(" Found %1").arg(query.numRowsAffected()));
00627
00628 LOG(VB_GENERAL, LOG_INFO, "Unmarking new episode rebroadcast repeats.");
00629 query.prepare("UPDATE program SET previouslyshown = 0 "
00630 "WHERE previouslyshown = 1 "
00631 "AND originalairdate is not null "
00632 "AND (to_days(starttime) - to_days(originalairdate)) "
00633 " <= :NEWWINDOW;");
00634 query.bindValue(":NEWWINDOW", newEpiWindow);
00635
00636 if (query.exec())
00637 LOG(VB_GENERAL, LOG_INFO,
00638 QString(" Found %1").arg(query.numRowsAffected()));
00639 }
00640
00641
00642
00643 if (grab_data)
00644 {
00645 MSqlQuery updt(MSqlQuery::InitCon());
00646 updt.prepare("UPDATE program SET first = 0, last = 0;");
00647 if (!updt.exec())
00648 MythDB::DBError("Clearing first and last showings", updt);
00649
00650 LOG(VB_GENERAL, LOG_INFO, "Marking episode first showings.");
00651 updt.prepare("UPDATE program "
00652 "JOIN (SELECT MIN(starttime) AS starttime, programid "
00653 " FROM program "
00654 " WHERE programid <> '' "
00655 " GROUP BY programid "
00656 " ) AS firsts "
00657 "ON program.programid = firsts.programid "
00658 " AND program.starttime = firsts.starttime "
00659 "SET program.first=1;");
00660 if (!updt.exec())
00661 MythDB::DBError("Marking first showings by id", updt);
00662 int found = updt.numRowsAffected();
00663
00664 updt.prepare("UPDATE program "
00665 "JOIN (SELECT MIN(starttime) AS starttime, title, subtitle,"
00666 " LEFT(description, 1024) AS partdesc "
00667 " FROM program "
00668 " WHERE programid = '' "
00669 " GROUP BY title, subtitle, partdesc "
00670 " ) AS firsts "
00671 "ON program.starttime = firsts.starttime "
00672 " AND program.title = firsts.title "
00673 " AND program.subtitle = firsts.subtitle "
00674 " AND LEFT(program.description, 1024) = firsts.partdesc "
00675 "SET program.first = 1 "
00676 "WHERE program.programid = '';");
00677 if (!updt.exec())
00678 MythDB::DBError("Marking first showings", updt);
00679 found += updt.numRowsAffected();
00680 LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(found));
00681
00682 LOG(VB_GENERAL, LOG_INFO, "Marking episode last showings.");
00683 updt.prepare("UPDATE program "
00684 "JOIN (SELECT MAX(starttime) AS starttime, programid "
00685 " FROM program "
00686 " WHERE programid <> '' "
00687 " GROUP BY programid "
00688 " ) AS lasts "
00689 "ON program.programid = lasts.programid "
00690 " AND program.starttime = lasts.starttime "
00691 "SET program.last=1;");
00692 if (!updt.exec())
00693 MythDB::DBError("Marking last showings by id", updt);
00694 found = updt.numRowsAffected();
00695
00696 updt.prepare("UPDATE program "
00697 "JOIN (SELECT MAX(starttime) AS starttime, title, subtitle,"
00698 " LEFT(description, 1024) AS partdesc "
00699 " FROM program "
00700 " WHERE programid = '' "
00701 " GROUP BY title, subtitle, partdesc "
00702 " ) AS lasts "
00703 "ON program.starttime = lasts.starttime "
00704 " AND program.title = lasts.title "
00705 " AND program.subtitle = lasts.subtitle "
00706 " AND LEFT(program.description, 1024) = lasts.partdesc "
00707 "SET program.last = 1 "
00708 "WHERE program.programid = '';");
00709 if (!updt.exec())
00710 MythDB::DBError("Marking last showings", updt);
00711 found += updt.numRowsAffected();
00712 LOG(VB_GENERAL, LOG_INFO, QString(" Found %1").arg(found));
00713 }
00714
00715 if (1)
00716 {
00717 MSqlQuery query(MSqlQuery::InitCon());
00718 query.prepare("SELECT count(previouslyshown) "
00719 "FROM program WHERE previouslyshown = 1;");
00720 if (query.exec() && query.next())
00721 {
00722 if (query.value(0).toInt() != 0)
00723 gCoreContext->SaveSettingOnHost("HaveRepeats", "1", NULL);
00724 else
00725 gCoreContext->SaveSettingOnHost("HaveRepeats", "0", NULL);
00726 }
00727 }
00728
00729 if ((usingDataDirect) &&
00730 (gCoreContext->GetNumSetting("MythFillGrabberSuggestsTime", 1)))
00731 {
00732 fill_data.ddprocessor.GrabNextSuggestedTime();
00733 }
00734
00735 LOG(VB_GENERAL, LOG_INFO, "\n"
00736 "===============================================================\n"
00737 "| Attempting to contact the master backend for rescheduling. |\n"
00738 "| If the master is not running, rescheduling will happen when |\n"
00739 "| the master backend is restarted. |\n"
00740 "===============================================================");
00741
00742 if (grab_data || mark_repeats)
00743 ScheduledRecording::RescheduleMatch(0, 0, 0, QDateTime(),
00744 "MythFillDatabase");
00745
00746 gCoreContext->SendMessage("CLEAR_SETTINGS_CACHE");
00747
00748 gCoreContext->SendSystemEvent("MYTHFILLDATABASE_RAN");
00749
00750 LOG(VB_GENERAL, LOG_NOTICE, "mythfilldatabase run complete.");
00751
00752 return GENERIC_EXIT_OK;
00753 }
00754
00755