7#include <QRegularExpression>
24 "SELECT mplexid, atsc_minor_chan, serviceid "
26 "WHERE deleted IS NULL AND "
27 " sourceid = :SOURCEID");
41 mplexid = (32767 == mplexid) ? 0 : mplexid;
43 if (mplexid && (
minor || prognum))
57 "WHERE sourceid = :SOURCEID");
70 return query.
value(0).toString();
80 "WHERE name = :NAME");
93 return query.
value(0).toUInt();
101 "WHERE deleted IS NULL AND "
102 " sourceid = :SOURCEID");
107 QMap<QString,uint> counts;
108 static const QRegularExpression kSeparatorRE { R
"((_|-|#|\.))" };
111 const QString channum = query.
value(0).toString();
112 const int where = channum.indexOf(kSeparatorRE);
113 if (channum.right(2).startsWith(
"0"))
116 counts[(where < 0) ?
"" : QString(channum.at(where))]++;
119 uint max = counts[
"_"];
120 static const std::array<const QString,5> s_spacers {
"",
"-",
"#",
".",
"0" };
121 for (
const auto & spacer : s_spacers)
123 if (counts[spacer] > max)
125 max = counts[spacer];
144 "WHERE deleted IS NULL AND "
145 " sourceid = :SOURCEID");
148 return query.
value(0).toUInt();
158 "FROM dtv_multiplex "
159 "WHERE sourceid = :SOURCEID");
162 std::vector<uint> list;
170 list.push_back(query.
value(0).toUInt());
176 QString &grabber, QString &userid,
177 QString &passwd, QString &lineupid)
181 "SELECT xmltvgrabber, userid, password, lineupid "
183 "WHERE sourceid = :SOURCEID");
195 grabber = query.
value(0).toString();
196 userid = query.
value(1).toString();
197 passwd = query.
value(2).toString();
198 lineupid = query.
value(3).toString();
209 "SELECT cardtype, inputname "
211 "WHERE capturecard.sourceid = :SOURCEID");
223 QString inputtype = query.
value(0).toString().toUpper();
224 QString inputname = query.
value(1).toString().toUpper();
225 inputtype = ((inputtype ==
"DVB") && (!inputname.startsWith(
"DVB"))) ?
244 QMap<QString,uint> counts;
245 for (
const auto &
type : std::as_const(
types))
253 counts[
"ANALOG_TUNING"]++;
255 counts[
"DIGITAL_TUNING"]++;
257 counts[
"VIRTUAL_TUNING"]++;
261 ((counts[
"ANALOG_TUNING"] != 0U) && (counts[
"DIGITAL_TUNING"] != 0U)) ||
262 ((counts[
"VIRTUAL_TUNING"] != 0U) && (counts[
"DIGITAL_TUNING"] != 0U));
263 bool enc_mismatch = (counts[
"ENCODER"] != 0U) && (counts[
"NOT_ENCODER"] != 0U);
264 bool scan_mismatch = (counts[
"SCAN"] != 0U) && (counts[
"NO_SCAN"] != 0U);
268 uint a = counts[
"ANALOG_TUNERS"];
269 uint d = counts[
"DIGITAL_TUNERS"];
270 uint v = counts[
"VIRTUAL_TUNERS"];
271 LOG(VB_GENERAL, LOG_NOTICE,
272 QString(
"SourceUtil::IsProperlyConnected(): ") +
273 QString(
"Connected to %1 analog, %2 digital and %3 virtual "
274 "tuners\n\t\t\t").arg(a).arg(
d).arg(v) +
275 QString(
"Can not mix digital with other tuning information."));
280 uint a = counts[
"ENCODER"];
281 uint d = counts[
"NOT_ENCODER"];
282 LOG(VB_GENERAL, LOG_NOTICE,
283 QString(
"SourceUtil::IsProperlyConnected(): ") +
284 QString(
"Source ID %1 ").arg(sourceid) +
285 QString(
"appears to be connected\n\t\t\tto %1 encoder%2, ")
286 .arg(a).arg((1 == a) ?
"":
"s") +
287 QString(
"and %1 non-encoder%2. ")
288 .arg(
d).arg((1 ==
d) ?
"":
"s") +
289 QString(
"This is probably a bad idea."));
294 uint a = counts[
"SCAN"];
295 uint d = counts[
"NO_SCAN"];
296 LOG(VB_GENERAL, LOG_NOTICE,
297 QString(
"SourceUtil::IsProperlyConnected(): ") +
298 QString(
"Source ID %1 ").arg(sourceid) +
299 QString(
"appears to be connected\n\t\t\t"
300 "to %1 scanable input%2, ")
301 .arg(a).arg((1 == a) ?
"":
"s") +
302 QString(
"and %1 non-scanable input%2. ")
303 .arg(
d).arg((1 ==
d) ?
"":
"s") +
304 QString(
"This may be a problem."));
308 return !tune_mismatch;
310 return !tune_mismatch && !enc_mismatch && !scan_mismatch;
317 bool encoder = std::ranges::all_of(std::as_const(
types), isencoder);
326 "SELECT atsc_minor_chan, serviceid "
328 "WHERE deleted IS NULL AND "
329 " sourceid = :SOURCEID");
332 bool has_any_chan =
false;
341 encoder &= !query.
value(0).toBool() && !query.
value(1).toBool();
346 return (strict && !has_any_chan) ?
false: encoder;
355 return std::ranges::all_of(std::as_const(
types), unscannable);
361 auto ccpresent = [](
uint input)
364 return std::ranges::any_of(std::as_const(inputs), ccpresent);
370 query.
prepare(
"SELECT sourceid FROM videosource");
391 "SELECT sourceid FROM videosource WHERE sourceid = :SOURCEID");
410 args.append(
"--only-update-channels");
414 args.append(QString(
"--sourceid"));
415 args.append(QString::number(sourceid));
417 if (!inputtype.isEmpty())
419 args.append(QString(
"--cardtype"));
420 args.append(inputtype);
430 "mythfilldatabase --only-update-channels";
432 cmd += QString(
" --sourceid %1").arg(sourceid);
433 if (!inputtype.isEmpty())
434 cmd += QString(
" --cardtype %1").arg(inputtype);
444 const QString& grabber,
const QString& userid,
445 const QString& freqtable,
const QString& lineupid,
446 const QString& password,
bool useeit,
447 const QString& configpath,
int nitid,
453 query.
prepare(
"UPDATE videosource SET name = :NAME, xmltvgrabber = :XMLTVGRABBER, "
454 "userid = :USERID, freqtable = :FREQTABLE, lineupid = :LINEUPID,"
455 "password = :PASSWORD, useeit = :USEEIT, configpath = :CONFIGPATH, "
456 "dvb_nit_id = :NITID, bouquet_id = :BOUQUETID, region_id = :REGIONID, "
457 "scanfrequency = :SCANFREQUENCY, lcnoffset = :LCNOFFSET "
458 "WHERE sourceid = :SOURCEID");
461 query.
bindValue(
":XMLTVGRABBER", grabber);
463 query.
bindValue(
":FREQTABLE", freqtable);
467 query.
bindValue(
":CONFIGPATH", configpath.isEmpty() ?
nullptr : configpath);
469 query.
bindValue(
":BOUQUETID", bouquetid);
472 query.
bindValue(
":SCANFREQUENCY", scanfrequency);
473 query.
bindValue(
":LCNOFFSET", lcnoffset);
485 const QString& grabber,
const QString& userid,
486 const QString& freqtable,
const QString& lineupid,
487 const QString& password,
bool useeit,
488 const QString& configpath,
int nitid,
494 query.
prepare(
"INSERT INTO videosource (name,xmltvgrabber,userid,freqtable,lineupid,"
495 "password,useeit,configpath,dvb_nit_id,bouquet_id,region_id, scanfrequency,"
497 "VALUES (:NAME, :XMLTVGRABBER, :USERID, :FREQTABLE, :LINEUPID, :PASSWORD, "
498 ":USEEIT, :CONFIGPATH, :NITID, :BOUQUETID, :REGIONID, :SCANFREQUENCY, "
502 query.
bindValue(
":XMLTVGRABBER", grabber);
504 query.
bindValue(
":FREQTABLE", freqtable);
508 query.
bindValue(
":CONFIGPATH", configpath.isEmpty() ?
nullptr : configpath);
510 query.
bindValue(
":BOUQUETID", bouquetid);
512 query.
bindValue(
":SCANFREQUENCY", scanfrequency);
513 query.
bindValue(
":LCNOFFSET", lcnoffset);
521 query.
prepare(
"SELECT MAX(sourceid) FROM videosource");
532 sourceid = query.
value(0).toInt();
542 query.
prepare(
"DELETE FROM dtv_multiplex "
543 "WHERE sourceid = :SOURCEID");
553 query.
prepare(
"UPDATE channel "
554 "SET deleted = NOW(), mplexid = 0, sourceid = 0 "
555 "WHERE deleted IS NULL AND sourceid = :SOURCEID");
565 query.
prepare(
"UPDATE capturecard "
567 "WHERE sourceid = :SOURCEID");
580 query.
prepare(
"DELETE FROM videosource "
581 "WHERE sourceid = :SOURCEID");
598 query.
prepare(
"UPDATE capturecard "
607 query.
prepare(
"UPDATE channel "
608 "SET deleted = NOW(), mplexid = 0, sourceid = 0 "
609 "WHERE deleted IS NULL");
617 return (query.
exec(
"TRUNCATE TABLE program") &&
618 query.
exec(
"TRUNCATE TABLE videosource") &&
619 query.
exec(
"TRUNCATE TABLE credits") &&
620 query.
exec(
"TRUNCATE TABLE programrating") &&
621 query.
exec(
"TRUNCATE TABLE programgenres") &&
622 query.
exec(
"TRUNCATE TABLE dtv_multiplex") &&
623 query.
exec(
"TRUNCATE TABLE diseqc_config") &&
624 query.
exec(
"TRUNCATE TABLE diseqc_tree") &&
625 query.
exec(
"TRUNCATE TABLE eit_cache") &&
626 query.
exec(
"TRUNCATE TABLE channelgroup") &&
627 query.
exec(
"TRUNCATE TABLE channelgroupnames"));
static bool IsUnscanable(const QString &rawtype)
static QString GetRawInputType(uint inputid)
static bool IsTuningAnalog(const QString &rawtype)
static bool IsTuningVirtual(const QString &rawtype)
static std::vector< uint > GetInputIDs(const QString &videodevice=QString(), const QString &rawtype=QString(), const QString &inputname=QString(), QString hostname=QString())
Returns all inputids of inputs that uses the specified videodevice if specified, and optionally rawty...
static bool IsEncoder(const QString &rawtype)
static bool IsTuningDigital(const QString &rawtype)
static bool IsCableCardPresent(uint inputid, const QString &inputType)
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool isActive(void) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
static void DBError(const QString &where, const MSqlQuery &query)
uint Wait(std::chrono::seconds timeout=0s)
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
static void DeleteScansFromSource(uint sourceid)
static uint GetConnectionCount(uint sourceid)
static bool HasDigitalChannel(uint sourceid)
static bool GetListingsLoginData(uint sourceid, QString &grabber, QString &userid, QString &passwd, QString &lineupid)
static QString GetChannelSeparator(uint sourceid)
static QString GetSourceName(uint sourceid)
static uint GetSourceID(const QString &name)
static QString GetChannelFormat(uint sourceid)
static bool DeleteSource(uint sourceid)
static bool DeleteAllSources(void)
static std::vector< uint > GetMplexIDs(uint sourceid)
static bool IsEncoder(uint sourceid, bool strict=false)
static bool IsSourceIDValid(uint sourceid)
static bool IsCableCardPresent(uint sourceid)
static uint GetChannelCount(uint sourceid)
static bool IsUnscanable(uint sourceid)
static bool IsAnySourceScanable(void)
static int CreateSource(const QString &sourcename, const QString &grabber, const QString &userid, const QString &freqtable, const QString &lineupid, const QString &password, bool useeit, const QString &configpath, int nitid, uint bouquetid, uint regionid, uint scanfrequency, uint lcnoffset)
static bool UpdateSource(uint sourceid, const QString &sourcename, const QString &grabber, const QString &userid, const QString &freqtable, const QString &lineupid, const QString &password, bool useeit, const QString &configpath, int nitid, uint bouquetid, uint regionid, uint scanfrequency, uint lcnoffset)
static bool UpdateChannelsFromListings(uint sourceid, const QString &inputtype=QString(), bool wait=false)
static bool IsProperlyConnected(uint sourceid, bool strict=false)
static const struct wl_interface * types[]
static const iso6937table * d
QString GetAppBinDir(void)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
@ kMSRunShell
run process through shell
@ kMSAutoCleanup
automatically delete if backgrounded
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
static QStringList get_inputtypes(uint sourceid)