40#include <sys/select.h>
64 DTVTunerType tuner_type,
const dvb_frontend_parameters& params);
67 uint intermediate_freq,
bool can_fec_auto,
bool do_tune =
true);
72#define LOC QString("DVBChan[%1](%2): ").arg(m_inputId).arg(DVBChannel::GetDevice())
75#define DTV_STAT_FULL_DEBUG 0
83 :
DTVChannel(parent), m_device(std::move(aDevice))
88 m_key += QString(
":%1")
98 else if (master !=
nullptr)
122 QMutexLocker master_locker(&(master->m_hwLock));
123 QMutexLocker new_master_locker(&(new_master->
m_hwLock));
124 new_master->
m_isOpen = master->m_isOpen;
148 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Closing DVB channel");
152 IsOpenMap::iterator it =
m_isOpen.find(who);
159 if (master !=
nullptr && master !=
this)
193 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Opening DVB channel");
198 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Use legacy DVBv3 API");
212 if (!master->
Open(who))
250 QByteArray devn = dvbdev.toLatin1();
252 for (
int tries = 1; ; ++tries)
259 LOG(VB_GENERAL, LOG_WARNING,
LOC +
260 "Opening DVB frontend device failed." +
ENO);
262 if (tries >= 5 || (errno != EBUSY && errno != EAGAIN))
264 LOG(VB_GENERAL, LOG_ERR,
LOC +
265 QString(
"Failed to open DVB frontend device due to "
266 "fatal error or too many attempts."));
269 std::this_thread::sleep_for(50ms);
274 dvb_frontend_info
info {};
277 LOG(VB_GENERAL, LOG_ERR,
LOC +
278 "Failed to get frontend information." +
ENO);
292 LOG(VB_CHANNEL, LOG_INFO,
LOC +
296 LOG(VB_CHANNEL, LOG_INFO, QString(
" %1").arg(capstr));
301 std::array<struct dtv_property,2> prop = {};
302 struct dtv_properties cmd = {};
304 prop[0].cmd = DTV_API_VERSION;
305 prop[1].cmd = DTV_DELIVERY_SYSTEM;
308 cmd.props = prop.data();
312 prop[0].u.data = 0x300;
313 prop[1].u.data = SYS_UNDEFINED;
339 if (
info.caps & FE_CAN_2G_MODULATION)
344 if (
info.caps & FE_CAN_TURBO_FEC)
359 if (
info.caps & FE_CAN_2G_MODULATION)
366 if (
info.caps & (FE_CAN_8VSB | FE_CAN_16VSB))
371 if (
info.caps & (FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO))
373 delsys = SYS_DVBC_ANNEX_B;
381 LOG(VB_GENERAL, LOG_ERR,
LOC +
382 QString(
"Frontend '%1' delivery system not detected.").arg(
m_frontendName));
391 std::array<struct dtv_property,1> prop = {};
392 struct dtv_properties cmd = {};
394 prop[0].cmd = DTV_ENUM_DELSYS;
397 cmd.props = prop.data();
401 LOG(VB_GENERAL, LOG_ERR,
LOC +
402 QString(
"Frontend '%1' FE_GET_PROPERTY failed.").arg(
m_frontendName));
407 int p_num_systems = prop[0].u.buffer.len;
408 for (
int i = 0; i < p_num_systems; i++)
414 if (p_num_systems == 0) {
415 LOG(VB_GENERAL, LOG_ERR,
LOC +
416 QString(
"Frontend '%1' returned 0 supported delivery systems!").arg(
m_frontendName));
426 LOG(VB_CHANNEL, LOG_INFO,
LOC +
428 LOG(VB_CHANNEL, LOG_INFO,
LOC +
429 QString(
"DVB version:0x%1 ").arg(
m_version,3,16,QChar(
'0')) +
434 LOG(VB_CHANNEL, LOG_INFO,
"Supported delivery systems: ");
439 LOG(VB_CHANNEL, LOG_INFO, QString(
" [%1]")
440 .arg(delsys.toString()));
444 LOG(VB_CHANNEL, LOG_INFO, QString(
" %1")
445 .arg(delsys.toString()));
449 uint32_t frq_min =
info.frequency_min;
450 uint32_t frq_max =
info.frequency_max;
451 uint32_t frq_stp =
info.frequency_stepsize;
453 if (
info.type == FE_QPSK)
461 LOG(VB_CHANNEL, LOG_INFO, QString(
"Frequency range for the current standard:"));
462 LOG(VB_CHANNEL, LOG_INFO, QString(
" From: %1 Hz").arg(frq_min,11));
463 LOG(VB_CHANNEL, LOG_INFO, QString(
" To: %1 Hz").arg(frq_max,11));
464 LOG(VB_CHANNEL, LOG_INFO, QString(
" Step: %1 Hz").arg(frq_stp,11));
466 if (
info.type == FE_QPSK ||
info.type == FE_QAM)
468 LOG(VB_CHANNEL, LOG_INFO, QString(
"Symbol rate ranges for the current standard:"));
469 LOG(VB_CHANNEL, LOG_INFO, QString(
" From: %1 Baud").arg(
info.symbol_rate_min,11));
470 LOG(VB_CHANNEL, LOG_INFO, QString(
" To: %1 Baud").arg(
info.symbol_rate_max,11));
483 LOG(VB_CHANNEL, LOG_INFO,
LOC +
484 QString(
"Change delivery system from %1 to %2.")
493 LOG(VB_CHANNEL, LOG_INFO,
LOC +
494 QString(
"Delivery system in database and in card equal, leave at %1.")
500 LOG(VB_CHANNEL, LOG_INFO,
LOC +
518 LOG(VB_CHANNEL, LOG_INFO,
LOC +
519 QString(
"Requested %1 channel is on SCR system")
524 LOG(VB_CHANNEL, LOG_INFO,
LOC +
525 QString(
"Requested %1 channel is on non-SCR system")
550 IsOpenMap::const_iterator it =
m_isOpen.find(
this);
571 LOG(VB_GENERAL, LOG_WARNING,
LOC +
572 QString(
"Frequency setting (%1) is out of range (min/max:%2/%3)")
582 LOG(VB_GENERAL, LOG_WARNING,
LOC +
583 "'Auto' inversion parameter unsupported by this driver, "
584 "falling back to 'off'.");
603 LOG(VB_GENERAL, LOG_WARNING,
LOC +
604 QString(
"Symbol Rate setting (%1) is out of range (min/max:%2/%3)")
611 LOG(VB_GENERAL, LOG_WARNING,
LOC +
612 "Selected fec_inner parameter unsupported by this driver.");
617 LOG(VB_GENERAL, LOG_WARNING,
LOC +
618 "Selected modulation parameter unsupported by this driver.");
634 LOG(VB_GENERAL, LOG_WARNING,
LOC +
635 "Selected code_rate_hp parameter unsupported by this driver.");
640 LOG(VB_GENERAL, LOG_WARNING,
LOC +
641 "Selected code_rate_lp parameter unsupported by this driver.");
647 LOG(VB_GENERAL, LOG_WARNING,
LOC +
648 "'Auto' bandwidth parameter unsupported by this driver.");
654 LOG(VB_GENERAL, LOG_WARNING,
LOC +
655 "'Auto' transmission_mode parameter unsupported by this driver.");
661 LOG(VB_GENERAL, LOG_WARNING,
LOC +
662 "'Auto' guard_interval parameter unsupported by this driver.");
668 LOG(VB_GENERAL, LOG_WARNING,
LOC +
669 "'Auto' hierarchy parameter unsupported by this driver. ");
674 LOG(VB_GENERAL, LOG_WARNING,
LOC +
675 "Selected modulation parameter unsupported by this driver.");
748 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Tune(): Invalid input."));
751 return Tune(tuning,
false,
false);
780 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Tuning on slave channel");
782 bool ok = master->
Tune(tuning, force_reset,
false);
789 uint intermediate_freq = 0;
790 bool can_fec_auto =
false;
795 LOG(VB_GENERAL, LOG_ERR,
LOC +
796 "DVB-S/S2 needs device tree for LNB handling");
804 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Tune(): Card not open!");
812 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Tuning parameters:");
814 LOG(VB_CHANNEL, LOG_INFO,
" New: " + tuning.
toString());
819 int freq_mult = (is_dvbs) ? 1 : 1000;
820 QString suffix = (is_dvbs) ?
"kHz" :
"Hz";
824 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Tune(): Tuning to %1%2")
825 .arg(intermediate_freq ? intermediate_freq : tuning.
m_frequency)
832 if (tuning_delay > 0ms)
834 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Next tuning after less than %1ms, delaying by %2ms")
836 std::this_thread::sleep_for(tuning_delay);
852 LOG(VB_GENERAL, LOG_ERR,
LOC +
853 "Tune(): Failed to setup DiSEqC devices");
861 LOG(VB_GENERAL, LOG_ERR,
LOC +
862 "Tune(): No LNB for this configuration");
896 struct dtv_property p_clear = {};
897 struct dtv_properties cmdseq_clear = {};
899 p_clear.cmd = DTV_CLEAR;
900 cmdseq_clear.num = 1;
901 cmdseq_clear.props = &p_clear;
903 if ((ioctl(
m_fdFrontend, FE_SET_PROPERTY, &cmdseq_clear)) < 0)
905 LOG(VB_GENERAL, LOG_ERR,
LOC +
906 "Tune(): Clearing DTV properties cache failed." +
ENO);
914 LOG(VB_GENERAL, LOG_ERR,
LOC +
915 "Failed to convert DTVMultiplex to DTV_PROPERTY sequence");
921 for (
uint i = 0; i < cmds->num; i++)
923 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
924 QString(
"prop %1: cmd = %2, data %3")
925 .arg(i).arg(cmds->props[i].cmd)
926 .arg(cmds->props[i].u.data));
939 LOG(VB_GENERAL, LOG_ERR,
LOC +
940 "Tune(): Setting Frontend tuning parameters failed." +
ENO);
948 m_tunerType, tuning, intermediate_freq, can_fec_auto);
952 LOG(VB_GENERAL, LOG_ERR,
LOC +
953 "Tune(): Setting Frontend tuning parameters failed." +
ENO);
969 LOG(VB_CHANNEL, LOG_INFO,
LOC + QString(
"Tune(): Tuning to %1%2 skipped, already tuned")
970 .arg(intermediate_freq ? intermediate_freq : tuning.
m_frequency)
977 LOG(VB_CHANNEL, LOG_INFO,
LOC +
"Tune(): Frequency tuning successful");
996 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Card not open!");
1018 dvb_frontend_parameters params {};
1020 int res = ioctl(
m_fdFrontend, FE_GET_FRONTEND, ¶ms);
1023 LOG(VB_CHANNEL, LOG_ERR,
LOC +
"FE_GET_FRONTEND failed." +
ENO);
1042 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Card not open!");
1072 dvb_frontend_parameters params {};
1075 LOG(VB_GENERAL, LOG_ERR,
LOC +
1076 "Getting Frontend tuning parameters failed." +
ENO);
1103 query.
prepare(
"SELECT chanid, visible "
1104 "FROM channel, capturecard "
1105 "WHERE channel.deleted IS NULL AND "
1106 " capturecard.sourceid = channel.sourceid AND "
1107 " channel.channum = :CHANNUM AND "
1108 " capturecard.cardid = :INPUTID");
1119 while (query.
next())
1121 bool visible = query.
value(1).toInt() > 0;
1124 int chanid = query.
value(0).toInt();
1125 idlist.append(chanid);
1129 if (idlist.isEmpty())
1131 LOG(VB_GENERAL, LOG_WARNING,
LOC +
1132 QString(
"No visible channel ID for %1")
1137 id = idlist.value(0);
1138 if (idlist.count() > 1)
1141 for (
auto chanid : idlist)
1143 sl.append(QString::number(chanid));
1145 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
1146 QString(
"Found for '%1' multiple visible channel IDs: %2")
1151 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
1152 QString(
"Found visible channel ID %1 for '%2'")
1173 bool haslock = master->
HasLock(ok);
1179#if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1180 fe_status_t status = FE_NONE;
1182 fe_status_t status = (fe_status_t)0;
1185 int ret = ioctl(
m_fdFrontend, FE_READ_STATUS, &status);
1188 LOG(VB_GENERAL, LOG_ERR,
LOC +
"FE_READ_STATUS failed" +
ENO);
1192 LOG(VB_CHANNEL, LOG_DEBUG,
LOC + QString(
"%1 status: 0x%2 %3")
1193 .arg(__func__).arg(status,2,16,QChar(
'0')).arg(
toString(status)));
1199 return (status & FE_HAS_LOCK) != 0;
1204 struct dtv_property prop = {};
1205 struct dtv_properties cmd = {};
1207 prop.cmd = DTV_STAT_SIGNAL_STRENGTH;
1213 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"FE_GET_PROPERTY DTV_STAT_SIGNAL_STRENGTH failed" +
ENO);
1217#if DTV_STAT_FULL_DEBUG
1218 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"DTV_STAT_SIGNAL_STRENGTH " +
1219 QString(
"res=%1 len=%2 scale=%3 val=%4")
1220 .arg(cmd.props->result)
1221 .arg(cmd.props->u.st.len)
1222 .arg(cmd.props->u.st.stat[0].scale)
1223 .arg(cmd.props->u.st.stat[0].svalue));
1227 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1234 if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1240 int64_t svalue = cmd.props->u.st.stat[0].svalue;
1241 if (svalue >= -100000 && svalue <= 0)
1244 value = svalue + 100000;
1245 value = value / 100000.0;
1246 value = std::min(value, 1.0);
1249 else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1252 value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1284 int ret = ioctl(
m_fdFrontend, FE_READ_SIGNAL_STRENGTH, &sig);
1288 return sig * (1.0 / 65535.0);
1293 struct dtv_property prop = {};
1294 struct dtv_properties cmd = {};
1296 prop.cmd = DTV_STAT_CNR;
1302 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"FE_GET_PROPERTY DTV_STAT_CNR failed" +
ENO);
1306#if DTV_STAT_FULL_DEBUG
1307 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"DTV_STAT_CNR " +
1308 QString(
"res=%1 len=%2 scale=%3 val=%4")
1309 .arg(cmd.props->result)
1310 .arg(cmd.props->u.st.len)
1311 .arg(cmd.props->u.st.stat[0].scale)
1312 .arg(cmd.props->u.st.stat[0].svalue));
1316 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1322 if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1327 value = cmd.props->u.st.stat[0].svalue;
1328 value = value / 50000.0;
1334 else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1337 value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1348 double val = master->
GetSNR(ok);
1373 return snr * (1.0 / 65535.0);
1378 std::array<struct dtv_property,2> prop {};
1379 struct dtv_properties cmd = {};
1381 prop[0].cmd = DTV_STAT_POST_ERROR_BIT_COUNT;
1382 prop[1].cmd = DTV_STAT_POST_TOTAL_BIT_COUNT;
1383 cmd.num = prop.size();
1384 cmd.props = prop.data();
1388 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"FE_GET_PROPERTY DTV_STAT_POST_ERROR_BIT_COUNT failed" +
ENO);
1392#if DTV_STAT_FULL_DEBUG
1393 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"DTV_STAT_POST_ERROR_BIT_COUNT " +
1394 QString(
"res=%1 len=%2 scale=%3 val=%4 res=%5 len=%6 scale=%7 val=%8")
1395 .arg(cmd.props[0].result)
1396 .arg(cmd.props[0].u.st.len)
1397 .arg(cmd.props[0].u.st.stat[0].scale)
1398 .arg(cmd.props[0].u.st.stat[0].uvalue)
1399 .arg(cmd.props[1].result)
1400 .arg(cmd.props[1].u.st.len)
1401 .arg(cmd.props[1].u.st.stat[0].scale)
1402 .arg(cmd.props[1].u.st.stat[0].uvalue));
1406 bool tmpOk = (ret == 0) &&
1407 (cmd.props[0].u.st.len > 0) &&
1408 (cmd.props[1].u.st.len > 0);
1414 if ((cmd.props[0].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1415 (cmd.props[1].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1416 (cmd.props[1].u.st.stat[0].uvalue != 0))
1418 value =
static_cast<double>(
1419 static_cast<long double>(cmd.props[0].u.st.stat[0].uvalue) /
1420 cmd.props[1].u.st.stat[0].uvalue);
1454 return (
double) ber;
1459 struct dtv_property prop = {};
1460 struct dtv_properties cmd = {};
1462 prop.cmd = DTV_STAT_ERROR_BLOCK_COUNT;
1468 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"FE_GET_PROPERTY DTV_STAT_ERROR_BLOCK_COUNT failed" +
ENO);
1472#if DTV_STAT_FULL_DEBUG
1473 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
"DTV_STAT_ERROR_BLOCK_COUNT " +
1474 QString(
"res=%1 len=%2 scale=%3 val=%4")
1475 .arg(cmd.props[0].result)
1476 .arg(cmd.props[0].u.st.len)
1477 .arg(cmd.props[0].u.st.stat[0].scale)
1478 .arg(cmd.props[0].u.st.stat[0].svalue));
1482 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1488 if (cmd.props->u.st.stat[0].scale == FE_SCALE_COUNTER)
1489 value = cmd.props->u.st.stat[0].uvalue;
1517 uint32_t ublocks = 0;
1518 int ret = ioctl(
m_fdFrontend, FE_READ_UNCORRECTED_BLOCKS, &ublocks);
1522 return static_cast<double>(ublocks);
1535 auto *dvbm =
dynamic_cast<DVBChannel*
>(master);
1536 if (master && !dvbm)
1544 bool is_master = (master ==
this);
1556 struct dvb_frontend_event event {};
1558 while ((ret = ioctl(fd, FE_GET_EVENT, &event)) == 0);
1559 if ((ret < 0) && (EAGAIN != errno) && (EWOULDBLOCK != errno) && (EOVERFLOW != errno))
1561 LOG(VB_CHANNEL, LOG_ERR,
LOC +
1562 QString(
"%1 FE_GET_EVENT failed: ").arg(__func__) +
logStrerror(errno));
1591 auto seconds = duration_cast<std::chrono::seconds>(timeout_ms);
1592 auto usecs = duration_cast<std::chrono::microseconds>(timeout_ms) - seconds;
1593 struct timeval select_timeout = {
1594 .tv_sec=
static_cast<time_t
>(seconds.count()),
1595 .tv_usec=
static_cast<suseconds_t
>(usecs.count())};
1596 fd_set fd_select_set;
1597 FD_ZERO( &fd_select_set);
1598 FD_SET (fd, &fd_select_set);
1602 int ret = select(fd+1, &fd_select_set,
nullptr,
nullptr, &select_timeout);
1603 while ((-1 == ret) && (EINTR == errno))
1604 ret = select(fd+1, &fd_select_set,
nullptr,
nullptr, &select_timeout);
1608 LOG(VB_GENERAL, LOG_ERR,
LOC +
1609 QString(
"%1: Failed to wait on output.").arg(__func__) +
ENO);
1615#if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1616 fe_status_t status = FE_NONE;
1618 fe_status_t status = (fe_status_t)0;
1621 if (ioctl(fd, FE_READ_STATUS, &status) < 0)
1623 LOG(VB_GENERAL, LOG_ERR,
LOC +
1624 QString(
"%1: FE_READ_STATUS failed.").arg(__func__) +
ENO);
1629 LOG(VB_CHANNEL, LOG_DEBUG,
LOC +
1630 QString(
"%1: status: 0x%2 %3") .arg(__func__)
1631 .arg(status,2,16,QChar(
'0')).arg(
toString(status)));
1640 uint intermediate_freq,
bool can_fec_auto)
1642 dvb_frontend_parameters params {};
1644 params.frequency = tuning.m_frequency;
1645 params.inversion = (fe_spectral_inversion_t) (
int) tuning.m_inversion;
1651 LOG(VB_GENERAL, LOG_ERR,
1652 "DVBChan: Cannot tune to DVB-S2 transport with DVB-S card.");
1655 params.frequency = intermediate_freq;
1656 params.u.qpsk.symbol_rate = tuning.m_symbolRate;
1657 params.u.qpsk.fec_inner = can_fec_auto ? FEC_AUTO
1658 : (fe_code_rate_t) (
int) tuning.m_fec;
1663 LOG(VB_GENERAL, LOG_ERR,
1664 "DVBChan: Cannot tune DVB-S2 card with DVBv3 API.");
1669 params.u.qam.symbol_rate = tuning.m_symbolRate;
1670 params.u.qam.fec_inner = (fe_code_rate_t) (
int) tuning.m_fec;
1671 params.u.qam.modulation = (fe_modulation_t) (
int) tuning.m_modulation;
1677 params.u.ofdm.bandwidth = (fe_bandwidth_t) (
int) tuning.m_bandwidth;
1678 params.u.ofdm.code_rate_HP = (fe_code_rate_t) (
int) tuning.m_hpCodeRate;
1679 params.u.ofdm.code_rate_LP = (fe_code_rate_t) (
int) tuning.m_lpCodeRate;
1680 params.u.ofdm.constellation = (fe_modulation_t) (
int) tuning.m_modulation;
1681 params.u.ofdm.transmission_mode = (fe_transmit_mode_t) (
int) tuning.m_transMode;
1682 params.u.ofdm.guard_interval = (fe_guard_interval_t) (
int) tuning.m_guardInterval;
1683 params.u.ofdm.hierarchy_information = (fe_hierarchy_t) (
int) tuning.m_hierarchy;
1688 params.u.vsb.modulation = (fe_modulation_t) (
int) tuning.m_modulation;
1697 DTVTunerType tuner_type,
const dvb_frontend_parameters ¶ms)
1708 tuning.
m_fec = params.u.qpsk.fec_inner;
1714 tuning.
m_fec = params.u.qam.fec_inner;
1725 tuning.
m_transMode = params.u.ofdm.transmission_mode;
1727 tuning.
m_hierarchy = params.u.ofdm.hierarchy_information;
1742 uint intermediate_freq,
bool can_fec_auto,
bool do_tune)
1747 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]: m_modsys:%2 current_sys:%3")
1748 .arg(QString::number(inputId),
1753 auto *cmdseq = (
struct dtv_properties*) calloc(1,
sizeof(
struct dtv_properties));
1757 cmdseq->props = (
struct dtv_property*) calloc(20,
sizeof(*(cmdseq->props)));
1758 if (!(cmdseq->props))
1770 can_fec_auto =
false;
1780 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1781 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1785 delivery_system = current_sys;
1786 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1787 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1792 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1793 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1798 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1799 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1804 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1805 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1810 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1811 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1816 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1817 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1822 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"DVBChan[%1]:%2 set delivery_system to %3")
1823 .arg(inputId).arg(__LINE__).arg(delivery_system.
toString()));
1826 LOG(VB_CHANNEL, LOG_INFO, QString(
"DVBChan[%1]: Delivery system: %2")
1827 .arg(inputId).arg(delivery_system.
toString()));
1831 cmdseq->props[c].cmd = DTV_DELIVERY_SYSTEM;
1832 cmdseq->props[c++].u.data = delivery_system;
1836 LOG(VB_GENERAL, LOG_ERR, QString(
"DVBChan[%1]: Delivery system: %2")
1837 .arg(inputId).arg(delivery_system.
toString()));
1841 cmdseq->props[c].cmd = DTV_FREQUENCY;
1842 cmdseq->props[c++].u.data = intermediate_freq ? intermediate_freq : tuning.
m_frequency;
1843 cmdseq->props[c].cmd = DTV_MODULATION;
1845 cmdseq->props[c].cmd = DTV_INVERSION;
1853 cmdseq->props[c].cmd = DTV_SYMBOL_RATE;
1860 cmdseq->props[c].cmd = DTV_INNER_FEC;
1861 cmdseq->props[c++].u.data = can_fec_auto ? FEC_AUTO
1862 : (fe_code_rate_t) (
int) tuning.
m_fec;
1869 cmdseq->props[c].cmd = DTV_BANDWIDTH_HZ;
1870 cmdseq->props[c++].u.data = (8-tuning.
m_bandwidth) * 1000000;
1871 cmdseq->props[c].cmd = DTV_CODE_RATE_HP;
1873 cmdseq->props[c].cmd = DTV_CODE_RATE_LP;
1875 cmdseq->props[c].cmd = DTV_TRANSMISSION_MODE;
1877 cmdseq->props[c].cmd = DTV_GUARD_INTERVAL;
1879 cmdseq->props[c].cmd = DTV_HIERARCHY;
1886 cmdseq->props[c].cmd = DTV_ROLLOFF;
1893 cmdseq->props[c].cmd = DTV_PILOT;
1894 cmdseq->props[c++].u.data = PILOT_AUTO;
1895 cmdseq->props[c].cmd = DTV_ROLLOFF;
1896 cmdseq->props[c++].u.data = tuning.
m_rolloff;
1900 cmdseq->props[c++].cmd = DTV_TUNE;
static DTVModulationSystem GetDeliverySystem(uint inputid)
static int SetDeliverySystem(uint inputid)
static bool HasDVBCRCBug(const QString &device)
Returns true if and only if the device munges PAT/PMT tables, and then doesn't fix the CRC.
static std::chrono::milliseconds GetMinSignalMonitoringDelay(const QString &device)
static uint GetSourceID(uint inputid)
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
static QStringList CapabilitiesToString(uint64_t capabilities)
static DTVTunerType ConvertToTunerType(DTVModulationSystem delsys)
virtual bool Init(QString &startchannel, bool setchan)
virtual bool InitializeInput(void)
Fills in input map from DB.
Class providing a generic interface to digital tuning hardware.
static void ReturnMasterLock(DTVChannelP &chan)
void SetSIStandard(const QString &si_std)
Sets PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
static DTVChannel * GetMasterLock(const QString &key)
static MasterMap s_master_map
static QReadWriteLock s_master_map_lock
@ kModulationSystem_DVBS2
@ kModulationSystem_DVBT2
@ kModulationSystem_DVBC_ANNEX_A
@ kModulationSystem_UNDEFINED
bool IsEqual(DTVTunerType type, const DTVMultiplex &other, uint freq_range=0, bool fuzzy=false) const
DTVTransmitMode m_transMode
DTVModulation m_modulation
DTVModulationSystem m_modSys
DTVGuardInterval m_guardInterval
bool IsFECVariable(void) const
bool IsDiSEqCSupported(void) const
static const int kTunerTypeDVBS2
static const int kTunerTypeDVBT
static const int kTunerTypeDVBC
bool IsModulationVariable(void) const
static const int kTunerTypeDVBS1
static const int kTunerTypeDVBT2
static const int kTunerTypeATSC
void SetPMT(const ChannelBase *chan, const ProgramMapTable *pmt)
bool IsRunning(void) const
void SetTimeOffset(double offset_in_seconds)
Provides interface to the tuning hardware when using DVB drivers.
void CheckOptions(DTVMultiplex &t) const override
Checks tuning for problems, and tries to fix them.
bool Open(void) override
Opens the channel changing hardware for use.
bool CheckModulation(DTVModulation modulation) const
Return true iff modulation is supported modulation on the frontend.
DTVMultiplex m_desiredTuning
bool Retune(void) override
bool IsTuningParamsProbeSupported(void) const
Returns true iff tuning info probing is working.
std::chrono::milliseconds m_sigMonDelay
DTVModulationSystem m_currentSys
QList< DTVModulationSystem > m_sysList
const DiSEqCDevRotor * GetRotor(void) const
Returns rotor object if it exists, nullptr otherwise.
uint64_t m_frequencyMaximum
uint64_t m_extModulations
void DrainDVBEvents(void)
bool Init(QString &startchannel, bool setchan) override
int GetChanID(void) const override
Returns Channel ID.
void SetPMT(const ProgramMapTable *pmt)
Tells the Conditional Access Module which streams we wish to decode.
bool WaitForBackend(std::chrono::milliseconds timeout_ms)
Waits for backend to get tune message.
DVBChannel(QString device, TVRec *parent=nullptr)
uint64_t m_frequencyMinimum
void SetTimeOffset(double offset)
Tells the Conditional Access Module the offset from the computers utc time to dvb time.
bool IsMaster(void) const override
Returns true if this is the first of a number of multi-rec devs.
double GetUncorrectedBlockCount(bool *ok=nullptr) const
Returns # of uncorrected blocks since last call. First call undefined.
static std::chrono::milliseconds s_lastTuning
bool HasLock(bool *ok=nullptr) const
Returns true iff we have a signal carrier lock.
double GetBitErrorRate(bool *ok=nullptr) const
Returns # of corrected bits since last call. First call undefined.
void CheckFrequency(uint64_t frequency) const
Checks tuning frequency.
void Close(void) override
Closes the channel changing hardware to use.
double GetSNR(bool *ok=nullptr) const
Returns signal/noise in the range [0..1.0].
DiSEqCDevTree * m_diseqcTree
DTVMultiplex m_prevTuning
bool ProbeTuningParams(DTVMultiplex &tuning) const
Fetches DTVMultiplex params from driver.
DVBChannel * GetMasterLock(void) const
double GetSignalStrengthDVBv5(bool *ok) const
Get Signal strength from the DVBv5 interface [0-1.0] It is transformed to a linear relative scale if ...
double GetUncorrectedBlockCountDVBv5(bool *ok) const
Get Uncorrected Block Count from the DVBv5 interface.
bool CheckCodeRate(DTVCodeRate rate) const
Return true iff rate is supported rate on the frontend.
bool Tune(const DTVMultiplex &tuning) override
This performs the actual frequency tuning and in some cases input switching.
double GetSignalStrength(bool *ok=nullptr) const
Returns signal strength in the range [0.0..1.0] (non-calibrated).
DiSEqCDevSettings m_diseqcSettings
bool IsOpen(void) const override
Reports whether channel is already open.
double GetSNRDVBv5(bool *ok) const
Get SNR from the DVBv5 interface [0-1.0] It is transformed to a linear relative scale if provided in ...
static void ReturnMasterLock(DVBChannel *&dvbm)
std::chrono::milliseconds m_tuningDelay
double GetBitErrorRateDVBv5(bool *ok) const
Get Bit Error Rate from the DVBv5 interface.
uint GetDeviceID(void) const
uint32_t GetIntermediateFrequency(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const
Calculate proper intermediate frequency for the given settings and tuning parameters.
uint32_t GetIntermediateFrequency(uint32_t frequency) const
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Applies settings to the entire tree.
DiSEqCDevSCR * FindSCR(const DiSEqCDevSettings &settings)
Returns the SCR device object selected by the configuration chain.
DiSEqCDevLNB * FindLNB(const DiSEqCDevSettings &settings)
Returns the LNB device object selected by the configuration chain.
DiSEqCDevRotor * FindRotor(const DiSEqCDevSettings &settings, uint index=0)
Returns the nth rotor device object in the tree.
void Open(int fd_frontend, bool is_SCR)
Retrieve device tree.
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
QVariant value(int i) const
bool isActive(void) const
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
bool GetDVBv3(void) const
static void DBError(const QString &where, const MSqlQuery &query)
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
This is the coordinating class of the Recorder Subsystem.
uint GetInputId(void) const
Returns the inputid.
static constexpr std::chrono::milliseconds concurrent_tunings_delay
static struct dtv_properties * dtvmultiplex_to_dtvproperties(uint inputId, DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning, uint intermediate_freq, bool can_fec_auto, bool do_tune=true)
static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(DTVTunerType tuner_type, const DTVMultiplex &tuning, uint intermediate_freq, bool can_fec_auto)
static DTVMultiplex dvbparams_to_dtvmultiplex(DTVTunerType tuner_type, const dvb_frontend_parameters ¶ms)
QString logStrerror(int errnum)
Verbose helper function for ENO macro.
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
#define ENO
This can be appended to the LOG args with "+".
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
std::chrono::milliseconds currentMSecsSinceEpochAsDuration(void)
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
VERBOSE_PREAMBLE Most true