diff -Naur vdr-1.4.0-noEIT/channels.c vdr-1.4.0/channels.c
--- vdr-1.4.0-noEIT/channels.c	2006-01-14 10:51:02.000000000 -0500
+++ vdr-1.4.0/channels.c	2006-05-07 18:50:25.000000000 -0500
@@ -970,7 +970,7 @@
   return NULL;
 }
 
-cChannel *cChannels::GetByChannelID(tChannelID ChannelID, bool TryWithoutRid, bool TryWithoutPolarization)
+cChannel *cChannels::GetByChannelID(tChannelID ChannelID, bool TryWithoutRid, bool TryWithoutPolarization, bool TryWithoutSource)
 {
   int sid = ChannelID.Sid();
   cList<cHashObject> *list = channelsHashSid.GetList(sid);
@@ -980,6 +980,13 @@
          if (channel->Sid() == sid && channel->GetChannelID() == ChannelID)
             return channel;
          }
+  if (TryWithoutSource) {
+     ChannelID.ClrSource();
+     for (cChannel *channel = First(); channel; channel = Next(channel)) {
+         if (!channel->GroupSep() && channel->GetChannelID().ClrSource() == ChannelID)
+            return channel;
+         }
+     }
      if (TryWithoutRid) {
         ChannelID.ClrRid();
         for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
diff -Naur vdr-1.4.0-noEIT/channels.c.orig vdr-1.4.0/channels.c.orig
--- vdr-1.4.0-noEIT/channels.c.orig	1969-12-31 19:00:00.000000000 -0500
+++ vdr-1.4.0/channels.c.orig	2006-01-14 10:51:02.000000000 -0500
@@ -0,0 +1,1047 @@
+/*
+ * channels.c: Channel handling
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: channels.c 1.48 2006/01/14 15:51:02 kls Exp $
+ */
+
+#include "channels.h"
+#include <linux/dvb/frontend.h>
+#include <ctype.h>
+#include "device.h"
+#include "epg.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
+// value!
+
+// -- Channel Parameter Maps -------------------------------------------------
+
+const tChannelParameterMap InversionValues[] = {
+  {   0, INVERSION_OFF },
+  {   1, INVERSION_ON },
+  { 999, INVERSION_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap BandwidthValues[] = {
+  {   6, BANDWIDTH_6_MHZ },
+  {   7, BANDWIDTH_7_MHZ },
+  {   8, BANDWIDTH_8_MHZ },
+  { 999, BANDWIDTH_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap CoderateValues[] = {
+  {   0, FEC_NONE },
+  {  12, FEC_1_2 },
+  {  23, FEC_2_3 },
+  {  34, FEC_3_4 },
+  {  45, FEC_4_5 },
+  {  56, FEC_5_6 },
+  {  67, FEC_6_7 },
+  {  78, FEC_7_8 },
+  {  89, FEC_8_9 },
+  { 999, FEC_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap ModulationValues[] = {
+  {   0, QPSK },
+  {  16, QAM_16 },
+  {  32, QAM_32 },
+  {  64, QAM_64 },
+  { 128, QAM_128 },
+  { 256, QAM_256 },
+  { 999, QAM_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap TransmissionValues[] = {
+  {   2, TRANSMISSION_MODE_2K },
+  {   8, TRANSMISSION_MODE_8K },
+  { 999, TRANSMISSION_MODE_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap GuardValues[] = {
+  {   4, GUARD_INTERVAL_1_4 },
+  {   8, GUARD_INTERVAL_1_8 },
+  {  16, GUARD_INTERVAL_1_16 },
+  {  32, GUARD_INTERVAL_1_32 },
+  { 999, GUARD_INTERVAL_AUTO },
+  { -1 }
+  };
+
+const tChannelParameterMap HierarchyValues[] = {
+  {   0, HIERARCHY_NONE },
+  {   1, HIERARCHY_1 },
+  {   2, HIERARCHY_2 },
+  {   4, HIERARCHY_4 },
+  { 999, HIERARCHY_AUTO },
+  { -1 }
+  };
+
+int UserIndex(int Value, const tChannelParameterMap *Map)
+{
+  const tChannelParameterMap *map = Map;
+  while (map && map->userValue != -1) {
+        if (map->userValue == Value)
+           return map - Map;
+        map++;
+        }
+  return -1;
+}
+
+int DriverIndex(int Value, const tChannelParameterMap *Map)
+{
+  const tChannelParameterMap *map = Map;
+  while (map && map->userValue != -1) {
+        if (map->driverValue == Value)
+           return map - Map;
+        map++;
+        }
+  return -1;
+}
+
+int MapToUser(int Value, const tChannelParameterMap *Map)
+{
+  int n = DriverIndex(Value, Map);
+  if (n >= 0)
+     return Map[n].userValue;
+  return -1;
+}
+
+int MapToDriver(int Value, const tChannelParameterMap *Map)
+{
+  int n = UserIndex(Value, Map);
+  if (n >= 0)
+     return Map[n].driverValue;
+  return -1;
+}
+
+// -- tChannelID -------------------------------------------------------------
+
+const tChannelID tChannelID::InvalidID;
+
+tChannelID tChannelID::FromString(const char *s)
+{
+  char *sourcebuf = NULL;
+  int nid;
+  int tid;
+  int sid;
+  int rid = 0;
+  int fields = sscanf(s, "%a[^-]-%d-%d-%d-%d", &sourcebuf, &nid, &tid, &sid, &rid);
+  if (fields == 4 || fields == 5) {
+     int source = cSource::FromString(sourcebuf);
+     free(sourcebuf);
+     if (source >= 0)
+        return tChannelID(source, nid, tid, sid, rid);
+     }
+  return tChannelID::InvalidID;
+}
+
+cString tChannelID::ToString(void) const
+{
+  char buffer[256];
+  snprintf(buffer, sizeof(buffer), rid ? "%s-%d-%d-%d-%d" : "%s-%d-%d-%d", *cSource::ToString(source), nid, tid, sid, rid);
+  return buffer;
+}
+
+tChannelID &tChannelID::ClrPolarization(void)
+{
+  while (tid > 100000)
+        tid -= 100000;
+  return *this;
+}
+
+// -- cChannel ---------------------------------------------------------------
+
+cChannel::cChannel(void)
+{
+  name = strdup("");
+  shortName = strdup("");
+  provider = strdup("");
+  portalName = strdup("");
+  memset(&__BeginData__, 0, (char *)&__EndData__ - (char *)&__BeginData__);
+  inversion    = INVERSION_AUTO;
+  bandwidth    = BANDWIDTH_AUTO;
+  coderateH    = FEC_AUTO;
+  coderateL    = FEC_AUTO;
+  modulation   = QAM_AUTO;
+  transmission = TRANSMISSION_MODE_AUTO;
+  guard        = GUARD_INTERVAL_AUTO;
+  hierarchy    = HIERARCHY_AUTO;
+  modification = CHANNELMOD_NONE;
+  schedule     = NULL;
+  linkChannels = NULL;
+  refChannel   = NULL;
+}
+
+cChannel::cChannel(const cChannel &Channel)
+{
+  name = NULL;
+  shortName = NULL;
+  provider = NULL;
+  portalName = NULL;
+  schedule     = NULL;
+  linkChannels = NULL;
+  refChannel   = NULL;
+  *this = Channel;
+}
+
+cChannel::~cChannel()
+{
+  delete linkChannels;
+  linkChannels = NULL; // more than one channel can link to this one, so we need the following loop
+  for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
+      if (Channel->linkChannels) {
+         for (cLinkChannel *lc = Channel->linkChannels->First(); lc; lc = Channel->linkChannels->Next(lc)) {
+             if (lc->Channel() == this) {
+                Channel->linkChannels->Del(lc);
+                break;
+                }
+             }
+         if (Channel->linkChannels->Count() == 0) {
+            delete Channel->linkChannels;
+            Channel->linkChannels = NULL;
+            }
+         }
+      }
+  free(name);
+  free(shortName);
+  free(provider);
+  free(portalName);
+}
+
+cChannel& cChannel::operator= (const cChannel &Channel)
+{
+  name = strcpyrealloc(name, Channel.name);
+  shortName = strcpyrealloc(shortName, Channel.shortName);
+  provider = strcpyrealloc(provider, Channel.provider);
+  portalName = strcpyrealloc(portalName, Channel.portalName);
+  memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__);
+  return *this;
+}
+
+int cChannel::Transponder(int Frequency, char Polarization)
+{
+  // some satellites have transponders at the same frequency, just with different polarization:
+  switch (tolower(Polarization)) {
+    case 'h': Frequency += 100000; break;
+    case 'v': Frequency += 200000; break;
+    case 'l': Frequency += 300000; break;
+    case 'r': Frequency += 400000; break;
+    }
+  return Frequency;
+}
+
+int cChannel::Transponder(void) const
+{
+  int tf = frequency;
+  while (tf > 20000)
+        tf /= 1000;
+  if (IsSat())
+     tf = Transponder(tf, polarization);
+  return tf;
+}
+
+int cChannel::Modification(int Mask)
+{
+  int Result = modification & Mask;
+  modification = CHANNELMOD_NONE;
+  return Result;
+}
+
+void cChannel::CopyTransponderData(const cChannel *Channel)
+{
+  if (Channel) {
+     frequency    = Channel->frequency;
+     source       = Channel->source;
+     srate        = Channel->srate;
+     polarization = Channel->polarization;
+     inversion    = Channel->inversion;
+     bandwidth    = Channel->bandwidth;
+     coderateH    = Channel->coderateH;
+     coderateL    = Channel->coderateL;
+     modulation   = Channel->modulation;
+     transmission = Channel->transmission;
+     guard        = Channel->guard;
+     hierarchy    = Channel->hierarchy;
+     }
+}
+
+bool cChannel::SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH)
+{
+  // Workarounds for broadcaster stupidity:
+  // Some providers broadcast the transponder frequency of their channels with two different
+  // values (like 12551 and 12552), so we need to allow for a little tolerance here
+  if (abs(frequency - Frequency) <= 1)
+     Frequency = frequency;
+  // Sometimes the transponder frequency is set to 0, which is just wrong
+  if (Frequency == 0)
+     return false;
+
+  if (source != Source || frequency != Frequency || polarization != Polarization || srate != Srate || coderateH != CoderateH) {
+     if (Number()) {
+        dsyslog("changing transponder data of channel %d from %s:%d:%c:%d:%d to %s:%d:%c:%d:%d", Number(), *cSource::ToString(source), frequency, polarization, srate, coderateH, *cSource::ToString(Source), Frequency, Polarization, Srate, CoderateH);
+        modification |= CHANNELMOD_TRANSP;
+        Channels.SetModified();
+        }
+     source = Source;
+     frequency = Frequency;
+     polarization = Polarization;
+     srate = Srate;
+     coderateH = CoderateH;
+     modulation = QPSK;
+     schedule = NULL;
+     }
+  return true;
+}
+
+bool cChannel::SetCableTransponderData(int Source, int Frequency, int Modulation, int Srate, int CoderateH)
+{
+  if (source != Source || frequency != Frequency || modulation != Modulation || srate != Srate || coderateH != CoderateH) {
+     if (Number()) {
+        dsyslog("changing transponder data of channel %d from %s:%d:%d:%d:%d to %s:%d:%d:%d:%d", Number(), *cSource::ToString(source), frequency, modulation, srate, coderateH, *cSource::ToString(Source), Frequency, Modulation, Srate, CoderateH);
+        modification |= CHANNELMOD_TRANSP;
+        Channels.SetModified();
+        }
+     source = Source;
+     frequency = Frequency;
+     modulation = Modulation;
+     srate = Srate;
+     coderateH = CoderateH;
+     schedule = NULL;
+     }
+  return true;
+}
+
+bool cChannel::SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CoderateH, int CoderateL, int Guard, int Transmission)
+{
+  if (source != Source || frequency != Frequency || bandwidth != Bandwidth || modulation != Modulation || hierarchy != Hierarchy || coderateH != CoderateH || coderateL != CoderateL || guard != Guard || transmission != Transmission) {
+     if (Number()) {
+        dsyslog("changing transponder data of channel %d from %s:%d:%d:%d:%d:%d:%d:%d:%d to %s:%d:%d:%d:%d:%d:%d:%d:%d", Number(), *cSource::ToString(source), frequency, bandwidth, modulation, hierarchy, coderateH, coderateL, guard, transmission, *cSource::ToString(Source), Frequency, Bandwidth, Modulation, Hierarchy, CoderateH, CoderateL, Guard, Transmission);
+        modification |= CHANNELMOD_TRANSP;
+        Channels.SetModified();
+        }
+     source = Source;
+     frequency = Frequency;
+     bandwidth = Bandwidth;
+     modulation = Modulation;
+     hierarchy = Hierarchy;
+     coderateH = CoderateH;
+     coderateL = CoderateL;
+     guard = Guard;
+     transmission = Transmission;
+     schedule = NULL;
+     }
+  return true;
+}
+
+void cChannel::SetId(int Nid, int Tid, int Sid, int Rid)
+{
+  if (nid != Nid || tid != Tid || sid != Sid || rid != Rid) {
+     if (Number()) {
+        dsyslog("changing id of channel %d from %d-%d-%d-%d to %d-%d-%d-%d", Number(), nid, tid, sid, rid, Nid, Tid, Sid, Rid);
+        modification |= CHANNELMOD_ID;
+        Channels.SetModified();
+        Channels.UnhashChannel(this);
+        }
+     nid = Nid;
+     tid = Tid;
+     sid = Sid;
+     rid = Rid;
+     if (Number())
+        Channels.HashChannel(this);
+     schedule = NULL;
+     }
+}
+
+void cChannel::SetName(const char *Name, const char *ShortName, const char *Provider)
+{
+  if (!isempty(Name)) {
+     bool nn = strcmp(name, Name) != 0;
+     bool ns = strcmp(shortName, ShortName) != 0;
+     bool np = strcmp(provider, Provider) != 0;
+     if (nn || ns || np) {
+        if (Number()) {
+           dsyslog("changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider);
+           modification |= CHANNELMOD_NAME;
+           Channels.SetModified();
+           }
+        if (nn)
+           name = strcpyrealloc(name, Name);
+        if (ns)
+           shortName = strcpyrealloc(shortName, ShortName);
+        if (np)
+           provider = strcpyrealloc(provider, Provider);
+        }
+     }
+}
+
+void cChannel::SetPortalName(const char *PortalName)
+{
+  if (!isempty(PortalName) && strcmp(portalName, PortalName) != 0) {
+     if (Number()) {
+        dsyslog("changing portal name of channel %d from '%s' to '%s'", Number(), portalName, PortalName);
+        modification |= CHANNELMOD_NAME;
+        Channels.SetModified();
+        }
+     portalName = strcpyrealloc(portalName, PortalName);
+     }
+}
+
+#define STRDIFF 0x01
+#define VALDIFF 0x02
+
+static int IntArraysDiffer(const int *a, const int *b, const char na[][MAXLANGCODE2] = NULL, const char nb[][MAXLANGCODE2] = NULL)
+{
+  int result = 0;
+  for (int i = 0; a[i] || b[i]; i++) {
+      if (a[i] && na && nb && strcmp(na[i], nb[i]) != 0)
+         result |= STRDIFF;
+      if (a[i] != b[i])
+         result |= VALDIFF;
+      if (!a[i] || !b[i])
+         break;
+      }
+  return result;
+}
+
+static int IntArrayToString(char *s, const int *a, int Base = 10, const char n[][MAXLANGCODE2] = NULL)
+{
+  char *q = s;
+  int i = 0;
+  while (a[i] || i == 0) {
+        q += sprintf(q, Base == 16 ? "%s%X" : "%s%d", i ? "," : "", a[i]);
+        if (a[i] && n && *n[i])
+           q += sprintf(q, "=%s", n[i]);
+        if (!a[i])
+           break;
+        i++;
+        }
+  *q = 0;
+  return q - s;
+}
+
+void cChannel::SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][MAXLANGCODE2], int *Dpids, char DLangs[][MAXLANGCODE2], int Tpid)
+{
+  int mod = CHANNELMOD_NONE;
+  if (vpid != Vpid || ppid != Ppid || tpid != Tpid)
+     mod |= CHANNELMOD_PIDS;
+  int m = IntArraysDiffer(apids, Apids, alangs, ALangs) | IntArraysDiffer(dpids, Dpids, dlangs, DLangs);
+  if (m & STRDIFF)
+     mod |= CHANNELMOD_LANGS;
+  if (m & VALDIFF)
+     mod |= CHANNELMOD_PIDS;
+  if (mod) {
+     const int BufferSize = (MAXAPIDS + MAXDPIDS) * (5 + 1 + MAXLANGCODE2) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia
+     char OldApidsBuf[BufferSize];
+     char NewApidsBuf[BufferSize];
+     char *q = OldApidsBuf;
+     q += IntArrayToString(q, apids, 10, alangs);
+     if (dpids[0]) {
+        *q++ = ';';
+        q += IntArrayToString(q, dpids, 10, dlangs);
+        }
+     *q = 0;
+     q = NewApidsBuf;
+     q += IntArrayToString(q, Apids, 10, ALangs);
+     if (Dpids[0]) {
+        *q++ = ';';
+        q += IntArrayToString(q, Dpids, 10, DLangs);
+        }
+     *q = 0;
+     dsyslog("changing pids of channel %d from %d+%d:%s:%d to %d+%d:%s:%d", Number(), vpid, ppid, OldApidsBuf, tpid, Vpid, Ppid, NewApidsBuf, Tpid);
+     vpid = Vpid;
+     ppid = Ppid;
+     for (int i = 0; i < MAXAPIDS; i++) {
+         apids[i] = Apids[i];
+         strn0cpy(alangs[i], ALangs[i], MAXLANGCODE2);
+         }
+     apids[MAXAPIDS] = 0;
+     for (int i = 0; i < MAXDPIDS; i++) {
+         dpids[i] = Dpids[i];
+         strn0cpy(dlangs[i], DLangs[i], MAXLANGCODE2);
+         }
+     dpids[MAXDPIDS] = 0;
+     tpid = Tpid;
+     modification |= mod;
+     Channels.SetModified();
+     }
+}
+
+void cChannel::SetCaIds(const int *CaIds)
+{
+  if (caids[0] && caids[0] <= 0x00FF)
+     return; // special values will not be overwritten
+  if (IntArraysDiffer(caids, CaIds)) {
+     char OldCaIdsBuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia
+     char NewCaIdsBuf[MAXCAIDS * 5 + 10];
+     IntArrayToString(OldCaIdsBuf, caids, 16);
+     IntArrayToString(NewCaIdsBuf, CaIds, 16);
+     dsyslog("changing caids of channel %d from %s to %s", Number(), OldCaIdsBuf, NewCaIdsBuf);
+     for (int i = 0; i <= MAXCAIDS; i++) { // <= to copy the terminating 0
+         caids[i] = CaIds[i];
+         if (!CaIds[i])
+            break;
+         }
+     modification |= CHANNELMOD_CA;
+     Channels.SetModified();
+     }
+}
+
+void cChannel::SetCaDescriptors(int Level)
+{
+  if (Level > 0) {
+     modification |= CHANNELMOD_CA;
+     Channels.SetModified();
+     if (Level > 1)
+        dsyslog("changing ca descriptors of channel %d", Number());
+     }
+}
+
+void cChannel::SetLinkChannels(cLinkChannels *LinkChannels)
+{
+  if (!linkChannels && !LinkChannels)
+     return;
+  if (linkChannels && LinkChannels) {
+     cLinkChannel *lca = linkChannels->First();
+     cLinkChannel *lcb = LinkChannels->First();
+     while (lca && lcb) {
+           if (lca->Channel() != lcb->Channel()) {
+              lca = NULL;
+              break;
+              }
+           lca = linkChannels->Next(lca);
+           lcb = LinkChannels->Next(lcb);
+           }
+     if (!lca && !lcb) {
+        delete LinkChannels;
+        return; // linkage has not changed
+        }
+     }
+  char buffer[((linkChannels ? linkChannels->Count() : 0) + (LinkChannels ? LinkChannels->Count() : 0)) * 6 + 256]; // 6: 5 digit channel number plus blank, 256: other texts (see below) plus reserve
+  char *q = buffer;
+  q += sprintf(q, "linking channel %d from", Number());
+  if (linkChannels) {
+     for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
+         lc->Channel()->SetRefChannel(NULL);
+         q += sprintf(q, " %d", lc->Channel()->Number());
+         }
+     delete linkChannels;
+     }
+  else
+     q += sprintf(q, " none");
+  q += sprintf(q, " to");
+  linkChannels = LinkChannels;
+  if (linkChannels) {
+     for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
+         lc->Channel()->SetRefChannel(this);
+         q += sprintf(q, " %d", lc->Channel()->Number());
+         //dsyslog("link %4d -> %4d: %s", Number(), lc->Channel()->Number(), lc->Channel()->Name());
+         }
+     }
+  else
+     q += sprintf(q, " none");
+  dsyslog(buffer);
+}
+
+void cChannel::SetRefChannel(cChannel *RefChannel)
+{
+  refChannel = RefChannel;
+}
+
+static int PrintParameter(char *p, char Name, int Value)
+{
+  return Value >= 0 && Value != 999 ? sprintf(p, "%c%d", Name, Value) : 0;
+}
+
+cString cChannel::ParametersToString(void) const
+{
+  char type = **cSource::ToString(source);
+  if (isdigit(type))
+     type = 'S';
+#define ST(s) if (strchr(s, type))
+  char buffer[64];
+  char *q = buffer;
+  *q = 0;
+  ST(" S ")  q += sprintf(q, "%c", polarization);
+  ST("CST")  q += PrintParameter(q, 'I', MapToUser(inversion, InversionValues));
+  ST("CST")  q += PrintParameter(q, 'C', MapToUser(coderateH, CoderateValues));
+  ST("  T")  q += PrintParameter(q, 'D', MapToUser(coderateL, CoderateValues));
+  ST("C T")  q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
+  ST("  T")  q += PrintParameter(q, 'B', MapToUser(bandwidth, BandwidthValues));
+  ST("  T")  q += PrintParameter(q, 'T', MapToUser(transmission, TransmissionValues));
+  ST("  T")  q += PrintParameter(q, 'G', MapToUser(guard, GuardValues));
+  ST("  T")  q += PrintParameter(q, 'Y', MapToUser(hierarchy, HierarchyValues));
+  return buffer;
+}
+
+static const char *ParseParameter(const char *s, int &Value, const tChannelParameterMap *Map)
+{
+  if (*++s) {
+     char *p = NULL;
+     errno = 0;
+     int n = strtol(s, &p, 10);
+     if (!errno && p != s) {
+        Value = MapToDriver(n, Map);
+        if (Value >= 0)
+           return p;
+        }
+     }
+  esyslog("ERROR: invalid value for parameter '%c'", *(s - 1));
+  return NULL;
+}
+
+bool cChannel::StringToParameters(const char *s)
+{
+  while (s && *s) {
+        switch (toupper(*s)) {
+          case 'B': s = ParseParameter(s, bandwidth, BandwidthValues); break;
+          case 'C': s = ParseParameter(s, coderateH, CoderateValues); break;
+          case 'D': s = ParseParameter(s, coderateL, CoderateValues); break;
+          case 'G': s = ParseParameter(s, guard, GuardValues); break;
+          case 'H': polarization = *s++; break;
+          case 'I': s = ParseParameter(s, inversion, InversionValues); break;
+          case 'L': polarization = *s++; break;
+          case 'M': s = ParseParameter(s, modulation, ModulationValues); break;
+          case 'R': polarization = *s++; break;
+          case 'T': s = ParseParameter(s, transmission, TransmissionValues); break;
+          case 'V': polarization = *s++; break;
+          case 'Y': s = ParseParameter(s, hierarchy, HierarchyValues); break;
+          default: esyslog("ERROR: unknown parameter key '%c'", *s);
+                   return false;
+          }
+        }
+  return true;
+}
+
+cString cChannel::ToText(const cChannel *Channel)
+{
+  char FullName[strlen(Channel->name) + 1 + strlen(Channel->shortName) + 1 + strlen(Channel->provider) + 1 + 10]; // +10: paranoia
+  char *q = FullName;
+  q += sprintf(q, "%s", Channel->name);
+  if (!isempty(Channel->shortName))
+     q += sprintf(q, ",%s", Channel->shortName);
+  if (!isempty(Channel->provider))
+     q += sprintf(q, ";%s", Channel->provider);
+  *q = 0;
+  strreplace(FullName, ':', '|');
+  char *buffer;
+  if (Channel->groupSep) {
+     if (Channel->number)
+        asprintf(&buffer, ":@%d %s\n", Channel->number, FullName);
+     else
+        asprintf(&buffer, ":%s\n", FullName);
+     }
+  else {
+     char vpidbuf[32];
+     char *q = vpidbuf;
+     q += snprintf(q, sizeof(vpidbuf), "%d", Channel->vpid);
+     if (Channel->ppid && Channel->ppid != Channel->vpid)
+        q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid);
+     *q = 0;
+     const int BufferSize = (MAXAPIDS + MAXDPIDS) * (5 + 1 + MAXLANGCODE2) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia
+     char apidbuf[BufferSize];
+     q = apidbuf;
+     q += IntArrayToString(q, Channel->apids, 10, Channel->alangs);
+     if (Channel->dpids[0]) {
+        *q++ = ';';
+        q += IntArrayToString(q, Channel->dpids, 10, Channel->dlangs);
+        }
+     *q = 0;
+     char caidbuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia
+     q = caidbuf;
+     q += IntArrayToString(q, Channel->caids, 16);
+     *q = 0;
+     asprintf(&buffer, "%s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d\n", FullName, Channel->frequency, *Channel->ParametersToString(), *cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
+     }
+  return cString(buffer, true);
+}
+
+cString cChannel::ToText(void) const
+{
+  return ToText(this);
+}
+
+bool cChannel::Parse(const char *s)
+{
+  bool ok = true;
+  if (*s == ':') {
+     groupSep = true;
+     if (*++s == '@' && *++s) {
+        char *p = NULL;
+        errno = 0;
+        int n = strtol(s, &p, 10);
+        if (!errno && p != s && n > 0) {
+           number = n;
+           s = p;
+           }
+        }
+     name = strcpyrealloc(name, skipspace(s));
+     strreplace(name, '|', ':');
+     }
+  else {
+     groupSep = false;
+     char *namebuf = NULL;
+     char *sourcebuf = NULL;
+     char *parambuf = NULL;
+     char *vpidbuf = NULL;
+     char *apidbuf = NULL;
+     char *caidbuf = NULL;
+     int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%d :%a[^:]:%d :%d :%d :%d ", &namebuf, &frequency, &parambuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpid, &caidbuf, &sid, &nid, &tid, &rid);
+     if (fields >= 9) {
+        if (fields == 9) {
+           // allow reading of old format
+           sid = atoi(caidbuf);
+           delete caidbuf;
+           caidbuf = NULL;
+           caids[0] = tpid;
+           caids[1] = 0;
+           tpid = 0;
+           }
+        vpid = ppid = 0;
+        apids[0] = 0;
+        dpids[0] = 0;
+        ok = false;
+        if (parambuf && sourcebuf && vpidbuf && apidbuf) {
+           ok = StringToParameters(parambuf) && (source = cSource::FromString(sourcebuf)) >= 0;
+
+           char *p = strchr(vpidbuf, '+');
+           if (p)
+              *p++ = 0;
+           if (sscanf(vpidbuf, "%d", &vpid) != 1)
+              return false;
+           if (p) {
+              if (sscanf(p, "%d", &ppid) != 1)
+                 return false;
+              }
+           else
+              ppid = vpid;
+
+           char *dpidbuf = strchr(apidbuf, ';');
+           if (dpidbuf)
+              *dpidbuf++ = 0;
+           p = apidbuf;
+           char *q;
+           int NumApids = 0;
+           char *strtok_next;
+           while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
+                 if (NumApids < MAXAPIDS) {
+                    char *l = strchr(q, '=');
+                    if (l) {
+                       *l++ = 0;
+                       strn0cpy(alangs[NumApids], l, MAXLANGCODE2);
+                       }
+                    else
+                       *alangs[NumApids] = 0;
+                    apids[NumApids++] = strtol(q, NULL, 10);
+                    }
+                 else
+                    esyslog("ERROR: too many APIDs!"); // no need to set ok to 'false'
+                 p = NULL;
+                 }
+           apids[NumApids] = 0;
+           if (dpidbuf) {
+              char *p = dpidbuf;
+              char *q;
+              int NumDpids = 0;
+              char *strtok_next;
+              while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
+                    if (NumDpids < MAXDPIDS) {
+                       char *l = strchr(q, '=');
+                       if (l) {
+                          *l++ = 0;
+                          strn0cpy(dlangs[NumDpids], l, MAXLANGCODE2);
+                          }
+                       else
+                          *dlangs[NumDpids] = 0;
+                       dpids[NumDpids++] = strtol(q, NULL, 10);
+                       }
+                    else
+                       esyslog("ERROR: too many DPIDs!"); // no need to set ok to 'false'
+                    p = NULL;
+                    }
+              dpids[NumDpids] = 0;
+              }
+
+           if (caidbuf) {
+              char *p = caidbuf;
+              char *q;
+              int NumCaIds = 0;
+              char *strtok_next;
+              while ((q = strtok_r(p, ",", &strtok_next)) != NULL) {
+                    if (NumCaIds < MAXCAIDS) {
+                       caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF;
+                       if (NumCaIds == 1 && caids[0] <= 0x00FF)
+                          break;
+                       }
+                    else
+                       esyslog("ERROR: too many CA ids!"); // no need to set ok to 'false'
+                    p = NULL;
+                    }
+              caids[NumCaIds] = 0;
+              }
+           }
+        strreplace(namebuf, '|', ':');
+
+        char *p = strchr(namebuf, ';');
+        if (p) {
+           *p++ = 0;
+           provider = strcpyrealloc(provider, p);
+           }
+        p = strchr(namebuf, ',');
+        if (p) {
+           *p++ = 0;
+           shortName = strcpyrealloc(shortName, p);
+           }
+        name = strcpyrealloc(name, namebuf);
+
+        free(parambuf);
+        free(sourcebuf);
+        free(vpidbuf);
+        free(apidbuf);
+        free(caidbuf);
+        free(namebuf);
+        if (!GetChannelID().Valid()) {
+           esyslog("ERROR: channel data results in invalid ID!");
+           return false;
+           }
+        }
+     else
+        return false;
+     }
+  return ok;
+}
+
+bool cChannel::Save(FILE *f)
+{
+  return fprintf(f, "%s", *ToText()) > 0;
+}
+
+// -- cChannelSorter ---------------------------------------------------------
+
+class cChannelSorter : public cListObject {
+public:
+  cChannel *channel;
+  tChannelID channelID;
+  cChannelSorter(cChannel *Channel) {
+    channel = Channel;
+    channelID = channel->GetChannelID();
+    }
+  virtual int Compare(const cListObject &ListObject) const {
+    cChannelSorter *cs = (cChannelSorter *)&ListObject;
+    return memcmp(&channelID, &cs->channelID, sizeof(channelID));
+    }
+  };
+
+// -- cChannels --------------------------------------------------------------
+
+cChannels Channels;
+
+cChannels::cChannels(void)
+{
+  maxNumber = 0;
+  modified = CHANNELSMOD_NONE;
+}
+
+void cChannels::DeleteDuplicateChannels(void)
+{
+  cList<cChannelSorter> ChannelSorter;
+  for (cChannel *channel = First(); channel; channel = Next(channel)) {
+      if (!channel->GroupSep())
+         ChannelSorter.Add(new cChannelSorter(channel));
+      }
+  ChannelSorter.Sort();
+  cChannelSorter *cs = ChannelSorter.First();
+  while (cs) {
+        cChannelSorter *next = ChannelSorter.Next(cs);
+        if (next && cs->channelID == next->channelID) {
+           dsyslog("deleting duplicate channel %s", *next->channel->ToText());
+           Del(next->channel);
+           }
+        cs = next;
+        }
+}
+
+bool cChannels::Load(const char *FileName, bool AllowComments, bool MustExist)
+{
+  if (cConfig<cChannel>::Load(FileName, AllowComments, MustExist)) {
+     DeleteDuplicateChannels();
+     ReNumber();
+     return true;
+     }
+  return false;
+}
+
+void cChannels::HashChannel(cChannel *Channel)
+{
+  channelsHashSid.Add(Channel, Channel->Sid());
+}
+
+void cChannels::UnhashChannel(cChannel *Channel)
+{
+  channelsHashSid.Del(Channel, Channel->Sid());
+}
+
+int cChannels::GetNextGroup(int Idx)
+{
+  cChannel *channel = Get(++Idx);
+  while (channel && !(channel->GroupSep() && *channel->Name()))
+        channel = Get(++Idx);
+  return channel ? Idx : -1;
+}
+
+int cChannels::GetPrevGroup(int Idx)
+{
+  cChannel *channel = Get(--Idx);
+  while (channel && !(channel->GroupSep() && *channel->Name()))
+        channel = Get(--Idx);
+  return channel ? Idx : -1;
+}
+
+int cChannels::GetNextNormal(int Idx)
+{
+  cChannel *channel = Get(++Idx);
+  while (channel && channel->GroupSep())
+        channel = Get(++Idx);
+  return channel ? Idx : -1;
+}
+
+void cChannels::ReNumber( void )
+{
+  channelsHashSid.Clear();
+  int Number = 1;
+  for (cChannel *channel = First(); channel; channel = Next(channel)) {
+      if (channel->GroupSep()) {
+         if (channel->Number() > Number)
+            Number = channel->Number();
+         }
+      else {
+         HashChannel(channel);
+         maxNumber = Number;
+         channel->SetNumber(Number++);
+         }
+      }
+}
+
+cChannel *cChannels::GetByNumber(int Number, int SkipGap)
+{
+  cChannel *previous = NULL;
+  for (cChannel *channel = First(); channel; channel = Next(channel)) {
+      if (!channel->GroupSep()) {
+         if (channel->Number() == Number)
+            return channel;
+         else if (SkipGap && channel->Number() > Number)
+            return SkipGap > 0 ? channel : previous;
+         previous = channel;
+         }
+      }
+  return NULL;
+}
+
+cChannel *cChannels::GetByServiceID(int Source, int Transponder, unsigned short ServiceID)
+{
+  cList<cHashObject> *list = channelsHashSid.GetList(ServiceID);
+  if (list) {
+     for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
+         cChannel *channel = (cChannel *)hobj->Object();
+         if (channel->Sid() == ServiceID && channel->Source() == Source && ISTRANSPONDER(channel->Transponder(), Transponder))
+            return channel;
+         }
+     }
+  return NULL;
+}
+
+cChannel *cChannels::GetByChannelID(tChannelID ChannelID, bool TryWithoutRid, bool TryWithoutPolarization)
+{
+  int sid = ChannelID.Sid();
+  cList<cHashObject> *list = channelsHashSid.GetList(sid);
+  if (list) {
+     for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
+         cChannel *channel = (cChannel *)hobj->Object();
+         if (channel->Sid() == sid && channel->GetChannelID() == ChannelID)
+            return channel;
+         }
+     if (TryWithoutRid) {
+        ChannelID.ClrRid();
+        for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
+            cChannel *channel = (cChannel *)hobj->Object();
+            if (channel->Sid() == sid && channel->GetChannelID().ClrRid() == ChannelID)
+               return channel;
+            }
+        }
+     if (TryWithoutPolarization) {
+        ChannelID.ClrPolarization();
+        for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
+            cChannel *channel = (cChannel *)hobj->Object();
+            if (channel->Sid() == sid && channel->GetChannelID().ClrPolarization() == ChannelID)
+               return channel;
+            }
+        }
+     }
+  return NULL;
+}
+
+bool cChannels::HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel)
+{
+  tChannelID NewChannelID = NewChannel->GetChannelID();
+  for (cChannel *channel = First(); channel; channel = Next(channel)) {
+      if (!channel->GroupSep() && channel != OldChannel && channel->GetChannelID() == NewChannelID)
+         return false;
+      }
+  return true;
+}
+
+bool cChannels::SwitchTo(int Number)
+{
+  cChannel *channel = GetByNumber(Number);
+  return channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true);
+}
+
+void cChannels::SetModified(bool ByUser)
+{
+  modified = ByUser ? CHANNELSMOD_USER : !modified ? CHANNELSMOD_AUTO : modified;
+}
+
+int cChannels::Modified(void)
+{
+  int Result = modified;
+  modified = CHANNELSMOD_NONE;
+  return Result;
+}
+
+cChannel *cChannels::NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid)
+{
+  if (Transponder) {
+     dsyslog("creating new channel '%s,%s;%s' on %s transponder %d with id %d-%d-%d-%d", Name, ShortName, Provider, *cSource::ToString(Transponder->Source()), Transponder->Transponder(), Nid, Tid, Sid, Rid);
+     cChannel *NewChannel = new cChannel;
+     NewChannel->CopyTransponderData(Transponder);
+     NewChannel->SetId(Nid, Tid, Sid, Rid);
+     NewChannel->SetName(Name, ShortName, Provider);
+     Add(NewChannel);
+     ReNumber();
+     return NewChannel;
+     }
+  return NULL;
+}
+
+cString ChannelString(const cChannel *Channel, 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());
+     }
+  else if (Number)
+     snprintf(buffer, sizeof(buffer), "%d-", Number);
+  else
+     snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
+  return buffer;
+}
diff -Naur vdr-1.4.0-noEIT/channels.h vdr-1.4.0/channels.h
--- vdr-1.4.0-noEIT/channels.h	2006-02-19 09:39:43.000000000 -0500
+++ vdr-1.4.0/channels.h	2006-05-07 18:50:25.000000000 -0500
@@ -76,8 +76,9 @@
 public:
   tChannelID(void) { source = nid = tid = sid = rid = 0; }
   tChannelID(int Source, int Nid, int Tid, int Sid, int Rid = 0) { source = Source; nid = Nid; tid = Tid; sid = Sid; rid = Rid; }
