11#include <QReadWriteLock>
12#include <QRegularExpression>
23#define LOC QString("ChanUtil: ")
40 "WHERE sourceid = :SOURCEID "
41 " AND sistandard = :SISTANDARD ";
43 if (sistandard.toLower() !=
"dvb")
45 qstr +=
"AND frequency = :FREQUENCY ";
49 qstr +=
"AND transportid = :TRANSPORTID ";
50 qstr +=
"AND networkid = :NETWORKID ";
51 qstr +=
"AND polarity = :POLARITY ";
58 query.
bindValue(
":SOURCEID", db_source_id);
59 query.
bindValue(
":SISTANDARD", sistandard);
61 if (sistandard.toLower() !=
"dvb")
63 query.
bindValue(
":FREQUENCY", QString::number(frequency));
67 query.
bindValue(
":TRANSPORTID", transport_id);
68 query.
bindValue(
":NETWORKID", network_id);
79 return query.
value(0).toUInt();
85 int db_source_id,
const QString& sistandard,
86 uint64_t frequency,
const QString& modulation,
88 int transport_id,
int network_id,
89 int symbol_rate,
signed char bandwidth,
90 signed char polarity,
signed char inversion,
91 signed char trans_mode,
92 const QString& inner_FEC,
const QString& constellation,
93 signed char hierarchy,
const QString& hp_code_rate,
94 const QString& lp_code_rate,
const QString& guard_interval,
95 const QString& mod_sys,
const QString& rolloff)
101 db_source_id, sistandard, frequency,
103 transport_id, network_id, polarity);
105 LOG(VB_CHANSCAN, LOG_INFO,
"insert_dtv_multiplex(" +
106 QString(
"dbid:%1 std:'%2' ").arg(db_source_id).arg(sistandard) +
107 QString(
"freq:%1 mod:%2 ").arg(frequency).arg(modulation) +
108 QString(
"tid:%1 nid:%2 ").arg(transport_id).arg(network_id) +
109 QString(
"pol:%1 msys:%2 ...)").arg(QChar(
static_cast<uint16_t>(polarity))).arg(mod_sys) +
110 QString(
"mplexid:%1").arg(mplex));
112 bool isDVB = (sistandard.toLower() ==
"dvb");
115 "UPDATE dtv_multiplex "
116 "SET frequency = :FREQUENCY1, ";
118 updateStr += (!modulation.isNull()) ?
119 "modulation = :MODULATION, " :
"";
120 updateStr += (symbol_rate >= 0) ?
121 "symbolrate = :SYMBOLRATE, " :
"";
122 updateStr += (bandwidth >= 0) ?
123 "bandwidth = :BANDWIDTH, " :
"";
124 updateStr += (polarity >= 0) ?
125 "polarity = :POLARITY, " :
"";
126 updateStr += (inversion >= 0) ?
127 "inversion = :INVERSION, " :
"";
128 updateStr += (trans_mode >= 0) ?
129 "transmission_mode= :TRANS_MODE, " :
"";
130 updateStr += (!inner_FEC.isNull()) ?
131 "fec = :INNER_FEC, " :
"";
132 updateStr += (!constellation.isNull()) ?
133 "constellation = :CONSTELLATION, " :
"";
134 updateStr += (hierarchy >= 0) ?
135 "hierarchy = :HIERARCHY, " :
"";
136 updateStr += (!hp_code_rate.isNull()) ?
137 "hp_code_rate = :HP_CODE_RATE, " :
"";
138 updateStr += (!lp_code_rate.isNull()) ?
139 "lp_code_rate = :LP_CODE_RATE, " :
"";
140 updateStr += (!guard_interval.isNull()) ?
141 "guard_interval = :GUARD_INTERVAL, " :
"";
142 updateStr += (!mod_sys.isNull()) ?
143 "mod_sys = :MOD_SYS, " :
"";
144 updateStr += (symbol_rate >= 0) ?
145 "rolloff = :ROLLOFF, " :
"";
146 updateStr += (transport_id && !isDVB) ?
147 "transportid = :TRANSPORTID, " :
"";
149 updateStr = updateStr.left(updateStr.length()-2) +
" ";
152 "WHERE sourceid = :SOURCEID AND "
153 " sistandard = :SISTANDARD AND ";
156 " polarity = :WHEREPOLARITY AND "
157 " transportid = :TRANSPORTID AND networkid = :NETWORKID " :
158 " frequency = :FREQUENCY2 ";
161 "INSERT INTO dtv_multiplex "
162 " (sourceid, sistandard, frequency, ";
164 insertStr += (!modulation.isNull()) ?
"modulation, " :
"";
165 insertStr += (transport_id || isDVB) ?
"transportid, " :
"";
166 insertStr += isDVB ?
"networkid, " :
"";
167 insertStr += (symbol_rate >= 0) ?
"symbolrate, " :
"";
168 insertStr += (bandwidth >= 0) ?
"bandwidth, " :
"";
169 insertStr += (polarity >= 0) ?
"polarity, " :
"";
170 insertStr += (inversion >= 0) ?
"inversion, " :
"";
171 insertStr += (trans_mode >= 0) ?
"transmission_mode, " :
"";
172 insertStr += (!inner_FEC.isNull()) ?
"fec, " :
"";
173 insertStr += (!constellation.isNull()) ?
"constellation, " :
"";
174 insertStr += (hierarchy >= 0) ?
"hierarchy, " :
"";
175 insertStr += (!hp_code_rate.isNull()) ?
"hp_code_rate, " :
"";
176 insertStr += (!lp_code_rate.isNull()) ?
"lp_code_rate, " :
"";
177 insertStr += (!guard_interval.isNull()) ?
"guard_interval, " :
"";
178 insertStr += (!mod_sys.isNull()) ?
"mod_sys, " :
"";
179 insertStr += (!rolloff.isNull()) ?
"rolloff, " :
"";
180 insertStr = insertStr.left(insertStr.length()-2) +
") ";
184 " (:SOURCEID, :SISTANDARD, :FREQUENCY1, ";
185 insertStr += (!modulation.isNull()) ?
":MODULATION, " :
"";
186 insertStr += (transport_id || isDVB) ?
":TRANSPORTID, " :
"";
187 insertStr += isDVB ?
":NETWORKID, " :
"";
188 insertStr += (symbol_rate >= 0) ?
":SYMBOLRATE, " :
"";
189 insertStr += (bandwidth >= 0) ?
":BANDWIDTH, " :
"";
190 insertStr += (polarity >= 0) ?
":POLARITY, " :
"";
191 insertStr += (inversion >= 0) ?
":INVERSION, " :
"";
192 insertStr += (trans_mode >= 0) ?
":TRANS_MODE, " :
"";
193 insertStr += (!inner_FEC.isNull()) ?
":INNER_FEC, " :
"";
194 insertStr += (!constellation.isNull()) ?
":CONSTELLATION, " :
"";
195 insertStr += (hierarchy >= 0) ?
":HIERARCHY, " :
"";
196 insertStr += (!hp_code_rate.isNull()) ?
":HP_CODE_RATE, " :
"";
197 insertStr += (!lp_code_rate.isNull()) ?
":LP_CODE_RATE, " :
"";
198 insertStr += (!guard_interval.isNull()) ?
":GUARD_INTERVAL, " :
"";
199 insertStr += (!mod_sys.isNull()) ?
":MOD_SYS, " :
"";
200 insertStr += (!rolloff.isNull()) ?
":ROLLOFF, " :
"";
201 insertStr = insertStr.left(insertStr.length()-2) +
");";
203 query.
prepare(mplex ? updateStr : insertStr);
205 query.
bindValue(
":SOURCEID", db_source_id);
206 query.
bindValue(
":SISTANDARD", sistandard);
207 query.
bindValue(
":FREQUENCY1", QString::number(frequency));
213 query.
bindValue(
":TRANSPORTID", transport_id);
214 query.
bindValue(
":NETWORKID", network_id);
219 query.
bindValue(
":FREQUENCY2", QString::number(frequency));
221 query.
bindValue(
":TRANSPORTID", transport_id);
226 if (transport_id || isDVB)
227 query.
bindValue(
":TRANSPORTID", transport_id);
229 query.
bindValue(
":NETWORKID", network_id);
232 if (!modulation.isNull())
233 query.
bindValue(
":MODULATION", modulation);
235 if (symbol_rate >= 0)
236 query.
bindValue(
":SYMBOLRATE", symbol_rate);
238 query.
bindValue(
":BANDWIDTH", QString(
"%1").arg((
char)bandwidth));
240 query.
bindValue(
":POLARITY", QString(
"%1").arg((
char)polarity));
242 query.
bindValue(
":INVERSION", QString(
"%1").arg((
char)inversion));
244 query.
bindValue(
":TRANS_MODE", QString(
"%1").arg((
char)trans_mode));
246 if (!inner_FEC.isNull())
247 query.
bindValue(
":INNER_FEC", inner_FEC);
248 if (!constellation.isNull())
249 query.
bindValue(
":CONSTELLATION", constellation);
251 query.
bindValue(
":HIERARCHY", QString(
"%1").arg((
char)hierarchy));
252 if (!hp_code_rate.isNull())
253 query.
bindValue(
":HP_CODE_RATE", hp_code_rate);
254 if (!lp_code_rate.isNull())
255 query.
bindValue(
":LP_CODE_RATE", lp_code_rate);
256 if (!guard_interval.isNull())
257 query.
bindValue(
":GUARD_INTERVAL",guard_interval);
258 if (!mod_sys.isNull())
260 if (!rolloff.isNull())
273 db_source_id, sistandard, frequency,
275 transport_id, network_id, polarity);
277 LOG(VB_CHANSCAN, LOG_INFO, QString(
"insert_dtv_multiplex -- ") +
278 QString(
"inserted mplexid %1").arg(mplex));
302 uint dummy_netid = 0;
304 dummy_tsid, dummy_netid, dummy_sistd);
308 (
int)sourceid,
"dvb",
311 (
int)tsid, (
int)netid,
318 QString(), QString());
321 muxes.push_back(mux);
345 QString(), QString(),
349 muxes.push_back(mux);
369 QString(), QString(),
370 QString(), QString());
373 muxes.push_back(mux);
378 uint64_t frequency,
const QString& modulation,
379 int transport_id,
int network_id)
382 sourceid, sistandard,
383 frequency, modulation,
384 transport_id, network_id,
388 QString(), QString(),
390 QString(), QString(),
391 QString(), QString());
395 int sourceid,
const QString& sistandard,
396 uint64_t
freq,
const QString& modulation,
398 int transport_id,
int network_id,
399 int symbol_rate,
signed char bandwidth,
400 signed char polarity,
signed char inversion,
401 signed char trans_mode,
402 const QString& inner_FEC,
const QString& constellation,
403 signed char hierarchy,
const QString& hp_code_rate,
404 const QString& lp_code_rate,
const QString& guard_interval,
405 const QString& mod_sys,
const QString& rolloff)
408 sourceid, sistandard,
411 transport_id, network_id,
412 symbol_rate, bandwidth,
415 inner_FEC, constellation,
416 hierarchy, hp_code_rate,
417 lp_code_rate, guard_interval,
422 int transport_id,
int network_id)
428 transport_id, network_id,
445 std::vector<uint> muxes;
458 for (
const auto *j : list)
474 "WHERE deleted IS NULL AND "
475 " sourceid = :SOURCEID AND "
476 " channum = :CHANNUM");
483 else if (query.
next())
484 return query.
value(0).toInt();
495 "FROM dtv_multiplex "
496 "WHERE sourceid = :SOURCEID AND "
497 " frequency = :FREQUENCY");
500 query.
bindValue(
":FREQUENCY", QString::number(frequency));
509 return query.
value(0).toInt();
521 "FROM dtv_multiplex "
522 "WHERE networkid = :NETWORKID AND "
523 " transportid = :TRANSPORTID AND "
524 " frequency = :FREQUENCY AND "
525 " sourceid = :SOURCEID");
528 query.
bindValue(
":NETWORKID", network_id);
529 query.
bindValue(
":TRANSPORTID", transport_id);
530 query.
bindValue(
":FREQUENCY", QString::number(frequency));
539 return query.
value(0).toInt();
551 "FROM dtv_multiplex "
552 "WHERE networkid = :NETWORKID AND "
553 " transportid = :TRANSPORTID AND "
554 " sourceid = :SOURCEID");
557 query.
bindValue(
":NETWORKID", network_id);
558 query.
bindValue(
":TRANSPORTID", transport_id);
567 return query.
value(0).toInt();
579 "WHERE chanid = :CHANID");
585 else if (query.
next())
586 return query.
value(0).toInt();
619 LOG(VB_CHANSCAN, LOG_INFO,
620 QString(
"GetBetterMplexID(mplexId %1, tId %2, netId %3)")
621 .arg(current_mplexid).arg(transport_id).arg(network_id));
624 int q_transportid = 0;
627 query.
prepare(
"SELECT networkid, transportid "
628 "FROM dtv_multiplex "
629 "WHERE mplexid = :MPLEX_ID");
631 query.
bindValue(
":MPLEX_ID", current_mplexid);
637 else if (query.
next())
639 q_networkid = query.
value(0).toInt();
640 q_transportid = query.
value(1).toInt();
644 if ((q_networkid == network_id) && (q_transportid == transport_id))
646 LOG(VB_CHANSCAN, LOG_INFO,
647 QString(
"GetBetterMplexID(): Returning perfect match %1")
648 .arg(current_mplexid));
649 return current_mplexid;
653 if (!q_networkid && !q_transportid)
655 int qsize = query.
size();
656 query.
prepare(
"UPDATE dtv_multiplex "
657 "SET networkid = :NETWORK_ID, "
658 " transportid = :TRANSPORT_ID "
659 "WHERE mplexid = :MPLEX_ID");
661 query.
bindValue(
":NETWORK_ID", network_id);
662 query.
bindValue(
":TRANSPORT_ID", transport_id);
663 query.
bindValue(
":MPLEX_ID", current_mplexid);
668 LOG(VB_CHANSCAN, LOG_INFO,
669 QString(
"GetBetterMplexID(): net id and transport id "
670 "are null, qsize(%1), Returning %2")
671 .arg(qsize).arg(current_mplexid));
672 return current_mplexid;
676 std::array<QString,2> theQueries
678 QString(
"SELECT a.mplexid "
679 "FROM dtv_multiplex a, dtv_multiplex b "
680 "WHERE a.networkid = :NETWORK_ID AND "
681 " a.transportid = :TRANSPORT_ID AND "
682 " a.sourceid = b.sourceid AND "
683 " b.mplexid = :MPLEX_ID"),
685 QString(
"SELECT mplexid "
686 "FROM dtv_multiplex "
687 "WHERE networkid = :NETWORK_ID AND "
688 " transportid = :TRANSPORT_ID"),
691 for (
uint i=0; i<2; i++)
695 query.
bindValue(
":NETWORK_ID", network_id);
696 query.
bindValue(
":TRANSPORT_ID", transport_id);
698 query.
bindValue(
":MPLEX_ID", current_mplexid);
703 if (query.
size() == 1 && query.
next())
705 LOG(VB_CHANSCAN, LOG_INFO,
706 QString(
"GetBetterMplexID(): query#%1 qsize(%2) "
708 .arg(i).arg(query.
size()).arg(current_mplexid));
709 return query.
value(0).toInt();
714 int ret = (i==0) ? current_mplexid : query.
value(0).toInt();
715 LOG(VB_CHANSCAN, LOG_INFO,
716 QString(
"GetBetterMplexID(): query#%1 qsize(%2) "
718 .arg(i).arg(query.
size()).arg(ret));
724 LOG(VB_CHANSCAN, LOG_INFO,
"GetBetterMplexID(): Returning -1");
731 uint &dvb_transportid,
735 if (!mplexid || (mplexid == 32767))
740 "SELECT transportid, networkid, frequency, modulation, sistandard "
741 "FROM dtv_multiplex "
742 "WHERE mplexid = :MPLEXID");
754 dvb_transportid = query.
value(0).toUInt();
755 dvb_networkid = query.
value(1).toUInt();
756 frequency = query.
value(2).toULongLong();
757 modulation = query.
value(3).toString();
758 si_std = query.
value(4).toString();
769 query.
prepare(QString(
"SELECT %1 FROM channel "
770 "WHERE chanid = :CHANID").arg(field));
781 return query.
value(0).toString();
798 query.
prepare(
"SELECT sourceid "
799 "FROM dtv_multiplex "
800 "WHERE mplexid = :MPLEXID");
809 return query.
value(0).toInt();
821 "WHERE chanid = :CHANID");
826 else if (query.
next())
827 return query.
value(0).toUInt();
835 query.
prepare(
"SELECT cardtype "
836 "FROM capturecard, channel "
837 "WHERE channel.chanid = :CHANID AND "
838 " channel.sourceid = capturecard.sourceid "
839 "GROUP BY cardtype");
849 list.push_back(query.
value(0).toString());
869 query.
prepare(
"SELECT pid, tableid FROM pidcache "
870 "WHERE chanid = :CHANID");
882 int pid = query.
value(0).toInt();
883 int tid = query.
value(1).toInt();
884 if ((pid >= 0) && (tid >= 0))
885 pid_cache.emplace_back(pid, tid);
907 query.
prepare(
"DELETE FROM pidcache WHERE chanid = :CHANID");
912 "DELETE FROM pidcache "
913 "WHERE chanid = :CHANID AND tableid < 65536");
931 "INSERT INTO pidcache "
932 "SET chanid = :CHANID, pid = :PID, tableid = :TABLEID");
936 auto ito = old_cache.begin();
937 for (
const auto& itn : pid_cache)
940 for (; ito != old_cache.end() && ito->GetPID() < itn.GetPID(); ++ito);
943 if (ito != old_cache.end() && ito->GetPID() == itn.GetPID())
947 query.
bindValue(
":TABLEID", itn.GetComposite());
961 const QString &channum)
971 "WHERE deleted IS NULL AND "
972 " channum = :CHANNUM AND "
973 " sourceid = :SOURCEID")
974 .arg(channel_field));
981 else if (query.
next())
982 retval = query.
value(0).toString();
989 const QString &channum)
995 retval = val.toInt();
997 return retval ? retval : -1;
1002 if (channel_name.isEmpty())
1006 query.
prepare(
"SELECT channum FROM channel WHERE sourceid = :SOURCEID "
1008 "AND deleted IS NULL;" );
1010 query.
bindValue(
":NAME", channel_name.left(64));
1020 return query.
value(0).toString();
1024 const QString &new_channum,
1025 const QString &old_channum)
1027 if (new_channum.isEmpty() || old_channum.isEmpty())
1030 if (new_channum == old_channum)
1041 LOG(VB_CHANNEL, LOG_INFO, QString(
"IsOnSameMultiplex? %1==%2 -> %3")
1042 .arg(old_mplexid).arg(new_mplexid)
1043 .arg(old_mplexid == new_mplexid));
1045 return old_mplexid == new_mplexid;
1055 QStringList reclist;
1062 "SELECT capturecard.cardid "
1064 "LEFT JOIN capturecard ON channel.sourceid = capturecard.sourceid "
1065 "WHERE channel.chanid = :CHANID AND "
1066 " capturecard.livetvorder > 0 "
1067 "ORDER BY capturecard.livetvorder, capturecard.cardid");
1076 while (query.
next())
1077 reclist << query.
value(0).toString();
1089 QStringList reclist;
1096 "SELECT capturecard.cardid "
1098 "LEFT JOIN capturecard ON channel.sourceid = capturecard.sourceid "
1099 "WHERE channel.deleted IS NULL AND "
1100 " channel.channum = :CHANNUM AND "
1101 " capturecard.livetvorder > 0 "
1102 "ORDER BY capturecard.livetvorder, capturecard.cardid");
1111 while (query.
next())
1112 reclist << query.
value(0).toString();
1125 uint chanid,
const QString &channum)
1129 if (!channum.isEmpty())
1138 std::vector<uint> conflicting;
1143 "SELECT chanid from channel "
1144 "WHERE deleted IS NULL AND "
1145 " sourceid = :SOURCEID AND "
1146 " channum = :CHANNUM");
1152 "SELECT chanid from channel "
1153 "WHERE deleted IS NULL AND "
1154 " channum = :CHANNUM");
1161 conflicting.push_back(0);
1165 while (query.
next())
1166 conflicting.push_back(query.
value(0).toUInt());
1172 const QString& value,
1174 const QString &channum)
1179 QString(
"UPDATE channel SET channel.%1=:VALUE "
1180 "WHERE channel.channum = :CHANNUM AND "
1181 " channel.sourceid = :SOURCEID").arg(field_name));
1187 return query.
exec();
1191 const QString& value,
1197 QString(
"UPDATE channel SET channel.%1=:VALUE "
1198 "WHERE channel.chanid = :CHANID").arg(field_name));
1203 return query.
exec();
1224 "SELECT chanid, m.default_authority "
1226 "LEFT JOIN dtv_multiplex m "
1227 "ON (c.mplexid = m.mplexid) "
1228 "WHERE deleted IS NULL");
1231 while (query.
next())
1233 if (!query.
value(1).toString().isEmpty())
1236 query.
value(1).toString();
1247 "SELECT chanid, default_authority "
1249 "WHERE deleted IS NULL");
1252 while (query.
next())
1254 if (!query.
value(1).toString().isEmpty())
1257 query.
value(1).toString();
1281 static QReadWriteLock s_channelIconMapLock;
1282 static QHash<uint,QString> s_channelIconMap;
1283 static bool s_runInit =
true;
1285 s_channelIconMapLock.lockForRead();
1287 QString ret(s_channelIconMap.value(chanid,
"_cold_"));
1289 s_channelIconMapLock.unlock();
1291 if (ret !=
"_cold_")
1294 s_channelIconMapLock.lockForWrite();
1297 QString iconquery =
"SELECT chanid, icon FROM channel";
1300 iconquery +=
" WHERE visible > 0";
1302 iconquery +=
" WHERE chanid = :CHANID";
1313 s_channelIconMap.reserve(query.
size());
1314 while (query.
next())
1316 s_channelIconMap[query.
value(0).toUInt()] =
1317 query.
value(1).toString();
1323 s_channelIconMap[chanid] = (query.
next()) ?
1324 query.
value(1).toString() :
"";
1332 ret = s_channelIconMap.value(chanid,
"");
1334 s_channelIconMapLock.unlock();
1341 return tr(
"UNKNOWN",
"Synthesized callsign");
1345 int major_channel,
int minor_channel,
1351 query.
prepare(
"SELECT sourceid "
1352 "FROM dtv_multiplex "
1353 "WHERE mplexid = :MPLEXID");
1363 int source_id = query.
value(0).toInt();
1366 query.
prepare(
"SELECT chanid FROM channel,dtv_multiplex "
1367 "WHERE channel.deleted IS NULL AND "
1368 " channel.sourceid = :SOURCEID AND "
1369 " atsc_major_chan = :MAJORCHAN AND "
1370 " atsc_minor_chan = :MINORCHAN AND "
1371 " dtv_multiplex.transportid = :TRANSPORTID AND "
1372 " dtv_multiplex.mplexid = :MPLEXID AND "
1373 " dtv_multiplex.sourceid = channel.sourceid AND "
1374 " dtv_multiplex.mplexid = channel.mplexid");
1376 query.
bindValue(
":SOURCEID", source_id);
1377 query.
bindValue(
":MAJORCHAN", major_channel);
1378 query.
bindValue(
":MINORCHAN", minor_channel);
1379 query.
bindValue(
":TRANSPORTID", service_transport_id);
1383 return query.
value(0).toInt();
1387 query.
prepare(
"SELECT chanid FROM channel "
1388 "WHERE deleted IS NULL AND "
1389 "sourceid = :SOURCEID AND "
1390 "atsc_major_chan = :MAJORCHAN AND "
1391 "atsc_minor_chan = :MINORCHAN");
1393 query.
bindValue(
":SOURCEID", source_id);
1394 query.
bindValue(
":MAJORCHAN", major_channel);
1395 query.
bindValue(
":MINORCHAN", minor_channel);
1398 return query.
value(0).toInt();
1401 query.
prepare(
"SELECT chanid FROM channel "
1402 "WHERE deleted IS NULL AND "
1403 "sourceid = :SOURCEID AND "
1404 "serviceID = :SERVICEID AND "
1405 "mplexid = :MPLEXID");
1407 query.
bindValue(
":SOURCEID", source_id);
1408 query.
bindValue(
":SERVICEID", program_number);
1412 return query.
value(0).toInt();
1420 query.
prepare(
"SELECT chanid "
1422 "WHERE deleted IS NULL AND "
1423 " sourceid = :SOURCEID AND "
1424 " freqid = :FREQID");
1431 else if (query.
next())
1432 return query.
value(0).toUInt();
1440 QString qstr =
"SELECT MAX(chanid) FROM channel ";
1441 qstr += sourceid ?
"WHERE sourceid = :SOURCEID" :
"";
1451 else if (!query.
next())
1452 LOG(VB_GENERAL, LOG_ERR,
"Error getting chanid for new channel.");
1454 return query.
value(0).toUInt();
1465 "WHERE chanid = :CHANID");
1470 else if (query.
size() == 0)
1483 static const QRegularExpression kNonDigitRE { R
"(\D)" };
1485 int chansep = chan_num.indexOf(kNonDigitRE);
1489 (sourceid * 10000) +
1490 (chan_num.left(chansep).toInt() * 100) +
1491 chan_num.right(chan_num.length() - chansep - 1).toInt();
1495 chanid = (sourceid * 10000) + chan_num.toInt();
1502 chanid = std::max(
get_max_chanid(sourceid) + 1, sourceid * 10000);
1519 uint new_channel_id,
1520 const QString &callsign,
1521 const QString &service_name,
1522 const QString &chan_num,
1524 uint atsc_major_channel,
1525 uint atsc_minor_channel,
1526 bool use_on_air_guide,
1528 const QString &freqid,
1529 const QString& icon,
1531 const QString& xmltvid,
1532 const QString& default_authority,
1540 QString chanNum = (chan_num ==
"-1") ?
1541 QString::number(service_id) : chan_num;
1544 "INSERT INTO channel "
1545 " (chanid, channum, sourceid, "
1546 " callsign, name, serviceid, ";
1547 qstr += (db_mplexid > 0) ?
"mplexid, " :
"";
1548 qstr += (!freqid.isEmpty()) ?
"freqid, " :
"";
1550 " atsc_major_chan, atsc_minor_chan, "
1551 " useonairguide, visible, tvformat, "
1552 " icon, xmltvid, default_authority, "
1553 " service_type, recpriority, tmoffset, "
1556 " (:CHANID, :CHANNUM, :SOURCEID, "
1557 " :CALLSIGN, :NAME, :SERVICEID, ";
1558 qstr += (db_mplexid > 0) ?
":MPLEXID, " :
"";
1559 qstr += (!freqid.isEmpty()) ?
":FREQID, " :
"";
1561 " :MAJORCHAN, :MINORCHAN, "
1562 " :USEOAG, :VISIBLE, :TVFORMAT, "
1563 " :ICON, :XMLTVID, :AUTHORITY, "
1564 " :SERVICETYPE, :RECPRIORITY, :TMOFFSET, "
1569 query.
bindValue (
":CHANID", new_channel_id);
1571 query.
bindValue (
":SOURCEID", db_sourceid);
1576 query.
bindValue(
":MPLEXID", db_mplexid);
1578 query.
bindValue(
":SERVICEID", service_id);
1579 query.
bindValue(
":MAJORCHAN", atsc_major_channel);
1580 query.
bindValue(
":MINORCHAN", atsc_minor_channel);
1581 query.
bindValue(
":USEOAG", use_on_air_guide);
1584 if (!freqid.isEmpty())
1587 QString tvformat = (atsc_minor_channel > 0) ?
"ATSC" : std::move(format);
1592 query.
bindValue (
":SERVICETYPE", service_type);
1593 query.
bindValue (
":RECPRIORITY", recpriority);
1594 query.
bindValue (
":TMOFFSET", tmOffset);
1595 query.
bindValue (
":COMMMETHOD", commMethod);
1608 const QString &callsign,
1609 const QString &service_name,
1610 const QString &chan_num,
1612 uint atsc_major_channel,
1613 uint atsc_minor_channel,
1614 bool use_on_air_guide,
1616 const QString& freqid,
1617 const QString& icon,
1619 const QString& xmltvid,
1620 const QString& default_authority,
1629 QString tvformat = (atsc_minor_channel > 0) ?
"ATSC" : std::move(format);
1630 bool set_channum = !chan_num.isEmpty() && chan_num !=
"-1";
1631 QString qstr = QString(
1633 "SET %1 %2 %3 %4 %5 %6 %7 %8 %9 "
1634 " mplexid = :MPLEXID, serviceid = :SERVICEID, "
1635 " atsc_major_chan = :MAJORCHAN, atsc_minor_chan = :MINORCHAN, "
1636 " callsign = :CALLSIGN, name = :NAME, "
1637 " sourceid = :SOURCEID, useonairguide = :USEOAG, "
1638 " visible = :VISIBLE, service_type = :SERVICETYPE "
1639 "WHERE chanid=:CHANID")
1640 .arg((!set_channum) ?
"" :
"channum = :CHANNUM, ",
1641 (freqid.isEmpty()) ?
"" :
"freqid = :FREQID, ",
1642 (icon.isEmpty()) ?
"" :
"icon = :ICON, ",
1643 (tvformat.isEmpty()) ?
"" :
"tvformat = :TVFORMAT, ",
1644 (xmltvid.isEmpty()) ?
"" :
"xmltvid = :XMLTVID, ",
1645 (default_authority.isEmpty()) ?
1646 "" :
"default_authority = :AUTHORITY,",
1647 (recpriority == INT_MIN) ?
"" :
"recpriority = :RECPRIORITY, ",
1648 (tmOffset == INT_MIN) ?
"" :
"tmOffset = :TMOFFSET, ",
1649 (commMethod == INT_MIN) ?
"" :
"commmethod = :COMMMETHOD, ");
1659 query.
bindValue (
":SOURCEID", source_id);
1663 query.
bindValue(
":MPLEXID", db_mplexid);
1664 query.
bindValue(
":SERVICEID", service_id);
1665 query.
bindValue(
":MAJORCHAN", atsc_major_channel);
1666 query.
bindValue(
":MINORCHAN", atsc_minor_channel);
1667 query.
bindValue(
":USEOAG", use_on_air_guide);
1669 query.
bindValue(
":SERVICETYPE", service_type);
1671 if (!freqid.isNull())
1673 if (!tvformat.isNull())
1677 if (!xmltvid.isNull())
1679 if (!default_authority.isNull())
1680 query.
bindValue(
":AUTHORITY", default_authority);
1681 if (recpriority != INT_MIN)
1682 query.
bindValue(
":RECPRIORITY", recpriority);
1683 if (tmOffset != INT_MIN)
1685 if (commMethod != INT_MIN)
1686 query.
bindValue(
":COMMMETHOD", commMethod);
1702 "WHERE chanid = :ID");
1713 QString channum = query.
value(0).toString();
1715 if (!channum.isEmpty())
1726 "SELECT xmltvid, useonairguide, visible "
1728 "WHERE chanid = :ID");
1739 QString xmltvid = query.
value(0).toString();
1740 bool useeit = query.
value(1).toBool();
1744 if (!xmltvid.isEmpty())
1748 LOG(VB_GENERAL, LOG_ERR,
1749 "Using EIT and xmltv for the same channel "
1750 "is an unsupported configuration.");
1767 "DELETE FROM iptv_channel "
1768 "WHERE chanid=:CHANID");
1778 "INSERT INTO iptv_channel (chanid, url, type, bitrate) "
1779 "VALUES (:CHANID, :URL, :TYPE, :BITRATE)");
1824 "SET deleted = NOW() "
1825 "WHERE chanid = :ID");
1842 "SET visible = :VISIBLE "
1843 "WHERE chanid = :ID");
1860 query.
prepare(
"UPDATE dtv_multiplex "
1861 "SET serviceversion = :VERSION "
1862 "WHERE mplexid = :MPLEXID");
1879 query.
prepare(
"SELECT serviceversion "
1880 "FROM dtv_multiplex "
1881 "WHERE mplexid = :MPLEXID");
1892 return query.
value(0).toInt();
1904 "SELECT atsc_major_chan, atsc_minor_chan "
1906 "WHERE deleted IS NULL AND "
1907 " channum = :CHANNUM AND "
1908 " sourceid = :SOURCEID");
1917 else if (query.
next())
1919 major = query.
value(0).toUInt();
1929 uint &chanid,
const QString &channum,
1930 QString &name, QString &callsign,
1931 QString &tvformat, QString &modulation,
1932 QString &freqtable, QString &freqid,
1933 int &finetune, uint64_t &frequency,
1934 QString &dtv_si_std,
int &mpeg_prog_num,
1935 uint &atsc_major,
uint &atsc_minor,
1936 uint &dvb_transportid,
uint &dvb_networkid,
1949 atsc_major = atsc_minor = mplexid = 0;
1950 dvb_networkid = dvb_transportid = 0;
1956 "SELECT finetune, freqid, tvformat, freqtable, "
1957 " commmethod, mplexid, "
1958 " atsc_major_chan, atsc_minor_chan, serviceid, "
1959 " chanid, channel.name, callsign, visible "
1960 "FROM channel, videosource "
1961 "WHERE channel.deleted IS NULL AND "
1962 " videosource.sourceid = channel.sourceid AND "
1963 " channum = :CHANNUM AND "
1964 " channel.sourceid = :SOURCEID "
1965 "ORDER BY channel.visible > 0 DESC, channel.chanid ");
1977 finetune = query.
value(0).toInt();
1978 freqid = query.
value(1).toString();
1979 tvformat = query.
value(2).toString();
1980 freqtable = query.
value(3).toString();
1981 commfree = (query.
value(4).toInt() == -2);
1982 mplexid = query.
value(5).toUInt();
1983 atsc_major = query.
value(6).toUInt();
1984 atsc_minor = query.
value(7).toUInt();
1985 mpeg_prog_num = (query.
value(8).isNull()) ? -1
1986 : query.
value(8).toInt();
1987 chanid = query.
value(9).toUInt();
1988 name = query.
value(10).toString();
1989 callsign = query.
value(11).toString();
1995 while (query.
next())
1999 if (found == 0 && chanid)
2001 LOG(VB_GENERAL, LOG_WARNING,
2002 QString(
"No visible channels for %1, using invisble chanid %2")
2003 .arg(channum).arg(chanid));
2008 LOG(VB_GENERAL, LOG_WARNING,
2009 QString(
"Found multiple visible channels for %1, using chanid %2")
2010 .arg(channum).arg(chanid));
2015 LOG(VB_GENERAL, LOG_ERR,
2016 QString(
"Could not find channel '%1' in DB for source %2 '%3'.")
2021 if (!mplexid || (mplexid == 32767))
2025 dvb_transportid, dvb_networkid, dtv_si_std);
2032 "SELECT type+0, url, bitrate "
2033 "FROM iptv_channel "
2034 "WHERE chanid = :CHANID "
2048 std::array<uint,3> bitrate { 0, 0, 0, };
2049 while (query.
next())
2052 query.
value(0).toUInt();
2056 data_url = query.
value(1).toString();
2057 bitrate[0] = query.
value(2).toUInt();
2062 fec_url0 = query.
value(1).toString();
2063 bitrate[1] = query.
value(2).toUInt();
2068 fec_url1 = query.
value(1).toString();
2069 bitrate[2] = query.
value(2).toUInt();
2093 fec_url0, bitrate[1], fec_url1, bitrate[2]);
2094 LOG(VB_GENERAL, LOG_INFO, QString(
"Loaded %1 for %2")
2105 uint sourceid,
bool visible_only,
bool include_disconnected,
2106 const QString &group_by,
uint channel_groupid)
2112 QString qstr = QString(
2113 "SELECT videosource.sourceid, GROUP_CONCAT(capturecard.cardid) "
2115 "%1 JOIN capturecard ON capturecard.sourceid = videosource.sourceid "
2116 "GROUP BY videosource.sourceid")
2117 .arg(include_disconnected ?
"LEFT" :
"");
2126 QMap<uint, QList<uint>> inputIdLists;
2127 while (query.
next())
2129 uint qSourceId = query.
value(0).toUInt();
2130 QList<uint> &inputIdList = inputIdLists[qSourceId];
2131 QStringList inputIds = query.
value(1).toString().split(
",");
2132 while (!inputIds.isEmpty())
2133 inputIdList.append(inputIds.takeFirst().toUInt());
2137 "SELECT channum, callsign, channel.chanid, "
2138 " atsc_major_chan, atsc_minor_chan, "
2139 " name, icon, mplexid, visible, "
2140 " channel.sourceid, "
2141 " GROUP_CONCAT(DISTINCT channelgroup.grpid), "
2144 "LEFT JOIN channelgroup ON channel.chanid = channelgroup.chanid ");
2146 qstr +=
"WHERE deleted IS NULL ";
2149 qstr += QString(
"AND channel.sourceid='%1' ").arg(sourceid);
2152 if (channel_groupid > 0)
2153 qstr += QString(
"AND channelgroup.grpid = '%1' ").arg(channel_groupid);
2156 qstr += QString(
"AND visible > 0 ");
2158 qstr +=
" GROUP BY chanid";
2160 if (!group_by.isEmpty())
2161 qstr += QString(
", %1").arg(group_by);
2170 while (query.
next())
2172 if (query.
value(0).toString().isEmpty() || !query.
value(2).toBool())
2175 uint qSourceID = query.
value(9).toUInt();
2177 query.
value(0).toString(),
2178 query.
value(1).toString(),
2179 query.
value(2).toUInt(),
2180 query.
value(3).toUInt(),
2181 query.
value(4).toUInt(),
2182 query.
value(7).toUInt(),
2185 query.
value(5).toString(),
2186 query.
value(6).toString(),
2191 for (
auto inputId : std::as_const(inputIdLists[qSourceID]))
2194 QStringList groupIDs = query.
value(10).toString().split(
",");
2195 while (!groupIDs.isEmpty())
2196 chan.
AddGroupId(groupIDs.takeFirst().toUInt());
2198 list.push_back(chan);
2209 QString select =
"SELECT chanid FROM channel WHERE deleted IS NULL ";
2211 if (onlyVisible || sourceid > 0)
2214 select +=
"AND visible > 0 ";
2216 select +=
"AND sourceid=" + QString::number(sourceid);
2219 std::vector<uint> list;
2227 while (query.
next())
2228 list.push_back(query.
value(0).toUInt());
2243 static QMutex s_sepExprLock;
2246 bool isIntA =
false;
2247 bool isIntB =
false;
2248 int a_int = a.
m_chanNum.toUInt(&isIntA);
2249 int b_int = b.
m_chanNum.toUInt(&isIntB);
2259 QMutexLocker locker(&s_sepExprLock);
2267 int major = a.
m_chanNum.left(idxA).toUInt(&tmp1);
2270 (a_major = major), (a_minor =
minor), (isIntA =
false);
2277 int major = b.
m_chanNum.left(idxB).toUInt(&tmp1);
2280 (b_major = major), (b_minor =
minor), (isIntB =
false);
2284 if ((a_minor > 0) && isIntA)
2286 int atsc_int = (QString(
"%1%2").arg(a_major).arg(a_minor)).toInt();
2287 a_minor = (atsc_int == a_int) ? a_minor : 0;
2290 if ((b_minor > 0) && isIntB)
2292 int atsc_int = (QString(
"%1%2").arg(b_major).arg(b_minor)).toInt();
2293 b_minor = (atsc_int == b_int) ? b_minor : 0;
2298 if ((a_minor || b_minor) &&
2299 (a_minor || isIntA) && (b_minor || isIntB))
2301 int a_maj = (!a_minor && isIntA) ? a_int : a_major;
2302 int b_maj = (!b_minor && isIntB) ? b_int : b_major;
2303 int cmp = a_maj - b_maj;
2307 cmp = a_minor - b_minor;
2312 if (isIntA && isIntB)
2315 int cmp = a_int - b_int;
2319 else if (isIntA ^ isIntB)
2345 select =
"SELECT chanid FROM channel WHERE deleted IS NULL ";
2347 select +=
"AND sourceid=" + QString::number(sourceid);
2355 return query.
size();
2359 bool eliminate_duplicates)
2361 bool cs = order.toLower() ==
"callsign";
2365 std::ranges::stable_sort(list,
lt_smart);
2367 if (eliminate_duplicates && !list.empty())
2370 tmp.push_back(list[0]);
2371 for (
size_t i = 1; i < list.size(); i++)
2374 (!cs &&
lt_smart(tmp.back(), list[i])))
2376 tmp.push_back(list[i]);
2392 const QString &channum)
2397 for (
int i = 0; i < (int)list.size(); ++i)
2422 if (it != l.begin())
2442 uint mplexid_restriction,
2443 uint chanid_restriction,
2445 bool skip_non_visible,
2446 bool skip_same_channum_and_callsign,
2447 bool skip_other_sources)
2453 if (it == sorted.end())
2454 it = sorted.begin();
2457 return it->m_chanId;
2467 if (skip_other_sources && (it->m_sourceId != start->m_sourceId))
2469 if (skip_same_channum_and_callsign && (it->m_chanNum == start->m_chanNum &&
2470 it->m_callSign == start->m_callSign))
2472 if ((mplexid_restriction != 0U) && (mplexid_restriction != it->m_mplexId))
2474 if ((chanid_restriction != 0U) && (chanid_restriction != it->m_chanId))
2479 return it->m_chanId;
2483 uint &totalAvailable,
2488 uint channelGroupID,
2490 const QString& callsign,
2491 const QString& channum,
2492 bool ignoreUntunable)
2498 QString sql = QString(
2499 "SELECT parentid, GROUP_CONCAT(cardid ORDER BY cardid) "
2501 "WHERE parentid <> 0 "
2502 "GROUP BY parentid ");
2511 QMap<uint, QList<uint>> childIdLists;
2512 while (query.
next())
2514 auto parentId = query.
value(0).toUInt();
2515 auto &childIdList = childIdLists[parentId];
2516 auto childIds = query.
value(1).toString().split(
",");
2517 while (!childIds.isEmpty())
2518 childIdList.append(childIds.takeFirst().toUInt());
2521 sql =
"SELECT %1 channum, freqid, channel.sourceid, "
2522 "callsign, name, icon, finetune, videofilters, xmltvid, "
2523 "channel.recpriority, channel.contrast, channel.brightness, "
2524 "channel.colour, channel.hue, tvformat, "
2525 "visible, outputfilters, useonairguide, mplexid, "
2526 "serviceid, atsc_major_chan, atsc_minor_chan, last_record, "
2527 "default_authority, commmethod, tmoffset, iptvid, "
2529 "GROUP_CONCAT(DISTINCT `groups`.`groupids`), "
2530 "GROUP_CONCAT(DISTINCT capturecard.cardid "
2531 " ORDER BY livetvorder), "
2532 "MIN(livetvorder) livetvorder "
2534 if (!channelGroupID)
2538 " GROUP_CONCAT(grpid ORDER BY grpid) groupids "
2539 " FROM channelgroup ";
2541 sql +=
" WHERE grpid = :CHANGROUPID ";
2542 sql +=
" GROUP BY chanid "
2544 " ON channel.chanid = `groups`.`chanid` ";
2545 if (!ignoreUntunable && !liveTVOnly)
2547 sql +=
"JOIN capturecard "
2548 " ON capturecard.sourceid = channel.sourceid "
2549 " AND capturecard.parentid = 0 ";
2551 sql +=
" AND capturecard.livetvorder > 0 ";
2553 sql +=
"WHERE channel.deleted IS NULL ";
2555 sql +=
"AND channel.visible > 0 ";
2558 sql +=
"AND channel.sourceid = :SOURCEID ";
2561 sql +=
"GROUP BY channel.callsign ";
2563 sql +=
"GROUP BY channel.callsign, channel.channum ";
2565 sql +=
"GROUP BY channel.chanid ";
2569 sql +=
"ORDER BY channel.name ";
2574 sql +=
"ORDER BY LPAD(CAST(channel.channum AS UNSIGNED), 10, 0), "
2575 " LPAD(channel.channum, 10, 0) ";
2579 sql +=
"ORDER BY callsign = :CALLSIGN1 AND channum = :CHANNUM DESC, "
2580 " callsign = :CALLSIGN2 DESC, "
2582 " channel.recpriority DESC, "
2587 sql +=
"LIMIT :LIMIT ";
2590 sql +=
"OFFSET :STARTINDEX ";
2593 if (startIndex > 0 || count > 0)
2594 sql = sql.arg(
"SQL_CALC_FOUND_ROWS");
2600 if (channelGroupID > 0)
2601 query.
bindValue(
":CHANGROUPID", channelGroupID);
2610 query.
bindValue(
":STARTINDEX", startIndex);
2614 query.
bindValue(
":CALLSIGN1", callsign);
2616 query.
bindValue(
":CALLSIGN2", callsign);
2625 std::vector<uint> groupIdList;
2626 while (query.
next())
2642 channelInfo.
m_hue = query.
value(13).toUInt();
2659 QStringList groupIDs = query.
value(28).toString().split(
",");
2660 groupIdList.clear();
2661 while (!groupIDs.isEmpty())
2662 groupIdList.push_back(groupIDs.takeFirst().toUInt());
2663 std::ranges::sort(groupIdList);
2664 for (
auto groupId : groupIdList)
2667 QStringList parentIDs = query.
value(29).toString().split(
",");
2668 while (!parentIDs.isEmpty())
2670 auto parentId = parentIDs.takeFirst().toUInt();
2672 auto childIdList = childIdLists[parentId];
2673 for (
auto childId : childIdList)
2677 channelList.push_back(channelInfo);
2680 if ((startIndex > 0 || count > 0) &&
2681 query.
exec(
"SELECT FOUND_ROWS()") && query.
next())
2682 totalAvailable = query.
value(0).toUInt();
2684 totalAvailable = query.
size();
std::vector< ChannelInfo >::const_iterator ChannelInfoList_ci
std::vector< ChannelInfo > ChannelInfoList
static bool lt_pidcache(const pid_cache_item_t a, const pid_cache_item_t b)
static uint get_dtv_multiplex(uint db_source_id, const QString &sistandard, uint64_t frequency, uint transport_id, uint network_id, signed char polarity)
static void handle_transport_desc(std::vector< uint > &muxes, const MPEGDescriptor &desc, uint sourceid, uint tsid, uint netid)
static bool chanid_available(uint chanid)
bool lt_callsign(const ChannelInfo &a, const ChannelInfo &b)
bool lt_smart(const ChannelInfo &a, const ChannelInfo &b)
static QStringList get_valid_recorder_list(uint chanid)
Returns list of the recorders that have chanid in their sources.
static uint insert_dtv_multiplex(int db_source_id, const QString &sistandard, uint64_t frequency, const QString &modulation, int transport_id, int network_id, int symbol_rate, signed char bandwidth, signed char polarity, signed char inversion, signed char trans_mode, const QString &inner_FEC, const QString &constellation, signed char hierarchy, const QString &hp_code_rate, const QString &lp_code_rate, const QString &guard_interval, const QString &mod_sys, const QString &rolloff)
static uint get_max_chanid(uint sourceid)
std::vector< pid_cache_item_t > pid_cache_t
unsigned long long FrequencyHz(void) const
QString ModulationString(void) const
QString FECInnerString(void) const
uint SymbolRateHz(void) const
ChannelVisibleType m_visible
void AddGroupId(uint lgroupid)
void AddInputId(uint linputid)
QString m_defaultAuthority
ChannelVisibleType m_visible
static std::vector< uint > GetChanIDs(int sourceid=-1, bool onlyVisible=false)
static QStringList GetValidRecorderList(uint chanid, const QString &channum)
Returns list of the recorders that have chanid or channum in their sources.
static bool s_channelDefaultAuthority_runInit
static uint GetMplexID(uint sourceid, const QString &channum)
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
static QMap< uint, QString > s_channelDefaultAuthorityMap
static QStringList GetInputTypes(uint chanid)
static QString GetChannelNumber(uint sourceid, const QString &channel_name)
static QReadWriteLock s_channelDefaultAuthorityMapLock
static bool DeleteChannel(uint channel_id)
static bool GetCachedPids(uint chanid, pid_cache_t &pid_cache)
Returns cached MPEG PIDs when given a Channel ID.
static QString GetIcon(uint chanid)
static int GetBetterMplexID(int current_mplexid, int transport_id, int network_id)
Returns best match multiplex ID, creating one if needed.
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
static int GetServiceVersion(int mplexid)
static int GetSourceID(int mplexid)
static QString GetChannelValueStr(const QString &channel_field, uint sourceid, const QString &channum)
static const QString kATSCSeparators
static bool UpdateIPTVTuningData(uint channel_id, const IPTVTuningData &tuning)
static bool SaveCachedPids(uint chanid, const pid_cache_t &_pid_cache, bool delete_all=false)
Saves PIDs for PSIP tables to database.
static bool UpdateChannel(uint db_mplexid, uint source_id, uint channel_id, const QString &callsign, const QString &service_name, const QString &chan_num, uint service_id, uint atsc_major_channel, uint atsc_minor_channel, bool use_on_air_guide, ChannelVisibleType visible, const QString &freqid=QString(), const QString &icon=QString(), QString format=QString(), const QString &xmltvid=QString(), const QString &default_authority=QString(), uint service_type=0, int recpriority=INT_MIN, int tmOffset=INT_MIN, int commMethod=INT_MIN)
static uint CreateMultiplex(int sourceid, const QString &sistandard, uint64_t frequency, const QString &modulation, int transport_id=-1, int network_id=-1)
static bool IsOnSameMultiplex(uint srcid, const QString &new_channum, const QString &old_channum)
static std::vector< uint > CreateMultiplexes(int sourceid, const NetworkInformationTable *nit)
static std::chrono::minutes GetTimeOffset(int chan_id)
Returns the listings time offset in minutes for given channel.
static bool SetVisible(uint channel_id, ChannelVisibleType visible)
static bool SetChannelValue(const QString &field_name, const QString &value, uint sourceid, const QString &channum)
static int GetChannelValueInt(const QString &channel_field, uint sourceid, const QString &channum)
static int GetNearestChannel(const ChannelInfoList &list, const QString &channum)
static QString GetDefaultAuthority(uint chanid)
Returns the DVB default authority for the chanid given.
static QString GetChannelStringField(int chan_id, const QString &field)
static bool GetChannelData(uint sourceid, uint &chanid, const QString &channum, QString &name, QString &callsign, QString &tvformat, QString &modulation, QString &freqtable, QString &freqid, int &finetune, uint64_t &frequency, QString &dtv_si_std, int &mpeg_prog_num, uint &atsc_major, uint &atsc_minor, uint &dvb_transportid, uint &dvb_networkid, uint &mplexid, bool &commfree)
@ kChanGroupByCallsignAndChannum
static std::vector< uint > GetConflicting(const QString &channum, uint sourceid=0)
static uint GetNextChannel(const ChannelInfoList &sorted, uint old_chanid, uint mplexid_restriction, uint chanid_restriction, ChannelChangeDirection direction, bool skip_non_visible=true, bool skip_same_channum_and_callsign=false, bool skip_other_sources=false)
static uint GetChannelCount(int sourceid=-1)
static int CreateChanID(uint sourceid, const QString &chan_num)
Creates a unique channel ID for database use.
static QString GetChanNum(int chan_id)
Returns the channel-number string of the given channel.
static bool CreateChannel(uint db_mplexid, uint db_sourceid, uint new_channel_id, const QString &callsign, const QString &service_name, const QString &chan_num, uint service_id, uint atsc_major_channel, uint atsc_minor_channel, bool use_on_air_guide, ChannelVisibleType visible, const QString &freqid, const QString &icon=QString(), QString format="Default", const QString &xmltvid=QString(), const QString &default_authority=QString(), uint service_type=0, int recpriority=0, int tmOffset=0, int commMethod=-1)
static ChannelInfoList GetChannelsInternal(uint sourceid, bool visible_only, bool include_disconnected, const QString &group_by, uint channel_groupid)
static bool GetTuningParams(uint mplexid, QString &modulation, uint64_t &frequency, uint &dvb_transportid, uint &dvb_networkid, QString &si_std)
static ChannelInfoList LoadChannels(uint startIndex, uint count, uint &totalAvailable, bool ignoreHidden=true, OrderBy orderBy=kChanOrderByChanNum, GroupBy groupBy=kChanGroupByChanid, uint sourceID=0, uint channelGroupID=0, bool liveTVOnly=false, const QString &callsign="", const QString &channum="", bool ignoreUntunable=true)
Load channels from database into a list of ChannelInfo objects.
static IPTVTuningData GetIPTVTuningData(uint chanid)
static void UpdateChannelNumberFromDB(ChannelInsertInfo &chan)
static QString GetUnknownCallsign(void)
static void UpdateInsertInfoFromDB(ChannelInsertInfo &chan)
static bool SetServiceVersion(int mplexid, int version)
static uint FindChannel(uint sourceid, const QString &freqid)
static uint GetSourceIDForChannel(uint chanid)
static bool GetATSCChannel(uint sourceid, const QString &channum, uint &major, uint &minor)
DTVTransmitMode m_transMode
DTVModulation m_modulation
DTVModulationSystem m_modSys
DTVGuardInterval m_guardInterval
@ satellite_delivery_system
@ terrestrial_delivery_system
QString GetFECTypeString(uint i) const
QUrl GetDataURL(void) const
QUrl GetFECURL0(void) const
QUrl GetFECURL1(void) const
uint GetBitrate(uint i) const
QString GetDeviceName(void) const
static desc_list_t Parse(const unsigned char *data, uint len)
uint DescriptorTag(void) const
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
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
static MSqlQueryInfo ChannelCon()
Returns dedicated connection. (Required for using temporary SQL tables.)
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)
uint64_t FrequencykHz(void) const
uint SymbolRateHz(void) const
QString FECInnerString(void) const
QString ModulationString(void) const
QString PolarizationString() const
QString RollOffString(void) const
QString ModulationSystemString(void) const
static QString GetSourceName(uint sourceid)
QString HierarchyString(void) const
QString CodeRateHPString(void) const
QString CodeRateLPString(void) const
uint64_t FrequencyHz(void) const
QString GuardIntervalString(void) const
QString ConstellationString(void) const
QString TransmissionModeString(void) const
QString BandwidthString(void) const
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
static const std::array< const uint32_t, 4 > freq
static const iso6937table * d
std::vector< const unsigned char * > desc_list_t
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
MBASE_PUBLIC std::strong_ordering naturalCompare(const QString &_a, const QString &_b, Qt::CaseSensitivity caseSensitivity=Qt::CaseSensitive)
This method chops the input a and b into pieces of digits and non-digits (a1.05 becomes a | 1 | .
ChannelInfoList_ci next_w_wrap(const ChannelInfoList &l, ChannelInfoList_ci it, ChannelChangeDirection d)
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.