diff -u -r vdr-1.4.3-orig/config.c vdr-1.4.3-lnbsharing/config.c
--- vdr-1.4.3-orig/config.c	2006-07-22 13:57:51.000000000 +0200
+++ vdr-1.4.3-lnbsharing/config.c	2006-10-23 20:42:12.000000000 +0200
@@ -275,6 +275,12 @@
   CurrentDolby = 0;
   InitialChannel = 0;
   InitialVolume = -1;
+
+//ML
+  VerboseLNBlog = 0;
+  for (int i = 0; i < MAXDEVICES; i++) CardUsesLNBnr[i] = i + 1;
+//ML-Ende
+ 
 }
 
 cSetup& cSetup::operator= (const cSetup &s)
@@ -437,7 +443,23 @@
   else if (!strcasecmp(Name, "InitialChannel"))      InitialChannel     = atoi(Value);
   else if (!strcasecmp(Name, "InitialVolume"))       InitialVolume      = atoi(Value);
   else
-     return false;
+
+//ML
+  if (!strcasecmp(Name, "VerboseLNBlog")) VerboseLNBlog = atoi(Value);
+  else {
+    char tmp[20];
+    bool result = false;
+    for (int i = 1; i <= MAXDEVICES; i++) {
+      sprintf(tmp, "Card%dusesLNBnr", i);
+      if (!strcasecmp(Name, tmp)) {
+        CardUsesLNBnr[i - 1] = atoi(Value);
+        result = true;
+      }
+    }  
+     return result;
+  }
+//ML-Ende
+
   return true;
 }
 
@@ -505,6 +527,17 @@
   Store("InitialChannel",     InitialChannel);
   Store("InitialVolume",      InitialVolume);
 
