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