diff options
author | Dimitar Petrovski <dimeptr@gmail.com> | 2011-11-01 09:58:09 +0100 |
---|---|---|
committer | Dimitar Petrovski <dimeptr@gmail.com> | 2011-11-01 09:58:09 +0100 |
commit | e239d8a308dcd76cb01d7bb05acb15167341cde5 (patch) | |
tree | e454fa2eb92998b96969975a4b5afb5c0f48e052 | |
parent | e6cc26ab4a3fb21510366ae25865be4aaca76e11 (diff) | |
parent | 726d99a3ed5c12242e0e3c6416b3175c18dbedfd (diff) | |
download | vdr-plugin-eepg-e239d8a308dcd76cb01d7bb05acb15167341cde5.tar.gz vdr-plugin-eepg-e239d8a308dcd76cb01d7bb05acb15167341cde5.tar.bz2 |
Merge branch 'Branch_na_ok' into experimental
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | dish.c | 616 | ||||
-rw-r--r-- | dish.h | 300 | ||||
-rw-r--r-- | eepg.c | 445 | ||||
-rw-r--r-- | eepg.h | 66 |
5 files changed, 1276 insertions, 158 deletions
@@ -65,7 +65,7 @@ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): -OBJS = $(PLUGIN).o +OBJS = $(PLUGIN).o dish.o ifdef DBG CXXFLAGS += -g @@ -78,7 +78,10 @@ I18Npot = $(PODIR)/$(PLUGIN).pot I18Nmsgs = $(addprefix $(LOCALEDIR)/,$(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo,$(notdir $(foreach file, $(wildcard $(PODIR)/*.po), $(basename $(file)))))) LOCALEDIR = $(VDRDIR)/locale -# Dependencies: +### Default Target +default: $(OBJS) + +### Dependencies: MAKEDEP = $(CXX) -MM -MG DEPFILE = .dependencies @@ -0,0 +1,616 @@ +/*************************************************************************** + * * + * These routines decompress Huffman coded Dish Network EIT data. * + * The implementation is based on the algorithm presentend in * + * * + * "A memory-efficient Huffman decoding algorithm" * + * Pi-Chung Wang, Yuan-Rung Yang, Chun-Liang Lee, Hung-Yi Chang * + * Proceedings of the 19th International Conference on Advanced * + * Information Networking and Applications (AINA'05) * + * * + ***************************************************************************/ + +#include "dish.h" +#include <libsi/si.h> +#include <libsi/descriptor.h> +#include <string.h> +#include <string> +#include <stdlib.h> +#include <vdr/tools.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)); + } + + DishDescriptor::DishDescriptor() + { + 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 [] 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; + + 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; + } + + const char *DishDescriptor::getCategory() + { + using namespace DISH_CATEGORIES; + + switch (DishCategory) { + case Action: return "Action"; + case ActionSports: return "Action Sports"; + case Adults_only: return "Adults only"; + case Adventure: return "Adventure"; + case Agriculture: return "Agriculture"; + case AirRacing: return "Air racing"; + case Animals: return "Animals"; + case Animated: return "Animated"; + case Anime: return "Anime"; + case Anthology: return "Anthology"; + case ArmWrestling: return "Arm wrestling"; + case Art: return "Art"; + case Arts_crafts: return "Arts/crafts"; + case Auction: return "Auction"; + case Auto: return "Auto"; + case AutoRacing: return "Auto racing"; + case Awards: return "Awards"; + case Badminton: return "Badminton"; + case Ballet: return "Ballet"; + case Baseball: return "Baseball"; + case Basketball: return "Basketball"; + case BicycleRacing: return "Bicycle racing"; + case Biography: return "Biography"; + case Boat: return "Boat"; + case BoatRacing: return "Boat racing"; + case Bowling: return "Bowling"; + case Boxing: return "Boxing"; + case Bus_financial: return "Bus./financial"; + case CardGames: return "Card games"; + case Children: return "Children"; + case ChildrenMusic: return "Children music"; + case ChildrenNews: return "Children news"; + case ChildrenSpecial: return "Children special"; + case Collectibles: return "Collectibles"; + case Comedy: return "Comedy"; + case ComedyDrama: return "Comedy-drama"; + case Community: return "Community"; + case Computers: return "Computers"; + case Consumer: return "Consumer"; + case Cooking: return "Cooking"; + case Crime: return "Crime"; + case CrimeDrama: return "Crime drama"; + case Dance: return "Dance"; + case Debate: return "Debate"; + case DishNetwork: return "Dish Network"; + case Docudrama: return "Docudrama"; + case Documentary: return "Documentary"; + case DogShow: return "DogShow"; + case DragRacing: return "DragRacing"; + case Drama: return "Drama"; + case Educational: return "Educational"; + case Entertainment: return "Entertainment"; + case Environment: return "Environment"; + case Equestrian: return "Equestrian"; + case Excercise: return "Excercise"; + case Fantasy: return "Fantasy"; + case Fashion: return "Fashion"; + case FieldHockey: return "Field hockey"; + case Fishing: return "Fishing"; + case Football: + case Football2: return "Football"; + case French: return "French"; + case Fundraiser: return "Fundraiser"; + case GameShow: return "GameShow"; + case Gay_lesbian: return "Gay/lesbian"; + case Golf: return "Golf"; + case Gymnastics: return "Gymnastics"; + case Handball: return "Handball"; + case Health: return "Health"; + case HistoricalDrama: return "Historical drama"; + case History: return "History"; + case Hockey: return "Hockey"; + case Holiday: return "Holiday"; + case HolidayChildren: return "Holiday children"; + case HolidayChildrenSpecial: return "Holiday children special"; + case HolidaySpecial: return "Holiday special"; + case HomeImprovement: return "Home improvement"; + case Horror: return "Horror"; + case HorseRacing: return "Horse racing"; + case House_garden: return "House/garden"; + case HowTo: return "HowTo"; + case Hunting: return "Hunting"; + case HydroplaneRacing: return "Hydroplane racing"; + case Interview: return "Interview"; + case Lacrosse: return "Lacrosse"; + case Law: return "Law"; + case MartialArts: return "Martial arts"; + case Medical: return "Medical"; + case Military: return "Military"; + case Miniseries: return "Miniseries"; + case MixedMartialArts: return "Mixed martial arts"; + case Motorcycle: return "Motorcycle"; + case MotorcycleRacing: return "Motorcycle racing"; + case Motorsports: return "Motorsports"; + case Music: return "Music"; + case MusicSpecial: return "Music special"; + case MusicTalk: return "Music talk"; + case Musical: return "Musical"; + case MusicalComedy: return "Musical comedy"; + case Mystery: return "Mystery"; + case Nature: return "Nature"; + case News: return "News"; + case Newsmagazine: return "Newsmagazine"; + case Opera: return "Opera"; + case Outdoors: return "Outdoors"; + case Paranormal: return "Paranormal"; + case Parenting: return "Parenting"; + case PerformingArts: return "Performing arts"; + case Poker: return "Poker"; + case Politics: return "Politics"; + case ProWrestling: return "Pro wrestling"; + case PublicAffairs: return "Public affairs"; + case Reality: return "Reality"; + case Religious: return "Religious"; + case Rodeo: return "Rodeo"; + case Romance: return "Romance"; + case RomanceComedy: return "Romance comedy"; + case Rugby: return "Rugby"; + case Running: return "Running"; + case Sailing: return "Sailing"; + case Science: return "Science"; + case ScienceFiction: return "Science fiction"; + case SelfImprovement: return "Self improvement"; + case Shooting: return "Shooting"; + case Shopping: return "Shopping"; + case Sitcom: return "Sitcom"; + case Skateboarding: return "Skateboarding"; + case Skiing: return "Skiing"; + case Snowboarding: return "Snowboarding"; + case Soap: return "Soap"; + case Soccor: return "Soccor"; + case Softball: return "Softball"; + case Spanish: return "Spanish"; + case Special: return "Special"; + case SportsNonEvent: return "SportsNonEvent"; + case SportsTalk: return "SportsTalk"; + case Standup: return "Standup"; + case Surfing: return "Surfing"; + case Suspense: return "Suspense"; + case Swimming: return "Swimming"; + case Talk: return "Talk"; + case Technology: return "Technology"; + case Tennis: + case Tennis2: return "Tennis"; + case Track_field: return "Track/field"; + case Travel: return "Travel"; + case Triathlon: return "Triathlon"; + case Variety: return "Variety"; + case Volleyball: return "Volleyball"; + case War: return "War"; + case Watersports: return "Watersports"; + case Weather: return "Weather"; + case Western: return "Western"; + case Wrestling: return "Wrestling"; + case Yoga: return "Yoga"; + default: return ""; + } + } + + void DishDescriptor::setShortData(unsigned char Tid, CharArray data) + { + decompressedShort = Decompress(Tid, data); + if (decompressedShort) { + name = (char*)decompressedShort; + } + } + + void DishDescriptor::setExtendedtData(unsigned char Tid, CharArray data) + { + 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 = (char*)decompressedExtended; + description = (split[1] == 0x20) ? split + 2 : split + 1; + }else{ + description = (char*)decompressedExtended; + } + } + } + + const char *DishDescriptor::getShortText(void) + { +// 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 = ""; +//// 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 (data.TwoBytes(6) != 0 && data.TwoBytes(6) != 0x9e8b ) { + originalAirDate = ((data[6] << 0x08 | data[7]) - 40587) * 86400; + } + } + + void DishDescriptor::setContent(ContentDescriptor::Nibble Nibble) + { + DishTheme = Nibble.getContentNibbleLevel2() & 0xF; + DishCategory = ((Nibble.getUserNibble1() & 0xF) << 4) | (Nibble.getUserNibble2() & 0xF); + } + + void DishDescriptor::setRating(uint16_t rating) + { + uint16_t newRating = (rating >> 10) & 0x07; + if (newRating == 0) newRating = 5; + if (newRating == 6) newRating = 0; + mpaaRating = (newRating << 10) | (rating & 0x3FF); + starRating = (rating >> 13) & 0x07; + } + + const char* DishDescriptor::getRating(){ + static const char *const ratings[8] = { "", "G", "PG", "PG-13", "R", "NR/AO", "", "NC-17" }; + + if (mpaaRating == 0) { + return ratings[mpaaRating]; + } + + std::string str = ratings[(mpaaRating >> 10) & 0x07]; +// char buffer[19]; +// buffer[0] = 0; +// strcpy(buffer, ratings[(mpaaRating >> 10) & 0x07]); + if (mpaaRating & 0x3A7F) { + str += " ["; +// strcat(buffer, " ["); + if (mpaaRating & 0x0230) + str += "V,"; +// strcat(buffer, "V,"); + if (mpaaRating & 0x000A) + str += "L,"; +// strcat(buffer, "L,"); + if (mpaaRating & 0x0044) + str += "N,"; +// strcat(buffer, "N,"); + if (mpaaRating & 0x0101) + 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) ? "" : buffer; + } + + const char* DishDescriptor::getStarRating(){ + static const char *const critiques[8] = { "", "*", "*+", "**", "**+", "***", "***+", "****" }; + return critiques[starRating & 0x07]; + } + + unsigned char* DishDescriptor::Decompress(unsigned char Tid, CharArray data) + { + const unsigned char *str = data.getData(); + const unsigned char *cmp = NULL; + int length = 0; // Length of compressed data + unsigned int dLength = 0; // Length of decompressed data + if((str[3] & 0xFC) == 0x80){ + length = str[1] - 2; + dLength = (str[2] & 0x40) ? ((str[3] << 6) & 0xFF) | (str[2] & 0x3F) : str[2] & 0x3F; + cmp = str + 4; + }else{ + length = str[1] - 1; + dLength = str[2] & 0x7F; + cmp = str + 3; + } + if(length <= 0 || !dLength) + return NULL; + + 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; + } else { + 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){ + // Find the interval containing the sequence of length numBits starting + // at currentBit. The corresponding character will be the one encoded + // at the begin of the sequence. + unsigned int code = getBits(currentBit, numBits, cmp, length); + // We could use a binary search, but in practice this linear search is faster. + unsigned int index = 0; + while(table[index].startingAddress <= code && index < tableSize){ + index++; + } + index--; + decompressed[count++] = table[index].character; + currentBit += table[index].numberOfBits; + } + + decompressed[count] = 0; + return decompressed; + } + + +struct DishDescriptor::HuffmanTable DishDescriptor::Table128[SIZE_TABLE_128] = { + { 0x0000, 0x20, 0x03 }, { 0x0100, 0x65, 0x04 }, { 0x0180, 0x74, 0x04 }, + { 0x0200, 0x61, 0x04 }, { 0x0280, 0x6F, 0x04 }, { 0x0300, 0x73, 0x04 }, + { 0x0380, 0x6E, 0x04 }, { 0x0400, 0x72, 0x06 }, { 0x0420, 0x69, 0x06 }, + { 0x0440, 0x6C, 0x06 }, { 0x0460, 0x63, 0x06 }, { 0x0480, 0x68, 0x06 }, + { 0x04A0, 0x75, 0x06 }, { 0x04C0, 0x64, 0x06 }, { 0x04E0, 0x70, 0x06 }, + { 0x0500, 0x6D, 0x06 }, { 0x0520, 0x67, 0x06 }, { 0x0540, 0x79, 0x06 }, + { 0x0560, 0x76, 0x06 }, { 0x0580, 0x0A, 0x06 }, { 0x05A0, 0x2E, 0x06 }, + { 0x05C0, 0x77, 0x06 }, { 0x05E0, 0x66, 0x06 }, { 0x0600, 0x53, 0x07 }, + { 0x0610, 0x62, 0x07 }, { 0x0620, 0x54, 0x07 }, { 0x0630, 0x22, 0x07 }, + { 0x0640, 0x6B, 0x07 }, { 0x0650, 0x50, 0x07 }, { 0x0660, 0x41, 0x07 }, + { 0x0670, 0x43, 0x07 }, { 0x0680, 0x44, 0x07 }, { 0x0690, 0x4C, 0x07 }, + { 0x06A0, 0x4D, 0x07 }, { 0x06B0, 0x49, 0x07 }, { 0x06C0, 0x4E, 0x07 }, + { 0x06D0, 0x3A, 0x07 }, { 0x06E0, 0x52, 0x07 }, { 0x06F0, 0x2C, 0x07 }, + { 0x0700, 0x45, 0x08 }, { 0x0708, 0x55, 0x08 }, { 0x0710, 0x46, 0x08 }, + { 0x0718, 0x48, 0x08 }, { 0x0720, 0x59, 0x08 }, { 0x0728, 0x56, 0x08 }, + { 0x0730, 0x2D, 0x08 }, { 0x0738, 0x7A, 0x08 }, { 0x0740, 0x78, 0x08 }, + { 0x0748, 0x2F, 0x08 }, { 0x0750, 0x4F, 0x08 }, { 0x0758, 0x3F, 0x08 }, + { 0x0760, 0x57, 0x08 }, { 0x0768, 0x47, 0x08 }, { 0x0770, 0x42, 0x08 }, + { 0x0778, 0x33, 0x08 }, { 0x0780, 0x31, 0x09 }, { 0x0784, 0x71, 0x09 }, + { 0x0788, 0x30, 0x09 }, { 0x078C, 0x21, 0x09 }, { 0x0790, 0x6A, 0x09 }, + { 0x0794, 0x5A, 0x09 }, { 0x0798, 0x39, 0x09 }, { 0x079C, 0x34, 0x09 }, + { 0x07A0, 0x4B, 0x09 }, { 0x07A4, 0x2A, 0x09 }, { 0x07A8, 0x37, 0x09 }, + { 0x07AC, 0x36, 0x09 }, { 0x07B0, 0x35, 0x09 }, { 0x07B4, 0x4A, 0x09 }, + { 0x07B8, 0x38, 0x09 }, { 0x07BC, 0x29, 0x09 }, { 0x07C0, 0x28, 0x0A }, + { 0x07C2, 0x58, 0x0A }, { 0x07C4, 0x51, 0x0A }, { 0x07C6, 0x3C, 0x0A }, + { 0x07C8, 0x32, 0x0A }, { 0x07CA, 0x27, 0x0A }, { 0x07CC, 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[SIZE_TABLE_255] = { + { 0x0000, 0x20, 0x02 }, { 0x0800, 0x65, 0x04 }, { 0x0A00, 0x72, 0x04 }, + { 0x0C00, 0x6E, 0x04 }, { 0x0E00, 0x61, 0x04 }, { 0x1000, 0x74, 0x05 }, + { 0x1100, 0x6F, 0x05 }, { 0x1200, 0x73, 0x05 }, { 0x1300, 0x69, 0x05 }, + { 0x1400, 0x6C, 0x05 }, { 0x1500, 0x75, 0x05 }, { 0x1600, 0x63, 0x05 }, + { 0x1700, 0x64, 0x05 }, { 0x1800, 0x70, 0x07 }, { 0x1840, 0x6D, 0x07 }, + { 0x1880, 0x76, 0x07 }, { 0x18C0, 0x67, 0x07 }, { 0x1900, 0x68, 0x07 }, + { 0x1940, 0x2E, 0x07 }, { 0x1980, 0x66, 0x07 }, { 0x19C0, 0x0A, 0x07 }, + { 0x1A00, 0x53, 0x07 }, { 0x1A40, 0x41, 0x07 }, { 0x1A80, 0x45, 0x07 }, + { 0x1AC0, 0x43, 0x07 }, { 0x1B00, 0x27, 0x07 }, { 0x1B40, 0x7A, 0x07 }, + { 0x1B80, 0x52, 0x07 }, { 0x1BC0, 0x22, 0x07 }, { 0x1C00, 0x4C, 0x08 }, + { 0x1C20, 0x49, 0x08 }, { 0x1C40, 0x4F, 0x08 }, { 0x1C60, 0x62, 0x08 }, + { 0x1C80, 0x54, 0x08 }, { 0x1CA0, 0x4E, 0x08 }, { 0x1CC0, 0x55, 0x08 }, + { 0x1CE0, 0x79, 0x08 }, { 0x1D00, 0x44, 0x08 }, { 0x1D20, 0x50, 0x08 }, + { 0x1D40, 0x71, 0x08 }, { 0x1D60, 0x56, 0x08 }, { 0x1D80, 0x2D, 0x08 }, + { 0x1DA0, 0x3A, 0x08 }, { 0x1DC0, 0x2C, 0x08 }, { 0x1DE0, 0x48, 0x08 }, + { 0x1E00, 0x4D, 0x09 }, { 0x1E10, 0x78, 0x09 }, { 0x1E20, 0x77, 0x09 }, + { 0x1E30, 0x42, 0x09 }, { 0x1E40, 0x47, 0x09 }, { 0x1E50, 0x46, 0x09 }, + { 0x1E60, 0x30, 0x09 }, { 0x1E70, 0x3F, 0x09 }, { 0x1E80, 0x33, 0x09 }, + { 0x1E90, 0x2F, 0x09 }, { 0x1EA0, 0x39, 0x09 }, { 0x1EB0, 0x31, 0x09 }, + { 0x1EC0, 0x38, 0x09 }, { 0x1ED0, 0x6B, 0x09 }, { 0x1EE0, 0x6A, 0x09 }, + { 0x1EF0, 0x21, 0x09 }, { 0x1F00, 0x36, 0x0A }, { 0x1F08, 0x35, 0x0A }, + { 0x1F10, 0x59, 0x0A }, { 0x1F18, 0x51, 0x0A }, { 0x1F20, 0x34, 0x0B }, + { 0x1F24, 0x58, 0x0B }, { 0x1F28, 0x32, 0x0B }, { 0x1F2C, 0x2B, 0x0B }, + { 0x1F30, 0x2A, 0x0B }, { 0x1F34, 0x5A, 0x0B }, { 0x1F38, 0x4A, 0x0B }, + { 0x1F3C, 0x29, 0x0B }, { 0x1F40, 0x28, 0x0C }, { 0x1F42, 0x23, 0x0C }, + { 0x1F44, 0x57, 0x0C }, { 0x1F46, 0x4B, 0x0C }, { 0x1F48, 0x3C, 0x0C }, + { 0x1F4A, 0x37, 0x0C }, { 0x1F4C, 0x7D, 0x0C }, { 0x1F4E, 0x7B, 0x0C }, + { 0x1F50, 0x60, 0x0C }, { 0x1F52, 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 @@ -0,0 +1,300 @@ +/*************************************************************************** + * * + * 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 <libsi/util.h> +#include <libsi/descriptor.h> +#include <time.h> + +namespace SI +{ + + namespace DISH_THEMES { + enum eDishThemes { + Movie = 0x01, + Sports = 0x02, + News_Business = 0x03, + Family_Children = 0x04, + Education = 0x05, + Series_Special = 0x06, + Music_Art = 0x07, + Religious = 0x08 + }; + }; + + namespace DISH_CATEGORIES { + enum eDishCategories { + Action = 0x01, + Adults_only = 0x02, + Adventure = 0x03, + Animals = 0x04, + Animated = 0x05, + // Anime + Anthology = 0x07, + Art = 0x08, + Auto = 0x09, + Awards = 0x0a, + Ballet = 0x0b, + Baseball = 0x0c, + Basketball = 0x0d, + // Beach soccer + // Beach volleyball + // Biathlon + Biography = 0x11, + Boat = 0x12, + // Boat racing + Bowling = 0x14, + Boxing = 0x15, + Bus_financial = 0x16, + Children = 0x1a, + ChildrenSpecial = 0x1b, + ChildrenNews = 0x1c, + ChildrenMusic = 0x1d, + Collectibles = 0x1f, + Comedy = 0x20, + ComedyDrama = 0x21, + Computers = 0x22, + Cooking = 0x23, + Crime = 0x24, + CrimeDrama = 0x25, + // Curling + Dance = 0x27, + // Dark comedy + Docudrama = 0x29, + Documentary = 0x2a, + Drama = 0x2b, + Educational = 0x2c, + // Erotic + Excercise = 0x2f, + Fantasy = 0x31, + Fashion = 0x32, + // Fencing + Fishing = 0x34, + Football = 0x35, + French = 0x36, + Fundraiser = 0x37, + GameShow = 0x38, + Golf = 0x39, + Gymnastics = 0x3a, + Health = 0x3b, + History = 0x3c, + HistoricalDrama = 0x3d, + Hockey = 0x3e, + Holiday = 0x3f, + HolidayChildren = 0x40, + HolidayChildrenSpecial = 0x41, + // Holiday music + // Holiday music special + HolidaySpecial = 0x44, + Horror = 0x45, + HorseRacing = 0x46, + House_garden = 0x47, + HowTo = 0x49, + Interview = 0x4b, + Lacrosse = 0x4d, + MartialArts = 0x4f, + Medical = 0x50, + Miniseries = 0x51, + Motorsports = 0x52, + Motorcycle = 0x53, + Music = 0x54, + MusicSpecial = 0x55, + MusicTalk = 0x56, + Musical = 0x57, + MusicalComedy = 0x58, + Mystery = 0x5a, + Nature = 0x5b, + News = 0x5c, + // Olympics + Opera = 0x5f, + Outdoors = 0x60, + // Parade + // Politics = 0x62, + PublicAffairs = 0x63, + Reality = 0x66, + Religious = 0x67, + Rodeo = 0x68, + Romance = 0x69, + RomanceComedy = 0x6a, + Rugby = 0x6b, + Running = 0x6c, + Science = 0x6e, + ScienceFiction = 0x6f, + SelfImprovement = 0x70, + Shopping = 0x71, + Skiing = 0x74, + Soap = 0x77, + // Soap special + // Soap talk + Soccor = 0x7b, + Softball = 0x7c, + Spanish = 0x7d, + Special = 0x7e, + // Speedskating + // Sports event + SportsNonEvent = 0x81, + SportsTalk = 0x82, + Suspense = 0x83, + Swimming = 0x85, + Talk = 0x86, + Tennis = 0x87, + // Theater + // Thriller + Track_field = 0x89, + Travel = 0x8a, + Variety = 0x8b, + Volleyball = 0x8c, + War = 0x8d, + Watersports = 0x8e, + Weather = 0x8f, + Western = 0x90, + Wrestling = 0x92, + Yoga = 0x93, + Agriculture = 0x94, + Anime = 0x95, + ArmWrestling = 0x97, + Arts_crafts = 0x98, + Auction = 0x99, + AutoRacing = 0x9a, + AirRacing = 0x9b, + Badminton = 0x9c, + // Bicycle + BicycleRacing = 0xa0, + BoatRacing = 0xa1, + // Bobsled + // Bodybilding + // Canoe + // Cheerleading + Community = 0xa6, + Consumer = 0xa7, + // Darts + Debate = 0xaa, + // Diving + DogShow = 0xac, + DragRacing = 0xad, + Entertainment = 0xae, + Environment = 0xaf, + Equestrian = 0xb0, + // Event + FieldHockey = 0xb3, + // Figure skating + Football2 = 0xb5, + Gay_lesbian = 0xb6, + Handball = 0xb7, + HomeImprovement = 0xb8, + Hunting = 0xb9, + // Hurling + HydroplaneRacing = 0xbb, + // Indoor soccer + // Intl hockey + // Intl soccer + // Kayaking + Law = 0xc1, + // Luge + // Mountain biking + MotorcycleRacing = 0xc3, + Newsmagazine = 0xc5, + Paranormal = 0xc7, + Parenting = 0xc8, + PerformingArts = 0xca, + // Playoff sports + Politics = 0xcc, + // Polo + // Pool + ProWrestling = 0xcf, + // Ringuette + // Roller derby + // Rowing + Sailing = 0xd3, + Shooting = 0xd4, + Sitcom = 0xd5, + Skateboarding = 0xd6, + // Skating + // Skeleton + Snowboarding = 0xd9, + // Snowmobile = 0xda, + Standup = 0xdd, + // Sumo wrestling + Surfing = 0xdf, + Tennis2 = 0xe0, + Triathlon = 0xe1, + // Water polo + // Water skiing + // Weightlifting + // Yacht racing + CardGames = 0xe6 , + Poker = 0xe7 , + // Musical = 0xe9, + Military = 0xea, + Technology = 0xeb, + MixedMartialArts = 0xec, + ActionSports = 0xed, + DishNetwork = 0xff + }; + }; +#define SIZE_TABLE_128 128 +#define SIZE_TABLE_255 255 + +class UnimplementedDescriptor; + +class DishDescriptor { +public: + DishDescriptor(); + virtual ~DishDescriptor(); + 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():""; } + // const char* getDescription(void) const { return description?description->c_str():""; } + const char *getTheme(); + 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 + 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; + uint8_t starRating; + time_t originalAirDate; + char* seriesId; + char* programId; + + + struct HuffmanTable { + unsigned int startingAddress; + unsigned char character; + unsigned char numberOfBits; + }; + static HuffmanTable Table128[SIZE_TABLE_128]; + static HuffmanTable Table255[SIZE_TABLE_255]; + +}; + +} /* namespace SI */ +#endif /* LIBSI_DISH_H */ @@ -10,7 +10,6 @@ * -Freesat patch written by dom /at/ suborbital.org.uk * * - * This code 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. @@ -37,12 +36,13 @@ #include <libsi/descriptor.h> #include <libsi/si.h> #include "eepg.h" +#include "dish.h" #include <map> #include <string> #include <stdarg.h> -#define VERBOSE 1 +#define VERBOSE 3 /* 0 = only print errors, 1 = print channels and themes, 2 = print channels, themes, titles, summaries 3 = debug mode */ /* all is logged into /var/log/syslog */ @@ -258,6 +258,26 @@ static int AvailableSources[32]; static int NumberOfAvailableSources = 0; static int LastVersionNagra = -1; //currently only used for Nagra, should be stored per transponder, per system +#ifdef USE_NOEPG +bool allowedEPG (tChannelID kanalID) +{ + bool rc; + + if (Setup.noEPGMode == 1) { + rc = false; + if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL) + rc = true; + } else { + rc = true; + if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL) + rc = false; + } + + return rc; +} +#endif /* NOEPG */ + + class cFilterEEPG:public cFilter { private: @@ -268,7 +288,7 @@ private: bool EndChannels, EndThemes; //only used for ?? int MHWStartTime; //only used for MHW1 bool ChannelsOk; - int Format; //the format that this filter currently is processing + //int Format; //the format that this filter currently is processing std::map < int, int >ChannelSeq; // ChannelSeq[ChannelId] returns the recordnumber of the channel Summary_t *Summaries[MAX_TITLES]; @@ -286,10 +306,8 @@ private: unsigned char InitialSummary[64]; void NextPmt (void); + void ProccessContinuous(u_short Pid, u_char Tid, int Length, const u_char *Data); protected: -#ifdef USE_NOEPG - virtual bool allowedEPG (tChannelID kanalID); -#endif virtual void Process (u_short Pid, u_char Tid, const u_char * Data, int Length); virtual void AddFilter (u_short Pid, u_char Tid); virtual void AddFilter (u_short Pid, u_char Tid, unsigned char Mask); @@ -350,7 +368,7 @@ void cFilterEEPG::SetStatus (bool On) if (!On) { FreeSummaries (); FreeTitles (); - Format = 0; + //Format = 0; ChannelsOk = false; NumberOfTables = 0; } else { @@ -371,25 +389,6 @@ void cFilterEEPG::NextPmt (void) LogE(3, prep("PMT next\n")); } -//TODO next routine is also in cEIT2, make this simpler -#ifdef USE_NOEPG -bool cFilterEEPG::allowedEPG (tChannelID kanalID) -{ - bool rc; - - if (Setup.noEPGMode == 1) { - rc = false; - if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL) - rc = true; - } else { - rc = true; - if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL) - rc = false; - } - - return rc; -} -#endif /* NOEPG */ // ------------------- Freesat ------------------- @@ -668,6 +667,8 @@ void GetLocalTimeOffset (void) void CleanString (unsigned char *String) { + +// LogD (1, prep("Unclean: %s"), String); unsigned char *Src; unsigned char *Dst; int Spaces; @@ -698,10 +699,10 @@ void CleanString (unsigned char *String) } if (Spaces < 2) { *Dst = *Src; - *Dst++; + Dst++; pC++; } - *Src++; + Src++; } if (Spaces > 0) { Dst--; @@ -709,6 +710,25 @@ void CleanString (unsigned char *String) } else { *Dst = 0; } +// LogD (1, prep("Clean: %s"), String); +} + +cChannel *GetChannelByID(tChannelID & channelID, bool searchOtherPos) +{ + cChannel *VC = Channels.GetByChannelID(channelID, true); + if(!VC && searchOtherPos){ + //look on other satpositions + for(int i = 0;i < NumberOfAvailableSources;i++){ + channelID = tChannelID(AvailableSources[i], channelID.Nid(), channelID.Tid(), channelID.Sid()); + VC = Channels.GetByChannelID(channelID, true); + if(VC){ + //found this actually on satellite nextdoor... + break; + } + } + } + + return VC; } bool cFilterEEPG::GetThemesSKYBOX (void) //TODO can't we read this from the DVB stream? @@ -1147,8 +1167,8 @@ int cFilterEEPG::GetChannelsMHW (const u_char * Data, int Length, int MHW) memcpy (C->Name, &Channel->Name, 16); //MHW1 else { //MHW2 int lenName = Data[pName] & 0x0f; - if (lenName < 256) //TODO impossible, after & 0x0f lenName is always < 0x0f !! - decodeText2(&Data[pName+1],lenName,(char*)C->Name,256); + //LogD (1, prep("EEPGDebug: MHW2 lenName:%d"), lenName); + decodeText2(&Data[pName+1],lenName,(char*)C->Name,256); //memcpy (C->Name, &Data[pName + 1], lenName); //else //memcpy (C->Name, &Data[pName + 1], 256); @@ -1160,18 +1180,10 @@ int cFilterEEPG::GetChannelsMHW (const u_char * Data, int Length, int MHW) C->Tid[0] = HILO16 (Channel->TransportId); C->Sid[0] = HILO16 (Channel->ServiceId); tChannelID channelID = tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]); - cChannel *VC = Channels.GetByChannelID (channelID, true); + cChannel *VC = GetChannelByID(channelID, true); bool IsFound = (VC); - if (!IsFound) { //look on other satpositions - for (int i = 0; i < NumberOfAvailableSources; i++) { - channelID = tChannelID (AvailableSources[i], C->Nid[0], C->Tid[0], C->Sid[0]); - VC = Channels.GetByChannelID (channelID, true); - IsFound = (VC); - if (IsFound) { //found this actually on satellite nextdoor... - C->Src[0] = AvailableSources[i]; - break; - } - } + if(IsFound) { + C->Src[0] = VC->Source(); } CleanString (C->Name); @@ -1215,7 +1227,7 @@ int cFilterEEPG::GetThemesMHW1 (const u_char * Data, int Length) ThemeId++; } memcpy (&Themes[Offset][0], &Theme->Name, 15); - Themes[Offset][15] = NULL; //trailing null + Themes[Offset][15] = '\0'; //trailing null CleanString (Themes[Offset]); LogI(1, prep("%.15s"), Themes[Offset]); Offset++; @@ -1238,7 +1250,7 @@ int cFilterEEPG::GetThemesMHW1 (const u_char * Data, int Length) */ int cFilterEEPG::GetThemesMHW2 (const u_char * Data, int Length) { - if (!EndThemes) { //only proces if not processed + if (!EndThemes) { //only process if not processed int p1; int p2; int pThemeName = 0; @@ -1391,7 +1403,7 @@ char *cFilterEEPG::GetSummaryTextNagra (const u_char * DataStart, long int Offse LastTextBlock = ((ST->LastTextNr == 0) || (ST->TextNr >= ST->LastTextNr)); } while (!LastTextBlock); Text = (unsigned char *) realloc (Text, 1 + TotLength); //allocate 1 extra byte - Text[TotLength] = NULL; //terminate string by NULL char + Text[TotLength] = '\0'; //terminate string by NULL char LogD(5, prep("DEBUG: Full Text:%s."), Text); break; @@ -1678,7 +1690,7 @@ void cFilterEEPG::GetTitlesNagra (const u_char * Data, int Length, unsigned shor } while (p < DataEnd); //end of TitleBlock } -int cFilterEEPG::GetThemesNagra (const u_char * Data, int Length, unsigned short TableIdExtension) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed +int cFilterEEPG::GetThemesNagra (const u_char * Data, int Length, unsigned short TableIdExtension) //return code 0 = fatal error, code 1 = success, code 2 = last item processed { u_char *DataStart = (u_char *) Data; u_char *p = DataStart; //TODO Language code terminated by 0 is ignored @@ -1752,7 +1764,7 @@ int cFilterEEPG::GetThemesNagra (const u_char * Data, int Length, unsigned short continue; } memcpy (&Themes[ThemeId], Text, Textlength); - Themes[ThemeId][Textlength] = NULL; //trailing NULL + Themes[ThemeId][Textlength] = '\0'; //trailing NULL CleanString (Themes[ThemeId]); nThemes++; LogI(1, prep("%02x %s"), ThemeId, Themes[ThemeId]); @@ -1791,30 +1803,20 @@ int cFilterEEPG::GetChannelsNagra (const u_char * Data, int Length) ChannelSeq[C->ChannelId] = j; //fill lookup table to go from channel-id to sequence nr in table; lookuptable starts with 0 C->SkyNumber = 0; C->NumberOfEquivalences = 1; //there is always an original channel. every equivalence adds 1 - C->Src[0] = Source (); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!! + C->Src[0] = Source(); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!! C->Nid[0] = HILO16 (Channel->NetworkId); C->Tid[0] = HILO16 (Channel->TransportId); C->Sid[0] = HILO16 (Channel->ServiceId); - tChannelID channelID = tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]); - cChannel *VC = Channels.GetByChannelID (channelID, true); + tChannelID channelID = tChannelID(C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]); + cChannel *VC = GetChannelByID(channelID, true); bool IsFound = (VC); - - if (!IsFound) { //look on other satpositions - for (int i = 0; i < NumberOfAvailableSources; i++) { - channelID = tChannelID (AvailableSources[i], C->Nid[0], C->Tid[0], C->Sid[0]); - VC = Channels.GetByChannelID (channelID, true); - IsFound = (VC); - if (IsFound) { //found this actually on satellite nextdoor... - C->Src[0] = AvailableSources[i]; - break; - } - } + if(IsFound) { + strncpy((char*)(C->Name), VC->Name (), 64); + C->Src[0] = VC->Source(); + CleanString (C->Name); } - if (IsFound) - strncpy ((char *) C->Name, VC->Name (), 64); else - C->Name[0] = NULL; //empty string - CleanString (C->Name); + C->Name[0] = '\0'; //empty string LogI(1, "|% 5d | %-26.26s | %-22.22s | %-3.3s | % 6d |\n", C->ChannelId , *channelID.ToString(), C->Name, IsFound ? "YES" : "NO", C->SkyNumber); @@ -1977,7 +1979,7 @@ int cFilterEEPG::GetNagra (const u_char * Data, int Length) void cFilterEEPG::ProcessNagra () { for (int i = 0; i < MAX_THEMES; i++) //clear all themes - Themes[i][0] = NULL; + Themes[i][0] = '\0'; for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes unsigned short int TableIdExtension = NagraTIE[i]; @@ -2062,7 +2064,7 @@ int cFilterEEPG::GetTitlesMHW1 (const u_char * Data, int Length) LogE(0, prep("Titles memory allocation error.")); return 0; } - T->Text[46] = NULL; //end string with NULL character + T->Text[46] = '\0'; //end string with NULL character //memcpy (T->Text, &Title->Title, 23); decodeText2((unsigned char *)&Title->Title, 23, (char*)T->Text, 47); CleanString (T->Text); @@ -2143,7 +2145,7 @@ int cFilterEEPG::GetTitlesMHW2 (const u_char * Data, int Length) LogE(0, prep("Titles memory allocation error.")); return 0; //fatal error } - T->Text[Len] = NULL; //end string with NULL character + T->Text[Len] = '\0'; //end string with NULL character decodeText2(&Data[Pos + 8],Len,(char*)T->Text,Len+1); //memcpy (T->Text, &Data[Pos + 8], Len); CleanString (T->Text); @@ -2190,7 +2192,7 @@ int cFilterEEPG::GetSummariesMHW1 (const u_char * Data, int Length) LogE(0, prep("Summaries memory allocation error.")); return 0; } - Text[SummaryLength+1] = NULL; //end string with NULL character + Text[SummaryLength+1] = '\0'; //end string with NULL character //memcpy (Text, &Data[SummaryOffset], SummaryLength); decodeText2(&Data[SummaryOffset], SummaryLength, (char*)Text, 2*SummaryLength + 1); // CleanString (Text); @@ -2314,7 +2316,7 @@ int cFilterEEPG::GetSummariesMHW2 (const u_char * Data, int Length) } } S->Text = (unsigned char *) malloc (SummaryLength + 2); - S->Text[SummaryLength] = NULL; //end string with NULL character + S->Text[SummaryLength] = '\0'; //end string with NULL character if (S->Text == NULL) { LogE(0, prep("Summaries memory allocation error.")); return 0; //fatal error @@ -2401,7 +2403,7 @@ int cFilterEEPG::GetChannelsSKYBOX (const u_char * Data, int Length) if (IsFound) strncpy ((char *) C->Name, VC->Name (), 64); else - C->Name[0] = NULL; //empty string + C->Name[0] = '\0'; //empty string LogI(1, "|% 5d | %-26.26s | %-22.22s | %-3.3s | % 6d |\n", C->ChannelId , *channelID.ToString(), C->Name, IsFound ? "YES" : "NO", C->SkyNumber); @@ -2510,7 +2512,7 @@ int cFilterEEPG::GetTitlesSKYBOX (const u_char * Data, int Length) LogE(0, prep("Titles memory allocation error.")); return 0; } - T->Text[Len2] = NULL; //end string with NULL character + T->Text[Len2] = '\0'; //end string with NULL character memcpy (T->Text, tmp, Len2); CleanString (T->Text); T->SummaryAvailable = 1; //TODO I assume this is true? @@ -2589,7 +2591,7 @@ int cFilterEEPG::GetSummariesSKYBOX (const u_char * Data, int Length) return 0; } memcpy (S->Text, tmp, Len2); - S->Text[Len2] = NULL; //end string with NULL character + S->Text[Len2] = '\0'; //end string with NULL character CleanString (S->Text); LogI(3, prep("EventId %08x Summnr %d:%.30s."), S->EventId, nSummaries, S->Text); p += Len1; @@ -2676,8 +2678,9 @@ void cFilterEEPG::LoadIntoSchedule (void) //esyslog("foundtitle %x for next title that has a summary:%d",foundtitle,i); if (!foundtitle) //no more titles with summaries - break; //TODO: does this work??? - if ((T->EventId == S->EventId) && (T->MjdTime == S->Replays[0].MjdTime) && ((T->ChannelId == S->Replays[0].ChannelId) || ((Format != SKY_IT) && (Format != SKY_UK)))) { //should always be true, titles and summaries are broadcasted in order... + break; + if ((T->EventId == S->EventId) && (T->MjdTime == S->Replays[0].MjdTime) + && ((T->ChannelId == S->Replays[0].ChannelId) || ((Format != SKY_IT) && (Format != SKY_UK)))) { //should always be true, titles and summaries are broadcasted in order... LogD(3, prep("T->EventId == S->EventId")); //MjdTime = 0 for all but SKY //S->ChannelId must be equal to T->ChannelId only for SKY; in MHW1 S->ChannelId overrides T->ChannelId when NumReplays > 1 @@ -2809,50 +2812,45 @@ void cFilterEEPG::AddFilter (u_short Pid, u_char Tid, unsigned char Mask) namespace SI { + enum DescriptorTagExt { + DishRatingDescriptorTag = 0x89, + DishShortEventDescriptorTag = 0x91, + DishExtendedEventDescriptorTag = 0x92, + DishSeriesDescriptorTag = 0x96, + }; + + // typedef InheritEnum< DescriptorTagExt, SI::DescriptorTag > ExtendedDescriptorTag; + /*extern const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte = NULL); extern bool convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode); extern bool SystemCharacterTableIsSingleByte;*/ class cEIT2:public SI::EIT { public: - cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, - bool OnlyRunningStatus = false); - -#ifdef USE_NOEPG -private: - bool allowedEPG (tChannelID kanalID); -#endif /* NOEPG */ + cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool OnlyRunningStatus = false); }; -#ifdef USE_NOEPG -bool cEIT2::allowedEPG (tChannelID kanalID) -{ - bool rc; - - if (Setup.noEPGMode == 1) { - rc = false; - if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL) - rc = true; - } else { - rc = true; - if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL) - rc = false; - } - - return rc; -} -#endif /* NOEPG */ - cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool OnlyRunningStatus) : SI::EIT (Data, false) { - if (!CheckCRCAndParse ()) + //LogD(2, prep("cEIT2::cEIT2")); + if (Tid > 0 && Format == DISH_BEV) Tid--; + + if (!CheckCRCAndParse ()) { + LogD(2, prep("!CheckCRCAndParse ()")); return; + } + + bool searchOtherSatPositions = Format == DISH_BEV; tChannelID channelID (Source, getOriginalNetworkId (), getTransportStreamId (), getServiceId ()); - cChannel *channel = Channels.GetByChannelID (channelID, true); - if (!channel) + cChannel *channel = GetChannelByID (channelID, searchOtherSatPositions); + if (!channel) { + LogD(3, prep("!channel channelID: %s"), *channelID.ToString()); return; // only collect data for known channels + } + + LogD(4, prep("channelID: %s format:%d"), *channel->GetChannelID().ToString(), Format); #ifdef USE_NOEPG // only use epg from channels not blocked by noEPG-patch @@ -2983,7 +2981,7 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers. - else if (Tid == pEvent->TableID () && pEvent->Version () == getVersionNumber ()) + else if (Tid == pEvent->TableID() && pEvent->Version() == getVersionNumber()) continue; } if (!ExternalData) { @@ -3004,7 +3002,7 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat } if (OnlyRunningStatus) continue; // do this before setting the version, so that the full update can be done later - pEvent->SetVersion (getVersionNumber ()); + pEvent->SetVersion (getVersionNumber()); int LanguagePreferenceShort = -1; int LanguagePreferenceExt = -1; @@ -3012,13 +3010,22 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat SI::Descriptor * d; SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL; SI::ShortEventDescriptor * ShortEventDescriptor = NULL; + //SI::DishDescriptor *DishExtendedEventDescriptor = NULL; + SI::DishDescriptor *DishEventDescriptor = NULL; + //uchar DishTheme = 0, DishCategory = 0; + + cLinkChannels *LinkChannels = NULL; cComponents *Components = NULL; for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext (it2));) { if (ExternalData && d->getDescriptorTag () != SI::ComponentDescriptorTag) { delete d; + LogD(2, prep("continue:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); continue; } + + //LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x)"), d->getDescriptorTag ()); + switch (d->getDescriptorTag ()) { case SI::ExtendedEventDescriptorTag: { SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d; @@ -3057,6 +3064,12 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat Contents[NumContents] = ((Nibble.getContentNibbleLevel1() & 0xF) << 4) | (Nibble.getContentNibbleLevel2() & 0xF); NumContents++; } + if (DishEventDescriptor && NumContents == 1) { + DishEventDescriptor->setContent(Nibble); + } + //LogD(2, prep("EEPGDEBUG:Nibble:%x-%x-%x-%x)"), Nibble.getContentNibbleLevel1(),Nibble.getContentNibbleLevel2() + // , Nibble.getUserNibble1(), Nibble.getUserNibble2()); + } pEvent->SetContents(Contents); } @@ -3151,7 +3164,6 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat link = Channels.NewChannel (transponder, linkName, "", "", ld->getOriginalNetworkId (), ld->getTransportStreamId (), ld->getServiceId ()); - //XXX patFilter->Trigger(); } if (link) { if (!LinkChannels) @@ -3179,6 +3191,47 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat } } break; + case SI::DishExtendedEventDescriptorTag: { + SI::UnimplementedDescriptor *deed = (SI::UnimplementedDescriptor *)d; + if (!DishEventDescriptor) { + DishEventDescriptor = new SI::DishDescriptor(); + } + DishEventDescriptor->setExtendedtData(Tid+1, deed->getData()); + HasExternalData = true; + } + break; + case SI::DishShortEventDescriptorTag: { + SI::UnimplementedDescriptor *dsed = (SI::UnimplementedDescriptor *)d; + if (!DishEventDescriptor) { + DishEventDescriptor = new SI::DishDescriptor(); + } + DishEventDescriptor->setShortData(Tid+1, dsed->getData()); + HasExternalData = true; + } + break; + case SI::DishRatingDescriptorTag: { + 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: break; } @@ -3189,12 +3242,12 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat if (ShortEventDescriptor) { char buffer[Utf8BufSize (256)]; unsigned char *f; - int l = ShortEventDescriptor->name.getLength (); + int l = ShortEventDescriptor->name.getLength(); f = (unsigned char *) ShortEventDescriptor->name.getData().getData(); decodeText2 (f, l, buffer, sizeof (buffer)); //ShortEventDescriptor->name.getText(buffer, sizeof(buffer)); pEvent->SetTitle (buffer); - l = ShortEventDescriptor->text.getLength (); + l = ShortEventDescriptor->text.getLength(); f = (unsigned char *) ShortEventDescriptor->text.getData().getData(); decodeText2 (f, l, buffer, sizeof (buffer)); //ShortEventDescriptor->text.getText(buffer, sizeof(buffer)); @@ -3208,12 +3261,75 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")); } else if (!HasExternalData) pEvent->SetDescription (NULL); + + if (DishEventDescriptor) { + 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()); + } } delete ExtendedEventDescriptors; delete ShortEventDescriptor; + delete DishEventDescriptor; pEvent->SetComponents (Components); +// LogD(2, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title()); + +// if (pEvent->ChannelID() == tChannelID::FromString("S119.0W-4100-6-110-110")) { +// LogD(2, prep("ID: %d Title: %s Time: %d Tid: 0x%x"), pEvent->EventID(), pEvent->Title(), pEvent->StartTime(), pEvent->TableID()); +// } + if (!HasExternalData) pEvent->FixEpgBugs (); if (LinkChannels) @@ -3285,16 +3401,21 @@ cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Dat pSchedule->ClrRunningStatus (channel); if (Tid == 0x4E) pSchedule->SetPresentSeen (); - if (OnlyRunningStatus) + if (OnlyRunningStatus) { + LogD(2, prep("OnlyRunningStatus")); return; + } if (Modified) { pSchedule->Sort (); if (!HasExternalData) pSchedule->DropOutdated (SegmentStart, SegmentEnd, Tid, getVersionNumber ()); Schedules->SetModified (pSchedule); } + LogD(2, prep("end of cEIT2")); + } //end of cEIT2 + } //end namespace SI void cFilterEEPG::ProcessNextFormat (bool FirstTime = false) @@ -3343,16 +3464,19 @@ void cFilterEEPG::ProcessNextFormat (bool FirstTime = false) //now start looking for next format to process int pid; - Format = -1; //unused value - for (int i = 0; i <= HIGHEST_FORMAT; i++) //find first format that is detected + for (int i = 0; i <= HIGHEST_FORMAT; i++){ //find first format that is detected if (UnprocessedFormat[i]) { isyslog ("EEPG: %s Extended EPG detected on pid %x.", FormatName[i], UnprocessedFormat[i]); - Format = i; - } //highest format is processed first this way;; TODO make sure that CONT protocols like Premiere, Freesat are processed AFTER ONCE protocols like MHW, SKY and NAGRA - - if (Format == -1) { //there are no formats left to process - isyslog ("EEPG: Ended all processing"); - return; + Format = (EFormat)i; + // highest format is processed first this way + // make sure that CONT protocols like Premiere, Freesat are processed + // AFTER ONCE protocols like MHW, SKY and NAGRA + break; + } + if (i == HIGHEST_FORMAT) { //there are no formats left to process + isyslog ("EEPG: Ended all processing"); + return; + } } pid = UnprocessedFormat[Format]; //and reinstall its pid @@ -3391,18 +3515,51 @@ void cFilterEEPG::ProcessNextFormat (bool FirstTime = false) AddFilter (0x39, 0x60, 0xf0); //event info, other TS, Viasat break; case NAGRA: - // isyslog ("EEPG: NagraGuide Extended EPG detected."); AddFilter (pid, 0xb0); //perhaps TID is equal to first data byte? break; + case DISH_BEV: + AddFilter (0x12, 0, 0); // event info, actual(0x4e)/other(0x4f) TS, present/following + AddFilter (0x0300, 0, 0); // Dish Network EEPG event info, actual(0x4e)/other(0x4f) TS, present/following + AddFilter (0x0441, 0, 0); // Dish Network EEPG event info, actual(0x4e)/other(0x4f) TS, present/following +// AddFilter (0x0441, 0x50, 0xf0); // Bell ExpressVU EEPG +// AddFilter (0x0441, 0x60, 0xf0); // Bell ExpressVU EEPG + break; default: break; } } +void cFilterEEPG::ProccessContinuous(u_short Pid, u_char Tid, int Length, const u_char *Data) +{ + //0x39 Viasat, 0x0300 Dish Network EEPG, 0x0441 Bell ExpressVU EEPG + LogD(4, prep("Pid: 0x%02x Tid: %d Length: %d"), Pid, Tid, Length); + cSchedulesLock SchedulesLock(true, 10); + cSchedules *Schedules = (cSchedules*)(cSchedules::Schedules(SchedulesLock)); + //Look for other satelite positions only if Dish/Bell ExpressVU for the moment hardcoded pid check + if(Schedules) + SI::cEIT2 EIT(Schedules, Source(), Tid, Data); + + else//cEIT EIT (Schedules, Source (), Tid, Data); + { + // If we don't get a write lock, let's at least get a read lock, so + // that we can set the running status and 'seen' timestamp (well, actually + // with a read lock we shouldn't be doing that, but it's only integers that + // get changed, so it should be ok) + cSchedulesLock SchedulesLock; + cSchedules *Schedules = (cSchedules*)(cSchedules::Schedules(SchedulesLock)); + if(Schedules) + SI::cEIT2 EIT(Schedules, Source(), Tid, Data, true); + + //cEIT EIT (Schedules, Source (), Tid, Data, true); + } +} + void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Length) { int now = time (0); - //LogD(5, prep("PMT pid now 0x%04x pid now 0x%04x"), Pid, Tid); +// LogD(2, prep("Pid: 0x%02x Tid: %d Length: %d PMT pid: 0x%04x"), Pid, Tid, Length, pmtpid); +// LogD(2, prep("Source: %d Transponder: %d"), Source () , Transponder ()); + if (Pid == 0 && Tid == SI::TableIdPAT) { if (!pmtnext || now > pmtnext) { if (pmtpid) @@ -3443,8 +3600,8 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len if (pmt.CheckCRCAndParse () && pmt.getServiceId () == pmtsid) { SI::PMT::Stream stream; for (SI::Loop::Iterator it; pmt.streamLoop.getNext (stream, it);) { -// if(stream.getStreamType()==0x05) { - if (stream.getStreamType () == 0x05 || stream.getStreamType () == 0xc1) { //0x05 = Premiere, SKY, Freeview, Nagra 0xc1 = MHW1,MHW2 + LogD(2, prep("StreamType: 0x%02x"), stream.getStreamType ()); + if (stream.getStreamType () == 0x05 || stream.getStreamType () == 0xc1) { //0x05 = Premiere, SKY, Freeview, Nagra 0xc1 = MHW1,MHW2; SI::CharArray data = stream.getData (); if ((data[1] & 0xE0) == 0xE0 && (data[3] & 0xF0) == 0xF0) { bool prvData = false, usrData = false; @@ -3453,11 +3610,12 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len if (data[2]==0x39) {//TODO Test This prvFRV = true; usrFRV = 1; + LogD(1, prep("if (data[2]==0x39) {//TODO Test This")); } //Format = 0; // 0 = premiere, 1 = MHW1, 2 = MHW2, 3 = Sky Italy (OpenTV), 4 = Sky UK (OpenTV), 5 = Freesat (Freeview), 6 = Nagraguide SI::Descriptor * d; for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext (it));) { - //esyslog ("EEPGDEBUG:d->getDescriptorTAG():%x,SI::PrivateTag:%x\n", d->getDescriptorTag (), SI::PrivateDataSpecifierDescriptorTag); + LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x,SI::PrivateTag:%x\n"), d->getDescriptorTag (), SI::PrivateDataSpecifierDescriptorTag); switch (d->getDescriptorTag ()) { case SI::PrivateDataSpecifierDescriptorTag: //esyslog ("prv: %d %08x\n", d->getLength (), d->getData ().FourBytes (2)); @@ -3472,7 +3630,6 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len //if (d->getLength () == 3 && d->getData ().FourBytes (2) == 0xb07ea882) { if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb000)) UnprocessedFormat[NAGRA] = stream.getPid (); - //int nop; //FIXME break; case 0x90: //esyslog ("usr: %d %08x\n", d->getLength (), d->getData ().FourBytes (2)); @@ -3482,9 +3639,7 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len //if (d->getLength () == 3 && (d->getData ().TwoBytes (2) == 0xb6a5)) //SKY IT //TODO ugly! usrOTV = SKY_IT; //Format = SKY_IT; - if (d->getLength () == 3 && d->getData ().FourBytes (2) == 0xc004e288) //SKY UK - //if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0x9d00)) //SKY UK //TODO ugly! usrOTV = SKY_UK; //Format = SKY_UK; break; @@ -3496,12 +3651,12 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len case 0xc2: //MHW1, MHW2 if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x45504700) //MHw1 CanDigNL and CSat UnprocessedFormat[MHW1] = stream.getPid (); - //int nop;//FIXME else if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x46494348) { //MHW2 UnprocessedFormat[MHW2] = stream.getPid (); } break; case 0xd1: //Freeview + LogD(1, prep("case 0xd1: //Freeview")); if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0x0100)) usrFRV = 0x01; //01 = EIT pid 3842 @@ -3528,8 +3683,17 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len UnprocessedFormat[FREEVIEW] = stream.getPid (); if (prvData && usrData) UnprocessedFormat[PREMIERE] = stream.getPid (); - } //if data[1] && data [3] - } //if streamtype + //TODO DPE this is not good since the DISH/BEV filters are always on, but have to test somehow. + //EEPG:12472:H:S119.0W:20000:0:0:0:0:36862:4100:18:36862 + if (((Source() == cSource::FromString("S119.0W") + && Transponder() == cChannel::Transponder(12472,'H')) + || (Source() == cSource::FromString("S91.0W") + && Transponder() == cChannel::Transponder(12224,'R'))) + && !UnprocessedFormat[DISH_BEV]) { + UnprocessedFormat[DISH_BEV] = stream.getPid (); + } + } //if data[1] && data [3] + } //if streamtype /*if (Format != PREMIERE) //any format found break; //break out for loop */ } //for loop that walks through streams @@ -3547,6 +3711,12 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len } //checkCRC } //if pmtpid else if (Source ()) { + + if ( Pid == 0x12 || Pid == 0x0300 || Pid == 0x0441 ) { + if (Tid >= 0x4E) + ProccessContinuous(Pid, Tid, Length, Data); + return; + } int Result; switch (Tid) { case 0xA0: //TODO DPE test this missing break but it seems a bug @@ -3767,23 +3937,8 @@ void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Len // PID found: 3843 (0x0f03) [SECTION: ATSC reserved] TODO find out what compressed text info is here! // PID found: 3844 (0x0f04) [SECTION: Time Offset Table (TOT)] - if (Pid == 3842 || Pid ==0x39) {//0x39 Viasat - cSchedulesLock SchedulesLock (true, 10); - cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock); - if (Schedules) - SI::cEIT2 EIT (Schedules, Source (), Tid, Data); - //cEIT EIT (Schedules, Source (), Tid, Data); - else { - // If we don't get a write lock, let's at least get a read lock, so - // that we can set the running status and 'seen' timestamp (well, actually - // with a read lock we shouldn't be doing that, but it's only integers that - // get changed, so it should be ok) - cSchedulesLock SchedulesLock; - cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock); - if (Schedules) - SI::cEIT2 EIT (Schedules, Source (), Tid, Data, true); - //cEIT EIT (Schedules, Source (), Tid, Data, true); - } + if (Pid == 3842 || Pid == 0x39) {//0x39 Viasat, 0x0300 Dish Network EEPG, 0x0441 Bell ExpressVU EEPG + ProccessContinuous(Pid, Tid, Length, Data); } break; @@ -10,21 +10,34 @@ #define MAX_EQUIVALENCES 8 //the number of equivalences one channel can have //Formats (need to be consecutively numbered): -//First all CONTinuous protocols, so they will be processed LAST: -#define PREMIERE 0 -#define FREEVIEW 1 -//Then all batchmode, load ONCE protocols: -#define MHW1 2 -#define MHW2 3 -#define SKY_IT 4 -#define SKY_UK 5 -#define NAGRA 6 -#define HIGHEST_FORMAT 6 //the highest number of EPG-formats that is supported by this plugin +//#define PREMIERE 0 +//#define FREEVIEW 1 +//#define MHW1 2 +//#define MHW2 3 +//#define SKY_IT 4 +//#define SKY_UK 5 +//#define NAGRA 6 +//#define HIGHEST_FORMAT 6 + +enum EFormat { +//First all batchmode, load ONCE protocols: + MHW1 = 0, + MHW2 , + SKY_IT , + SKY_UK , + NAGRA , +//Than all CONTinuous protocols, so they will be processed LAST: + PREMIERE , + FREEVIEW , + DISH_BEV , +//the highest number of EPG-formats that is supported by this plugin + HIGHEST_FORMAT = DISH_BEV +} Format; #define NAGRA_TABLE_ID 0x55 //the lower the table Id, the more "current" it is; table_id 0x00 never gets overwritten, now/next are at 0x4e or 0x4f! #define DEFAULT_TABLE_ID 0x30 -const char *FormatName[]= {"Premiere","FreeView","MediaHighWay 1","MediaHighWay 2","Sky Italy","Sky UK","NagraGuide"}; +const char *FormatName[]= {"MediaHighWay 1","MediaHighWay 2","Sky Italy","Sky UK","NagraGuide","Premiere","FreeView","Dish/Bev"}; struct sNode { @@ -75,6 +88,37 @@ typedef struct { unsigned char * Text; } Summary_t; + +// -- InheritEnum.h +template <typename EnumT, typename BaseEnumT> +class InheritEnum +{ +public: + InheritEnum() {} + InheritEnum(EnumT e) + : enum_(e) + {} + + InheritEnum(BaseEnumT e) + : baseEnum_(e) + {} + + explicit InheritEnum( int val ) + : enum_(static_cast<EnumT>(val)) + {} + + operator EnumT() const { return enum_; } +private: + // Note - the value is declared as a union mainly for as a debugging aid. If + // the union is undesired and you have other methods of debugging, change it + // to either of EnumT and do a cast for the constructor that accepts BaseEnumT. + union + { + EnumT enum_; + BaseEnumT baseEnum_; + }; +}; + static const char *FileEquivalences[] = { "#", "# Simply add a list of the channels in this file with the following format:", |