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);
114#
if QT_VERSION < QT_VERSION_CHECK(6,0,0)
115 channum.rightRef(2).startsWith(
"0")
117 QStringView(channum).right(2).startsWith(QStringLiteral(
"0"))
122 counts[(where < 0) ?
"" : QString(channum.at(where))]++;
125 uint max = counts[
"_"];
126 static const std::array<const QString,5> s_spacers {
"",
"-",
"#",
".",
"0" };
127 for (
const auto & spacer : s_spacers)
129 if (counts[spacer] > max)
131 max = counts[spacer];
150 "WHERE deleted IS NULL AND "
151 " sourceid = :SOURCEID");
154 return query.
value(0).toUInt();
164 "FROM dtv_multiplex "
165 "WHERE sourceid = :SOURCEID");
168 std::vector<uint> list;
176 list.push_back(query.
value(0).toUInt());
182 QString &grabber, QString &userid,
183 QString &passwd, QString &lineupid)
187 "SELECT xmltvgrabber, userid, password, lineupid "
189 "WHERE sourceid = :SOURCEID");
201 grabber = query.
value(0).toString();
202 userid = query.
value(1).toString();
203 passwd = query.
value(2).toString();
204 lineupid = query.
value(3).toString();
215 "SELECT cardtype, inputname "
217 "WHERE capturecard.sourceid = :SOURCEID");
229 QString inputtype = query.
value(0).toString().toUpper();
230 QString inputname = query.
value(1).toString().toUpper();
231 inputtype = ((inputtype ==
"DVB") && (!inputname.startsWith(
"DVB"))) ?
250 QMap<QString,uint> counts;
251 for (
const auto &
type : std::as_const(
types))
259 counts[
"ANALOG_TUNING"]++;
261 counts[
"DIGITAL_TUNING"]++;
263 counts[
"VIRTUAL_TUNING"]++;
267 ((counts[
"ANALOG_TUNING"] != 0U) && (counts[
"DIGITAL_TUNING"] != 0U)) ||
268 ((counts[
"VIRTUAL_TUNING"] != 0U) && (counts[
"DIGITAL_TUNING"] != 0U));
269 bool enc_mismatch = (counts[
"ENCODER"] != 0U) && (counts[
"NOT_ENCODER"] != 0U);
270 bool scan_mismatch = (counts[
"SCAN"] != 0U) && (counts[
"NO_SCAN"] != 0U);
274 uint a = counts[
"ANALOG_TUNERS"];
275 uint d = counts[
"DIGITAL_TUNERS"];
276 uint v = counts[
"VIRTUAL_TUNERS"];
277 LOG(VB_GENERAL, LOG_NOTICE,
278 QString(
"SourceUtil::IsProperlyConnected(): ") +
279 QString(
"Connected to %1 analog, %2 digital and %3 virtual "
280 "tuners\n\t\t\t").arg(a).arg(
d).arg(v) +
281 QString(
"Can not mix digital with other tuning information."));
286 uint a = counts[
"ENCODER"];
287 uint d = counts[
"NOT_ENCODER"];
288 LOG(VB_GENERAL, LOG_NOTICE,
289 QString(
"SourceUtil::IsProperlyConnected(): ") +
290 QString(
"Source ID %1 ").arg(sourceid) +
291 QString(
"appears to be connected\n\t\t\tto %1 encoder%2, ")
292 .arg(a).arg((1 == a) ?
"":
"s") +
293 QString(
"and %1 non-encoder%2. ")
294 .arg(
d).arg((1 ==
d) ?
"":
"s") +
295 QString(
"This is probably a bad idea."));
300 uint a = counts[
"SCAN"];
301 uint d = counts[
"NO_SCAN"];
302 LOG(VB_GENERAL, LOG_NOTICE,
303 QString(
"SourceUtil::IsProperlyConnected(): ") +
304 QString(
"Source ID %1 ").arg(sourceid) +
305 QString(
"appears to be connected\n\t\t\t"
306 "to %1 scanable input%2, ")
307 .arg(a).arg((1 == a) ?
"":
"s") +
308 QString(
"and %1 non-scanable input%2. ")
309 .arg(
d).arg((1 ==
d) ?
"":
"s") +
310 QString(
"This may be a problem."));
314 return !tune_mismatch;
316 return !tune_mismatch && !enc_mismatch && !scan_mismatch;
323 bool encoder = std::ranges::all_of(std::as_const(
types), isencoder);
332 "SELECT atsc_minor_chan, serviceid "
334 "WHERE deleted IS NULL AND "
335 " sourceid = :SOURCEID");
338 bool has_any_chan =
false;
347 encoder &= !query.
value(0).toBool() && !query.
value(1).toBool();
352 return (strict && !has_any_chan) ?
false: encoder;
361 return std::ranges::all_of(std::as_const(
types), unscannable);
367 auto ccpresent = [](
uint input)
370 return std::ranges::any_of(std::as_const(inputs), ccpresent);
376 query.
prepare(
"SELECT sourceid FROM videosource");
397 "SELECT sourceid FROM videosource WHERE sourceid = :SOURCEID");
416 args.append(
"--only-update-channels");
420 args.append(QString(
"--sourceid"));
421 args.append(QString::number(sourceid));
423 if (!inputtype.isEmpty())
425 args.append(QString(
"--cardtype"));
426 args.append(inputtype);
436 "mythfilldatabase --only-update-channels";
438 cmd += QString(
" --sourceid %1").arg(sourceid);
439 if (!inputtype.isEmpty())
440 cmd += QString(
" --cardtype %1").arg(inputtype);
450 const QString& grabber,
const QString& userid,
451 const QString& freqtable,
const QString& lineupid,
452 const QString& password,
bool useeit,
453 const QString& configpath,
int nitid,
459 query.
prepare(
"UPDATE videosource SET name = :NAME, xmltvgrabber = :XMLTVGRABBER, "
460 "userid = :USERID, freqtable = :FREQTABLE, lineupid = :LINEUPID,"
461 "password = :PASSWORD, useeit = :USEEIT, configpath = :CONFIGPATH, "
462 "dvb_nit_id = :NITID, bouquet_id = :BOUQUETID, region_id = :REGIONID, "
463 "scanfrequency = :SCANFREQUENCY, lcnoffset = :LCNOFFSET "
464 "WHERE sourceid = :SOURCEID");
467 query.
bindValue(
":XMLTVGRABBER", grabber);
469 query.
bindValue(
":FREQTABLE", freqtable);
473 query.
bindValue(
":CONFIGPATH", configpath.isEmpty() ?
nullptr : configpath);
475 query.
bindValue(
":BOUQUETID", bouquetid);
478 query.
bindValue(
":SCANFREQUENCY", scanfrequency);
479 query.
bindValue(
":LCNOFFSET", lcnoffset);
491 const QString& grabber,
const QString& userid,
492 const QString& freqtable,
const QString& lineupid,
493 const QString& password,
bool useeit,
494 const QString& configpath,
int nitid,
500 query.
prepare(
"INSERT INTO videosource (name,xmltvgrabber,userid,freqtable,lineupid,"
501 "password,useeit,configpath,dvb_nit_id,bouquet_id,region_id, scanfrequency,"
503 "VALUES (:NAME, :XMLTVGRABBER, :USERID, :FREQTABLE, :LINEUPID, :PASSWORD, "
504 ":USEEIT, :CONFIGPATH, :NITID, :BOUQUETID, :REGIONID, :SCANFREQUENCY, "
508 query.
bindValue(
":XMLTVGRABBER", grabber);
510 query.
bindValue(
":FREQTABLE", freqtable);
514 query.
bindValue(
":CONFIGPATH", configpath.isEmpty() ?
nullptr : configpath);
516 query.
bindValue(
":BOUQUETID", bouquetid);
518 query.
bindValue(
":SCANFREQUENCY", scanfrequency);
519 query.
bindValue(
":LCNOFFSET", lcnoffset);
527 query.
prepare(
"SELECT MAX(sourceid) FROM videosource");
538 sourceid = query.
value(0).toInt();
548 query.
prepare(
"DELETE FROM dtv_multiplex "
549 "WHERE sourceid = :SOURCEID");
559 query.
prepare(
"UPDATE channel "
560 "SET deleted = NOW(), mplexid = 0, sourceid = 0 "
561 "WHERE deleted IS NULL AND sourceid = :SOURCEID");
571 query.
prepare(
"UPDATE capturecard "
573 "WHERE sourceid = :SOURCEID");
586 query.
prepare(
"DELETE FROM videosource "
587 "WHERE sourceid = :SOURCEID");
604 query.
prepare(
"UPDATE capturecard "
613 query.
prepare(
"UPDATE channel "
614 "SET deleted = NOW(), mplexid = 0, sourceid = 0 "
615 "WHERE deleted IS NULL");
623 return (query.
exec(
"TRUNCATE TABLE program") &&
624 query.
exec(
"TRUNCATE TABLE videosource") &&
625 query.
exec(
"TRUNCATE TABLE credits") &&
626 query.
exec(
"TRUNCATE TABLE programrating") &&
627 query.
exec(
"TRUNCATE TABLE programgenres") &&
628 query.
exec(
"TRUNCATE TABLE dtv_multiplex") &&
629 query.
exec(
"TRUNCATE TABLE diseqc_config") &&
630 query.
exec(
"TRUNCATE TABLE diseqc_tree") &&
631 query.
exec(
"TRUNCATE TABLE eit_cache") &&
632 query.
exec(
"TRUNCATE TABLE channelgroup") &&
633 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)