summaryrefslogtreecommitdiff
path: root/patches
diff options
context:
space:
mode:
authorLars Heer <l.heer@gmx.de>2013-09-18 05:50:03 +0200
committerLars Heer <l.heer@gmx.de>2013-09-18 05:50:03 +0200
commitccf6e0f9c6b0481ed13e0f4794e3fbead750f385 (patch)
treeed86efb54f7ee41edfba5c89ca519b5fd10aa0d5 /patches
downloadvdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.gz
vdr-plugin-mcli-ccf6e0f9c6b0481ed13e0f4794e3fbead750f385.tar.bz2
added vdr-plugin-mcli-0.0.1+svn20120927
Diffstat (limited to 'patches')
-rw-r--r--patches/.svn/entries232
-rw-r--r--patches/.svn/text-base/reelvdr-device-handling-patch.diff.svn-base158
-rw-r--r--patches/.svn/text-base/vdr-1.4.0-closefilter.patch.svn-base45
-rw-r--r--patches/.svn/text-base/vdr-1.6-device-consistent-destruct.patch.svn-base97
-rw-r--r--patches/.svn/text-base/vdr-1.6-section-read-abstraction.patch.svn-base38
-rw-r--r--patches/.svn/text-base/vdr-1.6.0-altmenuaction.patch.svn-base38
-rw-r--r--patches/.svn/text-base/vdr-1.6.0-intcamdevices.patch.svn-base78
-rw-r--r--patches/reelvdr-device-handling-patch.diff158
-rw-r--r--patches/vdr-1.4.0-closefilter.patch45
-rw-r--r--patches/vdr-1.6-device-consistent-destruct.patch97
-rw-r--r--patches/vdr-1.6-section-read-abstraction.patch38
-rw-r--r--patches/vdr-1.6.0-altmenuaction.patch38
-rw-r--r--patches/vdr-1.6.0-intcamdevices.patch78
13 files changed, 1140 insertions, 0 deletions
diff --git a/patches/.svn/entries b/patches/.svn/entries
new file mode 100644
index 0000000..2a0dc74
--- /dev/null
+++ b/patches/.svn/entries
@@ -0,0 +1,232 @@
+10
+
+dir
+18963
+svn://reelbox.org/testing/src/vdr-plugins/src/mcli-1/patches
+svn://reelbox.org
+
+
+
+2011-07-12T13:36:23.313379Z
+16905
+rollercoaster
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12be777f-adf9-0310-842f-e37ecc4c7426
+
+vdr-1.6.0-intcamdevices.patch
+file
+
+
+
+
+2012-09-27T17:22:49.486848Z
+d32580d7ee6e033fa8754b408ef17dad
+2011-07-12T13:36:23.313379Z
+16905
+rollercoaster
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5742
+
+reelvdr-device-handling-patch.diff
+file
+
+
+
+
+2012-09-27T17:22:49.486848Z
+258a74a6d2dd9adfb93ba6e2cae04e6f
+2011-07-12T13:36:23.313379Z
+16905
+rollercoaster
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5301
+
+vdr-1.6-device-consistent-destruct.patch
+file
+
+
+
+
+2012-09-27T17:22:49.486848Z
+a577595d5404ebeb755d3068843663a5
+2011-07-12T13:36:23.313379Z
+16905
+rollercoaster
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3078
+
+vdr-1.6.0-altmenuaction.patch
+file
+
+
+
+
+2012-09-27T17:22:49.486848Z
+3fba8e9949af8cb9ebee9f659e49f531
+2011-07-12T13:36:23.313379Z
+16905
+rollercoaster
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1265
+
+vdr-1.6-section-read-abstraction.patch
+file
+
+
+
+
+2012-09-27T17:22:49.486848Z
+d73a367e8f7160ad8f3a29f0451d96b8
+2011-07-12T13:36:23.313379Z
+16905
+rollercoaster
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1773
+
+vdr-1.4.0-closefilter.patch
+file
+
+
+
+
+2012-09-27T17:22:49.486848Z
+b4de0862c8b127039dc5425780e4dfd4
+2011-07-12T13:36:23.313379Z
+16905
+rollercoaster
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1585
+
diff --git a/patches/.svn/text-base/reelvdr-device-handling-patch.diff.svn-base b/patches/.svn/text-base/reelvdr-device-handling-patch.diff.svn-base
new file mode 100644
index 0000000..d0592aa
--- /dev/null
+++ b/patches/.svn/text-base/reelvdr-device-handling-patch.diff.svn-base
@@ -0,0 +1,158 @@
+Index: device.c
+===================================================================
+--- device.c (Revision 10504)
++++ device.c (Arbeitskopie)
+@@ -270,14 +270,19 @@
+ for (int i = 0; i < MAXRECEIVERS; i++)
+ receiver[i] = NULL;
+
+- if (numDevices < MAXDEVICES)
+- device[numDevices++] = this;
+- else
+- esyslog("ERROR: too many devices!");
++ for (int i = 0; i < MAXDEVICES; i++)
++ if (!device[i]) {
++ device[i] = this;
++ numDevices++;
++ return;
++ }
++ esyslog("ERROR: too many devices!");
+ }
+
+ cDevice::~cDevice()
+ {
++ numDevices--;
++ device[DeviceNumber()] = NULL;
+ Detach(player);
+ for (int i = 0; i < MAXRECEIVERS; i++)
+ Detach(receiver[i]);
+@@ -290,7 +295,7 @@
+ {
+ for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
+ bool ready = true;
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && !device[i]->Ready())
+ ready = false;
+ }
+@@ -322,7 +327,7 @@
+
+ int cDevice::DeviceNumber(void) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] == this)
+ return i;
+ }
+@@ -336,7 +341,7 @@
+ bool cDevice::SetPrimaryDevice(int n)
+ {
+ n--;
+- if (0 <= n && n < numDevices && device[n]) {
++ if (0 <= n && n < MAXDEVICES && device[n]) {
+ isyslog("setting primary device to %d", n + 1);
+ if (primaryDevice)
+ primaryDevice->MakePrimaryDevice(false);
+@@ -369,15 +374,17 @@
+
+ cDevice *cDevice::GetDevice(int Index)
+ {
+- return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
++ return (0 <= Index && Index < MAXDEVICES) ? device[Index] : NULL;
+ }
+
+ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
+ {
+ cDevice *d = NULL;
+ uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ bool ndr;
++ if (device[i] == NULL)
++ continue; // this device was not allocated
+ #ifdef DETACH_UNUSED_DEVICES
+ if(!device[i]->Receiving()) {
+ isyslog("device %d (%p) not receiving", i, device[i]);
+@@ -419,10 +426,11 @@
+ void cDevice::Shutdown(void)
+ {
+ primaryDevice = NULL;
+- for (int i = 0; i < numDevices; i++) {
+- delete device[i];
+- device[i] = NULL;
++ for (int i = 0; i < MAXDEVICES; i++) {
++ if( device[i]) {
++ delete device[i];
+ }
++ }
+ }
+
+ uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
+@@ -724,6 +732,16 @@
+ return -1;
+ }
+
++int cDevice::ReadFilter(int Handle, void *Buffer, size_t Length)
++{
++ return safe_read(Handle, Buffer, Length);
++}
++
++void cDevice::CloseFilter(int Handle)
++{
++ close(Handle);
++}
++
+ void cDevice::AttachFilter(cFilter *Filter)
+ {
+ if (sectionHandler)
+@@ -753,7 +771,7 @@
+
+ bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
+ return false;
+ }
+Index: device.h
+===================================================================
+--- device.h (Revision 10504)
++++ device.h (Arbeitskopie)
+@@ -326,6 +326,15 @@
+ ///< Opens a file handle for the given filter data.
+ ///< A derived device that provides section data must
+ ///< implement this function.
++ virtual int ReadFilter(int Handle, void *Buffer, size_t Length);
++ ///< Read from a handle for the given filter data.
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
++ virtual void CloseFilter(int Handle);
++ ///< Closes a file handle that has previously been opened
++ ///< by OpenFilter(). If this is as simple as calling close(Handle),
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
+ void AttachFilter(cFilter *Filter);
+ ///< Attaches the given filter to this device.
+ void Detach(cFilter *Filter);
+Index: sections.c
+===================================================================
+--- sections.c (Revision 10504)
++++ sections.c (Arbeitskopie)
+@@ -105,7 +105,7 @@
+ for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
+ if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
+ if (--fh->used <= 0) {
+- close(fh->handle);
++ device->CloseFilter(fh->handle);
+ filterHandles.Del(fh);
+ break;
+ }
+@@ -198,7 +198,7 @@
+ if (fh) {
+ // Read section data:
+ unsigned char buf[4096]; // max. allowed size for any EIT section
+- int r = safe_read(fh->handle, buf, sizeof(buf));
++ int r = device->ReadFilter(fh->handle, buf, sizeof(buf));
+ if (!DeviceHasLock)
+ continue; // we do the read anyway, to flush any data that might have come from a different transponder
+ if (r > 3) { // minimum number of bytes necessary to get section length
diff --git a/patches/.svn/text-base/vdr-1.4.0-closefilter.patch.svn-base b/patches/.svn/text-base/vdr-1.4.0-closefilter.patch.svn-base
new file mode 100644
index 0000000..cd87632
--- /dev/null
+++ b/patches/.svn/text-base/vdr-1.4.0-closefilter.patch.svn-base
@@ -0,0 +1,45 @@
+Index: device.c
+===================================================================
+--- device.c (Revision 10449)
++++ device.c (Arbeitskopie)
+@@ -724,6 +724,11 @@
+ return -1;
+ }
+
++void cDevice::CloseFilter(int Handle)
++{
++ close(Handle);
++}
++
+ void cDevice::AttachFilter(cFilter *Filter)
+ {
+ if (sectionHandler)
+Index: device.h
+===================================================================
+--- device.h (Revision 10449)
++++ device.h (Arbeitskopie)
+@@ -326,6 +326,11 @@
+ ///< Opens a file handle for the given filter data.
+ ///< A derived device that provides section data must
+ ///< implement this function.
++ virtual void CloseFilter(int Handle);
++ ///< Closes a file handle that has previously been opened
++ ///< by OpenFilter(). If this is as simple as calling close(Handle),
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
+ void AttachFilter(cFilter *Filter);
+ ///< Attaches the given filter to this device.
+ void Detach(cFilter *Filter);
+Index: sections.c
+===================================================================
+--- sections.c (Revision 10449)
++++ sections.c (Arbeitskopie)
+@@ -105,7 +105,7 @@
+ for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
+ if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
+ if (--fh->used <= 0) {
+- close(fh->handle);
++ device->CloseFilter(fh->handle);
+ filterHandles.Del(fh);
+ break;
+ }
diff --git a/patches/.svn/text-base/vdr-1.6-device-consistent-destruct.patch.svn-base b/patches/.svn/text-base/vdr-1.6-device-consistent-destruct.patch.svn-base
new file mode 100644
index 0000000..9299be0
--- /dev/null
+++ b/patches/.svn/text-base/vdr-1.6-device-consistent-destruct.patch.svn-base
@@ -0,0 +1,97 @@
+--- ../vdr-1.6.0/device.c 2009-01-26 20:26:49.000000000 +0100
++++ device.c 2009-01-26 22:32:03.000000000 +0100
+@@ -253,14 +253,19 @@
+ for (int i = 0; i < MAXRECEIVERS; i++)
+ receiver[i] = NULL;
+
+- if (numDevices < MAXDEVICES)
+- device[numDevices++] = this;
+- else
+- esyslog("ERROR: too many devices!");
++ for (int i = 0; i < MAXDEVICES; i++)
++ if (!device[i]) {
++ device[i] = this;
++ numDevices++;
++ return;
++ }
++ esyslog("ERROR: too many devices!");
+ }
+
+ cDevice::~cDevice()
+ {
++ numDevices--;
++ device[DeviceNumber()] = NULL;
+ Detach(player);
+ DetachAllReceivers();
+ delete liveSubtitle;
+@@ -272,7 +277,7 @@
+ {
+ for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
+ bool ready = true;
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && !device[i]->Ready()) {
+ ready = false;
+ cCondWait::SleepMs(100);
+@@ -304,7 +309,7 @@
+
+ int cDevice::DeviceNumber(void) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] == this)
+ return i;
+ }
+@@ -318,7 +323,7 @@
+ bool cDevice::SetPrimaryDevice(int n)
+ {
+ n--;
+- if (0 <= n && n < numDevices && device[n]) {
++ if (0 <= n && n < MAXDEVICES && device[n]) {
+ isyslog("setting primary device to %d", n + 1);
+ if (primaryDevice)
+ primaryDevice->MakePrimaryDevice(false);
+@@ -352,7 +357,7 @@
+
+ cDevice *cDevice::GetDevice(int Index)
+ {
+- return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
++ return (0 <= Index && Index < MAXDEVICES) ? device[Index] : NULL;
+ }
+
+ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView)
+@@ -388,8 +393,8 @@
+ for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) {
+ if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY)
+ continue; // there is no CAM available in this slot
+- for (int i = 0; i < numDevices; i++) {
+- if (device[i] == AvoidDevice)
++ for (int i = 0; i < MAXDEVICES; i++) {
++ if (device[i] == NULL || device[i] == AvoidDevice)
+ 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
+@@ -463,10 +468,11 @@
+ void cDevice::Shutdown(void)
+ {
+ primaryDevice = NULL;
+- for (int i = 0; i < numDevices; i++) {
+- delete device[i];
+- device[i] = NULL;
++ for (int i = 0; i < MAXDEVICES; i++) {
++ if( device[i]) {
++ delete device[i];
+ }
++ }
+ }
+
+ uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
+@@ -703,7 +709,7 @@
+
+ bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
+ return false;
+ }
diff --git a/patches/.svn/text-base/vdr-1.6-section-read-abstraction.patch.svn-base b/patches/.svn/text-base/vdr-1.6-section-read-abstraction.patch.svn-base
new file mode 100644
index 0000000..3d1bea4
--- /dev/null
+++ b/patches/.svn/text-base/vdr-1.6-section-read-abstraction.patch.svn-base
@@ -0,0 +1,38 @@
+--- ../vdr-1.6.0/device.c 2009-01-26 20:26:49.000000000 +0100
++++ device.c 2009-01-26 23:12:59.000000000 +0100
+@@ -674,6 +680,11 @@
+ return -1;
+ }
+
++int cDevice::ReadFilter(int Handle, void *Buffer, size_t Length)
++{
++ return safe_read(Handle, Buffer, Length);
++}
++
+ void cDevice::CloseFilter(int Handle)
+ {
+ close(Handle);
+--- ../vdr-1.6.0/device.h 2009-01-26 20:26:49.000000000 +0100
++++ device.h 2009-01-26 23:12:41.000000000 +0100
+@@ -317,6 +317,10 @@
+ ///< Opens a file handle for the given filter data.
+ ///< A derived device that provides section data must
+ ///< implement this function.
++ virtual int ReadFilter(int Handle, void *Buffer, size_t Length);
++ ///< Read from a handle for the given filter data.
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
+ virtual void CloseFilter(int Handle);
+ ///< Closes a file handle that has previously been opened
+ ///< by OpenFilter(). If this is as simple as calling close(Handle),
+--- ../vdr-1.6.0/sections.c 2007-10-14 14:52:07.000000000 +0200
++++ sections.c 2009-01-26 23:14:00.000000000 +0100
+@@ -198,7 +198,7 @@
+ if (fh) {
+ // Read section data:
+ unsigned char buf[4096]; // max. allowed size for any EIT section
+- int r = safe_read(fh->handle, buf, sizeof(buf));
++ int r = device->ReadFilter(fh->handle, buf, sizeof(buf));
+ if (!DeviceHasLock)
+ continue; // we do the read anyway, to flush any data that might have come from a different transponder
+ if (r > 3) { // minimum number of bytes necessary to get section length
diff --git a/patches/.svn/text-base/vdr-1.6.0-altmenuaction.patch.svn-base b/patches/.svn/text-base/vdr-1.6.0-altmenuaction.patch.svn-base
new file mode 100644
index 0000000..4b06850
--- /dev/null
+++ b/patches/.svn/text-base/vdr-1.6.0-altmenuaction.patch.svn-base
@@ -0,0 +1,38 @@
+Index: plugin.h
+===================================================================
+--- plugin.h (revision 2072)
++++ plugin.h (working copy)
+@@ -45,7 +45,8 @@
+
+ virtual const char *MainMenuEntry(void);
+ virtual cOsdObject *MainMenuAction(void);
+-
++ virtual cOsdObject *AltMenuAction(void) { return NULL; };
++
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+ void SetupStore(const char *Name, const char *Value = NULL);
+Index: vdr.c
+===================================================================
+--- vdr.c (revision 2072)
++++ vdr.c (working copy)
+@@ -929,6 +929,19 @@
+ Recordings.Update();
+ DeletedRecordings.Update();
+ }
++ cPlugin *mcliPlugin = cPluginManager::GetPlugin("mcli");
++ if (mcliPlugin) {
++ if (!ShutdownHandler.countdown) { // if kPower has been pressed, cMenuShutdown takes precedence over other menus
++ cOsdObject *MyMenu = mcliPlugin->AltMenuAction();
++ if (MyMenu) { // is there any cam-menu waiting?
++ DELETE_MENU;
++ if (cControl::Control())
++ cControl::Control()->Hide();
++ Menu = MyMenu;
++ Menu->Show();
++ }
++ }
++ }
+ // CAM control:
+ if (!Menu && !cOsd::IsOpen())
+ Menu = CamControl();
diff --git a/patches/.svn/text-base/vdr-1.6.0-intcamdevices.patch.svn-base b/patches/.svn/text-base/vdr-1.6.0-intcamdevices.patch.svn-base
new file mode 100644
index 0000000..aab1fb4
--- /dev/null
+++ b/patches/.svn/text-base/vdr-1.6.0-intcamdevices.patch.svn-base
@@ -0,0 +1,78 @@
+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; }
+
diff --git a/patches/reelvdr-device-handling-patch.diff b/patches/reelvdr-device-handling-patch.diff
new file mode 100644
index 0000000..d0592aa
--- /dev/null
+++ b/patches/reelvdr-device-handling-patch.diff
@@ -0,0 +1,158 @@
+Index: device.c
+===================================================================
+--- device.c (Revision 10504)
++++ device.c (Arbeitskopie)
+@@ -270,14 +270,19 @@
+ for (int i = 0; i < MAXRECEIVERS; i++)
+ receiver[i] = NULL;
+
+- if (numDevices < MAXDEVICES)
+- device[numDevices++] = this;
+- else
+- esyslog("ERROR: too many devices!");
++ for (int i = 0; i < MAXDEVICES; i++)
++ if (!device[i]) {
++ device[i] = this;
++ numDevices++;
++ return;
++ }
++ esyslog("ERROR: too many devices!");
+ }
+
+ cDevice::~cDevice()
+ {
++ numDevices--;
++ device[DeviceNumber()] = NULL;
+ Detach(player);
+ for (int i = 0; i < MAXRECEIVERS; i++)
+ Detach(receiver[i]);
+@@ -290,7 +295,7 @@
+ {
+ for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
+ bool ready = true;
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && !device[i]->Ready())
+ ready = false;
+ }
+@@ -322,7 +327,7 @@
+
+ int cDevice::DeviceNumber(void) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] == this)
+ return i;
+ }
+@@ -336,7 +341,7 @@
+ bool cDevice::SetPrimaryDevice(int n)
+ {
+ n--;
+- if (0 <= n && n < numDevices && device[n]) {
++ if (0 <= n && n < MAXDEVICES && device[n]) {
+ isyslog("setting primary device to %d", n + 1);
+ if (primaryDevice)
+ primaryDevice->MakePrimaryDevice(false);
+@@ -369,15 +374,17 @@
+
+ cDevice *cDevice::GetDevice(int Index)
+ {
+- return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
++ return (0 <= Index && Index < MAXDEVICES) ? device[Index] : NULL;
+ }
+
+ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
+ {
+ cDevice *d = NULL;
+ uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ bool ndr;
++ if (device[i] == NULL)
++ continue; // this device was not allocated
+ #ifdef DETACH_UNUSED_DEVICES
+ if(!device[i]->Receiving()) {
+ isyslog("device %d (%p) not receiving", i, device[i]);
+@@ -419,10 +426,11 @@
+ void cDevice::Shutdown(void)
+ {
+ primaryDevice = NULL;
+- for (int i = 0; i < numDevices; i++) {
+- delete device[i];
+- device[i] = NULL;
++ for (int i = 0; i < MAXDEVICES; i++) {
++ if( device[i]) {
++ delete device[i];
+ }
++ }
+ }
+
+ uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
+@@ -724,6 +732,16 @@
+ return -1;
+ }
+
++int cDevice::ReadFilter(int Handle, void *Buffer, size_t Length)
++{
++ return safe_read(Handle, Buffer, Length);
++}
++
++void cDevice::CloseFilter(int Handle)
++{
++ close(Handle);
++}
++
+ void cDevice::AttachFilter(cFilter *Filter)
+ {
+ if (sectionHandler)
+@@ -753,7 +771,7 @@
+
+ bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
+ return false;
+ }
+Index: device.h
+===================================================================
+--- device.h (Revision 10504)
++++ device.h (Arbeitskopie)
+@@ -326,6 +326,15 @@
+ ///< Opens a file handle for the given filter data.
+ ///< A derived device that provides section data must
+ ///< implement this function.
++ virtual int ReadFilter(int Handle, void *Buffer, size_t Length);
++ ///< Read from a handle for the given filter data.
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
++ virtual void CloseFilter(int Handle);
++ ///< Closes a file handle that has previously been opened
++ ///< by OpenFilter(). If this is as simple as calling close(Handle),
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
+ void AttachFilter(cFilter *Filter);
+ ///< Attaches the given filter to this device.
+ void Detach(cFilter *Filter);
+Index: sections.c
+===================================================================
+--- sections.c (Revision 10504)
++++ sections.c (Arbeitskopie)
+@@ -105,7 +105,7 @@
+ for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
+ if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
+ if (--fh->used <= 0) {
+- close(fh->handle);
++ device->CloseFilter(fh->handle);
+ filterHandles.Del(fh);
+ break;
+ }
+@@ -198,7 +198,7 @@
+ if (fh) {
+ // Read section data:
+ unsigned char buf[4096]; // max. allowed size for any EIT section
+- int r = safe_read(fh->handle, buf, sizeof(buf));
++ int r = device->ReadFilter(fh->handle, buf, sizeof(buf));
+ if (!DeviceHasLock)
+ continue; // we do the read anyway, to flush any data that might have come from a different transponder
+ if (r > 3) { // minimum number of bytes necessary to get section length
diff --git a/patches/vdr-1.4.0-closefilter.patch b/patches/vdr-1.4.0-closefilter.patch
new file mode 100644
index 0000000..cd87632
--- /dev/null
+++ b/patches/vdr-1.4.0-closefilter.patch
@@ -0,0 +1,45 @@
+Index: device.c
+===================================================================
+--- device.c (Revision 10449)
++++ device.c (Arbeitskopie)
+@@ -724,6 +724,11 @@
+ return -1;
+ }
+
++void cDevice::CloseFilter(int Handle)
++{
++ close(Handle);
++}
++
+ void cDevice::AttachFilter(cFilter *Filter)
+ {
+ if (sectionHandler)
+Index: device.h
+===================================================================
+--- device.h (Revision 10449)
++++ device.h (Arbeitskopie)
+@@ -326,6 +326,11 @@
+ ///< Opens a file handle for the given filter data.
+ ///< A derived device that provides section data must
+ ///< implement this function.
++ virtual void CloseFilter(int Handle);
++ ///< Closes a file handle that has previously been opened
++ ///< by OpenFilter(). If this is as simple as calling close(Handle),
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
+ void AttachFilter(cFilter *Filter);
+ ///< Attaches the given filter to this device.
+ void Detach(cFilter *Filter);
+Index: sections.c
+===================================================================
+--- sections.c (Revision 10449)
++++ sections.c (Arbeitskopie)
+@@ -105,7 +105,7 @@
+ for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
+ if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
+ if (--fh->used <= 0) {
+- close(fh->handle);
++ device->CloseFilter(fh->handle);
+ filterHandles.Del(fh);
+ break;
+ }
diff --git a/patches/vdr-1.6-device-consistent-destruct.patch b/patches/vdr-1.6-device-consistent-destruct.patch
new file mode 100644
index 0000000..9299be0
--- /dev/null
+++ b/patches/vdr-1.6-device-consistent-destruct.patch
@@ -0,0 +1,97 @@
+--- ../vdr-1.6.0/device.c 2009-01-26 20:26:49.000000000 +0100
++++ device.c 2009-01-26 22:32:03.000000000 +0100
+@@ -253,14 +253,19 @@
+ for (int i = 0; i < MAXRECEIVERS; i++)
+ receiver[i] = NULL;
+
+- if (numDevices < MAXDEVICES)
+- device[numDevices++] = this;
+- else
+- esyslog("ERROR: too many devices!");
++ for (int i = 0; i < MAXDEVICES; i++)
++ if (!device[i]) {
++ device[i] = this;
++ numDevices++;
++ return;
++ }
++ esyslog("ERROR: too many devices!");
+ }
+
+ cDevice::~cDevice()
+ {
++ numDevices--;
++ device[DeviceNumber()] = NULL;
+ Detach(player);
+ DetachAllReceivers();
+ delete liveSubtitle;
+@@ -272,7 +277,7 @@
+ {
+ for (time_t t0 = time(NULL); time(NULL) - t0 < Timeout; ) {
+ bool ready = true;
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && !device[i]->Ready()) {
+ ready = false;
+ cCondWait::SleepMs(100);
+@@ -304,7 +309,7 @@
+
+ int cDevice::DeviceNumber(void) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] == this)
+ return i;
+ }
+@@ -318,7 +323,7 @@
+ bool cDevice::SetPrimaryDevice(int n)
+ {
+ n--;
+- if (0 <= n && n < numDevices && device[n]) {
++ if (0 <= n && n < MAXDEVICES && device[n]) {
+ isyslog("setting primary device to %d", n + 1);
+ if (primaryDevice)
+ primaryDevice->MakePrimaryDevice(false);
+@@ -352,7 +357,7 @@
+
+ cDevice *cDevice::GetDevice(int Index)
+ {
+- return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
++ return (0 <= Index && Index < MAXDEVICES) ? device[Index] : NULL;
+ }
+
+ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView)
+@@ -388,8 +393,8 @@
+ for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) {
+ if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY)
+ continue; // there is no CAM available in this slot
+- for (int i = 0; i < numDevices; i++) {
+- if (device[i] == AvoidDevice)
++ for (int i = 0; i < MAXDEVICES; i++) {
++ if (device[i] == NULL || device[i] == AvoidDevice)
+ 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
+@@ -463,10 +468,11 @@
+ void cDevice::Shutdown(void)
+ {
+ primaryDevice = NULL;
+- for (int i = 0; i < numDevices; i++) {
+- delete device[i];
+- device[i] = NULL;
++ for (int i = 0; i < MAXDEVICES; i++) {
++ if( device[i]) {
++ delete device[i];
+ }
++ }
+ }
+
+ uchar *cDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
+@@ -703,7 +709,7 @@
+
+ bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const
+ {
+- for (int i = 0; i < numDevices; i++) {
++ for (int i = 0; i < MAXDEVICES; i++) {
+ if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
+ return false;
+ }
diff --git a/patches/vdr-1.6-section-read-abstraction.patch b/patches/vdr-1.6-section-read-abstraction.patch
new file mode 100644
index 0000000..3d1bea4
--- /dev/null
+++ b/patches/vdr-1.6-section-read-abstraction.patch
@@ -0,0 +1,38 @@
+--- ../vdr-1.6.0/device.c 2009-01-26 20:26:49.000000000 +0100
++++ device.c 2009-01-26 23:12:59.000000000 +0100
+@@ -674,6 +680,11 @@
+ return -1;
+ }
+
++int cDevice::ReadFilter(int Handle, void *Buffer, size_t Length)
++{
++ return safe_read(Handle, Buffer, Length);
++}
++
+ void cDevice::CloseFilter(int Handle)
+ {
+ close(Handle);
+--- ../vdr-1.6.0/device.h 2009-01-26 20:26:49.000000000 +0100
++++ device.h 2009-01-26 23:12:41.000000000 +0100
+@@ -317,6 +317,10 @@
+ ///< Opens a file handle for the given filter data.
+ ///< A derived device that provides section data must
+ ///< implement this function.
++ virtual int ReadFilter(int Handle, void *Buffer, size_t Length);
++ ///< Read from a handle for the given filter data.
++ ///< a derived class need not implement this function, because this
++ ///< is done by the default implementation.
+ virtual void CloseFilter(int Handle);
+ ///< Closes a file handle that has previously been opened
+ ///< by OpenFilter(). If this is as simple as calling close(Handle),
+--- ../vdr-1.6.0/sections.c 2007-10-14 14:52:07.000000000 +0200
++++ sections.c 2009-01-26 23:14:00.000000000 +0100
+@@ -198,7 +198,7 @@
+ if (fh) {
+ // Read section data:
+ unsigned char buf[4096]; // max. allowed size for any EIT section
+- int r = safe_read(fh->handle, buf, sizeof(buf));
++ int r = device->ReadFilter(fh->handle, buf, sizeof(buf));
+ if (!DeviceHasLock)
+ continue; // we do the read anyway, to flush any data that might have come from a different transponder
+ if (r > 3) { // minimum number of bytes necessary to get section length
diff --git a/patches/vdr-1.6.0-altmenuaction.patch b/patches/vdr-1.6.0-altmenuaction.patch
new file mode 100644
index 0000000..4b06850
--- /dev/null
+++ b/patches/vdr-1.6.0-altmenuaction.patch
@@ -0,0 +1,38 @@
+Index: plugin.h
+===================================================================
+--- plugin.h (revision 2072)
++++ plugin.h (working copy)
+@@ -45,7 +45,8 @@
+
+ virtual const char *MainMenuEntry(void);
+ virtual cOsdObject *MainMenuAction(void);
+-
++ virtual cOsdObject *AltMenuAction(void) { return NULL; };
++
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+ void SetupStore(const char *Name, const char *Value = NULL);
+Index: vdr.c
+===================================================================
+--- vdr.c (revision 2072)
++++ vdr.c (working copy)
+@@ -929,6 +929,19 @@
+ Recordings.Update();
+ DeletedRecordings.Update();
+ }
++ cPlugin *mcliPlugin = cPluginManager::GetPlugin("mcli");
++ if (mcliPlugin) {
++ if (!ShutdownHandler.countdown) { // if kPower has been pressed, cMenuShutdown takes precedence over other menus
++ cOsdObject *MyMenu = mcliPlugin->AltMenuAction();
++ if (MyMenu) { // is there any cam-menu waiting?
++ DELETE_MENU;
++ if (cControl::Control())
++ cControl::Control()->Hide();
++ Menu = MyMenu;
++ Menu->Show();
++ }
++ }
++ }
+ // CAM control:
+ if (!Menu && !cOsd::IsOpen())
+ Menu = CamControl();
diff --git a/patches/vdr-1.6.0-intcamdevices.patch b/patches/vdr-1.6.0-intcamdevices.patch
new file mode 100644
index 0000000..aab1fb4
--- /dev/null
+++ b/patches/vdr-1.6.0-intcamdevices.patch
@@ -0,0 +1,78 @@
+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; }
+