Index: vdr-1.6.0-nocamdevices/device.c =================================================================== --- vdr-1.6.0-nocamdevices/device.c +++ vdr-1.6.0-nocamdevices/device.c 2008-04-27 18:55:37.000000000 +0300 @@ -363,6 +363,7 @@ 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 @@ -376,7 +377,7 @@ } } 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; @@ -392,11 +393,13 @@ continue; // this device shall be temporarily avoided 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)) + if (InternalCamNeeded && !device[i]->HasInternalCam()) + continue; // no CAM is able to decrypt this channel and the device uses vdr handled CAMs + if (NumUsableSlots && !device[i]->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 basicly able to do the job - if (NumUsableSlots && device[i]->CamSlot() && device[i]->CamSlot() != CamSlots.Get(j)) + if (NumUsableSlots && !device[i]->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 @@ -410,18 +413,18 @@ imp <<= 1; imp |= device[i]->Receiving(); // avoid devices that are receiving imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF); // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used) - imp <<= 8; imp |= min(max((NumUsableSlots ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF); // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used) + imp <<= 8; imp |= min(max(((NumUsableSlots && !device[i]->HasInternalCam()) ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF); // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used) imp <<= 1; imp |= ndr; // avoid devices if we need to detach existing receivers imp <<= 1; imp |= device[i]->IsPrimaryDevice(); // avoid the primary device - 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]->HasDecoder(); // avoid 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 && !device[i]->HasInternalCam()) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel 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 && !device[i]->HasInternalCam()) s = CamSlots.Get(j); } } Index: vdr-1.6.0-nocamdevices/device.h =================================================================== --- vdr-1.6.0-nocamdevices/device.h +++ vdr-1.6.0-nocamdevices/device.h 2008-04-27 18:55:49.000000000 +0300 @@ -335,6 +335,12 @@ 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. when 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; }