+//ML
+  Store("VerboseLNBlog",       VerboseLNBlog);
+  char tmp[20];
+  if (cDevice::NumDevices() > 1) {
+     for (int i = 1; i <= cDevice::NumDevices(); i++) {
+        sprintf(tmp, "Card%dusesLNBnr", i);
+        Store(tmp, CardUsesLNBnr[i - 1]);
+     }
+  }
+//ML-Ende
+
   Sort();
 
   if (cConfig<cSetupLine>::Save()) {
diff -u -r vdr-1.4.3-orig/config.h vdr-1.4.3-lnbsharing/config.h
--- vdr-1.4.3-orig/config.h	2006-09-23 15:56:08.000000000 +0200
+++ vdr-1.4.3-lnbsharing/config.h	2006-10-23 20:42:12.000000000 +0200
@@ -252,6 +252,15 @@
   int CurrentDolby;
   int InitialChannel;
   int InitialVolume;
+
+//ML
+  int VerboseLNBlog;
+  #define MAXDEVICES 16 // Since VDR 1.3.32 we can not #include "device.h" for MAXDEVICES anymore. 
+                        // With this workaround a warning will be shown during compilation if 
+                        // MAXDEVICES changes in device.h.
+  int CardUsesLNBnr[MAXDEVICES];
+//ML-Ende
+
   int __EndData__;
   cSetup(void);
   cSetup& operator= (const cSetup &s);
diff -u -r vdr-1.4.3-orig/device.c vdr-1.4.3-lnbsharing/device.c
--- vdr-1.4.3-orig/device.c	2006-09-03 12:13:25.000000000 +0200
+++ vdr-1.4.3-lnbsharing/device.c	2006-10-23 20:48:50.000000000 +0200
@@ -19,6 +19,10 @@
 #include "status.h"
 #include "transfer.h"
 
+//ML
+#include "diseqc.h"
+//ML-Ende
+
 // --- cPesAssembler ---------------------------------------------------------
 
 class cPesAssembler {
@@ -155,6 +159,12 @@
 
   SetVideoFormat(Setup.VideoFormat);
 
+//ML
+  LNBstate = -1;
+  LNBnr = Setup.CardUsesLNBnr[cardIndex];
+  LNBsource = NULL;
+//ML-Ende
+
   mute = false;
   volume = Setup.CurrentVolume;
 
@@ -214,6 +224,16 @@
      useDevice |= (1 << n);
 }
 
+//ML
+void cDevice::SetLNBnr(void)
+{
+  for (int i = 0; i < numDevices; i++) {
+    device[i]->LNBnr = Setup.CardUsesLNBnr[i];
+    isyslog("LNB-sharing: setting device %d to use LNB %d", i, device[i]->LNBnr);
+  }
+}
+//ML-Ende
+
 int cDevice::NextCardIndex(int n)
 {
   if (n > 0) {
@@ -273,6 +293,98 @@
   return d;
 }
 
+//ML
+cDevice *cDevice::GetBadDevice(const cChannel *Channel)
+{
+  if(!cSource::IsSat(Channel->Source())) return NULL;
+  if (Setup.DiSEqC) {
+    cDiseqc *diseqc;
+    diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
+
+    for (int i = 0; i < numDevices; i++) {
+      if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBsource() != (int*) diseqc) {
+        if (Setup.VerboseLNBlog) {
+          isyslog("LNB %d: Device check for channel %d on device %d. LNB or DiSEq conflict with device %d", LNBnr, Channel->Number(), this->DeviceNumber(), i);
+        }
+        return device[i];
+      }
+    }
+    if (Setup.VerboseLNBlog) { 
+      isyslog("LNB %d: Device check for for channel %d on device %d. OK", LNBnr, Channel->Number(), this->DeviceNumber());
+    }
+  } else {
+    char requiredState;
+    if (Channel->Frequency() >= Setup.LnbSLOF) {
+      requiredState = 1 ;
+    } else {
+      requiredState = 0;
+    }
+    if (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') requiredState += 2;
+
+    for (int i = 0; i < numDevices; i++) {
+      if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBconf() != requiredState) {
+        if (Setup.VerboseLNBlog) {
+          isyslog("LNB %d: Device check for channel %d, LNBstate %d on device %d, current LNBstate %d. Conflict with device %d, LNBstate %d", LNBnr, Channel->Number(), requiredState, this->DeviceNumber(), LNBstate, i, device[i]->GetLNBconf());
+        }
+        return device[i];
+      }
+    }
+    if (Setup.VerboseLNBlog) { 
+      isyslog("LNB %d: Device check for channel %d, LNBstate %d on device %d, current LNBstate %d. No other devices affected", LNBnr, Channel->Number(), requiredState, this->DeviceNumber(), LNBstate);
+    }
+  }
+  return NULL;
+}
+
+int cDevice::GetMaxBadPriority(const cChannel *Channel)
+{                                
+  if(!cSource::IsSat(Channel->Source())) return -2;
+  bool PrimaryIsBad = false;
+  int maxBadPriority = -2;
+  if (Setup.DiSEqC) {
+    cDiseqc *diseqc;
+    diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
+
+    for (int i = 0; i < numDevices; i++) {
+      if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBsource() != (int*) diseqc) {
+        if (device[i]->Receiving() && device[i]->Priority() > maxBadPriority) {
+          maxBadPriority = device[i]->Priority();
+        }
+        if (device[i]->IsPrimaryDevice()) {
+            PrimaryIsBad = true;
+        }
+      }
+    }
+  } else {
+    char requiredState;
+    if (Channel->Frequency() >= Setup.LnbSLOF) {
+      requiredState = 1 ;
+    } else {
+      requiredState = 0;
+    }
+    if (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') requiredState += 2;
+
+    for (int i = 0; i < numDevices; i++) {
+      if (this != device[i] && device[i]->GetLNBnr() == LNBnr && device[i]->GetLNBconf() != requiredState) {
+        if (device[i]->Receiving() && device[i]->Priority() > maxBadPriority) {
+          maxBadPriority = device[i]->Priority();
+        }
+        if (device[i]->IsPrimaryDevice()) {
+            PrimaryIsBad = true;
+        }
+      }
+    }
+  }
+  if (PrimaryIsBad && maxBadPriority == -2) {
+    maxBadPriority = -1;
+  }
+  if (Setup.VerboseLNBlog) { 
+    isyslog("LNB %d: Request for channel %d on device %d. MaxBadPriority is %d", LNBnr, Channel->Number(), this->DeviceNumber(), maxBadPriority);
+  }
+  return maxBadPriority;
+}
+//ML-Ende
+
 cDevice *cDevice::GetDevice(int Index)
 {
   return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
@@ -282,7 +394,13 @@
 {
   cDevice *d = NULL;
   uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
-  for (int i = 0; i < numDevices; i++) {
+
+//ML
+  int badPriority;
+  uint imp2;
+//ML-Ende
+
+ for (int i = 0; i < numDevices; i++) {
       bool ndr;
       if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
          // Put together an integer number that reflects the "impact" using
@@ -299,7 +417,30 @@
          imp <<= 8; imp |= min(max(device[i]->ProvidesCa(Channel), 0), 0xFF);      // use the device that provides the lowest number of conditional access methods
          imp <<= 1; imp |= device[i]->IsPrimaryDevice();                           // avoid the primary device
          imp <<= 1; imp |= device[i]->HasDecoder();                                // avoid full featured cards
-         if (imp < Impact) {
+
+//ML
+         badPriority = device[i]->GetMaxBadPriority(Channel);
+         if (badPriority >= Priority || (badPriority == -1 && Priority < Setup.PrimaryLimit)) {
+            // channel is not available for the requested prioity
+            imp = 0xFFFFFFFF;
+         } else {
+            switch (badPriority) {
+               case -2: // not affected by LNB-sharing
+                  imp2 = 0;
+                  break;
+               case -1: // the primary device would need a channel switch
+				  imp += 1 <<  17;
+                  imp2 = 0xFFFFFFFF | 1 << 17;
+                  break;
+               default: // a device receiving with lower priority would need to be stopped
+                  imp += badPriority << 8;
+                  imp2 = 0xFFFFFFFF | badPriority << 8;
+                  break;
+            }
+         }
+         if (imp < Impact && imp2 < Impact) {
+//ML-Ende
+
             // This device has less impact than any previous one, so we take it.
             Impact = imp;
             d = device[i];
@@ -534,7 +675,11 @@
 bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const
 {
   for (int i = 0; i < numDevices; i++) {
-      if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
+
+//ML
+      if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel) && device[i]->GetLNBnr() != LNBnr)
+//ML-Ende
+
          return false;
       }
   return true;
@@ -557,6 +702,26 @@
 
 bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
 {
+
+//ML
+  cDevice *tmpDevice;
+	if (this->GetMaxBadPriority(Channel) >= 0) {
+		Skins.Message(mtInfo, tr("Channel locked by LNB!"));
+		return false;
+	}
+	while ((tmpDevice = GetBadDevice(Channel)) != NULL) {
+		if (tmpDevice->IsPrimaryDevice() && LiveView)
+			tmpDevice->SwitchChannelForced(Channel, true);
+		else
+			tmpDevice->SwitchChannelForced(Channel, false);
+   	}
+    return SwitchChannelForced(Channel, LiveView);
+}
+
+bool cDevice::SwitchChannelForced(const cChannel *Channel, bool LiveView)
+//ML-Ende
+
+{
   if (LiveView)
      isyslog("switching to channel %d", Channel->Number());
   for (int i = 3; i--;) {
@@ -582,11 +747,15 @@
      int first = n;
      cChannel *channel;
      while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
-           // try only channels which are currently available
-           if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, 0))
+	// try only channels which are currently available
+
+//ML
+	    if (PrimaryDevice()->GetMaxBadPriority(channel) < 0 && (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, 0)))       
+//ML-Ende
+
               break;
-           n = channel->Number() + Direction;
-           }
+	n = channel->Number() + Direction;
+     }
      if (channel) {
         int d = n - first;
         if (abs(d) == 1)
@@ -618,12 +787,40 @@
 
   eSetChannelResult Result = scrOk;
 
+//ML
+  char requiredState;
+  if (Channel->Frequency() >= Setup.LnbSLOF) {
+    requiredState = 1;
+  } else {
+    requiredState = 0;
+  }
+  if (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') requiredState += 2;
+  if (Setup.VerboseLNBlog) {
+    isyslog("LNB %d: Switching device %d to channel %d", LNBnr, this->DeviceNumber(), Channel->Number());
+  }
+//ML-Ende
+
   // 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:
 
   if (NeedsTransferMode) {
      cDevice *CaDevice = GetDevice(Channel, 0, &NeedsDetachReceivers);
      if (CaDevice && CanReplay()) {
+
+//ML
+       if (CaDevice->GetLNBnr() == LNBnr) {
+         if (LNBstate != requiredState || (Setup.DiSEqC && LNBsource != (int*) Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization())) ) {
+           if (IsPrimaryDevice()) {
+             SetChannelDevice(Channel, true);
+           } else {
+             SetChannelDevice(Channel, false);
+           }
+         LNBstate = requiredState;
+         LNBsource = (int*) Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
+         }
+       }
+//ML-Ende
+
         cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
         if (CaDevice->SetChannel(Channel, false) == scrOk) { // calling SetChannel() directly, not SwitchChannel()!
            if (NeedsDetachReceivers)
@@ -644,6 +841,12 @@
         sectionHandler->SetStatus(false);
         sectionHandler->SetChannel(NULL);
         }
+
+//ML
+     LNBstate = requiredState;
+     LNBsource = (int*) Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
+//ML-Ende
+
      // Tell the ciHandler about the channel switch and add all PIDs of this
      // channel to it, for possible later decryption:
      if (ciHandler) {
diff -u -r vdr-1.4.3-orig/device.h vdr-1.4.3-lnbsharing/device.h
--- vdr-1.4.3-orig/device.h	2006-06-15 11:32:48.000000000 +0200
+++ vdr-1.4.3-lnbsharing/device.h	2006-10-23 20:42:12.000000000 +0200
@@ -134,6 +134,33 @@
          ///< live viewing.
          ///< See ProvidesChannel() for more information on how
          ///< priorities are handled, and the meaning of NeedsDetachReceivers.
+
+//ML
+private:
+  char LNBstate;  // Current frequency band and polarization of the DVB-tuner
+//  cDiseqc *LNBsource;  // can not #include "diseqc.h". A workaround follows:
+  int *LNBsource;  // [DiSEqC] DiSEqC-Source
+  int LNBnr;      // Number of LNB used
+public:
+  char GetLNBconf(void) { return LNBstate; }
+  int *GetLNBsource(void) { return LNBsource; }
+  int GetLNBnr(void) { return LNBnr; }
+  static void SetLNBnr(void);
+  cDevice *GetBadDevice(const cChannel *Channel);
+         ///< Returns NULL if there is no device which uses the same LNB or if
+         ///< all of those devices are tuned to the same frequency band and 
+         ///< polarization as of the requested channel.
+         ///< Otherwise returns the first device found.
+  int GetMaxBadPriority(const cChannel *Channel);
+         ///< Returns the highest priority of all receiving devices which use
+         ///< the same LNB and are tuned to a different frequency band or 
+         ///< polarization as of the requested channel.
+         ///< Returns -1 if there are no such devices, but the primary device 
+         ///< would be affected by switching to the requested channel.
+         ///< Returns -2 if there are no such devices and the primary device 
+         ///< would not be affected by switching to the requested channel.
+//ML-Ende
+
   static void Shutdown(void);
          ///< Closes down all devices.
          ///< Must be called at the end of the program.
@@ -227,6 +254,13 @@
   bool SwitchChannel(const cChannel *Channel, bool LiveView);
          ///< Switches the device to the given Channel, initiating transfer mode
          ///< if necessary.
+
+//ML
+  bool SwitchChannelForced(const cChannel *Channel, bool LiveView);
+         ///< Switches the device to the given channel, initiating transfer mode
+         ///< if necessary. Forces the switch without taking care of the LNB configuration.
+//ML-Ende
+
   static bool SwitchChannel(int Direction);
          ///< Switches the primary device to the next available channel in the given
          ///< Direction (only the sign of Direction is evaluated, positive values
diff -u -r vdr-1.4.3-orig/eitscan.c vdr-1.4.3-lnbsharing/eitscan.c
--- vdr-1.4.3-orig/eitscan.c	2006-01-07 15:10:17.000000000 +0100
+++ vdr-1.4.3-lnbsharing/eitscan.c	2006-10-23 20:42:12.000000000 +0200
@@ -151,9 +151,11 @@
                             if (Device->ProvidesTransponder(Channel)) {
                                if (!Device->Receiving()) {
                                   bool MaySwitchTransponder = Device->MaySwitchTransponder();
-                                  if (MaySwitchTransponder || Device->ProvidesTransponderExclusively(Channel) && now - lastActivity > Setup.EPGScanTimeout * 3600) {
+//ML
+                                  if (MaySwitchTransponder && Device->GetMaxBadPriority(Channel) == -2 || Device->ProvidesTransponderExclusively(Channel) && Device->GetMaxBadPriority(Channel) <= -1 && now - lastActivity > Setup.EPGScanTimeout * 3600) {
                                      if (!MaySwitchTransponder) {
-                                        if (Device == cDevice::ActualDevice() && !currentChannel) {
+                                        if ((Device == cDevice::ActualDevice() || Device->GetMaxBadPriority(Channel) == -1) && !currentChannel) {
+//ML-Ende
                                            cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
                                            currentChannel = Device->CurrentChannel();
                                            Skins.Message(mtInfo, tr("Starting EPG scan"));
diff -u -r vdr-1.4.3-orig/i18n.c vdr-1.4.3-lnbsharing/i18n.c
--- vdr-1.4.3-orig/i18n.c	2006-09-16 11:08:30.000000000 +0200
+++ vdr-1.4.3-lnbsharing/i18n.c	2006-10-23 20:42:13.000000000 +0200
@@ -6126,6 +6126,76 @@
     "Ingen titel",
     "Bez názvu",
   },
+
+//ML
+  { "Channel locked by LNB!",
+    "Kanal durch LNB gesperrt!",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "Chaîne interdite par la LNB",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+  },
+  { "Setup.LNB$DVB device %d uses LNB No.",
+    "DVB-Empfänger %d nutzt LNB Nr.",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "La carte DVB %d utilise la LNB No.",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+  },
+  { "Setup.LNB$Log LNB usage",
+    "LNB-Nutzung protokollieren",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+  },
+//ML
+
   { NULL }
   };
 
diff -u -r vdr-1.4.3-orig/menu.c vdr-1.4.3-lnbsharing/menu.c
--- vdr-1.4.3-orig/menu.c	2006-07-23 11:23:11.000000000 +0200
+++ vdr-1.4.3-lnbsharing/menu.c	2006-10-23 20:42:13.000000000 +0200
@@ -2433,6 +2433,23 @@
 
   Clear();
 
+//ML
+  int numSatDevices = 0;
+  for (int i = 0; i < cDevice::NumDevices(); i++) {
+     	if (cDevice::GetDevice(i)->ProvidesSource(cSource::stSat)) numSatDevices++;
+  }     		
+  if (numSatDevices > 1) {
+  	 char tmp[30];
+     for (int i = 1; i <= cDevice::NumDevices(); i++) {
+     	if (cDevice::GetDevice(i - 1)->ProvidesSource(cSource::stSat)) {
+        	sprintf( tmp, tr("Setup.LNB$DVB device %d uses LNB No."), i);
+        	Add(new cMenuEditIntItem( tmp, &data.CardUsesLNBnr[i - 1], 1, numSatDevices ));
+        }
+     }
+   }
+  Add(new cMenuEditBoolItem(tr("Setup.LNB$Log LNB usage"), &data.VerboseLNBlog));
+//ML-Ende
+
   Add(new cMenuEditBoolItem(tr("Setup.LNB$Use DiSEqC"),               &data.DiSEqC));
   if (!data.DiSEqC) {
      Add(new cMenuEditIntItem( tr("Setup.LNB$SLOF (MHz)"),               &data.LnbSLOF));
@@ -2449,6 +2466,10 @@
   int oldDiSEqC = data.DiSEqC;
   eOSState state = cMenuSetupBase::ProcessKey(Key);
 
+//ML
+  if (Key == kOk) cDevice::SetLNBnr();
+//ML-Ende
+
   if (Key != kNone && data.DiSEqC != oldDiSEqC)
      Setup();
   return state;
@@ -3126,7 +3147,10 @@
   if (Direction) {
      while (Channel) {
            Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel);
-           if (Channel && !Channel->GroupSep() && (cDevice::PrimaryDevice()->ProvidesChannel(Channel, Setup.PrimaryLimit) || cDevice::GetDevice(Channel, 0)))
+
+//ML
+           if (Channel && !Channel->GroupSep() && ((cDevice::PrimaryDevice()->ProvidesChannel(Channel, Setup.PrimaryLimit) && cDevice::PrimaryDevice()->GetMaxBadPriority(Channel) < 0) || cDevice::GetDevice(Channel, 0) ) )
+//ML-Ende
               return Channel;
            }
      }
@@ -3649,6 +3673,21 @@
      int Priority = Timer ? Timer->Priority() : Pause ? Setup.PausePriority : Setup.DefaultPriority;
      cDevice *device = cDevice::GetDevice(channel, Priority, &NeedsDetachReceivers);
      if (device) {
+
+//ML
+       cDevice *tmpDevice;
+       while ((tmpDevice = device->GetBadDevice(channel))) {
+         if (tmpDevice->Replaying() == false) {
+           Stop(tmpDevice);
+           if (tmpDevice->IsPrimaryDevice() )
+             tmpDevice->SwitchChannelForced(channel, true);
+           else
+             tmpDevice->SwitchChannelForced(channel, false);
+         } else
+		 tmpDevice->SwitchChannelForced(channel, false);
+	   }
+//ML-Ende
+
         if (NeedsDetachReceivers) {
            Stop(device);
            if (device == cTransferControl::ReceiverDevice())
