diff -Nur vdr-1.7.11.orig/channels.c vdr-1.7.11/channels.c
--- vdr-1.7.11.orig/channels.c	2010-01-02 12:38:40.000000000 -0500
+++ vdr-1.7.11/channels.c	2010-01-15 16:42:54.000000000 -0500
@@ -1106,6 +1106,20 @@
      }
   return NULL;
 }
+
+cChannel *cChannels::GetByChannelID(int nid, int tid, int 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->Tid() == tid && channel->Nid() == nid)
+            return channel;
+         }
+     }
+  return NULL;
+}
+
 cChannel *cChannels::GetByTransponderID(tChannelID ChannelID)
 {
   int source = ChannelID.Source();
diff -Nur vdr-1.7.11.orig/channels.h vdr-1.7.11/channels.h
--- vdr-1.7.11.orig/channels.h	2009-12-06 07:57:45.000000000 -0500
+++ vdr-1.7.11/channels.h	2010-01-15 16:42:54.000000000 -0500
@@ -255,6 +255,7 @@
   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(int nid, int tid, int sid);
   cChannel *GetByTransponderID(tChannelID ChannelID);
   int BeingEdited(void) { return beingEdited; }
   void IncBeingEdited(void) { beingEdited++; }
diff -Nur vdr-1.7.11.orig/eit.c vdr-1.7.11/eit.c
--- vdr-1.7.11.orig/eit.c	2010-01-03 10:35:21.000000000 -0500
+++ vdr-1.7.11/eit.c	2010-01-22 19:46:21.000000000 -0500
@@ -16,6 +16,7 @@
 #include "i18n.h"
 #include "libsi/section.h"
 #include "libsi/descriptor.h"
+#include "libsi/dish.h"
 
 #define VALID_TIME (31536000 * 2) // two years
 
@@ -32,8 +33,7 @@
   if (!CheckCRCAndParse())
      return;
 
-  tChannelID channelID(Source, getOriginalNetworkId(), getTransportStreamId(), getServiceId());
-  cChannel *channel = Channels.GetByChannelID(channelID, true);
+  cChannel *channel = Channels.GetByChannelID(getOriginalNetworkId(), getTransportStreamId(), getServiceId());
   if (!channel)
      return; // only collect data for known channels
 
@@ -119,6 +119,8 @@
       int LanguagePreferenceExt = -1;
       bool UseExtendedEventDescriptor = false;
       SI::Descriptor *d;
+      SI::DishDescriptor *DishExtendedEventDescriptor = NULL;
+      SI::DishDescriptor *DishShortEventDescriptor = NULL;
       SI::ExtendedEventDescriptors *ExtendedEventDescriptors = NULL;
       SI::ShortEventDescriptor *ShortEventDescriptor = NULL;
       cLinkChannels *LinkChannels = NULL;
@@ -144,6 +146,26 @@
                     UseExtendedEventDescriptor = false;
                  }
                  break;
