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 free(cmds->props);
933 free(cmds);
934
935 if (res < 0)
936 {
937 LOG(VB_GENERAL, LOG_ERR, LOC +
938 "Tune(): Setting Frontend tuning parameters failed." + ENO);
939 return false;
940 }
941 }
942 else
943 {
944 // Legacy DVBv3 API
945 struct dvb_frontend_parameters params = dtvmultiplex_to_dvbparams(
946 m_tunerType, tuning, intermediate_freq, can_fec_auto);
947
948 if (ioctl(m_fdFrontend, FE_SET_FRONTEND, &params) < 0)
949 {
950 LOG(VB_GENERAL, LOG_ERR, LOC +
951 "Tune(): Setting Frontend tuning parameters failed." + ENO);
952 return false;
953 }
954 }
955
956 // Extra delay to add for broken DVB drivers
957 if (m_tuningDelay > 0ms)
958 std::this_thread::sleep_for(m_tuningDelay);
959
960 WaitForBackend(50ms);
961
962 m_prevTuning = tuning;
963 m_firstTune = false;
964 }
965 else
966 {
967 LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Tune(): Tuning to %1%2 skipped, already tuned")
968 .arg(intermediate_freq ? intermediate_freq : tuning.m_frequency)
969 .arg(suffix));
970 }
971
972
974
975 LOG(VB_CHANNEL, LOG_INFO, LOC + "Tune(): Frequency tuning successful");
976
977 return true;
978}
979
981{
982 return Tune(m_desiredTuning, true, true);
983}
984
989{
990 QMutexLocker locker(&m_hwLock);
991
992 if (m_fdFrontend < 0)
993 {
994 LOG(VB_GENERAL, LOG_ERR, LOC + "Card not open!");
995
996 return false;
997 }
998
999 DVBChannel *master = GetMasterLock();
1000 if (master != this)
1001 {
1002 bool ok = master->IsTuningParamsProbeSupported();
1003 ReturnMasterLock(master);
1004 return ok;
1005 }
1006 ReturnMasterLock(master); // If we're the master we don't need this lock.
1007
1008 if (m_diseqcTree)
1009 {
1010 // TODO We need to implement the inverse of
1011 // lnb->GetIntermediateFrequency() for ProbeTuningParams()
1012 // to accurately reflect the frequency before LNB transform.
1013 return false;
1014 }
1015
1016 dvb_frontend_parameters params {};
1017
1018 int res = ioctl(m_fdFrontend, FE_GET_FRONTEND, &params);
1019 if (res < 0)
1020 {
1021 LOG(VB_CHANNEL, LOG_ERR, LOC + "FE_GET_FRONTEND failed." + ENO);
1022 }
1023
1024 return (res >= 0);
1025}
1026
1035{
1036 QMutexLocker locker(&m_hwLock);
1037
1038 if (m_fdFrontend < 0)
1039 {
1040 LOG(VB_GENERAL, LOG_ERR, LOC + "Card not open!");
1041
1042 return false;
1043 }
1044
1045 DVBChannel *master = GetMasterLock();
1046 if (master != this)
1047 {
1048 bool ok = master->ProbeTuningParams(tuning);
1049 ReturnMasterLock(master);
1050 return ok;
1051 }
1052 ReturnMasterLock(master); // If we're the master we don't need this lock.
1053
1054 if (m_diseqcTree)
1055 {
1056 // TODO We need to implement the inverse of
1057 // lnb->GetIntermediateFrequency() for ProbeTuningParams()
1058 // to accurately reflect the frequency before LNB transform.
1059 return false;
1060 }
1061
1062 // DVBv5 API
1063 if (!m_legacyFe)
1064 {
1065 // TODO implement probing of tuning parameters with FE_GET_PROPERTY
1066 return false;
1067 }
1068
1069 // Legacy DVBv3 API
1070 dvb_frontend_parameters params {};
1071 if (ioctl(m_fdFrontend, FE_GET_FRONTEND, &params) < 0)
1072 {
1073 LOG(VB_GENERAL, LOG_ERR, LOC +
1074 "Getting Frontend tuning parameters failed." + ENO);
1075
1076 return false;
1077 }
1078
1079 uint mplex = tuning.m_mplex;
1080 QString sistandard = tuning.m_sistandard;
1081
1082 tuning = dvbparams_to_dtvmultiplex(m_tunerType, params);
1083
1084 tuning.m_mplex = mplex;
1085 tuning.m_sistandard = sistandard;
1086
1087 return true;
1088}
1089
1095{
1096 QList<int> idlist;
1097 int id = -1;
1098
1100
1101 query.prepare("SELECT chanid, visible "
1102 "FROM channel, capturecard "
1103 "WHERE channel.deleted IS NULL AND "
1104 " capturecard.sourceid = channel.sourceid AND "
1105 " channel.channum = :CHANNUM AND "
1106 " capturecard.cardid = :INPUTID");
1107
1108 query.bindValue(":CHANNUM", m_curChannelName);
1109 query.bindValue(":INPUTID", m_inputId);
1110
1111 if (!query.exec() || !query.isActive())
1112 {
1113 MythDB::DBError("fetching chanid", query);
1114 return -1;
1115 }
1116
1117 while (query.next())
1118 {
1119 bool visible = query.value(1).toInt() > 0;
1120 if (visible)
1121 {
1122 int chanid = query.value(0).toInt();
1123 idlist.append(chanid);
1124 }
1125 }
1126
1127 if (idlist.isEmpty())
1128 {
1129 LOG(VB_GENERAL, LOG_WARNING, LOC +
1130 QString("No visible channel ID for %1")
1131 .arg(m_curChannelName));
1132 }
1133 else
1134 {
1135 id = idlist.value(0);
1136 if (idlist.count() > 1)
1137 {
1138 QStringList sl;
1139 for (auto chanid : idlist)
1140 {
1141 sl.append(QString::number(chanid));
1142 }
1143 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1144 QString("Found for '%1' multiple visible channel IDs: %2")
1145 .arg(m_curChannelName, sl.join(" ")));
1146 }
1147 else
1148 {
1149 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1150 QString("Found visible channel ID %1 for '%2'")
1151 .arg(id).arg(m_curChannelName));
1152 }
1153 }
1154
1155 return id;
1156}
1157
1159{
1160 if (m_diseqcTree)
1162
1163 return nullptr;
1164}
1165
1166bool DVBChannel::HasLock(bool *ok) const
1167{
1168 DVBChannel *master = GetMasterLock();
1169 if (master != this)
1170 {
1171 bool haslock = master->HasLock(ok);
1172 ReturnMasterLock(master);
1173 return haslock;
1174 }
1175 ReturnMasterLock(master); // If we're the master we don't need this lock.
1176
1177#if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1178 fe_status_t status = FE_NONE;
1179#else // debian9, centos7
1180 fe_status_t status = (fe_status_t)0;
1181#endif
1182
1183 int ret = ioctl(m_fdFrontend, FE_READ_STATUS, &status);
1184 if (ret < 0)
1185 {
1186 LOG(VB_GENERAL, LOG_ERR, LOC + "FE_READ_STATUS failed" + ENO);
1187 }
1188 else
1189 {
1190 LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("%1 status: 0x%2 %3")
1191 .arg(__func__).arg(status,2,16,QChar('0')).arg(toString(status)));
1192 }
1193
1194 if (ok)
1195 *ok = (0 == ret);
1196
1197 return (status & FE_HAS_LOCK) != 0;
1198}
1199
1201{
1202 struct dtv_property prop = {};
1203 struct dtv_properties cmd = {};
1204
1205 prop.cmd = DTV_STAT_SIGNAL_STRENGTH;
1206 cmd.num = 1;
1207 cmd.props = &prop;
1208 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1209 if (ret < 0)
1210 {
1211 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_SIGNAL_STRENGTH failed" + ENO);
1212 }
1213 else
1214 {
1215#if DTV_STAT_FULL_DEBUG
1216 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_SIGNAL_STRENGTH " +
1217 QString("res=%1 len=%2 scale=%3 val=%4")
1218 .arg(cmd.props->result)
1219 .arg(cmd.props->u.st.len)
1220 .arg(cmd.props->u.st.stat[0].scale)
1221 .arg(cmd.props->u.st.stat[0].svalue));
1222#endif
1223 }
1224
1225 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1226 if (ok)
1227 *ok = tmpOk;
1228
1229 double value = 0;
1230 if (tmpOk)
1231 {
1232 if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1233 {
1234 // Convert range of -100dBm .. 0dBm to 0% .. 100%
1235 // Note that -100dBm is lower than the noise floor.
1236 // The measured svalue is in units of 0.001 dBm.
1237 // If the value is outside the range -100 to 0 dBm we do not believe it.
1238 int64_t svalue = cmd.props->u.st.stat[0].svalue;
1239 if (svalue >= -100000 && svalue <= 0)
1240 {
1241 // convert value from -100dBm to 0dBm to a 0-1 range
1242 value = svalue + 100000;
1243 value = value / 100000.0;
1244 value = std::min(value, 1.0);
1245 }
1246 }
1247 else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1248 {
1249 // Return as 16 bit unsigned
1250 value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1251 }
1252 }
1253 return value;
1254}
1255
1256double DVBChannel::GetSignalStrength(bool *ok) const
1257{
1258 DVBChannel *master = GetMasterLock();
1259 if (master != this)
1260 {
1261 double val = master->GetSignalStrength(ok);
1262 ReturnMasterLock(master);
1263 return val;
1264 }
1265 ReturnMasterLock(master); // If we're the master we don't need this lock.
1266
1267 if (!m_legacyFe && m_hasV5Stats)
1268 {
1269 bool v5_ok = false;
1270 double value = GetSignalStrengthDVBv5(&v5_ok);
1271 if (v5_ok)
1272 {
1273 if (ok)
1274 *ok = v5_ok;
1275 return value;
1276 }
1277 }
1278
1279 // We use uint16_t for sig because this is correct for DVB API 4.0,
1280 // and works better than the correct int16_t for the 3.x API
1281 uint16_t sig = 0;
1282 int ret = ioctl(m_fdFrontend, FE_READ_SIGNAL_STRENGTH, &sig);
1283 if (ok)
1284 *ok = (0 == ret);
1285
1286 return sig * (1.0 / 65535.0);
1287}
1288
1289double DVBChannel::GetSNRDVBv5(bool *ok) const
1290{
1291 struct dtv_property prop = {};
1292 struct dtv_properties cmd = {};
1293
1294 prop.cmd = DTV_STAT_CNR;
1295 cmd.num = 1;
1296 cmd.props = &prop;
1297 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1298 if (ret < 0)
1299 {
1300 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_CNR failed" + ENO);
1301 }
1302 else
1303 {
1304#if DTV_STAT_FULL_DEBUG
1305 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_CNR " +
1306 QString("res=%1 len=%2 scale=%3 val=%4")
1307 .arg(cmd.props->result)
1308 .arg(cmd.props->u.st.len)
1309 .arg(cmd.props->u.st.stat[0].scale)
1310 .arg(cmd.props->u.st.stat[0].svalue));
1311#endif
1312 }
1313
1314 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1315 if (ok)
1316 *ok = tmpOk;
1317 double value = 0;
1318 if (tmpOk)
1319 {
1320 if (cmd.props->u.st.stat[0].scale == FE_SCALE_DECIBEL)
1321 {
1322 // The measured svalue is in units of 0.001 dB
1323 // Let 50dB+ CNR be 100% quality and 0dB be 0%
1324 // Convert 0.001 dB from 0-50000 to a 0-1 range
1325 value = cmd.props->u.st.stat[0].svalue;
1326 value = value / 50000.0;
1327 if (value > 1.0)
1328 value = 1.0;
1329 else if (value < 0)
1330 value = 0.0;
1331 }
1332 else if (cmd.props->u.st.stat[0].scale == FE_SCALE_RELATIVE)
1333 {
1334 // Return as 16 bit unsigned
1335 value = cmd.props->u.st.stat[0].uvalue / 65535.0;
1336 }
1337 }
1338 return value;
1339}
1340
1341double DVBChannel::GetSNR(bool *ok) const
1342{
1343 DVBChannel *master = GetMasterLock();
1344 if (master != this)
1345 {
1346 double val = master->GetSNR(ok);
1347 ReturnMasterLock(master);
1348 return val;
1349 }
1350 ReturnMasterLock(master); // If we're the master we don't need this lock.
1351
1352 if (!m_legacyFe && m_hasV5Stats)
1353 {
1354 bool v5_ok = false;
1355 double value = GetSNRDVBv5(&v5_ok);
1356 if (v5_ok)
1357 {
1358 if (ok)
1359 *ok = v5_ok;
1360 return value;
1361 }
1362 }
1363
1364 // We use uint16_t for sig because this is correct for DVB API 4.0,
1365 // and works better than the correct int16_t for the 3.x API
1366 uint16_t snr = 0;
1367 int ret = ioctl(m_fdFrontend, FE_READ_SNR, &snr);
1368 if (ok)
1369 *ok = (0 == ret);
1370
1371 return snr * (1.0 / 65535.0);
1372}
1373
1375{
1376 std::array<struct dtv_property,2> prop {};
1377 struct dtv_properties cmd = {};
1378
1379 prop[0].cmd = DTV_STAT_POST_ERROR_BIT_COUNT;
1380 prop[1].cmd = DTV_STAT_POST_TOTAL_BIT_COUNT;
1381 cmd.num = prop.size();
1382 cmd.props = prop.data();
1383 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1384 if (ret < 0)
1385 {
1386 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_POST_ERROR_BIT_COUNT failed" + ENO);
1387 }
1388 else
1389 {
1390#if DTV_STAT_FULL_DEBUG
1391 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_POST_ERROR_BIT_COUNT " +
1392 QString("res=%1 len=%2 scale=%3 val=%4 res=%5 len=%6 scale=%7 val=%8")
1393 .arg(cmd.props[0].result)
1394 .arg(cmd.props[0].u.st.len)
1395 .arg(cmd.props[0].u.st.stat[0].scale)
1396 .arg(cmd.props[0].u.st.stat[0].uvalue)
1397 .arg(cmd.props[1].result)
1398 .arg(cmd.props[1].u.st.len)
1399 .arg(cmd.props[1].u.st.stat[0].scale)
1400 .arg(cmd.props[1].u.st.stat[0].uvalue));
1401#endif
1402 }
1403
1404 bool tmpOk = (ret == 0) &&
1405 (cmd.props[0].u.st.len > 0) &&
1406 (cmd.props[1].u.st.len > 0);
1407 if (ok)
1408 *ok = tmpOk;
1409 double value = 0;
1410 if (tmpOk)
1411 {
1412 if ((cmd.props[0].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1413 (cmd.props[1].u.st.stat[0].scale == FE_SCALE_COUNTER) &&
1414 (cmd.props[1].u.st.stat[0].uvalue != 0))
1415 {
1416 value = static_cast<double>(
1417 static_cast<long double>(cmd.props[0].u.st.stat[0].uvalue) /
1418 cmd.props[1].u.st.stat[0].uvalue);
1419 }
1420 }
1421 return value;
1422}
1423
1424double DVBChannel::GetBitErrorRate(bool *ok) const
1425{
1426 DVBChannel *master = GetMasterLock();
1427 if (master != this)
1428 {
1429 double val = master->GetBitErrorRate(ok);
1430 ReturnMasterLock(master);
1431 return val;
1432 }
1433 ReturnMasterLock(master); // If we're the master we don't need this lock.
1434
1435 if (!m_legacyFe && m_hasV5Stats)
1436 {
1437 bool v5_ok = false;
1438 double value = GetBitErrorRateDVBv5(&v5_ok);
1439 if (v5_ok)
1440 {
1441 if (ok)
1442 *ok = v5_ok;
1443 return value;
1444 }
1445 }
1446
1447 uint32_t ber = 0;
1448 int ret = ioctl(m_fdFrontend, FE_READ_BER, &ber);
1449 if (ok)
1450 *ok = (0 == ret);
1451
1452 return (double) ber;
1453}
1454
1456{
1457 struct dtv_property prop = {};
1458 struct dtv_properties cmd = {};
1459
1460 prop.cmd = DTV_STAT_ERROR_BLOCK_COUNT;
1461 cmd.num = 1;
1462 cmd.props = &prop;
1463 int ret = ioctl(m_fdFrontend, FE_GET_PROPERTY, &cmd);
1464 if (ret < 0)
1465 {
1466 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "FE_GET_PROPERTY DTV_STAT_ERROR_BLOCK_COUNT failed" + ENO);
1467 }
1468 else
1469 {
1470#if DTV_STAT_FULL_DEBUG
1471 LOG(VB_CHANNEL, LOG_DEBUG, LOC + "DTV_STAT_ERROR_BLOCK_COUNT " +
1472 QString("res=%1 len=%2 scale=%3 val=%4")
1473 .arg(cmd.props[0].result)
1474 .arg(cmd.props[0].u.st.len)
1475 .arg(cmd.props[0].u.st.stat[0].scale)
1476 .arg(cmd.props[0].u.st.stat[0].svalue));
1477#endif
1478 }
1479
1480 bool tmpOk = (ret == 0) && (cmd.props->u.st.len > 0);
1481 if (ok)
1482 *ok = tmpOk;
1483 double value = 0;
1484 if (tmpOk)
1485 {
1486 if (cmd.props->u.st.stat[0].scale == FE_SCALE_COUNTER)
1487 value = cmd.props->u.st.stat[0].uvalue;
1488 }
1489 return value;
1490}
1491
1493{
1494 DVBChannel *master = GetMasterLock();
1495 if (master != this)
1496 {
1497 double val = master->GetUncorrectedBlockCount(ok);
1498 ReturnMasterLock(master);
1499 return val;
1500 }
1501 ReturnMasterLock(master); // If we're the master we don't need this lock.
1502
1503 if (!m_legacyFe && m_hasV5Stats)
1504 {
1505 bool v5_ok = false;
1506 double value = GetUncorrectedBlockCountDVBv5(&v5_ok);
1507 if (v5_ok)
1508 {
1509 if (ok)
1510 *ok = v5_ok;
1511 return value;
1512 }
1513 }
1514
1515 uint32_t ublocks = 0;
1516 int ret = ioctl(m_fdFrontend, FE_READ_UNCORRECTED_BLOCKS, &ublocks);
1517 if (ok)
1518 *ok = (0 == ret);
1519
1520 return static_cast<double>(ublocks);
1521}
1522
1524{
1525 DTVChannel *chan = dvbm;
1527 dvbm = nullptr;
1528}
1529
1531{
1533 auto *dvbm = dynamic_cast<DVBChannel*>(master);
1534 if (master && !dvbm)
1536 return dvbm;
1537}
1538
1539bool DVBChannel::IsMaster(void) const
1540{
1541 DVBChannel *master = GetMasterLock();
1542 bool is_master = (master == this);
1543 ReturnMasterLock(master);
1544 return is_master;
1545}
1546
1547// Reads all the events off the queue, so we can use select in WaitForBackend.
1548//
1549// Note that FE_GET_EVENT is deprecated but there is no alternative yet.
1550//
1552{
1553 const int fd = m_fdFrontend;
1554 struct dvb_frontend_event event {};
1555 int ret = 0;
1556 while ((ret = ioctl(fd, FE_GET_EVENT, &event)) == 0);
1557 if ((ret < 0) && (EAGAIN != errno) && (EWOULDBLOCK != errno) && (EOVERFLOW != errno))
1558 {
1559 LOG(VB_CHANNEL, LOG_ERR, LOC +
1560 QString("%1 FE_GET_EVENT failed: ").arg(__func__) + logStrerror(errno));
1561 }
1562}
1563
1586bool DVBChannel::WaitForBackend(std::chrono::milliseconds timeout_ms)
1587{
1588 const int fd = m_fdFrontend;
1589 auto seconds = duration_cast<std::chrono::seconds>(timeout_ms);
1590 auto usecs = duration_cast<std::chrono::microseconds>(timeout_ms) - seconds;
1591 struct timeval select_timeout = {
1592 static_cast<typeof(select_timeout.tv_sec)>(seconds.count()),
1593 static_cast<typeof(select_timeout.tv_usec)>(usecs.count())};
1594 fd_set fd_select_set;
1595 FD_ZERO( &fd_select_set); // NOLINT(readability-isolate-declaration)
1596 FD_SET (fd, &fd_select_set);
1597
1598 // Try to wait for some output like an event, unfortunately
1599 // this fails on several DVB cards, so we have a timeout.
1600 int ret = 0;
1601 do ret = select(fd+1, &fd_select_set, nullptr, nullptr, &select_timeout);
1602 while ((-1 == ret) && (EINTR == errno));
1603
1604 if (-1 == ret)
1605 {
1606 LOG(VB_GENERAL, LOG_ERR, LOC +
1607 QString("%1: Failed to wait on output.").arg(__func__) + ENO);
1608
1609 return false;
1610 }
1611
1612 // This is supposed to work on all cards, post 2.6.12...
1613#if ((DVB_API_VERSION > 5) || ((DVB_API_VERSION == 5) && (DVB_API_VERSION_MINOR > 10)))
1614 fe_status_t status = FE_NONE;
1615#else // debian9, centos7
1616 fe_status_t status = (fe_status_t)0;
1617#endif
1618
1619 if (ioctl(fd, FE_READ_STATUS, &status) < 0)
1620 {
1621 LOG(VB_GENERAL, LOG_ERR, LOC +
1622 QString("%1: FE_READ_STATUS failed.").arg(__func__) + ENO);
1623
1624 return false;
1625 }
1626
1627 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
1628 QString("%1: status: 0x%2 %3") .arg(__func__)
1629 .arg(status,2,16,QChar('0')).arg(toString(status)));
1630
1631 return true;
1632}
1633
1634// Create legacy DVBv3 frontend parameters from DTVMultiplex.
1635//
1636static struct dvb_frontend_parameters dtvmultiplex_to_dvbparams(
1637 DTVTunerType tuner_type, const DTVMultiplex &tuning,
1638 uint intermediate_freq, bool can_fec_auto)
1639{
1640 dvb_frontend_parameters params {};
1641
1642 params.frequency = tuning.m_frequency;
1643 params.inversion = (fe_spectral_inversion_t) (int) tuning.m_inversion;
1644
1645 if (DTVTunerType::kTunerTypeDVBS1 == tuner_type)
1646 {
1647 if (tuning.m_modSys == DTVModulationSystem::kModulationSystem_DVBS2)
1648 {
1649 LOG(VB_GENERAL, LOG_ERR,
1650 "DVBChan: Cannot tune to DVB-S2 transport with DVB-S card.");
1651 }
1652
1653 params.frequency = intermediate_freq;
1654 params.u.qpsk.symbol_rate = tuning.m_symbolRate;
1655 params.u.qpsk.fec_inner = can_fec_auto ? FEC_AUTO
1656 : (fe_code_rate_t) (int) tuning.m_fec;
1657 }
1658
1659 if (DTVTunerType::kTunerTypeDVBS2 == tuner_type)
1660 {
1661 LOG(VB_GENERAL, LOG_ERR,
1662 "DVBChan: Cannot tune DVB-S2 card with DVBv3 API.");
1663 }
1664
1665 if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1666 {
1667 params.u.qam.symbol_rate = tuning.m_symbolRate;
1668 params.u.qam.fec_inner = (fe_code_rate_t) (int) tuning.m_fec;
1669 params.u.qam.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1670 }
1671
1672 if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1673 DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1674 {
1675 params.u.ofdm.bandwidth = (fe_bandwidth_t) (int) tuning.m_bandwidth;
1676 params.u.ofdm.code_rate_HP = (fe_code_rate_t) (int) tuning.m_hpCodeRate;
1677 params.u.ofdm.code_rate_LP = (fe_code_rate_t) (int) tuning.m_lpCodeRate;
1678 params.u.ofdm.constellation = (fe_modulation_t) (int) tuning.m_modulation;
1679 params.u.ofdm.transmission_mode = (fe_transmit_mode_t) (int) tuning.m_transMode;
1680 params.u.ofdm.guard_interval = (fe_guard_interval_t) (int) tuning.m_guardInterval;
1681 params.u.ofdm.hierarchy_information = (fe_hierarchy_t) (int) tuning.m_hierarchy;
1682 }
1683
1684 if (DTVTunerType::kTunerTypeATSC == tuner_type)
1685 {
1686 params.u.vsb.modulation = (fe_modulation_t) (int) tuning.m_modulation;
1687 }
1688
1689 return params;
1690}
1691
1692// Create DTVMultiplex from legacy DVBv3 frontend parameters.
1693//
1695 DTVTunerType tuner_type, const dvb_frontend_parameters &params)
1696{
1697 DTVMultiplex tuning;
1698
1699 tuning.m_frequency = params.frequency;
1700 tuning.m_inversion = params.inversion;
1701
1702 if ((DTVTunerType::kTunerTypeDVBS1 == tuner_type) ||
1703 (DTVTunerType::kTunerTypeDVBS2 == tuner_type))
1704 {
1705 tuning.m_symbolRate = params.u.qpsk.symbol_rate;
1706 tuning.m_fec = params.u.qpsk.fec_inner;
1707 }
1708
1709 if (DTVTunerType::kTunerTypeDVBC == tuner_type)
1710 {
1711 tuning.m_symbolRate = params.u.qam.symbol_rate;
1712 tuning.m_fec = params.u.qam.fec_inner;
1713 tuning.m_modulation = params.u.qam.modulation;
1714 }
1715
1716 if (DTVTunerType::kTunerTypeDVBT == tuner_type ||
1717 DTVTunerType::kTunerTypeDVBT2 == tuner_type)
1718 {
1719 tuning.m_bandwidth = params.u.ofdm.bandwidth;
1720 tuning.m_hpCodeRate = params.u.ofdm.code_rate_HP;
1721 tuning.m_lpCodeRate = params.u.ofdm.code_rate_LP;
1722 tuning.m_modulation = params.u.ofdm.constellation;
1723 tuning.m_transMode = params.u.ofdm.transmission_mode;
1724 tuning.m_guardInterval = params.u.ofdm.guard_interval;
1725 tuning.m_hierarchy = params.u.ofdm.hierarchy_information;
1726 }
1727
1728 if (DTVTunerType::kTunerTypeATSC == tuner_type)
1729 {
1730 tuning.m_modulation = params.u.vsb.modulation;
1731 }
1732
1733 return tuning;
1734}
1735
1736// Create a DVBv5 property list from the dtv_multiplex
1737//
1738static struct dtv_properties *dtvmultiplex_to_dtvproperties(uint inputId,
1739 DTVTunerType tuner_type, DTVModulationSystem current_sys, const DTVMultiplex &tuning,
1740 uint intermediate_freq, bool can_fec_auto, bool do_tune)
1741{
1742 DTVModulationSystem delivery_system = current_sys;
1743 uint c = 0;
1744
1745 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]: m_modsys:%2 current_sys:%3")
1746 .arg(QString::number(inputId),
1747 tuning.m_modSys.toString(),
1748 current_sys.toString()));
1749
1750 auto *cmdseq = (struct dtv_properties*) calloc(1, sizeof(struct dtv_properties));
1751 if (!cmdseq)
1752 return nullptr;
1753
1754 cmdseq->props = (struct dtv_property*) calloc(20, sizeof(*(cmdseq->props)));
1755 if (!(cmdseq->props))
1756 {
1757 free(cmdseq);
1758 return nullptr;
1759 }
1760
1761 // 20201117 TODO do this only for cx24116 but not for all DVB-S2 demods
1762 //
1763 // The cx24116 DVB-S2 demod announces FE_CAN_FEC_AUTO but has apparently
1764 // trouble with FEC_AUTO on DVB-S2 transponders
1766 can_fec_auto = false;
1767
1768 // Select delivery system in this order
1769 // - from dtv_multiplex
1770 // - modulation system in the card
1771 // - default based on tuner type
1772 //
1774 {
1775 delivery_system = tuning.m_modSys;
1776 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1777 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1778 }
1780 {
1781 delivery_system = current_sys;
1782 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1783 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1784 }
1785 else if (tuner_type == DTVTunerType::kTunerTypeDVBC)
1786 {
1788 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1789 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1790 }
1791 else if (tuner_type == DTVTunerType::kTunerTypeATSC)
1792 {
1794 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1795 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1796 }
1797 else if (tuner_type == DTVTunerType::kTunerTypeDVBT)
1798 {
1800 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1801 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1802 }
1803 else if (tuner_type == DTVTunerType::kTunerTypeDVBT2)
1804 {
1806 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1807 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1808 }
1809 else if (tuner_type == DTVTunerType::kTunerTypeDVBS1)
1810 {
1812 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1813 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1814 }
1815 else if (tuner_type == DTVTunerType::kTunerTypeDVBS2)
1816 {
1818 LOG(VB_CHANNEL, LOG_DEBUG, QString("DVBChan[%1]:%2 set delivery_system to %3")
1819 .arg(inputId).arg(__LINE__).arg(delivery_system.toString()));
1820 }
1821
1822 LOG(VB_CHANNEL, LOG_INFO, QString("DVBChan[%1]: Delivery system: %2")
1823 .arg(inputId).arg(delivery_system.toString()));
1824
1826 {
1827 cmdseq->props[c].cmd = DTV_DELIVERY_SYSTEM;
1828 cmdseq->props[c++].u.data = delivery_system;
1829 }
1830 else
1831 {
1832 LOG(VB_GENERAL, LOG_ERR, QString("DVBChan[%1]: Delivery system: %2")
1833 .arg(inputId).arg(delivery_system.toString()));
1834 }
1835
1836 // Frequency, modulation and inversion
1837 cmdseq->props[c].cmd = DTV_FREQUENCY;
1838 cmdseq->props[c++].u.data = intermediate_freq ? intermediate_freq : tuning.m_frequency;
1839 cmdseq->props[c].cmd = DTV_MODULATION;
1840 cmdseq->props[c++].u.data = tuning.m_modulation;
1841 cmdseq->props[c].cmd = DTV_INVERSION;
1842 cmdseq->props[c++].u.data = tuning.m_inversion;
1843
1844 // Symbol rate
1845 if (tuner_type == DTVTunerType::kTunerTypeDVBS1 ||
1846 tuner_type == DTVTunerType::kTunerTypeDVBS2 ||
1847 tuner_type == DTVTunerType::kTunerTypeDVBC)
1848 {
1849 cmdseq->props[c].cmd = DTV_SYMBOL_RATE;
1850 cmdseq->props[c++].u.data = tuning.m_symbolRate;
1851 }
1852
1853 // Forward error correction
1854 if (tuner_type.IsFECVariable())
1855 {
1856 cmdseq->props[c].cmd = DTV_INNER_FEC;
1857 cmdseq->props[c++].u.data = can_fec_auto ? FEC_AUTO
1858 : (fe_code_rate_t) (int) tuning.m_fec;
1859 }
1860
1861 // DVB-T/T2 properties
1862 if (tuner_type == DTVTunerType::kTunerTypeDVBT ||
1863 tuner_type == DTVTunerType::kTunerTypeDVBT2)
1864 {
1865 cmdseq->props[c].cmd = DTV_BANDWIDTH_HZ;
1866 cmdseq->props[c++].u.data = (8-tuning.m_bandwidth) * 1000000;
1867 cmdseq->props[c].cmd = DTV_CODE_RATE_HP;
1868 cmdseq->props[c++].u.data = tuning.m_hpCodeRate;
1869 cmdseq->props[c].cmd = DTV_CODE_RATE_LP;
1870 cmdseq->props[c++].u.data = tuning.m_lpCodeRate;
1871 cmdseq->props[c].cmd = DTV_TRANSMISSION_MODE;
1872 cmdseq->props[c++].u.data = tuning.m_transMode;
1873 cmdseq->props[c].cmd = DTV_GUARD_INTERVAL;
1874 cmdseq->props[c++].u.data = tuning.m_guardInterval;
1875 cmdseq->props[c].cmd = DTV_HIERARCHY;
1876 cmdseq->props[c++].u.data = tuning.m_hierarchy;
1877 }
1878
1879 // DVB-S properties can be set on DVB-S2 tuner
1880 if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS)
1881 {
1882 cmdseq->props[c].cmd = DTV_ROLLOFF;
1883 cmdseq->props[c++].u.data = DTVRollOff::kRollOff_35;
1884 }
1885
1886 // DVB-S2 properties
1887 if (delivery_system == DTVModulationSystem::kModulationSystem_DVBS2)
1888 {
1889 cmdseq->props[c].cmd = DTV_PILOT;
1890 cmdseq->props[c++].u.data = PILOT_AUTO;
1891 cmdseq->props[c].cmd = DTV_ROLLOFF;
1892 cmdseq->props[c++].u.data = tuning.m_rolloff;
1893 }
1894
1895 if (do_tune)
1896 cmdseq->props[c++].cmd = DTV_TUNE;
1897
1898 cmdseq->num = c;
1899
1900 return cmdseq;
1901}
@ 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:67
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:980
bool IsTuningParamsProbeSupported(void) const
Returns true iff tuning info probing is working.
Definition: dvbchannel.cpp:988
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:2525
Rotor class.
Definition: diseqc.h:303
Unicable / SCR Class.
Definition: diseqc.h:383
uint32_t GetIntermediateFrequency(uint32_t frequency) const
Definition: diseqc.cpp:2218
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:130
bool Execute(const DiSEqCDevSettings &settings, const DTVMultiplex &tuning)
Applies settings to the entire tree.
Definition: diseqc.cpp:511
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:598
DiSEqCDevLNB * FindLNB(const DiSEqCDevSettings &settings)
Returns the LNB device object selected by the configuration chain.
Definition: diseqc.cpp:575
DiSEqCDevRotor * FindRotor(const DiSEqCDevSettings &settings, uint index=0)
Returns the nth rotor device object in the tree.
Definition: diseqc.cpp:552
void Open(int fd_frontend, bool is_SCR)
Retrieve device tree.
Definition: diseqc.cpp:792
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:239
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
STL namespace.
VERBOSE_PREAMBLE Most true
Definition: verbosedefs.h:86