diff -u -N -r vdr_1.4.5_orig/device.c vdr_1.4.5_eddi_v2/device.c
--- vdr_1.4.5_orig/device.c	2006-09-03 12:13:25.000000000 +0200
+++ vdr_1.4.5_eddi_v2/device.c	2007-02-10 03:02:54.000000000 +0100
@@ -18,6 +18,7 @@
 #include "receiver.h"
 #include "status.h"
 #include "transfer.h"
+#include "dvbdevice.h"
 
 // --- cPesAssembler ---------------------------------------------------------
 
@@ -143,13 +144,21 @@
 int cDevice::numDevices = 0;
 int cDevice::useDevice = 0;
 int cDevice::nextCardIndex = 0;
+int cDevice::forceCardIndex = -1;
+int cDevice::numFrontends = 0;
+int cDevice::curFrontends = 0;
 int cDevice::currentChannel = 1;
 cDevice *cDevice::device[MAXDEVICES] = { NULL };
 cDevice *cDevice::primaryDevice = NULL;
 
 cDevice::cDevice(void)
 {
-  cardIndex = nextCardIndex++;
+  esyslog("cDevice Constructor");
+
+  if (forceCardIndex >=0)
+    cardIndex = forceCardIndex;
+  else
+    cardIndex = nextCardIndex++;
 
   SetDescription("receiver on device %d", CardIndex() + 1);
 
@@ -174,14 +183,22 @@
   for (int i = 0; i < MAXRECEIVERS; i++)
       receiver[i] = NULL;
 
-  if (numDevices < MAXDEVICES)
-     device[numDevices++] = this;
-  else
-     esyslog("ERROR: too many devices!");
+  if (forceCardIndex >=0)
+       device[cardIndex] = this;
+  else {
+    if (numDevices < MAXDEVICES)
+       device[numDevices++] = this;
+    else
+       esyslog("ERROR: too many devices!");
+  }
+  esyslog("cDevice Constructor: cardIndex=%d", cardIndex);
+  if (forceCardIndex >=0)
+    forceCardIndex = -1;
 }
 
 cDevice::~cDevice()
 {
+  esyslog("cDevice Destructor");
   Detach(player);
   for (int i = 0; i < MAXRECEIVERS; i++)
       Detach(receiver[i]);
@@ -192,6 +209,7 @@
   delete eitFilter;
   delete sectionHandler;
   delete pesAssembler;
+  esyslog("cDevice Destructor: cardIndex=%d", cardIndex);
 }
 
 bool cDevice::WaitForAllDevicesReady(int Timeout)
@@ -282,9 +300,50 @@
 {
   cDevice *d = NULL;
   uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
+
+  int frontend = 0, maxfrontends = 0;
+
+
   for (int i = 0; i < numDevices; i++) {
       bool ndr;
+
+      maxfrontends = device[i]->GetNumFrontends();
+
+
+while (!d && frontend <= maxfrontends) {
+      esyslog("debug frontend %d numfrontend %d", frontend, maxfrontends);
+
+
+
+
+  if (frontend != device[i]->GetCurFrontends()) {
+//    esyslog("cDvbDevice::ProvidesChannel stub: stop and restart frontend adapter/frontend %d/%d", adapter, frontend);
+
+//    esyslog("cDvbDevice::ProvidesChannel ForceCardIndex(%d)",adapter);
+//    ForceCardIndex(adapter);
+//    esyslog("cDvbDevice::ProvidesChannel delete dvbDevice[%d]",adapter);
+//    delete dvbDevice[adapter];
+//    esyslog("cDvbDevice::ProvidesChannel dvbDevice[%d] = NULL",adapter);
+//    dvbDevice[adapter] = NULL;
+//    esyslog("cDvbDevice::ProvidesChannel new cDvbDevice(%d,%d)",adapter, frontend);
+//    dvbDevice[adapter] = new cDvbDevice(adapter, frontend);
+//    esyslog("cDvbDevice::ProvidesChannel dvbDevice[%d]->SetCurFrontends(%d);",adapter, frontend);
+//    dvbDevice[adapter]->SetCurFrontends(frontend);
+//    esyslog("cDvbDevice::ProvidesChannel ForceCardIndex(-1)");
+//    ForceCardIndex(-1);
+
+    //device[i]->ForceCardIndex(i);
+    esyslog("*cDevice::GetDevice delete device[%d]",i);
+    device[i]->ForceCardIndex(i);
+    delete device[i];
+    new cDvbDevice(i, frontend, 1); //,true
+    device[i]->ForceCardIndex(-1);
+  }
+
+
+
       if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
+         esyslog("This frontend provides the channel");
          // Put together an integer number that reflects the "impact" using
          // this device would have on the overall system. Each condition is represented
          // by one bit in the number (or several bits, if the condition is actually
@@ -307,7 +366,10 @@
                *NeedsDetachReceivers = ndr;
             }
          }
+       frontend++;
       }