+            case SI::DishExtendedEventDescriptorTag: {
+                 SI::DishDescriptor *deed = (SI::DishDescriptor *)d;
+                 deed->Decompress(Tid);
+                 if (!DishExtendedEventDescriptor) {
+                    DishExtendedEventDescriptor = deed;
+                    d = NULL; // so that it is not deleted
+                    }
+                 HasExternalData = true; 
+                 }
+                 break;
+            case SI::DishShortEventDescriptorTag: {
+                 SI::DishDescriptor *dsed = (SI::DishDescriptor *)d;
+                 dsed->Decompress(Tid);
+                 if (!DishShortEventDescriptor) {
+                   DishShortEventDescriptor = dsed;
+                   d = NULL; // so that it is not deleted
+                   }
+                 HasExternalData = true;
+                 }
+                 break;
             case SI::ShortEventDescriptorTag: {
                  SI::ShortEventDescriptor *sed = (SI::ShortEventDescriptor *)d;
                  if (I18nIsPreferredLanguage(Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort) || !ShortEventDescriptor) {
@@ -167,6 +189,7 @@
                  pEvent->SetContents(Contents);
                  }
                  break;
+/*
             case SI::ParentalRatingDescriptorTag: {
                  int LanguagePreferenceRating = -1;
                  SI::ParentalRatingDescriptor *prd = (SI::ParentalRatingDescriptor *)d;
@@ -188,6 +211,17 @@
                      }
                  }
                  break;
+*/
+            case SI::DishRatingDescriptorTag:
+                 if (d->getLength() == 4) {
+                    uint16_t rating = d->getData().TwoBytes(2);
+                    uint16_t newRating = (rating >> 10) & 0x07;
+                    if (newRating == 0) newRating = 5;
+                    if (newRating == 6) newRating = 0;
+                    pEvent->SetParentalRating((newRating << 10) | (rating & 0x3FF));
+                    pEvent->SetStarRating((rating >> 13) & 0x07);
+                    }
+                 break;                  
             case SI::PDCDescriptorTag: {
                  SI::PDCDescriptor *pd = (SI::PDCDescriptor *)d;
                  t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
@@ -271,6 +305,13 @@
           }
 
       if (!rEvent) {
+         if (DishShortEventDescriptor) {
+            pEvent->SetTitle(DishShortEventDescriptor->getText());
+            }
+         if (DishExtendedEventDescriptor) {
+            pEvent->SetDescription(DishExtendedEventDescriptor->getText());
+            pEvent->SetShortText(DishExtendedEventDescriptor->getShortText());
+            }
          if (ShortEventDescriptor) {
             char buffer[Utf8BufSize(256)];
             pEvent->SetTitle(ShortEventDescriptor->name.getText(buffer, sizeof(buffer)));
@@ -287,6 +328,8 @@
          else if (!HasExternalData)
             pEvent->SetDescription(NULL);
          }
+      delete DishExtendedEventDescriptor;
+      delete DishShortEventDescriptor;
       delete ExtendedEventDescriptors;
       delete ShortEventDescriptor;
 
@@ -355,7 +398,9 @@
 
 cEitFilter::cEitFilter(void)
 {
-  Set(0x12, 0x40, 0xC0);  // event info now&next actual/other TS (0x4E/0x4F), future actual/other TS (0x5X/0x6X)
+  Set(0x12, 0x00, 0x00);
+  Set(0x0300, 0x00, 0x00); // Dish Network EEPG
+  Set(0x0441, 0x00, 0x00); // Bell ExpressVU EEPG 
   if (Setup.SetSystemTime && Setup.TimeTransponder)
      Set(0x14, 0x70);     // TDT
 }
@@ -374,8 +419,10 @@
         return;
      }
   switch (Pid) {
+    case 0x0300:
+    case 0x0441:
     case 0x12: {
-         if (Tid >= 0x4E && Tid <= 0x6F) {
+         if (Tid >= 0x4E) {
             cSchedulesLock SchedulesLock(true, 10);
             cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
             if (Schedules)
diff -Nur vdr-1.7.11.orig/epg.c vdr-1.7.11/epg.c
--- vdr-1.7.11.orig/epg.c	2010-01-03 09:10:20.000000000 -0500
+++ vdr-1.7.11/epg.c	2010-01-16 01:28:38.000000000 -0500
@@ -114,6 +114,7 @@
   components = NULL;
   memset(contents, 0, sizeof(contents));
   parentalRating = 0;
+  starRating = 0;
   startTime = 0;
   duration = 0;
   vps = 0;
@@ -384,6 +385,20 @@
            default: ;
            }
          break;
+    case EVCONTENTMASK_USERDEFINED:
+         switch (Content & 0x0F) {
+           //case 0x00: return tr("Content$"); // ???
+           case 0x01: return tr("Content$Movie");
+           case 0x02: return tr("Content$Sports");
+           case 0x03: return tr("Content$News");
+           case 0x04: return tr("Content$Children");
+           case 0x05: return tr("Content$Education");
+           case 0x06: return tr("Content$Series");
+           case 0x07: return tr("Content$Music");
+           case 0x08: return tr("Content$Religious");
+           default: ;
+           }
+         break;   
     default: ;
     }
   return "";
@@ -391,9 +406,31 @@
 
 cString cEvent::GetParentalRatingString(void) const
 {
-  if (parentalRating)
-     return cString::sprintf(tr("ParentalRating$from %d"), parentalRating);
-  return NULL;
+  static const char *const ratings[8] =  { "", "G", "PG", "PG-13", "R", "NR/AO", "", "NC-17" };
+  char buffer[19];
+  buffer[0] = 0;
+  strcpy(buffer, ratings[(parentalRating >> 10) & 0x07]);
+  if (parentalRating & 0x37F) {
+     strcat(buffer, " [");
+     if (parentalRating & 0x0230)
+        strcat(buffer, "V,");
+     if (parentalRating & 0x000A)
+        strcat(buffer, "L,");
+     if (parentalRating & 0x0044)
+        strcat(buffer, "N,");
+     if (parentalRating & 0x0101)
+        strcat(buffer, "SC,");
+     if (char *s = strrchr(buffer, ','))
+        s[0] = ']';    
+     }
+
+  return isempty(buffer) ? NULL : buffer;
+}
+
+cString cEvent::GetStarRatingString(void) const
+{
+  static const char *const critiques[8] = { "", "*", "*+", "**", "**+", "***", "***+", "****" };
+  return critiques[starRating & 0x07];
 }
 
 cString cEvent::GetDateString(void) const
@@ -438,8 +475,8 @@
             fprintf(f, " %02X", Contents(i));
         fprintf(f, "\n");
         }
-     if (parentalRating)
-        fprintf(f, "%sR %d\n", Prefix, parentalRating);
+     if (parentalRating || starRating)
+        fprintf(f, "%sR %d %d\n", Prefix, parentalRating, starRating);
      if (components) {
         for (int i = 0; i < components->NumComponents(); i++) {
             tComponent *p = components->Component(i);
@@ -480,7 +517,13 @@
                     }
               }
               break;
-    case 'R': SetParentalRating(atoi(t));
+    case 'R': {
+                int ParentalRating = 0;
+                int StarRating = 0;
+                sscanf(t, "%d %d", &ParentalRating, &StarRating);
+                SetParentalRating(ParentalRating);
+                SetStarRating(StarRating);
+              }
               break;
     case 'X': if (!components)
                  components = new cComponents;
diff -Nur vdr-1.7.11.orig/epg.h vdr-1.7.11/epg.h
--- vdr-1.7.11.orig/epg.h	2010-01-03 09:39:14.000000000 -0500
+++ vdr-1.7.11/epg.h	2010-01-15 23:50:33.000000000 -0500
@@ -33,6 +33,8 @@
 #define EVCONTENTMASK_SPECIAL                  0xB0
 #define EVCONTENTMASK_USERDEFINED              0xF0
 
+#define VDR_RATINGS_PATCHED_V2
+
 enum eDumpMode { dmAll, dmPresent, dmFollowing, dmAtTime };
 
 struct tComponent {
@@ -73,7 +75,8 @@
   uchar tableID;           // Table ID this event came from
   uchar version;           // Version number of section this event came from
   uchar runningStatus;     // 0=undefined, 1=not running, 2=starts in a few seconds, 3=pausing, 4=running
-  uchar parentalRating;    // Parental rating of this event
+  uint16_t parentalRating; // Parental rating of this event
+  uint8_t starRating;      // Dish/BEV star rating
   char *title;             // Title of this event
   char *shortText;         // Short description of this event (typically the episode name in case of a series)
   char *description;       // Description of this event
@@ -99,6 +102,7 @@
   const cComponents *Components(void) const { return components; }
   uchar Contents(int i = 0) const { return (0 <= i && i < MAXEVCONTENTS) ? contents[i] : 0; }
   int ParentalRating(void) const { return parentalRating; }
+  uint8_t StarRating(void) const { return starRating; }
   time_t StartTime(void) const { return startTime; }
   time_t EndTime(void) const { return startTime + duration; }
   int Duration(void) const { return duration; }
@@ -109,6 +113,7 @@
   bool IsRunning(bool OrAboutToStart = false) const;
   static const char *ContentToString(uchar Content);
   cString GetParentalRatingString(void) const;
+  cString GetStarRatingString(void) const;
   cString GetDateString(void) const;
   cString GetTimeString(void) const;
   cString GetEndTimeString(void) const;
@@ -123,6 +128,7 @@
   void SetComponents(cComponents *Components); // Will take ownership of Components!
   void SetContents(uchar *Contents);
   void SetParentalRating(int ParentalRating);
+  void SetStarRating(uint8_t StarRating) { starRating = StarRating; }
   void SetStartTime(time_t StartTime);
   void SetDuration(int Duration);
   void SetVps(time_t Vps);
diff -Nur vdr-1.7.11.orig/libsi/dish.c vdr-1.7.11/libsi/dish.c
--- vdr-1.7.11.orig/libsi/dish.c	1969-12-31 19:00:00.000000000 -0500
+++ vdr-1.7.11/libsi/dish.c	2010-01-22 18:55:04.000000000 -0500
@@ -0,0 +1,552 @@
+/***************************************************************************
+ *                                                                         *
+ *   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 implement Huffman decoding of compressed Dish          *
+ *   Network EIT data.                                                     *
+ *                                                                         *
+ ***************************************************************************/ 
+
+#include "dish.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+namespace SI {
+
+// returns the value of a sequence of bits in the byte array
+static unsigned int getBits(int bitIndex, int bitCount, const unsigned char *byteptr, int length)
+{
+   union {
+      unsigned char b[4];
+      unsigned long val;
+   } chunk;
+
+   int offset = bitIndex >> 3;
+   int bitnum = bitIndex - (offset << 3);
+   int rightend = 32 - bitnum - bitCount;   
+   
+   chunk.b[3] = byteptr[offset];
+   chunk.b[2] = (offset+1 < length) ? byteptr[offset+1] : 0;
+   chunk.b[1] = (offset+2 < length) ? byteptr[offset+2] : 0;
+   chunk.b[0] = 0; // Never need to look this far ahead.
+
+   return (unsigned int)((chunk.val & (0xFFFFFFFF >> bitnum)) >> rightend);
+}
+
+static unsigned char Lookup128(unsigned int  v);
+static unsigned char Lookup255(unsigned int  v);
+
+DishDescriptor::DishDescriptor(void)
+{
+   text = NULL;
+   shortText = NULL;
+   decompressed = NULL;
+}
+
+DishDescriptor::~DishDescriptor()
+{
+   free(decompressed);
+}
+
+void DishDescriptor::Decompress(unsigned char Tid)
+{
+   const unsigned char *str = data.getData();   
+   const unsigned char *cmp = NULL; // Compressed data
+   int length = 0;  // Length of compressed data
+   int dLength = 0; // Length of decompressed data
+   
+   if ((str[3] & 0xF8) == 0x80) {
+      length = str[1] - 2;
+      dLength = (str[2]&0x40) ? ((str[3] << 6)&0xFF) | (str[2]&0x3F) : str[2]&0x3F; // Educated guess...
+      cmp = str + 4;
+   }
+   else {
+      length = str[1] - 1;
+      dLength = str[2] & 0x7F;
+      cmp = str + 3;
+   }
+  
+   if (length <= 0 || !dLength)
+     return;
+
+   decompressed = (unsigned char*)malloc(dLength+1);
+   
+   HuffmanTable *ptrTable;
+   unsigned char (*lookup)(unsigned int);
+   int minSize, maxSize;
+   
+   if (Tid > 0x80) {
+      ptrTable = Table255;
+      lookup = Lookup255;
+      minSize = 2;
+      maxSize = 14;   
+   }
+   else {
+      ptrTable = Table128;
+      lookup = Lookup128;
+      minSize = 3;
+      maxSize = 12;
+   }
+   
+   int bLength = length << 3; // number of bits
+   
+   // walk through all the bits in the byte array, finding each sequence in the 
+   // list and decoding it to a character.
+   int currentBit = 0, count = 0;
+   while (currentBit < bLength - 1 && count < dLength) {
+      int numBits;
+      for (numBits = minSize; numBits<maxSize; numBits++) {
+         unsigned int key = lookup(getBits(currentBit, numBits, cmp, length));
+         if (key && (ptrTable[key].numberOfBits == numBits)) {
+            decompressed[count++] = ptrTable[key].character;
+            currentBit += numBits;
+            break;
+         }
+      }
+      if (numBits == maxSize)
+         currentBit++;
+   }
+   decompressed[count] = 0;
+   
+   char* split = strchr((char*)decompressed, 0x0D); // Look for carriage return
+   if (split) {
+      *split = 0;
+      shortText = (char*) decompressed;
+      text = (split[1]==0x20) ? split+2 : split+1;
+   }
+   else {
+      text = (char*) decompressed;
+   }
+}
+
+// These look-up functions are not as fast as a table, but have the advantage of
+// being much more compact.
+static unsigned char Lookup128(unsigned int v)
+{
+   switch (v) {
+    case 0x0000:            return 0x01;
+    case 0x0002 ... 0x0007: return v;
+    case 0x0020 ... 0x002F: return 0x08 + v - 0x0020;
+    case 0x0060 ... 0x006F: return 0x18 + v - 0x0060;
+    case 0x00E0 ... 0x00EF: return 0x28 + v - 0x00E0;
+    case 0x01E0 ... 0x01EF: return 0x38 + v - 0x01E0;
+    case 0x03E0 ... 0x03E6: return 0x48 + v - 0x03E0;
+    case 0x07CE ... 0x07FF: return 0x4F + v - 0x07CE;
+   }   
+   return 0x00; 
+}
+
+static unsigned char Lookup255(unsigned int v)
+{
+   switch (v) {
+      case 0x0000:            return 0x01;
+      case 0x0004 ... 0x0007: return 0x02 + v - 0x0004;
+      case 0x0010 ... 0x0017: return 0x06 + v - 0x0010;
+      case 0x0060 ... 0x006F: return 0x0E + v - 0x0060;    
+      case 0x00E0 ... 0x00EF: return 0x1E + v - 0x00E0;   
+      case 0x01E0 ... 0x01EF: return 0x2E + v - 0x01E0;
+      case 0x03E0 ... 0x03E3: return 0x3E + v - 0x03E0;
+      case 0x07C8 ... 0x07CF: return 0x42 + v - 0x07C8;
+      case 0x0FA0 ... 0x0FA9: return 0x4A + v - 0x0FA0;
+      case 0x1F54 ... 0x1FFF: return 0x54 + v - 0x1F54;
+   }
+   return 0x00; 
+}
+
+struct DishDescriptor::HuffmanTable DishDescriptor::Table128[MAX_TABLE128] = {
+   { 0x00, 0x00 },  // So that first entry has index 1
+   { 0x20, 0x03 },  // ' '
+   { 0x65, 0x04 },  // 'e'
+   { 0x74, 0x04 },  // 't'
+   { 0x61, 0x04 },  // 'a'
+   { 0x6F, 0x04 },  // 'o'
+   { 0x73, 0x04 },  // 's'
+   { 0x6E, 0x04 },  // 'n'
+   { 0x72, 0x06 },  // 'r'
+   { 0x69, 0x06 },  // 'i'
+   { 0x6C, 0x06 },  // 'l'
+   { 0x63, 0x06 },  // 'c'
+   { 0x68, 0x06 },  // 'h'
+   { 0x75, 0x06 },  // 'u'
+   { 0x64, 0x06 },  // 'd'
+   { 0x70, 0x06 },  // 'p'
+   { 0x6D, 0x06 },  // 'm'
+   { 0x67, 0x06 },  // 'g'
+   { 0x79, 0x06 },  // 'y'
+   { 0x76, 0x06 },  // 'v'
+   { 0x0A, 0x06 },
+   { 0x2E, 0x06 },  // '.'
+   { 0x77, 0x06 },  // 'w'
+   { 0x66, 0x06 },  // 'f'
+   { 0x53, 0x07 },  // 'S'
+   { 0x62, 0x07 },  // 'b'
+   { 0x54, 0x07 },  // 'T'
+   { 0x22, 0x07 },  // '"'
+   { 0x6B, 0x07 },  // 'k'
+   { 0x50, 0x07 },  // 'P'
+   { 0x41, 0x07 },  // 'A'
+   { 0x43, 0x07 },  // 'C'
+   { 0x44, 0x07 },  // 'D'
+   { 0x4C, 0x07 },  // 'L'
+   { 0x4D, 0x07 },  // 'M'
+   { 0x49, 0x07 },  // 'I'
+   { 0x4E, 0x07 },  // 'N'
+   { 0x3A, 0x07 },  // ':'
+   { 0x52, 0x07 },  // 'R'
+   { 0x2C, 0x07 },  // ','
+   { 0x45, 0x08 },  // 'E'
+   { 0x55, 0x08 },  // 'U'
+   { 0x46, 0x08 },  // 'F'
+   { 0x48, 0x08 },  // 'H'
+   { 0x59, 0x08 },  // 'Y'
+   { 0x56, 0x08 },  // 'V'
+   { 0x2D, 0x08 },  // '-'
+   { 0x7A, 0x08 },  // 'z'
+   { 0x78, 0x08 },  // 'x'
+   { 0x2F, 0x08 },  // '/'
+   { 0x4F, 0x08 },  // 'O'
+   { 0x3F, 0x08 },  // '?'
+   { 0x57, 0x08 },  // 'W'
+   { 0x47, 0x08 },  // 'G'
+   { 0x42, 0x08 },  // 'B'
+   { 0x33, 0x08 },  // '3'
+   { 0x31, 0x09 },  // '1'
+   { 0x71, 0x09 },  // 'q'
+   { 0x30, 0x09 },  // '0'
+   { 0x21, 0x09 },  // '!'
+   { 0x6A, 0x09 },  // 'j'
+   { 0x5A, 0x09 },  // 'Z'
+   { 0x39, 0x09 },  // '9'
+   { 0x34, 0x09 },  // '4'
+   { 0x4B, 0x09 },  // 'K'
+   { 0x2A, 0x09 },  // '*'
+   { 0x37, 0x09 },  // '7'
+   { 0x36, 0x09 },  // '6'
+   { 0x35, 0x09 },  // '5'
+   { 0x4A, 0x09 },  // 'J'
+   { 0x38, 0x09 },  // '8'
+   { 0x29, 0x09 },  // ')'
+   { 0x28, 0x0A },  // '('
+   { 0x58, 0x0A },  // 'X'
+   { 0x51, 0x0A },  // 'Q'
+   { 0x3C, 0x0A },  // '<'
+   { 0x32, 0x0A },  // '2'
+   { 0x27, 0x0A },
+   { 0x26, 0x0A },  // '&'
+   { 0x7F, 0x0B },
+   { 0x7E, 0x0B },  // '~'
+   { 0x7D, 0x0B },  // '}'
+   { 0x7C, 0x0B },  // '|'
+   { 0x7B, 0x0B },  // '{'
+   { 0x60, 0x0B },  // '`'
+   { 0x5F, 0x0B },  // '_'
+   { 0x5E, 0x0B },  // '^'
+   { 0x5D, 0x0B },  // ']'
+   { 0x5C, 0x0B },  // '\'
+   { 0x5B, 0x0B },  // '['
+   { 0x40, 0x0B },  // '@'
+   { 0x3E, 0x0B },  // '>'
+   { 0x3D, 0x0B },  // '='
+   { 0x3B, 0x0B },  // ';'
+   { 0x2B, 0x0B },  // '+'
+   { 0x25, 0x0B },  // '%'
+   { 0x24, 0x0B },  // '$'
+   { 0x23, 0x0B },  // '#'
+   { 0x1F, 0x0B },
+   { 0x1E, 0x0B },
+   { 0x1D, 0x0B },
+   { 0x1C, 0x0B },
+   { 0x1B, 0x0B },
+   { 0x1A, 0x0B },
+   { 0x19, 0x0B },
+   { 0x18, 0x0B },
+   { 0x17, 0x0B },
+   { 0x16, 0x0B },
+   { 0x15, 0x0B },
+   { 0x14, 0x0B },
+   { 0x13, 0x0B },
+   { 0x12, 0x0B },
+   { 0x11, 0x0B },
+   { 0x10, 0x0B },
+   { 0x0F, 0x0B },
+   { 0x0E, 0x0B },
+   { 0x0D, 0x0B },
+   { 0x0C, 0x0B },
+   { 0x0B, 0x0B },
+   { 0x09, 0x0B },
+   { 0x08, 0x0B },
+   { 0x07, 0x0B },
+   { 0x06, 0x0B },
+   { 0x05, 0x0B },
+   { 0x04, 0x0B },
+   { 0x03, 0x0B },
+   { 0x02, 0x0B },
+   { 0x01, 0x0B },
+   { 0x00, 0x0B }
+} ;
+
+struct DishDescriptor::HuffmanTable DishDescriptor::Table255[MAX_TABLE255] = {\
+   { 0x00, 0x00 },
+   { 0x20, 0x02 },  // ' '
+   { 0x65, 0x04 },  // 'e'
+   { 0x72, 0x04 },  // 'r'
+   { 0x6E, 0x04 },  // 'n'
+   { 0x61, 0x04 },  // 'a'
+   { 0x74, 0x05 },  // 't'
+   { 0x6F, 0x05 },  // 'o'
+   { 0x73, 0x05 },  // 's'
+   { 0x69, 0x05 },  // 'i'
+   { 0x6C, 0x05 },  // 'l'
+   { 0x75, 0x05 },  // 'u'
+   { 0x63, 0x05 },  // 'c'
+   { 0x64, 0x05 },  // 'd'
+   { 0x70, 0x07 },  // 'p'
+   { 0x6D, 0x07 },  // 'm'
+   { 0x76, 0x07 },  // 'v'
+   { 0x67, 0x07 },  // 'g'
+   { 0x68, 0x07 },  // 'h'
+   { 0x2E, 0x07 },  // '.'
+   { 0x66, 0x07 },  // 'f'
+   { 0x0A, 0x07 },
+   { 0x53, 0x07 },  // 'S'
+   { 0x41, 0x07 },  // 'A'
+   { 0x45, 0x07 },  // 'E'
+   { 0x43, 0x07 },  // 'C'
+   { 0x27, 0x07 },
+   { 0x7A, 0x07 },  // 'z'
+   { 0x52, 0x07 },  // 'R'
+   { 0x22, 0x07 },  // '"'
+   { 0x4C, 0x08 },  // 'L'
+   { 0x49, 0x08 },  // 'I'
+   { 0x4F, 0x08 },  // 'O'
+   { 0x62, 0x08 },  // 'b'
+   { 0x54, 0x08 },  // 'T'
+   { 0x4E, 0x08 },  // 'N'
+   { 0x55, 0x08 },  // 'U'
+   { 0x79, 0x08 },  // 'y'
+   { 0x44, 0x08 },  // 'D'
+   { 0x50, 0x08 },  // 'P'
+   { 0x71, 0x08 },  // 'q'
+   { 0x56, 0x08 },  // 'V'
+   { 0x2D, 0x08 },  // '-'
+   { 0x3A, 0x08 },  // ':'
+   { 0x2C, 0x08 },  // ','
+   { 0x48, 0x08 },  // 'H'
+   { 0x4D, 0x09 },  // 'M'
+   { 0x78, 0x09 },  // 'x'
+   { 0x77, 0x09 },  // 'w'
+   { 0x42, 0x09 },  // 'B'
+   { 0x47, 0x09 },  // 'G'
+   { 0x46, 0x09 },  // 'F'
+   { 0x30, 0x09 },  // '0'
+   { 0x3F, 0x09 },  // '?'
+   { 0x33, 0x09 },  // '3'
+   { 0x2F, 0x09 },  // '/'
+   { 0x39, 0x09 },  // '9'
+   { 0x31, 0x09 },  // '1'
+   { 0x38, 0x09 },  // '8'
+   { 0x6B, 0x09 },  // 'k'
+   { 0x6A, 0x09 },  // 'j'
+   { 0x21, 0x09 },  // '!'
+   { 0x36, 0x0A },  // '6'
+   { 0x35, 0x0A },  // '5'
+   { 0x59, 0x0A },  // 'Y'
+   { 0x51, 0x0A },  // 'Q'
+   { 0x34, 0x0B },  // '4'
+   { 0x58, 0x0B },  // 'X'
+   { 0x32, 0x0B },  // '2'
+   { 0x2B, 0x0B },  // '+'
+   { 0x2A, 0x0B },  // '*'
+   { 0x5A, 0x0B },  // 'Z'
+   { 0x4A, 0x0B },  // 'J'
+   { 0x29, 0x0B },  // ')'
+   { 0x28, 0x0C },  // '('
+   { 0x23, 0x0C },  // '#'
+   { 0x57, 0x0C },  // 'W'
+   { 0x4B, 0x0C },  // 'K'
+   { 0x3C, 0x0C },  // '<'
+   { 0x37, 0x0C },  // '7'
+   { 0x7D, 0x0C },  // '}'
+   { 0x7B, 0x0C },  // '{'
+   { 0x60, 0x0C },  // '`'
+   { 0x26, 0x0C },  // '&'
+   { 0xFE, 0x0D },  // 'þ'
+   { 0xFD, 0x0D },  // 'ý'
+   { 0xFC, 0x0D },  // 'ü'
+   { 0xFB, 0x0D },  // 'û'
+   { 0xFA, 0x0D },  // 'ú'
+   { 0xF9, 0x0D },  // 'ù'
+   { 0xF8, 0x0D },  // 'ø'
+   { 0xF7, 0x0D },  // '÷'
+   { 0xF6, 0x0D },  // 'ö'
+   { 0xF5, 0x0D },  // 'õ'
+   { 0xF4, 0x0D },  // 'ô'
+   { 0xF3, 0x0D },  // 'ó'
+   { 0xF2, 0x0D },  // 'ò'
+   { 0xF1, 0x0D },  // 'ñ'
+   { 0xF0, 0x0D },  // 'ð'
+   { 0xEF, 0x0D },  // 'ï'
+   { 0xEE, 0x0D },  // 'î'
+   { 0xED, 0x0D },  // 'í'
+   { 0xEC, 0x0D },  // 'ì'
+   { 0xEB, 0x0D },  // 'ë'
+   { 0xEA, 0x0D },  // 'ê'
+   { 0xE9, 0x0D },  // 'é'
+   { 0xE8, 0x0D },  // 'è'
+   { 0xE7, 0x0D },  // 'ç'
+   { 0xE6, 0x0D },  // 'æ'
+   { 0xE5, 0x0D },  // 'å'
+   { 0xE4, 0x0D },  // 'ä'
+   { 0xE3, 0x0D },  // 'ã'
+   { 0xE2, 0x0D },  // 'â'
+   { 0xE1, 0x0D },  // 'á'
+   { 0xE0, 0x0D },  // 'à'
+   { 0xDF, 0x0D },  // 'ß'
+   { 0xDE, 0x0D },  // 'Þ'
+   { 0xDD, 0x0D },  // 'Ý'
+   { 0xDC, 0x0D },  // 'Ü'
+   { 0xDB, 0x0D },  // 'Û'
+   { 0xDA, 0x0D },  // 'Ú'
+   { 0xD9, 0x0D },  // 'Ù'
+   { 0xD8, 0x0D },  // 'Ø'
+   { 0xD7, 0x0D },  // '×'
+   { 0xD6, 0x0D },  // 'Ö'
+   { 0xD5, 0x0D },  // 'Õ'
+   { 0xD4, 0x0D },  // 'Ô'
+   { 0xD3, 0x0D },  // 'Ó'
+   { 0xD2, 0x0D },  // 'Ò'
+   { 0xD1, 0x0D },
+   { 0xD0, 0x0D },
+   { 0xCF, 0x0D },
+   { 0xCE, 0x0D },
+   { 0xCD, 0x0D },
+   { 0xCC, 0x0D },
+   { 0xCB, 0x0D },
+   { 0xCA, 0x0D },
+   { 0xC9, 0x0D },
+   { 0xC8, 0x0D },
+   { 0xC7, 0x0D },
+   { 0xC6, 0x0D },
+   { 0xC5, 0x0D },
+   { 0xC4, 0x0D },
+   { 0xC3, 0x0D },
+   { 0xC2, 0x0D },
+   { 0xC1, 0x0D },
+   { 0xC0, 0x0D },
+   { 0xBF, 0x0D },
+   { 0xBE, 0x0D },
+   { 0xBD, 0x0D },
+   { 0xBC, 0x0D },
+   { 0xBB, 0x0D },
+   { 0xBA, 0x0D },
+   { 0xB9, 0x0D },
+   { 0xB8, 0x0D },
+   { 0xB7, 0x0D },
+   { 0xB6, 0x0D },
+   { 0xB5, 0x0D },
+   { 0xB4, 0x0D },
+   { 0xB3, 0x0D },
+   { 0xB2, 0x0D },
+   { 0xB1, 0x0D },
+   { 0xB0, 0x0D },
+   { 0xAF, 0x0D },
+   { 0xAE, 0x0D },
+   { 0xAD, 0x0D },
+   { 0xAC, 0x0D },
+   { 0xAB, 0x0D },
+   { 0xAA, 0x0D },
+   { 0xA9, 0x0D },
+   { 0xA8, 0x0D },
+   { 0xA7, 0x0D },
+   { 0xA6, 0x0D },
+   { 0xA5, 0x0D },
+   { 0xA4, 0x0D },
+   { 0xA3, 0x0D },
+   { 0xA2, 0x0D },
+   { 0xA1, 0x0D },
+   { 0xA0, 0x0D },
+   { 0x9F, 0x0D },
+   { 0x9E, 0x0D },
+   { 0x9D, 0x0D },
+   { 0x9C, 0x0D },
+   { 0x9B, 0x0D },
+   { 0x9A, 0x0D },
+   { 0x99, 0x0D },
+   { 0x98, 0x0D },
+   { 0x97, 0x0D },
+   { 0x96, 0x0D },
+   { 0x95, 0x0D },
+   { 0x94, 0x0D },
+   { 0x93, 0x0D },
+   { 0x92, 0x0D },
+   { 0x91, 0x0D },
+   { 0x90, 0x0D },
+   { 0x8F, 0x0D },
+   { 0x8E, 0x0D },
+   { 0x8D, 0x0D },
+   { 0x8C, 0x0D },
+   { 0x8B, 0x0D },
+   { 0x8A, 0x0D },
+   { 0x89, 0x0D },
+   { 0x88, 0x0D },
+   { 0x87, 0x0D },
+   { 0x86, 0x0D },
+   { 0x85, 0x0D },
+   { 0x84, 0x0D },
+   { 0x83, 0x0D },
+   { 0x82, 0x0D },
+   { 0x81, 0x0D },
+   { 0x80, 0x0D },
+   { 0x7F, 0x0D },
+   { 0x7E, 0x0D },
+   { 0x7C, 0x0D },
+   { 0x5F, 0x0D },
+   { 0x5E, 0x0D },
+   { 0x5D, 0x0D },
+   { 0x5C, 0x0D },
+   { 0x5B, 0x0D },
+   { 0x40, 0x0D },
+   { 0x3E, 0x0D },
+   { 0x3D, 0x0D },
+   { 0x3B, 0x0D },
+   { 0x25, 0x0D },
+   { 0x24, 0x0D },
+   { 0x1F, 0x0D },
+   { 0x1E, 0x0D },
+   { 0x1D, 0x0D },
+   { 0x1C, 0x0D },
+   { 0x1B, 0x0D },
+   { 0x1A, 0x0D },
+   { 0x19, 0x0D },
+   { 0x18, 0x0D },
+   { 0x17, 0x0D },
+   { 0x16, 0x0D },
+   { 0x15, 0x0D },
+   { 0x14, 0x0D },
+   { 0x13, 0x0D },
+   { 0x12, 0x0D },
+   { 0x11, 0x0D },
+   { 0x10, 0x0D },
+   { 0x0F, 0x0D },
+   { 0x0E, 0x0D },
+   { 0x0D, 0x0D },
+   { 0x0C, 0x0D },
+   { 0x0B, 0x0D },
+   { 0x09, 0x0D },
+   { 0x08, 0x0D },
+   { 0x07, 0x0D },
+   { 0x06, 0x0D },
+   { 0x05, 0x0D },
+   { 0x04, 0x0D },
+   { 0x03, 0x0D },
+   { 0x02, 0x0D },
+   { 0x01, 0x0D },
+   { 0x00, 0x0D }
+} ;
+
+} //end of namespace
diff -Nur vdr-1.7.11.orig/libsi/dish.h vdr-1.7.11/libsi/dish.h
--- vdr-1.7.11.orig/libsi/dish.h	1969-12-31 19:00:00.000000000 -0500
+++ vdr-1.7.11/libsi/dish.h	2010-01-22 14:44:01.000000000 -0500
@@ -0,0 +1,45 @@
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef LIBSI_DISH_H
+#define LIBSI_DISH_H
+
+#include "si.h"
+
+#define MAX_TABLE128 129
+#define MAX_TABLE255 256
+
+namespace SI {
+
+class DishDescriptor : public Descriptor {
+public:
+   DishDescriptor(void);
+   ~DishDescriptor();
+   const char* getText(void) const { return text; }
+   const char* getShortText(void) const { return shortText; }
+   // Decompress the byte arrary and stores the result to a text string
+   void Decompress(unsigned char Tid);
+protected: 
+   virtual void Parse() {};
+
+   const char* text; // name or description of the event
+   const char* shortText; // usually the episode name
+   unsigned char* decompressed;
+   
+   struct HuffmanTable {
+      unsigned char character;
+      unsigned char numberOfBits;
+   };
+   static HuffmanTable Table128[MAX_TABLE128];
+   static HuffmanTable Table255[MAX_TABLE255];  
+};
+
+} //end of namespace 
+
+#endif //LIBSI_DISH_H
diff -Nur vdr-1.7.11.orig/libsi/Makefile vdr-1.7.11/libsi/Makefile
--- vdr-1.7.11.orig/libsi/Makefile	2006-05-26 06:40:19.000000000 -0400
+++ vdr-1.7.11/libsi/Makefile	2010-01-15 16:42:54.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 -Nur vdr-1.7.11.orig/libsi/si.c vdr-1.7.11/libsi/si.c
--- vdr-1.7.11.orig/libsi/si.c	2009-12-05 11:20:12.000000000 -0500
+++ vdr-1.7.11/libsi/si.c	2010-01-16 15:09:51.000000000 -0500
@@ -17,6 +17,7 @@
 #include <stdlib.h> // for broadcaster stupidity workaround
 #include <string.h>
 #include "descriptor.h"
+#include "dish.h"
 
 namespace SI {
 
@@ -605,6 +606,10 @@
          case ExtensionDescriptorTag:
             d=new ExtensionDescriptor();
             break;
+         case DishShortEventDescriptorTag:
+         case DishExtendedEventDescriptorTag:
+            d=new DishDescriptor();
+            break;
 
          //note that it is no problem to implement one
          //of the unimplemented descriptors.
diff -Nur vdr-1.7.11.orig/libsi/si.h vdr-1.7.11/libsi/si.h
--- vdr-1.7.11.orig/libsi/si.h	2009-12-06 06:37:35.000000000 -0500
+++ vdr-1.7.11/libsi/si.h	2010-01-16 15:10:29.000000000 -0500
@@ -122,6 +122,9 @@
                AdaptationFieldDataDescriptorTag = 0x70,
                ServiceIdentifierDescriptorTag = 0x71,
                ServiceAvailabilityDescriptorTag = 0x72,
+               DishRatingDescriptorTag = 0x89,
+               DishShortEventDescriptorTag = 0x91,
+               DishExtendedEventDescriptorTag = 0x92,
   // defined by ETSI (EN 300 468) v 1.7.1
                DefaultAuthorityDescriptorTag = 0x73,
                RelatedContentDescriptorTag = 0x74,
diff -Nur vdr-1.7.11.orig/pat.c vdr-1.7.11/pat.c
--- vdr-1.7.11.orig/pat.c	2010-01-01 10:40:05.000000000 -0500
+++ vdr-1.7.11/pat.c	2010-01-16 14:57:37.000000000 -0500
@@ -447,6 +447,29 @@
                          }
                       }
                       break;
+              case 0x81: // DN/ATSC AC-3
+                      {
+                      char lang[MAXLANGCODE1] = { 0 };
+                      SI::Descriptor *d;
+                      for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
+                          switch (d->getDescriptorTag()) {
+                            case SI::ISO639LanguageDescriptorTag: {
+                                 SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
+                                 strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1);
+                                 }
+                                 break;
+                            default: ;
+                            }
+                          delete d;
+                          }
+                      if (NumDpids < MAXDPIDS) {
+                         Dpids[NumDpids] = esPid;
+                         strn0cpy(DLangs[NumDpids], lang, MAXLANGCODE1);
+                         NumDpids++;
+                         }
+                      ProcessCaDescriptors = true;
+                      }
+                      break;
               default: ;//printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());
               }
             if (ProcessCaDescriptors) {
diff -Nur vdr-1.7.11.orig/skinclassic.c vdr-1.7.11/skinclassic.c
--- vdr-1.7.11.orig/skinclassic.c	2010-01-03 09:55:10.000000000 -0500
+++ vdr-1.7.11/skinclassic.c	2010-01-17 14:32:40.000000000 -0500
@@ -372,6 +372,13 @@
      textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Event->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
      SetTextScrollbar();
      }
