summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitar Petrovski <dimeptr@gmail.com>2011-11-01 09:58:09 +0100
committerDimitar Petrovski <dimeptr@gmail.com>2011-11-01 09:58:09 +0100
commite239d8a308dcd76cb01d7bb05acb15167341cde5 (patch)
treee454fa2eb92998b96969975a4b5afb5c0f48e052
parente6cc26ab4a3fb21510366ae25865be4aaca76e11 (diff)
parent726d99a3ed5c12242e0e3c6416b3175c18dbedfd (diff)
downloadvdr-plugin-eepg-e239d8a308dcd76cb01d7bb05acb15167341cde5.tar.gz
vdr-plugin-eepg-e239d8a308dcd76cb01d7bb05acb15167341cde5.tar.bz2
Merge branch 'Branch_na_ok' into experimental
-rw-r--r--Makefile7
-rw-r--r--dish.c616
-rw-r--r--dish.h300
-rw-r--r--eepg.c445
-rw-r--r--eepg.h66
5 files changed, 1276 insertions, 158 deletions
diff --git a/Makefile b/Makefile
index 4d28ef7..19c0684 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/dish.c b/dish.c
new file mode 100644
index 0000000..021ac72
--- /dev/null
+++ b/dish.c
@@ -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
diff --git a/dish.h b/dish.h
new file mode 100644
index 0000000..07f0547
--- /dev/null
+++ b/dish.h
@@ -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 */
diff --git a/eepg.c b/eepg.c
index a3ec6e7..05ab246 100644
--- a/eepg.c
+++ b/eepg.c
@@ -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;
diff --git a/eepg.h b/eepg.h
index 01fa877..503e800 100644
--- a/eepg.h
+++ b/eepg.h
@@ -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:",