+  }
+
   return d;
 }
 
diff -u -N -r vdr_1.4.5_orig/device.h vdr_1.4.5_eddi_v2/device.h
--- vdr_1.4.5_orig/device.h	2006-06-15 11:32:48.000000000 +0200
+++ vdr_1.4.5_eddi_v2/device.h	2007-02-10 02:43:06.000000000 +0100
@@ -139,6 +139,8 @@
          ///< Must be called at the end of the program.
 private:
   static int nextCardIndex;
+  static int forceCardIndex;
+  static int numFrontends, curFrontends;
   int cardIndex;
 protected:
   cDevice(void);
@@ -165,10 +167,15 @@
          ///< anything the device needs to set up when it becomes the primary
          ///< device (On = true) or to shut down when it no longer is the primary
          ///< device (On = false), it should do so in this function.
+  static void ForceCardIndex(int n) { forceCardIndex = n; }
 public:
   bool IsPrimaryDevice(void) const { return this == primaryDevice; }
   int CardIndex(void) const { return cardIndex; }
          ///< Returns the card index of this device (0 ... MAXDEVICES - 1).
+  void SetNumFrontends(int n) { numFrontends = n; esyslog("SetNumFrontends: %d", numFrontends); }
+  int GetNumFrontends(void) const { esyslog("GetNumFrontends: %d", numFrontends); return numFrontends; }
+  void SetCurFrontends(int n) { curFrontends = n; esyslog("SetCurFrontends: %d", curFrontends); }
+  int GetCurFrontends(void) const { esyslog("GetCurFrontends: %d", curFrontends); return curFrontends; }
   int DeviceNumber(void) const;
          ///< Returns the number of this device (0 ... numDevices).
   virtual int ProvidesCa(const cChannel *Channel) const;
diff -u -N -r vdr_1.4.5_orig/dvbdevice.c vdr_1.4.5_eddi_v2/dvbdevice.c
--- vdr_1.4.5_orig/dvbdevice.c	2006-08-14 11:38:32.000000000 +0200
+++ vdr_1.4.5_eddi_v2/dvbdevice.c	2007-02-10 03:16:41.000000000 +0100
@@ -28,7 +28,6 @@
 
 #define DO_REC_AND_PLAY_ON_PRIMARY_DEVICE 1
 #define DO_MULTIPLE_RECORDINGS 1
-//#define DO_MULTIPLE_CA_CHANNELS
 
 #define DEV_VIDEO         "/dev/video"
 #define DEV_DVB_ADAPTER   "/dev/dvb/adapter"
@@ -47,22 +46,25 @@
 #define DVBT_TUNE_TIMEOUT  9000 //ms
 #define DVBT_LOCK_TIMEOUT  2000 //ms
 
+cDvbDevice *dvbDevice;
+
 class cDvbName {
 private:
   char buffer[PATH_MAX];
 public:
-  cDvbName(const char *Name, int n) {
-    snprintf(buffer, sizeof(buffer), "%s%d/%s%d", DEV_DVB_ADAPTER, n, Name, 0);
+  cDvbName(const char *Name, int adapter, int frontend) {
+    snprintf(buffer, sizeof(buffer), "%s%d/%s%d", DEV_DVB_ADAPTER, adapter, Name, frontend);
     }
   const char *operator*() { return buffer; }
   };
 
-static int DvbOpen(const char *Name, int n, int Mode, bool ReportError = false)
+static int DvbOpen(const char *Name, int adapter, int frontend, int Mode, bool ReportError = false)
 {
-  const char *FileName = *cDvbName(Name, n);
+  const char *FileName = *cDvbName(Name, adapter, frontend);
   int fd = open(FileName, Mode);
   if (fd < 0 && ReportError)
      LOG_ERROR_STR(FileName);
+  esyslog("DvbOpen: %s", FileName);
   return fd;
 }
 
@@ -358,24 +360,30 @@
 int cDvbDevice::devVideoOffset = -1;
 int cDvbDevice::setTransferModeForDolbyDigital = 1;
 
-cDvbDevice::cDvbDevice(int n)
+cDvbDevice::cDvbDevice(int adapter, int frontend, int force)
 {
+
+switch (force) {
+  case 0:        esyslog("SetNumFrontends force %d adapter %d frontend %d", force, adapter,frontend); SetNumFrontends(frontend); //Da usare in fase di scansione se busy
+		 break;
+  case 1:       // esyslog("SetNumFrontends force %d adapter %d frontend %d", force, adapter,frontend); SetNumFrontends(frontend); //Da usare in fase di scansione
+  case 2:        esyslog("SetCurfrontends force %d adapter %d frontend %d", force, adapter,frontend); SetCurFrontends(frontend); //Normale
+
   dvbTuner = NULL;
   frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
   spuDecoder = NULL;
   digitalAudio = false;
   playMode = pmNone;
-
   // Devices that are present on all card types:
 
-  int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
+  fd_frontend = DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK);
 
   // Devices that are only present on cards with decoders:
 
-  fd_osd      = DvbOpen(DEV_DVB_OSD,    n, O_RDWR);
-  fd_video    = DvbOpen(DEV_DVB_VIDEO,  n, O_RDWR | O_NONBLOCK);
-  fd_audio    = DvbOpen(DEV_DVB_AUDIO,  n, O_RDWR | O_NONBLOCK);
-  fd_stc      = DvbOpen(DEV_DVB_DEMUX,  n, O_RDWR);
+  fd_osd      = DvbOpen(DEV_DVB_OSD,    adapter, frontend, O_RDWR);
+  fd_video    = DvbOpen(DEV_DVB_VIDEO,  adapter, frontend, O_RDWR | O_NONBLOCK);
+  fd_audio    = DvbOpen(DEV_DVB_AUDIO,  adapter, frontend, O_RDWR | O_NONBLOCK);
+  fd_stc      = DvbOpen(DEV_DVB_DEMUX,  adapter, frontend, O_RDWR);
 
   // The DVR device (will be opened and closed as needed):
 
@@ -420,59 +428,95 @@
      dvb_frontend_info feinfo;
      if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
         frontendType = feinfo.type;
-        ciHandler = cCiHandler::CreateCiHandler(*cDvbName(DEV_DVB_CA, n));
+        ciHandler = cCiHandler::CreateCiHandler(*cDvbName(DEV_DVB_CA, adapter, frontend));
+        esyslog("cDvbDevice: CardIndex=%d", CardIndex());
         dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType, ciHandler);
         }
      else
         LOG_ERROR;
      }
   else
