diff --git a/PLUGINS/src/skincurses/skincurses.c b/PLUGINS/src/skincurses/skincurses.c
index 4abb863..65249df 100644
--- a/PLUGINS/src/skincurses/skincurses.c
+++ b/PLUGINS/src/skincurses/skincurses.c
@@ -194,7 +194,7 @@ private:
 public:
   cSkinCursesDisplayChannel(bool WithInfo);
   virtual ~cSkinCursesDisplayChannel();
-  virtual void SetChannel(const cChannel *Channel, int Number);
+  virtual void SetChannel(cChannelConfig channelConfig, int Number);
   virtual void SetEvents(const cEvent *Present, const cEvent *Following);
   virtual void SetMessage(eMessageType Type, const char *Text);
   virtual void Flush(void);
@@ -214,10 +214,10 @@ cSkinCursesDisplayChannel::~cSkinCursesDisplayChannel()
   delete osd;
 }
 
-void cSkinCursesDisplayChannel::SetChannel(const cChannel *Channel, int Number)
+void cSkinCursesDisplayChannel::SetChannel(cChannelConfig channelConfig, int Number)
 {
   osd->DrawRectangle(0, 0, ScOsdWidth - 1, 0, clrBackground);
-  osd->DrawText(0, 0, ChannelString(Channel, Number), clrWhite, clrBackground, &Font);
+  osd->DrawText(0, 0, ChannelString(channelConfig, Number), clrWhite, clrBackground, &Font);
 }
 
 void cSkinCursesDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
diff --git a/channels.c b/channels.c
index ebc7eb1..74695d1 100644
--- a/channels.c
+++ b/channels.c
@@ -13,6 +13,7 @@
 #include "epg.h"
 #include "libsi/si.h"
 #include "timers.h"
+#include "sources.h"
 
 // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
 // format characters in order to allow any number of blanks after a numeric
@@ -697,6 +698,12 @@ bool cChannel::Save(FILE *f)
   return fprintf(f, "%s", *ToText()) > 0;
 }
 
+bool cChannel::IsAtsc(void) const { return cSource::IsAtsc(source); }
+bool cChannel::IsCable(void) const { return cSource::IsCable(source); }
+bool cChannel::IsSat(void) const { return cSource::IsSat(source); }
+bool cChannel::IsTerr(void) const { return cSource::IsTerr(source); }
+bool cChannel::IsSourceType(char Source) const { return cSource::IsType(source, Source); }
+
 // --- cChannelSorter --------------------------------------------------------
 
 class cChannelSorter : public cListObject {
@@ -924,14 +931,20 @@ cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, c
   return NULL;
 }
 
-cString ChannelString(const cChannel *Channel, int Number)
+cString ChannelString(cChannelConfig cc, int Number)
 {
   char buffer[256];
-  if (Channel) {
-     if (Channel->GroupSep())
-        snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
-     else
-        snprintf(buffer, sizeof(buffer), "%d%s  %s", Channel->Number(), Number ? "-" : "", Channel->Name());
+  const cChannel *selected = Channels.Get(cc.selected()-1);
+  const cChannel *receiving = Channels.Get(cc.receiving()-1);
+  if (selected) {
+     if (selected->GroupSep())
+        snprintf(buffer, sizeof(buffer), "%s", selected->Name());
+     else {
+        if (selected == receiving || receiving == NULL)
+           snprintf(buffer, sizeof(buffer), "%d%s  %s", selected->Number(), Number ? "-" : "", selected->Name());
+        else
+           snprintf(buffer, sizeof(buffer), "%d(%d)%s  %s", selected->Number(), receiving->Number(), Number ? "-" : "", selected->Name());
+        }
      }
   else if (Number)
      snprintf(buffer, sizeof(buffer), "%d-", Number);
diff --git a/channels.h b/channels.h
index b867297..4a0ef83 100644
--- a/channels.h
+++ b/channels.h
@@ -10,10 +10,9 @@
 #ifndef __CHANNELS_H
 #define __CHANNELS_H
 
-#include "config.h"
-#include "sources.h"
 #include "thread.h"
 #include "tools.h"
+#include "config.h"
 
 #define ISTRANSPONDER(f1, f2)  (abs((f1) - (f2)) < 4) //XXX
 
@@ -176,11 +175,11 @@ public:
   const char *Parameters(void) const { return parameters; }
   const cLinkChannels* LinkChannels(void) const { return linkChannels; }
   const cChannel *RefChannel(void) const { return refChannel; }
-  bool IsAtsc(void) const { return cSource::IsAtsc(source); }
-  bool IsCable(void) const { return cSource::IsCable(source); }
-  bool IsSat(void) const { return cSource::IsSat(source); }
-  bool IsTerr(void) const { return cSource::IsTerr(source); }
-  bool IsSourceType(char Source) const { return cSource::IsType(source, Source); }
+  bool IsAtsc(void) const;
+  bool IsCable(void) const;
+  bool IsSat(void) const;
+  bool IsTerr(void) const;
+  bool IsSourceType(char Source) const;
   tChannelID GetChannelID(void) const { return tChannelID(source, nid, (nid || tid) ? tid : Transponder(), sid, rid); }
   bool HasTimer(void) const;
   int Modification(int Mask = CHANNELMOD_ALL);
@@ -234,6 +233,18 @@ public:
 
 extern cChannels Channels;
 
-cString ChannelString(const cChannel *Channel, int Number);
+class cChannelConfig {
+private:
+   const int selectedChannel;
+   const int receivingChannel;
+public:
+   cChannelConfig(
+         int selectedChannel, int receivingChannel) :
+         selectedChannel(selectedChannel), receivingChannel(receivingChannel) { }
+   int selected() {return selectedChannel;}
+   int receiving() {return receivingChannel;}
+};
+
+cString ChannelString(cChannelConfig cc, int Number);
 
 #endif //__CHANNELS_H
diff --git a/config.c b/config.c
index 73b11b1..aa8761a 100644
--- a/config.c
+++ b/config.c
@@ -15,6 +15,7 @@
 #include "interface.h"
 #include "plugin.h"
 #include "recording.h"
+#include "sources.h"
 
 // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
 // format characters in order to allow any number of blanks after a numeric
@@ -304,6 +305,228 @@ bool cSetupLine::Save(FILE *f)
   return fprintf(f, "%s%s%s = %s\n", plugin ? plugin : "", plugin ? "." : "", name, value) > 0;
 }
 
+// -- Class cAlternative ------------------------------------------------------------
+
+cAlternative::cAlternative(const cChannel *master) : master(master), alternativeChannels() {
+}
+
+void cAlternative::AddAlternativeChannel(const cChannel *Alternative) {
+   if (Alternative == master) return; // master cannot be an alternative
+   cAlternativeContainer *next = alternativeChannels.First();
+   while(next) {
+      if (next->channel == Alternative) return; // Already in list
+      if (Alternative->Number() < next->channel->Number()) {
+         alternativeChannels.Ins(new cAlternativeContainer(Alternative), next);
+         return;
+         }
+      next = alternativeChannels.Next(next);
+   }
+   alternativeChannels.Add(new cAlternativeContainer(Alternative));
+}
+
+void cAlternative::RemoveAlternativeChannel(const cChannel *Alternative) {
+   cAlternativeContainer *next = alternativeChannels.First();
+   while(next) {
+      if (next->channel == Alternative) {
+         alternativeChannels.Del(next, true);
+         return;
+         }
+      next = alternativeChannels.Next(next);
+      }
+}
+
+cList<cAlternativeContainer>& cAlternative::GetAlternativeChannels() {
+
+   return alternativeChannels;
+}
+
+bool cAlternative::operator<(const cAlternative& Other) {
+   if (master->Number() < Other.master->Number())
+      return -1;
+   if (master->Number() > Other.master->Number())
+      return 1;
+   return 0;
+}
+
+const cChannel *cAlternative::GetMaster() {
+   return master;
+}
+
+cAlternative::cAlternative(cAlternative *AlternativeToCopy) {
+   master = AlternativeToCopy->master;
+   alternativeChannels.Clear();
+   cAlternativeContainer *next = AlternativeToCopy->alternativeChannels.First();
+   while(next) {
+      alternativeChannels.Add(new cAlternativeContainer(next->channel));
+      next = AlternativeToCopy->alternativeChannels.Next(next);
+      }
+}
+
+cAlternative& cAlternative::operator= (const cAlternative &Other) {
+   master = Other.master;
+   alternativeChannels.Clear();
+   cAlternativeContainer *next = Other.alternativeChannels.First();
+   while(next) {
+      alternativeChannels.Add(new cAlternativeContainer(next->channel));
+      next = Other.alternativeChannels.Next(next);
+      }
+   return *this;
+}
+
+bool cAlternative::operator==(const cAlternative &Other) {
+   if (master != Other.master) return false;
+   cAlternativeContainer *thisNext = alternativeChannels.First();
+   cAlternativeContainer *otherNext = Other.alternativeChannels.First();
+   while(thisNext != NULL && otherNext != NULL) {
+      if (thisNext == NULL || otherNext == NULL) return false;
+      if (thisNext->channel != otherNext->channel) return false;
+      thisNext = alternativeChannels.Next(thisNext);
+      otherNext = Other.alternativeChannels.Next(otherNext);
+      }
+   return true;
+}
+
+
+cAlternative::~cAlternative() {
+}
+
+void cAlternative::Del(const cChannel *Channel) {
+   for(cAlternativeContainer * next = alternativeChannels.First() ; next ; next = alternativeChannels.Next(next)) {
+      if (next->channel == Channel) {
+         alternativeChannels.Del(next);
+         return;
+      }
+   }
+}
+
+
+////////////////////////////////////////////////////
+// Class: cAllAlternatives
+
+cAlternative *cAllAlternatives::FindAlternative(const cChannel *Master) {
+   Init();
+   for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+      if (next->GetMaster() == Master) {
+         return next;
+      }
+   }
+   return NULL;
+}
+
+void cAllAlternatives::CreateAlternative(const cChannel *Master) {
+   Init();
+   if (FindAlternative(Master) == NULL) {
+      cAlternative *ptr = new cAlternative(Master);
+      for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+         if (Master->Number() < next->GetMaster()->Number()) {
+            alternatives.Ins(ptr, next);
+            ptr = NULL;
+            break;
+            }
+         }
+      if (ptr) alternatives.Add(ptr);
+      }
+}
+
+void cAllAlternatives::RemoveAlternative(cAlternative* AlternativeToRemove) {
+   Init();
+   for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+      if (next == AlternativeToRemove) {
+         alternatives.Del(next, true /*delete*/);
+         return;
+      }
+   }
+}
+
+int cAllAlternatives::CountAlternatives() {
+   Init();
+   return alternatives.Count();
+}
+
+
+cAllAlternatives::~cAllAlternatives() {
+   alternatives.Clear();
+   masterToAlternative.Clear();
+}
+
+cAlternative *cAllAlternatives::GetAlternative(int Index) {
+   Init();
+   cAlternative *next = alternatives.First();
+   while(Index > 0 || next == NULL) {
+      next = alternatives.Next(next);
+      Index--;
+   }
+   return next;
+}
+
+void cAllAlternatives::AddAlternative(const cChannel *Master, const cChannel *AlternativeToAdd) {
+   Init();
+   cAlternative *alt = FindAlternative(Master);
+   if (alt == NULL) {
+      CreateAlternative(Master);
+      alt = FindAlternative(Master);
+   }
+   alt->AddAlternativeChannel(AlternativeToAdd);
+}
+
+void cAllAlternatives::LoadAlternative(int MasterNr, int AlternativeNr) {
+   masterToAlternative.Ins(new cIntPair(MasterNr, AlternativeNr));
+}
+
+void cAllAlternatives::Init() {
+  if (!init) {
+     init = true;
+     for(cIntPair *next = masterToAlternative.First() ; next ; next = masterToAlternative.Next(next)) {
+        const cChannel *master = Channels.Get(next->int1-1);
+        const cChannel *alternative = Channels.Get(next->int2-1);
+        if (master == NULL) continue;
+        if (alternative == NULL) continue;
+        AddAlternative(master, alternative);
+        }
+    }
+}
+
+cAllAlternatives& cAllAlternatives::operator= (const cAllAlternatives &Other) {
+   init = Other.init;
+   masterToAlternative.Clear();
+   for(cIntPair *next = Other.masterToAlternative.First() ; next ; next = Other.masterToAlternative.Next(next)) {
+      masterToAlternative.Add(new cIntPair(*next));
+      }
+   alternatives.Clear();
+   for(cAlternative *next = Other.alternatives.First() ; next ; next = Other.alternatives.Next(next)) {
+      alternatives.Add(new cAlternative(next));
+      }
+   return *this;
+}
+
+bool cAllAlternatives::operator==(cAllAlternatives &Other) {
+   Init();
+   Other.Init();
+   cAlternative *thisNext = alternatives.First();
+   cAlternative *otherNext = Other.alternatives.First();
+   while(thisNext != NULL && otherNext != NULL) {
+      if (thisNext == NULL || otherNext == NULL) return false;
+      if (*thisNext != *otherNext) return false;
+      thisNext = alternatives.Next(thisNext);
+      otherNext = Other.alternatives.Next(otherNext);
+      }
+   return true;
+}
+
+
+void cAllAlternatives::Del(const cChannel *Channel) {
+   for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+      if (next->GetMaster() == Channel) {
+         alternatives.Del(next);
+         break;
+         }
+      }
+   for(cAlternative *next = alternatives.First() ; next ; next = alternatives.Next(next)) {
+      next->Del(Channel);
+      }
+}
+
+
 // --- cSetup ----------------------------------------------------------------
 
 cSetup Setup;
