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);
1488#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1490 (sourceid * 10000) +
1491 (chan_num.leftRef(chansep).toInt() * 100) +
1492 chan_num.rightRef(chan_num.length() - chansep - 1).toInt();
1495 (sourceid * 10000) +
1496 (QStringView(chan_num).left(chansep).toInt() * 100) +
1497 QStringView(chan_num).right(chan_num.length() - chansep - 1).toInt();
1502 chanid = (sourceid * 10000) + chan_num.toInt();
1509 chanid = std::max(
get_max_chanid(sourceid) + 1, sourceid * 10000);
1526 uint new_channel_id,
1527 const QString &callsign,
1528 const QString &service_name,
1529 const QString &chan_num,
1531 uint atsc_major_channel,
1532 uint atsc_minor_channel,
1533 bool use_on_air_guide,
1535 const QString &freqid,
1536 const QString& icon,
1538 const QString& xmltvid,
1539 const QString& default_authority,
1547 QString chanNum = (chan_num ==
"-1") ?
1548 QString::number(service_id) : chan_num;
1551 "INSERT INTO channel "
1552 " (chanid, channum, sourceid, "
1553 " callsign, name, serviceid, ";
1554 qstr += (db_mplexid > 0) ?
"mplexid, " :
"";
1555 qstr += (!freqid.isEmpty()) ?
"freqid, " :
"";
1557 " atsc_major_chan, atsc_minor_chan, "
1558 " useonairguide, visible, tvformat, "
1559 " icon, xmltvid, default_authority, "
1560 " service_type, recpriority, tmoffset, "
1563 " (:CHANID, :CHANNUM, :SOURCEID, "
1564 " :CALLSIGN, :NAME, :SERVICEID, ";
1565 qstr += (db_mplexid > 0) ?
":MPLEXID, " :
"";
1566 qstr += (!freqid.isEmpty()) ?
":FREQID, " :
"";
1568 " :MAJORCHAN, :MINORCHAN, "
1569 " :USEOAG, :VISIBLE, :TVFORMAT, "
1570 " :ICON, :XMLTVID, :AUTHORITY, "
1571 " :SERVICETYPE, :RECPRIORITY, :TMOFFSET, "
1576 query.
bindValue (
":CHANID", new_channel_id);
1578 query.
bindValue (
":SOURCEID", db_sourceid);
1583 query.
bindValue(
":MPLEXID", db_mplexid);
1585 query.
bindValue(
":SERVICEID", service_id);
1586 query.
bindValue(
":MAJORCHAN", atsc_major_channel);
1587 query.
bindValue(
":MINORCHAN", atsc_minor_channel);
1588 query.
bindValue(
":USEOAG", use_on_air_guide);
1591 if (!freqid.isEmpty())
1594 QString tvformat = (atsc_minor_channel > 0) ?
"ATSC" : std::move(format);
1599 query.
bindValue (
":SERVICETYPE", service_type);
1600 query.
bindValue (
":RECPRIORITY", recpriority);
1601 query.
bindValue (
":TMOFFSET", tmOffset);
1602 query.
bindValue (
":COMMMETHOD", commMethod);
1615 const QString &callsign,
1616 const QString &service_name,
1617 const QString &chan_num,
1619 uint atsc_major_channel,
1620 uint atsc_minor_channel,
1621 bool use_on_air_guide,
1623 const QString& freqid,
1624 const QString& icon,
1626 const QString& xmltvid,
1627 const QString& default_authority,
1636 QString tvformat = (atsc_minor_channel > 0) ?
"ATSC" : std::move(format);
1637 bool set_channum = !chan_num.isEmpty() && chan_num !=
"-1";
1638 QString qstr = QString(
1640 "SET %1 %2 %3 %4 %5 %6 %7 %8 %9 "
1641 " mplexid = :MPLEXID, serviceid = :SERVICEID, "
1642 " atsc_major_chan = :MAJORCHAN, atsc_minor_chan = :MINORCHAN, "
1643 " callsign = :CALLSIGN, name = :NAME, "
1644 " sourceid = :SOURCEID, useonairguide = :USEOAG, "
1645 " visible = :VISIBLE, service_type = :SERVICETYPE "
1646 "WHERE chanid=:CHANID")
1647 .arg((!set_channum) ?
"" :
"channum = :CHANNUM, ",
1648 (freqid.isEmpty()) ?
"" :
"freqid = :FREQID, ",
1649 (icon.isEmpty()) ?
"" :
"icon = :ICON, ",
1650 (tvformat.isEmpty()) ?
"" :
"tvformat = :TVFORMAT, ",
1651 (xmltvid.isEmpty()) ?
"" :
"xmltvid = :XMLTVID, ",
1652 (default_authority.isEmpty()) ?
1653 "" :
"default_authority = :AUTHORITY,",
1654 (recpriority == INT_MIN) ?
"" :
"recpriority = :RECPRIORITY, ",
1655 (tmOffset == INT_MIN) ?
"" :
"tmOffset = :TMOFFSET, ",
1656 (commMethod == INT_MIN) ?
"" :
"commmethod = :COMMMETHOD, ");
1666 query.
bindValue (
":SOURCEID", source_id);
1670 query.
bindValue(
":MPLEXID", db_mplexid);
1671 query.
bindValue(
":SERVICEID", service_id);
1672 query.
bindValue(
":MAJORCHAN", atsc_major_channel);
1673 query.
bindValue(
":MINORCHAN", atsc_minor_channel);
1674 query.
bindValue(
":USEOAG", use_on_air_guide);
1676 query.
bindValue(
":SERVICETYPE", service_type);
1678 if (!freqid.isNull())
1680 if (!tvformat.isNull())
1684 if (!xmltvid.isNull())
1686 if (!default_authority.isNull())
1687 query.
bindValue(
":AUTHORITY", default_authority);
1688 if (recpriority != INT_MIN)
1689 query.
bindValue(
":RECPRIORITY", recpriority);
1690 if (tmOffset != INT_MIN)
1692 if (commMethod != INT_MIN)
1693 query.
bindValue(
":COMMMETHOD", commMethod);
1709 "WHERE chanid = :ID");
1720 QString channum = query.
value(0).toString();
1722 if (!channum.isEmpty())
1733 "SELECT xmltvid, useonairguide, visible "
1735 "WHERE chanid = :ID");
1746 QString xmltvid = query.
value(0).toString();
1747 bool useeit = query.
value(1).toBool();
1751 if (!xmltvid.isEmpty())
1755 LOG(VB_GENERAL, LOG_ERR,
1756 "Using EIT and xmltv for the same channel "
1757 "is an unsupported configuration.");
1774 "DELETE FROM iptv_channel "
1775 "WHERE chanid=:CHANID");
1785 "INSERT INTO iptv_channel (chanid, url, type, bitrate) "
1786 "VALUES (:CHANID, :URL, :TYPE, :BITRATE)");
1831 "SET deleted = NOW() "
1832 "WHERE chanid = :ID");
1849 "SET visible = :VISIBLE "
1850 "WHERE chanid = :ID");
1867 query.
prepare(
"UPDATE dtv_multiplex "
1868 "SET serviceversion = :VERSION "
1869 "WHERE mplexid = :MPLEXID");
1886 query.
prepare(
"SELECT serviceversion "
1887 "FROM dtv_multiplex "
1888 "WHERE mplexid = :MPLEXID");
1899 return query.
value(0).toInt();
1911 "SELECT atsc_major_chan, atsc_minor_chan "
1913 "WHERE deleted IS NULL AND "
1914 " channum = :CHANNUM AND "
1915 " sourceid = :SOURCEID");
1924 else if (query.
next())
1926 major = query.
value(0).toUInt();
1936 uint &chanid,
const QString &channum,
1937 QString &name, QString &callsign,
1938 QString &tvformat, QString &modulation,
1939 QString &freqtable, QString &freqid,
1940 int &finetune, uint64_t &frequency,
1941 QString &dtv_si_std,
int &mpeg_prog_num,
1942 uint &atsc_major,
uint &atsc_minor,
1943 uint &dvb_transportid,
uint &dvb_networkid,
1956 atsc_major = atsc_minor = mplexid = 0;
1957 dvb_networkid = dvb_transportid = 0;
1963 "SELECT finetune, freqid, tvformat, freqtable, "
1964 " commmethod, mplexid, "
1965 " atsc_major_chan, atsc_minor_chan, serviceid, "
1966 " chanid, channel.name, callsign, visible "
1967 "FROM channel, videosource "
1968 "WHERE channel.deleted IS NULL AND "
1969 " videosource.sourceid = channel.sourceid AND "
1970 " channum = :CHANNUM AND "
1971 " channel.sourceid = :SOURCEID "
1972 "ORDER BY channel.visible > 0 DESC, channel.chanid ");
1984 finetune = query.
value(0).toInt();
1985 freqid = query.
value(1).toString();
1986 tvformat = query.
value(2).toString();
1987 freqtable = query.
value(3).toString();
1988 commfree = (query.
value(4).toInt() == -2);
1989 mplexid = query.
value(5).toUInt();
1990 atsc_major = query.
value(6).toUInt();
1991 atsc_minor = query.
value(7).toUInt();
1992 mpeg_prog_num = (query.
value(8).isNull()) ? -1
1993 : query.
value(8).toInt();
1994 chanid = query.
value(9).toUInt();
1995 name = query.
value(10).toString();
1996 callsign = query.
value(11).toString();
2002 while (query.
next())
2006 if (found == 0 && chanid)
2008 LOG(VB_GENERAL, LOG_WARNING,
2009 QString(
"No visible channels for %1, using invisble chanid %2")
2010 .arg(channum).arg(chanid));
2015 LOG(VB_GENERAL, LOG_WARNING,
2016 QString(
"Found multiple visible channels for %1, using chanid %2")
2017 .arg(channum).arg(chanid));
2022 LOG(VB_GENERAL, LOG_ERR,
2023 QString(
"Could not find channel '%1' in DB for source %2 '%3'.")
2028 if (!mplexid || (mplexid == 32767))
2032 dvb_transportid, dvb_networkid, dtv_si_std);
2039 "SELECT type+0, url, bitrate "
2040 "FROM iptv_channel "
2041 "WHERE chanid = :CHANID "
2055 std::array<uint,3> bitrate { 0, 0, 0, };
2056 while (query.
next())
2059 query.
value(0).toUInt();
2063 data_url = query.
value(1).toString();
2064 bitrate[0] = query.
value(2).toUInt();
2069 fec_url0 = query.
value(1).toString();
2070 bitrate[1] = query.
value(2).toUInt();
2075 fec_url1 = query.
value(1).toString();
2076 bitrate[2] = query.
value(2).toUInt();
2100 fec_url0, bitrate[1], fec_url1, bitrate[2]);
2101 LOG(VB_GENERAL, LOG_INFO, QString(
"Loaded %1 for %2")
2112 uint sourceid,
bool visible_only,
bool include_disconnected,
2113 const QString &group_by,
uint channel_groupid)
2119 QString qstr = QString(
2120 "SELECT videosource.sourceid, GROUP_CONCAT(capturecard.cardid) "
2122 "%1 JOIN capturecard ON capturecard.sourceid = videosource.sourceid "
2123 "GROUP BY videosource.sourceid")
2124 .arg(include_disconnected ?
"LEFT" :
"");
2133 QMap<uint, QList<uint>> inputIdLists;
2134 while (query.
next())
2136 uint qSourceId = query.
value(0).toUInt();
2137 QList<uint> &inputIdList = inputIdLists[qSourceId];
2138 QStringList inputIds = query.
value(1).toString().split(
",");
2139 while (!inputIds.isEmpty())
2140 inputIdList.append(inputIds.takeFirst().toUInt());
2144 "SELECT channum, callsign, channel.chanid, "
2145 " atsc_major_chan, atsc_minor_chan, "
2146 " name, icon, mplexid, visible, "
2147 " channel.sourceid, "
2148 " GROUP_CONCAT(DISTINCT channelgroup.grpid), "
2151 "LEFT JOIN channelgroup ON channel.chanid = channelgroup.chanid ");
2153 qstr +=
"WHERE deleted IS NULL ";
2156 qstr += QString(
"AND channel.sourceid='%1' ").arg(sourceid);
2159 if (channel_groupid > 0)
2160 qstr += QString(
"AND channelgroup.grpid = '%1' ").arg(channel_groupid);
2163 qstr += QString(
"AND visible > 0 ");
2165 qstr +=
" GROUP BY chanid";
2167 if (!group_by.isEmpty())
2168 qstr += QString(
", %1").arg(group_by);
2177 while (query.
next())
2179 if (query.
value(0).toString().isEmpty() || !query.
value(2).toBool())
2182 uint qSourceID = query.
value(9).toUInt();
2184 query.
value(0).toString(),
2185 query.
value(1).toString(),
2186 query.
value(2).toUInt(),
2187 query.
value(3).toUInt(),
2188 query.
value(4).toUInt(),
2189 query.
value(7).toUInt(),
2192 query.
value(5).toString(),
2193 query.
value(6).toString(),
2198 for (
auto inputId : std::as_const(inputIdLists[qSourceID]))
2201 QStringList groupIDs = query.
value(10).toString().split(
",");
2202 while (!groupIDs.isEmpty())
2203 chan.
AddGroupId(groupIDs.takeFirst().toUInt());
2205 list.push_back(chan);
2216 QString select =
"SELECT chanid FROM channel WHERE deleted IS NULL ";
2218 if (onlyVisible || sourceid > 0)
2221 select +=
"AND visible > 0 ";
2223 select +=
"AND sourceid=" + QString::number(sourceid);
2226 std::vector<uint> list;
2234 while (query.
next())
2235 list.push_back(query.
value(0).toUInt());
2250 static QMutex s_sepExprLock;
2253 bool isIntA =
false;
2254 bool isIntB =
false;
2255 int a_int = a.
m_chanNum.toUInt(&isIntA);
2256 int b_int = b.
m_chanNum.toUInt(&isIntB);
2266 QMutexLocker locker(&s_sepExprLock);
2274#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2275 int major = a.
m_chanNum.leftRef(idxA).toUInt(&tmp1);
2278 int major = QStringView(a.
m_chanNum).left(idxA).toUInt(&tmp1);
2282 (a_major = major), (a_minor =
minor), (isIntA =
false);
2289#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
2290 int major = b.
m_chanNum.leftRef(idxB).toUInt(&tmp1);
2293 int major = QStringView(b.
m_chanNum).left(idxB).toUInt(&tmp1);
2297 (b_major = major), (b_minor =
minor), (isIntB =
false);
2301 if ((a_minor > 0) && isIntA)
2303 int atsc_int = (QString(
"%1%2").arg(a_major).arg(a_minor)).toInt();
2304 a_minor = (atsc_int == a_int) ? a_minor : 0;
2307 if ((b_minor > 0) && isIntB)
2309 int atsc_int = (QString(
"%1%2").arg(b_major).arg(b_minor)).toInt();
2310 b_minor = (atsc_int == b_int) ? b_minor : 0;
2315 if ((a_minor || b_minor) &&
2316 (a_minor || isIntA) && (b_minor || isIntB))
2318 int a_maj = (!a_minor && isIntA) ? a_int : a_major;
2319 int b_maj = (!b_minor && isIntB) ? b_int : b_major;
2320 int cmp = a_maj - b_maj;
2324 cmp = a_minor - b_minor;
2329 if (isIntA && isIntB)
2332 int cmp = a_int - b_int;
2336 else if (isIntA ^ isIntB)
2362 select =
"SELECT chanid FROM channel WHERE deleted IS NULL ";
2364 select +=
"AND sourceid=" + QString::number(sourceid);
2372 return query.
size();
2376 bool eliminate_duplicates)
2378 bool cs = order.toLower() ==
"callsign";
2382 std::ranges::stable_sort(list,
lt_smart);
2384 if (eliminate_duplicates && !list.empty())
2387 tmp.push_back(list[0]);
2388 for (
size_t i = 1; i < list.size(); i++)
2391 (!cs &&
lt_smart(tmp.back(), list[i])))
2393 tmp.push_back(list[i]);
2409 const QString &channum)
2414 for (
int i = 0; i < (int)list.size(); ++i)
2439 if (it != l.begin())
2459 uint mplexid_restriction,
2460 uint chanid_restriction,
2462 bool skip_non_visible,
2463 bool skip_same_channum_and_callsign,
2464 bool skip_other_sources)
2470 if (it == sorted.end())
2471 it = sorted.begin();
2474 return it->m_chanId;
2484 if (skip_other_sources && (it->m_sourceId != start->m_sourceId))
2486 if (skip_same_channum_and_callsign && (it->m_chanNum == start->m_chanNum &&
2487 it->m_callSign == start->m_callSign))
2489 if ((mplexid_restriction != 0U) && (mplexid_restriction != it->m_mplexId))
2491 if ((chanid_restriction != 0U) && (chanid_restriction != it->m_chanId))
2496 return it->m_chanId;
2500 uint &totalAvailable,
2505 uint channelGroupID,
2507 const QString& callsign,
2508 const QString& channum,
2509 bool ignoreUntunable)
2515 QString sql = QString(
2516 "SELECT parentid, GROUP_CONCAT(cardid ORDER BY cardid) "
2518 "WHERE parentid <> 0 "
2519 "GROUP BY parentid ");
2528 QMap<uint, QList<uint>> childIdLists;
2529 while (query.
next())
2531 auto parentId = query.
value(0).toUInt();
2532 auto &childIdList = childIdLists[parentId];
2533 auto childIds = query.
value(1).toString().split(
",");
2534 while (!childIds.isEmpty())
2535 childIdList.append(childIds.takeFirst().toUInt());
2538 sql =
"SELECT %1 channum, freqid, channel.sourceid, "
2539 "callsign, name, icon, finetune, videofilters, xmltvid, "
2540 "channel.recpriority, channel.contrast, channel.brightness, "
2541 "channel.colour, channel.hue, tvformat, "
2542 "visible, outputfilters, useonairguide, mplexid, "
2543 "serviceid, atsc_major_chan, atsc_minor_chan, last_record, "
2544 "default_authority, commmethod, tmoffset, iptvid, "
2546 "GROUP_CONCAT(DISTINCT `groups`.`groupids`), "
2547 "GROUP_CONCAT(DISTINCT capturecard.cardid "
2548 " ORDER BY livetvorder), "
2549 "MIN(livetvorder) livetvorder "
2551 if (!channelGroupID)
2555 " GROUP_CONCAT(grpid ORDER BY grpid) groupids "
2556 " FROM channelgroup ";
2558 sql +=
" WHERE grpid = :CHANGROUPID ";
2559 sql +=
" GROUP BY chanid "
2561 " ON channel.chanid = `groups`.`chanid` ";
2562 if (!ignoreUntunable && !liveTVOnly)
2564 sql +=
"JOIN capturecard "
2565 " ON capturecard.sourceid = channel.sourceid "
2566 " AND capturecard.parentid = 0 ";
2568 sql +=
" AND capturecard.livetvorder > 0 ";
2570 sql +=
"WHERE channel.deleted IS NULL ";
2572 sql +=
"AND channel.visible > 0 ";
2575 sql +=
"AND channel.sourceid = :SOURCEID ";
2578 sql +=
"GROUP BY channel.callsign ";
2580 sql +=
"GROUP BY channel.callsign, channel.channum ";
2582 sql +=
"GROUP BY channel.chanid ";
2586 sql +=
"ORDER BY channel.name ";
2591 sql +=
"ORDER BY LPAD(CAST(channel.channum AS UNSIGNED), 10, 0), "
2592 " LPAD(channel.channum, 10, 0) ";
2596 sql +=
"ORDER BY callsign = :CALLSIGN1 AND channum = :CHANNUM DESC, "
2597 " callsign = :CALLSIGN2 DESC, "
2599 " channel.recpriority DESC, "
2604 sql +=
"LIMIT :LIMIT ";
2607 sql +=
"OFFSET :STARTINDEX ";
2610 if (startIndex > 0 || count > 0)
2611 sql = sql.arg(
"SQL_CALC_FOUND_ROWS");
2617 if (channelGroupID > 0)
2618 query.
bindValue(
":CHANGROUPID", channelGroupID);
2627 query.
bindValue(
":STARTINDEX", startIndex);
2631 query.
bindValue(
":CALLSIGN1", callsign);
2633 query.
bindValue(
":CALLSIGN2", callsign);
2642 std::vector<uint> groupIdList;
2643 while (query.
next())
2659 channelInfo.
m_hue = query.
value(13).toUInt();
2676 QStringList groupIDs = query.
value(28).toString().split(
",");
2677 groupIdList.clear();
2678 while (!groupIDs.isEmpty())
2679 groupIdList.push_back(groupIDs.takeFirst().toUInt());
2680 std::ranges::sort(groupIdList);
2681 for (
auto groupId : groupIdList)
2684 QStringList parentIDs = query.
value(29).toString().split(
",");
2685 while (!parentIDs.isEmpty())
2687 auto parentId = parentIDs.takeFirst().toUInt();
2689 auto childIdList = childIdLists[parentId];
2690 for (
auto childId : childIdList)
2694 channelList.push_back(channelInfo);
2697 if ((startIndex > 0 || count > 0) &&
2698 query.
exec(
"SELECT FOUND_ROWS()") && query.
next())
2699 totalAvailable = query.
value(0).toUInt();
2701 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.