-     esyslog("ERROR: can't open DVB device %d", n);
+     esyslog("ERROR: can't open DVB adapter %d - frontend %d", adapter, frontend);
 
   StartSectionHandler();
+  }
+
 }
 
 cDvbDevice::~cDvbDevice()
 {
+  esyslog("~cDvbDevice()"); 
   delete spuDecoder;
   delete dvbTuner;
+  close(fd_stc);
+  close(fd_audio);
+  close(fd_video);
+  close(fd_osd);
+  close(fd_frontend);
+  Cancel(1);
   // We're not explicitly closing any device files here, since this sometimes
   // caused segfaults. Besides, the program is about to terminate anyway...
 }
 
-bool cDvbDevice::Probe(const char *FileName)
+int cDvbDevice::Probe(const char *FileName)
 {
   if (access(FileName, F_OK) == 0) {
      dsyslog("probing %s", FileName);
      int f = open(FileName, O_RDONLY);
      if (f >= 0) {
         close(f);
-        return true;
         }
      else if (errno != ENODEV && errno != EINVAL)
         LOG_ERROR_STR(FileName);
      }
   else if (errno != ENOENT)
      LOG_ERROR_STR(FileName);
-  return false;
+  return errno;
 }
 
 bool cDvbDevice::Initialize(void)
 {
   int found = 0;
-  int i;
+  int i, j, rc = 0;
   for (i = 0; i < MAXDVBDEVICES; i++) {
+    dvbDevice = NULL;
+    j = 0;
+    while (rc != ENOENT) {
       if (UseDevice(NextCardIndex())) {
-         if (Probe(*cDvbName(DEV_DVB_FRONTEND, i))) {
-            new cDvbDevice(i);
-            found++;
-            }
-         else
-            break;
+         rc = Probe(*cDvbName(DEV_DVB_FRONTEND, i ,j));
+         switch (rc) {
+	    case 0:        
+//dvbDevice[i] = 
+//            		   new cDvbDevice(i,j);
+            		   dvbDevice = new cDvbDevice(i,j,2);
+//		    	   dvbDevice[i]->SetNumFrontends(j);
+//			   dvbDevice[i]->SetCurFrontends(j);
+            		   found++;
+			   break;
+	    case EBUSY:    // we have a frontend that can't work in shared mode
+			   
+			   if (dvbDevice)
+			    dvbDevice->SetNumFrontends(j);
+//			   ForceCardIndex();
+//            		   new cDvbDevice(i,j,0);
+//			   ForceCardIndex(-1);
+			   esyslog("cDvbDevice::Initialize: WARNING %d - Device or resource busy", rc);
+			   // we have a frontend that can't work in shared mode
+			   break;
+	    case ENOENT:   esyslog("cDvbDevice::Initialize: Device %d have %d frontends", i, j);
+			   break;
+            default:       
+//dvbDevice[i] = NULL;
+			   esyslog("cDvbDevice::Initialize: %d", rc);
+			   break;
          }
+      }
       else
          NextCardIndex(1); // skips this one
-      }
+      j++;
+    }
+  }
+
   NextCardIndex(MAXDVBDEVICES - i); // skips the rest
   if (found > 0)
      isyslog("found %d video device%s", found, found > 1 ? "s" : "");
