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