00001
00002
00003
00004 #include <qregexp.h>
00005
00006
00007 #include "sourceutil.h"
00008 #include "cardutil.h"
00009 #include "mythdbcon.h"
00010 #include "util.h"
00011
00012 bool SourceUtil::HasDigitalChannel(uint sourceid)
00013 {
00014 MSqlQuery query(MSqlQuery::InitCon());
00015
00016 query.prepare(
00017 "SELECT mplexid, atsc_minor_chan, serviceid "
00018 "FROM channel "
00019 "WHERE sourceid = :SOURCEID");
00020 query.bindValue(":SOURCEID", sourceid);
00021
00022 if (!query.exec())
00023 {
00024 MythContext::DBError("SourceUtil::HasDigitalChannel()", query);
00025 return false;
00026 }
00027
00028 while (query.next())
00029 {
00030 uint mplexid = query.value(0).toUInt();
00031 uint minor = query.value(1).toUInt();
00032 uint prognum = query.value(2).toUInt();
00033 mplexid = (32767 == mplexid) ? 0 : mplexid;
00034
00035 if (mplexid && (minor || prognum))
00036 return true;
00037 }
00038
00039 return false;
00040 }
00041
00042 QString SourceUtil::GetSourceName(uint sourceid)
00043 {
00044 MSqlQuery query(MSqlQuery::InitCon());
00045
00046 query.prepare(
00047 "SELECT name "
00048 "FROM videosource "
00049 "WHERE sourceid = :SOURCEID");
00050 query.bindValue(":SOURCEID", sourceid);
00051
00052 if (!query.exec())
00053 {
00054 MythContext::DBError("SourceUtil::GetSourceName()", query);
00055 return QString::null;
00056 }
00057 else if (!query.next())
00058 {
00059 return QString::null;
00060 }
00061
00062 return query.value(0).toString();
00063 }
00064
00065 QString SourceUtil::GetChannelSeparator(uint sourceid)
00066 {
00067 MSqlQuery query(MSqlQuery::InitCon());
00068 query.prepare("SELECT channum "
00069 "FROM channel "
00070 "WHERE sourceid = :SOURCEID");
00071 query.bindValue(":SOURCEID", sourceid);
00072
00073 if (query.exec() && query.isActive() && query.size() > 0)
00074 {
00075 QMap<QString,uint> counts;
00076 const QRegExp sepExpr("(_|-|#|\\.)");
00077 while (query.next())
00078 {
00079 const QString channum = query.value(0).toString();
00080 const int where = channum.find(sepExpr);
00081 if (channum.right(2).left(1) == "0")
00082 counts["0"]++;
00083 else
00084 counts[(where < 0) ? "" : QString(channum.at(where))]++;
00085 }
00086 QString sep = "_";
00087 uint max = counts["_"];
00088 static char *spacers[6] = { "", "-", "#", ".", "0", NULL };
00089 for (uint i=0; (spacers[i] != NULL); ++i)
00090 {
00091 if (counts[spacers[i]] > max)
00092 {
00093 max = counts[spacers[i]];
00094 sep = spacers[i];
00095 }
00096 }
00097 return sep;
00098 }
00099 return "_";
00100 }
00101
00102 QString SourceUtil::GetChannelFormat(uint sourceid)
00103 {
00104 return QString("%1") + GetChannelSeparator(sourceid) + QString("%2");
00105 }
00106
00107 uint SourceUtil::GetChannelCount(uint sourceid)
00108 {
00109 MSqlQuery query(MSqlQuery::InitCon());
00110 query.prepare("SELECT sum(1) "
00111 "FROM channel "
00112 "WHERE sourceid = :SOURCEID");
00113 query.bindValue(":SOURCEID", sourceid);
00114 if (query.exec() && query.isActive() && query.next())
00115 return query.value(0).toUInt();
00116 return 0;
00117 }
00118
00119 bool SourceUtil::GetListingsLoginData(uint sourceid,
00120 QString &grabber, QString &userid,
00121 QString &passwd, QString &lineupid)
00122 {
00123 MSqlQuery query(MSqlQuery::InitCon());
00124 query.prepare(
00125 "SELECT xmltvgrabber, userid, password, lineupid "
00126 "FROM videosource "
00127 "WHERE sourceid = :SOURCEID");
00128 query.bindValue(":SOURCEID", sourceid);
00129
00130 if (!query.exec() || !query.isActive())
00131 {
00132 MythContext::DBError("SourceUtil::GetListingsLoginData()", query);
00133 return false;
00134 }
00135
00136 if (!query.next())
00137 return false;
00138
00139 grabber = query.value(0).toString();
00140 userid = query.value(1).toString();
00141 passwd = query.value(2).toString();
00142 lineupid = query.value(3).toString();
00143
00144 return true;
00145 }
00146
00147 static QStringList get_cardtypes(uint sourceid)
00148 {
00149 QStringList list;
00150
00151 MSqlQuery query(MSqlQuery::InitCon());
00152 query.prepare(
00153 "SELECT cardtype, inputname "
00154 "FROM capturecard, cardinput "
00155 "WHERE capturecard.cardid = cardinput.cardid AND "
00156 " cardinput.sourceid = :SOURCEID");
00157 query.bindValue(":SOURCEID", sourceid);
00158
00159 if (!query.exec() || !query.isActive())
00160 MythContext::DBError("get_cardtypes()", query);
00161 else
00162 {
00163 while (query.next())
00164 {
00166 QString cardtype = query.value(0).toString().upper();
00167 QString inputname = query.value(1).toString().upper();
00168 cardtype = ((cardtype == "DVB") && (inputname.left(3) != "DVB")) ?
00169 "V4L" : cardtype;
00171 list += cardtype;
00172 }
00173 }
00174
00175 return list;
00176 }
00177
00178 uint SourceUtil::GetConnectionCount(uint sourceid)
00179 {
00180 QStringList types = get_cardtypes(sourceid);
00181 return types.size();
00182 }
00183
00184 bool SourceUtil::IsProperlyConnected(uint sourceid, bool strict)
00185 {
00186 QStringList types = get_cardtypes(sourceid);
00187 QMap<QString,uint> counts;
00188 QStringList::const_iterator it = types.begin();
00189 for (; it != types.end(); ++it)
00190 {
00191 counts[*it]++;
00192
00193 counts[CardUtil::IsEncoder(*it) ? "ENCODER" : "NOT_ENCODER"]++;
00194 counts[CardUtil::IsUnscanable(*it) ? "NO_SCAN" : "SCAN"]++;
00195
00196 if (CardUtil::IsTuningAnalog(*it))
00197 counts["ANALOG_TUNING"]++;
00198 else if (CardUtil::IsTuningDigital(*it))
00199 counts["DIGITAL_TUNING"]++;
00200 else
00201 counts["OTHER_TUNING"]++;
00202 }
00203
00204 bool tune_mismatch = counts["ANALOG_TUNING"] && counts["DIGITAL_TUNING"];
00205 bool enc_mismatch = counts["ENCODER"] && counts["NOT_ENCODER"];
00206 bool scan_mismatch = counts["SCAN"] && counts["NO_SCAN"];
00207 bool fw_mismatch = (counts["FIREWIRE"] &&
00208 (counts["FIREWIRE"] < types.size()));
00209
00210 if (tune_mismatch)
00211 {
00212 uint a = counts["ANALOG_TUNERS"];
00213 uint d = counts["DIGITAL_TUNERS"];
00214 VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
00215 QString("Source ID %1 ").arg(sourceid) +
00216 QString("appears to be connected\n\t\t\tto %1 analog tuner%2,")
00217 .arg(a).arg((1 == a) ? "":"s") +
00218 QString("and %1 digital tuner%2.\n\t\t\t")
00219 .arg(d).arg((1 == d) ? "":"s") +
00220 QString("Can't mix analog and digital tuning information."));
00221 }
00222
00223 if (enc_mismatch)
00224 {
00225 uint a = counts["ENCODER"];
00226 uint d = counts["NOT_ENCODER"];
00227 VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
00228 QString("Source ID %1 ").arg(sourceid) +
00229 QString("appears to be connected\n\t\t\tto %1 encoder%2, ")
00230 .arg(a).arg((1 == a) ? "":"s") +
00231 QString("and %1 non-encoder%2. ")
00232 .arg(d).arg((1 == d) ? "":"s") +
00233 QString("This is probably a bad idea."));
00234 }
00235
00236 if (scan_mismatch)
00237 {
00238 uint a = counts["SCAN"];
00239 uint d = counts["NO_SCAN"];
00240 VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
00241 QString("Source ID %1 ").arg(sourceid) +
00242 QString("appears to be connected\n\t\t\t"
00243 "to %1 scanable input%2, ")
00244 .arg(a).arg((1 == a) ? "":"s") +
00245 QString("and %1 non-scanable input%2. ")
00246 .arg(d).arg((1 == d) ? "":"s") +
00247 QString("This may be a problem."));
00248 }
00249
00250 if (fw_mismatch)
00251 {
00252 VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
00253 QString(
00254 "Source ID %1 appears to be connected\n\t\t\t"
00255 "to both firewire and non-firewire inputs. "
00256 "This is probably a bad idea.").arg(sourceid));
00257 }
00258
00259 if (!strict)
00260 return !tune_mismatch;
00261
00262 return !tune_mismatch && !enc_mismatch && !scan_mismatch && !fw_mismatch;
00263 }
00264
00265 bool SourceUtil::IsEncoder(uint sourceid, bool strict)
00266 {
00267 bool encoder = true;
00268
00269 QStringList types = get_cardtypes(sourceid);
00270 QStringList::const_iterator it = types.begin();
00271 for (; it != types.end(); ++it)
00272 encoder &= CardUtil::IsEncoder(*it);
00273
00274
00275 if (!types.empty())
00276 return encoder;
00277
00278
00279 MSqlQuery query(MSqlQuery::InitCon());
00280 query.prepare(
00281 "SELECT atsc_minor_chan, serviceid "
00282 "FROM channel "
00283 "WHERE sourceid = :SOURCEID");
00284 query.bindValue(":SOURCEID", sourceid);
00285
00286 bool has_any_chan = false;
00287 if (!query.exec() || !query.isActive())
00288 MythContext::DBError("SourceUtil::IsEncoder", query);
00289 else
00290 {
00291 while (query.next())
00292 {
00293 encoder &= !query.value(0).toInt() && !query.value(1).toInt();
00294 has_any_chan = true;
00295 }
00296 }
00297
00298 return (strict && !has_any_chan) ? false: encoder;
00299 }
00300
00301 bool SourceUtil::IsUnscanable(uint sourceid)
00302 {
00303 bool unscanable = true;
00304 QStringList types = get_cardtypes(sourceid);
00305 QStringList::const_iterator it = types.begin();
00306 for (; it != types.end(); ++it)
00307 unscanable &= CardUtil::IsUnscanable(*it);
00308
00309 return types.empty() || unscanable;
00310 }
00311
00312 bool SourceUtil::IsAnySourceScanable(void)
00313 {
00314 MSqlQuery query(MSqlQuery::InitCon());
00315 query.prepare("SELECT sourceid FROM videosource");
00316
00317 if (!query.exec() || !query.isActive())
00318 {
00319 MythContext::DBError("SourceUtil::IsAnySourceScanable", query);
00320 return false;
00321 }
00322
00323 while (query.next())
00324 {
00325 if (!IsUnscanable(query.value(0).toUInt()))
00326 return true;
00327 }
00328
00329 return false;
00330 }
00331
00332 bool SourceUtil::UpdateChannelsFromListings(uint sourceid, QString cardtype)
00333 {
00334 QString cmd = "mythfilldatabase --only-update-channels ";
00335 if (sourceid)
00336 cmd += QString("--sourceid %1 ").arg(sourceid);
00337 if (!cardtype.isEmpty())
00338 cmd += QString("--cardtype %1 ").arg(cardtype);
00339
00340 myth_system(cmd);
00341
00342 return true;
00343 }
00344
00345 bool SourceUtil::DeleteSource(uint sourceid)
00346 {
00347 MSqlQuery query(MSqlQuery::InitCon());
00348
00349
00350 query.prepare("DELETE FROM channel "
00351 "WHERE sourceid = :SOURCEID");
00352 query.bindValue(":SOURCEID", sourceid);
00353
00354 if (!query.exec() || !query.isActive())
00355 {
00356 MythContext::DBError("Deleting Channels", query);
00357 return false;
00358 }
00359
00360
00361 query.prepare("DELETE FROM cardinput "
00362 "WHERE sourceid = :SOURCEID");
00363 query.bindValue(":SOURCEID", sourceid);
00364
00365 if (!query.exec() || !query.isActive())
00366 {
00367 MythContext::DBError("Deleting cardinputs", query);
00368 return false;
00369 }
00370
00371
00372 query.prepare("DELETE FROM videosource "
00373 "WHERE sourceid = :SOURCEID");
00374 query.bindValue(":SOURCEID", sourceid);
00375
00376 if (!query.exec() || !query.isActive())
00377 {
00378 MythContext::DBError("Deleting VideoSource", query);
00379 return false;
00380 }
00381
00382
00383 CardUtil::DeleteOrphanInputs();
00384 CardUtil::UnlinkInputGroup(0,0);
00385
00386 return true;
00387 }
00388
00389 bool SourceUtil::DeleteAllSources(void)
00390 {
00391 MSqlQuery query(MSqlQuery::InitCon());
00392 return (query.exec("TRUNCATE TABLE channel") &&
00393 query.exec("TRUNCATE TABLE program") &&
00394 query.exec("TRUNCATE TABLE videosource") &&
00395 query.exec("TRUNCATE TABLE credits") &&
00396 query.exec("TRUNCATE TABLE programrating") &&
00397 query.exec("TRUNCATE TABLE programgenres") &&
00398 query.exec("TRUNCATE TABLE dtv_multiplex") &&
00399 query.exec("TRUNCATE TABLE inputgroup") &&
00400 query.exec("TRUNCATE TABLE diseqc_config") &&
00401 query.exec("TRUNCATE TABLE diseqc_tree") &&
00402 query.exec("TRUNCATE TABLE cardinput"));
00403 }