@@ -668,7 +712,9 @@
      memset(&pesFilterParams, 0, sizeof(pesFilterParams));
      if (On) {
         if (Handle->handle < 0) {
-           Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), O_RDWR | O_NONBLOCK, true);
+	   esyslog("SetPid: CardIndex=%d", CardIndex());
+//           Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDWR | O_NONBLOCK, true);
+           Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), GetCurFrontends(), O_RDWR | O_NONBLOCK, true);
            if (Handle->handle < 0) {
               LOG_ERROR;
               return false;
@@ -705,7 +751,8 @@
 
 int cDvbDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
 {
-  const char *FileName = *cDvbName(DEV_DVB_DEMUX, CardIndex());
+//  const char *FileName = *cDvbName(DEV_DVB_DEMUX, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends());
+  const char *FileName = *cDvbName(DEV_DVB_DEMUX, CardIndex(), GetCurFrontends());
   int f = open(FileName, O_RDWR | O_NONBLOCK);
   if (f >= 0) {
      dmx_sct_filter_params sctFilterParams;
@@ -798,6 +845,7 @@
      }
   if (NeedsDetachReceivers)
      *NeedsDetachReceivers = needsDetachReceivers;
+
   return result;
 }
 
@@ -834,8 +882,6 @@
   if (TurnOffLivePIDs)
      TurnOffLiveMode(LiveView);
 
-  // Set the tuner:
-
   dvbTuner->Set(Channel, DoTune);
 
   // If this channel switch was requested by the EITScanner we don't wait for
@@ -954,8 +1000,10 @@
 {
   if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) {
      // reopen the devices
-     fd_video = DvbOpen(DEV_DVB_VIDEO,  CardIndex(), O_RDWR | O_NONBLOCK);
-     fd_audio = DvbOpen(DEV_DVB_AUDIO,  CardIndex(), O_RDWR | O_NONBLOCK);
+//     fd_video = DvbOpen(DEV_DVB_VIDEO,  CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDWR | O_NONBLOCK);
+//     fd_audio = DvbOpen(DEV_DVB_AUDIO,  CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDWR | O_NONBLOCK);
+     fd_video = DvbOpen(DEV_DVB_VIDEO,  CardIndex(), GetCurFrontends(), O_RDWR | O_NONBLOCK);
+     fd_audio = DvbOpen(DEV_DVB_AUDIO,  CardIndex(), GetCurFrontends(), O_RDWR | O_NONBLOCK);
      SetVideoFormat(Setup.VideoFormat);
      }
 
@@ -1183,7 +1231,8 @@
 bool cDvbDevice::OpenDvr(void)
 {
   CloseDvr();
-  fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), O_RDONLY | O_NONBLOCK, true);
+//  fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), dvbDevice[CardIndex()]->GetCurFrontends(), O_RDONLY | O_NONBLOCK, true);
+  fd_dvr = DvbOpen(DEV_DVB_DVR, CardIndex(), GetCurFrontends(), O_RDONLY | O_NONBLOCK, true);
   if (fd_dvr >= 0)
      tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(2), CardIndex() + 1);
   return fd_dvr >= 0;
diff -u -N -r vdr_1.4.5_orig/dvbdevice.h vdr_1.4.5_eddi_v2/dvbdevice.h
--- vdr_1.4.5_orig/dvbdevice.h	2006-05-28 17:05:19.000000000 +0200
+++ vdr_1.4.5_eddi_v2/dvbdevice.h	2007-02-09 23:10:44.000000000 +0100
@@ -20,6 +20,7 @@
 #endif
 
 #define MAXDVBDEVICES  4
+//#define MAXDVBFRONTENDS  4
 
 class cDvbTuner;
 
@@ -27,7 +28,7 @@
 
 class cDvbDevice : public cDevice {
 private:
-  static bool Probe(const char *FileName);
+  static int Probe(const char *FileName);
          ///< Probes for existing DVB devices.
 public:
   static bool Initialize(void);
@@ -36,11 +37,11 @@
          ///< \return True if any devices are available.
 private:
   fe_type_t frontendType;
-  int fd_osd, fd_audio, fd_video, fd_dvr, fd_stc;
+  int fd_frontend, fd_osd, fd_audio, fd_video, fd_dvr, fd_stc;
 protected:
   virtual void MakePrimaryDevice(bool On);
 public:
-  cDvbDevice(int n);
+  cDvbDevice(int adapter, int frontend, int force);
   virtual ~cDvbDevice();
   virtual bool Ready(void);
   virtual int ProvidesCa(const cChannel *Channel) const;