@@ -404,6 +627,7 @@ cSetup::cSetup(void)
 cSetup& cSetup::operator= (const cSetup &s)
 {
   memcpy(&__BeginData__, &s.__BeginData__, (char *)&s.__EndData__ - (char *)&s.__BeginData__);
+  Alternatives = s.Alternatives;
   return *this;
 }
 
@@ -423,7 +647,7 @@ void cSetup::Store(const char *Name, const char *Value, const char *Plugin, bool
   if (Name && *Name) {
      cSetupLine *l = Get(Name, Plugin);
      if (l && !AllowMultiple)
-        Del(l);
+        this->cList<cSetupLine>::Del(l);
      if (Value)
         Add(new cSetupLine(Name, Value, Plugin));
      }
@@ -590,11 +814,23 @@ bool cSetup::Parse(const char *Name, const char *Value)
   else if (!strcasecmp(Name, "InitialVolume"))       InitialVolume      = atoi(Value);
   else if (!strcasecmp(Name, "ChannelsWrap"))        ChannelsWrap       = atoi(Value);
   else if (!strcasecmp(Name, "EmergencyExit"))       EmergencyExit      = atoi(Value);
+  else if (strstr(Name, "master:"))          return LoadAlternative(Name, Value);
   else
      return false;
   return true;
 }
 
+bool cSetup::LoadAlternative(const char *Name, const char *Value) {
+   Name += strlen("master:");
+   char helper[128];
+   strcpy(helper, Name);
+   helper[strlen(helper)-4] = 0;
+   int masterNr = atoi(helper);
+   int alternativeNr = atoi(Value);
+   Alternatives.LoadAlternative(masterNr, alternativeNr);
+   return true;
+}
+
 bool cSetup::Save(void)
 {
   Store("OSDLanguage",        OSDLanguage);
@@ -686,7 +922,7 @@ bool cSetup::Save(void)
   Store("InitialVolume",      InitialVolume);
   Store("ChannelsWrap",       ChannelsWrap);
   Store("EmergencyExit",      EmergencyExit);
-
+  SaveAlternatives();
   Sort();
 
   if (cConfig<cSetupLine>::Save()) {
@@ -695,3 +931,48 @@ bool cSetup::Save(void)
      }
   return false;
 }
+
+void cSetup::SaveAlternatives() {
+   // Remove old alternatives or otherwise they will stay forever
+   for(cSetupLine *line = First() ; line ; line = Next(line)) {
+      if (strstr(line->Name(), "master:") == line->Name()) {
+         if (line->Prev() != NULL) {
+            cSetupLine *temp = line;
+            line = Prev(line);
+            this->cList<cSetupLine>::Del(temp);
+         } else {
+            this->cList<cSetupLine>::Del(line);
+            line = First();
+         }
+      }
+   }
+   int counter = 1000;
+   for(int i = 0 ; i < Alternatives.CountAlternatives() ; i++) {
+      cAlternative *alt = Alternatives.GetAlternative(i);
+      cList<cAlternativeContainer> &alternatives = alt->GetAlternativeChannels();
+
+      const cChannel *master = alt->GetMaster();
+
+      for(cAlternativeContainer *next = alternatives.First(); next ; next = alternatives.Next(next)) {
+         cString key = cString::sprintf("master:%d%d", master->Number(), counter);
+         Store(*key, next->channel->Number());
+         counter++;
+         }
+      }
+}
+
+cAllAlternatives& cSetup::getAllAlternatives() {
+   return Alternatives;
+}
+
+cList<cAlternativeContainer>& cSetup::findAlternativeChannels(const cChannel* channel) {
+   cAlternative *alt = Alternatives.FindAlternative(channel);
+   if (alt) {
+      return alt->GetAlternativeChannels();
+   }
+   return nullAlternatives;
+}
+
+void cSetup::Del(const cChannel* Channel) {
+  Alternatives.Del(Channel);
+}
diff --git a/config.h b/config.h
index 7c28d41..f4cbd76 100644
--- a/config.h
+++ b/config.h
@@ -7,49 +7,18 @@
  * $Id: config.h 2.28 2010/09/12 11:31:21 kls Exp $
  */
 
-#ifndef __CONFIG_H
-#define __CONFIG_H
+#ifndef __CCONFIG_H
+#define __CCONFIG_H
 
 #include <arpa/inet.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <time.h>
 #include <unistd.h>
 #include "i18n.h"
 #include "font.h"
 #include "tools.h"
 
-// VDR's own version number:
-
-#define VDRVERSION  "1.7.16"
-#define VDRVERSNUM   10716  // Version * 10000 + Major * 100 + Minor
-
-// The plugin API's version number:
-
-#define APIVERSION  "1.7.16"
-#define APIVERSNUM   10716  // Version * 10000 + Major * 100 + Minor
-
-// When loading plugins, VDR searches them by their APIVERSION, which
-// may be smaller than VDRVERSION in case there have been no changes to
-// VDR header files since the last APIVERSION. This allows compiled
-// plugins to work with newer versions of the core VDR as long as no
-// VDR header files have changed.
-
-#define MAXPRIORITY 99
-#define MAXLIFETIME 99
-
-#define MINOSDWIDTH   480
-#define MAXOSDWIDTH  1920
-#define MINOSDHEIGHT  324
-#define MAXOSDHEIGHT 1200
-
-#define MaxFileName 256
-#define MaxSkinName 16
-#define MaxThemeName 16
-
-typedef uint32_t in_addr_t; //XXX from /usr/include/netinet/in.h (apparently this is not defined on systems with glibc < 2.2)
-
 class cSVDRPhost : public cListObject {
 private:
   struct in_addr addr;
@@ -144,6 +113,44 @@ public:
   }
   };
 
