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