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-16 14:20:32.000000000 -0500 @@ -1106,6 +1106,20 @@ } return NULL; } + +cChannel *cChannels::GetByChannelID(int nid, int tid, int sid) +{ + cList *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-16 14:20:32.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-16 16:48:22.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,11 +119,13 @@ 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; 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; @@ -144,6 +146,26 @@ UseExtendedEventDescriptor = false; } break; + case SI::DishExtendedEventDescriptorTag: { + SI::DishDescriptor *sed = (SI::DishDescriptor *)d; + if (!DishExtendedEventDescriptor) { + delete DishExtendedEventDescriptor; + DishExtendedEventDescriptor = sed; + d = NULL; // so that it is not deleted + } + HasExternalData = true; + } + break; + case SI::DishShortEventDescriptorTag: { + SI::DishDescriptor *sed = (SI::DishDescriptor *)d; + if (!DishShortEventDescriptor) { + delete DishShortEventDescriptor; + DishShortEventDescriptor = sed; + 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) { @@ -188,6 +210,10 @@ } } break; + case SI::DishRatingDescriptorTag: + if (d->getLength() == 4) + pEvent->SetRating(d->getData().TwoBytes(2)); + 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 +297,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 +320,8 @@ else if (!HasExternalData) pEvent->SetDescription(NULL); } + delete DishExtendedEventDescriptor; + delete DishShortEventDescriptor; delete ExtendedEventDescriptors; delete ShortEventDescriptor; @@ -355,7 +390,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 +411,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 14:20:32.000000000 -0500 @@ -117,6 +117,7 @@ startTime = 0; duration = 0; vps = 0; + rating = 0x1800; SetSeen(); } @@ -422,7 +423,7 @@ void cEvent::Dump(FILE *f, const char *Prefix, bool InfoOnly) const { if (InfoOnly || startTime + duration + Setup.EPGLinger * 60 >= time(NULL)) { - fprintf(f, "%sE %u %ld %d %X %X\n", Prefix, eventID, startTime, duration, tableID, version); + fprintf(f, "%sE %u %ld %d %X %X %.4hX\n", Prefix, eventID, startTime, duration, tableID, version, rating); if (!isempty(title)) fprintf(f, "%sT %s\n", Prefix, title); if (!isempty(shortText)) @@ -511,8 +512,9 @@ int Duration; unsigned int TableID = 0; unsigned int Version = 0xFF; // actual value is ignored - int n = sscanf(t, "%u %ld %d %X %X", &EventID, &StartTime, &Duration, &TableID, &Version); - if (n >= 3 && n <= 5) { + uint16_t Rating = 0x1800; + int n = sscanf(t, "%u %ld %d %X %X %hX", &EventID, &StartTime, &Duration, &TableID, &Version, &Rating); + if (n >= 3 && n <= 6) { Event = (cEvent *)Schedule->GetEvent(EventID, StartTime); cEvent *newEvent = NULL; if (Event) @@ -525,6 +527,7 @@ Event->SetTableID(TableID); Event->SetStartTime(StartTime); Event->SetDuration(Duration); + Event->SetRating(Rating); if (newEvent) Schedule->AddEvent(newEvent); } 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-16 14:20:32.000000000 -0500 @@ -33,6 +33,8 @@ #define EVCONTENTMASK_SPECIAL 0xB0 #define EVCONTENTMASK_USERDEFINED 0xF0 +#define VDR_RATINGS_PATCHED + enum eDumpMode { dmAll, dmPresent, dmFollowing, dmAtTime }; struct tComponent { @@ -83,6 +85,7 @@ int duration; // Duration of this event in seconds time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL) time_t seen; // When this event was last seen in the data stream + uint16_t rating; // Dish/BEV Parental Rating public: cEvent(tEventID EventID); ~cEvent(); @@ -104,6 +107,7 @@ int Duration(void) const { return duration; } time_t Vps(void) const { return vps; } time_t Seen(void) const { return seen; } + uint16_t Rating(void) const { return rating; } bool SeenWithin(int Seconds) const { return time(NULL) - seen < Seconds; } bool HasTimer(void) const; bool IsRunning(bool OrAboutToStart = false) const; @@ -127,6 +131,7 @@ void SetDuration(int Duration); void SetVps(time_t Vps); void SetSeen(void); + void SetRating(uint16_t Rating) { rating = Rating; } cString ToDescr(void) const; void Dump(FILE *f, const char *Prefix = "", bool InfoOnly = false) const; bool Parse(char *s); 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-16 14:20:32.000000000 -0500 @@ -0,0 +1,499 @@ +/*************************************************************************** + * * + * 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 +#include + +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); +} + +DishDescriptor::DishDescriptor(unsigned char TID) +{ + Tid = TID; + text = NULL; + shortText = NULL; + decompressed = NULL; +} + +DishDescriptor::~DishDescriptor() +{ + free(decompressed); +} + +void DishDescriptor::Parse() +{ + const unsigned char *str = data.getData(); + + if ((str[3]&0xF8) == 0x80) { + int dlen = (str[2]&0x40) ? ((str[3] << 6)&0xFF) | (str[2]&0x3F) : str[2]&0x3F; // Educated guess... + Decompress(str+4, str[1]-2, dlen); + } + else + Decompress(str+3, str[1]-1, str[2]&0x7F); +} + +void DishDescriptor::Decompress(const unsigned char *compressed, int length, int dLength) +{ + if (!length || !dLength) + return; + + decompressed = (unsigned char*)malloc(dLength+1); + + int tableSize = (Tid > 0x80) ? MAX_TABLE255 : MAX_TABLE128; + HuffmanTable *ptrTable = (Tid > 0x80) ? Table255 : Table128; + + 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) { + // starting from the current bit + // try to find the sequence in the decode list + int i; + for (i = 0; i < tableSize; i++) { + unsigned int bits = getBits(currentBit, ptrTable[i].numberOfBits, compressed, length); + if (bits == ptrTable[i].encodedSequence) { + decompressed[count++] = ptrTable[i].character; + currentBit += ptrTable[i].numberOfBits; + break; + } + } + + if (i == tableSize) // if we get here then the bit sequence was not found, try to recover. + 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; + } +} + +struct DishDescriptor::HuffmanTable 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::HuffmanTable 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 } // '' +} ; + +} //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-16 14:20:32.000000000 -0500 @@ -0,0 +1,48 @@ +/*************************************************************************** + * * + * 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 128 +#define MAX_TABLE255 255 + +namespace SI { + +class DishDescriptor : public Descriptor { +public: + DishDescriptor(unsigned char TID); + ~DishDescriptor(); + const char* getText() const { return text; } + const char* getShortText() const { return shortText; } + +protected: + // decompress the byte arrary and stores the result to a text string + void Decompress(const unsigned char *compressed, int length, int dLength); + virtual void Parse(); + + const char* text; // name or description of the event + const char* shortText; // usually the episode name + unsigned char* decompressed; + unsigned char Tid; + + struct HuffmanTable { + unsigned int encodedSequence; + 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-16 14:20:32.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 14:20:32.000000000 -0500 @@ -17,6 +17,7 @@ #include // for broadcaster stupidity workaround #include #include "descriptor.h" +#include "dish.h" namespace SI { @@ -109,9 +110,9 @@ return (DescriptorTag)((const DescriptorHeader*)d)->descriptor_tag; } -Descriptor *DescriptorLoop::getNext(Iterator &it) { +Descriptor *DescriptorLoop::getNext(Iterator &it, u_char Tid) { if (isValid() && it.igetLength(); @@ -488,7 +489,7 @@ } } -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: @@ -605,6 +606,12 @@ case ExtensionDescriptorTag: d=new ExtensionDescriptor(); break; + case DishShortEventDescriptorTag: + d=new DishDescriptor(Tid); + break; + case DishExtendedEventDescriptorTag: + d=new DishDescriptor(Tid); + 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 14:20:32.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, @@ -283,7 +286,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 { @@ -347,7 +350,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, @@ -388,7 +391,7 @@ return count; } protected: - Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor); + Descriptor *createDescriptor(int &i, bool returnUnimplemetedDescriptor, u_char Tid=0); DescriptorTagDomain domain; }; 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:21:28.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) {