+
+#endif //__CCONFIG_H
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include "channels.h"
+
+// VDR's own version number:
+
+#define VDRVERSION  "1.7.16"
+#define VDRVERSNUM   10716  // Version * 10000 + Major * 100 + Minor
+
+// The plugin API's version number:
+
+#define APIVERSION  "1.7.16"
+#define APIVERSNUM   10716  // Version * 10000 + Major * 100 + Minor
+
+// When loading plugins, VDR searches them by their APIVERSION, which
+// may be smaller than VDRVERSION in case there have been no changes to
+// VDR header files since the last APIVERSION. This allows compiled
+// plugins to work with newer versions of the core VDR as long as no
+// VDR header files have changed.
+
+#define MAXPRIORITY 99
+#define MAXLIFETIME 99
+
+#define MINOSDWIDTH   480
+#define MAXOSDWIDTH  1920
+#define MINOSDHEIGHT  324
+#define MAXOSDHEIGHT 1200
+
+#define MaxFileName 256
+#define MaxSkinName 16
+#define MaxThemeName 16
+
+typedef uint32_t in_addr_t; //XXX from /usr/include/netinet/in.h (apparently this is not defined on systems with glibc < 2.2)
+
 class cNestedItem : public cListObject {
 private:
   char *text;
@@ -200,6 +207,70 @@ public:
   bool Save(FILE *f);
   };
 
+class cChannel;
+
+// -- Class cAlternativeContainer
+
+class cAlternativeContainer : public cListObject {
+public:
+   const cChannel *channel;
+   cAlternativeContainer(const cChannel *channel) : channel(channel) { };
+   cAlternativeContainer(const cAlternativeContainer& ref) {*this=ref;};
+   cAlternativeContainer& operator=(const cAlternativeContainer& ref) {channel = ref.channel;return *this;};
+};
+
+class cAlternative : public cListObject {
+private:
+   const cChannel *master;
+   cList<cAlternativeContainer> alternativeChannels;
+public:
+   cAlternative(const cChannel *master);
+   cAlternative(cAlternative &other) { *this = other;};
+   cAlternative(cAlternative *other);
+   void AddAlternativeChannel(const cChannel *Alternative);
+   void RemoveAlternativeChannel(const cChannel *alternative);
+   cList<cAlternativeContainer>& GetAlternativeChannels();
+   // < Returns a reference the alternative channel cList
+   const cChannel* GetMaster();
+   bool operator<(const cAlternative& other);
+   cAlternative& operator= (const cAlternative &s);
+   bool operator==(const cAlternative &Other);
+   bool operator!=(const cAlternative &Other) { return !(*this == Other);}
+   virtual ~cAlternative();
+   void Del(const cChannel *Channel);
+};
+
+class cIntPair : public cListObject {
+public:
+   int int1, int2;
+   cIntPair(int int1, int int2) : int1(int1), int2(int2) { }
+};
+
+class cAllAlternatives {
+   friend class cSetup;
+private:
+   cList<cAlternative> alternatives;
+   cList<cIntPair> masterToAlternative;
+   // Cache because when parsing the configuration the channels are not parsed yet.
+   void Init();
+   bool init;
+   cAlternative *FindAlternative(const cChannel *Master);
+public:
+   cAlternative *GetAlternative(int Index); // zero-based index
+   void CreateAlternative(const cChannel *Mmaster);
+   void RemoveAlternative(cAlternative *Alternative);
+   virtual ~cAllAlternatives();
+   int CountAlternatives();
+   void AddAlternative(const cChannel *Master, const cChannel *AlternativeToAdd);
+   cAllAlternatives() : init(false) { };
+   cAllAlternatives(cAllAlternatives &Other) { *this = Other;};
+   void LoadAlternative(int MasterNr, int AlternativeNr);
+   cAllAlternatives& operator= (const cAllAlternatives &Other);
+   bool operator==(cAllAlternatives &Other);
+   bool operator!=(cAllAlternatives &Other) { return !(*this == Other);}
+   void Del(const cChannel *Channel);
+};
+
 class cSetup : public cConfig<cSetupLine> {
   friend class cPlugin; // needs to be able to call Store()
 private:
@@ -210,7 +281,9 @@ private:
   void Store(const char *Name, const char *Value, const char *Plugin = NULL, bool AllowMultiple = false);
   void Store(const char *Name, int Value, const char *Plugin = NULL);
   void Store(const char *Name, double &Value, const char *Plugin = NULL);
+  cList<cAlternativeContainer> nullAlternatives;
 public:
+  cAllAlternatives Alternatives;
   // Also adjust cMenuSetup (menu.c) when adding parameters here!
   int __BeginData__;
   char OSDLanguage[I18N_MAX_LOCALE_LEN];
@@ -296,6 +369,11 @@ public:
   cSetup& operator= (const cSetup &s);
   bool Load(const char *FileName);
   bool Save(void);
+  bool LoadAlternative(const char *Name, const char *Value);
+  void SaveAlternatives();
+  cAllAlternatives& getAllAlternatives();
+  cList<cAlternativeContainer>& findAlternativeChannels(const cChannel* channel);
+  void Del(const cChannel *Channel);
   };
 
 extern cSetup Setup;
diff --git a/device.c b/device.c
index 681049b..a4d156a 100644
--- a/device.c
+++ b/device.c
@@ -67,7 +67,8 @@ bool cDeviceHook::DeviceProvidesTransponder(const cDevice *Device, const cChanne
 int cDevice::numDevices = 0;
 int cDevice::useDevice = 0;
 int cDevice::nextCardIndex = 0;
-int cDevice::currentChannel = 1;
+int cDevice::currentSelectedChannel = 1;
+int cDevice::currentReceivingChannel = 1;
 cDevice *cDevice::device[MAXDEVICES] = { NULL };
 cDevice *cDevice::primaryDevice = NULL;
 cDevice *cDevice::avoidDevice = NULL;
@@ -228,7 +229,52 @@ static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device)
   return NumProvidedSystems;
 }
 
-cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView)
+cDevice *cDevice::QueryDevice(const cChannel *Channel, int Priority, bool LiveView, const cChannel *&foundChannelRef, bool allowAlternatives)
+{
+  cList<cAlternativeContainer> &alternatives = Setup.findAlternativeChannels(Channel);
+  if (!LiveView) {
+     /*
+      * Searching for alternative without detaching is not relevant for LiveView.
+      * Why?: There can be other receivers with priority = -1 (like osdteletext) and
+      * there are no other receivers with priority <= 0 for live view. Timers,
+      * streamdev and so on have receivers with priority > 0. So detaching is allowed.
+      */
+     // first try original channel without detaching
+     cDevice *device = GetDevice(Channel, Priority, LiveView, false);
+     if (device) {
+        foundChannelRef = Channel;
+        return device;
+        }
+     // now try alternatives without detaching
+     if (allowAlternatives) {
+        for(cAlternativeContainer *next = alternatives.First(); next ; next = alternatives.Next(next)) {
+           device = GetDevice(next->channel, Priority, LiveView, false);
+           if (device) {
+              foundChannelRef = next->channel;
+              return device;
+              }
+           }
+        }
+     }
+  // once again the same steps, this time detaching is allowed
+  cDevice *device = GetDevice(Channel, Priority, LiveView, true);
+  if (device) {
+     foundChannelRef = Channel;
+     return device;
+     }
+  if (allowAlternatives) {
+     for(cAlternativeContainer *next = alternatives.First(); next ; next = alternatives.Next(next)) {
+        device = GetDevice(next->channel, Priority, LiveView, true);
+        if (device) {
+           foundChannelRef = next->channel;
+           return device;
+           }
+        }
+     }
+  return NULL;
+}
+
+cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool DetachingAllowed)
 {
   cDevice *AvoidDevice = avoidDevice;
   avoidDevice = NULL;
@@ -291,12 +337,18 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
              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
              if (imp < Impact) {
+                // If this is the primary device and not live view, this is like detaching.
+                // The primary device can be used if there is a player (=>Not watching live tv)
+                bool likeNdr = device[i]->IsPrimaryDevice() && !LiveView && device[i]->player == NULL;
                 // This device has less impact than any previous one, so we take it.
-                Impact = imp;
-                d = device[i];
-                NeedsDetachReceivers = ndr;
-                if (NumUsableSlots)
-                   s = CamSlots.Get(j);
+                if (DetachingAllowed && (ndr || likeNdr) || !ndr) {
+                   // Only use the device if detaching is allowed or detaching is not needed
+                   Impact = imp;
+                   d = device[i];
+                   NeedsDetachReceivers = ndr;
+                   if (NumUsableSlots)
+                      s = CamSlots.Get(j);
+                   }
                 }
              }
           }
@@ -660,12 +712,13 @@ bool cDevice::SwitchChannel(int Direction)
   Direction = sgn(Direction);
   if (Direction) {
      cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
-     int n = CurrentChannel() + Direction;
+     int n = CurrentChannelConfig().selected() + Direction;
      int first = n;
      cChannel *channel;
+     const cChannel *ptrAlternative;
      while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
            // try only channels which are currently available
-           if (GetDevice(channel, 0, true))
+           if (QueryDevice(channel, 0, true, ptrAlternative))
               break;
            n = channel->Number() + Direction;
            }
@@ -692,7 +745,15 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
      DELETENULL(dvbSubtitleConverter);
      }
 
-  cDevice *Device = (LiveView && IsPrimaryDevice()) ? GetDevice(Channel, 0, LiveView) : this;
+  cDevice *Device = NULL;
+  const cChannel *SourceChannel = NULL;
+  if (LiveView && IsPrimaryDevice()) {
+        Device = QueryDevice(Channel, 0, LiveView, SourceChannel);
+     }
+  else {
+        Device = this;
+        SourceChannel = Channel;
+     }
 
   bool NeedsTransferMode = Device != this;
 
