Go to the documentation of this file.
38 #include <QMutexLocker>
86 return "ChannelScanSM(u)";
89 #define LOC (ChannelScanSM::loc(this) + ": ")
150 int sourceID, std::chrono::milliseconds signal_timeout,
151 std::chrono::milliseconds channel_timeout, QString inputname,
152 bool test_decryption)
154 m_scanMonitor(scan_monitor),
156 m_signalMonitor(
SignalMonitor::Init(cardtype, m_channel->GetInputID(),
158 m_sourceID(sourceID),
159 m_signalTimeout(signal_timeout),
160 m_channelTimeout(channel_timeout),
161 m_inputName(
std::move(inputname)),
162 m_testDecryption(test_decryption),
173 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"Connecting up DTVSignalMonitor");
178 "SELECT dvb_nit_id, bouquet_id, region_id, lcnoffset "
180 "WHERE videosource.sourceid = :SOURCEID");
186 else if (query.
next())
188 int nitid = query.
value(0).toInt();
189 data->SetRealNetworkID(nitid);
190 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
191 QString(
"Setting NIT-ID to %1").arg(nitid));
196 m_nitId = nitid > 0 ? nitid : 0;
199 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
200 QString(
"Freesat/Sky bouquet_id:%1 region_id:%2")
211 if (dvbchannel && dvbchannel->GetRotor())
215 data->AddMPEGListener(
this);
216 data->AddATSCMainListener(
this);
217 data->AddDVBMainListener(
this);
218 data->AddDVBOtherListener(
this);
225 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"ChannelScanSM Stopped");
261 QMutexLocker locker(&
m_lock);
263 QString cur_chan = (*m_current).m_friendlyName;
264 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
265 QStringList list = cur_chan.split(
" ", QString::SkipEmptyParts);
267 QStringList list = cur_chan.split(
" ", Qt::SkipEmptyParts);
269 QString freqid = (list.size() >= 2) ? list[1] : cur_chan;
271 QString msg = QObject::tr(
"Updated Channel %1").arg(cur_chan);
277 QString callsign = QString(
"%1-%2")
295 QObject::tr(
"Added Channel %1").arg(cur_chan) :
296 QObject::tr(
"Failed to add channel %1").arg(cur_chan);
336 if (multiplexes.empty())
338 LOG(VB_CHANSCAN, LOG_ERR,
LOC +
"Unable to find any transports for " +
339 QString(
"sourceid %1").arg(sourceid));
344 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
345 QString(
"Found %1 transports for ").arg(multiplexes.size()) +
346 QString(
"sourceid %1").arg(sourceid));
348 for (
uint multiplex : multiplexes)
361 LOG(VB_CHANSCAN, LOG_ERR,
LOC +
362 "Unable to find add any transports for " +
363 QString(
"sourceid %1").arg(sourceid));
375 QStringList lines =
string.split(
'\n');
376 for (
const QString& line : qAsConst(lines))
377 LOG(VB_CHANSCAN, LOG_DEBUG, line);
383 QMutexLocker locker(&
m_lock);
385 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
386 QString(
"Got a Program Association Table for %1")
387 .arg((*m_current).m_friendlyName));
400 QMutexLocker locker(&
m_lock);
402 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
403 QString(
"Got a Conditional Access Table for %1")
404 .arg((*m_current).m_friendlyName));
410 QMutexLocker locker(&
m_lock);
412 LOG(VB_CHANSCAN, LOG_INFO,
LOC + QString(
"Got a Program Map Table for %1 program %2 (0x%3)")
426 QMutexLocker locker(&
m_lock);
428 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
429 QString(
"Got a Virtual Channel Table for %1")
430 .arg((*m_current).m_friendlyName));
446 QMutexLocker locker(&
m_lock);
448 LOG(VB_CHANSCAN, LOG_INFO,
LOC + QString(
"Got the Master Guide for %1")
449 .arg((*m_current).m_friendlyName));
464 QMutexLocker locker(&
m_lock);
466 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
467 QString(
"Got a Service Description Table for %1 section %2/%3")
468 .arg((*m_current).m_friendlyName)
478 SetFreesatAdditionalSI(
true);
485 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
486 QString(
"SDT has OriginalNetworkID %1, look for "
494 SetVersionSDT(sdt->
TSID(), -1, 0);
513 QMutexLocker locker(&
m_lock);
515 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
516 QString(
"Got a Network Information Table id %1 for %2 section %3/%4")
517 .arg(nit->
NetworkID()).arg((*m_current).m_friendlyName)
526 QMutexLocker locker(&
m_lock);
528 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
529 QString(
"Got a Bouquet Association Table id %1 for %2 section %3/%4")
530 .arg(bat->
BouquetID()).arg((*m_current).m_friendlyName)
544 const unsigned char *def_auth =
546 const unsigned char *serv_list =
549 if (def_auth && serv_list)
556 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
557 QString(
"Found default authority '%1' in BAT for services in nid %2 tid %3")
559 .arg(netid).arg(tsid));
565 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
566 QString(
"Found default authority '%1' in BAT for service nid %2 tid %3 sid %4")
568 .arg(netid).arg(tsid).arg(services.
ServiceID(j)));
569 uint64_t index = ((uint64_t)netid << 32) | (tsid << 16) |
581 QMutexLocker locker(&
m_lock);
583 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
584 QString(
"Got a Service Description Table (other) for Transport ID %1 section %2/%3")
599 const unsigned char *def_auth =
607 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
608 QString(
"Found default authority '%1' in SDTo for service nid %2 tid %3 sid %4")
610 .arg(netid).arg(tsid).arg(serviceId));
620 QMutexLocker locker(&
m_lock);
634 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Can't monitor decryption -- no pmts");
644 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"%1/%2 checked")
645 .arg(currentEncryptionStatusChecked.size())
646 .arg(currentEncryptionStatus.size()));
683 QObject::tr(
"Program %1 Testing Decryption")
686 QString(
"%1 -- Testing decryption of program %2")
687 .arg(cur_chan).arg(pnum);
690 LOG(VB_CHANSCAN, LOG_INFO,
LOC + msg);
705 LOG(VB_GENERAL, LOG_INFO,
LOC +
706 QString(
"Can't monitor decryption of program %1 -- no pmt")
727 for (
auto & tt : tts)
741 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC + QString(
"%1 NIT nid:%2 fr:%3 section:%4/%5 ts count:%6 ")
747 uint32_t tsid = nit->
TSID(i);
749 uint32_t
id = netid << 16 | tsid;
758 for (
const auto *
const item : list)
760 uint64_t frequency = 0;
819 LOG(VB_CHANSCAN, LOG_DEBUG, QString(
"NIT onid:%1 add ts(%2):%3 %4")
820 .arg(netid).arg(i).arg(tsid).arg(tuning.
toString()));
825 LOG(VB_CHANSCAN, LOG_DEBUG, QString(
"NIT onid:%1 cannot add ts(%2):%3 fr:%4")
826 .arg(netid).arg(i).arg(tsid).arg(frequency));
857 bool transport_tune_complete =
true;
863 QMap<uint,bool> tsid_checked;
864 for (
auto & pat : pattmp)
866 uint tsid = pat->TransportStreamID();
867 if (tsid_checked[tsid])
869 tsid_checked[tsid] =
true;
883 transport_tune_complete =
false;
885 transport_tune_complete &= !pattmp.empty();
918 tsid_checked.clear();
919 for (
auto & sdt : sdttmp)
921 uint tsid = sdt->TSID();
922 if (tsid_checked[tsid])
924 tsid_checked[tsid] =
true;
941 if (transport_tune_complete)
947 transport_tune_complete =
false;
953 transport_tune_complete &=
965 if (transport_tune_complete)
968 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
969 QString(
"\nTable status after transport tune complete:") +
975 QString(
"\nsd->HasCachedAllSDT(%1): %2").arg(tsid,5).arg(sd->
HasCachedAllSDT(tsid)) +
977 QString(
"\nsd->HasCachedMGT(): %1").arg(sd->
HasCachedMGT()) +
989 if (!wait_until_complete)
990 transport_tune_complete =
true;
991 if (transport_tune_complete)
993 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
994 QString(
"transport_tune_complete: wait_until_complete %1").arg(wait_until_complete));
1012 QString msg_tr1 = QObject::tr(
"Program %1").arg(it.key());
1013 QString msg_tr2 = QObject::tr(
"Unknown decryption status");
1015 msg_tr2 = QObject::tr(
"Encrypted");
1017 msg_tr2 = QObject::tr(
"Decrypted");
1018 QString msg_tr =QString(
"%1 %2").arg(msg_tr1, msg_tr2);
1022 QString msg = QString(
"Program %1").arg(it.key());
1024 msg = msg +
" -- Encrypted";
1026 msg = msg +
" -- Decrypted";
1028 msg = msg +
" -- Unknown decryption status";
1030 LOG(VB_CHANSCAN, LOG_INFO,
LOC + msg);
1048 if (transport_tune_complete)
1054 QString chan_tr = QObject::tr(
"%1 -- Timed out").arg(cchan_tr);
1055 QString chan = QString(
"%1 -- Timed out").arg(cchan);
1056 QString msg_tr =
"";
1086 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
1087 QString(
"Adding %1 offset:%2 ss:%3")
1091 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
1092 QString(
"%1(%2) m_inputName: %3 ").arg(__FUNCTION__).arg(__LINE__).arg(
m_inputName) +
1109 msg_tr = (cchan_cnt) ?
1110 QObject::tr(
"%1 possible channels").arg(cchan_cnt) :
1111 QObject::tr(
"no channels");
1112 msg_tr = QString(
"%1, %2").arg(chan_tr, msg_tr);
1114 QString(
"%1 possible channels").arg(cchan_cnt) :
1115 QString(
"no channels");
1116 msg = QString(
"%1, %2").arg(chan_tr, msg);
1119 m_timer.hasExpired((*m_current).m_timeoutTune.count()) &&
1122 msg_tr = QObject::tr(
"%1, no signal").arg(chan_tr);
1123 msg = QString(
"%1, no signal").arg(chan);
1127 msg_tr = QObject::tr(
"%1 -- Found %2 probable channels")
1128 .arg(cchan_tr).arg(cchan_cnt);
1130 msg = QString(
"%1 -- Found %2 probable channels")
1131 .arg(cchan).arg(cchan_cnt);
1135 LOG(VB_CHANSCAN, LOG_INFO,
LOC + msg);
1164 #define PCM_INFO_INIT(SISTD) \
1165 ChannelInsertInfo &info = pnum_to_dbchan[pnum]; \
1166 info.m_dbMplexId = mplexid; info.m_sourceId = m_sourceID; \
1167 info.m_serviceId = pnum; info.m_freqId = freqidStr; \
1168 info.m_siStandard = SISTD;
1208 const QMap<uint64_t, QString> &defAuthorities)
1213 bool force_guide_present = (
1230 QString service_name;
1234 if (callsign.trimmed().isEmpty())
1236 callsign = QString(
"%1-%2-%3")
1242 if (service_name.trimmed().isEmpty())
1243 service_name.clear();
1253 LOG(VB_CHANSCAN, LOG_INFO,
"ChannelScanSM: " +
1254 QString(
"No ServiceDescriptor for onid %1 tid %2 sid %3")
1266 force_guide_present;
1279 const unsigned char *def_auth =
1287 LOG(VB_CHANSCAN, LOG_DEBUG,
1288 QString(
"ChannelScanSM: Found default authority '%1' in SDT for service onid %2 tid %3 sid %4")
1298 uint64_t index = (uint64_t)info.
m_origNetId << 32 |
1300 if (defAuthorities.contains(index))
1308 info.
m_oldTsId = srdesc->OldTransportID();
1311 LOG(VB_CHANSCAN, LOG_DEBUG,
"ChannelScanSM: " +
1312 QString(
"Service '%1' onid:%2 tid:%3 sid:%4 ")
1317 QString(
" relocated from onid:%1 tid:%2 sid:%3")
1328 QString &cur_chan, QString &cur_chan_tr)
const
1333 cur_chan_tr.clear();
1337 uint max_chan_cnt = 0;
1341 for (
const auto & info : qAsConst(list))
1344 (info.m_inPat || info.m_inPmt ||
1345 info.m_inSdt || info.m_inVct) ? 1 : 0;
1351 cur_chan_tr = QString(
"%1%2")
1352 .arg((*m_current).m_friendlyName, offset_str_tr);
1356 cur_chan = QString(
"%1%2")
1357 .arg((*m_current).m_friendlyName, offset_str);
1359 return max_chan_cnt;
1362 QMap<uint,ChannelInsertInfo>
1366 QMap<uint,ChannelInsertInfo> pnum_to_dbchan;
1368 uint mplexid = (*trans_info).m_mplexid;
1369 int freqid = (*trans_info).m_friendlyNum;
1370 QString freqidStr = (freqid) ? QString::number(freqid) : QString(
"");
1371 QString iptv_channel = (*trans_info).m_iptvChannel;
1375 for (
const auto & chan : echan)
1377 uint pnum = chan.m_serviceid;
1379 info.m_serviceName = chan.m_name;
1380 info.m_inChannelsConf =
true;
1384 for (
const auto& pat_list : qAsConst(scan_info->
m_pats))
1386 for (
const auto *pat : pat_list)
1388 bool could_be_opencable =
false;
1389 for (
uint i = 0; i < pat->ProgramCount(); ++i)
1391 if ((pat->ProgramNumber(i) == 0) &&
1394 could_be_opencable =
true;
1398 for (
uint i = 0; i < pat->ProgramCount(); ++i)
1400 uint pnum = pat->ProgramNumber(i);
1404 info.m_patTsId = pat->TransportStreamID();
1405 info.m_couldBeOpencable = could_be_opencable;
1406 info.m_inPat =
true;
1413 for (
const auto *pmt : scan_info->
m_pmts)
1415 uint pnum = pmt->ProgramNumber();
1417 for (
uint i = 0; i < pmt->StreamCount(); ++i)
1419 info.m_couldBeOpencable |=
1424 pmt->ProgramInfo(), pmt->ProgramInfoLength(),
1427 for (
auto & desc : descs)
1434 info.m_couldBeOpencable =
true;
1437 info.m_isEncrypted |= pmt->IsEncrypted(
GetDTVChannel()->GetSIStandard());
1438 info.m_inPmt =
true;
1442 for (
const auto *cvct : scan_info->
m_cvcts)
1444 for (
uint i = 0; i < cvct->ChannelCount(); ++i)
1446 uint pnum = cvct->ProgramNumber(i);
1453 if ((info.m_atscMajorChannel & 0x3F0) == 0x3F0)
1455 info.m_chanNum = QString::number(((info.m_atscMajorChannel & 0x00F) << 10) + info.m_atscMinorChannel);
1459 info.m_chanNum =
kATSCChannelFormat.arg(info.m_atscMajorChannel).arg(info.m_atscMinorChannel);
1465 for (
const auto *tvct : scan_info->
m_tvcts)
1467 for (
uint i = 0; i < tvct->ChannelCount(); ++i)
1469 uint pnum = tvct->ProgramNumber(i);
1472 info.m_chanNum =
kATSCChannelFormat.arg(info.m_atscMajorChannel).arg(info.m_atscMinorChannel);
1477 QString siStandard = (scan_info->
m_mgt ==
nullptr) ?
"dvb" :
"atsc";
1478 for (
const auto& sdt_list : qAsConst(scan_info->
m_sdts))
1480 for (
const auto *sdt_it : sdt_list)
1482 for (
uint i = 0; i < sdt_it->ServiceCount(); ++i)
1484 uint pnum = sdt_it->ServiceID(i);
1492 QMap<qlonglong, uint> ukChanNums;
1493 QMap<qlonglong, uint> scnChanNums;
1494 QMap<uint,ChannelInsertInfo>::iterator dbchan_it;
1495 for (dbchan_it = pnum_to_dbchan.begin();
1496 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1501 for (
const auto *item : scan_info->
m_nits)
1503 for (
uint i = 0; i < item->TransportStreamCount(); ++i)
1525 const unsigned char *desc =
1541 const unsigned char *desc =
1561 const unsigned char *desc =
1603 QMap<uint,qlonglong> lcn_sid;
1605 for (
const auto *bat : scan_info->
m_bats)
1611 for (
uint t = 0;
t < bat->TransportStreamCount(); ++
t)
1613 uint netid = bat->OriginalNetworkID(
t);
1624 bat->TransportDescriptorsLength(
t));
1627 for (
const auto *item : parsed)
1652 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1656 if (lcn_sid.value(lcn,0) == 0)
1657 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1678 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1682 if (lcn_sid.value(lcn,0) == 0)
1683 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1686 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
1687 QString(
"LCN bid:%1 tid:%2 rid:%3 sid:%4 lcn:%5")
1688 .arg(bat->BouquetID()).arg(bat->TSID(
t)).arg(region_id).arg(service_id).arg(lcn));
1700 QMap<qlonglong, uint> sid_lcn;
1701 QMap<uint, qlonglong>::const_iterator r = lcn_sid.constEnd();
1702 while (r != lcn_sid.constBegin())
1705 qlonglong sid = r.value();
1713 for (dbchan_it = pnum_to_dbchan.begin();
1714 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1731 QMap<qlonglong, uint>::const_iterator it = scnChanNums.constFind(key);
1733 if (it != scnChanNums.constEnd())
1743 QMap<qlonglong, uint>::const_iterator it = ukChanNums.constFind(key);
1745 if (it != ukChanNums.constEnd())
1755 QMap<qlonglong, uint>::const_iterator it = sid_lcn.constFind(key);
1757 if (it != sid_lcn.constEnd())
1763 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
1764 QString(
"GetChannelList: service %1 (0x%2) chan_num '%3' callsign '%4'")
1770 for (dbchan_it = pnum_to_dbchan.begin();
1771 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1798 for (dbchan_it = pnum_to_dbchan.begin();
1799 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1806 if (!iptv_channel.isEmpty())
1815 for (dbchan_it = pnum_to_dbchan.begin();
1816 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1818 uint pnum = dbchan_it.key();
1823 return pnum_to_dbchan;
1837 QMap<uint,ChannelInsertInfo> pnum_to_dbchan =
1846 QMap<uint,ChannelInsertInfo>::iterator dbchan_it;
1847 for (dbchan_it = pnum_to_dbchan.begin();
1848 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1860 dbchan_it = pnum_to_dbchan.begin();
1910 list.push_back(item);
1943 #ifdef USING_HDHOMERUN
2001 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"run -- begin");
2011 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"run -- end");
2035 bool was_moving =
false;
2036 bool is_moving =
false;
2038 if (was_moving && !is_moving)
2070 if (
m_timer.hasExpired((*m_current).m_timeoutTune.count()) &&
2098 QMutexLocker locker(&
m_lock);
2151 QString name = QString(
"TransportID %1").arg(it.key() & 0xffff);
2197 return channel->
Tune(tuning,
true);
2216 return channel->
Tune(tuning);
2221 QString offset_str = (transport.
offset()) ?
2222 QObject::tr(
" offset %2").arg(transport.
offset()) :
"";
2223 QString cur_chan = QString(
"%1%2")
2224 .arg((*m_current).m_friendlyName, offset_str);
2225 QString tune_msg_str =
2226 QObject::tr(
"ScanTransport Tuning to %1 mplexid(%2)")
2227 .arg(cur_chan).arg((*m_current).m_mplexid);
2231 if (transport.
offset() &&
2245 LOG(VB_CHANSCAN, LOG_INFO,
LOC + tune_msg_str);
2247 if (!
Tune(transport))
2250 LOG(VB_CHANSCAN, LOG_ERR,
LOC +
2251 QString(
"Failed to tune %1 mplexid(%2) at offset %3")
2253 .arg(transport.
offset()));
2279 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"StopScanner");
2302 const QString &modulation,
2303 const QString &country,
2304 const QString &table_start,
2305 const QString &table_end)
2307 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
2308 QString(
"%1:%2 ").arg(__FUNCTION__).arg(__LINE__) +
2309 QString(
"SourceID:%1 ").arg(
SourceID) +
2310 QString(
"std:%1 ").arg(
std) +
2311 QString(
"modulation:%1 ").arg(modulation) +
2312 QString(
"country:%1 ").arg(country) +
2313 QString(
"table_start:%1 ").arg(table_start) +
2314 QString(
"table_end:%1 ").arg(table_end));
2328 QString msg = QString(
"No freq table for (%1, %2, %3) found")
2329 .arg(
std, modulation, country);
2332 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
2333 QString(
"Looked up freq table (%1, %2, %3) w/%4 entries")
2334 .arg(
std, modulation, country, QString::number(tables.size())));
2336 QString start = table_start;
2337 const QString& end = table_end;
2339 for (
auto it = tables.begin(); it != tables.end(); ++it)
2347 name = strNameFormat;
2348 if (strNameFormat.indexOf(
"%") >= 0)
2349 name = strNameFormat.arg(name_num);
2351 if (start.isEmpty() || name == start)
2359 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"ScanTransports " +
2366 if (!end.isEmpty() && name == end)
2369 if (!end.isEmpty() && name == end)
2373 while (!tables.empty())
2375 delete tables.back();
2392 const QString &cardtype,
2399 tunertype.
Parse(cardtype);
2401 auto it = channels.cbegin();
2402 for (
uint i = 0; it != channels.cend(); ++it, ++i)
2411 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"ScanForChannels " + item.
toString());
2416 LOG(VB_GENERAL, LOG_ERR,
LOC +
"ScanForChannels() no transports");
2436 fbox_chan_map_t::const_iterator Ichan = iptv_channels.begin();
2437 for (
uint idx = 0; Ichan != iptv_channels.end(); ++Ichan, ++idx)
2440 Ichan.value().m_tuning, Ichan.key(),
2445 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"ScanIPTVChannels " + item.
toString());
2450 LOG(VB_GENERAL, LOG_ERR,
LOC +
"ScanIPTVChannels() no transports");
2470 int sourceid,
const QMap<QString,QString> &startChan)
2472 if (startChan.find(
"std") == startChan.end() ||
2473 startChan.find(
"type") == startChan.end())
2478 QString
std = *startChan.find(
"std");
2479 QString si_std = (
std.toLower() !=
"atsc") ?
"dvb" :
"atsc";
2491 ok =
type.Parse(startChan[
"type"]);
2497 startChan[
"frequency"], startChan[
"inversion"],
2498 startChan[
"symbolrate"], startChan[
"fec"],
2499 startChan[
"polarity"],
2500 startChan[
"coderate_hp"], startChan[
"coderate_lp"],
2501 startChan[
"constellation"], startChan[
"trans_mode"],
2502 startChan[
"guard_interval"], startChan[
"hierarchy"],
2503 startChan[
"modulation"], startChan[
"bandwidth"],
2504 startChan[
"mod_sys"], startChan[
"rolloff"]);
2511 sourceid, QObject::tr(
"Frequency %1").arg(startChan[
"frequency"]),
2535 "SELECT sourceid, sistandard, transportid, frequency, modulation, mod_sys "
2536 "FROM dtv_multiplex "
2537 "WHERE mplexid = :MPLEXID");
2547 LOG(VB_GENERAL, LOG_ERR,
LOC +
"AddToList() " +
2548 QString(
"Failed to locate mplexid(%1) in DB").arg(mplexid));
2552 uint sourceid = query.
value(0).toUInt();
2553 QString sistandard = query.
value(1).toString();
2555 uint frequency = query.
value(3).toUInt();
2556 QString modulation = query.
value(4).toString();
2557 QString mod_sys = query.
value(5).toString();
2559 delsys.
Parse(mod_sys);
2561 QString fn = (tsid) ? QString(
"Transport ID %1").arg(tsid) :
2562 QString(
"Multiplex #%1").arg(mplexid);
2564 if (modulation ==
"8vsb")
2566 QString chan = QString(
"%1 Hz").arg(frequency);
2567 int findFrequency = (query.
value(3).toInt() / 1000) - 1750;
2570 if ((list.freq <= findFrequency + 200) &&
2571 (list.freq >= findFrequency - 200))
2573 chan = QString(
"%1").arg(list.name);
2576 fn = QObject::tr(
"ATSC Channel %1").arg(chan);
2584 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
2585 QString(
"tunertype:%1 %2 sourceid:%3 sistandard:%4 fn:'%5' mplexid:%6")
2586 .arg(tt).arg(tt.
toString()).arg(sourceid).arg(sistandard, fn).arg(mplexid));
2590 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"Adding " + fn);
2595 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"Not adding incomplete transport " + fn);
2645 uint mpeg_program_num,
2646 QString &service_name,
2648 QString &common_status_info)
2650 if (channels.empty())
2654 for (
const auto & channel : channels)
2656 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
2657 QString(
"comparing %1 %2 against %3 %4")
2658 .arg(channel.m_serviceid).arg(channel.m_name)
2659 .arg(mpeg_program_num).arg(common_status_info));
2661 if (channel.m_serviceid == mpeg_program_num)
2664 if (!channel.m_name.isEmpty())
2666 service_name = channel.m_name;
2667 callsign = channel.m_name;
2674 common_status_info += QString(
" %1 %2")
2675 .arg(QObject::tr(
"as"), service_name);
2680 QObject::tr(
"Skipping %1, not in imported channel map")
2681 .arg(common_status_info));
virtual std::vector< DTVTunerType > GetTunerTypes(void) const
Returns a vector of supported tuning types.
const MasterGuideTable * m_mgt
bool isActive(void) const
std::vector< const ProgramAssociationTable * > pat_vec_t
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
uint ProgramPID(uint i) const
This table contains information about the channels transmitted on this multiplex.
void AddFlags(uint64_t _flags) override
pat_vec_t GetCachedPATs(uint tsid) const
bat_vec_t GetCachedBATs(bool current=true) const
void start(QThread::Priority p=QThread::InheritPriority)
Tell MThread to start running the thread in the near future.
sdt_vec_t GetCachedSDTs(bool current=true) const
void HandleSDT(uint tsid, const ServiceDescriptionTable *sdt) override
bool IsAccessControlled(uint i) const
static QString GetDisplayName(uint inputid)
uint DescriptorTag(void) const
static const int kTunerTypeDVBC
bool HasCachedAnySDTs(bool current=true) const
void SetDVBService(uint network_id, uint transport_id, int service_id)
const DiSEqCDevRotor * GetRotor(void) const
Returns rotor object if it exists, nullptr otherwise.
void HandleSDTo(uint tsid, const ServiceDescriptionTable *sdt) override
QSet< uint32_t > m_tsScanned
bool HasCachedAllBATs(bool current=true) const
MThread * m_scannerThread
std::vector< const CableVirtualChannelTable * > cvct_vec_t
std::vector< const FrequencyTable * > freq_table_list_t
Freesat Logical Channel Number descriptor.
void Reset(void) override
@ s2_satellite_delivery_system
QMutex m_lock
The big lock.
bool HasCachedAllCVCTs(bool current=true) const
ScanStreamData * GetScanStreamData()
Returns the scan stream data if it exists.
static const std::chrono::milliseconds kMPEGTableTimeout
No logic here, lets just wait at least 15 seconds.
bool wait(std::chrono::milliseconds time=std::chrono::milliseconds::max())
Wait for the MThread to exit, with a maximum timeout.
static const int kTunerTypeDVBS1
bool HasCachedMGT(bool current=true) const
transport_scan_items_it_t m_current
bool FillFromDeliverySystemDesc(DTVTunerType type, const MPEGDescriptor &desc)
const unsigned char * TransportDescriptors(uint i) const
for(j=0;j<N;j++) x 6.0+p { descriptor() }
QMap< uint, pat_vec_t > pat_map_t
cvct_vec_t GetCachedCVCTs(bool current=true) const
std::vector< const TerrestrialVirtualChannelTable * > tvct_vec_t
static const std::array< const uint32_t, 4 > freq
static std::vector< uint > GetMplexIDs(uint sourceid)
@ dvb_simulcast_channel_descriptor
uint TransportDescriptorsLength(uint i) const
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
static const QString kATSCChannelFormat
void ScanPercentComplete(int pct)
static const uint64_t kDTVSigMon_WaitForMGT
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
QVariant value(int i) const
void SetRotorTarget(float target) override
Sets rotor target pos from 0.0 to 1.0.
uint ServiceID(uint i) const
service_id 16 0.0+p
HDHRChannel * GetHDHRChannel(void)
bool m_currentTestingDecryption
QString m_defaultAuthority
MPEGStreamData * GetStreamData()
Returns the MPEG stream data if it exists.
int GetSignalStrength(void)
uint LogicalChannelNumber(size_t i, size_t j) const
QString ShortChannelName(uint i) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
transport_scan_items_t m_scanTransports
void SetAnalog(bool is_analog)
uint ProgramNumber(void) const
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
std::chrono::milliseconds m_otherTableTimeout
IPTVTuningData m_iptvTuning
DVB Logical Channel Descriptor.
bool Tune(transport_scan_items_it_t transport)
void run(void) override
This runs the event loop for ChannelScanSM until 'threadExit' is true.
unsigned long long FrequencyHz(void) const
std::chrono::milliseconds m_signalTimeout
uint ProgramCount(void) const
std::vector< const BouquetAssociationTable * > bat_vec_t
virtual bool Tune(const DTVMultiplex &tuning)=0
This performs the actual frequency tuning and in some cases input switching.
void SetPMT(const ProgramMapTable *pmt)
Tells the Conditional Access Module which streams we wish to decode.
uint ProgramNumber(uint i) const
bool IsEncrypted(const QString &sistandard) const
Returns true iff PMT contains CA descriptor for a vid/aud stream.
bool IsHiddenInGuide(uint i) const
#define PCM_INFO_INIT(SISTD)
QString toString(void) const override
static QString GetUnknownCallsign(void)
QMap< uint, sdt_vec_t > sdt_map_t
bool HasCachedAllTVCTs(bool current=true) const
ScannedChannelInfo()=default
ScanMonitor * m_scanMonitor
uint ChannelNumber(uint i) const
QString FormatIdentifierString(void) const
virtual bool FillFromDB(DTVTunerType type, uint mplexid)
VERBOSE_PREAMBLE Most true
void StopScanner(void)
Stops the ChannelScanSM event loop and the signal monitor, blocking until both exit.
void GetRotorStatus(bool &was_moving, bool &is_moving) override
std::chrono::milliseconds m_otherTableTime
bool IsHidden(uint i) const
@ kModulationSystem_UNDEFINED
bool ScanTransports(int SourceID, const QString &std, const QString &mod, const QString &country, const QString &table_start=QString(), const QString &table_end=QString())
Generates a list of frequencies to scan and adds it to the scanTransport list, and then sets the scan...
virtual void ReturnCachedPATTables(pat_vec_t &pats) const
uint RegionID(size_t i, size_t j) const
uint ChannelTransportStreamID(uint i) const
static const unsigned char * FindExtension(const desc_list_t &parsed, uint desc_tag)
V4LChannel * GetV4LChannel(void)
@ terrestrial_delivery_system
bool HasCachedAllPMTs(void) const
std::vector< const ProgramMapTable * > pmt_vec_t
static const std::chrono::milliseconds kDVBTableTimeout
SDT's should be sent every 2 seconds and NIT's every 10 seconds, so lets wait at least 30 seconds,...
uint MajorChannel(uint i) const
void StartScanner(void)
Starts the ChannelScanSM event loop.
bool HasCachedAllSDT(uint tsid, bool current=true) const
IPTVTuningData m_iptvTuning
QString ServiceName(void) const
std::vector< DTVTransport > DTVChannelList
uint ServiceCount() const
Number of services.
nit_const_ptr_t GetCachedNIT(uint section_num, bool current=true) const
void HandleActiveScan(void)
Handles the TRANSPORT_LIST ChannelScanSM mode.
void HandleNIT(const NetworkInformationTable *nit) override
ServiceDescriptor * GetServiceDescriptor(uint i) const
static const uint64_t kDVBSigMon_WaitForPos
Wait for rotor to complete turning the antenna.
Abstract class providing a generic interface to tuning hardware.
bool HasCachedAnyPAT(uint tsid) const
std::vector< const ServiceDescriptionTable * > sdt_vec_t
static desc_list_t Parse(const unsigned char *data, uint len)
Class used for doing a list of frequencies / transports.
QString toString(void) const override
AnalogSignalHandler * m_analogSignalHandler
QString toString(void) const override
std::list< TransportScanItem >::iterator iter()
uint ChannelCount(void) const
uint OriginalNetworkID() const
original_network_id 16 8.0
static uint FindChannel(uint sourceid, const QString &freqid)
QMap< uint32_t, DTVMultiplex > m_extendTransports
static const int kTunerTypeUnknown
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
std::vector< DTVChannelInfo > DTVChannelInfoList
static void DBError(const QString &where, const MSqlQuery &query)
static const uint64_t kDTVSigMon_WaitForNIT
void HandlePAT(const ProgramAssociationTable *pat) override
void HandleEncryptionStatus(uint pnum, bool encrypted) override
bool teardown_frequency_tables(void)
static const uint64_t kDTVSigMon_WaitForSDT
uint ChannelNumber(uint i) const
std::vector< const unsigned char * > desc_list_t
uint OriginalNetworkID(uint i) const
bool HasCachedAllNIT(bool current=true) const
DVBStreamData * GetDVBStreamData()
Returns the DVB stream data if it exists.
static desc_list_t ParseOnlyInclude(const unsigned char *data, uint len, int excluded_descid)
This table tells the decoder on which PIDs to find A/V data.
ChannelScanSM(ScanMonitor *scan_monitor, const QString &cardtype, ChannelBase *channel, int sourceID, std::chrono::milliseconds signal_timeout, std::chrono::milliseconds channel_timeout, QString inputname, bool test_decryption)
pmt_vec_t GetCachedPMTs(void) const
Sky Logical Channel Number descriptor.
QString toString(void) const override
void HandleBAT(const BouquetAssociationTable *bat) override
uint32_t PrivateDataSpecifier(void) const
DVB HD Simulcast Logical Channel Descriptor.
bool UpdateChannelInfo(bool wait_until_complete)
static int CreateChanID(uint sourceid, const QString &chan_num)
Creates a unique channel ID for database use.
DTVModulationSystem m_modSys
uint DescriptorTagExtension(void) const
void UpdateScanTransports(uint frequency, const NetworkInformationTable *nit)
transport_scan_items_it_t m_nextIt
void ResetDecryptionMonitoringState(void)
bool HasCachedAnyBATs(bool current=true) const
Scanning class for cards that support a SignalMonitor class.
@ dvb_logical_channel_descriptor
uint GetCurrentTransportInfo(QString &chan, QString &chan_tr) const
std::vector< ScanDTVTransport > ScanDTVTransportList
DTVTunerType m_scanDTVTunerType
void HandlePMT(uint program_num, const ProgramMapTable *pmt) override
uint GetNetworkID(void) const
The Program Association Table lists all the programs in a stream, and is always found on PID 0.
uint GetTransportID(void) const
DVBSignalMonitor * GetDVBSignalMonitor(void)
static QString loc(const ChannelScanSM *siscan)
uint LastSection(void) const
void ScanAppendTextToLog(const QString &status)
uint ServiceType(void) const
Signal monitoring base class.
tvct_vec_t GetCachedTVCTs(bool current=true) const
void HandleMGT(const MasterGuideTable *mgt) override
freq_table_list_t get_matching_freq_tables(const QString &format, const QString &modulation, const QString &country)
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)
uint ServiceCount(void) const
volatile bool m_threadExit
static const int kTunerTypeDVBS2
bool ScanIPTVChannels(uint sourceid, const fbox_chan_map_t &iptv_channels)
uint ServiceID(uint i) const
DTVSignalMonitor * GetDTVSignalMonitor(void)
bool IsEncrypted(uint i) const
free_CA_mode 1 3.3+p
This table tells the decoder on which PIDs to find other tables, and their sizes and each table's cur...
const CHANLISTS_vec gChanLists
DTVTunerType GuessDTVTunerType(DTVTunerType type) const
uint64_t freq_offset(uint i) const
Provides interface to the tuning hardware when using DVB drivers.
std::chrono::milliseconds m_channelTimeout
bool AddToList(uint mplexid)
virtual void ReturnCachedPMTTables(pmt_vec_t &pmts) const
DVBChannel * GetDVBChannel(void)
uint TransportStreamCount(void) const
Tells what channels can be found on each transponder for one bouquet (a bunch of channels from one pr...
bool HasEITPresentFollowing(uint i) const
QString toString(void) const override
void SetChannel(int major, int minor)
ScannedChannelInfo * m_currentInfo
virtual bool TuneMultiplex(uint mplexid, const QString &inputname)
To be used by the channel scanner and possibly the EIT scanner.
void HandleVCT(uint tsid, const VirtualChannelTable *vct) override
std::vector< const NetworkInformationTable * > nit_vec_t
void AddListener(SignalMonitorListener *listener)
QString ServiceShortName(void) const
uint ServiceID(uint i) const
QMap< uint64_t, QString > m_defAuthorities
static const uint kRegionUndefined
QString toString(void) const override
void RemoveListener(SignalMonitorListener *listener)
uint LogicalChannelNumber(size_t i) const
uint ServiceType(uint i) const
static const std::chrono::milliseconds kATSCTableTimeout
No logic here, lets just wait at least 10 seconds.
SignalMonitor * m_signalMonitor
ChannelList m_channelList
Found Channel Info.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
virtual void SetStreamData(MPEGStreamData *data)
Sets the MPEG stream data for DTVSignalMonitor to use, and connects the table signals to the monitor.
uint64_t FrequencyHz(void) const
uint ChannelCount(void) const
bool ScanCurrentTransport(const QString &sistandard)
ServiceRelocatedDescriptor * GetServiceRelocatedDescriptor(uint i) const
The CAT is used to transmit additional ConditionalAccessDescriptor instances, in addition to the ones...
bool Parse(const QString &_value)
uint ServiceDescriptorsLength(uint i) const
desc_loop_length 12 3.4+p
This is a wrapper around QThread that does several additional things.
bool ParseTuningParams(DTVTunerType type, const QString &frequency, const QString &inversion, const QString &symbolrate, const QString &fec, const QString &polarity, const QString &hp_code_rate, const QString &lp_code_rate, const QString &ofdm_modulation, const QString &trans_mode, const QString &guard_interval, const QString &hierarchy, const QString &modulation, const QString &bandwidth, const QString &mod_sys, const QString &rolloff)
This class is intended to detect the presence of needed tables.
virtual int GetInputID(void) const
uint ServiceCount(void) const
bool HasCachedAnyPMTs(void) const
QMap< uint, uint > m_programEncryptionStatus
virtual void Start()
Start signal monitoring thread.
bool TestNextProgramEncryption(void)
uint LCNCount(size_t i) const
static const int kTunerTypeASI
bool HasCachedAllPAT(uint tsid) const
static DTVTunerType ConvertToTunerType(DTVModulationSystem delsys)
static const int kTunerTypeATSC
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
static void LogLines(const QString &string)
@ OpenCableVideo
Always MPEG-2??
Class providing a generic interface to digital tuning hardware.
uint ServiceID(size_t i) const
bool HasEITSchedule(uint i) const
void HandleCAT(const ConditionalAccessTable *cat) override
bool HasSignalLock(void) const
Returns true iff scriptStatus.IsGood() and signalLock.IsGood() return true.
static void update_info(ChannelInsertInfo &info, const VirtualChannelTable *vct, uint i)
@ kModulationSystem_DVBT2
static const int kTunerTypeDVBT
bool HasCachedAnyNIT(bool current=true) const
bool HasCachedAnyVCTs(bool current=true) const
uint RegionID(void) const
bool ScanTransportsStartingOn(int sourceid, const QMap< QString, QString > &startChan)
Generates a list of frequencies to scan and adds it to the scanTransport list, and then sets the scan...
uint ServiceID(size_t i) const
virtual void Stop()
Stop signal monitoring thread.
uint ModulationMode(uint i) const
static const unsigned char * Find(const desc_list_t &parsed, uint desc_tag)
chan_info_map_t GetChannelList(transport_scan_items_it_t trans_info, ScannedChannelInfo *scan_info) const
void ScanUpdateStatusText(const QString &status)
DTVChannel * GetDTVChannel(void)
static constexpr qint64 kDecryptionTimeout
static const int kTunerTypeDVBT2
bool ScanTransport(uint mplexid, bool follow_nit)
uint ChannelCount() const
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
bool ScanExistingTransports(uint sourceid, bool follow_nit)
If we are not already scanning a frequency table, this creates a new frequency table from database an...
IPTVProtocol GetProtocol(void) const
@ satellite_delivery_system
uint TransportStreamID() const
uint64_t FrequencykHz(void) const
QMap< QString, IPTVChannelInfo > fbox_chan_map_t
~ChannelScanSM() override
void ReturnCachedSDTTables(sdt_vec_t &sdts) const
void TestDecryption(const ProgramMapTable *pmt)
uint64_t m_frequencyStart
QMap< uint, uint > m_currentEncryptionStatus
bool CheckImportedList(const DTVChannelInfoList &channels, uint mpeg_program_num, QString &service_name, QString &callsign, QString &common_status_info)
If we are scanning a dvb-utils import verify channel is in list.
const unsigned char * ServiceDescriptors(uint i) const
for (j=0;j<N;j++) x 5.0+p { descriptor() }
const MasterGuideTable * GetCachedMGT(bool current=true) const
QPair< transport_scan_items_it_t, ScannedChannelInfo * > ChannelListItem
QMap< uint, bool > m_currentEncryptionStatusChecked
bool IsDigitalAudio(void) const
transport_scan_items_it_t nextTransport() const
uint TSID() const
transport_stream_id 16 3.0 0x0000
uint MinorChannel(uint i) const
void UpdateScanPercentCompleted(void)
static const uint64_t kDTVSigMon_WaitForVCT
bool ScanForChannels(uint sourceid, const QString &std, const QString &cardtype, const DTVChannelList &channels)
uint ServiceID(uint i) const
ChannelInsertInfoList m_channels
@ kModulationSystem_DVBC_ANNEX_A
uint ServiceCount(void) const
QString DefaultAuthority(void) const
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
bool Parse(const QString &_value)
SignalMonitor * GetSignalMonitor(void)
sdt_vec_t GetCachedSDTSections(uint tsid, bool current=true) const
QString GetExtendedChannelName(uint idx) const
void ScanUpdateStatusTitleText(const QString &status)