MythTV  0.26-pre
sourceutil.cpp
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
00002 
00003 // Qt headers
00004 #include <QRegExp>
00005 
00006 // MythTV headers
00007 #include "sourceutil.h"
00008 #include "cardutil.h"
00009 #include "mythdb.h"
00010 #include "mythdirs.h"
00011 #include "mythlogging.h"
00012 #include "mythmiscutil.h"
00013 
00014 bool SourceUtil::HasDigitalChannel(uint sourceid)
00015 {
00016     MSqlQuery query(MSqlQuery::InitCon());
00017 
00018     query.prepare(
00019         "SELECT mplexid, atsc_minor_chan, serviceid "
00020         "FROM channel "
00021         "WHERE sourceid = :SOURCEID");
00022     query.bindValue(":SOURCEID", sourceid);
00023 
00024     if (!query.exec())
00025     {
00026         MythDB::DBError("SourceUtil::HasDigitalChannel()", query);
00027         return false;
00028     }
00029 
00030     while (query.next())
00031     {
00032         uint mplexid = query.value(0).toUInt();
00033         uint minor   = query.value(1).toUInt();
00034         uint prognum = query.value(2).toUInt();
00035         mplexid = (32767 == mplexid) ? 0 : mplexid;
00036 
00037         if (mplexid && (minor || prognum))
00038             return true;
00039     }
00040 
00041     return false;
00042 }
00043 
00044 QString SourceUtil::GetSourceName(uint sourceid)
00045 {
00046     MSqlQuery query(MSqlQuery::InitCon());
00047 
00048     query.prepare(
00049         "SELECT name "
00050         "FROM videosource "
00051         "WHERE sourceid = :SOURCEID");
00052     query.bindValue(":SOURCEID", sourceid);
00053 
00054     if (!query.exec())
00055     {
00056         MythDB::DBError("SourceUtil::GetSourceName()", query);
00057         return QString::null;
00058     }
00059     else if (!query.next())
00060     {
00061         return QString::null;
00062     }
00063 
00064     return query.value(0).toString();
00065 }
00066 
00067 QString SourceUtil::GetChannelSeparator(uint sourceid)
00068 {
00069     MSqlQuery query(MSqlQuery::InitCon());
00070     query.prepare("SELECT channum "
00071                   "FROM channel "
00072                   "WHERE sourceid = :SOURCEID");
00073     query.bindValue(":SOURCEID", sourceid);
00074 
00075     if (query.exec() && query.isActive() && query.size() > 0)
00076     {
00077         QMap<QString,uint> counts;
00078         const QRegExp sepExpr("(_|-|#|\\.)");
00079         while (query.next())
00080         {
00081             const QString channum = query.value(0).toString();
00082             const int where = channum.indexOf(sepExpr);
00083             if (channum.right(2).left(1) == "0")
00084                 counts["0"]++;
00085             else
00086                 counts[(where < 0) ? "" : QString(channum.at(where))]++;
00087         }
00088         QString sep = "_";
00089         uint max = counts["_"];
00090         static const char *spacers[6] = { "", "-", "#", ".", "0", NULL };
00091         for (uint i=0; (spacers[i] != NULL); ++i)
00092         {
00093             if (counts[spacers[i]] > max)
00094             {
00095                 max = counts[spacers[i]];
00096                 sep = spacers[i];
00097             }
00098         }
00099         return sep;
00100     }
00101     return "_"; // default on failure
00102 }
00103 
00104 QString SourceUtil::GetChannelFormat(uint sourceid)
00105 {
00106     return QString("%1") + GetChannelSeparator(sourceid) + QString("%2");
00107 }
00108 
00109 uint SourceUtil::GetChannelCount(uint sourceid)
00110 {
00111     MSqlQuery query(MSqlQuery::InitCon());
00112     query.prepare("SELECT sum(1) "
00113                   "FROM channel "
00114                   "WHERE sourceid = :SOURCEID");
00115     query.bindValue(":SOURCEID", sourceid);
00116     if (query.exec() && query.isActive() && query.next())
00117         return query.value(0).toUInt();
00118     return 0;
00119 }
00120 
00121 vector<uint> SourceUtil::GetMplexIDs(uint sourceid)
00122 {
00123     MSqlQuery query(MSqlQuery::InitCon());
00124 
00125     query.prepare(
00126         "SELECT mplexid "
00127         "FROM dtv_multiplex "
00128         "WHERE sourceid = :SOURCEID");
00129     query.bindValue(":SOURCEID", sourceid);
00130 
00131     vector<uint> list;
00132     if (!query.exec())
00133     {
00134         MythDB::DBError("SourceUtil::GetMplexIDs()", query);
00135         return list;
00136     }
00137 
00138     while (query.next())
00139         list.push_back(query.value(0).toUInt());
00140 
00141     return list;
00142 }
00143 
00144 bool SourceUtil::GetListingsLoginData(uint sourceid,
00145                                       QString &grabber, QString &userid,
00146                                       QString &passwd,  QString &lineupid)
00147 {
00148     MSqlQuery query(MSqlQuery::InitCon());
00149     query.prepare(
00150         "SELECT xmltvgrabber, userid, password, lineupid "
00151         "FROM videosource "
00152         "WHERE sourceid = :SOURCEID");
00153     query.bindValue(":SOURCEID", sourceid);
00154 
00155     if (!query.exec() || !query.isActive())
00156     {
00157         MythDB::DBError("SourceUtil::GetListingsLoginData()", query);
00158         return false;
00159     }
00160 
00161     if (!query.next())
00162         return false;
00163 
00164     grabber  = query.value(0).toString();
00165     userid   = query.value(1).toString();
00166     passwd   = query.value(2).toString();
00167     lineupid = query.value(3).toString();
00168 
00169     return true;
00170 }
00171 
00172 static QStringList get_cardtypes(uint sourceid)
00173 {
00174     QStringList list;
00175 
00176     MSqlQuery query(MSqlQuery::InitCon());
00177     query.prepare(
00178         "SELECT cardtype, inputname "
00179         "FROM capturecard, cardinput "
00180         "WHERE capturecard.cardid = cardinput.cardid AND "
00181         "      cardinput.sourceid = :SOURCEID");
00182     query.bindValue(":SOURCEID", sourceid);
00183 
00184     if (!query.exec() || !query.isActive())
00185         MythDB::DBError("get_cardtypes()", query);
00186     else
00187     {
00188         while (query.next())
00189         {
00191             QString cardtype = query.value(0).toString().toUpper();
00192             QString inputname = query.value(1).toString().toUpper();
00193             cardtype = ((cardtype == "DVB") && (inputname.left(3) != "DVB")) ?
00194                 "V4L" : cardtype;
00196             list += cardtype;
00197         }
00198     }
00199 
00200     return list;
00201 }
00202 
00203 uint SourceUtil::GetConnectionCount(uint sourceid)
00204 {
00205     QStringList types = get_cardtypes(sourceid);
00206     return types.size();
00207 }
00208 
00209 bool SourceUtil::IsProperlyConnected(uint sourceid, bool strict)
00210 {
00211     QStringList types = get_cardtypes(sourceid);
00212     QMap<QString,uint> counts;
00213     QStringList::const_iterator it = types.begin();
00214     for (; it != types.end(); ++it)
00215     {
00216         counts[*it]++;
00217 
00218         counts[CardUtil::IsEncoder(*it)    ? "ENCODER" : "NOT_ENCODER"]++;
00219         counts[CardUtil::IsUnscanable(*it) ? "NO_SCAN" : "SCAN"]++;
00220 
00221         if (CardUtil::IsTuningAnalog(*it))
00222             counts["ANALOG_TUNING"]++;
00223         else if (CardUtil::IsTuningDigital(*it))
00224             counts["DIGITAL_TUNING"]++;
00225         else if (CardUtil::IsTuningVirtual(*it))
00226             counts["VIRTUAL_TUNING"]++;
00227     }
00228 
00229     bool tune_mismatch =
00230         (counts["ANALOG_TUNING"]  && counts["DIGITAL_TUNING"]) ||
00231         (counts["VIRTUAL_TUNING"] && counts["DIGITAL_TUNING"]);
00232     bool enc_mismatch  = counts["ENCODER"] && counts["NOT_ENCODER"];
00233     bool scan_mismatch = counts["SCAN"]    && counts["NO_SCAN"];
00234 
00235     if (tune_mismatch)
00236     {
00237         uint a = counts["ANALOG_TUNERS"];
00238         uint d = counts["DIGITAL_TUNERS"];
00239         uint v = counts["VIRTUAL_TUNERS"];
00240         LOG(VB_GENERAL, LOG_NOTICE,
00241             QString("SourceUtil::IsProperlyConnected(): ") +
00242             QString("Connected to %1 analog, %2 digital and %3 virtual "
00243                     "tuners\n\t\t\t").arg(a).arg(d).arg(v) +
00244             QString("Can not mix digital with other tuning information."));
00245     }
00246 
00247     if (enc_mismatch)
00248     {
00249         uint a = counts["ENCODER"];
00250         uint d = counts["NOT_ENCODER"];
00251         LOG(VB_GENERAL, LOG_NOTICE,
00252             QString("SourceUtil::IsProperlyConnected(): ") +
00253             QString("Source ID %1 ").arg(sourceid) +
00254             QString("appears to be connected\n\t\t\tto %1 encoder%2, ")
00255                 .arg(a).arg((1 == a) ? "":"s") +
00256             QString("and %1 non-encoder%2. ")
00257                 .arg(d).arg((1 == d) ? "":"s") +
00258             QString("This is probably a bad idea."));
00259     }
00260 
00261     if (scan_mismatch)
00262     {
00263         uint a = counts["SCAN"];
00264         uint d = counts["NO_SCAN"];
00265         LOG(VB_GENERAL, LOG_NOTICE,
00266             QString("SourceUtil::IsProperlyConnected(): ") +
00267             QString("Source ID %1 ").arg(sourceid) +
00268             QString("appears to be connected\n\t\t\t"
00269                     "to %1 scanable input%2, ")
00270                 .arg(a).arg((1 == a) ? "":"s") +
00271             QString("and %1 non-scanable input%2. ")
00272                 .arg(d).arg((1 == d) ? "":"s") +
00273             QString("This may be a problem."));
00274     }
00275 
00276     if (!strict)
00277         return !tune_mismatch;
00278 
00279     return !tune_mismatch && !enc_mismatch && !scan_mismatch;
00280 }
00281 
00282 bool SourceUtil::IsEncoder(uint sourceid, bool strict)
00283 {
00284     bool encoder = true;
00285 
00286     QStringList types = get_cardtypes(sourceid);
00287     QStringList::const_iterator it = types.begin();
00288     for (; it != types.end(); ++it)
00289         encoder &= CardUtil::IsEncoder(*it);
00290 
00291     // Source is connected, go by card types for type determination
00292     if (!types.empty())
00293         return encoder;
00294 
00295     // Try looking at channels if source is not connected,
00296     MSqlQuery query(MSqlQuery::InitCon());
00297     query.prepare(
00298         "SELECT atsc_minor_chan, serviceid "
00299         "FROM channel "
00300         "WHERE sourceid = :SOURCEID");
00301     query.bindValue(":SOURCEID", sourceid);
00302 
00303     bool has_any_chan = false;
00304     if (!query.exec() || !query.isActive())
00305         MythDB::DBError("SourceUtil::IsEncoder", query);
00306     else
00307     {
00308         while (query.next())
00309         {
00310             encoder &= !query.value(0).toInt() && !query.value(1).toInt();
00311             has_any_chan = true;
00312         }
00313     }
00314 
00315     return (strict && !has_any_chan) ? false: encoder;
00316 }
00317 
00318 bool SourceUtil::IsUnscanable(uint sourceid)
00319 {
00320     bool unscanable = true;
00321     QStringList types = get_cardtypes(sourceid);
00322     QStringList::const_iterator it = types.begin();
00323     for (; it != types.end(); ++it)
00324         unscanable &= CardUtil::IsUnscanable(*it);
00325 
00326     return types.empty() || unscanable;
00327 }
00328 
00329 bool SourceUtil::IsCableCardPresent(uint sourceid)
00330 {
00331     bool ccpresent = false;
00332     vector<uint> cards = CardUtil::GetCardIDs(sourceid);
00333     vector<uint>::iterator it = cards.begin();
00334     for (; it != cards.end(); ++it)
00335     {
00336         if (CardUtil::IsCableCardPresent(*it, CardUtil::GetRawCardType(*it)))
00337             ccpresent = true;
00338     }
00339 
00340     return ccpresent;
00341 }
00342 
00343 bool SourceUtil::IsAnySourceScanable(void)
00344 {
00345     MSqlQuery query(MSqlQuery::InitCon());
00346     query.prepare("SELECT sourceid FROM videosource");
00347 
00348     if (!query.exec() || !query.isActive())
00349     {
00350         MythDB::DBError("SourceUtil::IsAnySourceScanable", query);
00351         return false;
00352     }
00353 
00354     while (query.next())
00355     {
00356         if (!IsUnscanable(query.value(0).toUInt()))
00357             return true;
00358     }
00359 
00360     return false;
00361 }
00362 
00363 bool SourceUtil::UpdateChannelsFromListings(uint sourceid, QString cardtype, bool wait)
00364 {
00365     if (wait)
00366     {
00367         QString cmd = GetInstallPrefix() +
00368                       "/bin/mythfilldatabase";
00369         QStringList args;
00370         args.append("--only-update-channels");
00371 
00372         if (sourceid)
00373         {
00374             args.append(QString("--sourceid"));
00375             args.append(QString::number(sourceid));
00376         }
00377         if (!cardtype.isEmpty())
00378         {
00379             args.append(QString("--cardtype"));
00380             args.append(cardtype);
00381         }
00382 
00383         MythSystem getchan(cmd, args, kMSRunShell | kMSAutoCleanup );
00384         getchan.Run();
00385         getchan.Wait();
00386     }
00387     else
00388     {
00389         QString cmd = GetInstallPrefix() +
00390                       "/bin/mythfilldatabase --only-update-channels";
00391         if (sourceid)
00392             cmd += QString(" --sourceid %1").arg(sourceid);
00393         if (!cardtype.isEmpty())
00394             cmd += QString(" --cardtype %1").arg(cardtype);
00395         cmd += logPropagateArgs;
00396 
00397         myth_system(cmd);
00398     }
00399 
00400     return true;
00401 }
00402 
00403 bool SourceUtil::UpdateSource( uint sourceid, QString sourcename,
00404                                QString grabber, QString userid,
00405                                QString freqtable, QString lineupid,
00406                                QString password, bool useeit,
00407                                QString configpath, int nitid)
00408 {
00409     MSqlQuery query(MSqlQuery::InitCon());
00410 
00411     query.prepare("UPDATE videosource SET name = :NAME, xmltvgrabber = :XMLTVGRABBER, "
00412                   "userid = :USERID, freqtable = :FREQTABLE, lineupid = :LINEUPID,"
00413                   "password = :PASSWORD, useeit = :USEEIT, configpath = :CONFIGPATH, "
00414                   "dvb_nit_id = :NITID WHERE sourceid = :SOURCEID");
00415 
00416     query.bindValue(":NAME", sourcename);
00417     query.bindValue(":XMLTVGRABBER", grabber);
00418     query.bindValue(":USERID", userid);
00419     query.bindValue(":FREQTABLE", freqtable);
00420     query.bindValue(":LINEUPID", lineupid);
00421     query.bindValue(":PASSWORD", password);
00422     query.bindValue(":USEEIT", useeit);
00423     query.bindValue(":CONFIGPATH", configpath);
00424     query.bindValue(":NITID", nitid);
00425     query.bindValue(":SOURCEID", sourceid);
00426 
00427     if (!query.exec() || !query.isActive())
00428     {
00429         MythDB::DBError("Updating Video Source", query);
00430         return false;
00431     }
00432 
00433     return true;
00434 }
00435 
00436 int SourceUtil::CreateSource( QString sourcename,
00437                                QString grabber, QString userid,
00438                                QString freqtable, QString lineupid,
00439                                QString password, bool useeit,
00440                                QString configpath, int nitid)
00441 {
00442     MSqlQuery query(MSqlQuery::InitCon());
00443 
00444     query.prepare("INSERT INTO videosource (name,xmltvgrabber,userid,freqtable,lineupid,"
00445                   "password,useeit,configpath,dvb_nit_id) VALUES (:NAME, :XMLTVGRABBER, "
00446                   ":USERID, :FREQTABLE, :LINEUPID, :PASSWORD, :USEEIT, :CONFIGPATH, :NITID)");
00447 
00448     query.bindValue(":NAME", sourcename);
00449     query.bindValue(":XMLTVGRABBER", grabber);
00450     query.bindValue(":USERID", userid);
00451     query.bindValue(":FREQTABLE", freqtable);
00452     query.bindValue(":LINEUPID", lineupid);
00453     query.bindValue(":PASSWORD", password);
00454     query.bindValue(":USEEIT", useeit);
00455     query.bindValue(":CONFIGPATH", configpath);
00456     query.bindValue(":NITID", nitid);
00457 
00458     if (!query.exec() || !query.isActive())
00459     {
00460         MythDB::DBError("Adding Video Source", query);
00461         return -1;
00462     }
00463 
00464     query.prepare("SELECT MAX(sourceid) FROM videosource");
00465 
00466     if (!query.exec())
00467     {
00468         MythDB::DBError("CreateSource maxsource", query);
00469         return -1;
00470     }
00471 
00472     uint sourceid = -1;
00473 
00474     if (query.next())
00475         sourceid = query.value(0).toUInt();
00476 
00477     return sourceid;
00478 }
00479 
00480 bool SourceUtil::DeleteSource(uint sourceid)
00481 {
00482     MSqlQuery query(MSqlQuery::InitCon());
00483 
00484     // Delete the channels associated with the source
00485     query.prepare("DELETE FROM channel "
00486                   "WHERE sourceid = :SOURCEID");
00487     query.bindValue(":SOURCEID", sourceid);
00488 
00489     if (!query.exec() || !query.isActive())
00490     {
00491         MythDB::DBError("Deleting Channels", query);
00492         return false;
00493     }
00494 
00495     // Delete the multiplexes associated with the source
00496     query.prepare("DELETE FROM dtv_multiplex "
00497                   "WHERE sourceid = :SOURCEID");
00498     query.bindValue(":SOURCEID", sourceid);
00499 
00500     if (!query.exec() || !query.isActive())
00501     {
00502         MythDB::DBError("Deleting Multiplexes", query);
00503         return false;
00504     }
00505 
00506     // Delete the inputs associated with the source
00507     query.prepare("DELETE FROM cardinput "
00508                   "WHERE sourceid = :SOURCEID");
00509     query.bindValue(":SOURCEID", sourceid);
00510 
00511     if (!query.exec() || !query.isActive())
00512     {
00513         MythDB::DBError("Deleting cardinputs", query);
00514         return false;
00515     }
00516 
00517     // Delete the source itself
00518     query.prepare("DELETE FROM videosource "
00519                   "WHERE sourceid = :SOURCEID");
00520     query.bindValue(":SOURCEID", sourceid);
00521 
00522     if (!query.exec() || !query.isActive())
00523     {
00524         MythDB::DBError("Deleting VideoSource", query);
00525         return false;
00526     }
00527 
00528     // Delete any orphaned inputs & unused input groups
00529     CardUtil::DeleteOrphanInputs();
00530     CardUtil::UnlinkInputGroup(0,0);
00531 
00532     return true;
00533 }
00534 
00535 bool SourceUtil::DeleteAllSources(void)
00536 {
00537     MSqlQuery query(MSqlQuery::InitCon());
00538     return (query.exec("TRUNCATE TABLE channel") &&
00539             query.exec("TRUNCATE TABLE program") &&
00540             query.exec("TRUNCATE TABLE videosource") &&
00541             query.exec("TRUNCATE TABLE credits") &&
00542             query.exec("TRUNCATE TABLE programrating") &&
00543             query.exec("TRUNCATE TABLE programgenres") &&
00544             query.exec("TRUNCATE TABLE dtv_multiplex") &&
00545             query.exec("TRUNCATE TABLE inputgroup") &&
00546             query.exec("TRUNCATE TABLE diseqc_config") &&
00547             query.exec("TRUNCATE TABLE diseqc_tree") &&
00548             query.exec("TRUNCATE TABLE eit_cache") &&
00549             query.exec("TRUNCATE TABLE channelgroup") &&
00550             query.exec("TRUNCATE TABLE channelgroupnames") &&
00551             query.exec("TRUNCATE TABLE cardinput"));
00552 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends