--- channels.c.cfilter	2007-08-29 19:12:29.528179000 +0200
+++ channels.c	2007-08-29 19:12:29.578179000 +0200
@@ -857,6 +857,15 @@
     }
   };
 
+bool cChannel::Filtered(void)
+{
+  switch(Setup.ChannelFilter) {
+    case 1:    return (groupSep || vpid != 0);
+    case 2:    return (groupSep || vpid == 0);
+    default:   return true;
+  } 
+}
+
 // -- cChannels --------------------------------------------------------------
 
 cChannels Channels;
--- channels.h.cfilter	2007-08-29 19:12:29.538179000 +0200
+++ channels.h	2007-08-29 19:12:29.578179000 +0200
@@ -218,6 +218,7 @@
   void SetLinkChannels(cLinkChannels *LinkChannels);
   void SetRefChannel(cChannel *RefChannel);
   void SetGroupSep(bool Sep = true);
+  bool Filtered(void);
   };
 
 class cChannels : public cRwLock, public cConfig<cChannel> {
--- config.c.cfilter	2007-08-12 14:09:37.000000000 +0200
+++ config.c	2007-08-29 19:12:29.588179000 +0200
@@ -282,6 +282,7 @@
   CurrentChannel = -1;
   CurrentVolume = MAXVOLUME;
   CurrentDolby = 0;
+  ChannelFilter = 0;
   InitialChannel = 0;
   InitialVolume = -1;
 }
@@ -452,6 +453,7 @@
   else if (!strcasecmp(Name, "CurrentChannel"))      CurrentChannel     = atoi(Value);
   else if (!strcasecmp(Name, "CurrentVolume"))       CurrentVolume      = atoi(Value);
   else if (!strcasecmp(Name, "CurrentDolby"))        CurrentDolby       = atoi(Value);
+  else if (!strcasecmp(Name, "ChannelFilter"))       ChannelFilter      = atoi(Value);
   else if (!strcasecmp(Name, "InitialChannel"))      InitialChannel     = atoi(Value);
   else if (!strcasecmp(Name, "InitialVolume"))       InitialVolume      = atoi(Value);
   else
@@ -529,6 +531,7 @@
   Store("CurrentChannel",     CurrentChannel);
   Store("CurrentVolume",      CurrentVolume);
   Store("CurrentDolby",       CurrentDolby);
+  Store("ChannelFilter",      ChannelFilter);
   Store("InitialChannel",     InitialChannel);
   Store("InitialVolume",      InitialVolume);
 
--- config.h.cfilter	2007-08-19 18:02:50.000000000 +0200
+++ config.h	2007-08-29 19:12:29.588179000 +0200
@@ -260,6 +260,7 @@
   int CurrentChannel;
   int CurrentVolume;
   int CurrentDolby;
+  int ChannelFilter;
   int InitialChannel;
   int InitialVolume;
   int __EndData__;
--- device.c.cfilter	2007-08-29 19:12:29.378179000 +0200
+++ device.c	2007-08-29 19:12:29.608179000 +0200
@@ -653,7 +653,7 @@
      cChannel *channel;
      while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
            // try only channels which are currently available
-           if (GetDevice(channel, 0, true))
+           if (channel->Filtered() && GetDevice(channel, 0, true))
               break;
            n = channel->Number() + Direction;
            }
--- menu.c.cfilter	2007-08-29 19:12:29.428179000 +0200
+++ menu.c	2007-09-02 16:29:03.053652000 +0200
@@ -325,14 +325,14 @@
 
 class cMenuChannelItem : public cOsdItem {
 public:
-  enum eChannelSortMode { csmNumber, csmName, csmProvider };
+  enum eChannelSortMode { csmNumber, csmName, csmProvider, csmSourceNumber, csmSourceName, csmSourceProvider };
 private:
   static eChannelSortMode sortMode;
   cChannel *channel;
 public:
   cMenuChannelItem(cChannel *Channel);
   static void SetSortMode(eChannelSortMode SortMode) { sortMode = SortMode; }
-  static void IncSortMode(void) { sortMode = eChannelSortMode((sortMode == csmProvider) ? csmNumber : sortMode + 1); }
+  static void IncSortMode(void) { sortMode = eChannelSortMode((sortMode == csmSourceProvider) ? csmNumber : sortMode + 1); }
   static eChannelSortMode SortMode(void) { return sortMode; }
   virtual int Compare(const cListObject &ListObject) const;
   virtual void Set(void);
@@ -349,10 +349,42 @@
   Set();
 }
 
