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 sl.reserve(idlist.size());
1142 for (auto chanid : idlist)
1143 {
1144 sl.append(QString::number(chanid));
1145 }
1146 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1147 QString("Found for '%1' multiple visible channel IDs: %2")
1148 .arg(m_curChannelName, sl.join(" ")));
1149 }
1150 else
1151 {
1152 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1153 QString("Found visible channel ID %1 for '%2'")
1154 .arg(id).arg(m_curChannelName));
1155 }
1156 }
1157
1158 return id;
1159}
1160
1162{
1163 if (m_diseqcTree)
1165
1166 return nullptr;
1167}
1168
1169bool DVBChannel::HasLock(bool *ok) const
1170{
1171 DVBChannel *master = GetMasterLock();
1172 if (master != this)
1173 {
1174 bool haslock = master->HasLock(ok);
1175 ReturnMasterLock(master);
1176 return haslock;
1177 }
1178 ReturnMasterLock(master); // If we're the master we don't need this lock.
1179
1180#if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1181 fe_status_t status = FE_NONE;
1182#else // debian9, centos7
1183 fe_status_t status = (fe_status_t)0;
1184#endif
1185
1186 int ret = ioctl(m_fdFrontend, FE_READ_STATUS, &status);
1187 if (ret < 0)
1188 {
1189 LOG(VB_GENERAL, LOG_ERR, LOC + "FE_READ_STATUS failed" + ENO);
1190 }
1191 else
1192 {
1193 LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("%1 status: 0x%2 %3")
1194 .arg(__func__).arg(status,2,16,QChar('0')).arg(toString(status)));
1195 }
1196
1197 if (ok)
1198 *ok = (0 == ret);
1199
1200 return (status & FE_HAS_LOCK) != 0;
1201}
1202
1204{
1205 struct dtv_property prop = {};
1206 struct dtv_properties cmd = {};
1207
1208 prop.cmd = DTV_STAT_SIGNAL_STRENGTH;
1209 cmd.num = 1;
1210 cmd.props = &prop;
1211 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1212 if (ret < 0)
1213 {
1214 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_SIGNAL_STRENGTH failed" + ENO);
1215 }
1216 else
1217 {
1218#if DTV_STAT_FULL_DEBUG
1219 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_SIGNAL_STRENGTH " +
1220 QString("res=%1 len=%2 scale=%3 val=%4")
1221 .arg(cmd.props->result)
1222 .arg(cmd.props->u.st.len)
1223 .arg(cmd.props->u.st.stat[0].scale)
1224 .arg(cmd.props->u.st.stat[0].svalue));
1225#endif
1226 }
1227
1228 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1229 if (ok)
1230 *ok = tmpOk;
1231
1232 double value = 0;
1233 if (tmpOk)
1234 {
1235 if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1236 {
1237 // Convert range of -100dBm .. 0dBm to 0% .. 100%
1238 // Note that -100dBm is lower than the noise floor.
1239 // The measured svalue is in units of 0.001 dBm.
1240 // If the value is outside the range -100 to 0 dBm we do not believe it.
1241 int64_t svalue = cmd.props->u.st.stat[0].svalue;
1242 if (svalue >= -100000 && svalue <= 0)
1243 {
1244 // convert value from -100dBm to 0dBm to a 0-1 range
1245 value = svalue + 100000;
1246 value = value / 100000.0;
1247 value = std::min(value, 1.0);
1248 }
1249 }
1250 else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1251 {
1252 // Return as 16 bit unsigned
1253 value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1254 }
1255 }
1256 return value;
1257}
1258
1259double DVBChannel::GetSignalStrength(bool *ok) const
1260{
1261 DVBChannel *master = GetMasterLock();
1262 if (master != this)
1263 {
1264 double val = master->GetSignalStrength(ok);
1265 ReturnMasterLock(master);
1266 return val;
1267 }
1268 ReturnMasterLock(master); // If we're the master we don't need this lock.
1269
1270 if (!m_legacyFe && m_hasV5Stats)
1271 {
1272 bool v5_ok = false;
1273 double value = GetSignalStrengthDVBv5(&v5_ok);
1274 if (v5_ok)
1275 {
1276 if (ok)
1277 *ok = v5_ok;
1278 return value;
1279 }
1280 }
1281
1282 // We use uint16_t for sig because this is correct for DVB API 4.0,
1283 // and works better than the correct int16_t for the 3.x API
1284 uint16_t sig = 0;
1285 int ret = ioctl(m_fdFrontend, FE_READ_SIGNAL_STRENGTH, &sig);
1286 if (ok)
1287 *ok = (0 == ret);
1288
1289 return sig * (1.0 / 65535.0);
1290}
1291
1292double DVBChannel::GetSNRDVBv5(bool *ok) const
1293{
1294 struct dtv_property prop = {};
1295 struct dtv_properties cmd = {};
1296
1297 prop.cmd = DTV_STAT_CNR;
1298 cmd.num = 1;
1299 cmd.props = &prop;
1300 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1301 if (ret < 0)
1302 {
1303 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_CNR failed" + ENO);
1304 }
1305 else
1306 {
1307#if DTV_STAT_FULL_DEBUG
1308 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_CNR " +
1309 QString("res=%1 len=%2 scale=%3 val=%4")
1310 .arg(cmd.props->result)
1311 .arg(cmd.props->u.st.len)
1312 .arg(cmd.props->u.st.stat[0].scale)
1313 .arg(cmd.props->u.st.stat[0].svalue));
1314#endif
1315 }
1316
1317 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1318 if (ok)
1319 *ok = tmpOk;
1320 double value = 0;
1321 if (tmpOk)
1322 {
1323 if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1324 {
1325 // The measured svalue is in units of 0.001 dB
1326 // Let 50dB+ CNR be 100% quality and 0dB be 0%
1327 // Convert 0.001 dB from 0-50000 to a 0-1 range
1328 value = cmd.props->u.st.stat[0].svalue;
1329 value = value / 50000.0;
1330 if (value > 1.0)
1331 value = 1.0;
1332 else if (value < 0)
1333 value = 0.0;
1334 }
1335 else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1336 {
1337 // Return as 16 bit unsigned
1338 value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1339 }
1340 }
1341 return value;
1342}
1343
1344double DVBChannel::GetSNR(bool *ok) const
1345{
1346 DVBChannel *master = GetMasterLock();
1347 if (master != this)
1348 {
1349 double val = master->GetSNR(ok);
1350 ReturnMasterLock(master);
1351 return val;
1352 }
1353 ReturnMasterLock(master); // If we're the master we don't need this lock.
1354
1355 if (!m_legacyFe && m_hasV5Stats)
1356 {
1357 bool v5_ok = false;
1358 double value = GetSNRDVBv5(&v5_ok);
1359 if (v5_ok)
1360 {
1361 if (ok)
1362 *ok = v5_ok;
1363 return value;
1364 }
1365 }
1366
1367 // We use uint16_t for sig because this is correct for DVB API 4.0,
1368 // and works better than the correct int16_t for the 3.x API
1369 uint16_t snr = 0;
1370 int ret = ioctl(m_fdFrontend, FE_READ_SNR, &snr);
1371 if (ok)
1372 *ok = (0 == ret);
1373
1374 return snr * (1.0 / 65535.0);
1375}
1376
1378{
1379 std::array<struct dtv_property,2> prop {};
1380 struct dtv_properties cmd = {};
1381
1382 prop[0].cmd = DTV_STAT_POST_ERROR_BIT_COUNT;
1383 prop[1].cmd = DTV_STAT_POST_TOTAL_BIT_COUNT;
1384 cmd.num = prop.size();
1385 cmd.props = prop.data();
1386 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1387 if (ret < 0)
1388 {
1389 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_POST_ERROR_BIT_COUNT failed" + ENO);
1390 }
1391 else
1392 {
1393#if DTV_STAT_FULL_DEBUG
1394 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_POST_ERROR_BIT_COUNT " +
1395 QString("res=%1 len=%2 scale=%3 val=%4 res=%5 len=%6 scale=%7 val=%8")
1396 .arg(cmd.props[0].result)
1397 .arg(cmd.props[0].u.st.len)
1398 .arg(cmd.props[0].u.st.stat[0].scale)
1399 .arg(cmd.props[0].u.st.stat[0].uvalue)
1400 .arg(cmd.props[1].result)
1401 .arg(cmd.props[1].u.st.len)
1402 .arg(cmd.props[1].u.st.stat[0].scale)
1403 .arg(cmd.props[1].u.st.stat[0].uvalue));
1404#endif
1405 }
1406
1407 bool tmpOk = (ret == 0) &&
1408 (cmd.props[0].u.st.len > 0) &&
1409 (cmd.props[1].u.st.len > 0);
1410 if (ok)
1411 *ok = tmpOk;
1412 double value = 0;
1413 if (tmpOk)
1414 {
1415 if ((cmd.props[0].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1416 (cmd.props[1].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1417 (cmd.props[1].u.st.stat[0].uvalue != 0))
1418 {
1419 value = static_cast<double>(
1420 static_cast<long double>(cmd.props[0].u.st.stat[0].uvalue) /
1421 cmd.props[1].u.st.stat[0].uvalue);
1422 }
1423 }
1424 return value;
1425}
1426
1427double DVBChannel::GetBitErrorRate(bool *ok) const
1428{
1429 DVBChannel *master = GetMasterLock();
1430 if (master != this)
1431 {
1432 double val = master->GetBitErrorRate(ok);
1433 ReturnMasterLock(master);
1434 return val;
1435 }
1436 ReturnMasterLock(master); // If we're the master we don't need this lock.
1437
1438 if (!m_legacyFe && m_hasV5Stats)
1439 {
1440 bool v5_ok = false;
1441 double value = GetBitErrorRateDVBv5(&v5_ok);
1442 if (v5_ok)
1443 {
1444 if (ok)
1445 *ok = v5_ok;
1446 return value;
1447 }
1448 }
1449
1450 uint32_t ber = 0;
1451 int ret = ioctl(m_fdFrontend, FE_READ_BER, &ber);
1452 if (ok)
1453 *ok = (0 == ret);
1454
1455 return (double) ber;
1456}
1457
1459{
1460 struct dtv_property prop = {};
1461 struct dtv_properties cmd = {};
1462
1463 prop.cmd = DTV_STAT_ERROR_BLOCK_COUNT;
1464 cmd.num = 1;
1465 cmd.props = &prop;
1466 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1467 if (ret < 0)
1468 {
1469 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_ERROR_BLOCK_COUNT failed" + ENO);
1470 }
1471 else
1472 {
1473#if DTV_STAT_FULL_DEBUG
1474 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_ERROR_BLOCK_COUNT " +
1475 QString("res=%1 len=%2 scale=%3 val=%4")
1476 .arg(cmd.props[0].result)
1477 .arg(cmd.props[0].u.st.len)
1478 .arg(cmd.props[0].u.st.stat[0].scale)
1479 .arg(cmd.props[0].u.st.stat[0].svalue));
1480#endif
1481 }
1482
1483 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1484 if (ok)
1485 *ok = tmpOk;
1486 double value = 0;
1487 if (tmpOk)
1488 {
1489 if (cmd.props->u.st.stat[0].scale == FE_SCALE_COUNTER)
1490 value = cmd.props->u.st.stat[0].uvalue;
1491 }
1492 return value;
1493}
1494
1496{
1497 DVBChannel *master = GetMasterLock();
1498 if (master != this)
1499 {
1500 double val = master->GetUncorrectedBlockCount(ok);
1501 ReturnMasterLock(master);
1502 return val;
1503 }
1504 ReturnMasterLock(master); // If we're the master we don't need this lock.
1505
1506 if (!m_legacyFe && m_hasV5Stats)
1507 {
1508 bool v5_ok = false;
1509 double value = GetUncorrectedBlockCountDVBv5(&v5_ok);
1510 if (v5_ok)
1511 {
1512 if (ok)
1513 *ok = v5_ok;
1514 return value;
1515 }
1516 }
1517
1518 uint32_t ublocks = 0;
1519 int ret = ioctl(m_fdFrontend, FE_READ_UNCORRECTED_BLOCKS, &ublocks);
1520 if (ok)
1521 *ok = (0 == ret);
1522
1523 return static_cast<double>(ublocks);
1524}
1525
1527{
1528 DTVChannel *chan = dvbm;
1530 dvbm = nullptr;
1531}
1532
1534{
1536 auto *dvbm = dynamic_cast<DVBChannel*>(master);
1537 if (master && !dvbm)
1539 return dvbm;
1540}
1541
1542bool DVBChannel::IsMaster(void) const
1543{
1544 DVBChannel *master = GetMasterLock();
1545 bool is_master = (master == this);
1546 ReturnMasterLock(master);
1547 return is_master;
1548}
1549
1550// Reads all the events off the queue, so we can use select in WaitForBackend.
1551//
1552// Note that FE_GET_EVENT is deprecated but there is no alternative yet.
1553//
1555{
1556 const int fd = m_fdFrontend;
1557 struct dvb_frontend_event event {};
1558 int ret = 0;
1559 while ((ret = ioctl(fd, FE_GET_EVENT, &event)) == 0);
1560 if ((ret < 0) && (EAGAIN != errno) && (EWOULDBLOCK != errno) && (EOVERFLOW != errno))
1561 {
1562 LOG(VB_CHANNEL, LOG_ERR, LOC +
1563 QString("%1 FE_GET_EVENT failed: ").arg(__func__) + logStrerror(errno));
1564 }
1565}
1566
1589bool DVBChannel::WaitForBackend(std::chrono::milliseconds timeout_ms)
1590{
1591 const int fd = m_fdFrontend;
1592 auto seconds = duration_cast<std::chrono::seconds>(timeout_ms);
1593 auto usecs = duration_cast<std::chrono::microseconds>(timeout_ms) - seconds;
1594 struct timeval select_timeout = {
1595 .tv_sec=static_cast<time_t>(seconds.count()),
1596 .tv_usec=static_cast<suseconds_t>(usecs.count())};
1597 fd_set fd_select_set;
1598 FD_ZERO( &fd_select_set); // NOLINT(readability-isolate-declaration)
1599 FD_SET (fd, &fd_select_set);
1600
1601 // Try to wait for some output like an event, unfortunately
1602 // this fails on several DVB cards, so we have a timeout.
1603 int ret = select(fd+1, &fd_select_set, nullptr, nullptr, &select_timeout);
1604 while ((-1 == ret) && (EINTR == errno))
1605 ret = select(fd+1, &fd_select_set, nullptr, nullptr, &select_timeout);
1606
1607 if (-1 == ret)
1608 {
1609 LOG(VB_GENERAL, LOG_ERR, LOC +
1610 QString("%1: Failed to wait on output.").arg(__func__) + ENO);
1611
1612 return false;
1613 }
1614
1615 // This is supposed to work on all cards, post 2.6.12...
1616#if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1617 fe_status_t status = FE_NONE;
1618#else // debian9, centos7
1619 fe_status_t status = (fe_status_t)0;
1620#endif
1621
1622 if (ioctl(fd, FE_READ_STATUS, &status) < 0)
1623 {
1624 LOG(VB_GENERAL, LOG_ERR, LOC +
1625 QString("%1: FE_READ_STATUS failed.").arg(__func__) + ENO);
1626
1627 return false;
1628 }
1629
1630 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1631 QString("%1: status: 0x%2 %3") .arg(__func__)
1632 .arg(status,2,16,QChar('0')).arg(toString(status)));
1633
1634 return true;
1635}
1636
1637// Create legacy DVBv3 frontend parameters from DTVMultiplex.
1638//
1639static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(
1640 DTVTunerType tuner_type, const DTVMultiplex &tuning,
1641 uint intermediate_freq, bool can_fec_auto)
1642{
1643 dvb_frontend_parameters params {};
1644
1645 params.frequency = tuning.m_frequency;
1646 params.inversion = (fe_spectral_inversion_t) (int) tuning.m_inversion;
1647
1648 if (DTVTunerType::kTunerTypeDVBS1 == tuner_type)
1649 {
1650 if (tuning.m_modSys == DTVModulationSystem::kModulationSystem_DVBS2)
1651 {
1652 LOG(VB_GENERAL, LOG_ERR,
1653 "DVBChan: Cannot tune to DVB-S2 transport with DVB-S card.");
1654 }
1655
1656 params.frequency = intermediate_freq;
1657 params.u.qpsk.symbol_rate = tuning.m_symbolRate;
1658 params.u.qpsk.fec_inner = can_fec_auto ? FEC_AUTO
1659 : (fe_code_rate_t) (int) tuning.m_fec;
1660 }
1661
1662 if (DTVTunerType::kTunerTypeDVBS2 == tuner_type)
1663 {
1664 LOG(VB_GENERAL, LOG_ERR,
1665 "DVBChan: Cannot tune DVB-S2 card with DVBv3 API.");
1666 }
1667
1668 if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1669 {
1670 params.u.qam.symbol_rate = tuning.m_symbolRate;
1671 params.u.qam.fec_inner = (fe_code_rate_t) (int) tuning.m_fec;
1672 params.u.qam.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1673 }
1674
1675 if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1676 DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1677 {
1678 params.u.ofdm.bandwidth = (fe_bandwidth_t) (int) tuning.m_bandwidth;
1679 params.u.ofdm.code_rate_HP = (fe_code_rate_t) (int) tuning.m_hpCodeRate;
1680 params.u.ofdm.code_rate_LP = (fe_code_rate_t) (int) tuning.m_lpCodeRate;
1681 params.u.ofdm.constellation = (fe_modulation_t) (int) tuning.m_modulation;
1682 params.u.ofdm.transmission_mode = (fe_transmit_mode_t) (int) tuning.m_transMode;
1683 params.u.ofdm.guard_interval = (fe_guard_interval_t) (int) tuning.m_guardInterval;
1684 params.u.ofdm.hierarchy_information = (fe_hierarchy_t) (int) tuning.m_hierarchy;
1685 }
1686
1687 if (DTVTunerType::kTunerTypeATSC == tuner_type)
1688 {
1689 params.u.vsb.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1690 }
1691
1692 return params;
1693}
1694
1695// Create DTVMultiplex from legacy DVBv3 frontend parameters.
1696//
1698 DTVTunerType tuner_type, const dvb_frontend_parameters &params)
1699{
1700 DTVMultiplex tuning;
1701
1702 tuning.m_frequency = params.frequency;
1703 tuning.m_inversion = params.inversion;
1704
1705 if ((DTVTunerType::kTunerTypeDVBS1 == tuner_type) ||
1706 (DTVTunerType::kTunerTypeDVBS2 == tuner_type))
1707 {
1708 tuning.m_symbolRate = params.u.qpsk.symbol_rate;
1709 tuning.m_fec = params.u.qpsk.fec_inner;
1710 }
1711
1712 if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1713 {
1714 tuning.m_symbolRate = params.u.qam.symbol_rate;
1715 tuning.m_fec = params.u.qam.fec_inner;
1716 tuning.m_modulation = params.u.qam.modulation;
1717 }
1718
1719 if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1720 DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1721 {
1722 tuning.m_bandwidth = params.u.ofdm.bandwidth;
1723 tuning.m_hpCodeRate = params.u.ofdm.code_rate_HP;
1724 tuning.m_lpCodeRate = params.u.ofdm.code_rate_LP;
1725 tuning.m_modulation = params.u.ofdm.constellation;
1726 tuning.m_transMode = params.u.ofdm.transmission_mode;
1727 tuning.m_guardInterval = params.u.ofdm.guard_interval;
1728 tuning.m_hierarchy = params.u.ofdm.hierarchy_information;
1729 }
1730
1731 if (DTVTunerType::kTunerTypeATSC == tuner_type)
1732 {
1733 tuning.m_modulation = params.u.vsb.modulation;
1734 }
1735
1736 return tuning;
1737}
1738
1739// Create a DVBv5 property list from the dtv_multiplex
1740//
1741static struct dtv_properties *dtvmultiplex_to_dtvproperties(uint inputId,
1742 DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning,
1743 uint intermediate_freq, bool can_fec_auto, bool do_tune)
1744{
1745 DTVModulationSystem delivery_system = current_sys;
1746 uint c = 0;
1747
1748 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]: m_modsys:%2 current_sys:%3")
1749 .arg(QString::number(inputId),
1750 tuning.m_modSys.toString(),
1751 current_sys.toString()));
1752
1753 // C library structure. NOLINTBEGIN(cppcoreguidelines-no-malloc)
1754 auto *cmdseq = (struct dtv_properties*) calloc(1, sizeof(struct dtv_properties));
1755 if (!cmdseq)
1756 return nullptr;
1757
1758 cmdseq->props = (struct dtv_property*) calloc(20, sizeof(*(cmdseq->props)));
1759 if (!(cmdseq->props))
1760 {
1761 free(cmdseq);
1762 return nullptr;
1763 }
1764 // NOLINTEND(cppcoreguidelines-no-malloc)
1765
1766 // 20201117 TODO do this only for cx24116 but not for all DVB-S2 demods
1767 //
1768 // The cx24116 DVB-S2 demod announces FE_CAN_FEC_AUTO but has apparently
1769 // trouble with FEC_AUTO on DVB-S2 transponders
1771 can_fec_auto = false;
1772
1773 // Select delivery system in this order
1774 // - from dtv_multiplex
1775 // - modulation system in the card
1776 // - default based on tuner type
1777 //
1779 {
1780 delivery_system = tuning.m_modSys;
1781 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1782 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1783 }
1785 {
1786 delivery_system = current_sys;
1787 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1788 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1789 }
1790 else if (tuner_type == DTVTunerType::kTunerTypeDVBC)
1791 {
1793 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1794 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1795 }
1796 else if (tuner_type == DTVTunerType::kTunerTypeATSC)
1797 {
1799 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1800 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1801 }
1802 else if (tuner_type == DTVTunerType::kTunerTypeDVBT)
1803 {
1805 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1806 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1807 }
1808 else if (tuner_type == DTVTunerType::kTunerTypeDVBT2)
1809 {
1811 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1812 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1813 }
1814 else if (tuner_type == DTVTunerType::kTunerTypeDVBS1)
1815 {
1817 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1818 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1819 }
1820 else if (tuner_type == DTVTunerType::kTunerTypeDVBS2)
1821 {
1823 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1824 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1825 }
1826
1827 LOG(VB_CHANNEL, LOG_INFO, QString("DVBChan[%1]: Delivery system: %2")
1828 .arg(inputId).arg(delivery_system.toString()));
1829
1831 {
1832 cmdseq->props[c].cmd = DTV_DELIVERY_SYSTEM;
1833 cmdseq->props[c++].u.data = delivery_system;
1834 }
1835 else
1836 {
1837 LOG(VB_GENERAL, LOG_ERR, QString("DVBChan[%1]: Delivery system: %2")
1838 .arg(inputId).arg(delivery_system.toString()));
1839 }
1840
1841 // Frequency, modulation and inversion
1842 cmdseq->props[c].cmd = DTV_FREQUENCY;
1843 cmdseq->props[c++].u.data = intermediate_freq ? intermediate_freq : tuning.m_frequency;
1844 cmdseq->props[c].cmd = DTV_MODULATION;
1845 cmdseq->props[c++].u.data = tuning.m_modulation;
1846 cmdseq->props[c].cmd = DTV_INVERSION;
1847 cmdseq->props[c++].u.data = tuning.m_inversion;
1848
1849 // Symbol rate
1850 if (tuner_type == DTVTunerType::kTunerTypeDVBS1 ||
1851 tuner_type == DTVTunerType::kTunerTypeDVBS2 ||
1852 tuner_type == DTVTunerType::kTunerTypeDVBC)
1853 {
1854 cmdseq->props[c].cmd = DTV_SYMBOL_RATE;
1855 cmdseq->props[c++].u.data = tuning.m_symbolRate;
1856 }
1857
1858 // Forward error correction
1859 if (tuner_type.IsFECVariable())
1860 {
1861 cmdseq->props[c].cmd = DTV_INNER_FEC;
1862 cmdseq->props[c++].u.data = can_fec_auto ? FEC_AUTO
1863 : (fe_code_rate_t) (int) tuning.m_fec;
1864 }
1865
1866 // DVB-T/T2 properties
1867 if (tuner_type == DTVTunerType::kTunerTypeDVBT ||
1868 tuner_type == DTVTunerType::kTunerTypeDVBT2)
1869 {
1870 cmdseq->props[c].cmd = DTV_BANDWIDTH_HZ;
1871 cmdseq->props[c++].u.data = (8-tuning.m_bandwidth) * 1000000;
1872 cmdseq->props[c].cmd = DTV_CODE_RATE_HP;
1873 cmdseq->props[c++].u.data = tuning.m_hpCodeRate;
1874 cmdseq->props[c].cmd = DTV_CODE_RATE_LP;
1875 cmdseq->props[c++].u.data = tuning.m_lpCodeRate;
1876 cmdseq->props[c].cmd = DTV_TRANSMISSION_MODE;
1877 cmdseq->props[c++].u.data = tuning.m_transMode;
1878 cmdseq->props[c].cmd = DTV_GUARD_INTERVAL;
1879 cmdseq->props[c++].u.data = tuning.m_guardInterval;
1880 cmdseq->props[c].cmd = DTV_HIERARCHY;
1881 cmdseq->props[c++].u.data = tuning.m_hierarchy;
1882 }
1883
1884 // DVB-S properties can be set on DVB-S2 tuner
1885 if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS)
1886 {
1887 cmdseq->props[c].cmd = DTV_ROLLOFF;
1888 cmdseq->props[c++].u.data = DTVRollOff::kRollOff_35;
1889 }
1890
1891 // DVB-S2 properties
1892 if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS2)
1893 {
1894 cmdseq->props[c].cmd = DTV_PILOT;
1895 cmdseq->props[c++].u.data = PILOT_AUTO;
1896 cmdseq->props[c].cmd = DTV_ROLLOFF;
1897 cmdseq->props[c++].u.data = tuning.m_rolloff;
1898 }
1899
1900 if (do_tune)
1901 cmdseq->props[c++].cmd = DTV_TUNE;
1902
1903 cmdseq->num = c;
1904
1905 return cmdseq;
1906}
@ DVB_DEV_FRONTEND
Definition: cardutil.h:32
static DTVModulationSystem GetDeliverySystem(uint inputid)
Definition: cardutil.cpp:915
static int SetDeliverySystem(uint inputid)
Definition: cardutil.cpp:1144
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:797
static std::chrono::milliseconds GetMinSignalMonitoringDelay(const QString &device)
Definition: cardutil.cpp:804
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1961
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
Definition: cardutil.cpp:2991
static QStringList CapabilitiesToString(uint64_t capabilities)
Definition: cardutil.cpp:2493
static DTVTunerType ConvertToTunerType(DTVModulationSystem delsys)
Definition: cardutil.cpp:814
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:35
static void ReturnMasterLock(DTVChannelP &chan)
Definition: dtvchannel.cpp:148
DTVTunerType m_tunerType
Definition: dtvchannel.h:162
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:180
static QReadWriteLock s_master_map_lock
Definition: dtvchannel.h:179
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:175
~DVBChannel() override
Definition: dvbchannel.cpp:108
DTVMultiplex m_desiredTuning
Definition: dvbchannel.h:162
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:168
uint64_t m_capabilities
Definition: dvbchannel.h:145
QMutex m_tuneDelayLock
Definition: dvbchannel.h:178
DTVModulationSystem m_currentSys
Definition: dvbchannel.h:155
QString m_key
Definition: dvbchannel.h:174
QList< DTVModulationSystem > m_sysList
Definition: dvbchannel.h:156
uint m_symbolRateMaximum
Definition: dvbchannel.h:150
const DiSEqCDevRotor * GetRotor(void) const
Returns rotor object if it exists, nullptr otherwise.
bool m_legacyFe
Definition: dvbchannel.h:153
uint64_t m_frequencyMaximum
Definition: dvbchannel.h:148
uint m_lastLnbDevId
Definition: dvbchannel.h:165
uint64_t m_extModulations
Definition: dvbchannel.h:146
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:173
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:144
DVBCam * m_dvbCam
Definition: dvbchannel.h:141
QRecursiveMutex m_hwLock
Definition: dvbchannel.h:160
uint64_t m_frequencyMinimum
Definition: dvbchannel.h:147
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:169
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:177
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:154
void Close(void) override
Closes the channel changing hardware to use.
Definition: dvbchannel.h:38
uint m_symbolRateMinimum
Definition: dvbchannel.h:149
int m_fdFrontend
Definition: dvbchannel.h:172
double GetSNR(bool *ok=nullptr) const
Returns signal/noise in the range [0..1.0].
DiSEqCDevTree * m_diseqcTree
Definition: dvbchannel.h:140
DTVMultiplex m_prevTuning
Definition: dvbchannel.h:163
bool ProbeTuningParams(DTVMultiplex &tuning) const
Fetches DTVMultiplex params from driver.
QMutex m_tuneLock
Definition: dvbchannel.h:159
uint m_version
Definition: dvbchannel.h:152
IsOpenMap m_isOpen
Definition: dvbchannel.h:136
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:139
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:167
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:2534
Rotor class.
Definition: diseqc.h:303
Unicable / SCR Class.
Definition: diseqc.h:383
uint32_t GetIntermediateFrequency(uint32_t frequency) const
Definition: diseqc.cpp:2227
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:515
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:602
DiSEqCDevLNB * FindLNB(const DiSEqCDevSettings &settings)
Returns the LNB device object selected by the configuration chain.
Definition: diseqc.cpp:579
DiSEqCDevRotor * FindRotor(const DiSEqCDevSettings &settings, uint index=0)
Returns the nth rotor device object in the tree.
Definition: diseqc.cpp:556
void Open(int fd_frontend, bool is_SCR)
Retrieve device tree.
Definition: diseqc.cpp:797
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:129
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:839
QVariant value(int i) const
Definition: mythdbcon.h:205
bool isActive(void) const
Definition: mythdbcon.h:216
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:620
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:890
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:814
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:552
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:234
#define O_NONBLOCK
Definition: compat.h:139
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:1040
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