-  bool operator== (const tChannelID &arg) const { return source == arg.source && nid == arg.nid && tid == arg.tid && sid == arg.sid && rid == arg.rid; }
+  bool operator== (const tChannelID &arg) const { return source == arg.source && nid == arg.nid && tid == arg.tid && sid == arg.sid;} // && rid == arg.rid; }
   bool Valid(void) const { return (nid || tid) && sid; } // rid is optional and source may be 0//XXX source may not be 0???
+  tChannelID &ClrSource(void) { source = 0; return *this; }
   tChannelID &ClrRid(void) { rid = 0; return *this; }
   tChannelID &ClrPolarization(void);
   int Source(void) { return source; }
@@ -236,7 +237,8 @@
   void ReNumber(void);         // Recalculate 'number' based on channel type
   cChannel *GetByNumber(int Number, int SkipGap = 0);
   cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID);
-  cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false, bool TryWithoutPolarization = false);
+  cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false,
+  bool TryWithoutPolarization = false, bool TryWithoutSource = false);
   int BeingEdited(void) { return beingEdited; }
   void IncBeingEdited(void) { beingEdited++; }
   void DecBeingEdited(void) { beingEdited--; }
diff -Naur vdr-1.4.0-noEIT/channels.h.orig vdr-1.4.0/channels.h.orig
--- vdr-1.4.0-noEIT/channels.h.orig	1969-12-31 19:00:00.000000000 -0500
+++ vdr-1.4.0/channels.h.orig	2006-02-19 09:39:43.000000000 -0500
@@ -0,0 +1,257 @@
+/*
+ * channels.h: Channel handling
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: channels.h 1.39 2006/02/19 14:39:43 kls Exp $
+ */
+
+#ifndef __CHANNELS_H
+#define __CHANNELS_H
+
+#include "config.h"
+#include "sources.h"
+#include "thread.h"
+#include "tools.h"
+
+#define ISTRANSPONDER(f1, f2)  (abs((f1) - (f2)) < 4) //XXX
+
+#define CHANNELMOD_NONE     0x00
+#define CHANNELMOD_ALL      0xFF
+#define CHANNELMOD_NAME     0x01
+#define CHANNELMOD_PIDS     0x02
+#define CHANNELMOD_ID       0x04
+#define CHANNELMOD_CA       0x10
+#define CHANNELMOD_TRANSP   0x20
+#define CHANNELMOD_LANGS    0x40
+#define CHANNELMOD_RETUNE   (CHANNELMOD_PIDS | CHANNELMOD_CA | CHANNELMOD_TRANSP)
+
+#define CHANNELSMOD_NONE    0
+#define CHANNELSMOD_AUTO    1
+#define CHANNELSMOD_USER    2
+
+#define MAXAPIDS 32 // audio
+#define MAXDPIDS 16 // dolby (AC3 + DTS)
+#define MAXSPIDS  8 // subtitles
+#define MAXCAIDS  8 // conditional access
+
+#define MAXLANGCODE1 4 // a 3 letter language code, zero terminated
+#define MAXLANGCODE2 8 // up to two 3 letter language codes, separated by '+' and zero terminated
+
+#define CA_FTA           0x0000
+#define CA_DVB_MIN       0x0001
+#define CA_DVB_MAX       0x000F
+#define CA_USER_MIN      0x0010
+#define CA_USER_MAX      0x00FF
+#define CA_ENCRYPTED_MIN 0x0100
+#define CA_ENCRYPTED_MAX 0xFFFF
+
+struct tChannelParameterMap {
+  int userValue;
+  int driverValue;
+  };
+
+//XXX into cChannel???
+int MapToUser(int Value, const tChannelParameterMap *Map);
+int MapToDriver(int Value, const tChannelParameterMap *Map);
+int UserIndex(int Value, const tChannelParameterMap *Map);
+int DriverIndex(int Value, const tChannelParameterMap *Map);
+
+extern const tChannelParameterMap InversionValues[];
+extern const tChannelParameterMap BandwidthValues[];
+extern const tChannelParameterMap CoderateValues[];
+extern const tChannelParameterMap ModulationValues[];
+extern const tChannelParameterMap TransmissionValues[];
+extern const tChannelParameterMap GuardValues[];
+extern const tChannelParameterMap HierarchyValues[];
+
+struct tChannelID {
+private:
+  int source;
+  int nid; ///< actually the "original" network id
+  int tid;
+  int sid;
+  int rid;
+public:
+  tChannelID(void) { source = nid = tid = sid = rid = 0; }
+  tChannelID(int Source, int Nid, int Tid, int Sid, int Rid = 0) { source = Source; nid = Nid; tid = Tid; sid = Sid; rid = Rid; }
+  bool operator== (const tChannelID &arg) const { return source == arg.source && nid == arg.nid && tid == arg.tid && sid == arg.sid && rid == arg.rid; }
+  bool Valid(void) const { return (nid || tid) && sid; } // rid is optional and source may be 0//XXX source may not be 0???
+  tChannelID &ClrRid(void) { rid = 0; return *this; }
+  tChannelID &ClrPolarization(void);
+  int Source(void) { return source; }
+  int Nid(void) { return nid; }
+  int Tid(void) { return tid; }
+  int Sid(void) { return sid; }
+  int Rid(void) { return rid; }
+  static tChannelID FromString(const char *s);
+  cString ToString(void) const;
+  static const tChannelID InvalidID;
+  };
+
+class cChannel;
+
+class cLinkChannel : public cListObject {
+private:
+  cChannel *channel;
+public:
+  cLinkChannel(cChannel *Channel) { channel = Channel; }
+  cChannel *Channel(void) { return channel; }
+  };
+
+class cLinkChannels : public cList<cLinkChannel> {
+  };
+
+class cSchedule;
+
+class cChannel : public cListObject {
+  friend class cSchedules;
+  friend class cMenuEditChannel;
+private:
+  static cString ToText(const cChannel *Channel);
+  char *name;
+  char *shortName;
+  char *provider;
+  char *portalName;
+  int __BeginData__;
+  int frequency; // MHz
+  int source;
+  int srate;
+  int vpid;
+  int ppid;
+  int apids[MAXAPIDS + 1]; // list is zero-terminated
+  char alangs[MAXAPIDS][MAXLANGCODE2];
+  int dpids[MAXDPIDS + 1]; // list is zero-terminated
+  char dlangs[MAXDPIDS][MAXLANGCODE2];
+  int spids[MAXSPIDS + 1]; // list is zero-terminated
+  char slangs[MAXSPIDS][MAXLANGCODE2];
+  int tpid;
+  int caids[MAXCAIDS + 1]; // list is zero-terminated
+  int nid;
+  int tid;
+  int sid;
+  int rid;
+  int number;    // Sequence number assigned on load
+  bool groupSep;
+  char polarization;
+  int inversion;
+  int bandwidth;
+  int coderateH;
+  int coderateL;
+  int modulation;
+  int transmission;
+  int guard;
+  int hierarchy;
+  int __EndData__;
+  int modification;
+  mutable const cSchedule *schedule;
+  cLinkChannels *linkChannels;
+  cChannel *refChannel;
+  cString ParametersToString(void) const;
+  bool StringToParameters(const char *s);
+public:
+  cChannel(void);
+  cChannel(const cChannel &Channel);
+  ~cChannel();
+  cChannel& operator= (const cChannel &Channel);
+  cString ToText(void) const;
+  bool Parse(const char *s);
+  bool Save(FILE *f);
+  const char *Name(void) const { return name; }
+  const char *ShortName(bool OrName = false) const { return (OrName && isempty(shortName)) ? name : shortName; }
+  const char *Provider(void) const { return provider; }
+  const char *PortalName(void) const { return portalName; }
+  int Frequency(void) const { return frequency; } ///< Returns the actual frequency, as given in 'channels.conf'
+  int Transponder(void) const;                    ///< Returns the transponder frequency in MHz, plus the polarization in case of sat
+  static int Transponder(int Frequency, char Polarization); ///< builds the transponder from the given Frequency and Polarization
+  int Source(void) const { return source; }
+  int Srate(void) const { return srate; }
+  int Vpid(void) const { return vpid; }
+  int Ppid(void) const { return ppid; }
+  const int *Apids(void) const { return apids; }
+  const int *Dpids(void) const { return dpids; }
+  const int *Spids(void) const { return spids; }
+  int Apid(int i) const { return (0 <= i && i < MAXAPIDS) ? apids[i] : 0; }
+  int Dpid(int i) const { return (0 <= i && i < MAXDPIDS) ? dpids[i] : 0; }
+  int Spid(int i) const { return (0 <= i && i < MAXSPIDS) ? spids[i] : 0; }
+  const char *Alang(int i) const { return (0 <= i && i < MAXAPIDS) ? alangs[i] : ""; }
+  const char *Dlang(int i) const { return (0 <= i && i < MAXDPIDS) ? dlangs[i] : ""; }
+  const char *Slang(int i) const { return (0 <= i && i < MAXSPIDS) ? slangs[i] : ""; }
+  int Tpid(void) const { return tpid; }
+  int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; }
+  int Nid(void) const { return nid; }
+  int Tid(void) const { return tid; }
+  int Sid(void) const { return sid; }
+  int Rid(void) const { return rid; }
+  int Number(void) const { return number; }
+  void SetNumber(int Number) { number = Number; }
+  bool GroupSep(void) const { return groupSep; }
+  char Polarization(void) const { return polarization; }
+  int Inversion(void) const { return inversion; }
+  int Bandwidth(void) const { return bandwidth; }
+  int CoderateH(void) const { return coderateH; }
+  int CoderateL(void) const { return coderateL; }
+  int Modulation(void) const { return modulation; }
+  int Transmission(void) const { return transmission; }
+  int Guard(void) const { return guard; }
+  int Hierarchy(void) const { return hierarchy; }
+  const cLinkChannels* LinkChannels(void) const { return linkChannels; }
+  const cChannel *RefChannel(void) const { return refChannel; }
+  bool IsCable(void) const { return cSource::IsCable(source); }
+  bool IsSat(void) const { return cSource::IsSat(source); }
+  bool IsTerr(void) const { return cSource::IsTerr(source); }
+  tChannelID GetChannelID(void) const { return tChannelID(source, nid, (nid || tid) ? tid : Transponder(), sid, rid); }
+  int Modification(int Mask = CHANNELMOD_ALL);
+  void CopyTransponderData(const cChannel *Channel);
+  bool SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH);
+  bool SetCableTransponderData(int Source, int Frequency, int Modulation, int Srate, int CoderateH);
+  bool SetTerrTransponderData(int Source, int Frequency, int Bandwidth, int Modulation, int Hierarchy, int CodeRateH, int CodeRateL, int Guard, int Transmission);
+  void SetId(int Nid, int Tid, int Sid, int Rid = 0);
+  void SetName(const char *Name, const char *ShortName, const char *Provider);
+  void SetPortalName(const char *PortalName);
+  void SetPids(int Vpid, int Ppid, int *Apids, char ALangs[][MAXLANGCODE2], int *Dpids, char DLangs[][MAXLANGCODE2], int Tpid);
+  void SetCaIds(const int *CaIds); // list must be zero-terminated
+  void SetCaDescriptors(int Level);
+  void SetLinkChannels(cLinkChannels *LinkChannels);
+  void SetRefChannel(cChannel *RefChannel);
+  };
+
+class cChannels : public cRwLock, public cConfig<cChannel> {
+private:
+  int maxNumber;
+  int modified;
+  int beingEdited;
+  cHash<cChannel> channelsHashSid;
+  void DeleteDuplicateChannels(void);
+public:
+  cChannels(void);
+  bool Load(const char *FileName, bool AllowComments = false, bool MustExist = false);
+  void HashChannel(cChannel *Channel);
+  void UnhashChannel(cChannel *Channel);
+  int GetNextGroup(int Idx);   // Get next channel group
+  int GetPrevGroup(int Idx);   // Get previous channel group
+  int GetNextNormal(int Idx);  // Get next normal channel (not group)
+  void ReNumber(void);         // Recalculate 'number' based on channel type
+  cChannel *GetByNumber(int Number, int SkipGap = 0);
+  cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID);
+  cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false, bool TryWithoutPolarization = false);
+  int BeingEdited(void) { return beingEdited; }
+  void IncBeingEdited(void) { beingEdited++; }
+  void DecBeingEdited(void) { beingEdited--; }
+  bool HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel = NULL);
+  bool SwitchTo(int Number);
+  int MaxNumber(void) { return maxNumber; }
+  void SetModified(bool ByUser = false);
+  int Modified(void);
+      ///< Returns 0 if no channels have been modified, 1 if an automatic
+      ///< modification has been made, and 2 if the user has made a modification.
+      ///< Calling this function resets the 'modified' flag to 0.
+  cChannel *NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid = 0);
+  };
+
+extern cChannels Channels;
+
+cString ChannelString(const cChannel *Channel, int Number);
+
+#endif //__CHANNELS_H
diff -Naur vdr-1.4.0-noEIT/eit.c vdr-1.4.0/eit.c
--- vdr-1.4.0-noEIT/eit.c	2006-02-19 04:51:02.000000000 -0500
+++ vdr-1.4.0/eit.c	2006-05-07 19:15:26.000000000 -0500
@@ -16,6 +16,7 @@
 #include "i18n.h"
 #include "libsi/section.h"
 #include "libsi/descriptor.h"
