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