MythTV  master
dvbchannel.cpp
Go to the documentation of this file.
1 /*
2  * Class DVBChannel
3  *
4  * Copyright (C) Kenneth Aafloy 2003
5  *
6  * Description:
7  * Has the responsibility of opening the Frontend device and
8  * setting the options to tune a channel. It also keeps other
9  * channel options used by the dvb hierarcy.
10  *
11  * Author(s):
12  * Taylor Jacob (rtjacob at earthlink.net)
13  * - Changed tuning and DB structure
14  * Kenneth Aafloy (ke-aa at frisurf.no)
15  * - Rewritten for faster tuning.
16  * Ben Bucksch
17  * - Wrote the original implementation
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 2 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program; if not, write to the Free Software
31  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32  */
33 
34 // POSIX headers
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <algorithm>
38 #include <utility>
39 #include <sys/poll.h>
40 #include <sys/select.h>
41 #include <sys/time.h>
42 #include <sys/types.h>
43 
44 // C++ headers
45 #include <chrono>
46 #include <thread>
47 
48 // MythTV headers
49 #include "libmythbase/mythconfig.h"
50 #include "libmythbase/mythdb.h"
51 #include "cardutil.h"
52 #include "channelutil.h"
53 #include "dvbtypes.h"
54 #include "dvbchannel.h"
55 #include "dvbcam.h"
56 #include "tv_rec.h"
57 
58 
59 // Local functions
60 static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(
61  DTVTunerType tuner_type, const DTVMultiplex& tuning, uint intermediate_freq, bool can_fec_auto);
63  DTVTunerType tuner_type, const dvb_frontend_parameters& params);
64 static struct dtv_properties *dtvmultiplex_to_dtvproperties(uint inputId,
65  DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning,
66  uint intermediate_freq, bool can_fec_auto, bool do_tune = true);
67 
68 static constexpr std::chrono::milliseconds concurrent_tunings_delay { 1s };
70 
71 #define LOC QString("DVBChan[%1](%2): ").arg(m_inputId).arg(DVBChannel::GetDevice())
72 
73 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
74 #define DTV_STAT_FULL_DEBUG 0 // All DTV_STAT_xxx values
75 
81 DVBChannel::DVBChannel(QString aDevice, TVRec *parent)
82  : DTVChannel(parent), m_device(std::move(aDevice))
83 {
84  s_master_map_lock.lockForWrite();
86  if (m_pParent)
87  m_key += QString(":%1")
89 
90  s_master_map[m_key].push_back(this); // == RegisterForMaster
91  auto *master = dynamic_cast<DVBChannel*>(s_master_map[m_key].front());
92  if (master == this)
93  {
94  m_dvbCam = new DVBCam(m_device);
96  }
97  else if (master != nullptr)
98  {
99  m_dvbCam = master->m_dvbCam;
100  m_hasCrcBug = master->m_hasCrcBug;
101  }
102  s_master_map_lock.unlock();
103 
105 }
106 
108 {
109  // Set a new master if there are other instances and we're the master
110  // whether we are the master or not remove us from the map..
111  s_master_map_lock.lockForWrite();
112  auto *master = dynamic_cast<DVBChannel*>(s_master_map[m_key].front());
113  if (master == this)
114  {
115  s_master_map[m_key].pop_front();
116  DVBChannel *new_master = nullptr;
117  if (!s_master_map[m_key].empty())
118  new_master = dynamic_cast<DVBChannel*>(s_master_map[m_key].front());
119  if (new_master)
120  {
121  QMutexLocker master_locker(&(master->m_hwLock));
122  QMutexLocker new_master_locker(&(new_master->m_hwLock));
123  new_master->m_isOpen = master->m_isOpen;
124  }
125  }
126  else
127  {
128  s_master_map[m_key].removeAll(this);
129  }
130  s_master_map_lock.unlock();
131 
133 
134  // If we're the last one out delete dvbcam
135  s_master_map_lock.lockForRead();
136  MasterMap::iterator mit = s_master_map.find(m_key);
137  if ((*mit).empty())
138  delete m_dvbCam;
139  m_dvbCam = nullptr;
140  s_master_map_lock.unlock();
141 
142  // diseqc_tree is managed elsewhere
143 }
144 
146 {
147  LOG(VB_CHANNEL, LOG_INFO, LOC + "Closing DVB channel");
148 
149  QMutexLocker locker(&m_hwLock);
150 
151  IsOpenMap::iterator it = m_isOpen.find(who);
152  if (it == m_isOpen.end())
153  return; // This caller didn't have it open in the first place..
154 
155  m_isOpen.erase(it);
156 
157  DVBChannel *master = GetMasterLock();
158  if (master != nullptr && master != this)
159  {
160  if (m_dvbCam->IsRunning())
161  m_dvbCam->SetPMT(this, nullptr);
162  master->Close(this);
163  m_fdFrontend = -1;
164  ReturnMasterLock(master);
165  return;
166  }
167  ReturnMasterLock(master); // If we're the master we don't need this lock.
168 
169  if (!m_isOpen.empty())
170  return; // Not all callers have closed the DVB channel yet..
171 
172  if (m_diseqcTree)
173  m_diseqcTree->Close();
174 
175  if (m_fdFrontend >= 0)
176  {
178  m_fdFrontend = -1;
179 
180  m_dvbCam->Stop();
181  }
182 }
183 
185 {
186  if (!m_inputId)
187  {
188  if (!InitializeInput())
189  return false;
190  }
191 
192  LOG(VB_CHANNEL, LOG_INFO, LOC + "Opening DVB channel");
193 
195  if (m_legacyFe)
196  {
197  LOG(VB_CHANNEL, LOG_INFO, LOC + "Use legacy DVBv3 API");
198  }
199 
200  QMutexLocker locker(&m_hwLock);
201 
202  if (m_fdFrontend >= 0)
203  {
204  m_isOpen[who] = true;
205  return true;
206  }
207 
208  DVBChannel *master = GetMasterLock();
209  if (master != this)
210  {
211  if (!master->Open(who))
212  {
213  ReturnMasterLock(master);
214  return false;
215  }
216 
217  m_fdFrontend = master->m_fdFrontend;
218  m_frontendName = master->m_frontendName;
219  m_tunerType = master->m_tunerType;
220  m_capabilities = master->m_capabilities;
226  m_version = master->m_version;
227  m_legacyFe = master->m_legacyFe;
228  m_hasV5Stats = master->m_hasV5Stats;
229  m_currentSys = master->m_currentSys;
230  m_sysList = master->m_sysList;
231 
232  m_isOpen[who] = true;
233 
234  if (!InitializeInput())
235  {
236  Close();
237  ReturnMasterLock(master);
238  return false;
239  }
240 
241  ReturnMasterLock(master);
242  return true;
243  }
244  ReturnMasterLock(master); // If we're the master we don't need this lock.
245 
246  // Open the DVB device
247  //
249  QByteArray devn = dvbdev.toLatin1();
250 
251  for (int tries = 1; ; ++tries)
252  {
253  m_fdFrontend = open(devn.constData(), O_RDWR | O_NONBLOCK);
254  if (m_fdFrontend >= 0)
255  break;
256  if (tries == 1)
257  {
258  LOG(VB_GENERAL, LOG_WARNING, LOC +
259  "Opening DVB frontend device failed." + ENO);
260  }
261  if (tries >= 5 || (errno != EBUSY && errno != EAGAIN))
262  {
263  LOG(VB_GENERAL, LOG_ERR, LOC +
264  QString("Failed to open DVB frontend device due to "
265  "fatal error or too many attempts."));
266  return false;
267  }
268  std::this_thread::sleep_for(50ms);
269  }
270 
271  // Get the basic information from the frontend
272  //
273  dvb_frontend_info info {};
274  if (ioctl(m_fdFrontend, FE_GET_INFO, &info) < 0)
275  {
276  LOG(VB_GENERAL, LOG_ERR, LOC +
277  "Failed to get frontend information." + ENO);
278 
280  m_fdFrontend = -1;
281  return false;
282  }
283 
284  m_frontendName = info.name;
285  m_capabilities = info.caps;
286  m_frequencyMinimum = info.frequency_min;
287  m_frequencyMaximum = info.frequency_max;
288  m_symbolRateMinimum = info.symbol_rate_min;
289  m_symbolRateMaximum = info.symbol_rate_max;
290 
291  LOG(VB_CHANNEL, LOG_INFO, LOC +
292  QString("Frontend '%1' capabilities:").arg(m_frontendName));
293  for (auto & capstr : CardUtil::CapabilitiesToString(m_capabilities))
294  {
295  LOG(VB_CHANNEL, LOG_INFO, QString(" %1").arg(capstr));
296  }
297 
298  // Does this card use the DVBv5 or the legacy DVBv3 API?
299  {
300  std::array<struct dtv_property,2> prop = {};
301  struct dtv_properties cmd = {};
302 
303  prop[0].cmd = DTV_API_VERSION;
304  prop[1].cmd = DTV_DELIVERY_SYSTEM;
305 
306  cmd.num = 2;
307  cmd.props = prop.data();
308 
309  if (ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd) == -1)
310  {
311  prop[0].u.data = 0x300;
312  prop[1].u.data = SYS_UNDEFINED;
313  }
314 
315  m_version = prop[0].u.data;
316  m_currentSys = prop[1].u.data;
317 
318  m_legacyFe = m_version < 0x500 ? true : m_legacyFe;
319  m_hasV5Stats = m_version >= 0x50a;
320  }
321 
322  // Determine tuner capabilities and configured delivery system
323  //
324  m_sysList.clear();
325  if (m_legacyFe || m_version < 0x505)
326  {
327  // Legacy DVBv3 API
328  //
329  DTVModulationSystem delsys;
330  m_legacyFe = true;
331  switch (info.type) {
332  case FE_QPSK:
333  m_currentSys = SYS_DVBS;
334  m_sysList.append(m_currentSys);
335 
336  if (m_version < 0x0500)
337  break;
338  if (info.caps & FE_CAN_2G_MODULATION)
339  {
340  delsys = SYS_DVBS2;
341  m_sysList.append(delsys);
342  }
343  if (info.caps & FE_CAN_TURBO_FEC)
344  {
345  delsys = SYS_TURBO;
346  m_sysList.append(delsys);
347  }
348  break;
349  case FE_QAM:
350  m_currentSys = SYS_DVBC_ANNEX_A;
351  m_sysList.append(m_currentSys);
352  break;
353  case FE_OFDM:
354  m_currentSys = SYS_DVBT;
355  m_sysList.append(m_currentSys);
356  if (m_version < 0x0500)
357  break;
358  if (info.caps & FE_CAN_2G_MODULATION)
359  {
360  delsys = SYS_DVBT2;
361  m_sysList.append(delsys);
362  }
363  break;
364  case FE_ATSC:
365  if (info.caps & (FE_CAN_8VSB | FE_CAN_16VSB))
366  {
367  delsys = SYS_ATSC;
368  m_sysList.append(delsys);
369  }
370  if (info.caps & (FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO))
371  {
372  delsys = SYS_DVBC_ANNEX_B;
373  m_sysList.append(delsys);
374  }
375  m_currentSys = m_sysList.value(0);
376  break;
377  }
378  if (m_sysList.isEmpty())
379  {
380  LOG(VB_GENERAL, LOG_ERR, LOC +
381  QString("Frontend '%1' delivery system not detected.").arg(m_frontendName));
383  return false;
384  }
385  }
386  else
387  {
388  // DVBv5 API
389  //
390  std::array<struct dtv_property,1> prop = {};
391  struct dtv_properties cmd = {};
392 
393  prop[0].cmd = DTV_ENUM_DELSYS;
394 
395  cmd.num = 1;
396  cmd.props = prop.data();
397 
398  if (ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd) == -1)
399  {
400  LOG(VB_GENERAL, LOG_ERR, LOC +
401  QString("Frontend '%1' FE_GET_PROPERTY failed.").arg(m_frontendName));
403  return false;
404  }
405 
406  int p_num_systems = prop[0].u.buffer.len;
407  for (int i = 0; i < p_num_systems; i++)
408  {
409  DTVModulationSystem delsys(prop[0].u.buffer.data[i]);
410  m_sysList.append(delsys);
411  }
412 
413  if (p_num_systems == 0) {
414  LOG(VB_GENERAL, LOG_ERR, LOC +
415  QString("Frontend '%1' returned 0 supported delivery systems!").arg(m_frontendName));
417  return false;
418  }
419  }
420 
421  // Frontend info
422  //
423  if (VERBOSE_LEVEL_CHECK(VB_CHANNEL, LOG_INFO))
424  {
425  LOG(VB_CHANNEL, LOG_INFO, LOC +
426  QString("Frontend '%1' ").arg(m_frontendName));
427  LOG(VB_CHANNEL, LOG_INFO, LOC +
428  QString("DVB version:0x%1 ").arg(m_version,3,16,QChar('0')) +
429  QString("Delivery system:%1 ").arg(m_currentSys.toString()) +
430  QString("Legacy FE:%1 ").arg(m_legacyFe) +
431  QString("Has DVBv5 stats:%1").arg(m_hasV5Stats));
432 
433  LOG(VB_CHANNEL, LOG_INFO, "Supported delivery systems: ");
434  for (auto & delsys : m_sysList)
435  {
436  if (delsys == m_currentSys)
437  {
438  LOG(VB_CHANNEL, LOG_INFO, QString(" [%1]")
439  .arg(delsys.toString()));
440  }
441  else
442  {
443  LOG(VB_CHANNEL, LOG_INFO, QString(" %1")
444  .arg(delsys.toString()));
445  }
446  }
447 
448  uint32_t frq_min = info.frequency_min;
449  uint32_t frq_max = info.frequency_max;
450  uint32_t frq_stp = info.frequency_stepsize;
451 // uint32_t frq_tol = info.frequency_tolerance;
452  if (info.type == FE_QPSK) // Satellite frequencies are in kHz
453  {
454  frq_min *= 1000;
455  frq_max *= 1000;
456  frq_stp *= 1000;
457 // frq_tol *= 1000;
458  }
459 
460  LOG(VB_CHANNEL, LOG_INFO, QString("Frequency range for the current standard:"));
461  LOG(VB_CHANNEL, LOG_INFO, QString(" From: %1 Hz").arg(frq_min,11));
462  LOG(VB_CHANNEL, LOG_INFO, QString(" To: %1 Hz").arg(frq_max,11));
463  LOG(VB_CHANNEL, LOG_INFO, QString(" Step: %1 Hz").arg(frq_stp,11));
464 
465  if (info.type == FE_QPSK || info.type == FE_QAM)
466  {
467  LOG(VB_CHANNEL, LOG_INFO, QString("Symbol rate ranges for the current standard:"));
468  LOG(VB_CHANNEL, LOG_INFO, QString(" From: %1 Baud").arg(info.symbol_rate_min,11));
469  LOG(VB_CHANNEL, LOG_INFO, QString(" To: %1 Baud").arg(info.symbol_rate_max,11));
470  }
471  }
472 
473  if (m_currentSys == SYS_UNDEFINED)
474  m_currentSys = m_sysList.value(0);
475 
476  // Get delivery system from database and configure the tuner if needed.
479  {
480  if (delsys != m_currentSys)
481  {
482  LOG(VB_CHANNEL, LOG_INFO, LOC +
483  QString("Change delivery system from %1 to %2.")
484  .arg(m_currentSys.toString(),
485  delsys.toString()));
486 
488  m_currentSys = delsys;
489  }
490  else
491  {
492  LOG(VB_CHANNEL, LOG_INFO, LOC +
493  QString("Delivery system in database and in card equal, leave at %1.")
494  .arg(m_currentSys.toString()));
495  }
496  }
497  else
498  {
499  LOG(VB_CHANNEL, LOG_INFO, LOC +
500  QString("No delivery system in database, leave card at %1.").arg(m_currentSys.toString()));
501  }
503 
504  // Turn on the power to the LNB
506  {
507 
509  if (m_diseqcTree)
510  {
511  bool is_SCR = false;
512 
514  if (scr)
515  {
516  is_SCR = true;
517  LOG(VB_CHANNEL, LOG_INFO, LOC +
518  QString("Requested %1 channel is on SCR system")
519  .arg(m_tunerType.toString()));
520  }
521  else
522  {
523  LOG(VB_CHANNEL, LOG_INFO, LOC +
524  QString("Requested %1 channel is on non-SCR system")
525  .arg(m_tunerType.toString()));
526  }
527  m_diseqcTree->Open(m_fdFrontend, is_SCR);
528  }
529  }
530 
531  m_firstTune = true;
532 
533  if (!InitializeInput())
534  {
535  Close();
536  return false;
537  }
538 
539  if (m_fdFrontend >= 0)
540  m_isOpen[who] = true;
541 
542  return (m_fdFrontend >= 0);
543 }
544 
545 bool DVBChannel::IsOpen(void) const
546 {
547  // Have to acquire the hw lock to prevent m_isOpen being modified whilst we're searching it.
548  QMutexLocker locker(&m_hwLock);
549  IsOpenMap::const_iterator it = m_isOpen.find(this);
550  return it != m_isOpen.end();
551 }
552 
553 bool DVBChannel::Init(QString &startchannel, bool setchan)
554 {
555  if (setchan && !IsOpen())
556  Open(this);
557 
558  return ChannelBase::Init(startchannel, setchan);
559 }
560 
564 void DVBChannel::CheckFrequency(uint64_t frequency) const
565 {
568  (frequency < m_frequencyMinimum || frequency > m_frequencyMaximum))
569  {
570  LOG(VB_GENERAL, LOG_WARNING, LOC +
571  QString("Frequency setting (%1) is out of range (min/max:%2/%3)")
572  .arg(frequency).arg(m_frequencyMinimum).arg(m_frequencyMaximum));
573  }
574 }
575 
577 {
578  if ((tuning.m_inversion == DTVInversion::kInversionAuto) &&
579  ((m_capabilities & FE_CAN_INVERSION_AUTO) == 0U))
580  {
581  LOG(VB_GENERAL, LOG_WARNING, LOC +
582  "'Auto' inversion parameter unsupported by this driver, "
583  "falling back to 'off'.");
585  }
586 
587  // DVB-S/S2 needs a fully initialized DiSEqC tree and is checked later in Tune
588  if (!m_diseqcTree)
589  {
590  DVBChannel *master = GetMasterLock();
591  if (master == nullptr || !master->m_diseqcTree)
592  CheckFrequency(tuning.m_frequency);
593  ReturnMasterLock(master);
594  }
595 
596  if (m_tunerType.IsFECVariable() &&
599  (tuning.m_symbolRate < m_symbolRateMinimum ||
601  {
602  LOG(VB_GENERAL, LOG_WARNING, LOC +
603  QString("Symbol Rate setting (%1) is out of range (min/max:%2/%3)")
604  .arg(tuning.m_symbolRate)
606  }
607 
608  if (m_tunerType.IsFECVariable() && !CheckCodeRate(tuning.m_fec))
609  {
610  LOG(VB_GENERAL, LOG_WARNING, LOC +
611  "Selected fec_inner parameter unsupported by this driver.");
612  }
613 
615  {
616  LOG(VB_GENERAL, LOG_WARNING, LOC +
617  "Selected modulation parameter unsupported by this driver.");
618  }
619 
622  {
623  LOG(VB_CHANNEL, LOG_DEBUG, LOC + tuning.toString());
624  return;
625  }
626 
627  // ------ Below only DVB-T/T2 tuning parameters ------
628 
629  // Check OFDM Tuning params
630 
631  if (!CheckCodeRate(tuning.m_hpCodeRate))
632  {
633  LOG(VB_GENERAL, LOG_WARNING, LOC +
634  "Selected code_rate_hp parameter unsupported by this driver.");
635  }
636 
637  if (!CheckCodeRate(tuning.m_lpCodeRate))
638  {
639  LOG(VB_GENERAL, LOG_WARNING, LOC +
640  "Selected code_rate_lp parameter unsupported by this driver.");
641  }
642 
643  if ((tuning.m_bandwidth == DTVBandwidth::kBandwidthAuto) &&
644  ((m_capabilities & FE_CAN_BANDWIDTH_AUTO) == 0U))
645  {
646  LOG(VB_GENERAL, LOG_WARNING, LOC +
647  "'Auto' bandwidth parameter unsupported by this driver.");
648  }
649 
651  ((m_capabilities & FE_CAN_TRANSMISSION_MODE_AUTO) == 0U))
652  {
653  LOG(VB_GENERAL, LOG_WARNING, LOC +
654  "'Auto' transmission_mode parameter unsupported by this driver.");
655  }
656 
658  ((m_capabilities & FE_CAN_GUARD_INTERVAL_AUTO) == 0U))
659  {
660  LOG(VB_GENERAL, LOG_WARNING, LOC +
661  "'Auto' guard_interval parameter unsupported by this driver.");
662  }
663 
664  if ((tuning.m_hierarchy == DTVHierarchy::kHierarchyAuto) &&
665  ((m_capabilities & FE_CAN_HIERARCHY_AUTO) == 0U))
666  {
667  LOG(VB_GENERAL, LOG_WARNING, LOC +
668  "'Auto' hierarchy parameter unsupported by this driver. ");
669  }
670 
671  if (!CheckModulation(tuning.m_modulation))
672  {
673  LOG(VB_GENERAL, LOG_WARNING, LOC +
674  "Selected modulation parameter unsupported by this driver.");
675  }
676 
677  LOG(VB_CHANNEL, LOG_DEBUG, LOC + tuning.toString());
678 }
679 
684 {
685  const uint64_t caps = m_capabilities;
686  return
687  ((DTVCodeRate::kFECNone == rate)) ||
688  ((DTVCodeRate::kFEC_1_2 == rate) && ((caps & FE_CAN_FEC_1_2) != 0U)) ||
689  ((DTVCodeRate::kFEC_2_3 == rate) && ((caps & FE_CAN_FEC_2_3) != 0U)) ||
690  ((DTVCodeRate::kFEC_3_4 == rate) && ((caps & FE_CAN_FEC_3_4) != 0U)) ||
691  ((DTVCodeRate::kFEC_4_5 == rate) && ((caps & FE_CAN_FEC_4_5) != 0U)) ||
692  ((DTVCodeRate::kFEC_5_6 == rate) && ((caps & FE_CAN_FEC_5_6) != 0U)) ||
693  ((DTVCodeRate::kFEC_6_7 == rate) && ((caps & FE_CAN_FEC_6_7) != 0U)) ||
694  ((DTVCodeRate::kFEC_7_8 == rate) && ((caps & FE_CAN_FEC_7_8) != 0U)) ||
695  ((DTVCodeRate::kFEC_8_9 == rate) && ((caps & FE_CAN_FEC_8_9) != 0U)) ||
696  ((DTVCodeRate::kFECAuto == rate) && ((caps & FE_CAN_FEC_AUTO) != 0U));
697 }
698 
703 {
704  const DTVModulation m = modulation;
705  const uint64_t c = m_capabilities;
706 
707  return
708  ((DTVModulation::kModulationQPSK == m) && ((c & FE_CAN_QPSK) != 0U)) ||
709 #if HAVE_FE_CAN_2G_MODULATION
710  ((DTVModulation::kModulation8PSK == m) && ((c & FE_CAN_2G_MODULATION) != 0U)) ||
711  ((DTVModulation::kModulation16APSK == m) && ((c & FE_CAN_2G_MODULATION) != 0U)) ||
712  ((DTVModulation::kModulation32APSK == m) && ((c & FE_CAN_2G_MODULATION) != 0U)) ||
713 #endif //HAVE_FE_CAN_2G_MODULATION
714  ((DTVModulation::kModulationQAM16 == m) && ((c & FE_CAN_QAM_16) != 0U)) ||
715  ((DTVModulation::kModulationQAM32 == m) && ((c & FE_CAN_QAM_32) != 0U)) ||
716  ((DTVModulation::kModulationQAM64 == m) && ((c & FE_CAN_QAM_64) != 0U)) ||
717  ((DTVModulation::kModulationQAM128 == m) && ((c & FE_CAN_QAM_128) != 0U)) ||
718  ((DTVModulation::kModulationQAM256 == m) && ((c & FE_CAN_QAM_256) != 0U)) ||
719  ((DTVModulation::kModulationQAMAuto == m) && ((c & FE_CAN_QAM_AUTO) != 0U)) ||
720  ((DTVModulation::kModulation8VSB == m) && ((c & FE_CAN_8VSB) != 0U)) ||
721  ((DTVModulation::kModulation16VSB == m) && ((c & FE_CAN_16VSB) != 0U));
722 }
723 
728 {
729  if (!m_dvbCam->IsRunning())
730  m_dvbCam->Start();
731  if (pmt && m_dvbCam->IsRunning())
732  m_dvbCam->SetPMT(this, pmt);
733 }
734 
739 void DVBChannel::SetTimeOffset(double offset)
740 {
741  if (m_dvbCam->IsRunning())
742  m_dvbCam->SetTimeOffset(offset);
743 }
744 
745 bool DVBChannel::Tune(const DTVMultiplex &tuning)
746 {
747  if (!m_inputId)
748  {
749  LOG(VB_GENERAL, LOG_ERR, LOC + QString("Tune(): Invalid input."));
750  return false;
751  }
752  return Tune(tuning, false, false);
753 }
754 
755 
756 /*****************************************************************************
757  Tuning functions for each of the five types of cards.
758  *****************************************************************************/
759 
771 bool DVBChannel::Tune(const DTVMultiplex &tuning,
772  bool force_reset,
773  bool same_input)
774 {
775  QMutexLocker lock(&m_tuneLock);
776  QMutexLocker locker(&m_hwLock);
777 
778  DVBChannel *master = GetMasterLock();
779  if (master != this)
780  {
781  LOG(VB_CHANNEL, LOG_INFO, LOC + "Tuning on slave channel");
782  SetSIStandard(tuning.m_sistandard);
783  bool ok = master->Tune(tuning, force_reset, false);
784  ReturnMasterLock(master);
785  return ok;
786  }
787  ReturnMasterLock(master); // If we're the master we don't need this lock.
788 
789 
790  uint intermediate_freq = 0;
791  bool can_fec_auto = false;
792  bool reset = (force_reset || m_firstTune);
793 
795  {
796  LOG(VB_GENERAL, LOG_ERR, LOC +
797  "DVB-S/S2 needs device tree for LNB handling");
798  return false;
799  }
800 
801  m_desiredTuning = tuning;
802 
803  if (m_fdFrontend < 0)
804  {
805  LOG(VB_GENERAL, LOG_ERR, LOC + "Tune(): Card not open!");
806 
807  return false;
808  }
809 
810  // Remove all events in queue before tuning.
811  DrainDVBEvents();
812 
813  LOG(VB_CHANNEL, LOG_INFO, LOC + "Tuning parameters:");
814  LOG(VB_CHANNEL, LOG_INFO, " Old: " + m_prevTuning.toString());
815  LOG(VB_CHANNEL, LOG_INFO, " New: " + tuning.toString());
816 
817  // DVB-S/S2 is in kHz, other DVB is in Hz
818  bool is_dvbs = ((DTVTunerType::kTunerTypeDVBS1 == m_tunerType) ||
820  int freq_mult = (is_dvbs) ? 1 : 1000;
821  QString suffix = (is_dvbs) ? "kHz" : "Hz";
822 
823  if (reset || !m_prevTuning.IsEqual(m_tunerType, tuning, 500 * freq_mult))
824  {
825  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(): Tuning to %1%2")
826  .arg(intermediate_freq ? intermediate_freq : tuning.m_frequency)
827  .arg(suffix));
828 
829  m_tuneDelayLock.lock();
830 
831  std::chrono::milliseconds this_tuning = MythDate::currentMSecsSinceEpochAsDuration();
832  std::chrono::milliseconds tuning_delay = s_lastTuning + concurrent_tunings_delay - this_tuning;
833  if (tuning_delay > 0ms)
834  {
835  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Next tuning after less than %1ms, delaying by %2ms")
836  .arg(concurrent_tunings_delay.count()).arg(tuning_delay.count()));
837  std::this_thread::sleep_for(tuning_delay);
838  }
840 
841  m_tuneDelayLock.unlock();
842 
843  // For DVB-S/S2 configure DiSEqC and determine intermediate frequency
844  if (m_diseqcTree)
845  {
846  // Configure for new input
847  if (!same_input)
849 
850  // Execute DiSEqC commands
851  if (!m_diseqcTree->Execute(m_diseqcSettings, tuning))
852  {
853  LOG(VB_GENERAL, LOG_ERR, LOC +
854  "Tune(): Failed to setup DiSEqC devices");
855  return false;
856  }
857 
858  // Retrieve actual intermediate frequency
860  if (!lnb)
861  {
862  LOG(VB_GENERAL, LOG_ERR, LOC +
863  "Tune(): No LNB for this configuration");
864  return false;
865  }
866 
867  if (lnb->GetDeviceID() != m_lastLnbDevId)
868  {
869  m_lastLnbDevId = lnb->GetDeviceID();
870  // Make sure we tune to frequency, if the lnb has changed
871  m_firstTune = true;
872  }
873 
874  intermediate_freq = lnb->GetIntermediateFrequency(
875  m_diseqcSettings, tuning);
876 
877  // Retrieve SCR intermediate frequency
879  if (lnb && scr)
880  {
881  intermediate_freq = scr->GetIntermediateFrequency(intermediate_freq);
882  }
883 
884  // If card can auto-FEC, use it -- sometimes NITs are inaccurate
885  if (m_capabilities & FE_CAN_FEC_AUTO)
886  can_fec_auto = true;
887 
888  // Check DVB-S intermediate frequency here since it requires a fully
889  // initialized diseqc tree
890  CheckFrequency(intermediate_freq);
891  }
892 
893  // DVBv5 or legacy DVBv3 API
894  if (!m_legacyFe)
895  {
896  // DVBv5 API
897  struct dtv_property p_clear = {};
898  struct dtv_properties cmdseq_clear = {};
899 
900  p_clear.cmd = DTV_CLEAR;
901  cmdseq_clear.num = 1;
902  cmdseq_clear.props = &p_clear;
903 
904  if ((ioctl(m_fdFrontend, FE_SET_PROPERTY, &cmdseq_clear)) < 0)
905  {
906  LOG(VB_GENERAL, LOG_ERR, LOC +
907  "Tune(): Clearing DTV properties cache failed." + ENO);
908  return false;
909  }
910 
911  struct dtv_properties *cmds = dtvmultiplex_to_dtvproperties(m_inputId,
912  m_tunerType, m_currentSys, tuning, intermediate_freq, can_fec_auto);
913 
914  if (!cmds) {
915  LOG(VB_GENERAL, LOG_ERR, LOC +
916  "Failed to convert DTVMultiplex to DTV_PROPERTY sequence");
917  return false;
918  }
919 
920  if (VERBOSE_LEVEL_CHECK(VB_CHANNEL, LOG_DEBUG))
921  {
922  for (uint i = 0; i < cmds->num; i++)
923  {
924  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
925  QString("prop %1: cmd = %2, data %3")
926  .arg(i).arg(cmds->props[i].cmd)
927  .arg(cmds->props[i].u.data));
928  }
929  }
930 
931  int res = ioctl(m_fdFrontend, FE_SET_PROPERTY, cmds);
932 
933  free(cmds->props);
934  free(cmds);
935 
936  if (res < 0)
937  {
938  LOG(VB_GENERAL, LOG_ERR, LOC +
939  "Tune(): Setting Frontend tuning parameters failed." + ENO);
940  return false;
941  }
942  }
943  else
944  {
945  // Legacy DVBv3 API
946  struct dvb_frontend_parameters params = dtvmultiplex_to_dvbparams(
947  m_tunerType, tuning, intermediate_freq, can_fec_auto);
948 
949  if (ioctl(m_fdFrontend, FE_SET_FRONTEND, &params) < 0)
950  {
951  LOG(VB_GENERAL, LOG_ERR, LOC +
952  "Tune(): Setting Frontend tuning parameters failed." + ENO);
953  return false;
954  }
955  }
956 
957  // Extra delay to add for broken DVB drivers
958  if (m_tuningDelay > 0ms)
959  std::this_thread::sleep_for(m_tuningDelay);
960 
961  WaitForBackend(50ms);
962 
963  m_prevTuning = tuning;
964  m_firstTune = false;
965  }
966  else
967  {
968  LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(): Tuning to %1%2 skipped, already tuned")
969  .arg(intermediate_freq ? intermediate_freq : tuning.m_frequency)
970  .arg(suffix));
971  }
972 
973 
974  SetSIStandard(tuning.m_sistandard);
975 
976  LOG(VB_CHANNEL, LOG_INFO, LOC + "Tune(): Frequency tuning successful");
977 
978  return true;
979 }
980 
982 {
983  return Tune(m_desiredTuning, true, true);
984 }
985 
990 {
991  QMutexLocker locker(&m_hwLock);
992 
993  if (m_fdFrontend < 0)
994  {
995  LOG(VB_GENERAL, LOG_ERR, LOC + "Card not open!");
996 
997  return false;
998  }
999 
1000  DVBChannel *master = GetMasterLock();
1001  if (master != this)
1002  {
1003  bool ok = master->IsTuningParamsProbeSupported();
1004  ReturnMasterLock(master);
1005  return ok;
1006  }
1007  ReturnMasterLock(master); // If we're the master we don't need this lock.
1008 
1009  if (m_diseqcTree)
1010  {
1011  // TODO We need to implement the inverse of
1012  // lnb->GetIntermediateFrequency() for ProbeTuningParams()
1013  // to accurately reflect the frequency before LNB transform.
1014  return false;
1015  }
1016 
1017  dvb_frontend_parameters params {};
1018 
1019  int res = ioctl(m_fdFrontend, FE_GET_FRONTEND, &params);
1020  if (res < 0)
1021  {
1022  LOG(VB_CHANNEL, LOG_ERR, LOC + "FE_GET_FRONTEND failed." + ENO);
1023  }
1024 
1025  return (res >= 0);
1026 }
1027 
1036 {
1037  QMutexLocker locker(&m_hwLock);
1038 
1039  if (m_fdFrontend < 0)
1040  {
1041  LOG(VB_GENERAL, LOG_ERR, LOC + "Card not open!");
1042 
1043  return false;
1044  }
1045 
1046  DVBChannel *master = GetMasterLock();
1047  if (master != this)
1048  {
1049  bool ok = master->ProbeTuningParams(tuning);
1050  ReturnMasterLock(master);
1051  return ok;
1052  }
1053  ReturnMasterLock(master); // If we're the master we don't need this lock.
1054 
1055  if (m_diseqcTree)
1056  {
1057  // TODO We need to implement the inverse of
1058  // lnb->GetIntermediateFrequency() for ProbeTuningParams()
1059  // to accurately reflect the frequency before LNB transform.
1060  return false;
1061  }
1062 
1063  // DVBv5 API
1064  if (!m_legacyFe)
1065  {
1066  // TODO implement probing of tuning parameters with FE_GET_PROPERTY
1067  return false;
1068  }
1069 
1070  // Legacy DVBv3 API
1071  dvb_frontend_parameters params {};
1072  if (ioctl(m_fdFrontend, FE_GET_FRONTEND, &params) < 0)
1073  {
1074  LOG(VB_GENERAL, LOG_ERR, LOC +
1075  "Getting Frontend tuning parameters failed." + ENO);
1076 
1077  return false;
1078  }
1079 
1080  uint mplex = tuning.m_mplex;
1081  QString sistandard = tuning.m_sistandard;
1082 
1083  tuning = dvbparams_to_dtvmultiplex(m_tunerType, params);
1084 
1085  tuning.m_mplex = mplex;
1086  tuning.m_sistandard = sistandard;
1087 
1088  return true;
1089 }
1090 
1096 {
1097  QList<int> idlist;
1098  int id = -1;
1099 
1100  MSqlQuery query(MSqlQuery::InitCon());
1101 
1102  query.prepare("SELECT chanid, visible "
1103  "FROM channel, capturecard "
1104  "WHERE channel.deleted IS NULL AND "
1105  " capturecard.sourceid = channel.sourceid AND "
1106  " channel.channum = :CHANNUM AND "
1107  " capturecard.cardid = :INPUTID");
1108 
1109  query.bindValue(":CHANNUM", m_curChannelName);
1110  query.bindValue(":INPUTID", m_inputId);
1111 
1112  if (!query.exec() || !query.isActive())
1113  {
1114  MythDB::DBError("fetching chanid", query);
1115  return -1;
1116  }
1117 
1118  while (query.next())
1119  {
1120  bool visible = query.value(1).toInt() > 0;
1121  if (visible)
1122  {
1123  int chanid = query.value(0).toInt();
1124  idlist.append(chanid);
1125  }
1126  }
1127 
1128  if (idlist.isEmpty())
1129  {
1130  LOG(VB_GENERAL, LOG_WARNING, LOC +
1131  QString("No visible channel ID for %1")
1132  .arg(m_curChannelName));
1133  }
1134  else
1135  {
1136  id = idlist.value(0);
1137  if (idlist.count() > 1)
1138  {
1139  QStringList sl;
1140  for (auto chanid : idlist)
1141  {
1142  sl.append(QString::number(chanid));
1143  }
1144  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1145  QString("Found for '%1' multiple visible channel IDs: %2")
1146  .arg(m_curChannelName, sl.join(" ")));
1147  }
1148  else
1149  {
1150  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1151  QString("Found visible channel ID %1 for '%2'")
1152  .arg(id).arg(m_curChannelName));
1153  }
1154  }
1155 
1156  return id;
1157 }
1158 
1160 {
1161  if (m_diseqcTree)
1163 
1164  return nullptr;
1165 }
1166 
1167 bool DVBChannel::HasLock(bool *ok) const
1168 {
1169  DVBChannel *master = GetMasterLock();
1170  if (master != this)
1171  {
1172  bool haslock = master->HasLock(ok);
1173  ReturnMasterLock(master);
1174  return haslock;
1175  }
1176  ReturnMasterLock(master); // If we're the master we don't need this lock.
1177 
1178 #if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1179  fe_status_t status = FE_NONE;
1180 #else // debian9, centos7
1181  fe_status_t status = (fe_status_t)0;
1182 #endif
1183 
1184  int ret = ioctl(m_fdFrontend, FE_READ_STATUS, &status);
1185  if (ret < 0)
1186  {
1187  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_READ_STATUS failed" + ENO);
1188  }
1189  else
1190  {
1191  LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("%1 status: 0x%2 %3")
1192  .arg(__func__).arg(status,2,16,QChar('0')).arg(toString(status)));
1193  }
1194 
1195  if (ok)
1196  *ok = (0 == ret);
1197 
1198  return (status & FE_HAS_LOCK) != 0;
1199 }
1200 
1202 {
1203  struct dtv_property prop = {};
1204  struct dtv_properties cmd = {};
1205 
1206  prop.cmd = DTV_STAT_SIGNAL_STRENGTH;
1207  cmd.num = 1;
1208  cmd.props = &prop;
1209  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1210  if (ret < 0)
1211  {
1212  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_SIGNAL_STRENGTH failed" + ENO);
1213  }
1214  else
1215  {
1216 #if DTV_STAT_FULL_DEBUG
1217  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_SIGNAL_STRENGTH " +
1218  QString("res=%1 len=%2 scale=%3 val=%4")
1219  .arg(cmd.props->result)
1220  .arg(cmd.props->u.st.len)
1221  .arg(cmd.props->u.st.stat[0].scale)
1222  .arg(cmd.props->u.st.stat[0].svalue));
1223 #endif
1224  }
1225 
1226  bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1227  if (ok)
1228  *ok = tmpOk;
1229 
1230  double value = 0;
1231  if (tmpOk)
1232  {
1233  if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1234  {
1235  // Convert range of -100dBm .. 0dBm to 0% .. 100%
1236  // Note that -100dBm is lower than the noise floor.
1237  // The measured svalue is in units of 0.001 dBm.
1238  // If the value is outside the range -100 to 0 dBm we do not believe it.
1239  int64_t svalue = cmd.props->u.st.stat[0].svalue;
1240  if (svalue >= -100000 && svalue <= 0)
1241  {
1242  // convert value from -100dBm to 0dBm to a 0-1 range
1243  value = svalue + 100000;
1244  value = value / 100000.0;
1245  value = std::min(value, 1.0);
1246  }
1247  }
1248  else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1249  {
1250  // Return as 16 bit unsigned
1251  value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1252  }
1253  }
1254  return value;
1255 }
1256 
1257 double DVBChannel::GetSignalStrength(bool *ok) const
1258 {
1259  DVBChannel *master = GetMasterLock();
1260  if (master != this)
1261  {
1262  double val = master->GetSignalStrength(ok);
1263  ReturnMasterLock(master);
1264  return val;
1265  }
1266  ReturnMasterLock(master); // If we're the master we don't need this lock.
1267 
1268  if (!m_legacyFe && m_hasV5Stats)
1269  {
1270  bool v5_ok = false;
1271  double value = GetSignalStrengthDVBv5(&v5_ok);
1272  if (v5_ok)
1273  {
1274  if (ok)
1275  *ok = v5_ok;
1276  return value;
1277  }
1278  }
1279 
1280  // We use uint16_t for sig because this is correct for DVB API 4.0,
1281  // and works better than the correct int16_t for the 3.x API
1282  uint16_t sig = 0;
1283  int ret = ioctl(m_fdFrontend, FE_READ_SIGNAL_STRENGTH, &sig);
1284  if (ok)
1285  *ok = (0 == ret);
1286 
1287  return sig * (1.0 / 65535.0);
1288 }
1289 
1290 double DVBChannel::GetSNRDVBv5(bool *ok) const
1291 {
1292  struct dtv_property prop = {};
1293  struct dtv_properties cmd = {};
1294 
1295  prop.cmd = DTV_STAT_CNR;
1296  cmd.num = 1;
1297  cmd.props = &prop;
1298  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1299  if (ret < 0)
1300  {
1301  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_CNR failed" + ENO);
1302  }
1303  else
1304  {
1305 #if DTV_STAT_FULL_DEBUG
1306  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_CNR " +
1307  QString("res=%1 len=%2 scale=%3 val=%4")
1308  .arg(cmd.props->result)
1309  .arg(cmd.props->u.st.len)
1310  .arg(cmd.props->u.st.stat[0].scale)
1311  .arg(cmd.props->u.st.stat[0].svalue));
1312 #endif
1313  }
1314 
1315  bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1316  if (ok)
1317  *ok = tmpOk;
1318  double value = 0;
1319  if (tmpOk)
1320  {
1321  if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1322  {
1323  // The measured svalue is in units of 0.001 dB
1324  // Let 50dB+ CNR be 100% quality and 0dB be 0%
1325  // Convert 0.001 dB from 0-50000 to a 0-1 range
1326  value = cmd.props->u.st.stat[0].svalue;
1327  value = value / 50000.0;
1328  if (value > 1.0)
1329  value = 1.0;
1330  else if (value < 0)
1331  value = 0.0;
1332  }
1333  else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1334  {
1335  // Return as 16 bit unsigned
1336  value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1337  }
1338  }
1339  return value;
1340 }
1341 
1342 double DVBChannel::GetSNR(bool *ok) const
1343 {
1344  DVBChannel *master = GetMasterLock();
1345  if (master != this)
1346  {
1347  double val = master->GetSNR(ok);
1348  ReturnMasterLock(master);
1349  return val;
1350  }
1351  ReturnMasterLock(master); // If we're the master we don't need this lock.
1352 
1353  if (!m_legacyFe && m_hasV5Stats)
1354  {
1355  bool v5_ok = false;
1356  double value = GetSNRDVBv5(&v5_ok);
1357  if (v5_ok)
1358  {
1359  if (ok)
1360  *ok = v5_ok;
1361  return value;
1362  }
1363  }
1364 
1365  // We use uint16_t for sig because this is correct for DVB API 4.0,
1366  // and works better than the correct int16_t for the 3.x API
1367  uint16_t snr = 0;
1368  int ret = ioctl(m_fdFrontend, FE_READ_SNR, &snr);
1369  if (ok)
1370  *ok = (0 == ret);
1371 
1372  return snr * (1.0 / 65535.0);
1373 }
1374 
1375 double DVBChannel::GetBitErrorRateDVBv5(bool *ok) const
1376 {
1377  std::array<struct dtv_property,2> prop {};
1378  struct dtv_properties cmd = {};
1379 
1380  prop[0].cmd = DTV_STAT_POST_ERROR_BIT_COUNT;
1381  prop[1].cmd = DTV_STAT_POST_TOTAL_BIT_COUNT;
1382  cmd.num = prop.size();
1383  cmd.props = prop.data();
1384  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1385  if (ret < 0)
1386  {
1387  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_POST_ERROR_BIT_COUNT failed" + ENO);
1388  }
1389  else
1390  {
1391 #if DTV_STAT_FULL_DEBUG
1392  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_POST_ERROR_BIT_COUNT " +
1393  QString("res=%1 len=%2 scale=%3 val=%4 res=%5 len=%6 scale=%7 val=%8")
1394  .arg(cmd.props[0].result)
1395  .arg(cmd.props[0].u.st.len)
1396  .arg(cmd.props[0].u.st.stat[0].scale)
1397  .arg(cmd.props[0].u.st.stat[0].uvalue)
1398  .arg(cmd.props[1].result)
1399  .arg(cmd.props[1].u.st.len)
1400  .arg(cmd.props[1].u.st.stat[0].scale)
1401  .arg(cmd.props[1].u.st.stat[0].uvalue));
1402 #endif
1403  }
1404 
1405  bool tmpOk = (ret == 0) &&
1406  (cmd.props[0].u.st.len > 0) &&
1407  (cmd.props[1].u.st.len > 0);
1408  if (ok)
1409  *ok = tmpOk;
1410  double value = 0;
1411  if (tmpOk)
1412  {
1413  if ((cmd.props[0].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1414  (cmd.props[1].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1415  (cmd.props[1].u.st.stat[0].uvalue != 0))
1416  {
1417  value = static_cast<double>(
1418  static_cast<long double>(cmd.props[0].u.st.stat[0].uvalue) /
1419  cmd.props[1].u.st.stat[0].uvalue);
1420  }
1421  }
1422  return value;
1423 }
1424 
1425 double DVBChannel::GetBitErrorRate(bool *ok) const
1426 {
1427  DVBChannel *master = GetMasterLock();
1428  if (master != this)
1429  {
1430  double val = master->GetBitErrorRate(ok);
1431  ReturnMasterLock(master);
1432  return val;
1433  }
1434  ReturnMasterLock(master); // If we're the master we don't need this lock.
1435 
1436  if (!m_legacyFe && m_hasV5Stats)
1437  {
1438  bool v5_ok = false;
1439  double value = GetBitErrorRateDVBv5(&v5_ok);
1440  if (v5_ok)
1441  {
1442  if (ok)
1443  *ok = v5_ok;
1444  return value;
1445  }
1446  }
1447 
1448  uint32_t ber = 0;
1449  int ret = ioctl(m_fdFrontend, FE_READ_BER, &ber);
1450  if (ok)
1451  *ok = (0 == ret);
1452 
1453  return (double) ber;
1454 }
1455 
1457 {
1458  struct dtv_property prop = {};
1459  struct dtv_properties cmd = {};
1460 
1461  prop.cmd = DTV_STAT_ERROR_BLOCK_COUNT;
1462  cmd.num = 1;
1463  cmd.props = &prop;
1464  int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1465  if (ret < 0)
1466  {
1467  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_ERROR_BLOCK_COUNT failed" + ENO);
1468  }
1469  else
1470  {
1471 #if DTV_STAT_FULL_DEBUG
1472  LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_ERROR_BLOCK_COUNT " +
1473  QString("res=%1 len=%2 scale=%3 val=%4")
1474  .arg(cmd.props[0].result)
1475  .arg(cmd.props[0].u.st.len)
1476  .arg(cmd.props[0].u.st.stat[0].scale)
1477  .arg(cmd.props[0].u.st.stat[0].svalue));
1478 #endif
1479  }
1480 
1481  bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1482  if (ok)
1483  *ok = tmpOk;
1484  double value = 0;
1485  if (tmpOk)
1486  {
1487  if (cmd.props->u.st.stat[0].scale == FE_SCALE_COUNTER)
1488  value = cmd.props->u.st.stat[0].uvalue;
1489  }
1490  return value;
1491 }
1492 
1494 {
1495  DVBChannel *master = GetMasterLock();
1496  if (master != this)
1497  {
1498  double val = master->GetUncorrectedBlockCount(ok);
1499  ReturnMasterLock(master);
1500  return val;
1501  }
1502  ReturnMasterLock(master); // If we're the master we don't need this lock.
1503 
1504  if (!m_legacyFe && m_hasV5Stats)
1505  {
1506  bool v5_ok = false;
1507  double value = GetUncorrectedBlockCountDVBv5(&v5_ok);
1508  if (v5_ok)
1509  {
1510  if (ok)
1511  *ok = v5_ok;
1512  return value;
1513  }
1514  }
1515 
1516  uint32_t ublocks = 0;
1517  int ret = ioctl(m_fdFrontend, FE_READ_UNCORRECTED_BLOCKS, &ublocks);
1518  if (ok)
1519  *ok = (0 == ret);
1520 
1521  return static_cast<double>(ublocks);
1522 }
1523 
1525 {
1526  DTVChannel *chan = dvbm;
1528  dvbm = nullptr;
1529 }
1530 
1532 {
1534  auto *dvbm = dynamic_cast<DVBChannel*>(master);
1535  if (master && !dvbm)
1537  return dvbm;
1538 }
1539 
1540 bool DVBChannel::IsMaster(void) const
1541 {
1542  DVBChannel *master = GetMasterLock();
1543  bool is_master = (master == this);
1544  ReturnMasterLock(master);
1545  return is_master;
1546 }
1547 
1548 // Reads all the events off the queue, so we can use select in WaitForBackend.
1549 //
1550 // Note that FE_GET_EVENT is deprecated but there is no alternative yet.
1551 //
1553 {
1554  const int fd = m_fdFrontend;
1555  struct dvb_frontend_event event {};
1556  int ret = 0;
1557  while ((ret = ioctl(fd, FE_GET_EVENT, &event)) == 0);
1558  if ((ret < 0) && (EAGAIN != errno) && (EWOULDBLOCK != errno) && (EOVERFLOW != errno))
1559  {
1560  LOG(VB_CHANNEL, LOG_ERR, LOC +
1561  QString("%1 FE_GET_EVENT failed: ").arg(__func__) + logStrerror(errno));
1562  }
1563 }
1564 
1587 bool DVBChannel::WaitForBackend(std::chrono::milliseconds timeout_ms)
1588 {
1589  const int fd = m_fdFrontend;
1590  auto seconds = duration_cast<std::chrono::seconds>(timeout_ms);
1591  auto usecs = duration_cast<std::chrono::microseconds>(timeout_ms) - seconds;
1592  struct timeval select_timeout = {
1593  static_cast<typeof(select_timeout.tv_sec)>(seconds.count()),
1594  static_cast<typeof(select_timeout.tv_usec)>(usecs.count())};
1595  fd_set fd_select_set;
1596  FD_ZERO( &fd_select_set); // NOLINT(readability-isolate-declaration)
1597  FD_SET (fd, &fd_select_set);
1598 
1599  // Try to wait for some output like an event, unfortunately
1600  // this fails on several DVB cards, so we have a timeout.
1601  int ret = 0;
1602  do ret = select(fd+1, &fd_select_set, nullptr, nullptr, &select_timeout);
1603  while ((-1 == ret) && (EINTR == errno));
1604 
1605  if (-1 == ret)
1606  {
1607  LOG(VB_GENERAL, LOG_ERR, LOC +
1608  QString("%1: Failed to wait on output.").arg(__func__) + ENO);
1609 
1610  return false;
1611  }
1612 
1613  // This is supposed to work on all cards, post 2.6.12...
1614 #if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1615  fe_status_t status = FE_NONE;
1616 #else // debian9, centos7
1617  fe_status_t status = (fe_status_t)0;
1618 #endif
1619 
1620  if (ioctl(fd, FE_READ_STATUS, &status) < 0)
1621  {
1622  LOG(VB_GENERAL, LOG_ERR, LOC +
1623  QString("%1: FE_READ_STATUS failed.").arg(__func__) + ENO);
1624 
1625  return false;
1626  }
1627 
1628  LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1629  QString("%1: status: 0x%2 %3") .arg(__func__)
1630  .arg(status,2,16,QChar('0')).arg(toString(status)));
1631 
1632  return true;
1633 }
1634 
1635 // Create legacy DVBv3 frontend parameters from DTVMultiplex.
1636 //
1637 static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(
1638  DTVTunerType tuner_type, const DTVMultiplex &tuning,
1639  uint intermediate_freq, bool can_fec_auto)
1640 {
1641  dvb_frontend_parameters params {};
1642 
1643  params.frequency = tuning.m_frequency;
1644  params.inversion = (fe_spectral_inversion_t) (int) tuning.m_inversion;
1645 
1646  if (DTVTunerType::kTunerTypeDVBS1 == tuner_type)
1647  {
1648  if (tuning.m_modSys == DTVModulationSystem::kModulationSystem_DVBS2)
1649  {
1650  LOG(VB_GENERAL, LOG_ERR,
1651  "DVBChan: Cannot tune to DVB-S2 transport with DVB-S card.");
1652  }
1653 
1654  params.frequency = intermediate_freq;
1655  params.u.qpsk.symbol_rate = tuning.m_symbolRate;
1656  params.u.qpsk.fec_inner = can_fec_auto ? FEC_AUTO
1657  : (fe_code_rate_t) (int) tuning.m_fec;
1658  }
1659 
1660  if (DTVTunerType::kTunerTypeDVBS2 == tuner_type)
1661  {
1662  LOG(VB_GENERAL, LOG_ERR,
1663  "DVBChan: Cannot tune DVB-S2 card with DVBv3 API.");
1664  }
1665 
1666  if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1667  {
1668  params.u.qam.symbol_rate = tuning.m_symbolRate;
1669  params.u.qam.fec_inner = (fe_code_rate_t) (int) tuning.m_fec;
1670  params.u.qam.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1671  }
1672 
1673  if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1674  DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1675  {
1676  params.u.ofdm.bandwidth = (fe_bandwidth_t) (int) tuning.m_bandwidth;
1677  params.u.ofdm.code_rate_HP = (fe_code_rate_t) (int) tuning.m_hpCodeRate;
1678  params.u.ofdm.code_rate_LP = (fe_code_rate_t) (int) tuning.m_lpCodeRate;
1679  params.u.ofdm.constellation = (fe_modulation_t) (int) tuning.m_modulation;
1680  params.u.ofdm.transmission_mode = (fe_transmit_mode_t) (int) tuning.m_transMode;
1681  params.u.ofdm.guard_interval = (fe_guard_interval_t) (int) tuning.m_guardInterval;
1682  params.u.ofdm.hierarchy_information = (fe_hierarchy_t) (int) tuning.m_hierarchy;
1683  }
1684 
1685  if (DTVTunerType::kTunerTypeATSC == tuner_type)
1686  {
1687  params.u.vsb.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1688  }
1689 
1690  return params;
1691 }
1692 
1693 // Create DTVMultiplex from legacy DVBv3 frontend parameters.
1694 //
1696  DTVTunerType tuner_type, const dvb_frontend_parameters &params)
1697 {
1698  DTVMultiplex tuning;
1699 
1700  tuning.m_frequency = params.frequency;
1701  tuning.m_inversion = params.inversion;
1702 
1703  if ((DTVTunerType::kTunerTypeDVBS1 == tuner_type) ||
1704  (DTVTunerType::kTunerTypeDVBS2 == tuner_type))
1705  {
1706  tuning.m_symbolRate = params.u.qpsk.symbol_rate;
1707  tuning.m_fec = params.u.qpsk.fec_inner;
1708  }
1709 
1710  if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1711  {
1712  tuning.m_symbolRate = params.u.qam.symbol_rate;
1713  tuning.m_fec = params.u.qam.fec_inner;
1714  tuning.m_modulation = params.u.qam.modulation;
1715  }
1716 
1717  if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1718  DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1719  {
1720  tuning.m_bandwidth = params.u.ofdm.bandwidth;
1721  tuning.m_hpCodeRate = params.u.ofdm.code_rate_HP;
1722  tuning.m_lpCodeRate = params.u.ofdm.code_rate_LP;
1723  tuning.m_modulation = params.u.ofdm.constellation;
1724  tuning.m_transMode = params.u.ofdm.transmission_mode;
1725  tuning.m_guardInterval = params.u.ofdm.guard_interval;
1726  tuning.m_hierarchy = params.u.ofdm.hierarchy_information;
1727  }
1728 
1729  if (DTVTunerType::kTunerTypeATSC == tuner_type)
1730  {
1731  tuning.m_modulation = params.u.vsb.modulation;
1732  }
1733 
1734  return tuning;
1735 }
1736 
1737 // Create a DVBv5 property list from the dtv_multiplex
1738 //
1739 static struct dtv_properties *dtvmultiplex_to_dtvproperties(uint inputId,
1740  DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning,
1741  uint intermediate_freq, bool can_fec_auto, bool do_tune)
1742 {
1743  DTVModulationSystem delivery_system = current_sys;
1744  uint c = 0;
1745 
1746  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]: m_modsys:%2 current_sys:%3")
1747  .arg(QString::number(inputId),
1748  tuning.m_modSys.toString(),
1749  current_sys.toString()));
1750 
1751  auto *cmdseq = (struct dtv_properties*) calloc(1, sizeof(struct dtv_properties));
1752  if (!cmdseq)
1753  return nullptr;
1754 
1755  cmdseq->props = (struct dtv_property*) calloc(20, sizeof(*(cmdseq->props)));
1756  if (!(cmdseq->props))
1757  {
1758  free(cmdseq);
1759  return nullptr;
1760  }
1761 
1762  // 20201117 TODO do this only for cx24116 but not for all DVB-S2 demods
1763  //
1764  // The cx24116 DVB-S2 demod announces FE_CAN_FEC_AUTO but has apparently
1765  // trouble with FEC_AUTO on DVB-S2 transponders
1767  can_fec_auto = false;
1768 
1769  // Select delivery system in this order
1770  // - from dtv_multiplex
1771  // - modulation system in the card
1772  // - default based on tuner type
1773  //
1775  {
1776  delivery_system = tuning.m_modSys;
1777  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1778  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1779  }
1780  else if (current_sys != DTVModulationSystem::kModulationSystem_UNDEFINED)
1781  {
1782  delivery_system = current_sys;
1783  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1784  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1785  }
1786  else if (tuner_type == DTVTunerType::kTunerTypeDVBC)
1787  {
1789  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1790  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1791  }
1792  else if (tuner_type == DTVTunerType::kTunerTypeATSC)
1793  {
1795  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1796  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1797  }
1798  else if (tuner_type == DTVTunerType::kTunerTypeDVBT)
1799  {
1801  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1802  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1803  }
1804  else if (tuner_type == DTVTunerType::kTunerTypeDVBT2)
1805  {
1807  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1808  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1809  }
1810  else if (tuner_type == DTVTunerType::kTunerTypeDVBS1)
1811  {
1813  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1814  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1815  }
1816  else if (tuner_type == DTVTunerType::kTunerTypeDVBS2)
1817  {
1819  LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1820  .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1821  }
1822 
1823  LOG(VB_CHANNEL, LOG_INFO, QString("DVBChan[%1]: Delivery system: %2")
1824  .arg(inputId).arg(delivery_system.toString()));
1825 
1826  if (delivery_system != DTVModulationSystem::kModulationSystem_UNDEFINED)
1827  {
1828  cmdseq->props[c].cmd = DTV_DELIVERY_SYSTEM;
1829  cmdseq->props[c++].u.data = delivery_system;
1830  }
1831  else
1832  {
1833  LOG(VB_GENERAL, LOG_ERR, QString("DVBChan[%1]: Delivery system: %2")
1834  .arg(inputId).arg(delivery_system.toString()));
1835  }
1836 
1837  // Frequency, modulation and inversion
1838  cmdseq->props[c].cmd = DTV_FREQUENCY;
1839  cmdseq->props[c++].u.data = intermediate_freq ? intermediate_freq : tuning.m_frequency;
1840  cmdseq->props[c].cmd = DTV_MODULATION;
1841  cmdseq->props[c++].u.data = tuning.m_modulation;
1842  cmdseq->props[c].cmd = DTV_INVERSION;
1843  cmdseq->props[c++].u.data = tuning.m_inversion;
1844 
1845  // Symbol rate
1846  if (tuner_type == DTVTunerType::kTunerTypeDVBS1 ||
1847  tuner_type == DTVTunerType::kTunerTypeDVBS2 ||
1848  tuner_type == DTVTunerType::kTunerTypeDVBC)
1849  {
1850  cmdseq->props[c].cmd = DTV_SYMBOL_RATE;
1851  cmdseq->props[c++].u.data = tuning.m_symbolRate;
1852  }
1853 
1854  // Forward error correction
1855  if (tuner_type.IsFECVariable())
1856  {
1857  cmdseq->props[c].cmd = DTV_INNER_FEC;
1858  cmdseq->props[c++].u.data = can_fec_auto ? FEC_AUTO
1859  : (fe_code_rate_t) (int) tuning.m_fec;
1860  }
1861 
1862  // DVB-T/T2 properties
1863  if (tuner_type == DTVTunerType::kTunerTypeDVBT ||
1864  tuner_type == DTVTunerType::kTunerTypeDVBT2)
1865  {
1866  cmdseq->props[c].cmd = DTV_BANDWIDTH_HZ;
1867  cmdseq->props[c++].u.data = (8-tuning.m_bandwidth) * 1000000;
1868  cmdseq->props[c].cmd = DTV_CODE_RATE_HP;
1869  cmdseq->props[c++].u.data = tuning.m_hpCodeRate;
1870  cmdseq->props[c].cmd = DTV_CODE_RATE_LP;
1871  cmdseq->props[c++].u.data = tuning.m_lpCodeRate;
1872  cmdseq->props[c].cmd = DTV_TRANSMISSION_MODE;
1873  cmdseq->props[c++].u.data = tuning.m_transMode;
1874  cmdseq->props[c].cmd = DTV_GUARD_INTERVAL;
1875  cmdseq->props[c++].u.data = tuning.m_guardInterval;
1876  cmdseq->props[c].cmd = DTV_HIERARCHY;
1877  cmdseq->props[c++].u.data = tuning.m_hierarchy;
1878  }
1879 
1880  // DVB-S properties can be set on DVB-S2 tuner
1881  if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS)
1882  {
1883  cmdseq->props[c].cmd = DTV_ROLLOFF;
1884  cmdseq->props[c++].u.data = DTVRollOff::kRollOff_35;
1885  }
1886 
1887  // DVB-S2 properties
1888  if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS2)
1889  {
1890  cmdseq->props[c].cmd = DTV_PILOT;
1891  cmdseq->props[c++].u.data = PILOT_AUTO;
1892  cmdseq->props[c].cmd = DTV_ROLLOFF;
1893  cmdseq->props[c++].u.data = tuning.m_rolloff;
1894  }
1895 
1896  if (do_tune)
1897  cmdseq->props[c++].cmd = DTV_TUNE;
1898 
1899  cmdseq->num = c;
1900 
1901  return cmdseq;
1902 }
DTVMultiplex::m_frequency
uint64_t m_frequency
Definition: dtvmultiplex.h:94
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:215
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
DVBChannel::CheckModulation
bool CheckModulation(DTVModulation modulation) const
Return true iff modulation is supported modulation on the frontend.
Definition: dvbchannel.cpp:702
DTVMultiplex
Definition: dtvmultiplex.h:24
O_NONBLOCK
#define O_NONBLOCK
Definition: compat.h:341
DVBChannel::GetUncorrectedBlockCount
double GetUncorrectedBlockCount(bool *ok=nullptr) const
Returns # of uncorrected blocks since last call. First call undefined.
Definition: dvbchannel.cpp:1493
ChannelBase::Init
virtual bool Init(QString &startchannel, bool setchan)
Definition: channelbase.cpp:66
DVBChannel::Init
bool Init(QString &startchannel, bool setchan) override
Definition: dvbchannel.cpp:553
MythDate::toString
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
Definition: mythdate.cpp:93
DVBChannel::m_extModulations
uint64_t m_extModulations
Definition: dvbchannel.h:145
logStrerror
QString logStrerror(int errnum)
Verbose helper function for ENO macro.
Definition: logging.cpp:1036
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:74
DTVCodeRate::kFEC_1_2
@ kFEC_1_2
Definition: dtvconfparserhelpers.h:292
DVBChannel::ReturnMasterLock
static void ReturnMasterLock(DVBChannel *&dvbm)
Definition: dvbchannel.cpp:1524
DTVChannel::ReturnMasterLock
static void ReturnMasterLock(DTVChannelP &chan)
Definition: dtvchannel.cpp:148
DVBChannel::m_currentSys
DTVModulationSystem m_currentSys
Definition: dvbchannel.h:154
DTVTunerType::kTunerTypeDVBC
static const int kTunerTypeDVBC
Definition: dtvconfparserhelpers.h:95
dvbcam.h
DVBChannel::m_tuneLock
QMutex m_tuneLock
Definition: dvbchannel.h:158
DTVModulation::kModulationQAM256
@ kModulationQAM256
Definition: dtvconfparserhelpers.h:363
DVBChannel::IsTuningParamsProbeSupported
bool IsTuningParamsProbeSupported(void) const
Returns true iff tuning info probing is working.
Definition: dvbchannel.cpp:989
DiSEqCDevSCR::GetIntermediateFrequency
uint32_t GetIntermediateFrequency(uint32_t frequency) const
Definition: diseqc.cpp:2216
DVBChannel::m_frontendName
QString m_frontendName
Definition: dvbchannel.h:143
DTVCodeRate::kFECNone
@ kFECNone
Definition: dtvconfparserhelpers.h:291
DVBChannel::GetRotor
const DiSEqCDevRotor * GetRotor(void) const
Returns rotor object if it exists, nullptr otherwise.
Definition: dvbchannel.cpp:1159
DTVModulation::kModulation16VSB
@ kModulation16VSB
Definition: dtvconfparserhelpers.h:366
DTVMultiplex::m_rolloff
DTVRollOff m_rolloff
Definition: dtvmultiplex.h:107
DiSEqCDevRotor
Rotor class.
Definition: diseqc.h:302
DVBChannel::m_frequencyMinimum
uint64_t m_frequencyMinimum
Definition: dvbchannel.h:146
DVBChannel::DVBChannel
DVBChannel(QString device, TVRec *parent=nullptr)
Definition: dvbchannel.cpp:81
mythdb.h
DVBChannel::GetBitErrorRateDVBv5
double GetBitErrorRateDVBv5(bool *ok) const
Get Bit Error Rate from the DVBv5 interface.
Definition: dvbchannel.cpp:1375
DVBChannel::CheckCodeRate
bool CheckCodeRate(DTVCodeRate rate) const
Return true iff rate is supported rate on the frontend.
Definition: dvbchannel.cpp:683
DTVChannel::s_master_map
static MasterMap s_master_map
Definition: dtvchannel.h:179
DTVModulationSystem::kModulationSystem_DVBT
@ kModulationSystem_DVBT
Definition: dtvconfparserhelpers.h:659
DTVModulationSystem::kModulationSystem_DVBS2
@ kModulationSystem_DVBS2
Definition: dtvconfparserhelpers.h:662
DTVTunerType::kTunerTypeDVBS1
static const int kTunerTypeDVBS1
Definition: dtvconfparserhelpers.h:93
DTVCodeRate::kFEC_7_8
@ kFEC_7_8
Definition: dtvconfparserhelpers.h:298
DTVHierarchy::kHierarchyAuto
@ kHierarchyAuto
Definition: dtvconfparserhelpers.h:561
ProgramMapTable
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:694
DiSEqCDevTree::Execute
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Applies settings to the entire tree.
Definition: diseqc.cpp:509
dvbparams_to_dtvmultiplex
static DTVMultiplex dvbparams_to_dtvmultiplex(DTVTunerType tuner_type, const dvb_frontend_parameters &params)
Definition: dvbchannel.cpp:1695
DTVTransmitMode::kTransmissionModeAuto
@ kTransmissionModeAuto
Definition: dtvconfparserhelpers.h:437
VERBOSE_LEVEL_CHECK
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
Definition: mythlogging.h:29
DVBChannel::CheckOptions
void CheckOptions(DTVMultiplex &t) const override
Checks tuning for problems, and tries to fix them.
Definition: dvbchannel.cpp:576
DVBCam::Stop
bool Stop(void)
Definition: dvbcam.cpp:120
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
DTVMultiplex::m_hierarchy
DTVHierarchy m_hierarchy
Definition: dtvmultiplex.h:103
DVBChannel::m_symbolRateMaximum
uint m_symbolRateMaximum
Definition: dvbchannel.h:149
CardUtil::HasDVBCRCBug
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.
Definition: cardutil.cpp:788
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
ChannelBase::m_inputId
uint m_inputId
Definition: channelbase.h:137
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
DTVChannel::GetMasterLock
static DTVChannel * GetMasterLock(const QString &key)
Definition: dtvchannel.cpp:136
DTVMultiplex::m_bandwidth
DTVBandwidth m_bandwidth
Definition: dtvmultiplex.h:97
DiSEqCDevSettings::Load
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:128
DVBChannel::m_key
QString m_key
Definition: dvbchannel.h:173
DVBChannel::GetSignalStrength
double GetSignalStrength(bool *ok=nullptr) const
Returns signal strength in the range [0.0..1.0] (non-calibrated).
Definition: dvbchannel.cpp:1257
DVBChannel::SetPMT
void SetPMT(const ProgramMapTable *pmt)
Tells the Conditional Access Module which streams we wish to decode.
Definition: dvbchannel.cpp:727
DVBChannel::m_isOpen
IsOpenMap m_isOpen
Definition: dvbchannel.h:135
DVBChannel::m_frequencyMaximum
uint64_t m_frequencyMaximum
Definition: dvbchannel.h:147
DTVGuardInterval::kGuardIntervalAuto
@ kGuardIntervalAuto
Definition: dtvconfparserhelpers.h:502
DVBCam::IsRunning
bool IsRunning(void) const
Definition: dvbcam.h:30
dvbchannel.h
DiSEqCDevTree::Open
void Open(int fd_frontend, bool is_SCR)
Retrieve device tree.
Definition: diseqc.cpp:790
true
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:95
dtvmultiplex_to_dvbparams
static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(DTVTunerType tuner_type, const DTVMultiplex &tuning, uint intermediate_freq, bool can_fec_auto)
Definition: dvbchannel.cpp:1637
DTVCodeRate::kFEC_2_3
@ kFEC_2_3
Definition: dtvconfparserhelpers.h:293
close
#define close
Definition: compat.h:43
DVBChannel::IsMaster
bool IsMaster(void) const override
Returns true if this is the first of a number of multi-rec devs.
Definition: dvbchannel.cpp:1540
DTVCodeRate
Definition: dtvconfparserhelpers.h:280
DTVTunerType
Definition: dtvconfparserhelpers.h:76
DTVBandwidth::kBandwidthAuto
@ kBandwidthAuto
Definition: dtvconfparserhelpers.h:231
DVBChannel::m_capabilities
uint64_t m_capabilities
Definition: dvbchannel.h:144
DVBCam::SetTimeOffset
void SetTimeOffset(double offset_in_seconds)
Definition: dvbcam.cpp:375
CardUtil::SetDeliverySystem
static int SetDeliverySystem(uint inputid)
DTVMultiplex::m_inversion
DTVInversion m_inversion
Definition: dtvmultiplex.h:96
DTVModulation::kModulation8VSB
@ kModulation8VSB
Definition: dtvconfparserhelpers.h:365
DVBCam
Definition: dvbcam.h:22
TVRec::GetInputId
uint GetInputId(void) const
Returns the inputid.
Definition: tv_rec.h:234
DVBChannel::m_prevTuning
DTVMultiplex m_prevTuning
Definition: dvbchannel.h:162
DVBChannel::m_dvbCam
DVBCam * m_dvbCam
Definition: dvbchannel.h:140
DTVModulationSystem::kModulationSystem_UNDEFINED
@ kModulationSystem_UNDEFINED
Definition: dtvconfparserhelpers.h:656
dvbtypes.h
DTVMultiplex::m_mplex
uint m_mplex
Definition: dtvmultiplex.h:110
DTVRollOff::kRollOff_35
@ kRollOff_35
Definition: dtvconfparserhelpers.h:736
DTVModulationSystem::kModulationSystem_ATSC
@ kModulationSystem_ATSC
Definition: dtvconfparserhelpers.h:667
DTVModulation::kModulationQAM16
@ kModulationQAM16
Definition: dtvconfparserhelpers.h:359
CardUtil::GetMinSignalMonitoringDelay
static std::chrono::milliseconds GetMinSignalMonitoringDelay(const QString &device)
Definition: cardutil.cpp:795
DVBChannel::m_hasV5Stats
bool m_hasV5Stats
Definition: dvbchannel.h:153
ChannelBase::m_curChannelName
QString m_curChannelName
Definition: channelbase.h:135
DTVMultiplex::m_guardInterval
DTVGuardInterval m_guardInterval
Definition: dtvmultiplex.h:102
DVBChannel::WaitForBackend
bool WaitForBackend(std::chrono::milliseconds timeout_ms)
Waits for backend to get tune message.
Definition: dvbchannel.cpp:1587
DVBChannel::Tune
bool Tune(const DTVMultiplex &tuning) override
This performs the actual frequency tuning and in some cases input switching.
Definition: dvbchannel.cpp:745
DVBChannel::Close
void Close(void) override
Closes the channel changing hardware to use.
Definition: dvbchannel.h:39
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
DTVChannel::SetSIStandard
void SetSIStandard(const QString &si_std)
Sets PSIP table standard: MPEG, DVB, ATSC, or OpenCable.
Definition: dtvchannel.cpp:51
DVBChannel::~DVBChannel
~DVBChannel() override
Definition: dvbchannel.cpp:107
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
DTVTunerType::IsModulationVariable
bool IsModulationVariable(void) const
Definition: dtvconfparserhelpers.h:141
DVBCam::Start
bool Start(void)
Definition: dvbcam.cpp:88
DVBChannel::GetSNR
double GetSNR(bool *ok=nullptr) const
Returns signal/noise in the range [0..1.0].
Definition: dvbchannel.cpp:1342
DVBChannel::m_symbolRateMinimum
uint m_symbolRateMinimum
Definition: dvbchannel.h:148
DVBChannel::m_sysList
QList< DTVModulationSystem > m_sysList
Definition: dvbchannel.h:155
DVBChannel::m_fdFrontend
int m_fdFrontend
Definition: dvbchannel.h:171
DiSEqCDevSCR
Unicable / SCR Class.
Definition: diseqc.h:382
DVBChannel::m_version
uint m_version
Definition: dvbchannel.h:151
DTVModulation::kModulationQAM32
@ kModulationQAM32
Definition: dtvconfparserhelpers.h:360
DTVTunerType::toString
QString toString() const
Definition: dtvconfparserhelpers.h:154
DTVMultiplex::m_hpCodeRate
DTVCodeRate m_hpCodeRate
Definition: dtvmultiplex.h:98
LOC
#define LOC
Definition: dvbchannel.cpp:71
DVBChannel::m_diseqcSettings
DiSEqCDevSettings m_diseqcSettings
Definition: dvbchannel.h:138
DiSEqCDevLNB
LNB Class.
Definition: diseqc.h:446
DTVModulation::kModulation16APSK
@ kModulation16APSK
Definition: dtvconfparserhelpers.h:368
DTVMultiplex::m_modSys
DTVModulationSystem m_modSys
Definition: dtvmultiplex.h:106
DTVMultiplex::m_fec
DTVCodeRate m_fec
Definition: dtvmultiplex.h:105
DTVMultiplex::toString
QString toString() const
Definition: dtvmultiplex.cpp:35
DVBChannel::m_sigMonDelay
std::chrono::milliseconds m_sigMonDelay
Definition: dvbchannel.h:167
MythCoreContext::GetDVBv3
bool GetDVBv3(void) const
Definition: mythcorecontext.h:330
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:55
DVBChannel::m_legacyFe
bool m_legacyFe
Definition: dvbchannel.h:152
DVBChannel::m_lastLnbDevId
uint m_lastLnbDevId
Definition: dvbchannel.h:164
DiSEqCDev::FindTree
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:237
DTVCodeRate::kFEC_5_6
@ kFEC_5_6
Definition: dtvconfparserhelpers.h:296
DVBChannel::m_desiredTuning
DTVMultiplex m_desiredTuning
Definition: dvbchannel.h:161
DVBChannel::GetUncorrectedBlockCountDVBv5
double GetUncorrectedBlockCountDVBv5(bool *ok) const
Get Uncorrected Block Count from the DVBv5 interface.
Definition: dvbchannel.cpp:1456
DTVTunerType::IsFECVariable
bool IsFECVariable(void) const
Definition: dtvconfparserhelpers.h:134
DVBChannel::Retune
bool Retune(void) override
Definition: dvbchannel.cpp:981
channelutil.h
DTVTunerType::kTunerTypeDVBS2
static const int kTunerTypeDVBS2
Definition: dtvconfparserhelpers.h:94
DTVMultiplex::m_symbolRate
uint64_t m_symbolRate
Definition: dtvmultiplex.h:95
DiSEqCDevTree::FindLNB
DiSEqCDevLNB * FindLNB(const DiSEqCDevSettings &settings)
Returns the LNB device object selected by the configuration chain.
Definition: diseqc.cpp:573
DTVModulationSystem::toString
QString toString() const
Definition: dtvconfparserhelpers.h:719
CardUtil::GetDeviceName
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
Definition: cardutil.cpp:2965
DVBChannel::GetBitErrorRate
double GetBitErrorRate(bool *ok=nullptr) const
Returns # of corrected bits since last call. First call undefined.
Definition: dvbchannel.cpp:1425
DiSEqCDevTree::Close
void Close(void)
Definition: diseqc.h:108
MythDate::currentMSecsSinceEpochAsDuration
std::chrono::milliseconds currentMSecsSinceEpochAsDuration(void)
Definition: mythdate.cpp:207
DTVModulationSystem::kModulationSystem_DVBS
@ kModulationSystem_DVBS
Definition: dtvconfparserhelpers.h:661
DTVModulation::kModulationQAM128
@ kModulationQAM128
Definition: dtvconfparserhelpers.h:362
DVBChannel
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:31
DTVCodeRate::kFEC_3_4
@ kFEC_3_4
Definition: dtvconfparserhelpers.h:294
DTVCodeRate::kFEC_4_5
@ kFEC_4_5
Definition: dtvconfparserhelpers.h:295
DVBChannel::Open
bool Open(void) override
Opens the channel changing hardware for use.
Definition: dvbchannel.h:37
DVBChannel::GetSNRDVBv5
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 ...
Definition: dvbchannel.cpp:1290
DTVModulation::kModulation32APSK
@ kModulation32APSK
Definition: dtvconfparserhelpers.h:369
DTVChannel::m_tunerType
DTVTunerType m_tunerType
Definition: dtvchannel.h:161
DTVChannel::s_master_map_lock
static QReadWriteLock s_master_map_lock
Definition: dtvchannel.h:178
dtvmultiplex_to_dtvproperties
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)
Definition: dvbchannel.cpp:1739
DVBChannel::m_hwLock
QRecursiveMutex m_hwLock
Definition: dvbchannel.h:159
DiSEqCDevTree::FindRotor
DiSEqCDevRotor * FindRotor(const DiSEqCDevSettings &settings, uint index=0)
Returns the nth rotor device object in the tree.
Definition: diseqc.cpp:550
DTVModulationSystem
Definition: dtvconfparserhelpers.h:644
cardutil.h
DVBChannel::m_firstTune
bool m_firstTune
Definition: dvbchannel.h:168
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
DVBChannel::SetTimeOffset
void SetTimeOffset(double offset)
Tells the Conditional Access Module the offset from the computers utc time to dvb time.
Definition: dvbchannel.cpp:739
DVBChannel::m_tuningDelay
std::chrono::milliseconds m_tuningDelay
Definition: dvbchannel.h:166
DVBChannel::CheckFrequency
void CheckFrequency(uint64_t frequency) const
Checks tuning frequency.
Definition: dvbchannel.cpp:564
DVBChannel::m_diseqcTree
DiSEqCDevTree * m_diseqcTree
Definition: dvbchannel.h:139
DTVTunerType::IsDiSEqCSupported
bool IsDiSEqCSupported(void) const
Definition: dtvconfparserhelpers.h:148
CardUtil::GetDeliverySystem
static DTVModulationSystem GetDeliverySystem(uint inputid)
Definition: cardutil.cpp:906
TVRec
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:142
DTVModulationSystem::kModulationSystem_DVBT2
@ kModulationSystem_DVBT2
Definition: dtvconfparserhelpers.h:672
DTVMultiplex::m_sistandard
QString m_sistandard
Definition: dtvmultiplex.h:111
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_A
@ kModulationSystem_DVBC_ANNEX_A
Definition: dtvconfparserhelpers.h:657
DVBCam::SetPMT
void SetPMT(const ChannelBase *chan, const ProgramMapTable *pmt)
Definition: dvbcam.cpp:342
DiSEqCDevTree::FindSCR
DiSEqCDevSCR * FindSCR(const DiSEqCDevSettings &settings)
Returns the SCR device object selected by the configuration chain.
Definition: diseqc.cpp:596
CardUtil::GetSourceID
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1946
DVBChannel::ProbeTuningParams
bool ProbeTuningParams(DTVMultiplex &tuning) const
Fetches DTVMultiplex params from driver.
Definition: dvbchannel.cpp:1035
DVBChannel::HasLock
bool HasLock(bool *ok=nullptr) const
Returns true iff we have a signal carrier lock.
Definition: dvbchannel.cpp:1167
DTVInversion::kInversionOff
@ kInversionOff
Definition: dtvconfparserhelpers.h:173
tv_rec.h
DVBChannel::m_hasCrcBug
bool m_hasCrcBug
Definition: dvbchannel.h:174
DVBChannel::m_device
QString m_device
Definition: dvbchannel.h:172
DVBChannel::GetMasterLock
DVBChannel * GetMasterLock(void) const
Definition: dvbchannel.cpp:1531
concurrent_tunings_delay
static constexpr std::chrono::milliseconds concurrent_tunings_delay
Definition: dvbchannel.cpp:68
DTVCodeRate::kFEC_8_9
@ kFEC_8_9
Definition: dtvconfparserhelpers.h:299
DTVCodeRate::kFEC_6_7
@ kFEC_6_7
Definition: dtvconfparserhelpers.h:297
CardUtil::ConvertToTunerType
static DTVTunerType ConvertToTunerType(DTVModulationSystem delsys)
Definition: cardutil.cpp:805
DTVMultiplex::m_modulation
DTVModulation m_modulation
Definition: dtvmultiplex.h:100
DTVTunerType::kTunerTypeATSC
static const int kTunerTypeATSC
Definition: dtvconfparserhelpers.h:98
DVBChannel::IsOpen
bool IsOpen(void) const override
Reports whether channel is already open.
Definition: dvbchannel.cpp:545
DTVModulation::kModulationQAMAuto
@ kModulationQAMAuto
Definition: dtvconfparserhelpers.h:364
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3
DVBChannel::GetChanID
int GetChanID(void) const override
Returns Channel ID.
Definition: dvbchannel.cpp:1095
azlyrics.info
dictionary info
Definition: azlyrics.py:7
DTVChannel
Class providing a generic interface to digital tuning hardware.
Definition: dtvchannel.h:33
DiSEqCDevDevice::GetDeviceID
uint GetDeviceID(void) const
Definition: diseqc.h:170
DTVTunerType::kTunerTypeDVBT
static const int kTunerTypeDVBT
Definition: dtvconfparserhelpers.h:96
DTVModulation::kModulationQAM64
@ kModulationQAM64
Definition: dtvconfparserhelpers.h:361
DVBChannel::DrainDVBEvents
void DrainDVBEvents(void)
Definition: dvbchannel.cpp:1552
CardUtil::CapabilitiesToString
static QStringList CapabilitiesToString(uint64_t capabilities)
Definition: cardutil.cpp:2473
DTVMultiplex::IsEqual
bool IsEqual(DTVTunerType type, const DTVMultiplex &other, uint freq_range=0, bool fuzzy=false) const
Definition: dtvmultiplex.cpp:52
DTVCodeRate::kFECAuto
@ kFECAuto
Definition: dtvconfparserhelpers.h:300
DTVTunerType::kTunerTypeDVBT2
static const int kTunerTypeDVBT2
Definition: dtvconfparserhelpers.h:97
DVBChannel::GetSignalStrengthDVBv5
double GetSignalStrengthDVBv5(bool *ok) const
Get Signal strength from the DVBv5 interface [0-1.0] It is transformed to a linear relative scale if ...
Definition: dvbchannel.cpp:1201
ChannelBase::InitializeInput
virtual bool InitializeInput(void)
Fills in input map from DB.
Definition: channelbase.cpp:554
DVBChannel::m_tuneDelayLock
QMutex m_tuneDelayLock
Definition: dvbchannel.h:177
DVBChannel::s_lastTuning
static std::chrono::milliseconds s_lastTuning
Definition: dvbchannel.h:176
DTVInversion::kInversionAuto
@ kInversionAuto
Definition: dtvconfparserhelpers.h:175
DTVModulation::kModulationQPSK
@ kModulationQPSK
Definition: dtvconfparserhelpers.h:358
DTVModulation::kModulation8PSK
@ kModulation8PSK
Definition: dtvconfparserhelpers.h:367
DTVMultiplex::m_transMode
DTVTransmitMode m_transMode
Definition: dtvmultiplex.h:101
ChannelBase::m_pParent
TVRec * m_pParent
Definition: channelbase.h:134
DTVModulation
Definition: dtvconfparserhelpers.h:347
uint
unsigned int uint
Definition: freesurround.h:24
DiSEqCDevLNB::GetIntermediateFrequency
uint32_t GetIntermediateFrequency(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning) const
Calculate proper intermediate frequency for the given settings and tuning parameters.
Definition: diseqc.cpp:2523
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
DTVMultiplex::m_lpCodeRate
DTVCodeRate m_lpCodeRate
Definition: dtvmultiplex.h:99
DVB_DEV_FRONTEND
@ DVB_DEV_FRONTEND
Definition: cardutil.h:30