MythTV  0.26-pre
main.cpp
Go to the documentation of this file.
00001 // C headers
00002 #include <unistd.h>
00003 
00004 // C++ headers
00005 #include <iostream>
00006 using namespace std;
00007 
00008 // Qt headers
00009 #include <QCoreApplication>
00010 #include <QFileInfo>
00011 
00012 // libmyth headers
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 // libmythtv headers
00023 #include "commandlineparser.h"
00024 #include "scheduledrecording.h"
00025 #include "remoteutil.h"
00026 #include "videosource.h" // for is_grabber..
00027 #include "dbcheck.h"
00028 #include "mythsystemevent.h"
00029 #include "mythlogging.h"
00030 
00031 // filldata headers
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         // manual file mode
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         // datadirect file mode
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         // xaw channel import mode
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     // Mark first and last showings
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) // limit MSqlQuery's lifetime
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 /* vim: set expandtab tabstop=4 shiftwidth=4: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends