Index: libs/libmythtv/eitfixup.cpp
===================================================================
--- libs/libmythtv/eitfixup.cpp	(revision 26357)
+++ libs/libmythtv/eitfixup.cpp	(working copy)
@@ -7,6 +7,7 @@
 #include "channelutil.h" // for GetDefaultAuthority()
 
 #include "programinfo.h" // for subtitle types and audio and video properties
+#include "dishdescriptors.h" // for dish_theme_type_to_string
 
 /*------------------------------------------------------------------------
  * Event Fix Up Scripts - Turned on by entry in dtv_privatetype table
@@ -15,12 +16,22 @@
 EITFixUp::EITFixUp()
     : m_bellYear("[\\(]{1}[0-9]{4}[\\)]{1}"),
       m_bellActors("\\set\\s|,"),
+      m_bellPPVTitleAllDayHD("\\s*\\(All Day\\, HD\\)\\s*$"),
       m_bellPPVTitleAllDay("\\s*\\(All Day.*\\)\\s*$"),
       m_bellPPVTitleHD("^HD\\s?-\\s?"),
-      m_bellPPVSubtitleAllDay("^All Day \\(.*\\sEastern\\)$"),
+      m_bellPPVSubtitleAllDay("^All Day \\(.*\\sEastern\\)\\s*$"),
       m_bellPPVDescriptionAllDay("^\\(.*\\sEastern\\)"),
       m_bellPPVDescriptionAllDay2("^\\([0-9].*am-[0-9].*am\\sET\\)"),
       m_bellPPVDescriptionEventId("\\([0-9]{5}\\)"),
+      m_dishPPVTitleHD("\\sHD\\s*$"),
+      m_dishPPVTitleColon("\\:\\s*$"),
+      m_dishPPVSpacePerenEnd("\\s\\)\\s*$"),
+      m_dishDescriptionNew("\\s*New\\.\\s*"),
+      m_dishDescriptionFinale("\\s*(Series|Season)\\sFinale\\.\\s*"),
+      m_dishDescriptionFinale2("\\s*Finale\\.\\s*"),
+      m_dishDescriptionPremiere("\\s*(Series|Season)\\s(Premier|Premiere)\\.\\s*"), 
+      m_dishDescriptionPremiere2("\\s*(Premier|Premiere)\\.\\s*"), 
+      m_dishPPVCode("\\s*\\(([A-Z]|[0-9]){5}\\)\\s*$"),
       m_ukThen("\\s*(Then|Followed by) 60 Seconds\\.", Qt::CaseInsensitive),
       m_ukNew("(New\\.|\\s*(Brand New|New)\\s*(Series|Episode)\\s*[:\\.\\-])",Qt::CaseInsensitive),
       m_ukCEPQ("[:\\!\\.\\?]"),
@@ -133,6 +144,12 @@
     if (kFixBell & event.fixup)
         FixBellExpressVu(event);
 
+    if (kFixDish & event.fixup)
+        FixBellExpressVu(event);
+
+    if (kFixDish & event.fixup)
+        FixBellExpressVu(event);
+
     if (kFixUK & event.fixup)
         FixUK(event);
 
@@ -251,26 +268,55 @@
     position = event.description.indexOf(".");
     // Make sure they didn't leave it out and
     // you come up with an odd category
-    if (position < 10)
+    if (position >= 10)
+        event.category = "Unknown";
+
+    // If the content descriptor didn't come up with anything, try parsing the category
+    // out of the description.
+    if (event.category == "")
     {
-        const QString stmp       = event.description;
-        event.description        = stmp.right(stmp.length() - position - 2);
-        event.category = stmp.left(position);
+        // Take out the content description which is
+        // always next with a period after it
+        position = event.description.indexOf(".");
+        if ((position + 1) < event.description.length())
+            position = event.description.indexOf(". ");
+        // Make sure they didn't leave it out and
+        // you come up with an odd category
+        if ((position > -1) && position < 20)
+        {
+            const QString stmp       = event.description;
+            event.description        = stmp.right(stmp.length() - position - 2);
+            event.category = stmp.left(position);
+
+            int position_p = event.category.indexOf("(");
+            if (position_p == -1)
+                event.description = stmp.right(stmp.length() - position - 2);
+            else
+                event.category    = "Unknown";
+        }
+        else
+        {
+            event.category = "Unknown";
+        }
+
+        // When a channel is off air the category is "-"
+        // so leave the category as blank
+        if (event.category == "-")
+            event.category = "OffAir";
+
+        if (event.category.length() > 20)
+            event.category = "Unknown";
     }
-    else
+    else if (event.categoryType)
     {
-        event.category = "Unknown";
+        QString theme = dish_theme_type_to_string(event.categoryType);
+        event.description = event.description.replace(theme, "");
+        if (event.description.startsWith("."))
+            event.description = event.description.right(event.description.length() - 1);
+        if (event.description.startsWith(" "))
+            event.description = event.description.right(event.description.length() - 1);
     }
 
-    // When a channel is off air the category is "-"
-    // so leave the category as blank
-    if (event.category == "-")
-        event.category = "OffAir";
-
-    if (event.category.length() > 10)
-        event.category = "Unknown";
-
-
     // See if a year is present as (xxxx)
     position = event.description.indexOf(m_bellYear);
     if (position != -1 && event.category != "")
@@ -280,7 +326,11 @@
         bool ok;
         uint y = event.description.mid(position + 1, 4).toUInt(&ok);
         if (ok)
+        {
             event.originalairdate = QDate(y, 1, 1);
+            event.airdate = y;
+            event.previouslyshown = true;
+        }
 
         // Get the actors if they exist
         if (position > 3)
@@ -314,6 +364,14 @@
         event.description = event.description.replace(m_Stereo, "");
     }
 
+    // Check for "title (All Day, HD)" in the title
+    position = event.title.indexOf(m_bellPPVTitleAllDayHD);
+    if (position != -1)
+    {
+        event.title = event.title.replace(m_bellPPVTitleAllDayHD, "");
+        event.videoProps |= VID_HDTV;
+     }
+
     // Check for "title (All Day)" in the title
     position = event.title.indexOf(m_bellPPVTitleAllDay);
     if (position != -1)
@@ -329,6 +387,110 @@
         event.videoProps |= VID_HDTV;
     }
 
+    // Check for (HD) in the decription
+    position = event.description.indexOf("(HD)");
+    if (position != -1)
+    {
+        event.description = event.description.replace("(HD)", "");
+        event.videoProps |= VID_HDTV;
+    }
+
+    // Check for (HD) in the title
+    position = event.title.indexOf("(HD)");
+    if (position != -1)
+    {
+        event.description = event.title.replace("(HD)", "");
+        event.videoProps |= VID_HDTV;
+    }
+
+    // Check for HD at the end of the title
+    position = event.title.indexOf(m_dishPPVTitleHD);
+    if (position != -1)
+    {
+        event.title = event.title.replace(m_dishPPVTitleHD, "");
+        event.videoProps |= VID_HDTV;
+    }
+
+    // Check for (DD) at the end of the description
+    position = event.description.indexOf("(DD)");
+    if (position != -1)
+    {
+        event.description = event.description.replace("(DD)", "");
+        event.audioProps |= AUD_DOLBY;
+        event.audioProps |= AUD_STEREO;
+    }
+
+    // Remove SAP from Dish descriptions
+    position = event.description.indexOf("(SAP)");
+    if (position != -1)
+    {
+        event.description = event.description.replace("(SAP", "");
+        event.subtitleType |= SUB_HARDHEAR;
+    }
+
+    // Remove any trailing colon in title
+    position = event.title.indexOf(m_dishPPVTitleColon);
+    if (position != -1)
+    {
+        event.title = event.title.replace(m_dishPPVTitleColon, "");
+    }
+
+    // Remove New at the end of the description
+    position = event.description.indexOf(m_dishDescriptionNew);
+    if (position != -1)
+    {
+        event.previouslyshown = false;
+        event.description = event.description.replace(m_dishDescriptionNew, "");
+    }
+
+    // Remove Series Finale at the end of the desciption
+    position = event.description.indexOf(m_dishDescriptionFinale);
+    if (position != -1)
+    {
+        event.previouslyshown = false;
+        event.description = event.description.replace(m_dishDescriptionFinale, "");
+    }
+
+    // Remove Series Finale at the end of the desciption
+    position = event.description.indexOf(m_dishDescriptionFinale2);
+    if (position != -1)
+    {
+        event.previouslyshown = false;
+        event.description = event.description.replace(m_dishDescriptionFinale2, "");
+    }
+
+    // Remove Series Premiere at the end of the description
+    position = event.description.indexOf(m_dishDescriptionPremiere);
+    if (position != -1)
+    {
+        event.previouslyshown = false;
+        event.description = event.description.replace(m_dishDescriptionPremiere, "");
+    }
+
+    // Remove Series Premiere at the end of the description 
+    position = event.description.indexOf(m_dishDescriptionPremiere2);
+    if (position != -1)
+    {
+        event.previouslyshown = false;
+        event.description = event.description.replace(m_dishDescriptionPremiere2, "");
+    }
+
+    // Remove Dish's PPV code at the end of the description
+    QRegExp ppvcode = m_dishPPVCode; 
+    ppvcode.setCaseSensitivity(Qt::CaseInsensitive);
+    position = event.description.indexOf(ppvcode);
+    if (position != -1)
+    {
+        event.description = event.description.replace(ppvcode, "");
+    }
+
+    // Remove trailing garbage
+    position = event.description.indexOf(m_dishPPVSpacePerenEnd);
+    if (position != -1)
+    {
+        event.description = event.description.replace(m_dishPPVSpacePerenEnd, "");
+    }
+
     // Check for subtitle "All Day (... Eastern)" in the subtitle
     position = event.subtitle.indexOf(m_bellPPVSubtitleAllDay);
     if (position != -1)
Index: libs/libmythtv/eithelper.cpp
===================================================================
--- libs/libmythtv/eithelper.cpp	(revision 26357)
+++ libs/libmythtv/eithelper.cpp	(working copy)
@@ -333,7 +333,7 @@
         QString subtitle      = QString("");
         QString description   = QString("");
         QString category      = QString("");
-        MythCategoryType category_type = kCategoryNone;
+        uint category_type = kCategoryNone;
         unsigned char subtitle_type=0, audio_props=0, video_props=0;
 
         // Parse descriptors
@@ -368,19 +368,91 @@
         parse_dvb_component_descriptors(list, subtitle_type, audio_props,
                                         video_props);
 
+        QString programId;
+        QString seriesId;
+        QString rating;
+        QString rating_system;
+        QString advisory;
+        float stars = 0.0;
+
+        if (EITFixUp::kFixDish & fix)
+        {
+            const unsigned char *mpaa_data =
+                MPEGDescriptor::Find(list, DescriptorID::dish_event_mpaa);
+            if (mpaa_data)
+            {
+                DishEventMPAADescriptor mpaa(mpaa_data);
+                stars = mpaa.stars();
+
+                if (stars) // Only movies for now
+                {
+                    rating = mpaa.rating();
+                    rating_system = "MPAA";
+                    advisory = mpaa.advisory();
+                }
+            }
+
+            if (!stars) // Not MPAA rated, check VCHIP
+            {
+                const unsigned char *vchip_data =
+                    MPEGDescriptor::Find(list, DescriptorID::dish_event_vchip);
+                if (vchip_data)
+                {
+                    DishEventVCHIPDescriptor vchip(vchip_data);
+                    rating = vchip.rating();
+                    rating_system = "VCHIP";
+                    advisory = vchip.advisory();
+                }
+            }
+
+            if (!advisory.isEmpty() && !rating.isEmpty())
+                rating += ", " + advisory;
+            else if (!advisory.isEmpty())
+            {
+                rating = advisory;
+                rating_system = "advisory";
+            }
+
+            const unsigned char *tags_data =
+                MPEGDescriptor::Find(list, DescriptorID::dish_event_tags);
+            if (tags_data)
+            {
+                DishEventTagsDescriptor tags(tags_data);
+                seriesId  = tags.seriesid();
+                programId = tags.programid();
+            }
+
+            const unsigned char *properties_data =
+                MPEGDescriptor::Find(list, DescriptorID::dish_event_properties);
+            if (properties_data)
+            {
+                DishEventPropertiesDescriptor properties(properties_data);
+                subtitle_type |= properties.SubtitleProperties(descCompression);
+                audio_props   |= properties.AudioProperties(descCompression);
+            }
+        }
+
         const unsigned char *content_data =
             MPEGDescriptor::Find(list, DescriptorID::content);
         if (content_data)
         {
-            ContentDescriptor content(content_data);
-            category      = content.GetDescription(0);
-            category_type = content.GetMythCategory(0);
+            if ((EITFixUp::kFixDish & fix) || (EITFixUp::kFixBell & fix))
+            {
+                DishContentDescriptor content(content_data);
+                category_type = content.GetTheme();
+                if (EITFixUp::kFixDish & fix)
+                    category  = content.GetCategory();
+            }
+            else
+            {
+                ContentDescriptor content(content_data);
+                category      = content.GetDescription(0);
+                category_type = content.GetMythCategory(0);
+            }
         }
 
         desc_list_t contentIds =
             MPEGDescriptor::FindAll(list, DescriptorID::dvb_content_identifier);
-        QString programId = QString("");
-        QString seriesId  = QString("");
         for (uint j = 0; j < contentIds.size(); j++)
         {
             DVBContentIdentifierDescriptor desc(contentIds[j]);
@@ -410,6 +482,7 @@
             subtitle_type,
             audio_props,
             video_props,
+            stars,
             seriesId,  programId);
 
         db_events.enqueue(event);
@@ -516,7 +589,7 @@
                 starttime, endtime,       fix,
                 subtitle_type,
                 audio_props,
-                video_props,
+                video_props, 0.0,
                 "",  "");
 
             db_events.enqueue(event);
Index: libs/libmythtv/mpeg/dishdescriptors.cpp
===================================================================
--- libs/libmythtv/mpeg/dishdescriptors.cpp	(revision 26357)
+++ libs/libmythtv/mpeg/dishdescriptors.cpp	(working copy)
@@ -2,6 +2,7 @@
 
 #include "dishdescriptors.h"
 #include "atsc_huffman.h"
+#include "programinfo.h" // for subtitle types and audio and video properties
 
 QString DishEventNameDescriptor::Name(uint compression_type) const
 {
@@ -41,3 +42,462 @@
 
     return QString::null;
 }
+
+bool DishEventPropertiesDescriptor::decompressed = false;
+uint DishEventPropertiesDescriptor::subtitle_props = SUB_UNKNOWN;
+uint DishEventPropertiesDescriptor::audio_props = AUD_UNKNOWN;
+
+uint DishEventPropertiesDescriptor::SubtitleProperties(uint compression_type) const
+{
+    decompress_properties(compression_type);
+
+    return subtitle_props;
+}
+
+uint DishEventPropertiesDescriptor::AudioProperties(uint compression_type) const
+{
+    decompress_properties(compression_type);
+
+    return audio_props;
+}
+
+void DishEventPropertiesDescriptor::decompress_properties(uint compression_type) const
+{
+    subtitle_props = SUB_UNKNOWN;
+    audio_props = AUD_UNKNOWN;
+
+    if (HasProperties())
+    {
+        QString properties_raw = atsc_huffman2_to_string(
+            _data + 4, DescriptorLength() - 2, compression_type);
+
+        if (properties_raw.contains("6|CC"))
+            subtitle_props |= SUB_HARDHEAR;
+
+        if (properties_raw.contains("7|Stereo"))
+            audio_props    |= AUD_STEREO;
+    }
+}
+
+QString DishEventTagsDescriptor::programid(void) const
+{
+    QString id;
+
+    if (DescriptorLength() != 8)
+        return QString::null;
+
+    id.sprintf("%02x%02x%02x%02x%02x%02x%02x", _data[3], _data[4], _data[5],
+                                               _data[6], _data[7], _data[8],
+                                               _data[9]);
+
+    return id;
+}
+
+QString DishEventTagsDescriptor::seriesid(void) const            
+{
+    QString id;
+
+    if (DescriptorLength() != 8)
+        return QString::null;
+
+    id.sprintf("%02x%02x%02x%01x", _data[3], _data[4], _data[5],
+                                   ((_data[6] & 0xf0) >> 0x04));
+
+    return id;
+}
+
+QMutex            DishEventMPAADescriptor::mpaaRatingsLock;
+map<uint,QString> DishEventMPAADescriptor::mpaaRatingsDesc;
+bool              DishEventMPAADescriptor::mpaaRatingsExists = false;
+
+float DishEventMPAADescriptor::stars(void) const
+{
+    switch(stars_raw())
+    {
+        case 0x01: return 1.0 / 4;
+        case 0x02: return 1.5 / 4;
+        case 0x03: return 2.0 / 4;
+        case 0x04: return 2.5 / 4;
+        case 0x05: return 3.0 / 4;
+        case 0x06: return 3.5 / 4;
+        case 0x07: return 4.0 / 4;
+    }
+
+    return 0.0;
+}
+
+QString DishEventMPAADescriptor::rating(void) const
+{
+    if (!mpaaRatingsExists)
+        Init();
+
+    QMutexLocker locker(&mpaaRatingsLock);
+
+    map<uint,QString>::const_iterator it = mpaaRatingsDesc.find(rating_raw());
+    if (it != mpaaRatingsDesc.end())
+    {
+        QString ret = (*it).second;
+        ret.detach();
+        return ret;
+    }
+
+    // Found nothing? Just return empty string.
+    return "";
+}
+
+QString DishEventMPAADescriptor::advisory(void) const
+{
+    int advisory = advisory_raw();
+    QStringList advisories;
+
+    if (advisory & 0x01)
+        advisories.append("S");
+    if (advisory & 0x02)
+        advisories.append("L");
+    if (advisory & 0x04)
+        advisories.append("mQ");
+    if (advisory & 0x08)
+        advisories.append("FV");
+    if (advisory & 0x10)
+        advisories.append("V");
+    if (advisory & 0x20)
+        advisories.append("mK");
+    if (advisory & 0x40)
+        advisories.append("N");
+
+    return advisories.join(",");
+}
+
+void DishEventMPAADescriptor::Init(void)
+{
+    QMutexLocker locker(&mpaaRatingsLock);
+
+    if (mpaaRatingsExists)
+        return;
+
+    mpaaRatingsDesc[0x01] = QObject::tr("G");
+    mpaaRatingsDesc[0x02] = QObject::tr("PG");
+    mpaaRatingsDesc[0x03] = QObject::tr("PG-13");
+    mpaaRatingsDesc[0x04] = QObject::tr("R");
+    mpaaRatingsDesc[0x05] = QObject::tr("NC-17");
+    mpaaRatingsDesc[0x06] = QObject::tr("NR");
+
+    mpaaRatingsExists = true;
+}
+
+QMutex            DishEventVCHIPDescriptor::vchipRatingsLock;
+map<uint,QString> DishEventVCHIPDescriptor::vchipRatingsDesc;
+bool              DishEventVCHIPDescriptor::vchipRatingsExists = false;
+
+QString DishEventVCHIPDescriptor::rating(void) const
+{
+    if (!vchipRatingsExists)
+        Init();
+
+    QMutexLocker locker(&vchipRatingsLock);
+
+    map<uint,QString>::const_iterator it = vchipRatingsDesc.find(rating_raw());
+    if (it != vchipRatingsDesc.end())
+    {
+        QString ret = (*it).second;
+        ret.detach();
+        return ret;
+    }
+
+    // Found nothing? Just return empty string.
+    return "";
+}
+
+QString DishEventVCHIPDescriptor::advisory(void) const
+{
+    int advisory = advisory_raw();
+    QStringList advisories;
+
+    if (advisory & 0x01)
+        advisories.append("FV");
+    if (advisory & 0x02)
+        advisories.append("V");
+    if (advisory & 0x04)
+        advisories.append("S");
+    if (advisory & 0x08)
+        advisories.append("L");
+    if (advisory & 0x10)
+        advisories.append("D");
+
+    return advisories.join(",");
+}
+
+void DishEventVCHIPDescriptor::Init(void)
+{
+    QMutexLocker locker(&vchipRatingsLock);
+
+    if (vchipRatingsExists)
+        return;
+
+    vchipRatingsDesc[0x01] = QObject::tr("TV-Y");
+    vchipRatingsDesc[0x02] = QObject::tr("TV-Y7");
+    vchipRatingsDesc[0x03] = QObject::tr("TV-G");
+    vchipRatingsDesc[0x04] = QObject::tr("TV-PG");
+    vchipRatingsDesc[0x05] = QObject::tr("TV-14");
+    vchipRatingsDesc[0x06] = QObject::tr("TV-MA");
+
+    vchipRatingsExists = true;
+}
+
+QMutex            DishContentDescriptor::categoryLock;
+map<uint,QString> DishContentDescriptor::themeDesc;
+map<uint,QString> DishContentDescriptor::categoryDesc;
+bool              DishContentDescriptor::categoriesExists = false;
+
+QString dish_theme_type_to_string(uint theme_type)
+{
+    static const char *themes[] =
+        { "", "Movie", "Sports", "News/Business", "Family/Children", "Education",
+          "Series/Special", "Music/Art", "Religious", "Off-Air" };
+
+    if ((theme_type > kThemeNone) && (theme_type < kThemeLast))
+        return QString(themes[theme_type]);
+
+    return "";
+}
+
+DishThemeType string_to_dish_theme_type(const QString &theme_type)
+{
+    static const char *themes[] =
+        { "", "Movie", "Sports", "News/Business", "Family/Children", "Education",
+          "Series/Special", "Music/Art", "Religious", "Off-Air" };
+
+    for (uint i = 1; i < 10; i++)
+        if (theme_type == themes[i])
+            return (DishThemeType) i;
+
+    return kThemeNone;
+}
+
+DishThemeType DishContentDescriptor::GetTheme(void) const
+{
+    if (!categoriesExists)
+        Init();
+
+    if (Nibble1() == 0x00)
+        return kThemeOffAir;
+
+    map<uint,QString>::const_iterator it = themeDesc.find(Nibble2());
+    if (it != themeDesc.end())
+        return string_to_dish_theme_type((*it).second);
+
+    // Found nothing? Just return empty string.
+    return kThemeNone;
+}
+
+QString DishContentDescriptor::GetCategory(void) const
+{
+    if (!categoriesExists)
+        Init();
+
+    QMutexLocker locker(&categoryLock);
+
+    // Try to get detailed description
+    map<uint,QString>::const_iterator it = categoryDesc.find(UserNibble());
+    if (it != categoryDesc.end())
+    {
+        QString ret = (*it).second;
+        ret.detach();
+        return ret;
+    }
+
+    // Fallback to just the theme
+    QString theme = dish_theme_type_to_string(GetTheme());
+
+    if (theme != "")
+        return theme;
+
+    // Found nothing? Just return empty string.
+    return "";
+}
+
+QString DishContentDescriptor::toString() const
+{
+    QString tmp("");
+    tmp += GetTheme() + " : " + GetCategory();
+    return tmp;
+}
+
+void DishContentDescriptor::Init(void)
+{
+    QMutexLocker locker(&categoryLock);
+
+    if (categoriesExists)
+        return;
+
+    // Dish/BEV "Themes"
+    themeDesc[kThemeMovie]     = QObject::tr("Movie");
+    themeDesc[kThemeSports]    = QObject::tr("Sports");
+    themeDesc[kThemeNews]      = QObject::tr("News/Business");
+    themeDesc[kThemeFamily]    = QObject::tr("Family/Children");
+    themeDesc[kThemeEducation] = QObject::tr("Education");
+    themeDesc[kThemeSeries]    = QObject::tr("Series/Special");
+    themeDesc[kThemeMusic]     = QObject::tr("Music/Art");
+    themeDesc[kThemeReligious] = QObject::tr("Religious");
+
+    // Dish/BEV categories
+    categoryDesc[0x01] = QObject::tr("Action");
+    categoryDesc[0x02] = QObject::tr("Adults only");
+    categoryDesc[0x03] = QObject::tr("Adventure");
+    categoryDesc[0x04] = QObject::tr("Animals");
+    categoryDesc[0x05] = QObject::tr("Animated");
+    categoryDesc[0x07] = QObject::tr("Anthology");
+    categoryDesc[0x08] = QObject::tr("Art");
+    categoryDesc[0x09] = QObject::tr("Auto");
+    categoryDesc[0x0a] = QObject::tr("Awards");
+    categoryDesc[0x0b] = QObject::tr("Ballet");
+    categoryDesc[0x0c] = QObject::tr("Baseball");
+    categoryDesc[0x0d] = QObject::tr("Basketball");
+    categoryDesc[0x11] = QObject::tr("Biography");
+    categoryDesc[0x12] = QObject::tr("Boat");
+    categoryDesc[0x14] = QObject::tr("Bowling");
+    categoryDesc[0x15] = QObject::tr("Boxing");
+    categoryDesc[0x16] = QObject::tr("Bus./financial");
+    categoryDesc[0x1a] = QObject::tr("Children");
+    categoryDesc[0x1b] = QObject::tr("Children-special");
+    categoryDesc[0x1c] = QObject::tr("Children-news");
+    categoryDesc[0x1d] = QObject::tr("Children-music");
+    categoryDesc[0x1f] = QObject::tr("Collectibles");
+    categoryDesc[0x20] = QObject::tr("Comedy");
+    categoryDesc[0x21] = QObject::tr("Comedy-drama");
+    categoryDesc[0x22] = QObject::tr("Computers");
+    categoryDesc[0x23] = QObject::tr("Cooking");
+    categoryDesc[0x24] = QObject::tr("Crime");
+    categoryDesc[0x25] = QObject::tr("Crime drama");
+    categoryDesc[0x27] = QObject::tr("Dance");
+    categoryDesc[0x29] = QObject::tr("Docudrama");
+    categoryDesc[0x2a] = QObject::tr("Documentary");
+    categoryDesc[0x2b] = QObject::tr("Drama");
+    categoryDesc[0x2c] = QObject::tr("Educational");
+    categoryDesc[0x2f] = QObject::tr("Excercise");
+    categoryDesc[0x31] = QObject::tr("Fantasy");
+    categoryDesc[0x32] = QObject::tr("Fasion");
+    categoryDesc[0x34] = QObject::tr("Fishing");
+    categoryDesc[0x35] = QObject::tr("Football");
+    categoryDesc[0x36] = QObject::tr("French");
+    categoryDesc[0x37] = QObject::tr("Fundraiser");
+    categoryDesc[0x38] = QObject::tr("Game show");
+    categoryDesc[0x39] = QObject::tr("Golf");
+    categoryDesc[0x3a] = QObject::tr("Gymnastics");
+    categoryDesc[0x3b] = QObject::tr("Health");
+    categoryDesc[0x3c] = QObject::tr("History");
+    categoryDesc[0x3d] = QObject::tr("Historical drama");
+    categoryDesc[0x3e] = QObject::tr("Hockey");
+    categoryDesc[0x3f] = QObject::tr("Holiday");
+    categoryDesc[0x40] = QObject::tr("Holiday-children");
+    categoryDesc[0x41] = QObject::tr("Holiday-children special");
+    categoryDesc[0x44] = QObject::tr("Holiday special");
+    categoryDesc[0x45] = QObject::tr("Horror");
+    categoryDesc[0x46] = QObject::tr("Horse racing");
+    categoryDesc[0x47] = QObject::tr("House/garden");
+    categoryDesc[0x49] = QObject::tr("How-to");
+    categoryDesc[0x4b] = QObject::tr("Interview");
+    categoryDesc[0x4d] = QObject::tr("Lacrosse");
+    categoryDesc[0x4f] = QObject::tr("Martial Arts");
+    categoryDesc[0x50] = QObject::tr("Medical");
+    categoryDesc[0x51] = QObject::tr("Miniseries");
+    categoryDesc[0x52] = QObject::tr("Motorsports");
+    categoryDesc[0x53] = QObject::tr("Motorcycle");
+    categoryDesc[0x54] = QObject::tr("Music");
+    categoryDesc[0x55] = QObject::tr("Music special");
+    categoryDesc[0x56] = QObject::tr("Music talk");
+    categoryDesc[0x57] = QObject::tr("Musical");
+    categoryDesc[0x58] = QObject::tr("Musical comedy");
+    categoryDesc[0x5a] = QObject::tr("Mystery");
+    categoryDesc[0x5b] = QObject::tr("Nature");
+    categoryDesc[0x5c] = QObject::tr("News");
+    categoryDesc[0x5f] = QObject::tr("Opera");
+    categoryDesc[0x60] = QObject::tr("Outdoors");
+    categoryDesc[0x63] = QObject::tr("Public affairs");
+    categoryDesc[0x66] = QObject::tr("Reality");
+    categoryDesc[0x67] = QObject::tr("Religious");
+    categoryDesc[0x68] = QObject::tr("Rodeo");
+    categoryDesc[0x69] = QObject::tr("Romance");
+    categoryDesc[0x6a] = QObject::tr("Romance-comedy");
+    categoryDesc[0x6b] = QObject::tr("Rugby");
+    categoryDesc[0x6c] = QObject::tr("Running");
+    categoryDesc[0x6e] = QObject::tr("Science");
+    categoryDesc[0x6f] = QObject::tr("Science fiction");
+    categoryDesc[0x70] = QObject::tr("Self improvement");
+    categoryDesc[0x71] = QObject::tr("Shopping");
+    categoryDesc[0x74] = QObject::tr("Skiing");
+    categoryDesc[0x77] = QObject::tr("Soap");
+    categoryDesc[0x7b] = QObject::tr("Soccor");
+    categoryDesc[0x7c] = QObject::tr("Softball");
+    categoryDesc[0x7d] = QObject::tr("Spanish");
+    categoryDesc[0x7e] = QObject::tr("Special");
+    categoryDesc[0x81] = QObject::tr("Sports non-event");
+    categoryDesc[0x82] = QObject::tr("Sports talk");
+    categoryDesc[0x83] = QObject::tr("Suspense");
+    categoryDesc[0x85] = QObject::tr("Swimming");
+    categoryDesc[0x86] = QObject::tr("Talk");
+    categoryDesc[0x87] = QObject::tr("Tennis");
+    categoryDesc[0x89] = QObject::tr("Track/field");
+    categoryDesc[0x8a] = QObject::tr("Travel");
+    categoryDesc[0x8b] = QObject::tr("Variety");
+    categoryDesc[0x8c] = QObject::tr("Volleyball");
+    categoryDesc[0x8d] = QObject::tr("War");
+    categoryDesc[0x8e] = QObject::tr("Watersports");
+    categoryDesc[0x8f] = QObject::tr("Weather");
+    categoryDesc[0x90] = QObject::tr("Western");
+    categoryDesc[0x92] = QObject::tr("Wrestling");
+    categoryDesc[0x93] = QObject::tr("Yoga");
+    categoryDesc[0x94] = QObject::tr("Agriculture");
+    categoryDesc[0x95] = QObject::tr("Anime");
+    categoryDesc[0x97] = QObject::tr("Arm Wrestling");
+    categoryDesc[0x98] = QObject::tr("Arts/crafts");
+    categoryDesc[0x99] = QObject::tr("Auction");
+    categoryDesc[0x9a] = QObject::tr("Auto racing");
+    categoryDesc[0x9b] = QObject::tr("Air racing");
+    categoryDesc[0x9c] = QObject::tr("Badminton");
+    categoryDesc[0xa0] = QObject::tr("Bicycle racing");
+    categoryDesc[0xa1] = QObject::tr("Boat Racing");
+    categoryDesc[0xa6] = QObject::tr("Community");
+    categoryDesc[0xa7] = QObject::tr("Consumer");
+    categoryDesc[0xaa] = QObject::tr("Debate");
+    categoryDesc[0xac] = QObject::tr("Dog show");
+    categoryDesc[0xad] = QObject::tr("Drag racing");
+    categoryDesc[0xae] = QObject::tr("Entertainment");
+    categoryDesc[0xaf] = QObject::tr("Environment");
+    categoryDesc[0xb0] = QObject::tr("Equestrian");
+    categoryDesc[0xb3] = QObject::tr("Field hockey");
+    categoryDesc[0xb5] = QObject::tr("Football");
+    categoryDesc[0xb6] = QObject::tr("Gay/lesbian");
+    categoryDesc[0xb7] = QObject::tr("Handball");
+    categoryDesc[0xb8] = QObject::tr("Home improvement");
+    categoryDesc[0xb9] = QObject::tr("Hunting");
+    categoryDesc[0xbb] = QObject::tr("Hydroplane racing");
+    categoryDesc[0xc1] = QObject::tr("Law");
+    categoryDesc[0xc3] = QObject::tr("Motorcycle racing");
+    categoryDesc[0xc5] = QObject::tr("Newsmagazine");
+    categoryDesc[0xc7] = QObject::tr("Paranormal");
+    categoryDesc[0xc8] = QObject::tr("Parenting");
+    categoryDesc[0xca] = QObject::tr("Performing arts");
+    categoryDesc[0xcc] = QObject::tr("Politics");
+    categoryDesc[0xcf] = QObject::tr("Pro wrestling");
+    categoryDesc[0xd3] = QObject::tr("Sailing");
+    categoryDesc[0xd4] = QObject::tr("Shooting");
+    categoryDesc[0xd5] = QObject::tr("Sitcom");
+    categoryDesc[0xd6] = QObject::tr("Skateboarding");
+    categoryDesc[0xd9] = QObject::tr("Snowboarding");
+    categoryDesc[0xdd] = QObject::tr("Standup");
+    categoryDesc[0xdf] = QObject::tr("Surfing");
+    categoryDesc[0xe0] = QObject::tr("Tennis");
+    categoryDesc[0xe1] = QObject::tr("Triathlon");
+    categoryDesc[0xe6] = QObject::tr("Card games");
+    categoryDesc[0xe7] = QObject::tr("Poker");
+    categoryDesc[0xea] = QObject::tr("Military");
+    categoryDesc[0xeb] = QObject::tr("Technology");
+    categoryDesc[0xec] = QObject::tr("Mixed martial arts");
+    categoryDesc[0xed] = QObject::tr("Action sports");
+    categoryDesc[0xff] = QObject::tr("Dish Network");
+
+    categoriesExists = true;
+}
+
+
Index: libs/libmythtv/mpeg/dishdescriptors.h
===================================================================
--- libs/libmythtv/mpeg/dishdescriptors.h	(revision 26357)
+++ libs/libmythtv/mpeg/dishdescriptors.h	(working copy)
@@ -4,11 +4,73 @@
 #define _DISH_DESCRIPTORS_H_
 
 #include <cassert>
+#include <map>
 
+#include <QMutex>
 #include <QString>
 
 #include "atscdescriptors.h"
 
+class DishEventMPAADescriptor : public MPEGDescriptor
+{
+  public:
+    DishEventMPAADescriptor(const unsigned char* data)
+        : MPEGDescriptor(data)
+    {
+    //       Name             bits  loc  expected value
+    // descriptor_tag           8   0.0       0x89
+        assert(DescriptorID::dish_event_mpaa == DescriptorTag());
+    // descriptor_length        8   1.0
+    }
+    // stars                    3   2.0
+    uint stars_raw(void) const { return (_data[2] & 0xe0) >> 0x05; }
+    float stars(void) const;
+
+    // rating                   3   2.3
+    uint rating_raw(void) const { return (_data[2] & 0x1c) >> 0x02; }
+    QString rating(void) const;
+
+    // advisories               8   3.0
+    uint advisory_raw(void) const { return _data[3]; }
+    QString advisory(void) const;
+
+  private:
+    static void Init(void);
+
+  private:
+    static QMutex            mpaaRatingsLock;
+    static map<uint,QString> mpaaRatingsDesc;
+    static bool              mpaaRatingsExists;
+};
+
+class DishEventVCHIPDescriptor : public MPEGDescriptor
+{
+  public:
+    DishEventVCHIPDescriptor(const unsigned char* data)
+        : MPEGDescriptor(data)               
+    {
+    //       Name             bits  loc  expected value
+    // descriptor_tag           8   0.0       0x95
+        assert(DescriptorID::dish_event_vchip == DescriptorTag());
+    // descriptor_length        8   1.0
+    }
+    // rating                   8   2.0
+    uint rating_raw(void) const { return _data[2]; }
+    QString rating(void) const;
+
+    // advisory                 8   3.0
+    uint advisory_raw(void) const { return _data[3]; }
+    QString advisory(void) const;
+
+  private:
+    static void Init(void);
+
+  private:
+    static QMutex            vchipRatingsLock;
+    static map<uint,QString> vchipRatingsDesc;
+    static bool              vchipRatingsExists;
+};
+
 class DishEventNameDescriptor : public MPEGDescriptor
 {
   public:
@@ -45,4 +107,106 @@
     QString Description(uint) const;
 };
 
+class DishEventPropertiesDescriptor : public MPEGDescriptor
+{
+  public:
+    DishEventPropertiesDescriptor(const unsigned char* data)
+        : MPEGDescriptor(data)
+    {
+    //       Name             bits  loc  expected value
+    // descriptor_tag           8   0.0       0x94
+        assert(DescriptorID::dish_event_properties == DescriptorTag());
+    // descriptor_length        8   1.0
+    }
+    // unknown                  8   2.0
+    // event_name            dlen-1 3.0
+    bool HasProperties(void) const { return DescriptorLength() > 1; }
+    uint SubtitleProperties(uint compression_type) const;
+    uint AudioProperties(uint compression_type) const;
+
+  private:
+    void decompress_properties(uint compression_type) const;
+
+  private:
+    static uint subtitle_props;
+    static uint audio_props;
+    static bool decompressed;
+};
+
+class DishEventTagsDescriptor : public MPEGDescriptor
+{
+  public:
+    DishEventTagsDescriptor(const unsigned char* data)
+        : MPEGDescriptor(data)
+    {
+    //       Name             bits  loc  expected value
+    // descriptor_tag           8   0.0       0x96
+        assert(DescriptorID::dish_event_tags == DescriptorTag());
+    // descriptor_length        8   1.0
+    }
+    // unknown                  8   2.0
+    // seriesid                 28  3.0
+    QString seriesid(void) const;
+
+    // programid                42  3.0
+    QString programid(void) const;
+};
+
+typedef enum
+{
+    kThemeNone = 0,
+    kThemeMovie,
+    kThemeSports,
+    kThemeNews,
+    kThemeFamily,
+    kThemeEducation,
+    kThemeSeries,
+    kThemeMusic,
+    kThemeReligious,
+    kThemeOffAir,
+    kThemeLast,
+} DishThemeType;
+
+QString dish_theme_type_to_string(uint category_type);
+DishThemeType string_to_dish_theme_type(const QString &type);
+
+class DishContentDescriptor : public MPEGDescriptor
+{
+  public:
+    DishContentDescriptor(const unsigned char* data) : MPEGDescriptor(data)
+    {
+    //       Name             bits  loc  expected value
+    // descriptor_tag           8   0.0       0x54
+        assert(DescriptorID::content == DescriptorTag());
+    // descriptor_length        8   1.0
+    }
+
+    //   content_nibble_level_1 4   0.0
+    uint Nibble1(void)       const { return _data[2] >> 4; }
+    //   content_nibble_level_2 4   0.4
+    uint Nibble2(void)       const { return _data[2] & 0xf; }
+
+    uint Nibble(void)        const { return _data[2]; }
+
+    //   user_nibble            4   1.0
+    uint UserNibble1(void)   const { return _data[3] >> 4; }
+    //   user_nibble            4   1.4
+    uint UserNibble2(void)   const { return _data[3] & 0xf; }
+    uint UserNibble(void)    const { return _data[3]; }
+    // }                            2.0
+
+    DishThemeType GetTheme(void) const;
+    QString GetCategory(void) const;
+    QString toString() const;
+
+  private:
+    static void Init(void);
+
+  private:
+    static QMutex            categoryLock;
+    static map<uint,QString> themeDesc;
+    static map<uint,QString> categoryDesc;
+    static bool              categoriesExists;
+};
+
 #endif // _DISH_DESCRIPTORS_H_
Index: libs/libmythtv/mpeg/mpegdescriptors.h
===================================================================
--- libs/libmythtv/mpeg/mpegdescriptors.h	(revision 26357)
+++ libs/libmythtv/mpeg/mpegdescriptors.h	(working copy)
@@ -128,8 +128,13 @@
         content_advisory            = 0x87,
 
         // Dish Network
+        dish_event_rights           = 0x87,
+        dish_event_mpaa             = 0x89,
         dish_event_name             = 0x91,
         dish_event_description      = 0x92,
+        dish_event_properties       = 0x94,
+        dish_event_vchip            = 0x95,
+        dish_event_tags             = 0x96,
 
         // ATSC
         extended_channel_name       = 0xA0,
Index: libs/libmythtv/programdata.cpp
===================================================================
--- libs/libmythtv/programdata.cpp	(revision 26357)
+++ libs/libmythtv/programdata.cpp	(working copy)
@@ -162,6 +162,7 @@
     seriesId        = other.seriesId;
     programId       = other.programId;
     previouslyshown = other.previouslyshown;
+    ratings         = other.ratings;
 
     Squeeze();
 
@@ -257,7 +258,8 @@
         "       partnumber,     parttotal, "
         "       syndicatedepisodenumber, "
         "       airdate,        originalairdate, "
-        "       previouslyshown,listingsource "
+        "       previouslyshown,listingsource, "
+        "       stars+0 "
         "FROM program "
         "WHERE chanid   = :CHANID AND "
         "      manualid = 0       AND "
@@ -290,6 +292,7 @@
             query.value(7).toUInt(),
             query.value(8).toUInt(),
             query.value(9).toUInt(),
+            query.value(19).toDouble(),
             query.value(10).toString(),
             query.value(11).toString(),
             query.value(18).toUInt());
@@ -690,7 +693,7 @@
         "  starttime,      endtime, "
         "  closecaptioned, stereo,         hdtv,            subtitled, "
         "  subtitletypes,  audioprop,      videoprop, "
-        "  partnumber,     parttotal, "
+        "  stars,          partnumber,     parttotal, "
         "  syndicatedepisodenumber, "
         "  airdate,        originalairdate,listingsource, "
         "  seriesid,       programid,      previouslyshown ) "
@@ -700,7 +703,7 @@
         " :STARTTIME,     :ENDTIME, "
         " :CC,            :STEREO,        :HDTV,           :HASSUBTITLES, "
         " :SUBTYPES,      :AUDIOPROP,     :VIDEOPROP, "
-        " :PARTNUMBER,    :PARTTOTAL, "
+        " :STARS,         :PARTNUMBER,    :PARTTOTAL, "
         " :SYNDICATENO, "
         " :AIRDATE,       :ORIGAIRDATE,   :LSOURCE, "
         " :SERIESID,      :PROGRAMID,     :PREVSHOWN) ");
@@ -722,6 +725,7 @@
     query.bindValue(":SUBTYPES",    subtitleType);
     query.bindValue(":AUDIOPROP",   audioProps);
     query.bindValue(":VIDEOPROP",   videoProps);
+    query.bindValue(":STARS",       stars);
     query.bindValue(":PARTNUMBER",  partnumber);
     query.bindValue(":PARTTOTAL",   parttotal);
     query.bindValue(":SYNDICATENO", syndicatedepisodenumber);
@@ -769,7 +773,6 @@
     colorcode       = other.colorcode;
     clumpidx        = other.clumpidx;
     clumpmax        = other.clumpmax;
-    ratings         = other.ratings;
 
     squeeze_str(channel);
     squeeze_str(startts);
@@ -873,7 +876,7 @@
         return 0;
     }
 
-    QList<ProgRating>::const_iterator j = ratings.begin();
+    QList<EventRating>::const_iterator j = ratings.begin();
     for (; j != ratings.end(); ++j)
     {
         query.prepare(
Index: libs/libmythtv/programdata.h
===================================================================
--- libs/libmythtv/programdata.h	(revision 26357)
+++ libs/libmythtv/programdata.h	(working copy)
@@ -60,6 +60,13 @@
 };
 typedef vector<DBPerson> DBCredits;
 
+class MPUBLIC EventRating
+{
+  public:
+    QString system;
+    QString rating;
+};
+
 class MPUBLIC DBEvent
 {
   public:
@@ -77,6 +84,7 @@
         subtitleType(0),
         audioProps(0),
         videoProps(0),
+        stars(0.0),
         categoryType(0/*kCategoryNone*/),
         seriesId(QString::null),
         programId(QString::null),
@@ -90,6 +98,7 @@
             unsigned char    _subtitleType,
             unsigned char    _audioProps,
             unsigned char    _videoProps,
+            float            _stars,
             const QString   &_seriesId,  const QString   &_programId,
             uint32_t         _listingsource) :
         title(_title),           subtitle(_subtitle),
@@ -102,6 +111,7 @@
         syndicatedepisodenumber(QString("")),
         subtitleType(_subtitleType),
         audioProps(_audioProps), videoProps(_videoProps),
+        stars(_stars),
         categoryType(_category_type),
         seriesId(_seriesId),
         programId(_programId),
@@ -152,11 +162,13 @@
     unsigned char subtitleType;
     unsigned char audioProps;
     unsigned char videoProps;
+    float         stars;
     unsigned char categoryType;
     QString       seriesId;
     QString       programId;
     bool          previouslyshown;
     uint32_t      listingsource;
+    QList<EventRating> ratings;
 };
 
 class MPUBLIC DBEventEIT : public DBEvent
@@ -171,10 +183,11 @@
                unsigned char    _subtitleType,
                unsigned char    _audioProps,
                unsigned char    _videoProps,
+               float            _stars,
                const QString   &_seriesId,  const QString   &_programId) :
         DBEvent(_title, _subtitle, _desc, _category, _category_type,
                 _start, _end, _subtitleType, _audioProps, _videoProps,
-                _seriesId, _programId, kListingSourceEIT),
+                _stars, _seriesId, _programId, kListingSourceEIT),
         chanid(_chanid), fixup(_fixup)
     {
     }
