diff options
-rw-r--r-- | dish.c | 273 | ||||
-rw-r--r-- | dish.h | 27 | ||||
-rw-r--r-- | eepg.c | 99 |
3 files changed, 254 insertions, 145 deletions
@@ -14,6 +14,7 @@ #include <libsi/si.h> //#include <libsi/descriptor.h> #include <string.h> +#include <string> #include <stdlib.h> #include <vdr/tools.h> @@ -43,63 +44,67 @@ namespace SI DishDescriptor::DishDescriptor() { - name = ""; - shortText = ""; - description = ""; - decompressed = NULL; + name = NULL; + shortText = NULL; + description = NULL; + decompressedShort = NULL; + decompressedExtended = NULL; DishTheme = 0; DishCategory = 0; mpaaRating = 0; starRating = 0; + originalAirDate = 0; + programId = NULL; + seriesId = NULL; } DishDescriptor::~DishDescriptor() { - delete [] decompressed; - decompressed = NULL; -// delete name; -// name = NULL; -// delete shortText; -// shortText = NULL; -// delete description; -// description = NULL; + delete [] decompressedShort; + decompressedShort = NULL; + delete [] decompressedExtended; + decompressedExtended = NULL; + delete [] programId; + programId = NULL; + delete [] seriesId; + seriesId = NULL; } const char *DishDescriptor::getTheme() { - const char *theme; - using namespace DISH_THEMES; + const char* theme; + using namespace DISH_THEMES; switch (DishTheme){ - case Movie: - theme = "Movie"; - break; - case Sports: - theme = "Sports"; - break; - case News_Business: - theme = "News/Business"; - break; - case Family_Children: - theme = "Family/Children"; - break; - case Education: - theme = "Education"; - break; - case Series_Special: - theme = "Series/Special"; - break; - case Music_Art: - theme = "Music/Art"; - break; - case Religious: - theme = "Religious"; - break; - default: - theme = ""; - break; - } - return theme; + case Movie: + theme = "Movie"; + break; + case Sports: + theme = "Sports"; + break; + case News_Business: + theme = "News/Business"; + break; + case Family_Children: + theme = "Family/Children"; + break; + case Education: + theme = "Education"; + break; + case Series_Special: + theme = "Series/Special"; + break; + case Music_Art: + theme = "Music/Art"; + break; + case Religious: + theme = "Religious"; + break; + default: + theme = ""; + break; + } + return theme; } const char *DishDescriptor::getCategory() @@ -268,78 +273,100 @@ namespace SI void DishDescriptor::setShortData(unsigned char Tid, CharArray data) { - Decompress(Tid, data); - if (decompressed) { - name = string(reinterpret_cast<char*>(decompressed)); - delete[] decompressed; - decompressed = NULL; - } else { -// name = new string(); + decompressedShort = Decompress(Tid, data); + if (decompressedShort) { + name = (char*)decompressedShort; } } void DishDescriptor::setExtendedtData(unsigned char Tid, CharArray data) { - Decompress(Tid, data); - if (decompressed) { - string str; - char *split = strchr(reinterpret_cast<char*>(decompressed), 0x0D); // Look for carriage return + decompressedExtended = Decompress(Tid, data); + if (decompressedExtended) { + char *split = strchr((char*)((decompressedExtended)), 0x0D); // Look for carriage return //LogD(2, prep("dLength:%d, length:%d, count:%d, decompressed: %s"), dLength, length, count, decompressed); if(split){ *split = 0; - shortText = string(reinterpret_cast<char*>(decompressed)); - description = string((split[1] == 0x20) ? split + 2 : split + 1); + shortText = (char*)decompressedExtended; + description = (split[1] == 0x20) ? split + 2 : split + 1; }else{ - description = string(reinterpret_cast<char*>(decompressed)); + description = (char*)decompressedExtended; } - delete[] decompressed; - decompressed = NULL; - } else { -// shortText = new string(); -// description = new string(); } } const char *DishDescriptor::getShortText(void) { - isyslog("EEPG DISH: shortText: %s", shortText.c_str()); - string tmp = shortText; -// if (shortText != NULL) tmp += *shortText; - //if (shortText != NULL) tmp.append(shortText); - if(DishTheme > 0){ - if(tmp != "") tmp += " - "; - - tmp.append(getTheme()); - isyslog("EEPG DISH: theme: %s", getTheme()); - } - if(DishCategory > 0){ - if(tmp != "") tmp += " - "; - - isyslog("EEPG DISH: category: %s", getCategory()); - tmp.append(getCategory()); - } - isyslog("EEPG DISH: full shorttext: %s", tmp.c_str()); - return tmp.c_str(); +// string tmp = ""; +//// if (shortText != NULL) tmp += *shortText; +// tmp += shortText; +// if(DishTheme > 0){ +// if(tmp != "") tmp += " - "; +// +// tmp += getTheme(); +// } +// if(DishCategory > 0){ +// if(tmp != "") tmp += " - "; +// +// tmp += getCategory(); +// } +// return tmp.c_str(); + return shortText?shortText:""; } const char *DishDescriptor::getDescription(void) { - string tmp = description; -// if (description != NULL) tmp += *description; - tmp += description; - isyslog("EEPG DISH: description: %s", description.c_str()); - const char* rating = getRating(); - if (rating && strcmp(rating,"") != 0) { - if(tmp != "") tmp += " ~ "; - tmp += rating; - isyslog("EEPG DISH: rating: %s", rating); +// string tmp = ""; +//// if (description != NULL) tmp += *description; +// tmp += description; +// const char* rating = getRating(); +// if (rating && strcmp(rating,"") != 0) { +// if(tmp != "") tmp += " ~ "; +// tmp += rating; +// } +// if (starRating > 0) { +// if(tmp != "") tmp += " ~ "; +// tmp += getStarRating(); +// } +// return tmp.c_str(); + return description?description:""; + } + + const char *DishDescriptor::getProgramId(void) { + return programId?programId:""; + } + + const char *DishDescriptor::getSeriesId(void) { + return seriesId?seriesId:""; + } + + void DishDescriptor::setEpisodeInfo(CharArray data) + { + data.addOffset(2); + int series = (data[1] << 0x12) | (data[2] << 0x0a) | (data[3] << 0x02) | ((data[4] & 0xc0) >> 0x06); + int episode = ((data[4] & 0x3f) << 0x08) | data[5]; + const char* prefix; + + if (data[0] == 0x7c) + prefix = "MV"; + else if (data[0] == 0x7d) + prefix = "SP"; + else if (data[0] == 0x7e) + prefix = "EP"; + else + prefix =""; + + programId = new char[17]; + + sprintf(programId, "%s%08d%04d", (data[0] == 0x7e && episode == 0 ? "SH" : prefix), series, episode); + + if (data[0] == 0x7e) { + seriesId = new char[11]; + sprintf(seriesId, "%s%08d", prefix, series); } - if (starRating > 0) { - if(tmp != "") tmp += " ~ "; - tmp += getStarRating(); - isyslog("EEPG DISH: star: %s", getStarRating()); + + if (data.TwoBytes(6) != 0 && data.TwoBytes(6) != 0x9e8b ) { + originalAirDate = ((data[6] << 0x08 | data[7]) - 40587) * 86400; } - isyslog("EEPG DISH: full description: %s", tmp.c_str()); - return tmp.c_str(); } void DishDescriptor::setContent(ContentDescriptor::Nibble Nibble) @@ -364,24 +391,36 @@ namespace SI return ratings[mpaaRating]; } - char buffer[19]; - buffer[0] = 0; - strcpy(buffer, ratings[(mpaaRating >> 10) & 0x07]); + std::string str = ratings[(mpaaRating >> 10) & 0x07]; +// char buffer[19]; +// buffer[0] = 0; +// strcpy(buffer, ratings[(mpaaRating >> 10) & 0x07]); if (mpaaRating & 0x3A7F) { - strcat(buffer, " ["); + str += " ["; +// strcat(buffer, " ["); if (mpaaRating & 0x0230) - strcat(buffer, "V,"); + str += "V,"; +// strcat(buffer, "V,"); if (mpaaRating & 0x000A) - strcat(buffer, "L,"); + str += "L,"; +// strcat(buffer, "L,"); if (mpaaRating & 0x0044) - strcat(buffer, "N,"); + str += "N,"; +// strcat(buffer, "N,"); if (mpaaRating & 0x0101) - strcat(buffer, "SC,"); - if (char *s = strrchr(buffer, ',')) - s[0] = ']'; + str += "SC,"; +// strcat(buffer, "SC,"); +// if (char *s = strrchr(buffer, ',')) +// s[0] = ']'; + if (str.find(',') != std::string::npos) { + str.erase(str.find_last_of(',')); } + str += "]"; + } + + return str.c_str(); - return isempty(buffer) ? NULL : buffer; +// return isempty(buffer) ? "" : buffer; } const char* DishDescriptor::getStarRating(){ @@ -389,8 +428,7 @@ namespace SI return critiques[starRating & 0x07]; } - - void DishDescriptor::Decompress(unsigned char Tid, CharArray data) + unsigned char* DishDescriptor::Decompress(unsigned char Tid, CharArray data) { const unsigned char *str = data.getData(); const unsigned char *cmp = NULL; @@ -406,20 +444,20 @@ namespace SI cmp = str + 3; } if(length <= 0 || !dLength) - return; + return NULL; - decompressed = new unsigned char[dLength + 1]; + unsigned char* decompressed = new unsigned char[dLength + 1]; HuffmanTable *table; unsigned int tableSize, numBits; if (Tid > 0x80) { - table = Table255; - tableSize = SIZE_TABLE_255; - numBits = 13; + table = Table255; + tableSize = SIZE_TABLE_255; + numBits = 13; } else { - table = Table128; - tableSize = SIZE_TABLE_128; - numBits = 11; - } + table = Table128; + tableSize = SIZE_TABLE_128; + numBits = 11; + } unsigned int bLength = length << 3; // number of bits unsigned int currentBit = 0, count = 0; while(currentBit < bLength - 1 && count < dLength){ @@ -438,6 +476,7 @@ namespace SI } decompressed[count] = 0; + return decompressed; } struct DishDescriptor::HuffmanTable DishDescriptor::Table128[SIZE_TABLE_128] = { @@ -10,9 +10,9 @@ #ifndef LIBSI_DISH_H #define LIBSI_DISH_H -#include <string> #include <libsi/util.h> #include <libsi/descriptor.h> +#include <time.h> namespace SI { @@ -249,7 +249,7 @@ class DishDescriptor { public: DishDescriptor(); virtual ~DishDescriptor(); - const char* getName(void) const { return name.c_str(); } + const char* getName(void) const { return name; } const char* getShortText(void); const char *getDescription(void); // const char* getShortText(void) const { return shortText?shortText->c_str():""; } @@ -258,23 +258,32 @@ public: const char *getCategory(); const char *getRating(); const char *getStarRating(); + const char *getSeriesId(); + const char *getProgramId(); + time_t getOriginalAirDate() { return originalAirDate; } + bool hasTheme() {return DishTheme > 0;} + bool hasCategory() {return DishCategory > 0;} void setShortData(unsigned char Tid, CharArray data); void setExtendedtData(unsigned char Tid, CharArray data); void setRating(uint16_t value); void setContent(ContentDescriptor::Nibble Nibble); - + void setEpisodeInfo(CharArray data); protected: // Decompress the byte array and stores the result to a text string - void Decompress(unsigned char Tid, CharArray data); - string name; // name of the event - string shortText; // usually the episode name - string description; // description of the event - unsigned char *decompressed; + unsigned char* Decompress(unsigned char Tid, CharArray data); + const char* name; // name of the event + const char* shortText; // usually the episode name + const char* description; // description of the event + unsigned char* decompressedShort; + unsigned char* decompressedExtended; unsigned char DishTheme; unsigned char DishCategory; uint16_t mpaaRating; - uint16_t starRating; + uint8_t starRating; + time_t originalAirDate; + char* seriesId; + char* programId; struct HuffmanTable { @@ -2821,7 +2821,9 @@ namespace SI enum DescriptorTagExt { DishRatingDescriptorTag = 0x89, DishShortEventDescriptorTag = 0x91, - DishExtendedEventDescriptorTag = 0x92 }; + DishExtendedEventDescriptorTag = 0x92, + DishSeriesDescriptorTag = 0x96, + }; // typedef InheritEnum< DescriptorTagExt, SI::DescriptorTag > ExtendedDescriptorTag; @@ -2838,6 +2840,8 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat : SI::EIT (Data, false) { //LogD(2, prep("cEIT2::cEIT2")); + if (Tid > 0 && (Format == DISH_BEV || (SetupPE.ProcessEIT && isEITPid))) Tid--; + if (!CheckCRCAndParse ()) { LogD(2, prep("!CheckCRCAndParse ()")); return; @@ -2881,9 +2885,6 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat SegmentStart = SiEitEvent.getStartTime (); SegmentEnd = SiEitEvent.getStartTime () + SiEitEvent.getDuration (); int versionNumber = getVersionNumber(); - // increase version number for DISH_BEV EIT so it does not get overwriten by VDR. - // TODO check the same for other providers. - if ((Format == DISH_BEV || SetupPE.ProcessEIT )&& isEITPid) versionNumber++; cEvent *newEvent = NULL; cEvent *rEvent = NULL; @@ -2981,8 +2982,7 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat } // If the new event has a higher table ID, let's skip it. // The lower the table ID, the more "current" the information. - // if the Table ID is DEFAULT_TABLE_ID it is most probably EEPG event so we can overwrite - else if (Tid > pEvent->TableID() && (SetupPE.ProcessEIT ? pEvent->TableID () != DEFAULT_TABLE_ID : true)) + else if (Tid > pEvent->TableID()) continue; // If the new event comes from the same table and has the same version number // as the existing one, let's skip it to avoid unnecessary work. @@ -3033,7 +3033,7 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat continue; } - LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); + //LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); switch (d->getDescriptorTag ()) { case SI::ExtendedEventDescriptorTag: { @@ -3205,7 +3205,7 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat if (!DishEventDescriptor) { DishEventDescriptor = new SI::DishDescriptor(); } - DishEventDescriptor->setExtendedtData(Tid, deed->getData()); + DishEventDescriptor->setExtendedtData(Tid+1, deed->getData()); HasExternalData = true; } break; @@ -3214,15 +3214,31 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat if (!DishEventDescriptor) { DishEventDescriptor = new SI::DishDescriptor(); } - DishEventDescriptor->setShortData(Tid, dsed->getData()); + DishEventDescriptor->setShortData(Tid+1, dsed->getData()); HasExternalData = true; } break; case SI::DishRatingDescriptorTag: { - if (d->getLength() == 4 && DishEventDescriptor) { - uint16_t rating = d->getData().TwoBytes(2); - DishEventDescriptor->setRating(rating); - } + if (d->getLength() == 4) { + if (!DishEventDescriptor) { + DishEventDescriptor = new SI::DishDescriptor(); + } + uint16_t rating = d->getData().TwoBytes(2); + DishEventDescriptor->setRating(rating); + } + } + break; + case SI::DishSeriesDescriptorTag: { + if (d->getLength() == 10) { + //LogD(2, prep("DishSeriesDescriptorTag: %s)"), (const char*) d->getData().getData()); + if (!DishEventDescriptor) { + DishEventDescriptor = new SI::DishDescriptor(); + } + DishEventDescriptor->setEpisodeInfo(d->getData()); + } +// else { +// LogD(2, prep("DishSeriesDescriptorTag length: %d)"), d->getLength()); +// } } break; default: @@ -3258,14 +3274,59 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat LogD(3, prep("Description: %s"), pEvent->Description()); } else if (!HasExternalData) { pEvent->SetDescription (NULL); - LogD(3, prep("SetDescription (NULL)")); - } if (DishEventDescriptor) { - pEvent->SetTitle(DishEventDescriptor->getName()); - pEvent->SetDescription(DishEventDescriptor->getDescription()); - pEvent->SetShortText(DishEventDescriptor->getShortText()); - //LogD(2, prep("channelID: %s DishTitle: %s"), *channel->GetChannelID().ToString(), DishEventDescriptor->getName()); + if (DishEventDescriptor->getName()) + pEvent->SetTitle(DishEventDescriptor->getName()); + //LogD(2, prep("channelID: %s DishTitle: %s"), *channel->GetChannelID().ToString(), DishShortEventDescriptor->getText()); +// pEvent->SetDescription(DishExtendedEventDescriptor->getText()); + char *tmp; + string fmt; + fmt = "%s"; + if (0 != strcmp(DishEventDescriptor->getShortText(),"") && DishEventDescriptor->hasTheme()) { + fmt += " - "; + } + fmt += "%s"; + if (DishEventDescriptor->hasTheme() && DishEventDescriptor->hasCategory()) { + fmt += " ~ "; + } + fmt += "%s"; + + Asprintf (&tmp, fmt.c_str(), DishEventDescriptor->getShortText() + , DishEventDescriptor->getTheme() + , DishEventDescriptor->getCategory()); + pEvent->SetShortText(tmp); + //LogD(2, prep("EEPGDEBUG:DishTheme:%x-DishCategory:%x)"), DishTheme, DishCategory); + free(tmp); + + fmt = "%s"; + if (0 != strcmp(DishEventDescriptor->getDescription(),"") + && (0 != strcmp(DishEventDescriptor->getRating(),"") + || 0 != strcmp(DishEventDescriptor->getStarRating(),""))) { + fmt += "\n\nRating: "; + } + fmt += "%s %s"; + if (0 != strcmp(DishEventDescriptor->getProgramId(),"")) { + fmt += "\n\nProgram ID: "; + } + fmt += "%s %s%s"; + time_t orgAirDate = DishEventDescriptor->getOriginalAirDate(); + char datestr [80]; + bool dateok = false; + if (orgAirDate == 0) { + dateok = strftime (datestr,80," Original Air Date: %a %b %d %Y",gmtime(&orgAirDate)) > 0; + } + + Asprintf (&tmp, fmt.c_str(), DishEventDescriptor->getDescription() + , DishEventDescriptor->getRating() + , DishEventDescriptor->getStarRating() + , DishEventDescriptor->getProgramId() + , DishEventDescriptor->getSeriesId() + , orgAirDate == 0 || !dateok ? "" : datestr); + pEvent->SetDescription(tmp); + free(tmp); + + //LogD(2, prep("DishDescription: %s"), DishExtendedEventDescriptor->getText()); //LogD(2, prep("DishShortText: %s"), DishExtendedEventDescriptor->getShortText()); } |