Go to the documentation of this file.
38 #include <QMutexLocker>
86 return "ChannelScanSM(u)";
89 #define LOC (ChannelScanSM::loc(this) + ": ")
91 #define kDecryptionTimeout 4250
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);
1163 #define PCM_INFO_INIT(SISTD) \
1164 ChannelInsertInfo &info = pnum_to_dbchan[pnum]; \
1165 info.m_dbMplexId = mplexid; info.m_sourceId = m_sourceID; \
1166 info.m_serviceId = pnum; info.m_freqId = freqidStr; \
1167 info.m_siStandard = SISTD;
1207 const QMap<uint64_t, QString> &defAuthorities)
1212 bool force_guide_present = (
1229 QString service_name;
1233 if (callsign.trimmed().isEmpty())
1235 callsign = QString(
"%1-%2-%3")
1241 if (service_name.trimmed().isEmpty())
1242 service_name.clear();
1252 LOG(VB_CHANSCAN, LOG_INFO,
"ChannelScanSM: " +
1253 QString(
"No ServiceDescriptor for onid %1 tid %2 sid %3")
1265 force_guide_present;
1278 const unsigned char *def_auth =
1286 LOG(VB_CHANSCAN, LOG_DEBUG,
1287 QString(
"ChannelScanSM: Found default authority '%1' in SDT for service onid %2 tid %3 sid %4")
1297 uint64_t index = (uint64_t)info.
m_origNetId << 32 |
1299 if (defAuthorities.contains(index))
1307 info.
m_oldTsId = srdesc->OldTransportID();
1310 LOG(VB_CHANSCAN, LOG_DEBUG,
"ChannelScanSM: " +
1311 QString(
"Service '%1' onid:%2 tid:%3 sid:%4 ")
1316 QString(
" relocated from onid:%1 tid:%2 sid:%3")
1327 QString &cur_chan, QString &cur_chan_tr)
const
1332 cur_chan_tr.clear();
1336 uint max_chan_cnt = 0;
1340 for (
const auto & info : qAsConst(list))
1343 (info.m_inPat || info.m_inPmt ||
1344 info.m_inSdt || info.m_inVct) ? 1 : 0;
1350 cur_chan_tr = QString(
"%1%2")
1351 .arg((*m_current).m_friendlyName, offset_str_tr);
1355 cur_chan = QString(
"%1%2")
1356 .arg((*m_current).m_friendlyName, offset_str);
1358 return max_chan_cnt;
1361 QMap<uint,ChannelInsertInfo>
1365 QMap<uint,ChannelInsertInfo> pnum_to_dbchan;
1367 uint mplexid = (*trans_info).m_mplexid;
1368 int freqid = (*trans_info).m_friendlyNum;
1369 QString freqidStr = (freqid) ? QString::number(freqid) : QString(
"");
1370 QString iptv_channel = (*trans_info).m_iptvChannel;
1374 for (
const auto & chan : echan)
1376 uint pnum = chan.m_serviceid;
1378 info.m_serviceName = chan.m_name;
1379 info.m_inChannelsConf =
true;
1383 for (
const auto& pat_list : qAsConst(scan_info->
m_pats))
1385 for (
const auto *pat : pat_list)
1387 bool could_be_opencable =
false;
1388 for (
uint i = 0; i < pat->ProgramCount(); ++i)
1390 if ((pat->ProgramNumber(i) == 0) &&
1393 could_be_opencable =
true;
1397 for (
uint i = 0; i < pat->ProgramCount(); ++i)
1399 uint pnum = pat->ProgramNumber(i);
1403 info.m_patTsId = pat->TransportStreamID();
1404 info.m_couldBeOpencable = could_be_opencable;
1405 info.m_inPat =
true;
1412 for (
const auto *pmt : scan_info->
m_pmts)
1414 uint pnum = pmt->ProgramNumber();
1416 for (
uint i = 0; i < pmt->StreamCount(); ++i)
1418 info.m_couldBeOpencable |=
1423 pmt->ProgramInfo(), pmt->ProgramInfoLength(),
1426 for (
auto & desc : descs)
1433 info.m_couldBeOpencable =
true;
1436 info.m_isEncrypted |= pmt->IsEncrypted(
GetDTVChannel()->GetSIStandard());
1437 info.m_inPmt =
true;
1441 for (
const auto *cvct : scan_info->
m_cvcts)
1443 for (
uint i = 0; i < cvct->ChannelCount(); ++i)
1445 uint pnum = cvct->ProgramNumber(i);
1452 if ((info.m_atscMajorChannel & 0x3F0) == 0x3F0)
1454 info.m_chanNum = QString::number(((info.m_atscMajorChannel & 0x00F) << 10) + info.m_atscMinorChannel);
1458 info.m_chanNum =
kATSCChannelFormat.arg(info.m_atscMajorChannel).arg(info.m_atscMinorChannel);
1464 for (
const auto *tvct : scan_info->
m_tvcts)
1466 for (
uint i = 0; i < tvct->ChannelCount(); ++i)
1468 uint pnum = tvct->ProgramNumber(i);
1471 info.m_chanNum =
kATSCChannelFormat.arg(info.m_atscMajorChannel).arg(info.m_atscMinorChannel);
1476 QString siStandard = (scan_info->
m_mgt ==
nullptr) ?
"dvb" :
"atsc";
1477 for (
const auto& sdt_list : qAsConst(scan_info->
m_sdts))
1479 for (
const auto *sdt_it : sdt_list)
1481 for (
uint i = 0; i < sdt_it->ServiceCount(); ++i)
1483 uint pnum = sdt_it->ServiceID(i);
1491 QMap<qlonglong, uint> ukChanNums;
1492 QMap<qlonglong, uint> scnChanNums;
1493 QMap<uint,ChannelInsertInfo>::iterator dbchan_it;
1494 for (dbchan_it = pnum_to_dbchan.begin();
1495 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1500 for (
const auto *item : scan_info->
m_nits)
1502 for (
uint i = 0; i < item->TransportStreamCount(); ++i)
1524 const unsigned char *desc =
1540 const unsigned char *desc =
1560 const unsigned char *desc =
1602 QMap<uint,qlonglong> lcn_sid;
1604 for (
const auto *bat : scan_info->
m_bats)
1610 for (
uint t = 0;
t < bat->TransportStreamCount(); ++
t)
1612 uint netid = bat->OriginalNetworkID(
t);
1623 bat->TransportDescriptorsLength(
t));
1626 for (
const auto *item : parsed)
1651 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1655 if (lcn_sid.value(lcn,0) == 0)
1656 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1677 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1681 if (lcn_sid.value(lcn,0) == 0)
1682 lcn_sid[lcn] = ((qlonglong)netid<<32) | service_id;
1685 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
1686 QString(
"LCN bid:%1 tid:%2 rid:%3 sid:%4 lcn:%5")
1687 .arg(bat->BouquetID()).arg(bat->TSID(
t)).arg(region_id).arg(service_id).arg(lcn));
1699 QMap<qlonglong, uint> sid_lcn;
1700 QMap<uint, qlonglong>::const_iterator r = lcn_sid.constEnd();
1701 while (r != lcn_sid.constBegin())
1704 qlonglong sid = r.value();
1712 for (dbchan_it = pnum_to_dbchan.begin();
1713 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1730 QMap<qlonglong, uint>::const_iterator it = scnChanNums.constFind(key);
1732 if (it != scnChanNums.constEnd())
1742 QMap<qlonglong, uint>::const_iterator it = ukChanNums.constFind(key);
1744 if (it != ukChanNums.constEnd())
1754 QMap<qlonglong, uint>::const_iterator it = sid_lcn.constFind(key);
1756 if (it != sid_lcn.constEnd())
1762 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
1763 QString(
"GetChannelList: service %1 (0x%2) chan_num '%3' callsign '%4'")
1769 for (dbchan_it = pnum_to_dbchan.begin();
1770 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1797 for (dbchan_it = pnum_to_dbchan.begin();
1798 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1805 if (!iptv_channel.isEmpty())
1814 for (dbchan_it = pnum_to_dbchan.begin();
1815 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1817 uint pnum = dbchan_it.key();
1822 return pnum_to_dbchan;
1836 QMap<uint,ChannelInsertInfo> pnum_to_dbchan =
1845 QMap<uint,ChannelInsertInfo>::iterator dbchan_it;
1846 for (dbchan_it = pnum_to_dbchan.begin();
1847 dbchan_it != pnum_to_dbchan.end(); ++dbchan_it)
1859 dbchan_it = pnum_to_dbchan.begin();
1909 list.push_back(item);
1942 #ifdef USING_HDHOMERUN
2000 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"run -- begin");
2010 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"run -- end");
2034 bool was_moving =
false;
2035 bool is_moving =
false;
2037 if (was_moving && !is_moving)
2069 if (
m_timer.hasExpired((*m_current).m_timeoutTune.count()) &&
2097 QMutexLocker locker(&
m_lock);
2150 QString name = QString(
"TransportID %1").arg(it.key() & 0xffff);
2196 return channel->
Tune(tuning,
true);
2215 return channel->
Tune(tuning);
2220 QString offset_str = (transport.
offset()) ?
2221 QObject::tr(
" offset %2").arg(transport.
offset()) :
"";
2222 QString cur_chan = QString(
"%1%2")
2223 .arg((*m_current).m_friendlyName, offset_str);
2224 QString tune_msg_str =
2225 QObject::tr(
"ScanTransport Tuning to %1 mplexid(%2)")
2226 .arg(cur_chan).arg((*m_current).m_mplexid);
2230 if (transport.
offset() &&
2244 LOG(VB_CHANSCAN, LOG_INFO,
LOC + tune_msg_str);
2246 if (!
Tune(transport))
2249 LOG(VB_CHANSCAN, LOG_ERR,
LOC +
2250 QString(
"Failed to tune %1 mplexid(%2) at offset %3")
2252 .arg(transport.
offset()));
2278 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"StopScanner");
2301 const QString &modulation,
2302 const QString &country,
2303 const QString &table_start,
2304 const QString &table_end)
2306 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
2307 QString(
"%1:%2 ").arg(__FUNCTION__).arg(__LINE__) +
2308 QString(
"SourceID:%1 ").arg(
SourceID) +
2309 QString(
"std:%1 ").arg(
std) +
2310 QString(
"modulation:%1 ").arg(modulation) +
2311 QString(
"country:%1 ").arg(country) +
2312 QString(
"table_start:%1 ").arg(table_start) +
2313 QString(
"table_end:%1 ").arg(table_end));
2327 QString msg = QString(
"No freq table for (%1, %2, %3) found")
2328 .arg(
std, modulation, country);
2331 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
2332 QString(
"Looked up freq table (%1, %2, %3) w/%4 entries")
2333 .arg(
std, modulation, country, QString::number(tables.size())));
2335 QString start = table_start;
2336 const QString& end = table_end;
2338 for (
auto it = tables.begin(); it != tables.end(); ++it)
2346 name = strNameFormat;
2347 if (strNameFormat.indexOf(
"%") >= 0)
2348 name = strNameFormat.arg(name_num);
2350 if (start.isEmpty() || name == start)
2358 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"ScanTransports " +
2365 if (!end.isEmpty() && name == end)
2368 if (!end.isEmpty() && name == end)
2372 while (!tables.empty())
2374 delete tables.back();
2391 const QString &cardtype,
2398 tunertype.
Parse(cardtype);
2400 auto it = channels.cbegin();
2401 for (
uint i = 0; it != channels.cend(); ++it, ++i)
2410 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"ScanForChannels " + item.
toString());
2415 LOG(VB_GENERAL, LOG_ERR,
LOC +
"ScanForChannels() no transports");
2435 fbox_chan_map_t::const_iterator Ichan = iptv_channels.begin();
2436 for (
uint idx = 0; Ichan != iptv_channels.end(); ++Ichan, ++idx)
2439 Ichan.value().m_tuning, Ichan.key(),
2444 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"ScanIPTVChannels " + item.
toString());
2449 LOG(VB_GENERAL, LOG_ERR,
LOC +
"ScanIPTVChannels() no transports");
2469 int sourceid,
const QMap<QString,QString> &startChan)
2471 if (startChan.find(
"std") == startChan.end() ||
2472 startChan.find(
"type") == startChan.end())
2477 QString
std = *startChan.find(
"std");
2478 QString si_std = (
std.toLower() !=
"atsc") ?
"dvb" :
"atsc";
2490 ok =
type.Parse(startChan[
"type"]);
2496 startChan[
"frequency"], startChan[
"inversion"],
2497 startChan[
"symbolrate"], startChan[
"fec"],
2498 startChan[
"polarity"],
2499 startChan[
"coderate_hp"], startChan[
"coderate_lp"],
2500 startChan[
"constellation"], startChan[
"trans_mode"],
2501 startChan[
"guard_interval"], startChan[
"hierarchy"],
2502 startChan[
"modulation"], startChan[
"bandwidth"],
2503 startChan[
"mod_sys"], startChan[
"rolloff"]);
2510 sourceid, QObject::tr(
"Frequency %1").arg(startChan[
"frequency"]),
2534 "SELECT sourceid, sistandard, transportid, frequency, modulation, mod_sys "
2535 "FROM dtv_multiplex "
2536 "WHERE mplexid = :MPLEXID");
2546 LOG(VB_GENERAL, LOG_ERR,
LOC +
"AddToList() " +
2547 QString(
"Failed to locate mplexid(%1) in DB").arg(mplexid));
2551 uint sourceid = query.
value(0).toUInt();
2552 QString sistandard = query.
value(1).toString();
2554 uint frequency = query.
value(3).toUInt();
2555 QString modulation = query.
value(4).toString();
2556 QString mod_sys = query.
value(5).toString();
2558 delsys.
Parse(mod_sys);
2560 QString fn = (tsid) ? QString(
"Transport ID %1").arg(tsid) :
2561 QString(
"Multiplex #%1").arg(mplexid);
2563 if (modulation ==
"8vsb")
2565 QString chan = QString(
"%1 Hz").arg(frequency);
2566 int findFrequency = (query.
value(3).toInt() / 1000) - 1750;
2569 if ((list.freq <= findFrequency + 200) &&
2570 (list.freq >= findFrequency - 200))
2572 chan = QString(
"%1").arg(list.name);
2575 fn = QObject::tr(
"ATSC Channel %1").arg(chan);
2583 LOG(VB_CHANSCAN, LOG_DEBUG,
LOC +
2584 QString(
"tunertype:%1 %2 sourceid:%3 sistandard:%4 fn:'%5' mplexid:%6")
2585 .arg(tt).arg(tt.
toString()).arg(sourceid).arg(sistandard, fn).arg(mplexid));
2589 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"Adding " + fn);
2594 LOG(VB_CHANSCAN, LOG_INFO,
LOC +
"Not adding incomplete transport " + fn);
2644 uint mpeg_program_num,
2645 QString &service_name,
2647 QString &common_status_info)
2649 if (channels.empty())
2653 for (
const auto & channel : channels)
2655 LOG(VB_GENERAL, LOG_DEBUG,
LOC +
2656 QString(
"comparing %1 %2 against %3 %4")
2657 .arg(channel.m_serviceid).arg(channel.m_name)
2658 .arg(mpeg_program_num).arg(common_status_info));
2660 if (channel.m_serviceid == mpeg_program_num)
2663 if (!channel.m_name.isEmpty())
2665 service_name = channel.m_name;
2666 callsign = channel.m_name;
2673 common_status_info += QString(
" %1 %2")
2674 .arg(QObject::tr(
"as"), service_name);
2679 QObject::tr(
"Skipping %1, not in imported channel map")
2680 .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
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)
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 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)
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
uint LCNCount(int i) 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 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)
#define kDecryptionTimeout
uint ServiceID(int i) const
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.
unsigned long long FrequencykHz(void) const
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)
uint ServiceCount(void) const
uint ServiceID(int i) 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
uint RegionID(int i, int j) const
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)
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
ScannedChannelInfo * m_currentInfo
uint LogicalChannelNumber(int i) const
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 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)
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.
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...
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 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
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
uint LogicalChannelNumber(int i, int j) const
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)