@@ -188,7 +201,7 @@
                unsigned char    _videoProps) :
         DBEvent(_title, QString(""), _desc, QString(""), 0/*kCategoryNone*/,
                 _start, _end, _subtitleType, _audioProps, _videoProps,
-                QString(""), QString(""), kListingSourceEIT),
+                0.0, QString(""), QString(""), kListingSourceEIT),
         chanid(_chanid), fixup(_fixup)
     {
     }
@@ -203,13 +216,6 @@
     uint32_t      fixup;
 };
 
-class MPUBLIC ProgRating
-{
-  public:
-    QString system;
-    QString rating;
-};
-
 class MPUBLIC ProgInfo : public DBEvent
 {
   public:
@@ -245,7 +251,6 @@
     QString       colorcode;
     QString       clumpidx;
     QString       clumpmax;
-    QList<ProgRating> ratings;
 };
 
 class MPUBLIC ProgramData
Index: libs/libmythtv/eitfixup.h
===================================================================
--- libs/libmythtv/eitfixup.h	(revision 26357)
+++ libs/libmythtv/eitfixup.h	(working copy)
@@ -50,6 +50,7 @@
         kFixCategory   = 0x8000,
         kFixNO         = 0x10000,
         kFixNRK_DVBT   = 0x20000,
+        kFixDish       = 0x40000,
 
         // Early fixups
         kEFixForceISO8859_1  = 0x2000,