+  y += textScroller.Height() + font->Height();  
+  if (Event->StarRating()) {
+     cString buffer = cString::sprintf(" %s ", *Event->GetStarRatingString());
+     const cFont *font = cFont::GetFont(fontSml);
+     int w = font->Width(buffer);
+     osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
+     }
 }
 
 void cSkinClassicDisplayMenu::SetRecording(const cRecording *Recording)
@@ -416,6 +423,13 @@
      textScroller.Set(osd, x1, y, x2 - x1, y3 - y, Info->Description(), font, Theme.Color(clrMenuEventDescription), Theme.Color(clrBackground));
      SetTextScrollbar();
      }
+  y += textScroller.Height() + font->Height();
+  if (Info->GetEvent()->StarRating()) {
+     cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetStarRatingString());
+     const cFont *font = cFont::GetFont(fontSml);
+     int w = font->Width(buffer);
+     osd->DrawText(x3 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
+     }
 }
 
 void cSkinClassicDisplayMenu::SetText(const char *Text, bool FixedFont)
diff -Nur vdr-1.7.11.orig/skinsttng.c vdr-1.7.11/skinsttng.c
--- vdr-1.7.11.orig/skinsttng.c	2010-01-03 09:51:35.000000000 -0500
+++ vdr-1.7.11/skinsttng.c	2010-01-16 14:59:26.000000000 -0500
@@ -629,6 +629,16 @@
      osd->DrawEllipse  (x1, yb,             x2, yb + Roundness, frameColor, -2);
      SetTextScrollbar();
      }