@@ -704,8 +765,8 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
   if (NeedsTransferMode) {
      if (Device && CanReplay()) {
         cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
-        if (Device->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
-           cControl::Launch(new cTransferControl(Device, Channel));
+        if (Device->SetChannel(SourceChannel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
+           cControl::Launch(new cTransferControl(Device, SourceChannel));
         else
            Result = scrNoTransfer;
         }
@@ -714,6 +775,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
      }
   else {
      Channels.Lock(false);
+
      cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
      // Stop section handling:
      if (sectionHandler) {
@@ -723,11 +785,11 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
      // Tell the camSlot about the channel switch and add all PIDs of this
      // channel to it, for possible later decryption:
      if (camSlot)
-        camSlot->AddChannel(Channel);
-     if (SetChannelDevice(Channel, LiveView)) {
+        camSlot->AddChannel(SourceChannel);
+     if (SetChannelDevice(SourceChannel, LiveView)) {
         // Start section handling:
         if (sectionHandler) {
-           sectionHandler->SetChannel(Channel);
+           sectionHandler->SetChannel(SourceChannel);
            sectionHandler->SetStatus(true);
            }
         // Start decrypting any PIDs that might have been set in SetChannelDevice():
@@ -741,17 +803,18 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
 
   if (Result == scrOk) {
      if (LiveView && IsPrimaryDevice()) {
-        currentChannel = Channel->Number();
+        currentSelectedChannel = Channel->Number();
+        currentReceivingChannel = SourceChannel->Number();
         // Set the available audio tracks:
         ClrAvailableTracks();
         for (int i = 0; i < MAXAPIDS; i++)
-            SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
+            SetAvailableTrack(ttAudio, i, SourceChannel->Apid(i), SourceChannel->Alang(i));
         if (Setup.UseDolbyDigital) {
            for (int i = 0; i < MAXDPIDS; i++)
-               SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
+               SetAvailableTrack(ttDolby, i, SourceChannel->Dpid(i), SourceChannel->Dlang(i));
            }
         for (int i = 0; i < MAXSPIDS; i++)
-            SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
+            SetAvailableTrack(ttSubtitle, i, SourceChannel->Spid(i), SourceChannel->Slang(i));
         if (!NeedsTransferMode)
            EnsureAudioTrack(true);
         EnsureSubtitleTrack();
@@ -765,7 +828,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
 void cDevice::ForceTransferMode(void)
 {
   if (!cTransferControl::ReceiverDevice()) {
-     cChannel *Channel = Channels.GetByNumber(CurrentChannel());
+     cChannel *Channel = Channels.GetByNumber(CurrentChannelConfig().receiving());
      if (Channel)
         SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
      }
diff --git a/device.h b/device.h
index cb3bc2c..2430786 100644
--- a/device.h
+++ b/device.h
@@ -138,7 +138,12 @@ public:
          ///< Gets the device with the given Index.
          ///< \param Index must be in the range 0..numDevices-1.
          ///< \return A pointer to the device, or NULL if the Index was invalid.
-  static cDevice *GetDevice(const cChannel *Channel, int Priority, bool LiveView);
+  static cDevice *QueryDevice(const cChannel *Channel, int Priority, bool LiveView, const cChannel *&foundChannelRef, bool allowAlternatives = true);
+         ///< Search for a device providing the given channel Channel. If other
+         ///< receivers would get detached, the alternative channels gets queried.
+         ///< The returned device doesn't have to provide the given channel. It
+         ///< will provide the returned channel foundChannelRef
+  static cDevice *GetDevice(const cChannel *Channel, int Priority, bool LiveView, bool DetachingAllowed = true);
          ///< Returns a device that is able to receive the given Channel at the
          ///< given Priority, with the least impact on active recordings and
          ///< live viewing. The LiveView parameter tells whether the device will
@@ -218,7 +223,9 @@ public:
 // Channel facilities
 
 protected:
-  static int currentChannel;
+  static int currentSelectedChannel;
+
+  static int currentReceivingChannel;
 public:
   virtual bool ProvidesSource(int Source) const;
          ///< Returns true if this device can provide the given source.
@@ -275,9 +282,16 @@ protected:
   virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
          ///< Sets the device to the given channel (actual physical setup).
 public:
-  static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
-         ///< Returns the number of the current channel on the primary device.
-  static void SetCurrentChannel(const cChannel *Channel) { currentChannel = Channel ? Channel->Number() : 0; }
+  static cChannelConfig CurrentChannelConfig(void) { return primaryDevice ? cChannelConfig(currentSelectedChannel, currentReceivingChannel) : cChannelConfig(0,0); }
+  static int CurrentChannel(void) { return primaryDevice ? currentSelectedChannel:0; }
+         ///< Returns the number of the current selected channel on the primary device.
+  static int CurrentReceivingChannel(void) { return primaryDevice ? currentReceivingChannel : 0; }
+         ///< Returns the number of the current receiving channel on the primary device.
+  static void SetCurrentChannel(const cChannel *Channel) { currentSelectedChannel = Channel ? Channel->Number() : 0; }
+         ///< Sets the number of the current channel on the primary device, without
+         ///< actually switching to it. This can be used to correct the current
+         ///< channel number while replaying.
+  static void SetReceivingChannel(const cChannel *Channel) { currentReceivingChannel = Channel ? Channel->Number() : 0; }
          ///< Sets the number of the current channel on the primary device, without
          ///< actually switching to it. This can be used to correct the current
          ///< channel number while replaying.
diff --git a/dvbdevice.c b/dvbdevice.c
index f32b350..28b659d 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -20,6 +20,7 @@
 #include "dvbci.h"
 #include "menuitems.h"
 #include "sourceparams.h"
+#include "sources.h"
 
 #define FE_CAN_TURBO_FEC  0x8000000 // TODO: remove this once it is defined in the driver
 
diff --git a/eitscan.c b/eitscan.c
index 2b43e71..00042bc 100644
--- a/eitscan.c
+++ b/eitscan.c
@@ -155,7 +155,7 @@ void cEITScanner::Process(void)
                                      if (!MaySwitchTransponder) {
                                         if (Device == cDevice::ActualDevice() && !currentChannel) {
                                            cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
-                                           currentChannel = Device->CurrentChannel();
+                                           currentChannel = Device->CurrentChannelConfig().selected();
                                            Skins.Message(mtInfo, tr("Starting EPG scan"));
                                            }
                                         }
diff --git a/menu.c b/menu.c
index 19cfabb..60b2c72 100644
--- a/menu.c
+++ b/menu.c
@@ -399,7 +399,7 @@ void cMenuChannels::Setup(void)
 {
   cChannel *currentChannel = GetChannel(Current());
   if (!currentChannel)
-     currentChannel = Channels.GetByNumber(cDevice::CurrentChannel());
+     currentChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
   cMenuChannelItem *currentItem = NULL;
   Clear();
   for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
@@ -486,7 +486,7 @@ eOSState cMenuChannels::New(void)
 eOSState cMenuChannels::Delete(void)
 {
   if (!HasSubMenu() && Count() > 0) {
-     int CurrentChannelNr = cDevice::CurrentChannel();
+     int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
      cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
      int Index = Current();
      cChannel *channel = GetChannel(Current());
@@ -504,6 +504,7 @@ eOSState cMenuChannels::Delete(void)
            CurrentChannel = Channels.Get(n);
            CurrentChannelNr = 0; // triggers channel switch below
            }
+        ::Setup.Del(channel);
         Channels.Del(channel);
         cOsdMenu::Del(Index);
         Propagate();
@@ -522,8 +523,10 @@ eOSState cMenuChannels::Delete(void)
 
 void cMenuChannels::Move(int From, int To)
 {
-  int CurrentChannelNr = cDevice::CurrentChannel();
+  int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
+  int ReceivingChannelNr = cDevice::CurrentChannelConfig().receiving();
   cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
+  cChannel *ReceivingChannel = Channels.GetByNumber(ReceivingChannelNr);
   cChannel *FromChannel = GetChannel(From);
   cChannel *ToChannel = GetChannel(To);
   if (FromChannel && ToChannel) {
@@ -534,11 +537,16 @@ void cMenuChannels::Move(int From, int To)
      Propagate();
      Channels.SetModified(true);
      isyslog("channel %d moved to %d", FromNumber, ToNumber);
-     if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
+     if (CurrentChannel && ReceivingChannel && (
+           CurrentChannel->Number() != CurrentChannelNr ||
+           ReceivingChannel->Number() != ReceivingChannelNr)
+           ) {
         if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
            Channels.SwitchTo(CurrentChannel->Number());
-        else
+        else {
            cDevice::SetCurrentChannel(CurrentChannel);
+           cDevice::SetReceivingChannel(ReceivingChannel);
+           }
         }
      }
 }
@@ -1547,7 +1555,7 @@ cMenuSchedule::cMenuSchedule(void)
   timerState = 0;
   Timers.Modified(timerState);
   cMenuScheduleItem::SetSortMode(cMenuScheduleItem::ssmAllThis);
-  cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
+  cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
   if (channel) {
      cMenuWhatsOn::SetCurrentChannel(channel->Number());
      schedules = cSchedules::Schedules(schedulesLock);
@@ -1674,7 +1682,7 @@ eOSState cMenuSchedule::Number(void)
      Channel = Channels.GetByChannelID(Event->ChannelID(), true);
      }
   else
-     Channel = Channels.GetByNumber(cDevice::CurrentChannel());
+     Channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
   switch (cMenuScheduleItem::SortMode()) {
     case cMenuScheduleItem::ssmAllThis:  PrepareScheduleAllThis(Event, Channel); break;
     case cMenuScheduleItem::ssmThisThis: PrepareScheduleThisThis(Event, Channel); break;
@@ -1778,7 +1786,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
         if (channel) {
            cMenuScheduleItem::SetSortMode(cMenuScheduleItem::ssmAllThis);
            PrepareScheduleAllThis(NULL, channel);
-           if (channel->Number() != cDevice::CurrentChannel()) {
+           if (channel->Number() != cDevice::CurrentChannelConfig().selected()) {
               otherChannel = channel->Number();
               SetHelp(Count() ? tr("Button$Record") : NULL, tr("Button$Now"), tr("Button$Next"), tr("Button$Switch"));
               }
@@ -3166,6 +3174,284 @@ eOSState cMenuSetupPlugins::ProcessKey(eKeys Key)
   return state;
 }
 
+// --- SelectChannelMenu -----------------------------------------------------
+
+class SelectChannelMenu : public cOsdMenu {
+private:
+   bool menuClosed;
+   static const cChannel *selectedChannel;
+public:
+   SelectChannelMenu();
+   static const cChannel *getSelectedChannel();
+   bool menuHasToBeClosed();;
+   virtual eOSState ProcessKey(eKeys Key);
+};
+
+const cChannel *SelectChannelMenu::selectedChannel = NULL;
+
+SelectChannelMenu::SelectChannelMenu() : cOsdMenu(tr("select channel"))
+{
+   menuClosed = false;
+   selectedChannel = NULL;
+   if (Channels.Count() > 0) {
+      const cChannel *channel = Channels.First();
+      while(true) {
+         Add(new cOsdItem(strdup(channel->Name()), osUnknown, true));
+         if (channel == Channels.Last())
+            break;
+         channel = Channels.Next(channel);
+      }
+   }
+}
+
+eOSState SelectChannelMenu::ProcessKey(eKeys Key) {
+   eOSState state = osUnknown;
+   if (Key == kOk) {
+      if (Channels.Count() > 0) {
+         selectedChannel = Channels.Get(Current());
+      }
+      state = osBack;
+   } else if (Key == kBack) {
+      state = osBack;
+   } else {
+      cOsdMenu::ProcessKey(Key);
+   }
+   return state;
+}
+
+bool SelectChannelMenu::menuHasToBeClosed() {
+   return menuClosed;
+}
+
+const cChannel *SelectChannelMenu::getSelectedChannel() {
+   return selectedChannel;
+}
+
+
+// --- cMenuSetupAlternativeMenuItem -----------------------------------------------------
+
+class cMenuSetupAlternativeMenuItem : public cOsdItem {
+   const cChannel *channel;
+public:
+   cMenuSetupAlternativeMenuItem(const cChannel *alternative, bool selectable = false);
+   const cChannel *getChannel();
+};
+
+cMenuSetupAlternativeMenuItem::cMenuSetupAlternativeMenuItem(const cChannel *alternative, bool selectable) : cOsdItem(NULL, osUnknown, selectable) {
+   char buf[128];
+   strcpy(buf, "  ");
+   strcat(buf, alternative->Name());
+   SetText(buf, true /* copy the string */);
+   this->channel = alternative;
+}
+
+const cChannel *cMenuSetupAlternativeMenuItem::getChannel() {
+   return channel;
+}
+
+// --- AltEditAlternative -----------------------------------------------------
+
+class cMenuSetupEditAlternative : public cOsdMenu {
+private:
+   cAlternative *alternative;
+   bool closeMenu;
+   void refreshHelp();
+   void refreshMenu();
+   bool IsDeletionEnabled();
+   void refreshAll();
+   SelectChannelMenu *selectChannelSubmenu;
+
+public:
+   cMenuSetupEditAlternative(cAlternative *alternative);
+   virtual eOSState ProcessKey(eKeys Key);
+   bool menuHasToBeClosed();
+};
+
+cMenuSetupEditAlternative::cMenuSetupEditAlternative(cAlternative *alternative) : cOsdMenu(tr("Edit Alternatives"))
+{
+   this->alternative = alternative;
+   selectChannelSubmenu = NULL;
+   refreshAll();
+   closeMenu = false;
+}
+
+bool cMenuSetupEditAlternative::IsDeletionEnabled()
+{
+    return alternative->GetAlternativeChannels().Count() > 0;
+}
+
+void cMenuSetupEditAlternative::refreshAll() {
+   refreshHelp();
+   refreshMenu();
+}
+
+void cMenuSetupEditAlternative::refreshHelp() {
+   if (IsDeletionEnabled()) {
+      SetHelp(tr("Add Channel"), tr("Remove Channel"));
+   } else {
+      SetHelp(tr("Add Channel"));
+   }
+}
+
+bool cMenuSetupEditAlternative::menuHasToBeClosed() {
+   return closeMenu;
+}
+
+void cMenuSetupEditAlternative::refreshMenu() {
+   Clear();
+   Add(new cOsdItem(alternative->GetMaster()->Name(), osUnknown, false));
+   cList<cAlternativeContainer>& ref = alternative->GetAlternativeChannels();
+   for(cAlternativeContainer *next = ref.First() ; next ; next = ref.Next(next)) {
+      Add(new cMenuSetupAlternativeMenuItem(next->channel, true));
+   }
+   RefreshCurrent();
+   Display();
+}
+
+eOSState cMenuSetupEditAlternative::ProcessKey(eKeys Key) {
+   eOSState state = osUnknown;
+   if (HasSubMenu()) {
+      state = cOsdMenu::ProcessKey(Key);
+      if (!HasSubMenu()) {
+         const cChannel *selected = SelectChannelMenu::getSelectedChannel();
+         if (selected) {
+            alternative->AddAlternativeChannel(selected);
+         }
+         refreshAll();
+         state = osContinue;
+      }
+   } else {
+      if (Key == kRed) {
+         AddSubMenu(selectChannelSubmenu = new SelectChannelMenu());
+      } else if (Key == kGreen) {
+         if (IsDeletionEnabled()) {
+            cMenuSetupAlternativeMenuItem *selected = static_cast<cMenuSetupAlternativeMenuItem *>(Get(Current()));
+            alternative->RemoveAlternativeChannel(selected->getChannel());
+            refreshAll();
+         }
+      } else {
+         state = cOsdMenu::ProcessKey(Key);
+      }
+   }
+   return state;
+}
+
+// --- MasterMenuItem -----------------------------------------------------
+
+class cMenuSetupAlternativeMasterMenuItem : public cOsdItem {
+private:
+   cAlternative* alternative;
+public:
+   cMenuSetupAlternativeMasterMenuItem(cAlternative *alternative);
+   cAlternative *getAlternative();
+};
+
+cMenuSetupAlternativeMasterMenuItem::cMenuSetupAlternativeMasterMenuItem(cAlternative *alternatives) : cOsdItem(alternatives->GetMaster()->Name(), osUnknown, true) {
+   this->alternative = alternatives;
+}
+
+cAlternative *cMenuSetupAlternativeMasterMenuItem::getAlternative() {
+   return alternative;
+}
+
+
+// --- cMenuSetupAlternative -----------------------------------------------------
+
+class cMenuSetupAlternative : public cMenuSetupBase {
+private:
+   SelectChannelMenu *selectChannelSubmenu;
+   cMenuSetupEditAlternative *editAlternative;
+
+protected:
+   virtual void Store(void);
+   void update();
+public:
+   cMenuSetupAlternative();
+   virtual eOSState ProcessKey(eKeys Key);
+};
+
+cMenuSetupAlternative::cMenuSetupAlternative() {
+    update();
+    selectChannelSubmenu = NULL;
+    editAlternative = NULL;
+}
+
+void cMenuSetupAlternative::Store() {
+   cMenuSetupBase::Store();
+}
+
+eOSState cMenuSetupAlternative::ProcessKey(eKeys Key) {
+   eOSState state  = osContinue;
+   if (HasSubMenu()) {
+      state = cMenuSetupPage::ProcessKey(Key);
+      if (!HasSubMenu()) { // submenu closed ?
+         if (selectChannelSubmenu) {
+            selectChannelSubmenu = NULL;
+            const cChannel *master = SelectChannelMenu::getSelectedChannel();
+            if (master != NULL) data.getAllAlternatives().CreateAlternative(master);
+            update();
+         } else if (editAlternative) {
+            editAlternative = NULL;
+            update();
+         }
+         state = osContinue;
+      }
+   } else {
+      switch (Key) {
+      case kRed:
+         AddSubMenu(selectChannelSubmenu = new SelectChannelMenu());
+         break;
+      case kGreen:
+         if (data.getAllAlternatives().CountAlternatives() > 0) {
+            cMenuSetupAlternativeMasterMenuItem *master = static_cast<cMenuSetupAlternativeMasterMenuItem *>(Get(Current()));
+            data.getAllAlternatives().RemoveAlternative(master->getAlternative());
+         }
+         update();
+         break;
+      case kYellow:
+      {
+         cMenuSetupAlternativeMasterMenuItem *item = static_cast<cMenuSetupAlternativeMasterMenuItem *>(Get(Current()));
+         AddSubMenu(editAlternative = new cMenuSetupEditAlternative(item->getAlternative()));
+         break;
+      }
+      case kBack:
+      {
+         if (Setup.Alternatives == data.Alternatives) {
+            state = cMenuSetupPage::ProcessKey(Key);
+            }
+         else {
+            if (Interface->Confirm(tr("Cancel without saving ?")))
+               state = cMenuSetupPage::ProcessKey(Key);
+            }
+         break;
+      }
+      default:
+         state = cMenuSetupPage::ProcessKey(Key);
+      }
+   }
+   return state;
+}
+
+void cMenuSetupAlternative::update() {
+   Clear();
+   for(int i = 0 ; i < data.getAllAlternatives().CountAlternatives() ; i++) {
+      cAlternative *alternative = data.getAllAlternatives().GetAlternative(i);
+      Add(new cMenuSetupAlternativeMasterMenuItem(alternative));
+      cList<cAlternativeContainer>& ref = alternative->GetAlternativeChannels();
+      for(cAlternativeContainer *next = ref.First() ; next ; next = ref.Next(next)) {
+         Add(new cMenuSetupAlternativeMenuItem(next->channel));
+      }
+   }
+   if (data.getAllAlternatives().CountAlternatives() == 0)
+      SetHelp(tr("New Alternative"));
+   else {
+      SetHelp(tr("New Alternative"), tr("Delete Alternative"), tr("Edit Alternative"));
+   }
+   RefreshCurrent();
+   Display();
+}
+
+
 // --- cMenuSetup ------------------------------------------------------------
 
 class cMenuSetup : public cOsdMenu {
@@ -3198,9 +3484,10 @@ void cMenuSetup::Set(void)
   Add(new cOsdItem(hk(tr("Recording")),     osUser6));
   Add(new cOsdItem(hk(tr("Replay")),        osUser7));
   Add(new cOsdItem(hk(tr("Miscellaneous")), osUser8));
+  Add(new cOsdItem(hk(tr("Alternatives")),  osUser9));
   if (cPluginManager::HasPlugins())
-  Add(new cOsdItem(hk(tr("Plugins")),       osUser9));
-  Add(new cOsdItem(hk(tr("Restart")),       osUser10));
+  Add(new cOsdItem(hk(tr("Plugins")),       osUser10));
+  Add(new cOsdItem(hk(tr("Restart")),       osUser11));
 }
 
 eOSState cMenuSetup::Restart(void)
@@ -3226,8 +3513,9 @@ eOSState cMenuSetup::ProcessKey(eKeys Key)
     case osUser6: return AddSubMenu(new cMenuSetupRecord);
     case osUser7: return AddSubMenu(new cMenuSetupReplay);
     case osUser8: return AddSubMenu(new cMenuSetupMisc);
-    case osUser9: return AddSubMenu(new cMenuSetupPlugins);
-    case osUser10: return Restart();
+    case osUser9: return AddSubMenu(new cMenuSetupAlternative);
+    case osUser10: return AddSubMenu(new cMenuSetupPlugins);
+    case osUser11: return Restart();
     default: ;
     }
   if (I18nCurrentLanguage() != osdLanguage) {
@@ -3519,7 +3807,7 @@ static void SetTrackDescriptions(int LiveChannel)
 
 cDisplayChannel *cDisplayChannel::currentDisplayChannel = NULL;
 
-cDisplayChannel::cDisplayChannel(int Number, bool Switched)
+cDisplayChannel::cDisplayChannel(int Number, int NumberReceiving, bool Switched)
 :cOsdObject(true)
 {
   currentDisplayChannel = this;
@@ -3528,9 +3816,10 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
   displayChannel = Skins.Current()->DisplayChannel(withInfo);
   number = 0;
   timeout = Switched || Setup.TimeoutRequChInfo;
-  channel = Channels.GetByNumber(Number);
+  selectedChannel = Channels.GetByNumber(Number);
+  receivingChannel = Channels.GetByNumber(NumberReceiving);
   lastPresent = lastFollowing = NULL;
-  if (channel) {
+  if (selectedChannel) {
      DisplayChannel();
      DisplayInfo();
      displayChannel->Flush();
@@ -3549,7 +3838,8 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
   lastTime.Set();
   withInfo = Setup.ShowInfoOnChSwitch;
   displayChannel = Skins.Current()->DisplayChannel(withInfo);
-  channel = Channels.GetByNumber(cDevice::CurrentChannel());
+  selectedChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
+  receivingChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().receiving());
   ProcessKey(FirstKey);
 }
 
@@ -3562,23 +3852,24 @@ cDisplayChannel::~cDisplayChannel()
 
 void cDisplayChannel::DisplayChannel(void)
 {
-  displayChannel->SetChannel(channel, number);
-  cStatus::MsgOsdChannel(ChannelString(channel, number));
+  cChannelConfig cc(selectedChannel->Number(), receivingChannel->Number());
+  displayChannel->SetChannel(cc, number);
+  cStatus::MsgOsdChannel(ChannelString(cc, number));
   lastPresent = lastFollowing = NULL;
 }
 
 void cDisplayChannel::DisplayInfo(void)
 {
-  if (withInfo && channel) {
+  if (withInfo && selectedChannel) {
      cSchedulesLock SchedulesLock;
      const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
      if (Schedules) {
-        const cSchedule *Schedule = Schedules->GetSchedule(channel);
+        const cSchedule *Schedule = Schedules->GetSchedule(selectedChannel);
         if (Schedule) {
            const cEvent *Present = Schedule->GetPresentEvent();
            const cEvent *Following = Schedule->GetFollowingEvent();
            if (Present != lastPresent || Following != lastFollowing) {
-              SetTrackDescriptions(channel->Number());
+              SetTrackDescriptions(receivingChannel->Number());
               displayChannel->SetEvents(Present, Following);
               cStatus::MsgOsdProgramme(Present ? Present->StartTime() : 0, Present ? Present->Title() : NULL, Present ? Present->ShortText() : NULL, Following ? Following->StartTime() : 0, Following ? Following->Title() : NULL, Following ? Following->ShortText() : NULL);
               lastPresent = Present;
@@ -3595,15 +3886,18 @@ void cDisplayChannel::Refresh(void)
   displayChannel->SetEvents(NULL, NULL);
 }
 
-cChannel *cDisplayChannel::NextAvailableChannel(cChannel *Channel, int Direction)
+cChannel *cDisplayChannel::NextAvailableChannel(cChannel *Channel, int Direction, const cChannel *&RefReceiving)
 {
   if (Direction) {
      while (Channel) {
            Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel);
            if (!Channel && Setup.ChannelsWrap)
               Channel = Direction > 0 ? Channels.First() : Channels.Last();
-           if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, 0, true))
+           const cChannel *PtrAlternative = NULL;
+           if (Channel && !Channel->GroupSep() && cDevice::QueryDevice(Channel, 0, true, PtrAlternative)) {
+        	  RefReceiving = PtrAlternative;
               return Channel;
+              }
            }
      }
   return NULL;
@@ -3628,13 +3922,13 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
                number = Key - k0;
             else
                number = number * 10 + Key - k0;
-            channel = Channels.GetByNumber(number);
+            receivingChannel = selectedChannel = Channels.GetByNumber(number); // also assign receiving for hiding parenthese
             Refresh();
             withInfo = false;
             // Lets see if there can be any useful further input:
-            int n = channel ? number * 10 : 0;
+            int n = selectedChannel ? number * 10 : 0;
             int m = 10;
-            cChannel *ch = channel;
+            cChannel *ch = selectedChannel;
             while (ch && (ch = Channels.Next(ch)) != NULL) {
                   if (!ch->GroupSep()) {
                      if (n <= ch->Number() && ch->Number() < n + m) {
@@ -3649,7 +3943,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
                   }
             if (n > 0) {
                // This channel is the only one that fits the input, so let's take it right away:
-               NewChannel = channel;
+               NewChannel = selectedChannel;
                withInfo = true;
                number = 0;
                Refresh();
@@ -3667,7 +3961,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
          withInfo = false;
          number = 0;
          if (group < 0) {
-            cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
+            cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
             if (channel)
                group = channel->Index();
             }
@@ -3679,10 +3973,10 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
                group = Channels.GetPrevGroup(group < 1 ? 1 : group);
             if (group < 0)
                group = SaveGroup;
-            channel = Channels.Get(group);
-            if (channel) {
+            selectedChannel = Channels.Get(group);
+            if (selectedChannel) {
                Refresh();
-               if (!channel->GroupSep())
+               if (!selectedChannel->GroupSep())
                   group = -1;
                }
             }
@@ -3696,10 +3990,13 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
     case kChanDn|k_Repeat:
     case kChanDn: {
          eKeys k = NORMALKEY(Key);
-         cChannel *ch = NextAvailableChannel(channel, (k == kUp || k == kChanUp) ? 1 : -1);
-         if (ch)
-            channel = ch;
-         else if (channel && channel->Number() != cDevice::CurrentChannel())
+         const cChannel *rec = NULL;
+         cChannel *ch = NextAvailableChannel(selectedChannel, (k == kUp || k == kChanUp) ? 1 : -1, rec);
+         if (ch) {
+            selectedChannel = ch;
+            receivingChannel = ch; // the correct channel will be set later after the break
+         }
+         else if (selectedChannel && selectedChannel->Number() != cDevice::CurrentChannelConfig().selected())
             Key = k; // immediately switches channel when hitting the beginning/end of the channel list with k_Repeat
          }
          // no break here
@@ -3709,8 +4006,8 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
     case kChanDn|k_Release:
     case kNext|k_Release:
     case kPrev|k_Release:
-         if (!(Key & k_Repeat) && channel && channel->Number() != cDevice::CurrentChannel())
-            NewChannel = channel;
+         if (!(Key & k_Repeat) && selectedChannel && selectedChannel->Number() != cDevice::CurrentChannelConfig().selected())
+            NewChannel = selectedChannel;
          withInfo = true;
          group = -1;
          number = 0;
@@ -3718,9 +4015,9 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
          break;
     case kNone:
          if (number && Setup.ChannelEntryTimeout && int(lastTime.Elapsed()) > Setup.ChannelEntryTimeout) {
-            channel = Channels.GetByNumber(number);
-            if (channel)
-               NewChannel = channel;
+            selectedChannel = Channels.GetByNumber(number);
+            if (selectedChannel)
+               NewChannel = selectedChannel;
             withInfo = true;
             number = 0;
             Refresh();
@@ -3732,17 +4029,17 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
     //XXX case kYellow: return osEventNext;
     case kOk:
          if (group >= 0) {
-            channel = Channels.Get(Channels.GetNextNormal(group));
-            if (channel)
-               NewChannel = channel;
+            selectedChannel = Channels.Get(Channels.GetNextNormal(group));
+            if (selectedChannel)
+               NewChannel = selectedChannel;
             withInfo = true;
             group = -1;
             Refresh();
             }
          else if (number > 0) {
-            channel = Channels.GetByNumber(number);
-            if (channel)
-               NewChannel = channel;
+            selectedChannel = Channels.GetByNumber(number);
+            if (selectedChannel)
+               NewChannel = selectedChannel;
             withInfo = true;
             number = 0;
             Refresh();
@@ -3757,9 +4054,9 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
             }
     };
   if (!timeout || lastTime.Elapsed() < (uint64_t)(Setup.ChannelInfoTime * 1000)) {
-     if (Key == kNone && !number && group < 0 && !NewChannel && channel && channel->Number() != cDevice::CurrentChannel()) {
+     if (Key == kNone && !number && group < 0 && !NewChannel && selectedChannel && selectedChannel->Number() != cDevice::CurrentChannelConfig().selected()) {
         // makes sure a channel switch through the SVDRP CHAN command is displayed
-        channel = Channels.GetByNumber(cDevice::CurrentChannel());
+        selectedChannel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
         Refresh();
         lastTime.Set();
         }
@@ -3769,7 +4066,9 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
         SetTrackDescriptions(NewChannel->Number()); // to make them immediately visible in the channel display
         Channels.SwitchTo(NewChannel->Number());
         SetTrackDescriptions(NewChannel->Number()); // switching the channel has cleared them
-        channel = NewChannel;
+        selectedChannel = NewChannel;
+        receivingChannel = Channels.Get(cDevice::CurrentChannelConfig().receiving()-1); // .Get is zero-based
+        Refresh();
         }
      return osContinue;
      }
@@ -3853,7 +4152,7 @@ cDisplayTracks::cDisplayTracks(void)
 :cOsdObject(true)
 {
   cDevice::PrimaryDevice()->EnsureAudioTrack();
-  SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannel() : 0);
+  SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannelConfig().receiving() : 0);
   currentDisplayTracks = this;
   numTracks = track = 0;
   audioChannel = cDevice::PrimaryDevice()->GetAudioChannel();
@@ -3972,7 +4271,7 @@ cDisplaySubtitleTracks *cDisplaySubtitleTracks::currentDisplayTracks = NULL;
 cDisplaySubtitleTracks::cDisplaySubtitleTracks(void)
 :cOsdObject(true)
 {
-  SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannel() : 0);
+  SetTrackDescriptions(!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring() ? cDevice::CurrentChannelConfig().receiving() : 0);
   currentDisplayTracks = this;
   numTracks = track = 0;
   types[numTracks] = ttNone;
@@ -4219,13 +4518,16 @@ bool cRecordControls::Start(cTimer *Timer, bool Pause)
   LastNoDiskSpaceMessage = 0;
 
   ChangeState();
-  int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannel();
+  int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannelConfig().selected();
   cChannel *channel = Channels.GetByNumber(ch);
 
   if (channel) {
      int Priority = Timer ? Timer->Priority() : Pause ? Setup.PausePriority : Setup.DefaultPriority;
-     cDevice *device = cDevice::GetDevice(channel, Priority, false);
+     const cChannel *receivingChannel = NULL;
+     cDevice *device = cDevice::QueryDevice(channel, Priority, false, receivingChannel);
      if (device) {
+    	channel = Channels.Get(receivingChannel->Number()-1); // receivingChannel is const, channel not
+    	if (Timer) Timer->SetChannel(channel);
         dsyslog("switching device %d to channel %d", device->DeviceNumber() + 1, channel->Number());
         if (!device->SwitchChannel(channel, false)) {
            ShutdownHandler.RequestEmergencyExit();
diff --git a/menu.h b/menu.h
index ec1c175..a3d8dcd 100644
--- a/menu.h
+++ b/menu.h
@@ -119,16 +119,17 @@ private:
   cTimeMs lastTime;
   int number;
   bool timeout;
-  cChannel *channel;
+  cChannel *selectedChannel;
+  const cChannel *receivingChannel;
   const cEvent *lastPresent;
   const cEvent *lastFollowing;
   static cDisplayChannel *currentDisplayChannel;
   void DisplayChannel(void);
   void DisplayInfo(void);
   void Refresh(void);
-  cChannel *NextAvailableChannel(cChannel *Channel, int Direction);
+  cChannel *NextAvailableChannel(cChannel *Channel, int Direction, const cChannel *&RefReceiving);
 public:
-  cDisplayChannel(int Number, bool Switched);
+  cDisplayChannel(int Number, int NumberReceiving, bool Switched);
   cDisplayChannel(eKeys FirstKey);
   virtual ~cDisplayChannel();
   virtual eOSState ProcessKey(eKeys Key);
diff --git a/nit.c b/nit.c
index dfd0207..9c50a4b 100644
--- a/nit.c
+++ b/nit.c
@@ -15,6 +15,7 @@
 #include "libsi/section.h"
 #include "libsi/descriptor.h"
 #include "tools.h"
+#include "sources.h"
 
 cNitFilter::cNitFilter(void)
 {
diff --git a/osdbase.h b/osdbase.h
index 91c5ff7..231d64f 100644
--- a/osdbase.h
+++ b/osdbase.h
@@ -44,6 +44,11 @@ enum eOSState { osUnknown,
                 osUser8,
                 osUser9,
                 osUser10,
+                osUser11,
+                osUser12,
+                osUser13,
+                osUser14,
+                osUser15,
               };
 
 class cOsdItem : public cListObject {
diff --git a/rcu.c b/rcu.c
index 2e20314..a8131f9 100644
--- a/rcu.c
+++ b/rcu.c
@@ -320,7 +320,7 @@ bool cRcuRemote::DetectCode(unsigned char *Code)
 void cRcuRemote::ChannelSwitch(const cDevice *Device, int ChannelNumber)
 {
   if (ChannelNumber && Device->IsPrimaryDevice())
-     SetNumber(cDevice::CurrentChannel());
+     SetNumber(cDevice::CurrentChannelConfig().selected());
 }
 
 void cRcuRemote::Recording(const cDevice *Device, const char *Name, const char *FileName, bool On)
diff --git a/sdt.c b/sdt.c
index 5f2502b..cb1c070 100644
--- a/sdt.c
+++ b/sdt.c
@@ -12,6 +12,7 @@
 #include "config.h"
 #include "libsi/section.h"
 #include "libsi/descriptor.h"
+#include "sources.h"
 
 // --- cSdtFilter ------------------------------------------------------------
 
diff --git a/skinclassic.c b/skinclassic.c
index 3852010..9fd1b23 100644
--- a/skinclassic.c
+++ b/skinclassic.c
@@ -83,7 +83,7 @@ private:
 public:
   cSkinClassicDisplayChannel(bool WithInfo);
   virtual ~cSkinClassicDisplayChannel();
-  virtual void SetChannel(const cChannel *Channel, int Number);
+  virtual void SetChannel(cChannelConfig channelConfig, int Number);
   virtual void SetEvents(const cEvent *Present, const cEvent *Following);
   virtual void SetMessage(eMessageType Type, const char *Text);
   virtual void Flush(void);
@@ -112,10 +112,10 @@ cSkinClassicDisplayChannel::~cSkinClassicDisplayChannel()
   delete osd;
 }
 
-void cSkinClassicDisplayChannel::SetChannel(const cChannel *Channel, int Number)
+void cSkinClassicDisplayChannel::SetChannel(cChannelConfig channelConfig, int Number)
 {
   osd->DrawRectangle(0, 0, osd->Width() - 1, lineHeight - 1, Theme.Color(clrBackground));
-  osd->DrawText(TextFrame, 0, ChannelString(Channel, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
+  osd->DrawText(TextFrame, 0, ChannelString(channelConfig, Number), Theme.Color(clrChannelName), Theme.Color(clrBackground), cFont::GetFont(fontOsd));
   lastDate = NULL;
 }
 
diff --git a/skins.h b/skins.h
index 6f41da5..93abc4b 100644
--- a/skins.h
+++ b/skins.h
@@ -50,7 +50,7 @@ class cSkinDisplayChannel : public cSkinDisplay {
        ///< the present and following EPG even. How and to what extent this
        ///< is done is totally up to the derived class.
 public:
-  virtual void SetChannel(const cChannel *Channel, int Number) = 0;
+  virtual void SetChannel(cChannelConfig channelConfig, int Number) = 0;
        ///< Sets the current channel to Channel. If Number is not 0, the
        ///< user is in the process of entering a channel number, which must
        ///< be displayed accordingly.
diff --git a/skinsttng.c b/skinsttng.c
index b37a2e9..bdd5df0 100644
--- a/skinsttng.c
+++ b/skinsttng.c
@@ -7,7 +7,7 @@
  * $Id: skinsttng.c 2.5 2010/02/13 13:30:59 kls Exp $
  */
 
-// Star Trek: The Next Generation� is a registered trademark of Paramount Pictures
+// Star Trek: The Next Generation��� is a registered trademark of Paramount Pictures
 // registered in the United States Patent and Trademark Office.
 // No infringement intended.
 
@@ -139,7 +139,7 @@ private:
 public:
   cSkinSTTNGDisplayChannel(bool WithInfo);
   virtual ~cSkinSTTNGDisplayChannel();
-  virtual void SetChannel(const cChannel *Channel, int Number);
+  virtual void SetChannel(cChannelConfig channelConfig, int Number);
   virtual void SetEvents(const cEvent *Present, const cEvent *Following);
   virtual void SetMessage(eMessageType Type, const char *Text);
   virtual void Flush(void);
@@ -240,10 +240,11 @@ cSkinSTTNGDisplayChannel::~cSkinSTTNGDisplayChannel()
   delete osd;
 }
 
-void cSkinSTTNGDisplayChannel::SetChannel(const cChannel *Channel, int Number)
+void cSkinSTTNGDisplayChannel::SetChannel(cChannelConfig channelConfig, int Number)
 {
   osd->DrawRectangle(x3, y0, x4 - 1, y1 - 1, frameColor);
   int x = x4 - SymbolSpacing;
+  const cChannel *Channel = Channels.Get(channelConfig.selected());
   if (Channel && !Channel->GroupSep()) {
      bool rec = cRecordControls::Active();
      x -= bmRecording.Width() + SymbolSpacing;
@@ -263,7 +264,7 @@ void cSkinSTTNGDisplayChannel::SetChannel(const cChannel *Channel, int Number)
         osd->DrawBitmap(x, y0 + (y1 - y0 - bmRadio.Height()) / 2, bmRadio, Theme.Color(clrChannelSymbolOn), frameColor);
         }
      }
-  osd->DrawText(x3 + TextFrame, y0, ChannelString(Channel, Number), Theme.Color(clrChannelName), frameColor, cFont::GetFont(fontOsd), x - x3 - TextFrame);
+  osd->DrawText(x3 + TextFrame, y0, ChannelString(channelConfig, Number), Theme.Color(clrChannelName), frameColor, cFont::GetFont(fontOsd), x - x3 - TextFrame);
 }
 
 void cSkinSTTNGDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
diff --git a/sources.h b/sources.h
index 6b362e3..a6f0db3 100644
--- a/sources.h
+++ b/sources.h
@@ -10,6 +10,7 @@
 #ifndef __SOURCES_H
 #define __SOURCES_H
 
+#include "tools.h"
 #include "config.h"
 
 class cSource : public cListObject {
diff --git a/svdrp.c b/svdrp.c
index cb9a935..4dbe742 100644
--- a/svdrp.c
+++ b/svdrp.c
@@ -488,14 +488,14 @@ void cSVDRP::CmdCHAN(const char *Option)
            n = o;
         }
      else if (strcmp(Option, "-") == 0) {
-        n = cDevice::CurrentChannel();
+        n = cDevice::CurrentChannelConfig().selected();
         if (n > 1) {
            n--;
            d = -1;
            }
         }
      else if (strcmp(Option, "+") == 0) {
-        n = cDevice::CurrentChannel();
+        n = cDevice::CurrentChannelConfig().selected();
         if (n < Channels.MaxNumber()) {
            n++;
            d = 1;
@@ -536,11 +536,11 @@ void cSVDRP::CmdCHAN(const char *Option)
      else
         cDevice::SwitchChannel(d);
      }
-  cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
+  cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
   if (channel)
      Reply(250, "%d %s", channel->Number(), channel->Name());
   else
-     Reply(550, "Unable to find channel \"%d\"", cDevice::CurrentChannel());
+     Reply(550, "Unable to find channel \"%d\"", cDevice::CurrentChannelConfig().selected());
 }
 
 void cSVDRP::CmdCLRE(const char *Option)
@@ -613,7 +613,7 @@ void cSVDRP::CmdDELC(const char *Option)
                      return;
                      }
                   }
-              int CurrentChannelNr = cDevice::CurrentChannel();
+              int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
               cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
               if (CurrentChannel && channel == CurrentChannel) {
                  int n = Channels.GetNextNormal(CurrentChannel->Index());
@@ -1214,7 +1214,7 @@ void cSVDRP::CmdMOVC(const char *Option)
            tail = skipspace(tail);
            if (tail && tail != Option) {
               int To = strtol(tail, NULL, 10);
-              int CurrentChannelNr = cDevice::CurrentChannel();
+              int CurrentChannelNr = cDevice::CurrentChannelConfig().selected();
               cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
               cChannel *FromChannel = Channels.GetByNumber(From);
               if (FromChannel) {
diff --git a/timers.c b/timers.c
index 246fd86..be18a26 100644
--- a/timers.c
+++ b/timers.c
@@ -33,7 +33,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel)
   flags = tfNone;
   if (Instant)
      SetFlags(tfActive | tfInstant);
-  channel = Channel ? Channel : Channels.GetByNumber(cDevice::CurrentChannel());
+  channel = Channel ? Channel : Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
   time_t t = time(NULL);
   struct tm tm_r;
   struct tm *now = localtime_r(&t, &tm_r);
@@ -771,3 +771,7 @@ void cTimers::DeleteExpired(void)
         }
   lastDeleteExpired = time(NULL);
 }
+
+void cTimer::SetChannel(cChannel *channel) {
+	this->channel = channel;
+}
diff --git a/timers.h b/timers.h
index 8f67add..846b4c0 100644
--- a/timers.h
+++ b/timers.h
@@ -92,6 +92,7 @@ public:
   void Skip(void);
   void OnOff(void);
   cString PrintFirstDay(void) const;
+  void SetChannel(cChannel *channel);
   static int TimeToInt(int t);
   static bool ParseDay(const char *s, time_t &Day, int &WeekDays);
   static cString PrintDay(time_t Day, int WeekDays, bool SingleByteChars);
diff --git a/vdr.c b/vdr.c
index 93f586a..ed54c79 100644
--- a/vdr.c
+++ b/vdr.c
@@ -747,9 +747,10 @@ int main(int argc, char *argv[])
         if (!EITScanner.Active() && cDevice::PrimaryDevice()->HasDecoder() && !cDevice::PrimaryDevice()->HasProgramme()) {
            static time_t lastTime = 0;
            if ((!Menu || CheckHasProgramme) && Now - lastTime > MINCHANNELWAIT) { // !Menu to avoid interfering with the CAM if a CAM menu is open
-              cChannel *Channel = Channels.GetByNumber(cDevice::CurrentChannel());
+              cChannel *Channel = Channels.GetByNumber(cDevice::CurrentChannelConfig().selected());
               if (Channel && (Channel->Vpid() || Channel->Apid(0))) {
-                 if (!Channels.SwitchTo(cDevice::CurrentChannel()) // try to switch to the original channel...
+                 /// TODO: search for an alternative
+                 if (!Channels.SwitchTo(Channel->Number()) // try to switch to the original channel...
                      && !(LastTimerChannel > 0 && Channels.SwitchTo(LastTimerChannel))) // ...or the one used by the last timer...
                     ;
                  }
@@ -795,7 +796,7 @@ int main(int argc, char *argv[])
               for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
                   if (Channel->Modification(CHANNELMOD_RETUNE)) {
                      cRecordControls::ChannelDataModified(Channel);
-                     if (Channel->Number() == cDevice::CurrentChannel()) {
+                     if (Channel->Number() == cDevice::CurrentChannelConfig().receiving()) {
                         if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) {
                            if (cDevice::ActualDevice()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder
                               isyslog("retuning due to modification of channel %d", Channel->Number());
@@ -809,10 +810,10 @@ int main(int argc, char *argv[])
               }
            }
         // Channel display:
-        if (!EITScanner.Active() && cDevice::CurrentChannel() != LastChannel) {
+        if (!EITScanner.Active() && cDevice::CurrentChannelConfig().selected() != LastChannel) {
            if (!Menu)
-              Menu = new cDisplayChannel(cDevice::CurrentChannel(), LastChannel >= 0);
-           LastChannel = cDevice::CurrentChannel();
+              Menu = new cDisplayChannel(cDevice::CurrentChannelConfig().selected(), cDevice::CurrentChannelConfig().receiving(), LastChannel >= 0);
+           LastChannel = cDevice::CurrentChannelConfig().selected();
            LastChannelChanged = Now;
            }
         if (Now - LastChannelChanged >= Setup.ZapTimeout && LastChannel != PreviousChannel[PreviousChannelIndex])
@@ -903,7 +904,8 @@ int main(int argc, char *argv[])
                         if (cDevice::PrimaryDevice()->HasDecoder() && !cDevice::PrimaryDevice()->HasProgramme()) {
                            // the previous SwitchChannel() has switched away the current live channel
                            cDevice::SetAvoidDevice(Device);
-                           if (!Channels.SwitchTo(cDevice::CurrentChannel())) // try to switch to the original channel on a different device...
+                           /// TODO: search for an alternative
+                           if (!Channels.SwitchTo(cDevice::CurrentChannelConfig().selected())) // try to switch to the original channel on a different device...
                               Channels.SwitchTo(Timer->Channel()->Number()); // ...or avoid toggling between old channel and black screen
                            Skins.Message(mtInfo, tr("Upcoming recording!"));
                            }
@@ -1306,7 +1308,7 @@ Exit:
   Skins.Clear();
   SourceParams.Clear();
   if (ShutdownHandler.GetExitCode() != 2) {
-     Setup.CurrentChannel = cDevice::CurrentChannel();
+     Setup.CurrentChannel = cDevice::CurrentChannelConfig().selected();
      Setup.CurrentVolume  = cDevice::CurrentVolume();
      Setup.Save();
      }