@@ -94,12 +95,22 @@
 
     const QRegExp m_bellYear;
     const QRegExp m_bellActors;
+    const QRegExp m_bellPPVTitleAllDayHD;
     const QRegExp m_bellPPVTitleAllDay;
     const QRegExp m_bellPPVTitleHD;
     const QRegExp m_bellPPVSubtitleAllDay;
     const QRegExp m_bellPPVDescriptionAllDay;
     const QRegExp m_bellPPVDescriptionAllDay2;
     const QRegExp m_bellPPVDescriptionEventId;
+    const QRegExp m_dishPPVTitleHD;
+    const QRegExp m_dishPPVTitleColon;
+    const QRegExp m_dishPPVSpacePerenEnd;
+    const QRegExp m_dishDescriptionNew;
+    const QRegExp m_dishDescriptionFinale;
+    const QRegExp m_dishDescriptionFinale2;
+    const QRegExp m_dishDescriptionPremiere;
+    const QRegExp m_dishDescriptionPremiere2;
+    const QRegExp m_dishPPVCode;
     const QRegExp m_ukThen;
     const QRegExp m_ukNew;
     const QRegExp m_ukCEPQ;
Index: programs/mythfilldatabase/xmltvparser.cpp
===================================================================
--- programs/mythfilldatabase/xmltvparser.cpp	(revision 26357)
+++ programs/mythfilldatabase/xmltvparser.cpp	(working copy)
@@ -403,7 +403,7 @@
                 QDomElement item = values.item(0).toElement();
                 if (item.isNull())
                     continue;
-                ProgRating rating;
+                EventRating rating;
                 rating.system = info.attribute("system", "");
                 rating.rating = getFirstText(item);
                 pginfo->ratings.append(rating);