+#include "libsi/dish.h"
 
 // --- cEIT ------------------------------------------------------------------
 
@@ -30,10 +31,11 @@
   if (!CheckCRCAndParse())
      return;
 
-  tChannelID channelID(Source, getOriginalNetworkId(), getTransportStreamId(), getServiceId());
-  cChannel *channel = Channels.GetByChannelID(channelID, true);
+  tChannelID channelID_search(Source, getOriginalNetworkId(), getTransportStreamId(), getServiceId());
+  cChannel *channel = Channels.GetByChannelID(channelID_search, true, true, true);
   if (!channel)
      return; // only collect data for known channels
+  tChannelID channelID(channel->Source(), getOriginalNetworkId(), getTransportStreamId(), getServiceId());
 
   cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true);
 
@@ -98,16 +100,27 @@
       int LanguagePreferenceExt = -1;
       bool UseExtendedEventDescriptor = false;
       SI::Descriptor *d;
+       SI::DishExtendedEventDescriptor *DishExtendedEventDescriptor = NULL;
+       SI::DishShortEventDescriptor *DishShortEventDescriptor = NULL;
       SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL;
       SI::ShortEventDescriptor *ShortEventDescriptor = NULL;
       cLinkChannels *LinkChannels = NULL;
       cComponents *Components = NULL;
