mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Added support for DVB devices with more than one frontend that all use the same dvr and demux
This commit is contained in:
parent
bcee8ad43d
commit
cbc77f1f25
6
HISTORY
6
HISTORY
@ -9348,7 +9348,7 @@ Video Disk Recorder Revision History
|
|||||||
Senzel).
|
Senzel).
|
||||||
- Official release.
|
- Official release.
|
||||||
|
|
||||||
2018-09-23: Version 2.4.1
|
2018-10-29: Version 2.4.1
|
||||||
|
|
||||||
- Fixed handling the tfRecording flag in the SVDRP commands MODT and UPDT (reported
|
- Fixed handling the tfRecording flag in the SVDRP commands MODT and UPDT (reported
|
||||||
by Johann Friedrichs).
|
by Johann Friedrichs).
|
||||||
@ -9367,3 +9367,7 @@ Video Disk Recorder Revision History
|
|||||||
Binder).
|
Binder).
|
||||||
- Now deactivating MTD support if a non MCD capable CAM is inserted after removing
|
- Now deactivating MTD support if a non MCD capable CAM is inserted after removing
|
||||||
a previously used CAM that is MCD capable (thanks to Helmut Binder).
|
a previously used CAM that is MCD capable (thanks to Helmut Binder).
|
||||||
|
- Added support for DVB devices with more than one frontend that all use the same
|
||||||
|
dvr and demux. Note that in order for this to work, you must not set symbolic
|
||||||
|
links like "demux1 -> demux0" and "dvr1 -> dvr0", as is mentioned in some user
|
||||||
|
manuals of multi frontend DVB cards.
|
||||||
|
295
dvbdevice.c
295
dvbdevice.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbdevice.c 4.16 2018/02/15 15:37:01 kls Exp $
|
* $Id: dvbdevice.c 4.17 2018/10/29 10:40:34 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbdevice.h"
|
#include "dvbdevice.h"
|
||||||
@ -293,6 +293,90 @@ bool cDvbTransponderParameters::Parse(const char *s)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- cDvbFrontend ----------------------------------------------------------
|
||||||
|
|
||||||
|
class cDvbFrontend {
|
||||||
|
private:
|
||||||
|
int adapter, frontend;
|
||||||
|
int fd_frontend;
|
||||||
|
uint32_t subsystemId;
|
||||||
|
dvb_frontend_info frontendInfo;
|
||||||
|
cVector<int> deliverySystems;
|
||||||
|
int numModulations;
|
||||||
|
bool QueryDeliverySystems(void);
|
||||||
|
public:
|
||||||
|
cDvbFrontend(int Adapter, int Frontend);
|
||||||
|
~cDvbFrontend();
|
||||||
|
int Open(void);
|
||||||
|
void Close(void);
|
||||||
|
const char *FrontendName(void) { return frontendInfo.name; }
|
||||||
|
bool ProvidesDeliverySystem(int DeliverySystem) const;
|
||||||
|
bool ProvidesModulation(int System, int StreamId, int Modulation) const;
|
||||||
|
int NumDeliverySystems(void) const { return deliverySystems.Size(); }
|
||||||
|
int NumModulations(void) const { return numModulations; }
|
||||||
|
uint32_t SubsystemId(void) const { return subsystemId; }
|
||||||
|
};
|
||||||
|
|
||||||
|
cDvbFrontend::cDvbFrontend(int Adapter, int Frontend)
|
||||||
|
{
|
||||||
|
adapter = Adapter;
|
||||||
|
frontend = Frontend;
|
||||||
|
fd_frontend = -1;
|
||||||
|
subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
|
||||||
|
numModulations = 0;
|
||||||
|
Open();
|
||||||
|
QueryDeliverySystems();
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
cDvbFrontend::~cDvbFrontend()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cDvbFrontend::Open(void)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
fd_frontend = DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK, true);
|
||||||
|
return fd_frontend;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cDvbFrontend::Close(void)
|
||||||
|
{
|
||||||
|
if (fd_frontend >= 0) {
|
||||||
|
if (close(fd_frontend) != 0)
|
||||||
|
esyslog("ERROR: frontend %d/%d", adapter, frontend);
|
||||||
|
fd_frontend = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDvbFrontend::ProvidesDeliverySystem(int DeliverySystem) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < deliverySystems.Size(); i++) {
|
||||||
|
if (deliverySystems[i] == DeliverySystem)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDvbFrontend::ProvidesModulation(int System, int StreamId, int Modulation) const
|
||||||
|
{
|
||||||
|
if (StreamId != 0 && !(frontendInfo.caps & FE_CAN_MULTISTREAM))
|
||||||
|
return false;
|
||||||
|
if (Modulation == QPSK && !(frontendInfo.caps & FE_CAN_QPSK) ||
|
||||||
|
Modulation == QAM_16 && !(frontendInfo.caps & FE_CAN_QAM_16) ||
|
||||||
|
Modulation == QAM_32 && !(frontendInfo.caps & FE_CAN_QAM_32) ||
|
||||||
|
Modulation == QAM_64 && !(frontendInfo.caps & FE_CAN_QAM_64) ||
|
||||||
|
Modulation == QAM_128 && !(frontendInfo.caps & FE_CAN_QAM_128) ||
|
||||||
|
Modulation == QAM_256 && !(frontendInfo.caps & FE_CAN_QAM_256) ||
|
||||||
|
Modulation == QAM_AUTO && !(frontendInfo.caps & FE_CAN_QAM_AUTO) ||
|
||||||
|
Modulation == VSB_8 && !(frontendInfo.caps & FE_CAN_8VSB) ||
|
||||||
|
Modulation == VSB_16 && !(frontendInfo.caps & FE_CAN_16VSB) ||
|
||||||
|
Modulation == PSK_8 && !(frontendInfo.caps & FE_CAN_TURBO_FEC) && System == SYS_DVBS) // "turbo fec" is a non standard FEC used by North American broadcasters - this is a best guess to de
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// --- cDvbTuner -------------------------------------------------------------
|
// --- cDvbTuner -------------------------------------------------------------
|
||||||
|
|
||||||
#define TUNER_POLL_TIMEOUT 10 // ms
|
#define TUNER_POLL_TIMEOUT 10 // ms
|
||||||
@ -303,9 +387,13 @@ private:
|
|||||||
enum eTunerStatus { tsIdle, tsSet, tsPositioning, tsTuned, tsLocked };
|
enum eTunerStatus { tsIdle, tsSet, tsPositioning, tsTuned, tsLocked };
|
||||||
int frontendType;
|
int frontendType;
|
||||||
const cDvbDevice *device;
|
const cDvbDevice *device;
|
||||||
int fd_frontend;
|
mutable int fd_frontend;
|
||||||
int adapter, frontend;
|
int adapter;
|
||||||
uint32_t subsystemId;
|
mutable int frontend;
|
||||||
|
cVector<cDvbFrontend *> dvbFrontends;
|
||||||
|
mutable cDvbFrontend *dvbFrontend;
|
||||||
|
int numDeliverySystems;
|
||||||
|
int numModulations;
|
||||||
int tuneTimeout;
|
int tuneTimeout;
|
||||||
int lockTimeout;
|
int lockTimeout;
|
||||||
time_t lastTimeoutReport;
|
time_t lastTimeoutReport;
|
||||||
@ -320,7 +408,7 @@ private:
|
|||||||
const cScr *scr;
|
const cScr *scr;
|
||||||
bool lnbPowerTurnedOn;
|
bool lnbPowerTurnedOn;
|
||||||
eTunerStatus tunerStatus;
|
eTunerStatus tunerStatus;
|
||||||
cMutex mutex;
|
mutable cMutex mutex;
|
||||||
cCondVar locked;
|
cCondVar locked;
|
||||||
cCondVar newSet;
|
cCondVar newSet;
|
||||||
cDvbTuner *bondedTuner;
|
cDvbTuner *bondedTuner;
|
||||||
@ -337,14 +425,19 @@ private:
|
|||||||
bool SetFrontend(void);
|
bool SetFrontend(void);
|
||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
public:
|
public:
|
||||||
cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend);
|
cDvbTuner(const cDvbDevice *Device, int Adapter, int Frontend);
|
||||||
virtual ~cDvbTuner();
|
virtual ~cDvbTuner();
|
||||||
|
bool ProvidesDeliverySystem(int DeliverySystem) const;
|
||||||
|
bool ProvidesModulation(int System, int StreamId, int Modulation) const;
|
||||||
|
bool ProvidesFrontend(const cChannel *Channel, bool Activate = false) const;
|
||||||
int FrontendType(void) const { return frontendType; }
|
int FrontendType(void) const { return frontendType; }
|
||||||
|
const char *FrontendName(void) { return dvbFrontend->FrontendName(); }
|
||||||
|
int NumProvidedSystems(void) const { return numDeliverySystems + numModulations; }
|
||||||
bool Bond(cDvbTuner *Tuner);
|
bool Bond(cDvbTuner *Tuner);
|
||||||
void UnBond(void);
|
void UnBond(void);
|
||||||
bool BondingOk(const cChannel *Channel, bool ConsiderOccupied = false) const;
|
bool BondingOk(const cChannel *Channel, bool ConsiderOccupied = false) const;
|
||||||
const cChannel *GetTransponder(void) const { return &channel; }
|
const cChannel *GetTransponder(void) const { return &channel; }
|
||||||
uint32_t SubsystemId(void) const { return subsystemId; }
|
uint32_t SubsystemId(void) const { return dvbFrontend->SubsystemId(); }
|
||||||
bool IsTunedTo(const cChannel *Channel) const;
|
bool IsTunedTo(const cChannel *Channel) const;
|
||||||
void SetChannel(const cChannel *Channel);
|
void SetChannel(const cChannel *Channel);
|
||||||
bool Locked(int TimeoutMs = 0);
|
bool Locked(int TimeoutMs = 0);
|
||||||
@ -356,14 +449,14 @@ public:
|
|||||||
|
|
||||||
cMutex cDvbTuner::bondMutex;
|
cMutex cDvbTuner::bondMutex;
|
||||||
|
|
||||||
cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend)
|
cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Adapter, int Frontend)
|
||||||
{
|
{
|
||||||
frontendType = SYS_UNDEFINED;
|
frontendType = SYS_UNDEFINED;
|
||||||
device = Device;
|
device = Device;
|
||||||
fd_frontend = Fd_Frontend;
|
fd_frontend = -1;
|
||||||
adapter = Adapter;
|
adapter = Adapter;
|
||||||
frontend = Frontend;
|
frontend = Frontend;
|
||||||
subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
|
dvbFrontend = NULL;
|
||||||
tuneTimeout = 0;
|
tuneTimeout = 0;
|
||||||
lockTimeout = 0;
|
lockTimeout = 0;
|
||||||
lastTimeoutReport = 0;
|
lastTimeoutReport = 0;
|
||||||
@ -379,7 +472,31 @@ cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int
|
|||||||
tunerStatus = tsIdle;
|
tunerStatus = tsIdle;
|
||||||
bondedTuner = NULL;
|
bondedTuner = NULL;
|
||||||
bondedMaster = false;
|
bondedMaster = false;
|
||||||
SetDescription("frontend %d/%d tuner", adapter, frontend);
|
cDvbFrontend *fe = new cDvbFrontend(adapter, frontend);
|
||||||
|
dvbFrontends.Append(fe);
|
||||||
|
numDeliverySystems = fe->NumDeliverySystems();
|
||||||
|
numModulations = fe->NumModulations();
|
||||||
|
cString FrontendNumbers = cString::sprintf("%d", frontend);
|
||||||
|
// Check for multiple frontends:
|
||||||
|
if (frontend == 0) {
|
||||||
|
for (int i = 1; ; i++) {
|
||||||
|
if (access(DvbName(DEV_DVB_FRONTEND, adapter, i), F_OK) == 0) {
|
||||||
|
if (access(DvbName(DEV_DVB_DEMUX, adapter, i), F_OK) != 0) {
|
||||||
|
fe = new cDvbFrontend(adapter, i);
|
||||||
|
dvbFrontends.Append(fe);
|
||||||
|
numDeliverySystems += fe->NumDeliverySystems();
|
||||||
|
//numModulations += fe->NumModulations(); // looks like in multi frontend devices all frontends report the same modulations
|
||||||
|
FrontendNumbers = cString::sprintf("%s+%d", *FrontendNumbers, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Open default frontend:
|
||||||
|
dvbFrontend = dvbFrontends[0];
|
||||||
|
fd_frontend = dvbFrontend->Open();
|
||||||
|
SetDescription("frontend %d/%s tuner", adapter, *FrontendNumbers);
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,6 +513,51 @@ cDvbTuner::~cDvbTuner()
|
|||||||
ExecuteDiseqc(lastDiseqc, &Frequency);
|
ExecuteDiseqc(lastDiseqc, &Frequency);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
for (int i = 0; i < dvbFrontends.Size(); i++)
|
||||||
|
delete dvbFrontends[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDvbTuner::ProvidesDeliverySystem(int DeliverySystem) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < dvbFrontends.Size(); i++) {
|
||||||
|
if (dvbFrontends[i]->ProvidesDeliverySystem(DeliverySystem))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cDvbTuner::ProvidesModulation(int System, int StreamId, int Modulation) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < dvbFrontends.Size(); i++) {
|
||||||
|
if (dvbFrontends[i]->ProvidesModulation(System, StreamId, Modulation))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetRequiredDeliverySystem(const cChannel *Channel, const cDvbTransponderParameters *Dtp);//TODO
|
||||||
|
|
||||||
|
bool cDvbTuner::ProvidesFrontend(const cChannel *Channel, bool Activate) const
|
||||||
|
{
|
||||||
|
cDvbTransponderParameters dtp(Channel->Parameters());
|
||||||
|
int DeliverySystem = GetRequiredDeliverySystem(Channel, &dtp);
|
||||||
|
for (int i = 0; i < dvbFrontends.Size(); i++) {
|
||||||
|
if (dvbFrontends[i]->ProvidesDeliverySystem(DeliverySystem) && dvbFrontends[i]->ProvidesModulation(dtp.System(), dtp.StreamId(), dtp.Modulation())) {
|
||||||
|
if (Activate && dvbFrontend != dvbFrontends[i]) {
|
||||||
|
cMutexLock MutexLock(&mutex);
|
||||||
|
dvbFrontend->Close();
|
||||||
|
dvbFrontend = dvbFrontends[i];
|
||||||
|
fd_frontend = dvbFrontend->Open();
|
||||||
|
frontend = i;
|
||||||
|
dsyslog("using frontend %d/%d", adapter, frontend);
|
||||||
|
lastUncValue = 0;
|
||||||
|
lastUncDelta = 0;
|
||||||
|
lastUncChange = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbTuner::Bond(cDvbTuner *Tuner)
|
bool cDvbTuner::Bond(cDvbTuner *Tuner)
|
||||||
@ -585,7 +747,7 @@ bool cDvbTuner::GetSignalStats(int &Valid, double *Strength, double *Cnr, double
|
|||||||
CmdSeq.props = Props;
|
CmdSeq.props = Props;
|
||||||
Valid = DTV_STAT_VALID_NONE;
|
Valid = DTV_STAT_VALID_NONE;
|
||||||
if (ioctl(fd_frontend, FE_READ_STATUS, &FeStatus) != 0) {
|
if (ioctl(fd_frontend, FE_READ_STATUS, &FeStatus) != 0) {
|
||||||
esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
|
esyslog("ERROR: frontend %d/%d: %m (%s:%d)", adapter, frontend, __FILE__, __LINE__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (Status) {
|
if (Status) {
|
||||||
@ -606,7 +768,7 @@ bool cDvbTuner::GetSignalStats(int &Valid, double *Strength, double *Cnr, double
|
|||||||
if (Per) { SETCMD(DTV_STAT_ERROR_BLOCK_COUNT, 0);
|
if (Per) { SETCMD(DTV_STAT_ERROR_BLOCK_COUNT, 0);
|
||||||
SETCMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0); }
|
SETCMD(DTV_STAT_TOTAL_BLOCK_COUNT, 0); }
|
||||||
if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
|
if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
|
||||||
esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
|
esyslog("ERROR: frontend %d/%d: %m (%s:%d)", adapter, frontend, __FILE__, __LINE__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -939,7 +1101,7 @@ int cDvbTuner::GetSignalStrength(void) const
|
|||||||
SETCMD(DTV_CODE_RATE_HP, 0); // DVB-T only
|
SETCMD(DTV_CODE_RATE_HP, 0); // DVB-T only
|
||||||
SETCMD(DTV_INNER_FEC, 0);
|
SETCMD(DTV_INNER_FEC, 0);
|
||||||
if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
|
if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
|
||||||
esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
|
esyslog("ERROR: frontend %d/%d: %m (%s:%d)", adapter, frontend, __FILE__, __LINE__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int FeMod = (Props[1].u.st.len > 0) ? (int)Props[1].u.data : -1;
|
int FeMod = (Props[1].u.st.len > 0) ? (int)Props[1].u.data : -1;
|
||||||
@ -973,7 +1135,7 @@ int cDvbTuner::GetSignalStrength(void) const
|
|||||||
uint16_t MaxSignal = 0xFFFF; // Let's assume the default is using the entire range.
|
uint16_t MaxSignal = 0xFFFF; // Let's assume the default is using the entire range.
|
||||||
// Use the subsystemId to identify individual devices in case they need
|
// Use the subsystemId to identify individual devices in case they need
|
||||||
// special treatment to map their Signal value into the range 0...0xFFFF.
|
// special treatment to map their Signal value into the range 0...0xFFFF.
|
||||||
switch (subsystemId) {
|
switch (dvbFrontend->SubsystemId()) {
|
||||||
case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2)
|
case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2)
|
||||||
case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2)
|
case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2)
|
||||||
MaxSignal = 670; break;
|
MaxSignal = 670; break;
|
||||||
@ -982,7 +1144,7 @@ int cDvbTuner::GetSignalStrength(void) const
|
|||||||
if (s > 100)
|
if (s > 100)
|
||||||
s = 100;
|
s = 100;
|
||||||
#ifdef DEBUG_SIGNALSTRENGTH
|
#ifdef DEBUG_SIGNALSTRENGTH
|
||||||
fprintf(stderr, "FE %d/%d: API3 %08X S = %04X %04X %3d%%\n", adapter, frontend, subsystemId, MaxSignal, Signal, s);
|
fprintf(stderr, "FE %d/%d: API3 %08X S = %04X %04X %3d%%\n", adapter, frontend, dvbFrontend->SubsystemId(), MaxSignal, Signal, s);
|
||||||
#endif
|
#endif
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -1005,7 +1167,7 @@ int cDvbTuner::GetSignalQuality(void) const
|
|||||||
SETCMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0);
|
SETCMD(DTV_STAT_POST_ERROR_BIT_COUNT, 0);
|
||||||
SETCMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0);
|
SETCMD(DTV_STAT_POST_TOTAL_BIT_COUNT, 0);
|
||||||
if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
|
if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) != 0) {
|
||||||
esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
|
esyslog("ERROR: frontend %d/%d: %m (%s:%d)", adapter, frontend, __FILE__, __LINE__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int FeMod = (Props[1].u.st.len > 0) ? (int)Props[1].u.data : -1;
|
int FeMod = (Props[1].u.st.len > 0) ? (int)Props[1].u.data : -1;
|
||||||
@ -1132,7 +1294,7 @@ int cDvbTuner::GetSignalQuality(void) const
|
|||||||
uint16_t MaxSnr = 0xFFFF; // Let's assume the default is using the entire range.
|
uint16_t MaxSnr = 0xFFFF; // Let's assume the default is using the entire range.
|
||||||
// Use the subsystemId to identify individual devices in case they need
|
// Use the subsystemId to identify individual devices in case they need
|
||||||
// special treatment to map their Snr value into the range 0...0xFFFF.
|
// special treatment to map their Snr value into the range 0...0xFFFF.
|
||||||
switch (subsystemId) {
|
switch (dvbFrontend->SubsystemId()) {
|
||||||
case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2)
|
case 0x13C21019: // TT-budget S2-3200 (DVB-S/DVB-S2)
|
||||||
case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2)
|
case 0x1AE40001: // TechniSat SkyStar HD2 (DVB-S/DVB-S2)
|
||||||
if (frontendType == SYS_DVBS2) {
|
if (frontendType == SYS_DVBS2) {
|
||||||
@ -1154,7 +1316,7 @@ int cDvbTuner::GetSignalQuality(void) const
|
|||||||
if (q > 100)
|
if (q > 100)
|
||||||
q = 100;
|
q = 100;
|
||||||
#ifdef DEBUG_SIGNALQUALITY
|
#ifdef DEBUG_SIGNALQUALITY
|
||||||
fprintf(stderr, "FE %d/%d: API3 %08X Q = %04X %04X %d %5d %5d %3d%%\n", adapter, frontend, subsystemId, MaxSnr, Snr, HasSnr, HasBer ? int(Ber) : -1, HasUnc ? int(Unc) : -1, q);
|
fprintf(stderr, "FE %d/%d: API3 %08X Q = %04X %04X %d %5d %5d %3d%%\n", adapter, frontend, dvbFrontend->SubsystemId(), MaxSnr, Snr, HasSnr, HasBer ? int(Ber) : -1, HasUnc ? int(Unc) : -1, q);
|
||||||
#endif
|
#endif
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
@ -1265,7 +1427,7 @@ bool cDvbTuner::SetFrontend(void)
|
|||||||
CmdSeq.props = Props;
|
CmdSeq.props = Props;
|
||||||
SETCMD(DTV_CLEAR, 0);
|
SETCMD(DTV_CLEAR, 0);
|
||||||
if (ioctl(fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
|
if (ioctl(fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
|
||||||
esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
|
esyslog("ERROR: frontend %d/%d: %m (%s:%d)", adapter, frontend, __FILE__, __LINE__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CmdSeq.num = 0;
|
CmdSeq.num = 0;
|
||||||
@ -1390,7 +1552,7 @@ bool cDvbTuner::SetFrontend(void)
|
|||||||
}
|
}
|
||||||
SETCMD(DTV_TUNE, 0);
|
SETCMD(DTV_TUNE, 0);
|
||||||
if (ioctl(fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
|
if (ioctl(fd_frontend, FE_SET_PROPERTY, &CmdSeq) < 0) {
|
||||||
esyslog("ERROR: frontend %d/%d: %m", adapter, frontend);
|
esyslog("ERROR: frontend %d/%d: %m (%s:%d)", adapter, frontend, __FILE__, __LINE__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1402,11 +1564,11 @@ void cDvbTuner::Action(void)
|
|||||||
bool LostLock = false;
|
bool LostLock = false;
|
||||||
fe_status_t Status = (fe_status_t)0;
|
fe_status_t Status = (fe_status_t)0;
|
||||||
while (Running()) {
|
while (Running()) {
|
||||||
|
int WaitTime = 1000;
|
||||||
fe_status_t NewStatus;
|
fe_status_t NewStatus;
|
||||||
if (GetFrontendStatus(NewStatus))
|
if (GetFrontendStatus(NewStatus))
|
||||||
Status = NewStatus;
|
Status = NewStatus;
|
||||||
cMutexLock MutexLock(&mutex);
|
cMutexLock MutexLock(&mutex);
|
||||||
int WaitTime = 1000;
|
|
||||||
switch (tunerStatus) {
|
switch (tunerStatus) {
|
||||||
case tsIdle:
|
case tsIdle:
|
||||||
break; // we want the TimedWait() below!
|
break; // we want the TimedWait() below!
|
||||||
@ -1542,7 +1704,7 @@ int cDvbDevice::setTransferModeForDolbyDigital = 1;
|
|||||||
cMutex cDvbDevice::bondMutex;
|
cMutex cDvbDevice::bondMutex;
|
||||||
|
|
||||||
const char *DeliverySystemNames[] = {
|
const char *DeliverySystemNames[] = {
|
||||||
"",
|
"???",
|
||||||
"DVB-C",
|
"DVB-C",
|
||||||
"DVB-C",
|
"DVB-C",
|
||||||
"DVB-T",
|
"DVB-T",
|
||||||
@ -1580,16 +1742,10 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend)
|
|||||||
frontend = Frontend;
|
frontend = Frontend;
|
||||||
ciAdapter = NULL;
|
ciAdapter = NULL;
|
||||||
dvbTuner = NULL;
|
dvbTuner = NULL;
|
||||||
numDeliverySystems = 0;
|
|
||||||
numModulations = 0;
|
|
||||||
bondedDevice = NULL;
|
bondedDevice = NULL;
|
||||||
needsDetachBondedReceivers = false;
|
needsDetachBondedReceivers = false;
|
||||||
tsBuffer = NULL;
|
tsBuffer = NULL;
|
||||||
|
|
||||||
// Devices that are present on all card types:
|
|
||||||
|
|
||||||
int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK);
|
|
||||||
|
|
||||||
// Common Interface:
|
// Common Interface:
|
||||||
|
|
||||||
fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR);
|
fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR);
|
||||||
@ -1603,12 +1759,7 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend)
|
|||||||
|
|
||||||
// We only check the devices that must be present - the others will be checked before accessing them://XXX
|
// We only check the devices that must be present - the others will be checked before accessing them://XXX
|
||||||
|
|
||||||
if (fd_frontend >= 0) {
|
dvbTuner = new cDvbTuner(this, adapter, frontend);
|
||||||
if (QueryDeliverySystems(fd_frontend))
|
|
||||||
dvbTuner = new cDvbTuner(this, fd_frontend, adapter, frontend);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
esyslog("ERROR: can't open DVB device %d/%d", adapter, frontend);
|
|
||||||
|
|
||||||
StartSectionHandler();
|
StartSectionHandler();
|
||||||
}
|
}
|
||||||
@ -1623,12 +1774,12 @@ cDvbDevice::~cDvbDevice()
|
|||||||
// caused segfaults. Besides, the program is about to terminate anyway...
|
// caused segfaults. Besides, the program is about to terminate anyway...
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cDvbDevice::DvbName(const char *Name, int Adapter, int Frontend)
|
cString DvbName(const char *Name, int Adapter, int Frontend)
|
||||||
{
|
{
|
||||||
return cString::sprintf("%s/%s%d/%s%d", DEV_DVB_BASE, DEV_DVB_ADAPTER, Adapter, Name, Frontend);
|
return cString::sprintf("%s/%s%d/%s%d", DEV_DVB_BASE, DEV_DVB_ADAPTER, Adapter, Name, Frontend);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cDvbDevice::DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError)
|
int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError)
|
||||||
{
|
{
|
||||||
cString FileName = DvbName(Name, Adapter, Frontend);
|
cString FileName = DvbName(Name, Adapter, Frontend);
|
||||||
int fd = open(FileName, Mode);
|
int fd = open(FileName, Mode);
|
||||||
@ -1669,18 +1820,16 @@ bool cDvbDevice::Probe(int Adapter, int Frontend)
|
|||||||
|
|
||||||
cString cDvbDevice::DeviceType(void) const
|
cString cDvbDevice::DeviceType(void) const
|
||||||
{
|
{
|
||||||
if (dvbTuner) {
|
if (dvbTuner)
|
||||||
if (dvbTuner->FrontendType() != SYS_UNDEFINED)
|
|
||||||
return GetDeliverySystemName(dvbTuner->FrontendType());
|
return GetDeliverySystemName(dvbTuner->FrontendType());
|
||||||
if (numDeliverySystems)
|
|
||||||
return GetDeliverySystemName(deliverySystems[0]); // to have some reasonable default
|
|
||||||
}
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cDvbDevice::DeviceName(void) const
|
cString cDvbDevice::DeviceName(void) const
|
||||||
{
|
{
|
||||||
return frontendInfo.name;
|
if (dvbTuner)
|
||||||
|
return dvbTuner->FrontendName();
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbDevice::Initialize(void)
|
bool cDvbDevice::Initialize(void)
|
||||||
@ -1702,6 +1851,7 @@ bool cDvbDevice::Initialize(void)
|
|||||||
while ((f = AdapterDir.Next()) != NULL) {
|
while ((f = AdapterDir.Next()) != NULL) {
|
||||||
if (strstr(f->d_name, DEV_DVB_FRONTEND) == f->d_name) {
|
if (strstr(f->d_name, DEV_DVB_FRONTEND) == f->d_name) {
|
||||||
int Frontend = strtol(f->d_name + strlen(DEV_DVB_FRONTEND), NULL, 10);
|
int Frontend = strtol(f->d_name + strlen(DEV_DVB_FRONTEND), NULL, 10);
|
||||||
|
if (access(DvbName(DEV_DVB_DEMUX, Adapter, Frontend), F_OK) == 0) // we only create devices for actual demuxes
|
||||||
Nodes.Append(strdup(cString::sprintf("%2d %2d", Adapter, Frontend)));
|
Nodes.Append(strdup(cString::sprintf("%2d %2d", Adapter, Frontend)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1741,9 +1891,11 @@ bool cDvbDevice::Initialize(void)
|
|||||||
return Found > 0;
|
return Found > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbDevice::QueryDeliverySystems(int fd_frontend)
|
//TODO move this up to cDvbFrontend later (leaving it here for now to keep the diff small)
|
||||||
|
bool cDvbFrontend::QueryDeliverySystems(void)
|
||||||
{
|
{
|
||||||
numDeliverySystems = 0;
|
deliverySystems.Clear();
|
||||||
|
numModulations = 0;
|
||||||
if (ioctl(fd_frontend, FE_GET_INFO, &frontendInfo) < 0) {
|
if (ioctl(fd_frontend, FE_GET_INFO, &frontendInfo) < 0) {
|
||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
return false;
|
return false;
|
||||||
@ -1773,11 +1925,9 @@ bool cDvbDevice::QueryDeliverySystems(int fd_frontend)
|
|||||||
int Result = ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq);
|
int Result = ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq);
|
||||||
if (Result == 0) {
|
if (Result == 0) {
|
||||||
for (uint i = 0; i < Props[0].u.buffer.len; i++) {
|
for (uint i = 0; i < Props[0].u.buffer.len; i++) {
|
||||||
if (numDeliverySystems >= MAXDELIVERYSYSTEMS) {
|
// activate this line to simulate a multi-frontend device if you only have a single-frontend device with DVB-S and DVB-S2:
|
||||||
esyslog("ERROR: too many delivery systems on frontend %d/%d", adapter, frontend);
|
//if (frontend == 0 && Props[0].u.buffer.data[i] != SYS_DVBS || frontend == 1 && Props[0].u.buffer.data[i] != SYS_DVBS2)
|
||||||
break;
|
deliverySystems.Append(Props[0].u.buffer.data[i]);
|
||||||
}
|
|
||||||
deliverySystems[numDeliverySystems++] = Props[0].u.buffer.data[i];
|
|
||||||
}
|
}
|
||||||
LegacyMode = false;
|
LegacyMode = false;
|
||||||
}
|
}
|
||||||
@ -1788,22 +1938,22 @@ bool cDvbDevice::QueryDeliverySystems(int fd_frontend)
|
|||||||
if (LegacyMode) {
|
if (LegacyMode) {
|
||||||
// Legacy mode (DVB-API < 5.5):
|
// Legacy mode (DVB-API < 5.5):
|
||||||
switch (frontendInfo.type) {
|
switch (frontendInfo.type) {
|
||||||
case FE_QPSK: deliverySystems[numDeliverySystems++] = SYS_DVBS;
|
case FE_QPSK: deliverySystems.Append(SYS_DVBS);
|
||||||
if (frontendInfo.caps & FE_CAN_2G_MODULATION)
|
if (frontendInfo.caps & FE_CAN_2G_MODULATION)
|
||||||
deliverySystems[numDeliverySystems++] = SYS_DVBS2;
|
deliverySystems.Append(SYS_DVBS2);
|
||||||
break;
|
break;
|
||||||
case FE_OFDM: deliverySystems[numDeliverySystems++] = SYS_DVBT;
|
case FE_OFDM: deliverySystems.Append(SYS_DVBT);
|
||||||
if (frontendInfo.caps & FE_CAN_2G_MODULATION)
|
if (frontendInfo.caps & FE_CAN_2G_MODULATION)
|
||||||
deliverySystems[numDeliverySystems++] = SYS_DVBT2;
|
deliverySystems.Append(SYS_DVBT2);
|
||||||
break;
|
break;
|
||||||
case FE_QAM: deliverySystems[numDeliverySystems++] = SYS_DVBC_ANNEX_AC; break;
|
case FE_QAM: deliverySystems.Append(SYS_DVBC_ANNEX_AC); break;
|
||||||
case FE_ATSC: deliverySystems[numDeliverySystems++] = SYS_ATSC; break;
|
case FE_ATSC: deliverySystems.Append(SYS_ATSC); break;
|
||||||
default: esyslog("ERROR: unknown frontend type %d on frontend %d/%d", frontendInfo.type, adapter, frontend);
|
default: esyslog("ERROR: unknown frontend type %d on frontend %d/%d", frontendInfo.type, adapter, frontend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (numDeliverySystems > 0) {
|
if (deliverySystems.Size() > 0) {
|
||||||
cString ds("");
|
cString ds("");
|
||||||
for (int i = 0; i < numDeliverySystems; i++)
|
for (int i = 0; i < deliverySystems.Size(); i++)
|
||||||
ds = cString::sprintf("%s%s%s", *ds, i ? "," : "", GetDeliverySystemName(deliverySystems[i]));
|
ds = cString::sprintf("%s%s%s", *ds, i ? "," : "", GetDeliverySystemName(deliverySystems[i]));
|
||||||
cString ms("");
|
cString ms("");
|
||||||
if (frontendInfo.caps & FE_CAN_QPSK) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QPSK, ModulationValues)); }
|
if (frontendInfo.caps & FE_CAN_QPSK) { numModulations++; ms = cString::sprintf("%s%s%s", *ms, **ms ? "," : "", MapToUserString(QPSK, ModulationValues)); }
|
||||||
@ -1999,11 +2149,7 @@ void cDvbDevice::CloseFilter(int Handle)
|
|||||||
|
|
||||||
bool cDvbDevice::ProvidesDeliverySystem(int DeliverySystem) const
|
bool cDvbDevice::ProvidesDeliverySystem(int DeliverySystem) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numDeliverySystems; i++) {
|
return dvbTuner->ProvidesDeliverySystem(DeliverySystem);
|
||||||
if (deliverySystems[i] == DeliverySystem)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbDevice::ProvidesSource(int Source) const
|
bool cDvbDevice::ProvidesSource(int Source) const
|
||||||
@ -2020,20 +2166,9 @@ bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
|
|||||||
{
|
{
|
||||||
if (!ProvidesSource(Channel->Source()))
|
if (!ProvidesSource(Channel->Source()))
|
||||||
return false; // doesn't provide source
|
return false; // doesn't provide source
|
||||||
cDvbTransponderParameters dtp(Channel->Parameters());
|
if (!dvbTuner->ProvidesFrontend(Channel))
|
||||||
if (!ProvidesDeliverySystem(GetRequiredDeliverySystem(Channel, &dtp)) ||
|
|
||||||
dtp.StreamId() != 0 && !(frontendInfo.caps & FE_CAN_MULTISTREAM) ||
|
|
||||||
dtp.Modulation() == QPSK && !(frontendInfo.caps & FE_CAN_QPSK) ||
|
|
||||||
dtp.Modulation() == QAM_16 && !(frontendInfo.caps & FE_CAN_QAM_16) ||
|
|
||||||
dtp.Modulation() == QAM_32 && !(frontendInfo.caps & FE_CAN_QAM_32) ||
|
|
||||||
dtp.Modulation() == QAM_64 && !(frontendInfo.caps & FE_CAN_QAM_64) ||
|
|
||||||
dtp.Modulation() == QAM_128 && !(frontendInfo.caps & FE_CAN_QAM_128) ||
|
|
||||||
dtp.Modulation() == QAM_256 && !(frontendInfo.caps & FE_CAN_QAM_256) ||
|
|
||||||
dtp.Modulation() == QAM_AUTO && !(frontendInfo.caps & FE_CAN_QAM_AUTO) ||
|
|
||||||
dtp.Modulation() == VSB_8 && !(frontendInfo.caps & FE_CAN_8VSB) ||
|
|
||||||
dtp.Modulation() == VSB_16 && !(frontendInfo.caps & FE_CAN_16VSB) ||
|
|
||||||
dtp.Modulation() == PSK_8 && !(frontendInfo.caps & FE_CAN_TURBO_FEC) && dtp.System() == SYS_DVBS) // "turbo fec" is a non standard FEC used by North American broadcasters - this is a best guess to determine this condition
|
|
||||||
return false; // requires modulation system which frontend doesn't provide
|
return false; // requires modulation system which frontend doesn't provide
|
||||||
|
cDvbTransponderParameters dtp(Channel->Parameters());
|
||||||
if (!cSource::IsSat(Channel->Source()) ||
|
if (!cSource::IsSat(Channel->Source()) ||
|
||||||
(!Setup.DiSEqC || Diseqcs.Get(CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL)))
|
(!Setup.DiSEqC || Diseqcs.Get(CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL)))
|
||||||
return DeviceHooksProvidesTransponder(Channel);
|
return DeviceHooksProvidesTransponder(Channel);
|
||||||
@ -2047,7 +2182,7 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
|
|||||||
bool needsDetachReceivers = false;
|
bool needsDetachReceivers = false;
|
||||||
needsDetachBondedReceivers = false;
|
needsDetachBondedReceivers = false;
|
||||||
|
|
||||||
if (dvbTuner && ProvidesTransponder(Channel)) {
|
if (ProvidesTransponder(Channel)) {
|
||||||
result = hasPriority;
|
result = hasPriority;
|
||||||
if (Priority > IDLEPRIORITY) {
|
if (Priority > IDLEPRIORITY) {
|
||||||
if (Receiving()) {
|
if (Receiving()) {
|
||||||
@ -2097,7 +2232,7 @@ bool cDvbDevice::ProvidesEIT(void) const
|
|||||||
|
|
||||||
int cDvbDevice::NumProvidedSystems(void) const
|
int cDvbDevice::NumProvidedSystems(void) const
|
||||||
{
|
{
|
||||||
return numDeliverySystems + numModulations;
|
return dvbTuner ? dvbTuner->NumProvidedSystems() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cPositioner *cDvbDevice::Positioner(void) const
|
const cPositioner *cDvbDevice::Positioner(void) const
|
||||||
@ -2137,9 +2272,11 @@ bool cDvbDevice::MaySwitchTransponder(const cChannel *Channel) const
|
|||||||
|
|
||||||
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||||
{
|
{
|
||||||
if (dvbTuner)
|
if (dvbTuner->ProvidesFrontend(Channel, true)) {
|
||||||
dvbTuner->SetChannel(Channel);
|
dvbTuner->SetChannel(Channel);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cDvbDevice::HasLock(int TimeoutMs) const
|
bool cDvbDevice::HasLock(int TimeoutMs) const
|
||||||
|
15
dvbdevice.h
15
dvbdevice.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: dvbdevice.h 4.4 2017/05/09 11:24:47 kls Exp $
|
* $Id: dvbdevice.h 4.5 2018/10/20 11:39:11 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVBDEVICE_H
|
#ifndef __DVBDEVICE_H
|
||||||
@ -67,8 +67,6 @@ enum {
|
|||||||
|
|
||||||
// --- End of definitions for older DVB API versions -------------------------
|
// --- End of definitions for older DVB API versions -------------------------
|
||||||
|
|
||||||
#define MAXDELIVERYSYSTEMS 8
|
|
||||||
|
|
||||||
#define DEV_VIDEO "/dev/video"
|
#define DEV_VIDEO "/dev/video"
|
||||||
#define DEV_DVB_BASE "/dev/dvb"
|
#define DEV_DVB_BASE "/dev/dvb"
|
||||||
#define DEV_DVB_ADAPTER "adapter"
|
#define DEV_DVB_ADAPTER "adapter"
|
||||||
@ -162,12 +160,12 @@ public:
|
|||||||
|
|
||||||
class cDvbTuner;
|
class cDvbTuner;
|
||||||
|
|
||||||
|
cString DvbName(const char *Name, int Adapter, int Frontend);
|
||||||
|
int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError = false);
|
||||||
|
|
||||||
/// The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API.
|
/// The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API.
|
||||||
|
|
||||||
class cDvbDevice : public cDevice {
|
class cDvbDevice : public cDevice {
|
||||||
protected:
|
|
||||||
static cString DvbName(const char *Name, int Adapter, int Frontend);
|
|
||||||
static int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError = false);
|
|
||||||
private:
|
private:
|
||||||
static bool Exists(int Adapter, int Frontend);
|
static bool Exists(int Adapter, int Frontend);
|
||||||
///< Checks whether the given adapter/frontend exists.
|
///< Checks whether the given adapter/frontend exists.
|
||||||
@ -182,16 +180,11 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
int adapter, frontend;
|
int adapter, frontend;
|
||||||
private:
|
private:
|
||||||
dvb_frontend_info frontendInfo;
|
|
||||||
int deliverySystems[MAXDELIVERYSYSTEMS];
|
|
||||||
int numDeliverySystems;
|
|
||||||
int numModulations;
|
|
||||||
int fd_dvr, fd_ca;
|
int fd_dvr, fd_ca;
|
||||||
bool checkTsBuffer;
|
bool checkTsBuffer;
|
||||||
static cMutex bondMutex;
|
static cMutex bondMutex;
|
||||||
cDvbDevice *bondedDevice;
|
cDvbDevice *bondedDevice;
|
||||||
mutable bool needsDetachBondedReceivers;
|
mutable bool needsDetachBondedReceivers;
|
||||||
bool QueryDeliverySystems(int fd_frontend);
|
|
||||||
public:
|
public:
|
||||||
cDvbDevice(int Adapter, int Frontend);
|
cDvbDevice(int Adapter, int Frontend);
|
||||||
virtual ~cDvbDevice();
|
virtual ~cDvbDevice();
|
||||||
|
Loading…
Reference in New Issue
Block a user