The attached patch (for VDR 1.7.16) implements support for multituner cards
where only one tuner can be active at one time, the so called shared frontend
cards (notably the HVR-4000 and its derivatives).
Currently VDR tries to open all the frontends on startup, with the result that
the first frontend (usually DVB-S) works, but the second (usually DVB-T) fails
with Device or resource busy error. The patch adds a new configuration option
to setup.conf, called OnDemand; it defaults to 0 (exactly the current
behaviour). If set to 1, tuners will be appropriately opened and closed when
switching channels. I've tested it with the vnsi plugin and XBMC.
I'd be happy if someone could review it and tell me if there is anything to
correct and if it is possible to mainline it.
Alberto
diff -rupN vdr-1.7.16/config.c vdr-1.7.16-new/config.c
--- vdr-1.7.16/config.c 2010-06-06 12:06:43.0 +0200
+++ vdr-1.7.16-new/config.c 2010-09-19 23:38:15.569140978 +0200
@@ -399,6 +399,7 @@ cSetup::cSetup(void)
InitialVolume = -1;
ChannelsWrap = 0;
EmergencyExit = 1;
+ OnDemand = 0;
}
cSetup cSetup::operator= (const cSetup s)
@@ -590,6 +591,7 @@ bool cSetup::Parse(const char *Name, con
else if (!strcasecmp(Name, InitialVolume)) InitialVolume = atoi(Value);
else if (!strcasecmp(Name, ChannelsWrap))ChannelsWrap = atoi(Value);
else if (!strcasecmp(Name, EmergencyExit)) EmergencyExit = atoi(Value);
+ else if (!strcasecmp(Name, OnDemand))OnDemand = atoi(Value);
else
return false;
return true;
@@ -686,6 +688,7 @@ bool cSetup::Save(void)
Store(InitialVolume, InitialVolume);
Store(ChannelsWrap, ChannelsWrap);
Store(EmergencyExit, EmergencyExit);
+ Store(OnDemand, OnDemand);
Sort();
diff -rupN vdr-1.7.16/config.h vdr-1.7.16-new/config.h
--- vdr-1.7.16/config.h 2010-09-12 13:31:21.0 +0200
+++ vdr-1.7.16-new/config.h 2010-09-19 23:38:15.569140978 +0200
@@ -291,6 +291,7 @@ public:
int InitialVolume;
int ChannelsWrap;
int EmergencyExit;
+ int OnDemand;
int __EndData__;
cSetup(void);
cSetup operator= (const cSetup s);
diff -rupN vdr-1.7.16/device.c vdr-1.7.16-new/device.c
--- vdr-1.7.16/device.c 2010-06-03 15:35:02.0 +0200
+++ vdr-1.7.16-new/device.c 2010-09-19 23:38:15.570141038 +0200
@@ -261,6 +261,7 @@ cDevice *cDevice::GetDevice(const cChann
if (NumUsableSlots SlotPriority[j] MAXPRIORITY)
continue; // there is no CAM available in this slot
for (int i = 0; i numDevices; i++) {
+ device[i]-Access();
if (device[i] == AvoidDevice)
continue; // this device shall be temporarily avoided
if (Channel-Ca() Channel-Ca() = CA_DVB_MAX Channel-Ca() != device[i]-CardIndex() + 1)
@@ -269,6 +270,9 @@ cDevice *cDevice::GetDevice(const cChann
continue; // CAM slot can't be used with this device
bool ndr;
if (device[i]-ProvidesChannel(Channel, Priority, ndr)) { // this device is basicly able to do the job
+ if (Setup.OnDemand) {
+ return device[i]; // Skip impact tests to avoid long waintings and timeouts
+ }
if (NumUsableSlots device[i]-CamSlot() device[i]-CamSlot() != CamSlots.Get(j))
ndr = true; // using a different CAM slot requires detaching receivers
// Put together an integer number that reflects the impact using
@@ -633,6 +637,13 @@ bool cDevice::MaySwitchTransponder(void)
return !Receiving(true) !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid);
}
+void cDevice::CloseAll()
+{
+ for (int i = 0; i numDevices; i++) {
+device[i]-Close();
+ }
+}
+
bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
{
if (LiveView) {
@@ -698,6 +709,7 @@ eSetChannelResult cDevice::SetChannel(co
eSetChannelResult Result = scrOk;
+ Device-Access();
// If this DVB card can't receive this channel, let's see if we can
// use the card that actually can receive it and transfer data from there:
@@ -771,6 +783,14 @@ void cDevice::ForceTransferMode(void)
}
}
+void cDevice::Access(bool ondemand)
+{
+}
+
+void cDevice::Close(void)
+{
+}
+
bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
{
return false;
diff -rupN vdr-1.7.16/device.h vdr-1.7.16-new/device.h
--- vdr-1.7.16/device.h 2010-04-05 11:51:29.0 +0200
+++ vdr-1.7.16-new/device.h 2010-09-19 23:50:40.741137254 +0200
@@ -159,6 +159,8 @@ public:
static void Shutdown(void);
/// Closes down all devices.
/// Must be called at the end of the program.
+ virtual void CloseAll(void);
+ /// Closes all devices in OnDemand mode (called by Access()).
private:
static int nextCardIndex;
int cardIndex;
@@ -189,6 +191,10 @@ protected:
/// device (On = false), it should do so in this function.
/// A