+int snum(int source)
+{
+  int stype = (source & cSource::st_Mask);
+  // arbitrary order: sat, cable, terrestrial, none
+  int r;
+  switch(stype) {
+    case cSource::stCable: 
+      r=0x7FF0;
+      break;
+    case cSource::stTerr:
+      r=0x7FF2;
+      break;
+    case cSource::stSat: 
+      r=source & cSource::st_Pos;
+      if (source & cSource::st_Neg) r*=-1;
+      break;
+    default:  //stNone or unknown
+      r=0x7FFF;  
+  }
+  return r;    
+}
+
 int cMenuChannelItem::Compare(const cListObject &ListObject) const
 {
   cMenuChannelItem *p = (cMenuChannelItem *)&ListObject;
   int r = -1;
+  if (sortMode >= csmSourceNumber) {
+     int rsource = snum(channel->Source()) - snum(p->channel->Source());
+     if (sortMode == csmSourceProvider && rsource  == 0)
+        r = strcoll(channel->Provider(), p->channel->Provider());
+     if ((sortMode == csmSourceName || r == 0) && rsource == 0)
+        r = strcoll(channel->Name(), p->channel->Name());
+     if ((sortMode == csmSourceNumber || r == 0) && rsource == 0)
+        r = channel->Number() - p->channel->Number();
+     return ((rsource == 0) ? r : rsource);
+  }
   if (sortMode == csmProvider)
      r = strcoll(channel->Provider(), p->channel->Provider());
   if (sortMode == csmName || r == 0)
@@ -366,10 +398,10 @@
 {
   char *buffer = NULL;
   if (!channel->GroupSep()) {
-     if (sortMode == csmProvider)
-        asprintf(&buffer, "%d\t%s - %s", channel->Number(), channel->Provider(), channel->Name());
+     if (sortMode == csmProvider || sortMode == csmSourceProvider)
+        asprintf(&buffer, "%d\t%s %c %s - %s", channel->Number(), *cSource::ToString(channel->Source()), (sortMode >= csmSourceNumber) ? '*' : '-', channel->Provider(), channel->Name());
      else
-        asprintf(&buffer, "%d\t%s", channel->Number(), channel->Name());
+        asprintf(&buffer, "%d\t%s %c %s", channel->Number(), *cSource::ToString(channel->Source()), (sortMode >= csmSourceNumber) ? '*' : '-', channel->Name());
      }
   else
      asprintf(&buffer, "---\t%s ----------------------------------------------------------------", channel->Name());
@@ -421,7 +453,7 @@
   cMenuChannelItem *currentItem = NULL;
   Clear();
   for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
-      if (!channel->GroupSep() || cMenuChannelItem::SortMode() == cMenuChannelItem::csmNumber && *channel->Name()) {
+      if ((!channel->GroupSep() || cMenuChannelItem::SortMode() == cMenuChannelItem::csmNumber && *channel->Name()) && ( channel == currentChannel || channel->Filtered() )) {
          cMenuChannelItem *item = new cMenuChannelItem(channel);
          Add(item);
          if (channel == currentChannel)
@@ -432,6 +464,16 @@
      Sort();
   SetCurrent(currentItem);
   SetHelp(tr("Button$Edit"), tr("Button$New"), tr("Button$Delete"), tr("Button$Mark"));
+  char *buffer = NULL;
+  switch(::Setup.ChannelFilter) {
+    case 1: asprintf(&buffer, "%s (%s)", tr("Channels"),tr("Tv only"));
+            break;
+    case 2: asprintf(&buffer, "%s (%s)", tr("Channels"),tr("Radio only"));
+            break;
+    default:  asprintf(&buffer, "%s", tr("Channels"));        
+  }
+  SetTitle(buffer);
+  free(buffer);
   Display();
 }
 
@@ -2704,6 +2746,8 @@
 // --- cMenuSetupMisc --------------------------------------------------------
 
 class cMenuSetupMisc : public cMenuSetupBase {
+private:
+  const char *channelFilterTexts[3];
 public:
   cMenuSetupMisc(void);
   };
@@ -2711,10 +2755,14 @@
 cMenuSetupMisc::cMenuSetupMisc(void)
 {
   SetSection(tr("Miscellaneous"));
+ channelFilterTexts[0] = tr("no");
+ channelFilterTexts[1] = tr("Tv only");
+ channelFilterTexts[2] = tr("Radio only");
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. event timeout (min)"),   &data.MinEventTimeout));
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. user inactivity (min)"), &data.MinUserInactivity));
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"),          &data.SVDRPTimeout));
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Zap timeout (s)"),            &data.ZapTimeout));
+  Add(new cMenuEditStraItem(tr("Setup.Miscellaneous$Filter channels"),             &data.ChannelFilter, 3, channelFilterTexts));;    
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Channel entry timeout (ms)"), &data.ChannelEntryTimeout, 0));
   Add(new cMenuEditChanItem(tr("Setup.Miscellaneous$Initial channel"),            &data.InitialChannel, tr("Setup.Miscellaneous$as before")));
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Initial volume"),             &data.InitialVolume, -1, 255, tr("Setup.Miscellaneous$as before")));
@@ -3227,7 +3275,7 @@
   if (Direction) {
      while (Channel) {
            Channel = Direction > 0 ? Channels.Next(Channel) : Channels.Prev(Channel);
-           if (Channel && !Channel->GroupSep() && cDevice::GetDevice(Channel, 0, true))
+           if (Channel && Channel->Filtered() && !Channel->GroupSep() && cDevice::GetDevice(Channel, 0, true))
               return Channel;
            }
      }
