diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 49df88fe..0ed0a4fd 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -2347,6 +2347,9 @@ Tobias Grimm for avoiding a gcc 4.6 compiler error in the skincurses plugin. for suggesting to move setting LC_NUMERIC further up to make sure any floating point numbers use a decimal point + for implementing cDevice::HasInternalCam(), which can be implemented by devices that + provide encrypted channels in an already decrypted form, without requiring explicit + handling of a CAM Helge Lenz for reporting a bug in setting the 'Delta' parameter when calling the shutdown diff --git a/HISTORY b/HISTORY index fb21667b..4e937fb3 100644 --- a/HISTORY +++ b/HISTORY @@ -7208,3 +7208,6 @@ Video Disk Recorder Revision History - Fixed a race condition when zapping in transfer mode (reported by Reinhard Nissl). - The new function cDevice::ReadFilter() can be used by devices to implement their own way of retrieving section filter data (thanks to Deti Fliegl). +- The new function cDevice::HasInternalCam() can be implemented by devices that + provide encrypted channels in an already decrypted form, without requiring explicit + handling of a CAM (thanks to Tobias Grimm). diff --git a/device.c b/device.c index e2bcd915..0f667718 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 2.64 2012/08/26 12:53:39 kls Exp $ + * $Id: device.c 2.65 2012/08/26 13:45:38 kls Exp $ */ #include "device.h" @@ -241,6 +241,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView int NumCamSlots = CamSlots.Count(); int SlotPriority[NumCamSlots]; int NumUsableSlots = 0; + bool InternalCamNeeded = false; if (Channel->Ca() >= CA_ENCRYPTED_MIN) { for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) { SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used @@ -254,7 +255,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView } } if (!NumUsableSlots) - return NULL; // no CAM is able to decrypt this channel + InternalCamNeeded = true; // no CAM is able to decrypt this channel } bool NeedsDetachReceivers = false; @@ -268,11 +269,14 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView for (int i = 0; i < numDevices; i++) { if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != device[i]->CardIndex() + 1) continue; // a specific card was requested, but not this one - if (NumUsableSlots && !CamSlots.Get(j)->Assign(device[i], true)) + bool HasInternalCam = device[i]->HasInternalCam(); + if (InternalCamNeeded && !HasInternalCam) + continue; // no CAM is able to decrypt this channel and the device uses vdr handled CAMs + if (NumUsableSlots && !HasInternalCam && !CamSlots.Get(j)->Assign(device[i], true)) continue; // CAM slot can't be used with this device bool ndr; if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job - if (NumUsableSlots && device[i]->CamSlot() && device[i]->CamSlot() != CamSlots.Get(j)) + if (NumUsableSlots && !HasInternalCam && 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 // this device would have on the overall system. Each condition is represented @@ -287,18 +291,18 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView imp <<= 4; imp |= GetClippedNumProvidedSystems(4, device[i]) - 1; // avoid cards which support multiple delivery systems imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device imp <<= 8; imp |= device[i]->Priority() - IDLEPRIORITY; // use the device with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used) - imp <<= 8; imp |= (NumUsableSlots ? SlotPriority[j] : IDLEPRIORITY) - IDLEPRIORITY; // use the CAM slot with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used) + imp <<= 8; imp |= ((NumUsableSlots && !HasInternalCam) ? SlotPriority[j] : IDLEPRIORITY) - IDLEPRIORITY;// use the CAM slot with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used) imp <<= 1; imp |= ndr; // avoid devices if we need to detach existing receivers - imp <<= 1; imp |= NumUsableSlots ? 0 : device[i]->HasCi(); // avoid cards with Common Interface for FTA channels + imp <<= 1; imp |= (NumUsableSlots || InternalCamNeeded) ? 0 : device[i]->HasCi(); // avoid cards with Common Interface for FTA channels imp <<= 1; imp |= device[i]->AvoidRecording(); // avoid SD full featured cards - imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel + imp <<= 1; imp |= (NumUsableSlots && !HasInternalCam) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel imp <<= 1; imp |= device[i]->IsPrimaryDevice(); // avoid the primary device if (imp < Impact) { // This device has less impact than any previous one, so we take it. Impact = imp; d = device[i]; NeedsDetachReceivers = ndr; - if (NumUsableSlots) + if (NumUsableSlots && !HasInternalCam) s = CamSlots.Get(j); } } diff --git a/device.h b/device.h index 89a65694..1f945218 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 2.40 2012/08/26 12:56:14 kls Exp $ + * $Id: device.h 2.41 2012/08/26 13:25:44 kls Exp $ */ #ifndef __DEVICE_H @@ -415,6 +415,12 @@ private: public: virtual bool HasCi(void); ///< Returns true if this device has a Common Interface. + virtual bool HasInternalCam(void) { return false; } + ///< Returns true if this device handles encrypted channels itself + ///< without VDR assistance. This can be e.g. if the device is a + ///< client that gets the stream from another VDR instance that has + ///< already decrypted the stream. In this case ProvidesChannel() + ///< shall check whether the channel can be decrypted. void SetCamSlot(cCamSlot *CamSlot); ///< Sets the given CamSlot to be used with this device. cCamSlot *CamSlot(void) const { return camSlot; }