+  y += textScroller.Height() + font->Height();
+  if (Event->StarRating()) {
+     cString buffer = cString::sprintf(" %s ", *Event->GetStarRatingString());
+     const cFont *font = cFont::GetFont(fontSml);
+     int w = font->Width(buffer);
+     osd->DrawText(x4 - w, y, buffer, Theme.Color(clrMenuEventVps), frameColor, font, w);
+     int yb = y + font->Height();
+     osd->DrawRectangle(x5, y, x6 - 1, yb - 1, frameColor);
+     osd->DrawEllipse  (x6, y, x7 - 1, yb - 1, frameColor, 5);
+     }
 }
 
 void cSkinSTTNGDisplayMenu::SetRecording(const cRecording *Recording)
@@ -683,6 +693,16 @@
      osd->DrawEllipse  (x1, yb,             x2, yb + Roundness, frameColor, -2);
      SetTextScrollbar();
      }
+  y += textScroller.Height() + font->Height();
+  if (Info->GetEvent()->StarRating()) {
+     cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetStarRatingString());
+     const cFont *font = cFont::GetFont(fontSml);
+     int w = font->Width(buffer);
+     osd->DrawText(x4 - w, y, buffer, Theme.Color(clrMenuEventVps), frameColor, font, w);
+     int yb = y + font->Height();
+     osd->DrawRectangle(x5, y, x6 - 1, yb - 1, frameColor);
+     osd->DrawEllipse  (x6, y, x7 - 1, yb - 1, frameColor, 5);
+     }
 }
 
 void cSkinSTTNGDisplayMenu::SetText(const char *Text, bool FixedFont)