-      for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2)); ) {
+      for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext(it2, Tid)); ) {
           if (ExternalData && d->getDescriptorTag() != SI::ComponentDescriptorTag) {
              delete d;
              continue;
              }
           switch (d->getDescriptorTag()) {
+             case SI::DishExtendedEventDescriptorTag: {
+                    SI::DishExtendedEventDescriptor *sed = (SI::DishExtendedEventDescriptor *)d;
+                  if (!DishExtendedEventDescriptor)  {
+                     delete DishExtendedEventDescriptor;
+                       DishExtendedEventDescriptor = sed;
+                       d = NULL; // so that it is not deleted
+                     }
+                 }
+                break;
             case SI::ExtendedEventDescriptorTag: {
                  SI::ExtendedEventDescriptor *eed = (SI::ExtendedEventDescriptor *)d;
                  if (I18nIsPreferredLanguage(Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt) || !ExtendedEventDescriptors) {
@@ -123,6 +136,15 @@
                     UseExtendedEventDescriptor = false;
                  }
                  break;
+       case SI::DishShortEventDescriptorTag: {
+       SI::DishShortEventDescriptor *sed = (SI::DishShortEventDescriptor *)d;
+       if (!DishShortEventDescriptor)  {
+          delete DishShortEventDescriptor;
+                    DishShortEventDescriptor = sed;
+                    d = NULL; // so that it is not deleted
+          }
+      }
+      break;
             case SI::ShortEventDescriptorTag: {
                  SI::ShortEventDescriptor *sed = (SI::ShortEventDescriptor *)d;
                  if (I18nIsPreferredLanguage(Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort) || !ShortEventDescriptor) {
@@ -219,6 +241,14 @@
           }
 
       if (!rEvent) {
+         if (DishShortEventDescriptor) {
+       char buffer[256];
+            pEvent->SetTitle(DishShortEventDescriptor->name.getText(buffer, 256));
+       }
+         if (DishExtendedEventDescriptor) {
+       char buffer[256];
+            pEvent->SetDescription(DishExtendedEventDescriptor->name.getText(buffer, 256));
+       }
          if (ShortEventDescriptor) {
             char buffer[256];
             pEvent->SetTitle(ShortEventDescriptor->name.getText(buffer, sizeof(buffer)));
@@ -229,6 +259,8 @@
             pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": "));
             }
          }
+      delete DishExtendedEventDescriptor;
+      delete DishShortEventDescriptor;
       delete ExtendedEventDescriptors;
       delete ShortEventDescriptor;
 
@@ -298,15 +330,18 @@
 
 cEitFilter::cEitFilter(void)
 {
-  Set(0x12, 0x4E, 0xFE);  // event info, actual(0x4E)/other(0x4F) TS, present/following
-  Set(0x12, 0x50, 0xF0);  // event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
-  Set(0x12, 0x60, 0xF0);  // event info, other  TS, schedule(0x60)/schedule for future days(0x6X)
+//  Set(0x12, 0x4E, 0xFE);  // event info, actual(0x4E)/other(0x4F) TS, present/following
+//  Set(0x12, 0x50, 0xF0);  // event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
+//  Set(0x12, 0x60, 0xF0);  // event info, other  TS, schedule(0x60)/schedule for future days(0x6X)
   Set(0x14, 0x70);        // TDT
+  Set(0x12, 0x00, 0x00);
+  Set(0x0300, 0x00, 0x00);
 }
 
 void cEitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
 {
   switch (Pid) {
+    case 0x0300: // Dish Network EEPG
     case 0x12: {
          cSchedulesLock SchedulesLock(true, 10);
          cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);

diff -Naur vdr-1.4.0-noEIT/libsi/Makefile vdr-1.4.0/libsi/Makefile
--- vdr-1.4.0-noEIT/libsi/Makefile	2005-05-29 07:47:12.000000000 -0400
+++ vdr-1.4.0/libsi/Makefile	2006-05-07 18:50:25.000000000 -0500
@@ -23,7 +23,7 @@
 
 ### The object files (add further files here):
 
-OBJS = util.o si.o section.o descriptor.o
+OBJS = util.o si.o section.o descriptor.o dish.o
 
 ### Implicit rules:
 
@@ -51,4 +51,5 @@
 
 dist:
 	tar cvzf libsi.tar.gz -C .. libsi/util.c libsi/si.c libsi/section.c libsi/descriptor.c \
-   libsi/util.h libsi/si.h libsi/section.h libsi/descriptor.h libsi/headers.h libsi/Makefile libsi/gendescr.pl
+   libsi/util.h libsi/si.h libsi/section.h libsi/descriptor.h libsi/headers.h libsi/Makefile libsi/gendescr.pl \
+   libsi/dish.c
diff -Naur vdr-1.4.0-noEIT/libsi/dish.c vdr-1.4.0/libsi/dish.c
--- vdr-1.4.0-noEIT/libsi/dish.c	1969-12-31 19:00:00.000000000 -0500
+++ vdr-1.4.0/libsi/dish.c	2006-05-07 19:38:10.000000000 -0500
@@ -0,0 +1,539 @@
+/*****************************************************************************
+*                                                                            *
+*   This program is free software; you can redistribute it and/or modify     *
+*   it under the terms of the GNU General Public License as published by     *
+*   the Free Software Foundation; either version 2 of the License, or        *
+*   (at your option) any later version.                                      *
+*                                                                            *
+*   These routines can decompress the dishnetwork EIT title and descriptions *
+*   that are compressed.  Also it can decompress the EPG 7 day guide title   *
+*   and descriptions located on pid 768                                      *
+*                                                                            *
+*   Thanks to all those who helped make this possible.                       *
+*   Enjoy and carry it forward!                                              *
+*                                                                            *
+*   The table contains the encoded sequences for each text character.        *
+*   To decode, just start with the first bits of a compressed data byte      *
+*   array and compare them with values in the table when a match is found    *
+*   you have your first character, now move on to the next sequence of bits  *
+*   until you have decoded the entire compressed data byte array.            *
+*                                                                            *
+*   When using the table, start at the begining and compare for a sequence   *
+*   of bits, compare only the number of bits, if the bits sequence don't     *
+*   compare then continue down the table                                     *
+*                                                                            *
+******************************************************************************/
+
+#include <string.h>
+#include "descriptor.h"
+#include "dish.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+namespace SI {
+
+
+void DishShortEventDescriptor::Parse()
+{
+   const unsigned char* str = data.getData();
+   decompress(str+3, str[1]-1, (Tid>0x80)?2:1, name);
+}
+
+void DishExtendedEventDescriptor::Parse()
+{
+   const unsigned char* str = data.getData();
+   if ((str[3]&0xf8) == 0x80)
+   decompress(str+4, str[1]-2, (Tid>0x80)?2:1, name);
+   else
+   decompress(str+3, str[1]-1, (Tid>0x80)?2:1, name);
+}
+
+struct DishDescriptor::_table DishDescriptor::Table128[MAX_TABLE128] = {
+    {0x0000, 0x20, 0x03},  // ' '
+    {0x0002, 0x65, 0x04},  // 'e'
+    {0x0003, 0x74, 0x04},  // 't'
+    {0x0004, 0x61, 0x04},  // 'a'
+    {0x0005, 0x6F, 0x04},  // 'o'
+    {0x0006, 0x73, 0x04},  // 's'
+    {0x0007, 0x6E, 0x04},  // 'n'
+    {0x0020, 0x72, 0x06},  // 'r'
+    {0x0021, 0x69, 0x06},  // 'i'
+    {0x0022, 0x6C, 0x06},  // 'l'
+    {0x0023, 0x63, 0x06},  // 'c'
+    {0x0024, 0x68, 0x06},  // 'h'
+    {0x0025, 0x75, 0x06},  // 'u'
+    {0x0026, 0x64, 0x06},  // 'd'
+    {0x0027, 0x70, 0x06},  // 'p'
+    {0x0028, 0x6D, 0x06},  // 'm'
+    {0x0029, 0x67, 0x06},  // 'g'
+    {0x002A, 0x79, 0x06},  // 'y'
+    {0x002B, 0x76, 0x06},  // 'v'
+    {0x002C, 0x0A, 0x06},  // '''
+    {0x002D, 0x2E, 0x06},  // '.'
+    {0x002E, 0x77, 0x06},  // 'w'
+    {0x002F, 0x66, 0x06},  // 'f'
+    {0x0060, 0x53, 0x07},  // 'S'
+    {0x0061, 0x62, 0x07},  // 'b'
+    {0x0062, 0x54, 0x07},  // 'T'
+    {0x0063, 0x22, 0x07},  // '"'
+    {0x0064, 0x6B, 0x07},  // 'k'
+    {0x0065, 0x50, 0x07},  // 'P'
+    {0x0066, 0x41, 0x07},  // 'A'
+    {0x0067, 0x43, 0x07},  // 'C'
+    {0x0068, 0x44, 0x07},  // 'D'
+    {0x0069, 0x4C, 0x07},  // 'L'
+    {0x006A, 0x4D, 0x07},  // 'M'
+    {0x006B, 0x49, 0x07},  // 'I'
+    {0x006C, 0x4E, 0x07},  // 'N'
+    {0x006D, 0x3A, 0x07},  // ':'
+    {0x006E, 0x52, 0x07},  // 'R'
+    {0x006F, 0x2C, 0x07},  // ','
+    {0x00E0, 0x45, 0x08},  // 'E'
+    {0x00E1, 0x55, 0x08},  // 'U'
+    {0x00E2, 0x46, 0x08},  // 'F'
+    {0x00E3, 0x48, 0x08},  // 'H'
+    {0x00E4, 0x59, 0x08},  // 'Y'
+    {0x00E5, 0x56, 0x08},  // 'V'
+    {0x00E6, 0x2D, 0x08},  // '-'
+    {0x00E7, 0x7A, 0x08},  // 'z'
+    {0x00E8, 0x78, 0x08},  // 'x'
+    {0x00E9, 0x2F, 0x08},  // '/'
+    {0x00EA, 0x4F, 0x08},  // 'O'
+    {0x00EB, 0x3F, 0x08},  // '?'
+    {0x00EC, 0x57, 0x08},  // 'W'
+    {0x00ED, 0x47, 0x08},  // 'G'
+    {0x00EE, 0x42, 0x08},  // 'B'
+    {0x00EF, 0x33, 0x08},  // '3'
+    {0x01E0, 0x31, 0x09},  // '1'
+    {0x01E1, 0x71, 0x09},  // 'q'
+    {0x01E2, 0x30, 0x09},  // '0'
+    {0x01E3, 0x21, 0x09},  // '!'
+    {0x01E4, 0x6A, 0x09},  // 'j'
+    {0x01E5, 0x5A, 0x09},  // 'Z'
+    {0x01E6, 0x39, 0x09},  // '9'
+    {0x01E7, 0x34, 0x09},  // '4'
+    {0x01E8, 0x4B, 0x09},  // 'K'
+    {0x01E9, 0x2A, 0x09},  // '*'
+    {0x01EA, 0x37, 0x09},  // '7'
+    {0x01EB, 0x36, 0x09},  // '6'
+    {0x01EC, 0x35, 0x09},  // '5'
+    {0x01ED, 0x4A, 0x09},  // 'J'
+    {0x01EE, 0x38, 0x09},  // '8'
+    {0x01EF, 0x29, 0x09},  // ')'
+    {0x03E0, 0x28, 0x0A},  // '('
+    {0x03E1, 0x58, 0x0A},  // 'X'
+    {0x03E2, 0x51, 0x0A},  // 'Q'
+    {0x03E3, 0x3C, 0x0A},  // '<'
+    {0x03E4, 0x32, 0x0A},  // '2'
+    {0x03E5, 0x27, 0x0A},  // '''
+    {0x03E6, 0x26, 0x0A},  // '&'
+    {0x07CE, 0x7F, 0x0B},  // ''
+    {0x07CF, 0x7E, 0x0B},  // '~'
+    {0x07D0, 0x7D, 0x0B},  // '}'
+    {0x07D1, 0x7C, 0x0B},  // '|'
+    {0x07D2, 0x7B, 0x0B},  // '{'
+    {0x07D3, 0x60, 0x0B},  // '`'
+    {0x07D4, 0x5F, 0x0B},  // '_'
+    {0x07D5, 0x5E, 0x0B},  // '^'
+    {0x07D6, 0x5D, 0x0B},  // ']'
+    {0x07D7, 0x5C, 0x0B},  // '\'
+    {0x07D8, 0x5B, 0x0B},  // '['
+    {0x07D9, 0x40, 0x0B},  // '@'
+    {0x07DA, 0x3E, 0x0B},  // '>'
+    {0x07DB, 0x3D, 0x0B},  // '='
+    {0x07DC, 0x3B, 0x0B},  // ';'
+    {0x07DD, 0x2B, 0x0B},  // '+'
+    {0x07DE, 0x25, 0x0B},  // '%'
+    {0x07DF, 0x24, 0x0B},  // '$'
+    {0x07E0, 0x23, 0x0B},  // '#'
+    {0x07E1, 0x1F, 0x0B},  // ''
+    {0x07E2, 0x1E, 0x0B},  // ''
+    {0x07E3, 0x1D, 0x0B},  // ''
+    {0x07E4, 0x1C, 0x0B},  // ''
+    {0x07E5, 0x1B, 0x0B},  // ''
+    {0x07E6, 0x1A, 0x0B},  // ''
+    {0x07E7, 0x19, 0x0B},  // ''
+    {0x07E8, 0x18, 0x0B},  // ''
+    {0x07E9, 0x17, 0x0B},  // ''
+    {0x07EA, 0x16, 0x0B},  // ''
+    {0x07EB, 0x15, 0x0B},  // ''
+    {0x07EC, 0x14, 0x0B},  // ''
+    {0x07ED, 0x13, 0x0B},  // ''
+    {0x07EE, 0x12, 0x0B},  // ''
+    {0x07EF, 0x11, 0x0B},  // ''
+    {0x07F0, 0x10, 0x0B},  // ''
+    {0x07F1, 0x0F, 0x0B},  // ''
+    {0x07F2, 0x0E, 0x0B},  // ''
+    {0x07F3, 0x0D, 0x0B},  // '' 
+    {0x07F4, 0x0C, 0x0B},  // ''
+    {0x07F5, 0x0B, 0x0B},  // ''
+    {0x07F6, 0x09, 0x0B},  // ''
+    {0x07F7, 0x08, 0x0B},  // ''
+    {0x07F8, 0x07, 0x0B},  // ''
+    {0x07F9, 0x06, 0x0B},  // ''
+    {0x07FA, 0x05, 0x0B},  // ''
+    {0x07FB, 0x04, 0x0B},  // ''
+    {0x07FC, 0x03, 0x0B},  // ''
+    {0x07FD, 0x02, 0x0B},  // ''
+    {0x07FE, 0x01, 0x0B},  // ''
+    {0x07FF, 0x00, 0x0B},  // ''
+};
+
+struct DishDescriptor::_table DishDescriptor::Table255[MAX_TABLE255] = {
+    {0x0000, 0x20, 0x02},  // ' '
+    {0x0004, 0x65, 0x04},  // 'e'
+    {0x0005, 0x72, 0x04},  // 'r'
+    {0x0006, 0x6E, 0x04},  // 'n'
+    {0x0007, 0x61, 0x04},  // 'a'
+    {0x0010, 0x74, 0x05},  // 't'
+    {0x0011, 0x6F, 0x05},  // 'o'
+    {0x0012, 0x73, 0x05},  // 's'
+    {0x0013, 0x69, 0x05},  // 'i'
+    {0x0014, 0x6C, 0x05},  // 'l'
+    {0x0015, 0x75, 0x05},  // 'u'
+    {0x0016, 0x63, 0x05},  // 'c'
+    {0x0017, 0x64, 0x05},  // 'd'
+    {0x0060, 0x70, 0x07},  // 'p'
+    {0x0061, 0x6D, 0x07},  // 'm'
+    {0x0062, 0x76, 0x07},  // 'v'
+    {0x0063, 0x67, 0x07},  // 'g'
+    {0x0064, 0x68, 0x07},  // 'h'
+    {0x0065, 0x2E, 0x07},  // '.'
+    {0x0066, 0x66, 0x07},  // 'f'
+    {0x0067, 0x0A, 0x07},  // ''
+    {0x0068, 0x53, 0x07},  // 'S'
+    {0x0069, 0x41, 0x07},  // 'A'
+    {0x006A, 0x45, 0x07},  // 'E'
+    {0x006B, 0x43, 0x07},  // 'C'
+    {0x006C, 0x27, 0x07},  // '''
+    {0x006D, 0x7A, 0x07},  // 'z'
+    {0x006E, 0x52, 0x07},  // 'R'
+    {0x006F, 0x22, 0x07},  // '"'
+    {0x00E0, 0x4C, 0x08},  // 'L'
+    {0x00E1, 0x49, 0x08},  // 'I'
+    {0x00E2, 0x4F, 0x08},  // 'O'
+    {0x00E3, 0x62, 0x08},  // 'b'
+    {0x00E4, 0x54, 0x08},  // 'T'
+    {0x00E5, 0x4E, 0x08},  // 'N'
+    {0x00E6, 0x55, 0x08},  // 'U'
+    {0x00E7, 0x79, 0x08},  // 'y'
+    {0x00E8, 0x44, 0x08},  // 'D'
+    {0x00E9, 0x50, 0x08},  // 'P'
+    {0x00EA, 0x71, 0x08},  // 'q'
+    {0x00EB, 0x56, 0x08},  // 'V'
+    {0x00EC, 0x2D, 0x08},  // '-'
+    {0x00ED, 0x3A, 0x08},  // ':'
+    {0x00EE, 0x2C, 0x08},  // ','
+    {0x00EF, 0x48, 0x08},  // 'H'
+    {0x01E0, 0x4D, 0x09},  // 'M'
+    {0x01E1, 0x78, 0x09},  // 'x'
+    {0x01E2, 0x77, 0x09},  // 'w'
+    {0x01E3, 0x42, 0x09},  // 'B'
+    {0x01E4, 0x47, 0x09},  // 'G'
+    {0x01E5, 0x46, 0x09},  // 'F'
+    {0x01E6, 0x30, 0x09},  // '0'
+    {0x01E7, 0x3F, 0x09},  // '?'
+    {0x01E8, 0x33, 0x09},  // '3'
+    {0x01E9, 0x2F, 0x09},  // '/'
+    {0x01EA, 0x39, 0x09},  // '9'
+    {0x01EB, 0x31, 0x09},  // '1'
+    {0x01EC, 0x38, 0x09},  // '8'
+    {0x01ED, 0x6B, 0x09},  // 'k'
+    {0x01EE, 0x6A, 0x09},  // 'j'
+    {0x01EF, 0x21, 0x09},  // '!'
+    {0x03E0, 0x36, 0x0A},  // '6'
+    {0x03E1, 0x35, 0x0A},  // '5'
+    {0x03E2, 0x59, 0x0A},  // 'Y'
+    {0x03E3, 0x51, 0x0A},  // 'Q'
+    {0x07C8, 0x34, 0x0B},  // '4'
+    {0x07C9, 0x58, 0x0B},  // 'X'
+    {0x07CA, 0x32, 0x0B},  // '2'
+    {0x07CB, 0x2B, 0x0B},  // '+'
+    {0x07CC, 0x2A, 0x0B},  // '*'
+    {0x07CD, 0x5A, 0x0B},  // 'Z'
+    {0x07CE, 0x4A, 0x0B},  // 'J'
+    {0x07CF, 0x29, 0x0B},  // ')'
+    {0x0FA0, 0x28, 0x0C},  // '('
+    {0x0FA1, 0x23, 0x0C},  // '#'
+    {0x0FA2, 0x57, 0x0C},  // 'W'
+    {0x0FA3, 0x4B, 0x0C},  // 'K'
+    {0x0FA4, 0x3C, 0x0C},  // '<'
+    {0x0FA5, 0x37, 0x0C},  // '7'
+    {0x0FA6, 0x7D, 0x0C},  // '}'
+    {0x0FA7, 0x7B, 0x0C},  // '{'
+    {0x0FA8, 0x60, 0x0C},  // '`'
+    {0x0FA9, 0x26, 0x0C},  // '&'
+    {0x1F54, 0xFE, 0x0D},  // 'þ'
+    {0x1F55, 0xFD, 0x0D},  // 'ý'
+    {0x1F56, 0xFC, 0x0D},  // 'ü'
+    {0x1F57, 0xFB, 0x0D},  // 'û'
+    {0x1F58, 0xFA, 0x0D},  // 'ú'
+    {0x1F59, 0xF9, 0x0D},  // 'ù'
+    {0x1F5A, 0xF8, 0x0D},  // 'ø'
+    {0x1F5B, 0xF7, 0x0D},  // '÷'
+    {0x1F5C, 0xF6, 0x0D},  // 'ö'
+    {0x1F5D, 0xF5, 0x0D},  // 'õ'
+    {0x1F5E, 0xF4, 0x0D},  // 'ô'
+    {0x1F5F, 0xF3, 0x0D},  // 'ó'
+    {0x1F60, 0xF2, 0x0D},  // 'ò'
+    {0x1F61, 0xF1, 0x0D},  // 'ñ'
+    {0x1F62, 0xF0, 0x0D},  // 'ð'
+    {0x1F63, 0xEF, 0x0D},  // 'ï'
+    {0x1F64, 0xEE, 0x0D},  // 'î'
+    {0x1F65, 0xED, 0x0D},  // 'í'
+    {0x1F66, 0xEC, 0x0D},  // 'ì'
+    {0x1F67, 0xEB, 0x0D},  // 'ë'
+    {0x1F68, 0xEA, 0x0D},  // 'ê'
+    {0x1F69, 0xE9, 0x0D},  // 'é'
+    {0x1F6A, 0xE8, 0x0D},  // 'è'
+    {0x1F6B, 0xE7, 0x0D},  // 'ç'
+    {0x1F6C, 0xE6, 0x0D},  // 'æ'
+    {0x1F6D, 0xE5, 0x0D},  // 'å'
+    {0x1F6E, 0xE4, 0x0D},  // 'ä'
+    {0x1F6F, 0xE3, 0x0D},  // 'ã'
+    {0x1F70, 0xE2, 0x0D},  // 'â'
+    {0x1F71, 0xE1, 0x0D},  // 'á'
+    {0x1F72, 0xE0, 0x0D},  // 'à'
+    {0x1F73, 0xDF, 0x0D},  // 'ß'
+    {0x1F74, 0xDE, 0x0D},  // 'Þ'
+    {0x1F75, 0xDD, 0x0D},  // 'Ý'
+    {0x1F76, 0xDC, 0x0D},  // 'Ü'
+    {0x1F77, 0xDB, 0x0D},  // 'Û'
+    {0x1F78, 0xDA, 0x0D},  // 'Ú'
+    {0x1F79, 0xD9, 0x0D},  // 'Ù'
+    {0x1F7A, 0xD8, 0x0D},  // 'Ø'
+    {0x1F7B, 0xD7, 0x0D},  // '×'
+    {0x1F7C, 0xD6, 0x0D},  // 'Ö'
+    {0x1F7D, 0xD5, 0x0D},  // 'Õ'
+    {0x1F7E, 0xD4, 0x0D},  // 'Ô'
+    {0x1F7F, 0xD3, 0x0D},  // 'Ó'
+    {0x1F80, 0xD2, 0x0D},  // 'Ò'
+    {0x1F81, 0xD1, 0x0D},  // ''
+    {0x1F82, 0xD0, 0x0D},  // ''
+    {0x1F83, 0xCF, 0x0D},  // ''
+    {0x1F84, 0xCE, 0x0D},  // ''
+    {0x1F85, 0xCD, 0x0D},  // ''
+    {0x1F86, 0xCC, 0x0D},  // ''
+    {0x1F87, 0xCB, 0x0D},  // ''
+    {0x1F88, 0xCA, 0x0D},  // ''
+    {0x1F89, 0xC9, 0x0D},  // ''
+    {0x1F8A, 0xC8, 0x0D},  // ''
+    {0x1F8B, 0xC7, 0x0D},  // ''
+    {0x1F8C, 0xC6, 0x0D},  // ''
+    {0x1F8D, 0xC5, 0x0D},  // ''
+    {0x1F8E, 0xC4, 0x0D},  // ''
+    {0x1F8F, 0xC3, 0x0D},  // ''
+    {0x1F90, 0xC2, 0x0D},  // ''
+    {0x1F91, 0xC1, 0x0D},  // ''
+    {0x1F92, 0xC0, 0x0D},  // ''
+    {0x1F93, 0xBF, 0x0D},  // ''
+    {0x1F94, 0xBE, 0x0D},  // ''
+    {0x1F95, 0xBD, 0x0D},  // ''
+    {0x1F96, 0xBC, 0x0D},  // ''
+    {0x1F97, 0xBB, 0x0D},  // ''
+    {0x1F98, 0xBA, 0x0D},  // ''
+    {0x1F99, 0xB9, 0x0D},  // ''
+    {0x1F9A, 0xB8, 0x0D},  // ''
+    {0x1F9B, 0xB7, 0x0D},  // ''
+    {0x1F9C, 0xB6, 0x0D},  // ''
+    {0x1F9D, 0xB5, 0x0D},  // ''
+    {0x1F9E, 0xB4, 0x0D},  // ''
+    {0x1F9F, 0xB3, 0x0D},  // ''
+    {0x1FA0, 0xB2, 0x0D},  // ''
+    {0x1FA1, 0xB1, 0x0D},  // ''
+    {0x1FA2, 0xB0, 0x0D},  // ''
+    {0x1FA3, 0xAF, 0x0D},  // ''
+    {0x1FA4, 0xAE, 0x0D},  // ''
+    {0x1FA5, 0xAD, 0x0D},  // ''
+    {0x1FA6, 0xAC, 0x0D},  // ''
+    {0x1FA7, 0xAB, 0x0D},  // ''
+    {0x1FA8, 0xAA, 0x0D},  // ''
+    {0x1FA9, 0xA9, 0x0D},  // ''
+    {0x1FAA, 0xA8, 0x0D},  // ''
+    {0x1FAB, 0xA7, 0x0D},  // ''
+    {0x1FAC, 0xA6, 0x0D},  // ''
+    {0x1FAD, 0xA5, 0x0D},  // ''
+    {0x1FAE, 0xA4, 0x0D},  // ''
+    {0x1FAF, 0xA3, 0x0D},  // ''
+    {0x1FB0, 0xA2, 0x0D},  // ''
+    {0x1FB1, 0xA1, 0x0D},  // ''
+    {0x1FB2, 0xA0, 0x0D},  // ''
+    {0x1FB3, 0x9F, 0x0D},  // ''
+    {0x1FB4, 0x9E, 0x0D},  // ''
+    {0x1FB5, 0x9D, 0x0D},  // ''
+    {0x1FB6, 0x9C, 0x0D},  // ''
+    {0x1FB7, 0x9B, 0x0D},  // ''
+    {0x1FB8, 0x9A, 0x0D},  // ''
+    {0x1FB9, 0x99, 0x0D},  // ''
+    {0x1FBA, 0x98, 0x0D},  // ''
+    {0x1FBB, 0x97, 0x0D},  // ''
+    {0x1FBC, 0x96, 0x0D},  // ''
+    {0x1FBD, 0x95, 0x0D},  // ''
+    {0x1FBE, 0x94, 0x0D},  // ''
+    {0x1FBF, 0x93, 0x0D},  // ''
+    {0x1FC0, 0x92, 0x0D},  // ''
+    {0x1FC1, 0x91, 0x0D},  // ''
+    {0x1FC2, 0x90, 0x0D},  // ''
+    {0x1FC3, 0x8F, 0x0D},  // ''
+    {0x1FC4, 0x8E, 0x0D},  // ''
+    {0x1FC5, 0x8D, 0x0D},  // ''
+    {0x1FC6, 0x8C, 0x0D},  // ''
+    {0x1FC7, 0x8B, 0x0D},  // ''
+    {0x1FC8, 0x8A, 0x0D},  // ''
+    {0x1FC9, 0x89, 0x0D},  // ''
+    {0x1FCA, 0x88, 0x0D},  // ''
+    {0x1FCB, 0x87, 0x0D},  // ''
+    {0x1FCC, 0x86, 0x0D},  // ''
+    {0x1FCD, 0x85, 0x0D},  // ''
+    {0x1FCE, 0x84, 0x0D},  // ''
+    {0x1FCF, 0x83, 0x0D},  // ''
+    {0x1FD0, 0x82, 0x0D},  // ''
+    {0x1FD1, 0x81, 0x0D},  // ''
+    {0x1FD2, 0x80, 0x0D},  // ''
+    {0x1FD3, 0x7F, 0x0D},  // ''
+    {0x1FD4, 0x7E, 0x0D},  // ''
+    {0x1FD5, 0x7C, 0x0D},  // ''
+    {0x1FD6, 0x5F, 0x0D},  // ''
+    {0x1FD7, 0x5E, 0x0D},  // ''
+    {0x1FD8, 0x5D, 0x0D},  // ''
+    {0x1FD9, 0x5C, 0x0D},  // ''
+    {0x1FDA, 0x5B, 0x0D},  // ''
+    {0x1FDB, 0x40, 0x0D},  // ''
+    {0x1FDC, 0x3E, 0x0D},  // ''
+    {0x1FDD, 0x3D, 0x0D},  // ''
+    {0x1FDE, 0x3B, 0x0D},  // ''
+    {0x1FDF, 0x25, 0x0D},  // ''
+    {0x1FE0, 0x24, 0x0D},  // ''
+    {0x1FE1, 0x1F, 0x0D},  // ''
+    {0x1FE2, 0x1E, 0x0D},  // ''
+    {0x1FE3, 0x1D, 0x0D},  // ''
+    {0x1FE4, 0x1C, 0x0D},  // ''
+    {0x1FE5, 0x1B, 0x0D},  // ''
+    {0x1FE6, 0x1A, 0x0D},  // ''
+    {0x1FE7, 0x19, 0x0D},  // ''
+    {0x1FE8, 0x18, 0x0D},  // ''
+    {0x1FE9, 0x17, 0x0D},  // ''
+    {0x1FEA, 0x16, 0x0D},  // ''
+    {0x1FEB, 0x15, 0x0D},  // ''
+    {0x1FEC, 0x14, 0x0D},  // ''
+    {0x1FED, 0x13, 0x0D},  // ''
+    {0x1FEE, 0x12, 0x0D},  // ''
+    {0x1FEF, 0x11, 0x0D},  // ''
+    {0x1FF0, 0x10, 0x0D},  // ''
+    {0x1FF1, 0x0F, 0x0D},  // ''
+    {0x1FF2, 0x0E, 0x0D},  // ''
+    {0x1FF3, 0x0D, 0x0D},  // ''
+    {0x1FF4, 0x0C, 0x0D},  // ''
+    {0x1FF5, 0x0B, 0x0D},  // ''
+    {0x1FF6, 0x09, 0x0D},  // ''
+    {0x1FF7, 0x08, 0x0D},  // ''
+    {0x1FF8, 0x07, 0x0D},  // ''
+    {0x1FF9, 0x06, 0x0D},  // ''
+    {0x1FFA, 0x05, 0x0D},  // ''
+    {0x1FFB, 0x04, 0x0D},  // ''
+    {0x1FFC, 0x03, 0x0D},  // ''
+    {0x1FFD, 0x02, 0x0D},  // ''
+    {0x1FFE, 0x01, 0x0D},  // ''
+    {0x1FFF, 0x00, 0x0D},  // ''
+};
+
+
+//
+// returns the bit value of any bit in the byte array
+//
+// for example 3 byte array the bits are as follows
+// [0][1][2][3][4][5][6][7]   [8][9][10][11][12][13][14][15] [16][17][18][19][20][21][22][23]
+//
+
+int DishDescriptor::get_bit( int bit_index, const unsigned char *byteptr )
+{
+    int byte_offset;
+   int bit_number;
+   
+   byte_offset = bit_index / 8;
+    bit_number  = bit_index - ( byte_offset * 8 );
+
+   if ( byteptr[ byte_offset ] & ( 1 << (7 - bit_number) ) )
+      return 1;
+   else
+      return 0;
+}
+
+//
+//  returns the value of a sequence of bits in the byte array
+//
+unsigned int DishDescriptor::get_bits( int bit_index, int bit_count, const unsigned char *byteptr )
+{
+   int i;
+    unsigned int bits = 0;
+   
+   for ( i = 0 ; i < bit_count ; i++ )
+      bits = ( bits << 1 ) | get_bit( bit_index + i, byteptr );
+
+   return bits;
+}
+
+//
+//  decompress the byte arrary and returns the result to a text string
+//
+void DishDescriptor::decompress(const unsigned char *compressed, int length, int table, String& result)
+{
+   int            i;
+   int            total_bits;
+   int            current_bit = 0;
+   int            count = 0;
+   unsigned int   bits;
+   int            table_size;
+   struct _table *ptrTable;
+   unsigned char *decompressed = (unsigned char*)malloc(4096);
+
+   memset (decompressed, 0, sizeof(decompressed));
+
+   if ( table == 1 )
+   {
+      table_size = MAX_TABLE128;
+     ptrTable   = Table128;
+   }
+   else
+   {
+      table_size = MAX_TABLE255;
+     ptrTable   = Table255;
+   }
+
+   
+   total_bits = length * 8;
+
+   // walk thru all the bits in the byte array, finding each sequence in the
+   // list and decoding it to a character.
+   while ( current_bit < total_bits - 3 )
+   {
+     // starting from the current bit
+     // try to find the sequence in the decode list
+
+      for ( i = 0; i < table_size; i++ )
+     {
+           bits = get_bits( current_bit, ptrTable[i].number_of_bits, compressed );
+         if ( bits == ptrTable[i].encoded_sequence )
+        {
+             decompressed[ count++ ] = ptrTable[i].character;
+            current_bit += ptrTable[i].number_of_bits;
+           break;
+        }
+     }
+
+     if ( i == table_size ) // if we get here then the bit sequence was not found ... problem try to recover
+         current_bit += 1;
+   }
+
+   decompressed[ count ] = 0;
+   
+   CharArray dc;
+   dc.assign( decompressed, count+1);
+   result.setData(dc, count+1);
+   free (decompressed);
+}
+
+
+} //end of namespace
diff -Naur vdr-1.4.0-noEIT/libsi/dish.h vdr-1.4.0/libsi/dish.h
--- vdr-1.4.0-noEIT/libsi/dish.h	1969-12-31 19:00:00.000000000 -0500
+++ vdr-1.4.0/libsi/dish.h	2006-05-07 18:50:25.000000000 -0500
@@ -0,0 +1,61 @@
+/***************************************************************************
+ *       Copyright (c) 2003 by Marcel Wiesweg                              *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   $Id: dish.h                                                           *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef DISH_H
+#define DISH_H
+
+#include "si.h"
+#include "headers.h"
+
+#define MAX_TABLE128 128
+#define MAX_TABLE255 255
+
+namespace SI {
+
+class DishDescriptor : public Descriptor {
+public:
+    String name; //name of the event
+    u_char Tid;
+
+protected:
+
+    struct _table {
+   unsigned int  encoded_sequence;
+        unsigned char character;
+        unsigned char number_of_bits;
+    };
+
+    static struct _table Table128[MAX_TABLE128];
+    static struct _table Table255[MAX_TABLE255];
+
+    int get_bit( int bit_index, const unsigned char *byteptr );
+    unsigned int get_bits( int bit_index, int bit_count, const unsigned char *byteptr );
+    void decompress(const unsigned char *compressed, int length, int table, String& result);
+};
+
+class DishShortEventDescriptor : public DishDescriptor {
+public:
+    DishShortEventDescriptor(u_char TID) { Tid=TID; };
+protected:
+    virtual void Parse();
+};
+
+class DishExtendedEventDescriptor : public DishDescriptor {
+public:
+    DishExtendedEventDescriptor(u_char TID) { Tid=TID; };
+protected:
+    virtual void Parse();
+};
+
+} //end of namespace
+
+#endif
diff -Naur vdr-1.4.0-noEIT/libsi/si.c vdr-1.4.0/libsi/si.c
--- vdr-1.4.0-noEIT/libsi/si.c	2006-02-18 05:38:20.000000000 -0500
+++ vdr-1.4.0/libsi/si.c	2006-05-07 18:50:25.000000000 -0500
@@ -13,6 +13,7 @@
 #include <string.h>
 #include "si.h"
 #include "descriptor.h"
+#include "dish.h"
 
 namespace SI {
 
@@ -105,9 +106,9 @@
    return (DescriptorTag)((const DescriptorHeader*)d)->descriptor_tag;
 }
 
-Descriptor *DescriptorLoop::getNext(Iterator &it) {
+Descriptor *DescriptorLoop::getNext(Iterator &it, u_char Tid) {
    if (isValid() && it.i<getLength()) {
-      return createDescriptor(it.i, true);
+      return createDescriptor(it.i, true, Tid);
    }
    return 0;
 }
@@ -152,10 +153,10 @@
    return d;
 }
 
-Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor) {
+Descriptor *DescriptorLoop::createDescriptor(int &i, bool returnUnimplemetedDescriptor, u_char Tid) {
    if (!checkSize(Descriptor::getLength(data.getData(i))))
       return 0;
-   Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor);
+   Descriptor *d=Descriptor::getDescriptor(data+i, domain, returnUnimplemetedDescriptor, Tid);
    if (!d)
       return 0;
    i+=d->getLength();
@@ -314,7 +315,7 @@
    *toShort = '\0';
 }
 
-Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor) {
+Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor, u_char Tid) {
    Descriptor *d=0;
    switch (domain) {
    case SI:
@@ -425,6 +426,12 @@
          case AncillaryDataDescriptorTag:
             d=new AncillaryDataDescriptor();
             break;
+         case DishShortEventDescriptorTag:
+            d=new DishShortEventDescriptor(Tid);
+            break;
+         case DishExtendedEventDescriptorTag:
+            d=new DishExtendedEventDescriptor(Tid);
+            break;
 
          //note that it is no problem to implement one
          //of the unimplemented descriptors.

diff -Naur vdr-1.4.0-noEIT/libsi/si.h vdr-1.4.0/libsi/si.h
--- vdr-1.4.0-noEIT/libsi/si.h	2006-02-18 05:38:20.000000000 -0500
+++ vdr-1.4.0/libsi/si.h	2006-05-07 18:50:25.000000000 -0500
@@ -122,6 +122,8 @@
                AdaptationFieldDataDescriptorTag = 0x70,
                ServiceIdentifierDescriptorTag = 0x71,
                ServiceAvailabilityDescriptorTag = 0x72,
+               DishShortEventDescriptorTag = 0x91,
+               DishExtendedEventDescriptorTag = 0x92,
  // Defined by ETSI TS 102 812 (MHP)
                // They once again start with 0x00 (see page 234, MHP specification)
                MHP_ApplicationDescriptorTag = 0x00,
@@ -270,7 +272,7 @@
    //   Never returns null - maybe the UnimplementedDescriptor.
    //if returnUnimplemetedDescriptor==false:
    //   Never returns the UnimplementedDescriptor - maybe null
-   static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor);
+   static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain, bool returnUnimplemetedDescriptor, u_char Tid=0);
 };
 
 class Loop : public VariableLengthPart {
@@ -334,7 +336,7 @@
    //i must be 0 to get the first descriptor (with the first call)
    //All returned descriptors must be delete'd.
    //returns null if no more descriptors available
-   Descriptor *getNext(Iterator &it);
+   Descriptor *getNext(Iterator &it, u_char Tid=0);
    //return the next descriptor with given tag, or 0 if not available.
    //if returnUnimplemetedDescriptor==true:
    //   an UnimplementedDescriptor may be returned if the next matching descriptor is unimplemented,
@@ -375,7 +377,7 @@
          return count;
       }
 protected:
-   Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor);
+   Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor, u_char Tid=0);
    DescriptorTagDomain domain;
 };
 
diff -Naur vdr-1.4.0-noEIT/pat.c vdr-1.4.0/pat.c
--- vdr-1.4.0-noEIT/pat.c	2006-01-27 10:48:29.000000000 -0500
+++ vdr-1.4.0/pat.c	2006-05-07 18:50:25.000000000 -0500
@@ -408,6 +408,10 @@
                          }
                       }
                       break;
+            //add DD pid's to autoscan
+            case 0x81:
+                     Dpids[NumDpids++] = stream.getPid();
+            break;
               //default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX
               }
             for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
