summaryrefslogtreecommitdiff
path: root/eepg.c
diff options
context:
space:
mode:
authorDimitar Petrovski <dimeptr@gmail.com>2012-05-18 08:41:26 +0200
committerDimitar Petrovski <dimeptr@gmail.com>2012-05-18 08:41:26 +0200
commit16676f55d7aabc55a7b2894dbdf79a462749767f (patch)
treeaf7ac2254d0682b4d3f1da1a0b5f02be3da2f54e /eepg.c
parente7383edb0b991c6f3f185fbdf1b09cb485780b36 (diff)
parent27fd448d11b6eda6b72d294b73d42a54e1891ad9 (diff)
downloadvdr-plugin-eepg-16676f55d7aabc55a7b2894dbdf79a462749767f.tar.gz
vdr-plugin-eepg-16676f55d7aabc55a7b2894dbdf79a462749767f.tar.bz2
Merge branch 'experimental'
Conflicts: eepg.c
Diffstat (limited to 'eepg.c')
-rw-r--r--eepg.c5831
1 files changed, 2994 insertions, 2837 deletions
diff --git a/eepg.c b/eepg.c
index 883bff6..e469313 100644
--- a/eepg.c
+++ b/eepg.c
@@ -37,8 +37,11 @@
#include <libsi/descriptor.h>
#include <libsi/si.h>
#include "eepg.h"
+#include "dish.h"
#include <map>
+#include <string>
+#include <stdarg.h>
#define VERBOSE 1
/* 0 = only print errors, 1 = print channels and themes, 2 = print channels, themes, titles, summaries 3 = debug mode */
@@ -57,20 +60,30 @@
/*#ifdef DEBUG
#define d(x) { (x); }
#else
-#define d(x) ;
+#define d(x) ;
#endif
#ifdef DEBUG2
#define d2(x) { (x); }
#else
-#define d2(x) ;
+#define d2(x) ;
#endif*/
-#define PMT_SCAN_TIMEOUT 10 // seconds
-#define PMT_SCAN_IDLE 3600 // seconds
+#define PMT_SCAN_TIMEOUT 10 // seconds
+#define PMT_SCAN_IDLE 3600 // seconds
static const char *VERSION = "0.0.6pre";
static const char *DESCRIPTION = trNOOP ("Parses Extended EPG data");
+template <class T> T REALLOC(T Var, size_t Size)
+{
+ T p = (T)realloc(Var, Size);
+ if (!p)
+ free(Var);
+ return p;
+}
+
+using namespace std;
+
// --- cSetupEEPG -------------------------------------------------------
const char *optPats[] = {
@@ -105,8 +118,12 @@ public:
int RatingInfo;
int FixEpg;
int DisplayMessage;
+#ifdef DEBUG
+ int LogLevel;
+#endif
+
public:
- cSetupEEPG (void);
+ cSetupEEPG (void);
};
cSetupEEPG SetupPE;
@@ -118,6 +135,10 @@ cSetupEEPG::cSetupEEPG (void)
RatingInfo = 1;
FixEpg = 0;
DisplayMessage = 1;
+#ifdef DEBUG
+ LogLevel = 0;
+#endif
+
}
// --- cMenuSetupPremiereEpg ------------------------------------------------------------
@@ -129,9 +150,9 @@ private:
const char *optDisp[NUM_PATS];
char buff[NUM_PATS][32];
protected:
- virtual void Store (void);
+ virtual void Store (void);
public:
- cMenuSetupPremiereEpg (void);
+ cMenuSetupPremiereEpg (void);
};
cMenuSetupPremiereEpg::cMenuSetupPremiereEpg (void)
@@ -148,6 +169,9 @@ cMenuSetupPremiereEpg::cMenuSetupPremiereEpg (void)
Add (new cMenuEditBoolItem (tr ("Show rating information"), &data.RatingInfo));
Add (new cMenuEditBoolItem (tr ("Fix EPG data"), &data.FixEpg));
Add (new cMenuEditBoolItem (tr ("Display summary message"), &data.DisplayMessage));
+#ifdef DEBUG
+ Add (new cMenuEditIntItem (tr ("Level of logging verbosity"), &data.LogLevel, 0, 5));
+#endif
}
void cMenuSetupPremiereEpg::Store (void)
@@ -158,11 +182,72 @@ void cMenuSetupPremiereEpg::Store (void)
SetupStore ("RatingInfo", SetupPE.RatingInfo);
SetupStore ("FixEpg", SetupPE.FixEpg);
SetupStore ("DisplayMessage", SetupPE.DisplayMessage);
+#ifdef DEBUG
+ SetupStore ("LogLevel", SetupPE.LogLevel);
+#endif
+}
+
+bool CheckLevel(int level)
+{
+#ifdef DEBUG
+ if (SetupPE.LogLevel >= level)
+#else
+ if (VERBOSE >= level)
+#endif
+ {
+ return true;
+ }
+ return false;
}
+const char* PrepareLog(string message)
+{
+ message = "EEPG: " + message;
+ return message.c_str();
+}
+
+#define MAXSYSLOGBUF 256
+
+//void LogVsyslog(int errLevel, const char * message, ...)
+void LogVsyslog(int errLevel, int const& lineNum, const char * function, const char * message, ...)
+{
+ va_list ap;
+ char fmt[MAXSYSLOGBUF];
+ if (errLevel == LOG_DEBUG) {
+ snprintf(fmt, sizeof(fmt), "[%d] %s:%d %s", cThread::ThreadId(), function, lineNum, message);
+ } else {
+ snprintf(fmt, sizeof(fmt), "[%d] %s", cThread::ThreadId(), message);
+ }
+ va_start(ap,message);
+ vsyslog ( errLevel, fmt, ap );
+ va_end(ap);
+}
+
+#define LogI(a, b...) void( CheckLevel(a) ? LogVsyslog ( LOG_INFO, __LINE__, __FUNCTION__, b ) : void() )
+#define LogE(a, b...) void( CheckLevel(a) ? LogVsyslog ( LOG_ERR, __LINE__, __FUNCTION__, b ) : void() )
+#define LogD(a, b...) void( CheckLevel(a) ? LogVsyslog ( LOG_DEBUG, __LINE__, __FUNCTION__, b ) : void() )
+//#define LogE(a, b...) void( CheckLevel(a) ? esyslog ( b ) : void() )
+//#define LogD(a, b...) void( CheckLevel(a) ? dsyslog ( b ) : void() )
+#define prep(s) PrepareLog(s)
+#define prep2(s) s
+
+//void LogF(int level, const char * message, ...) __attribute__ ((format (printf,2,3)));
+
+//void LogF(int level, const char * message, ...)
+//{
+// if (CheckLevel(level)) {
+// va_list ap;
+// va_start(ap,message);
+// vsyslog (LOG_ERR, PrepareLog(message), ap );
+// va_end(ap);
+// }
+//}
+
+#define Asprintf(a, b, c...) void( asprintf(a, b, c) < 0 ? esyslog("memory allocation error - %s", b) : void() )
+
// --- CRC16 -------------------------------------------------------------------
-#define POLY 0xA001 // CRC16
+#define POLY 0xA001 // CRC16
unsigned int crc16 (unsigned int crc, unsigned char const *p, int len)
{
@@ -180,29 +265,49 @@ unsigned int crc16 (unsigned int crc, unsigned char const *p, int len)
static int AvailableSources[32];
static int NumberOfAvailableSources = 0;
-static int LastVersionNagra = -1; //currently only used for Nagra, should be stored per transponder, per system
+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:
int pmtpid, pmtsid, pmtidx, pmtnext;
- int UnprocessedFormat[HIGHEST_FORMAT + 1]; //stores the pid when a format is detected on this transponder, and that are not processed yet
+ int UnprocessedFormat[HIGHEST_FORMAT + 1]; //stores the pid when a format is detected on this transponder, and that are not processed yet
int nEquivChannels, nChannels, nThemes, nTitles, nSummaries, NumberOfTables, Version;
int TitleCounter, SummaryCounter, NoSummaryCounter, RejectTableId;
- bool EndChannels, EndThemes; //only used for ??
- int MHWStartTime; //only used for MHW1
+ bool EndChannels, EndThemes; //only used for ??
+ int MHWStartTime; //only used for MHW1
bool ChannelsOk;
- int Format; //the format that this filter currently is processing
- std::map < int, int >ChannelSeq; // ChannelSeq[ChannelId] returns the recordnumber of the channel
+ //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];
Title_t *Titles[MAX_TITLES];
sChannel sChannels[MAX_CHANNELS];
unsigned char Themes[MAX_THEMES][64];
- std::map < unsigned short int, unsigned char *>buffer; //buffer[Table_Extension_Id] returns the pointer to the buffer for this TEI
- std::map < unsigned short int, int >bufsize; //bufsize[Table_Extension_Id] returns the buffersize of the buffer for this TEI
- unsigned short int NagraTIE[64]; //at this moment a max of 31 table_ids could be used, so 64 should be enough ....stores the Table_Extension_Id's of summaries received, so they can be processed. Processing while receiving somehow drops sections, the 0x0000 marker will be missed ...
+ std::map < unsigned short int, unsigned char *>buffer; //buffer[Table_Extension_Id] returns the pointer to the buffer for this TEI
+ std::map < unsigned short int, int >bufsize; //bufsize[Table_Extension_Id] returns the buffersize of the buffer for this TEI
+ unsigned short int NagraTIE[64]; //at this moment a max of 31 table_ids could be used, so 64 should be enough ....stores the Table_Extension_Id's of summaries received, so they can be processed. Processing while receiving somehow drops sections, the 0x0000 marker will be missed ...
unsigned short int NagraCounter;
unsigned char InitialChannel[8];
@@ -210,20 +315,17 @@ 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);
virtual void ProcessNextFormat (bool FirstTime);
virtual int GetChannelsSKYBOX (const u_char * Data, int Length);
virtual bool GetThemesSKYBOX (void);
- virtual bool ReadFileDictionary (void); //Reads Huffman tables for SKY
virtual int GetTitlesSKYBOX (const u_char * Data, int Length);
virtual int GetSummariesSKYBOX (const u_char * Data, int Length);
- virtual int GetChannelsMHW (const u_char * Data, int Length, int MHW); //TODO replace MHW by Format?
+ virtual int GetChannelsMHW (const u_char * Data, int Length, int MHW); //TODO replace MHW by Format?
virtual int GetThemesMHW1 (const u_char * Data, int Length);
virtual int GetNagra (const u_char * Data, int Length);
virtual void ProcessNagra (void);
@@ -238,18 +340,21 @@ protected:
virtual int GetSummariesMHW2 (const u_char * Data, int Length);
virtual void FreeSummaries (void);
virtual void FreeTitles (void);
- virtual void PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]); //gets a channel and returns an array of schedules that WriteToSchedule can write to. Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
+ virtual void PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]); //gets a channel and returns an array of schedules that WriteToSchedule can write to. Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
virtual void FinishWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]);
virtual void WriteToSchedule (cSchedule * ps[MAX_EQUIVALENCES], unsigned short int NumberOfEquivalences,
- unsigned int EventId, unsigned int StartTime, unsigned int Duration, char *Text,
- char *SummText, unsigned short int ThemeId, unsigned short int TableId,
- unsigned short int Version, char Rating = 0x00);
+ unsigned int EventId, unsigned int StartTime, unsigned int Duration, char *Text,
+ char *SummText, unsigned short int ThemeId, unsigned short int TableId,
+ unsigned short int Version, char Rating = 0x00);
virtual void LoadIntoSchedule (void);
virtual void LoadEquivalentChannels (void);
+
+ void ProcessPremiere(const u_char *& Data);
public:
cFilterEEPG (void);
virtual void SetStatus (bool On);
void Trigger (void);
+ bool InitDictionary (void); //Initialize the Huffman tables for SKY and Freesat
};
cFilterEEPG::cFilterEEPG (void)
@@ -260,8 +365,7 @@ cFilterEEPG::cFilterEEPG (void)
void cFilterEEPG::Trigger (void)
{
- if (VERBOSE >= 3)
- isyslog ("trigger\n");
+ LogI(3, prep("trigger\n"));
pmtpid = 0;
pmtidx = 0;
pmtnext = 0;
@@ -269,18 +373,17 @@ void cFilterEEPG::Trigger (void)
void cFilterEEPG::SetStatus (bool On)
{
- isyslog ("setstatus %d\n", On);
+ LogI(0, prep("setstatus %d\n"), On);
if (!On) {
FreeSummaries ();
FreeTitles ();
- Format = 0;
+ //Format = 0;
ChannelsOk = false;
NumberOfTables = 0;
- }
- else {
+ } else {
//Set(0x00,0x00);
for (int i = 0; i <= HIGHEST_FORMAT; i++)
- UnprocessedFormat[i] = 0; //pid 0 is assumed to be nonvalid for EEPG transfers
+ UnprocessedFormat[i] = 0; //pid 0 is assumed to be nonvalid for EEPG transfers
AddFilter (0, 0);
}
cFilter::SetStatus (On);
@@ -292,30 +395,9 @@ void cFilterEEPG::NextPmt (void)
Del (pmtpid, 0x02);
pmtpid = 0;
pmtidx++;
- if (VERBOSE >= 3)
- esyslog ("PMT next\n");
+ 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 -------------------
@@ -343,8 +425,7 @@ void syslog_with_tid (int priority, const char *format, ...) __attribute__ ((for
-struct hufftab
-{
+struct hufftab {
unsigned int value;
short bits;
char next;
@@ -355,10 +436,11 @@ struct hufftab
#define ESCAPE '\1'
-int freesat_decode_error = 0; /* If set an error has occurred during decoding */
+int freesat_decode_error = 0; /* If set an error has occurred during decoding */
static struct hufftab *tables[2][256];
static int table_size[2][256];
+static sNodeH* sky_tables[2];
/** \brief Convert a textual character description into a value
*
@@ -371,14 +453,11 @@ static unsigned char resolve_char (char *str)
int val;
if (strcmp (str, "ESCAPE") == 0) {
return ESCAPE;
- }
- else if (strcmp (str, "STOP") == 0) {
+ } else if (strcmp (str, "STOP") == 0) {
return STOP;
- }
- else if (strcmp (str, "START") == 0) {
+ } else if (strcmp (str, "START") == 0) {
return START;
- }
- else if (sscanf (str, "0x%02x", &val) == 1) {
+ } else if (sscanf (str, "0x%02x", &val) == 1) {
return val;
}
return str[0];
@@ -414,8 +493,9 @@ static unsigned long decode_binary (char *binary)
*
* \param tableid - Table id that should be loaded
* \param filename - Filename to load
+ * \return Success of operation
*/
-static void load_file (int tableid, char *filename)
+static bool load_freesat_file (int tableid, const char *filename)
{
char buf[1024];
char *from, *to, *binary;
@@ -423,35 +503,169 @@ static void load_file (int tableid, char *filename)
tableid--;
if ((fp = fopen (filename, "r")) != NULL) {
- isyslog ("Loading table %d Filename <%s>", tableid + 1, filename);
+ LogI(2, prep("Loading table %d Filename <%s>"), tableid + 1, filename);
while (fgets (buf, sizeof (buf), fp) != NULL) {
from = binary = to = NULL;
int elems = sscanf (buf, "%a[^:]:%a[^:]:%a[^:]:", &from, &binary, &to);
if (elems == 3) {
- int bin_len = strlen (binary);
- int from_char = resolve_char (from);
- char to_char = resolve_char (to);
- unsigned long bin = decode_binary (binary);
- int i = table_size[tableid][from_char]++;
-
- tables[tableid][from_char] =
- (struct hufftab *) realloc (tables[tableid][from_char], (i + 1) * sizeof (tables[tableid][from_char][0]));
- tables[tableid][from_char][i].value = bin;
- tables[tableid][from_char][i].next = to_char;
- tables[tableid][from_char][i].bits = bin_len;
- free (from);
- free (to);
- free (binary);
+ int bin_len = strlen (binary);
+ int from_char = resolve_char (from);
+ char to_char = resolve_char (to);
+ unsigned long bin = decode_binary (binary);
+ int i = table_size[tableid][from_char]++;
+
+ tables[tableid][from_char] =
+ (struct hufftab *) REALLOC (tables[tableid][from_char], (i + 1) * sizeof (tables[tableid][from_char][0]));
+ tables[tableid][from_char][i].value = bin;
+ tables[tableid][from_char][i].next = to_char;
+ tables[tableid][from_char][i].bits = bin_len;
+ free (from);
+ free (to);
+ free (binary);
}
}
fclose (fp);
+ } else {
+ LogE(0, prep("Cannot load <%s> for table %d"), filename, tableid + 1);
+ return false;
}
- else {
- isyslog ("EEPG: Cannot load <%s> for table %d", filename, tableid + 1);
- }
+ return true;
}
+/** \brief Load an individual freesat data file
+ *
+ * \param filename - Filename to load
+ * \return Success of operation
+ */
+static bool load_sky_file (const char *filename)
+{
+ FILE *FileDict;
+ char *Line;
+ char Buffer[256];
+ sNodeH *nH;
+ int tableId;
+
+ FileDict = fopen (filename, "r");
+ if (FileDict == NULL) {
+ LogE (0, prep("Error opening file '%s'. %s"), filename, strerror (errno));
+ return false;
+ } else {
+ int i;
+ int LenPrefix;
+ char string1[256];
+ char string2[256];
+
+ tableId = Format == SKY_IT ? 0 : 1;
+ if (!sky_tables[tableId]) {
+ sky_tables[tableId] = (sNodeH*) calloc(1,sizeof(sNodeH));
+ if (!sky_tables[tableId]) {
+ LogE (0, prep("Not enough memory to load file '%s'."), filename);
+ return false;
+ }
+ }
+
+ while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
+ if (!isempty (Line)) {
+ memset (string1, 0, sizeof (string1));
+ memset (string2, 0, sizeof (string2));
+ if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2
+ || (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2)) {
+ nH = sky_tables[tableId];
+ LenPrefix = strlen (string2);
+ for (i = 0; i < LenPrefix; i++) {
+ switch (string2[i]) {
+ case '0':
+ if (nH->P0 == NULL) {
+ nH->P0 = new sNodeH ();
+ nH = nH->P0;
+ nH->Value = NULL;
+ nH->P0 = NULL;
+ nH->P1 = NULL;
+ if ((LenPrefix - 1) == i) {
+ Asprintf (&nH->Value, "%s", string1);
+ }
+ } else {
+ nH = nH->P0;
+ if (nH->Value != NULL || (LenPrefix - 1) == i) {
+ LogE (0 ,prep("Error, huffman prefix code already exists for \"%s\"=%s with '%s'"), string1,
+ string2, nH->Value);
+ }
+ }
+ break;
+ case '1':
+ if (nH->P1 == NULL) {
+ nH->P1 = new sNodeH ();
+ nH = nH->P1;
+ nH->Value = NULL;
+ nH->P0 = NULL;
+ nH->P1 = NULL;
+ if ((LenPrefix - 1) == i) {
+ Asprintf (&nH->Value, "%s", string1);
+ }
+ } else {
+ nH = nH->P1;
+ if (nH->Value != NULL || (LenPrefix - 1) == i) {
+ LogE (0, prep("Error, huffman prefix code already exists for \"%s\"=%s with '%s'"), string1,
+ string2, nH->Value);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ fclose (FileDict);
+ }
+
+ // check tree huffman nodes
+ FileDict = fopen (filename, "r");
+ if (FileDict) {
+ int i;
+ int LenPrefix;
+ char string1[256];
+ char string2[256];
+ while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
+ if (!isempty (Line)) {
+ memset (string1, 0, sizeof (string1));
+ memset (string2, 0, sizeof (string2));
+ if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2
+ || (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2)) {
+ nH = sky_tables[tableId];
+ LenPrefix = strlen (string2);
+ for (i = 0; i < LenPrefix; i++) {
+ switch (string2[i]) {
+ case '0':
+ if (nH->P0 != NULL) {
+ nH = nH->P0;
+ }
+ break;
+ case '1':
+ if (nH->P1 != NULL) {
+ nH = nH->P1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (nH->Value != NULL) {
+ if (memcmp (nH->Value, string1, strlen (nH->Value)) != 0) {
+ LogE (0, prep("Error, huffman prefix value '%s' not equal to '%s'"), nH->Value, string1);
+ }
+ } else {
+ LogE (0, prep("Error, huffman prefix value is not exists for \"%s\"=%s"), string1, string2);
+ }
+ }
+ }
+ }
+ fclose (FileDict);
+ }
+ return true;
+}
/** \brief Decode an EPG string as necessary
*
@@ -471,7 +685,7 @@ char *freesat_huffman_decode (const unsigned char *src, size_t size)
char *uncompressed = (char *) calloc (1, uncompressed_len + 1);
unsigned value = 0, byte = 2, bit = 0;
int p = 0;
- int lastch = START;
+ unsigned char lastch = START;
tableid = src[1] - 1;
while (byte < 6 && byte < size) {
@@ -481,68 +695,65 @@ char *freesat_huffman_decode (const unsigned char *src, size_t size)
//freesat_table_load (); /**< Load the tables as necessary */
do {
- int found = 0;
+ bool found = false;
unsigned bitShift = 0;
if (lastch == ESCAPE) {
- char nextCh = (value >> 24) & 0xff;
- found = 1;
- // Encoded in the next 8 bits.
- // Terminated by the first ASCII character.
- bitShift = 8;
- if ((nextCh & 0x80) == 0)
- lastch = nextCh;
- if (p >= uncompressed_len) {
- uncompressed_len += 10;
- uncompressed = (char *) realloc (uncompressed, uncompressed_len + 1);
- }
- uncompressed[p++] = nextCh;
- uncompressed[p] = 0;
- }
- else {
- int j;
- for (j = 0; j < table_size[tableid][lastch]; j++) {
- unsigned mask = 0, maskbit = 0x80000000;
- short kk;
- for (kk = 0; kk < tables[tableid][lastch][j].bits; kk++) {
- mask |= maskbit;
- maskbit >>= 1;
- }
- if ((value & mask) == tables[tableid][lastch][j].value) {
- char nextCh = tables[tableid][lastch][j].next;
- bitShift = tables[tableid][lastch][j].bits;
- if (nextCh != STOP && nextCh != ESCAPE) {
- if (p >= uncompressed_len) {
- uncompressed_len += 10;
- uncompressed = (char *) realloc (uncompressed, uncompressed_len + 1);
- }
- uncompressed[p++] = nextCh;
- uncompressed[p] = 0;
- }
- found = 1;
- lastch = nextCh;
- break;
- }
- }
+ char nextCh = (value >> 24) & 0xff;
+ found = true;
+ // Encoded in the next 8 bits.
+ // Terminated by the first ASCII character.
+ bitShift = 8;
+ if ((nextCh & 0x80) == 0)
+ lastch = nextCh;
+ if (p >= uncompressed_len) {
+ uncompressed_len += 10;
+ uncompressed = (char *) REALLOC (uncompressed, uncompressed_len + 1);
+ }
+ uncompressed[p++] = nextCh;
+ uncompressed[p] = 0;
+ } else {
+ int j;
+ for (j = 0; j < table_size[tableid][lastch]; j++) {
+ unsigned mask = 0, maskbit = 0x80000000;
+ short kk;
+ for (kk = 0; kk < tables[tableid][lastch][j].bits; kk++) {
+ mask |= maskbit;
+ maskbit >>= 1;
+ }
+ if ((value & mask) == tables[tableid][lastch][j].value) {
+ char nextCh = tables[tableid][lastch][j].next;
+ bitShift = tables[tableid][lastch][j].bits;
+ if (nextCh != STOP && nextCh != ESCAPE) {
+ if (p >= uncompressed_len) {
+ uncompressed_len += 10;
+ uncompressed = (char *) REALLOC (uncompressed, uncompressed_len + 1);
+ }
+ uncompressed[p++] = nextCh;
+ uncompressed[p] = 0;
+ }
+ found = true;
+ lastch = nextCh;
+ break;
+ }
+ }
}
if (found) {
- // Shift up by the number of bits.
- unsigned b;
- for (b = 0; b < bitShift; b++) {
- value = (value << 1) & 0xfffffffe;
- if (byte < size)
- value |= (src[byte] >> (7 - bit)) & 1;
- if (bit == 7) {
- bit = 0;
- byte++;
- }
- else
- bit++;
- }
- }
- else {
- isyslog ("Missing table %d entry: <%s>", tableid + 1, uncompressed);
- // Entry missing in table.
- return uncompressed;
+ // Shift up by the number of bits.
+ unsigned b;
+ for (b = 0; b < bitShift; b++) {
+ value = (value << 1) & 0xfffffffe;
+ if (byte < size)
+ value |= (src[byte] >> (7 - bit)) & 1;
+ if (bit == 7) {
+ bit = 0;
+ byte++;
+ } else
+ bit++;
+ }
+ } else {
+ LogE (0, prep("Missing table %d entry: <%s>"), tableid + 1, uncompressed);
+ // Entry missing in table.
+ return uncompressed;
}
} while (lastch != STOP && value != 0);
@@ -551,12 +762,103 @@ char *freesat_huffman_decode (const unsigned char *src, size_t size)
return NULL;
}
+int sky_huffman_decode (const u_char * Data, int Length, unsigned char *DecodeText)
+{
+ sNodeH *nH, H=(Format==SKY_IT)?*sky_tables[0]:*sky_tables[1];
+ int i;
+ int p;
+ int q;
+ bool CodeError;
+ bool IsFound;
+ unsigned char Byte;
+ unsigned char lastByte;
+ unsigned char Mask;
+ unsigned char lastMask;
+ nH = &H;
+ p = 0;
+ q = 0;
+ DecodeText[0] = '\0';
+ //DecodeErrorText[0] = '\0';
+ CodeError = false;
+ IsFound = false;
+ lastByte = 0;
+ lastMask = 0;
+ for (i = 0; i < Length; i++) {
+ Byte = Data[i];
+ Mask = 0x80;
+ if (i == 0) {
+ Mask = 0x20;
+ lastByte = i;
+ lastMask = Mask;
+ }
+loop1:
+ if (IsFound) {
+ lastByte = i;
+ lastMask = Mask;
+ IsFound = false;
+ }
+ if ((Byte & Mask) == 0) {
+ if (CodeError) {
+ //DecodeErrorText[q] = 0x30;
+ q++;
+ goto nextloop1;
+ }
+ if (nH->P0 != NULL) {
+ nH = nH->P0;
+ if (nH->Value != NULL) {
+ memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
+ p += strlen (nH->Value);
+ nH = &H;
+ IsFound = true;
+ }
+ } else {
+ memcpy (&DecodeText[p], "<...?...>", 9);
+ p += 9;
+ i = lastByte;
+ Byte = Data[lastByte];
+ Mask = lastMask;
+ CodeError = true;
+ goto loop1;
+ }
+ } else {
+ if (CodeError) {
+ //DecodeErrorText[q] = 0x31;
+ q++;
+ goto nextloop1;
+ }
+ if (nH->P1 != NULL) {
+ nH = nH->P1;
+ if (nH->Value != NULL) {
+ memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
+ p += strlen (nH->Value);
+ nH = &H;
+ IsFound = true;
+ }
+ } else {
+ memcpy (&DecodeText[p], "<...?...>", 9);
+ p += 9;
+ i = lastByte;
+ Byte = Data[lastByte];
+ Mask = lastMask;
+ CodeError = true;
+ goto loop1;
+ }
+ }
+nextloop1:
+ Mask = Mask >> 1;
+ if (Mask > 0) {
+ goto loop1;
+ }
+ }
+ DecodeText[p] = '\0';
+ //DecodeErrorText[q] = '\0';
+ return p;
+}
+
//here all declarations for global variables over all devices
char *ConfDir;
-sNodeH *nH, H;
-
//unsigned char DecodeErrorText[4096]; //TODO only used for debugging?
int Yesterday;
@@ -564,7 +866,7 @@ int YesterdayEpoch;
int YesterdayEpochUTC;
/*
- * Convert local time to UTC
+ * Convert local time to UTC
*/
time_t LocalTime2UTC (time_t t)
{
@@ -576,7 +878,7 @@ time_t LocalTime2UTC (time_t t)
}
/*
- * Convert UTC to local time
+ * Convert UTC to local time
*/
time_t UTC2LocalTime (time_t t)
{
@@ -602,6 +904,8 @@ void GetLocalTimeOffset (void)
void CleanString (unsigned char *String)
{
+
+// LogD (1, prep("Unclean: %s"), String);
unsigned char *Src;
unsigned char *Dst;
int Spaces;
@@ -612,65 +916,78 @@ void CleanString (unsigned char *String)
pC = 0;
while (*Src) {
// corrections
- if (*Src == 0x8c) // iso-8859-2 LATIN CAPITAL LETTER S WITH ACUTE
- {
+ if (*Src == 0x8c) { // iso-8859-2 LATIN CAPITAL LETTER S WITH ACUTE
*Src = 0xa6;
}
- if (*Src == 0x8f) // iso-8859-2 LATIN CAPITAL LETTER Z WITH ACUTE
- {
+ if (*Src == 0x8f) { // iso-8859-2 LATIN CAPITAL LETTER Z WITH ACUTE
*Src = 0xac;
}
- if (*Src!=0x0A && *Src < 0x20) { //don't remove newline
+ if (*Src!=0x0A && *Src < 0x20) { //don't remove newline
*Src = 0x20;
}
if (*Src == 0x20) {
Spaces++;
if (pC == 0) {
- Spaces++;
+ Spaces++;
}
- }
- else {
+ } else {
Spaces = 0;
}
if (Spaces < 2) {
*Dst = *Src;
- *Dst++;
+ Dst++;
pC++;
}
- *Src++;
+ Src++;
}
if (Spaces > 0) {
Dst--;
*Dst = 0;
- }
- else {
+ } else {
*Dst = 0;
}
+// LogD (1, prep("Clean: %s"), String);
}
-bool cFilterEEPG::GetThemesSKYBOX (void) //TODO can't we read this from the DVB stream?
+cChannel *GetChannelByID(tChannelID & channelID, bool searchOtherPos)
{
- char *FileName;
+ 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?
+{
+ string FileName = ConfDir;
FILE *FileThemes;
char *Line;
char Buffer[256];
if (Format == SKY_IT)
- asprintf (&FileName, "%s/%s", ConfDir, "sky_it.themes");
+ FileName += "/sky_it.themes";
else if (Format == SKY_UK)
- asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.themes");
+ FileName += "/sky_uk.themes";
else {
- esyslog ("EEPG: Error, wrong format detected in GetThemesSKYBOX. Format = %i.", Format);
+ LogE (0, prep("Error, wrong format detected in GetThemesSKYBOX. Format = %i."), Format);
return false;
}
//asprintf( &FileName, "%s/%s", ConfDir, ( lProviders + CurrentProvider )->Parm3 );
- FileThemes = fopen (FileName, "r");
+ FileThemes = fopen (FileName.c_str(), "r");
if (FileThemes == NULL) {
- esyslog ("EEPG: Error opening file '%s'. %s", FileName, strerror (errno));
- free (FileName);
+ LogE (0, prep("Error opening file '%s'. %s"), FileName.c_str(), strerror (errno));
return false;
- }
- else {
+ } else {
//int id = 0;
nThemes = 0;
char string1[256];
@@ -680,265 +997,77 @@ bool cFilterEEPG::GetThemesSKYBOX (void) //TODO can't we read this from the DVB
memset (string1, 0, sizeof (string1));
memset (string2, 0, sizeof (string2));
if (!isempty (Line)) {
- //T = &Themes[nThemes];
- if (sscanf (Line, "%[^=] =%[^\n] ", string1, string2) == 2) {
- snprintf ((char *) Themes[nThemes], 255, "%s", string2);
- }
- else {
- Themes[nThemes][0] = '\0';
- }
- //id ++;
- nThemes++;
+ //T = &Themes[nThemes];
+ if (sscanf (Line, "%[^=] =%[^\n] ", string1, string2) == 2) {
+ snprintf ((char *) Themes[nThemes], 255, "%s", string2);
+ } else {
+ Themes[nThemes][0] = '\0';
+ }
+ //id ++;
+ nThemes++;
}
}
fclose (FileThemes);
}
- free (FileName);
return true;
}
-bool cFilterEEPG::ReadFileDictionary (void)
+/**
+ * \brief Initialize the Huffman dictionaries if they are not already initialized.
+ *
+ */
+bool cFilterEEPG::InitDictionary (void)
{
- char *FileName;
- FILE *FileDict;
- char *Line;
- char Buffer[256];
+ string FileName = ConfDir;
switch (Format) {
case SKY_IT:
- asprintf (&FileName, "%s/%s", ConfDir, "sky_it.dict");
+ if (sky_tables[0] == NULL) {
+ FileName += "/sky_it.dict";
+ LogD (4, prep("EEPGDebug: loading sky_it.dict"));
+ return load_sky_file(FileName.c_str());
+ } else
+ LogD (4, prep("EEPGDebug: sky_it.dict already loaded"));
break;
case SKY_UK:
- asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.dict");
+ if (sky_tables[1] == NULL) {
+ FileName += "/sky_uk.dict";
+ LogD (4, prep("EEPGDebug: loading sky_uk.dict"));
+ return load_sky_file(FileName.c_str());
+ } else
+ LogD (4, prep("EEPGDebug: sky_uk.dict already loaded"));
break;
case FREEVIEW:
- asprintf (&FileName, "%s/%s", ConfDir, "freesat.t1");
- load_file (1, FileName);
- asprintf (&FileName, "%s/%s", ConfDir, "freesat.t2");
- load_file (2, FileName);
+ if (tables[0][0] == NULL) {
+ LogD (4, prep("EEPGDebug: loading freesat.dict"));
+ FileName += "/freesat.t1";
+ if (!load_freesat_file (1, FileName.c_str()))
+ return false;
+ FileName = ConfDir;
+ FileName += "/freesat.t2";
+ return load_freesat_file (2, FileName.c_str());
+ } else
+ LogD (4, prep("EEPGDebug: freesat.dict already loaded"));
break;
default:
- esyslog ("EEPG: Error, wrong format detected in ReadFileDictionary. Format = %i.", Format);
+ LogE (0 ,prep("Error, wrong format detected in ReadFileDictionary. Format = %i."), Format);
return false;
}
- if ((Format == SKY_IT) || (Format == SKY_UK)) { //SKY
- FileDict = fopen (FileName, "r");
- if (FileDict == NULL) {
- esyslog ("EEPG: Error opening file '%s'. %s", FileName, strerror (errno));
- free (FileName);
- return false;
- }
- else {
- int i;
- int LenPrefix;
- char string1[256];
- char string2[256];
- H.Value = NULL;
- H.P0 = NULL;
- H.P1 = NULL;
- while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
- if (!isempty (Line)) {
- memset (string1, 0, sizeof (string1));
- memset (string2, 0, sizeof (string2));
- if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2
- || (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2)) {
- nH = &H;
- LenPrefix = strlen (string2);
- for (i = 0; i < LenPrefix; i++) {
- switch (string2[i]) {
- case '0':
- if (nH->P0 == NULL) {
- nH->P0 = new sNodeH ();
- nH = nH->P0;
- nH->Value = NULL;
- nH->P0 = NULL;
- nH->P1 = NULL;
- if ((LenPrefix - 1) == i) {
- asprintf (&nH->Value, "%s", string1);
- }
- }
- else {
- nH = nH->P0;
- if (nH->Value != NULL || (LenPrefix - 1) == i) {
- esyslog ("EEPG: Error, huffman prefix code already exists for \"%s\"=%s with '%s'", string1,
- string2, nH->Value);
- }
- }
- break;
- case '1':
- if (nH->P1 == NULL) {
- nH->P1 = new sNodeH ();
- nH = nH->P1;
- nH->Value = NULL;
- nH->P0 = NULL;
- nH->P1 = NULL;
- if ((LenPrefix - 1) == i) {
- asprintf (&nH->Value, "%s", string1);
- }
- }
- else {
- nH = nH->P1;
- if (nH->Value != NULL || (LenPrefix - 1) == i) {
- esyslog ("EEPG: Error, huffman prefix code already exists for \"%s\"=%s with '%s'", string1,
- string2, nH->Value);
- }
- }
- break;
- default:
- break;
- }
- }
- }
- }
- }
- fclose (FileDict);
- }
-
- // check tree huffman nodes
- FileDict = fopen (FileName, "r");
- if (FileDict) {
- int i;
- int LenPrefix;
- char string1[256];
- char string2[256];
- while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
- if (!isempty (Line)) {
- memset (string1, 0, sizeof (string1));
- memset (string2, 0, sizeof (string2));
- if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2
- || (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2)) {
- nH = &H;
- LenPrefix = strlen (string2);
- for (i = 0; i < LenPrefix; i++) {
- switch (string2[i]) {
- case '0':
- if (nH->P0 != NULL) {
- nH = nH->P0;
- }
- break;
- case '1':
- if (nH->P1 != NULL) {
- nH = nH->P1;
- }
- break;
- default:
- break;
- }
- }
- if (nH->Value != NULL) {
- if (memcmp (nH->Value, string1, strlen (nH->Value)) != 0) {
- esyslog ("EEPG: Error, huffman prefix value '%s' not equal to '%s'", nH->Value, string1);
- }
- }
- else {
- esyslog ("EEPG: Error, huffman prefix value is not exists for \"%s\"=%s", string1, string2);
- }
- }
- }
- }
- fclose (FileDict);
- }
- } //if Format == 3 || Format == 4
- free (FileName);
return true;
}
-
-int DecodeHuffmanCode (const u_char * Data, int Length, unsigned char *DecodeText)
+void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize)
{
- int i;
- int p;
- int q;
- bool CodeError;
- bool IsFound;
- unsigned char Byte;
- unsigned char lastByte;
- unsigned char Mask;
- unsigned char lastMask;
- nH = &H;
- p = 0;
- q = 0;
- DecodeText[0] = '\0';
- //DecodeErrorText[0] = '\0';
- CodeError = false;
- IsFound = false;
- lastByte = 0;
- lastMask = 0;
- for (i = 0; i < Length; i++) {
- Byte = Data[i];
- Mask = 0x80;
- if (i == 0) {
- Mask = 0x20;
- lastByte = i;
- lastMask = Mask;
- }
-loop1:
- if (IsFound) {
- lastByte = i;
- lastMask = Mask;
- IsFound = false;
- }
- if ((Byte & Mask) == 0) {
- if (CodeError) {
- //DecodeErrorText[q] = 0x30;
- q++;
- goto nextloop1;
- }
- if (nH->P0 != NULL) {
- nH = nH->P0;
- if (nH->Value != NULL) {
- memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
- p += strlen (nH->Value);
- nH = &H;
- IsFound = true;
- }
- }
- else {
- memcpy (&DecodeText[p], "<...?...>", 9);
- p += 9;
- i = lastByte;
- Byte = Data[lastByte];
- Mask = lastMask;
- CodeError = true;
- goto loop1;
- }
- }
- else {
- if (CodeError) {
- //DecodeErrorText[q] = 0x31;
- q++;
- goto nextloop1;
- }
- if (nH->P1 != NULL) {
- nH = nH->P1;
- if (nH->Value != NULL) {
- memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
- p += strlen (nH->Value);
- nH = &H;
- IsFound = true;
- }
- }
- else {
- memcpy (&DecodeText[p], "<...?...>", 9);
- p += 9;
- i = lastByte;
- Byte = Data[lastByte];
- Mask = lastMask;
- CodeError = true;
- goto loop1;
- }
- }
-nextloop1:
- Mask = Mask >> 1;
- if (Mask > 0) {
- goto loop1;
+ if (from[0] == 0x1f) {
+ char *temp = freesat_huffman_decode (from, len);
+ if (temp) {
+ len = strlen (temp);
+ len = len < buffsize - 1 ? len : buffsize - 1;
+ strncpy (buffer, temp, len);
+ buffer[len] = 0;
+ free (temp);
+ return;
}
}
- DecodeText[p] = '\0';
- //DecodeErrorText[q] = '\0';
- return p;
-}
-
-void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize) {
if (from[0] == 0x1f) {
char *temp = freesat_huffman_decode (from, len);
@@ -956,9 +1085,9 @@ void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize
SI::CharArray charArray;
charArray.assign(from, len);
convStr.setData(charArray, len);
- //isyslog("decodeText2 from %s - length %d", from, len);
+ //LogE(5, prep("decodeText2 from %s - length %d"), from, len);
convStr.getText(buffer, buffsize);
- //isyslog("decodeText2 buffer %s - buffsize %d", buffer, buffsize);
+ //LogE(5, prep("decodeText2 buffer %s - buffsize %d"), buffer, buffsize);
}
void cFilterEEPG::LoadEquivalentChannels (void)
@@ -966,10 +1095,9 @@ void cFilterEEPG::LoadEquivalentChannels (void)
char Buffer[1024];
char *Line;
FILE *File;
- char *FileName;
+ string FileName = string(ConfDir) + "/" + EEPG_FILE_EQUIV;
- asprintf (&FileName, "%s/%s", ConfDir, EEPG_FILE_EQUIV);
- File = fopen (FileName, "r");
+ File = fopen (FileName.c_str(), "r");
if (File) {
memset (Buffer, 0, sizeof (Buffer));
char string1[256];
@@ -982,83 +1110,79 @@ void cFilterEEPG::LoadEquivalentChannels (void)
while ((Line = fgets (Buffer, sizeof (Buffer), File)) != NULL) {
Line = compactspace (skipspace (stripspace (Line)));
if (!isempty (Line)) {
- if (sscanf (Line, "%[^ ] %[^ ] %[^\n]\n", string1, string2, string3) == 3) {
- if (string1[0] != '#' && string1[0] != ';') {
- int1 = 0; //TODO: this could be made more readable
- int2 = 0;
- int3 = 0;
- int4 = 0;
- if (sscanf (string1, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4)
- if (sscanf (string2, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4) {
- if (sscanf (string1, "%[^-]-%i -%i -%i -%i ", string3, &int1, &int2, &int3, &int4) != 5) {
- int4 = 0;
- }
- tChannelID OriginalChID = tChannelID (cSource::FromString (string3), int1, int2, int3, int4);
- bool found = false;
- int i = 0;
- sChannel *C;
- while (i < nChannels && (!found)) {
- C = &sChannels[i];
- if (C->Src[0] == cSource::FromString (string3) && C->Nid[0] == int1
- && C->Tid[0] == int2 && C->Sid[0] == int3)
- found = true;
- else
- i++;
- }
- if (!found) {
- if (VERBOSE >= 2)
- isyslog
- ("EEPG Warning: in equivalence file, cannot find original channel %s. Perhaps you are tuned to another transponder right now.",
- string1);
- }
- else {
- cChannel *OriginalChannel = Channels.GetByChannelID (OriginalChID, false);
- if (!OriginalChannel && (VERBOSE >= 2))
- isyslog ("EEPG: warning, not found epg channel \'%s\' in channels.conf. Equivalency is assumed to be valid, but perhaps you should check the entry in the equivalents file", string1); //TODO: skip this warning?
- if (sscanf (string2, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4) {
- if (sscanf (string2, "%[^-]-%i -%i -%i -%i ", string3, &int1, &int2, &int3, &int4)
- != 5) {
- int4 = 0;
- }
- tChannelID EquivChID = tChannelID (cSource::FromString (string3), int1, int2, int3, int4);
- cChannel *EquivChannel = Channels.GetByChannelID (EquivChID, false); //TODO use valid function?
- if (EquivChannel) {
- if (C->NumberOfEquivalences < MAX_EQUIVALENCES) {
- C->Src[C->NumberOfEquivalences] = EquivChannel->Source ();
- C->Nid[C->NumberOfEquivalences] = EquivChannel->Nid ();
- C->Tid[C->NumberOfEquivalences] = EquivChannel->Tid ();
- C->Sid[C->NumberOfEquivalences] = EquivChannel->Sid ();
- C->NumberOfEquivalences++;
- nEquivChannels++;
- if (VERBOSE >= 3)
- isyslog
- ("EEPG: Added equivalent nr %i with Channel Id %s-%i-%i-%i to channel with id %i.",
- C->NumberOfEquivalences, *cSource::ToString (C->Src[C->NumberOfEquivalences - 1]),
- C->Nid[C->NumberOfEquivalences - 1], C->Tid[C->NumberOfEquivalences - 1],
- C->Sid[C->NumberOfEquivalences - 1], i);
- }
- else
- esyslog
- ("EEPG: Error, channel with id %i has more than %i equivalences. Increase MAX_EQUIVALENCES.",
- i, MAX_EQUIVALENCES);
- }
- else
- isyslog ("EEPG: warning, not found equivalent channel \'%s\' in channels.conf", string2);
- }
- } //else !found
- } //if scanf string1
- } //if string1
- } //if scanf
- } //if isempty
- } //while
+ if (sscanf (Line, "%[^ ] %[^ ] %[^\n]\n", string1, string2, string3) == 3) {
+ if (string1[0] != '#' && string1[0] != ';') {
+ int1 = 0; //TODO: this could be made more readable
+ int2 = 0;
+ int3 = 0;
+ int4 = 0;
+ if (sscanf (string1, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4)
+ if (sscanf (string2, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4) {
+ if (sscanf (string1, "%[^-]-%i -%i -%i -%i ", string3, &int1, &int2, &int3, &int4) != 5) {
+ int4 = 0;
+ }
+ tChannelID OriginalChID = tChannelID (cSource::FromString (string3), int1, int2, int3, int4);
+ bool found = false;
+ int i = 0;
+ sChannel *C = NULL;
+ while (i < nChannels && (!found)) {
+ C = &sChannels[i];
+ if (C->Src[0] == (unsigned int)cSource::FromString (string3) && C->Nid[0] == int1
+ && C->Tid[0] == int2 && C->Sid[0] == int3)
+ found = true;
+ else
+ i++;
+ }
+ if (!found) {
+ LogI(2, prep("Warning: in equivalence file, cannot find original channel %s. Perhaps you are tuned to another transponder right now."),
+ string1);
+ } else {
+ cChannel *OriginalChannel = Channels.GetByChannelID (OriginalChID, false);
+ if (!OriginalChannel)
+ LogI(2, prep("Warning, not found epg channel \'%s\' in channels.conf. Equivalency is assumed to be valid, but perhaps you should check the entry in the equivalents file"), string1); //TODO: skip this ing?
+ if (sscanf (string2, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4) {
+ if (sscanf (string2, "%[^-]-%i -%i -%i -%i ", string3, &int1, &int2, &int3, &int4)
+ != 5) {
+ int4 = 0;
+ }
+ tChannelID EquivChID = tChannelID (cSource::FromString (string3), int1, int2, int3, int4);
+ cChannel *EquivChannel = Channels.GetByChannelID (EquivChID, false); //TODO use valid function?
+ if (EquivChannel) {
+ if (C->NumberOfEquivalences < MAX_EQUIVALENCES) {
+ C->Src[C->NumberOfEquivalences] = EquivChannel->Source ();
+ C->Nid[C->NumberOfEquivalences] = EquivChannel->Nid ();
+ C->Tid[C->NumberOfEquivalences] = EquivChannel->Tid ();
+ C->Sid[C->NumberOfEquivalences] = EquivChannel->Sid ();
+ C->NumberOfEquivalences++;
+ nEquivChannels++;
+ LogI(3, prep("Added equivalent nr %i with Channel Id %s-%i-%i-%i to channel with id %i."),
+ C->NumberOfEquivalences, *cSource::ToString (C->Src[C->NumberOfEquivalences - 1]),
+ C->Nid[C->NumberOfEquivalences - 1], C->Tid[C->NumberOfEquivalences - 1],
+ C->Sid[C->NumberOfEquivalences - 1], i);
+ } else
+ LogE(0, prep("Error, channel with id %i has more than %i equivalences. Increase MAX_EQUIVALENCES."),
+ i, MAX_EQUIVALENCES);
+ } else
+ LogI(0, prep("Warning, not found equivalent channel \'%s\' in channels.conf"), string2);
+ }
+ } //else !found
+ } //if scanf string1
+ } //if string1
+ } //if scanf
+ } //if isempty
+ } //while
fclose (File);
- } //if file
- free (FileName);
-} //end of loadequiv
+ } //if file
+} //end of loadequiv
-int cFilterEEPG::GetChannelsMHW (const u_char * Data, int Length, int MHW) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get MHW channels
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetChannelsMHW (const u_char * Data, int Length, int MHW)
{
- if ((MHW == 1) || (nChannels == 0)) { //prevents MHW2 from reading channels twice while waiting for themes on same filter
+ if ((MHW == 1) || (nChannels == 0)) { //prevents MHW2 from reading channels twice while waiting for themes on same filter
sChannelMHW1 *Channel;
int Size, Off;
Size = sizeof (sChannelMHW1);
@@ -1069,138 +1193,124 @@ int cFilterEEPG::GetChannelsMHW (const u_char * Data, int Length, int MHW) //ret
}
if (MHW == 2) {
if (Length > 120)
- nChannels = Data[120];
+ nChannels = Data[120];
else {
- esyslog ("EEPG: Error, channels packet too short for MHW2.");
- return 0;
+ LogE(0, prep("Error, channels packet too short for MHW2."));
+ return 0;
}
int pName = ((nChannels * 8) + 121);
if (Length > pName) {
- //Channel = (sChannelMHW1 *) (Data + 120);
- Size -= 14; //MHW2 is 14 bytes shorter
- Off = 121; //and offset differs
- }
- else {
- esyslog ("EEPG: Error, channels length does not match pname.");
- return 0;
+ //Channel = (sChannelMHW1 *) (Data + 120);
+ Size -= 14; //MHW2 is 14 bytes shorter
+ Off = 121; //and offset differs
+ } else {
+ LogE(0, prep("Error, channels length does not match pname."));
+ return 0;
}
}
if (nChannels > MAX_CHANNELS) {
- esyslog ("EEPG: Error, channels found more than %i", MAX_CHANNELS);
+ LogE(0, prep("EEPG: Error, %i channels found more than %i"), nChannels, MAX_CHANNELS);
return 0;
- }
- else {
- if (VERBOSE >= 1) {
- isyslog ("| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
- isyslog ("|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
- "-----------------------------", "--------------------");
- }
- int pName = ((nChannels * 8) + 121); //TODO double ...
+ } else {
+ LogI(1, "| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+ LogI(1, "|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+ "-----------------------------", "--------------------");
+ int pName = ((nChannels * 8) + 121); //TODO double ...
for (int i = 0; i < nChannels; i++) {
- Channel = (sChannelMHW1 *) (Data + Off);
- sChannel *C = &sChannels[i];
- C->ChannelId = i;
- ChannelSeq[C->ChannelId] = i; //fill lookup table to go from channel-id to sequence nr in table
- C->SkyNumber = 0;
- if (MHW == 1)
- 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);
- //memcpy (C->Name, &Data[pName + 1], lenName);
- //else
- //memcpy (C->Name, &Data[pName + 1], 256);
- pName += (lenName + 1);
- }
- 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->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);
- 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;
- }
- }
- }
- CleanString (C->Name);
-
- if (VERBOSE >= 1) {
- char *ChID;
- asprintf (&ChID, "%s-%i-%i-%i-0", *cSource::ToString (C->Src[0]), C->Nid[0], C->Tid[0], C->Sid[0]);
- char *IsF;
- if (IsFound)
- asprintf (&IsF, " %-3.3s |", "YES");
- else
- asprintf (&IsF, " %-3.3s |", "NO");
- isyslog ("|% 5d | %-26.26s | %-22.22s |%s % 6d |\n", C->ChannelId, ChID, C->Name, IsF, C->SkyNumber);
- free (ChID);
- free (IsF);
- }
- Off += Size;
- } //for loop
- } //else nChannels > MAX_CHANNELS
+ Channel = (sChannelMHW1 *) (Data + Off);
+ sChannel *C = &sChannels[i];
+ C->ChannelId = i;
+ ChannelSeq[C->ChannelId] = i; //fill lookup table to go from channel-id to sequence nr in table
+ C->SkyNumber = 0;
+ if (MHW == 1)
+ memcpy (C->Name, &Channel->Name, 16); //MHW1
+ else { //MHW2
+ int lenName = Data[pName] & 0x0f;
+ //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);
+ pName += (lenName + 1);
+ }
+ 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->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 = GetChannelByID(channelID, true);
+ bool IsFound = (VC);
+ if(IsFound) {
+ C->Src[0] = VC->Source();
+ }
+ CleanString (C->Name);
+
+ LogI(1, "|% 5d | %-26.26s | %-22.22s | %-3.3s | % 6d |\n", C->ChannelId
+ , *tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]).ToString()
+ , C->Name, IsFound ? "YES" : "NO", C->SkyNumber);
+
+ Off += Size;
+ } //for loop
+ } //else nChannels > MAX_CHANNELS
LoadEquivalentChannels ();
- GetLocalTimeOffset (); //reread timing variables, only used for MHW
- return 2; //obviously, when you get here, channels are read succesfully, but since all channels are sent at once, you can stop now
- } //if nChannels == 0
- esyslog ("EEPG Warning: Trying to read Channels more than once!");
+ GetLocalTimeOffset (); //reread timing variables, only used for MHW
+ return 2; //obviously, when you get here, channels are read succesfully, but since all channels are sent at once, you can stop now
+ } //if nChannels == 0
+ LogE (0, prep("Warning: Trying to read Channels more than once!"));
//you will only get here when GetChannelsMHW is called, and nChannels !=0, e.g. when multiple citpids cause channels to be read multiple times. Second time, do nothing, give error so that the rest of the chain is not restarted also.
return 0;
}
-int cFilterEEPG::GetThemesMHW1 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
-{ //MHW1 Themes
+/**
+ * \brief Get MHW1 Themes
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetThemesMHW1 (const u_char * Data, int Length)
+{ //MHW1 Themes
if (Length > 19) {
sThemeMHW1 *Theme = (sThemeMHW1 *) (Data + 19);
nThemes = (Length - 19) / 15;
if (nThemes > MAX_THEMES) {
- esyslog ("EEPG: Error, themes found more than %i", MAX_THEMES);
+ LogE(1, prep("Error, %i themes found more than %i"), nThemes, MAX_THEMES);
return 0;
- }
- else {
- if (VERBOSE >= 1)
- isyslog ("-------------THEMES FOUND--------------");
+ } else {
+ LogI(1, "-------------THEMES FOUND--------------");
int ThemeId = 0;
int Offset = 0;
const u_char *ThemesIndex = (Data + 3);
for (int i = 0; i < nThemes; i++) {
- if (ThemesIndex[ThemeId] == i) {
- Offset = (Offset + 15) & 0xf0; //TODO do not understand this
- ThemeId++;
- }
- memcpy (&Themes[Offset][0], &Theme->Name, 15);
- Themes[Offset][15] = NULL; //trailing null
- CleanString (Themes[Offset]);
- if (VERBOSE >= 1)
- isyslog ("%.15s", Themes[Offset]);
- Offset++;
- Theme++;
+ if (ThemesIndex[ThemeId] == i) {
+ Offset = (Offset + 15) & 0xf0; //TODO do not understand this
+ ThemeId++;
+ }
+ memcpy (&Themes[Offset][0], &Theme->Name, 15);
+ Themes[Offset][15] = '\0'; //trailing null
+ CleanString (Themes[Offset]);
+ LogI(1, prep("%.15s"), Themes[Offset]);
+ Offset++;
+ Theme++;
}
if ((nThemes * 15) + 19 != Length) {
- esyslog ("EEPG: Themes error: buffer is smaller or bigger than sum of entries.");
- return 0;
- }
- else
- return 2;
+ LogE(0, "Themes error: buffer is smaller or bigger than sum of entries.");
+ return 0;
+ } else
+ return 2;
}
}
return 1;
}
-int cFilterEEPG::GetThemesMHW2 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get MHW2 Themes
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+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;
@@ -1209,82 +1319,81 @@ int cFilterEEPG::GetThemesMHW2 (const u_char * Data, int Length) //return code 0
int lenSubThemeName = 0;
int pThemeId = 0;
if (Length > 4) {
- if (VERBOSE >= 1)
- isyslog ("-------------THEMES FOUND--------------");
+ LogI(1, "-------------THEMES FOUND--------------");
for (int i = 0; i < Data[4]; i++) {
- p1 = ((Data[5 + i * 2] << 8) | Data[6 + i * 2]) + 3;
- if (Length > p1) {
- for (int ii = 0; ii <= (Data[p1] & 0x3f); ii++) {
- p2 = ((Data[p1 + 1 + ii * 2] << 8) | Data[p1 + 2 + ii * 2]) + 3;
- if (Length > p2) {
- if (ii == 0) {
- pThemeName = p2 + 1;
- lenThemeName = Data[p2] & 0x1f;
- lenSubThemeName = 0;
- }
- else {
- pSubThemeName = p2 + 1;
- lenSubThemeName = Data[p2] & 0x1f;
- }
- if (Length >= (pThemeName + lenThemeName)) {
- pThemeId = ((i & 0x3f) << 6) | (ii & 0x3f);
- if (pThemeId > MAX_THEMES)
- {
- esyslog ("EEPG: Error, something wrong with themes id calculation MaxThemes: %i pThemeID:%d", MAX_THEMES, pThemeId);
- return 0; //fatal error
- }
- if ((lenThemeName + 2) < 256) {
- decodeText2(&Data[pThemeName],lenThemeName,(char*)Themes[pThemeId],256);
- //memcpy (Themes[pThemeId], &Data[pThemeName], lenThemeName);
- if (Length >= (pSubThemeName + lenSubThemeName))
- if (lenSubThemeName > 0)
- if ((lenThemeName + lenSubThemeName + 2) < 256) {
- Themes[pThemeId][lenThemeName] = ' ';
- decodeText2(&Data[pSubThemeName],lenSubThemeName,(char*)&Themes[pThemeId][lenThemeName + 1],256);
- //memcpy (&Themes[pThemeId][lenThemeName + 1], &Data[pSubThemeName], lenSubThemeName);
- }
- CleanString (Themes[pThemeId]);
- if (VERBOSE >= 1)
- isyslog ("%.*s", lenThemeName + 1 + lenSubThemeName, Themes[pThemeId]);
- //isyslog ("%.15s", (lThemes + pThemeId)->Name);
- nThemes++;
- if (nThemes > MAX_THEMES) {
- esyslog ("EEPG: Error, themes found more than %i", MAX_THEMES);
- return 0; //fatal error
- }
- }
- }
- else
- return 1; //I assume non fatal error or success
- }
- else
- return 1; //I assume non fatal error or success
- }
- }
- else
- return 1; //I assume non fatal error or success
- } //for loop
+ p1 = ((Data[5 + i * 2] << 8) | Data[6 + i * 2]) + 3;
+ if (Length > p1) {
+ for (int ii = 0; ii <= (Data[p1] & 0x3f); ii++) {
+ p2 = ((Data[p1 + 1 + ii * 2] << 8) | Data[p1 + 2 + ii * 2]) + 3;
+ if (Length > p2) {
+ if (ii == 0) {
+ pThemeName = p2 + 1;
+ lenThemeName = Data[p2] & 0x1f;
+ lenSubThemeName = 0;
+ } else {
+ pSubThemeName = p2 + 1;
+ lenSubThemeName = Data[p2] & 0x1f;
+ }
+ if (Length >= (pThemeName + lenThemeName)) {
+ pThemeId = ((i & 0x3f) << 6) | (ii & 0x3f);
+ if (pThemeId > MAX_THEMES) {
+ LogE(1, prep("Error, something wrong with themes id calculation MaxThemes: %i pThemeID:%d"), MAX_THEMES, pThemeId);
+ return 0; //fatal error
+ }
+ if ((lenThemeName + 2) < 256) {
+ decodeText2(&Data[pThemeName],lenThemeName,(char*)Themes[pThemeId],256);
+ //memcpy (Themes[pThemeId], &Data[pThemeName], lenThemeName);
+ if (Length >= (pSubThemeName + lenSubThemeName))
+ if (lenSubThemeName > 0)
+ if ((lenThemeName + lenSubThemeName + 2) < 256) {
+ Themes[pThemeId][lenThemeName] = ' ';
+ decodeText2(&Data[pSubThemeName],lenSubThemeName,(char*)&Themes[pThemeId][lenThemeName + 1],256);
+ //memcpy (&Themes[pThemeId][lenThemeName + 1], &Data[pSubThemeName], lenSubThemeName);
+ }
+ CleanString (Themes[pThemeId]);
+ LogI(1, prep("%.*s"), lenThemeName + 1 + lenSubThemeName, Themes[pThemeId]);
+ //isyslog ("%.15s", (lThemes + pThemeId)->Name);
+ nThemes++;
+ if (nThemes > MAX_THEMES) {
+ LogE(1, prep("Error, %i themes found more than %i"), nThemes, MAX_THEMES);
+ return 0; //fatal error
+ }
+ }
+ } else
+ return 1; //I assume non fatal error or success
+ } else
+ return 1; //I assume non fatal error or success
+ }
+ } else
+ return 1; //I assume non fatal error or success
+ } //for loop
//Del (Pid, Tid);
EndThemes = true;
- return 2; //all themes read
- } //if length
- } //if !EndThemes
- return 1; //non fatal or success
+ return 2; //all themes read
+ } //if length
+ } //if !EndThemes
+ return 1; //non fatal or success
}
-char *cFilterEEPG::GetSummaryTextNagra (const u_char * DataStart, long int Offset, unsigned int TitleEventId) //this function returns pointer to reserved part of memory with summary text in it, terminated by NULL
- //EventId is passed from title, to check it against the eventid of the summary
+/**
+ * \brief Get Nagra Summary text
+ *
+ * \param TitleEventId EventId passed from title, to check it against the eventId of the summary
+ * \return pointer to reserved part of memory with summary text in it, terminated by NULL
+ */
+char *cFilterEEPG::GetSummaryTextNagra (const u_char * DataStart, long int Offset, unsigned int TitleEventId)
+//EventId is passed from title, to check it against the eventid of the summary
{
u_char *p = (u_char *) DataStart + Offset;
sSummaryDataNagraGuide *SD = (sSummaryDataNagraGuide *) p;
if (TitleEventId != HILO32 (SD->EventId)) {
- esyslog ("EEPG: ERROR, Title has EventId %08x and points to Summary with EventId %08x.", TitleEventId,
- HILO32 (SD->EventId));
- return 0; //return empty string
+ LogI(0, prep("ERROR, Title has EventId %08x and points to Summary with EventId %08x."), TitleEventId,
+ HILO32 (SD->EventId));
+ return 0; //return empty string
}
- if (VERBOSE >= 3) {
+ if (CheckLevel(3)) {
if (SD->AlwaysZero1 != 0)
isyslog ("EEPGDEBUG: SummAlwaysZero1 is NOT ZERO:%x.", SD->AlwaysZero1);
if (SD->AlwaysZero2 != 0)
@@ -1304,7 +1413,7 @@ char *cFilterEEPG::GetSummaryTextNagra (const u_char * DataStart, long int Offse
if (SD->AlwaysZero9 != 0)
isyslog ("EEPGDEBUG: SummAlwaysZero9 is NOT ZERO:%x.", SD->AlwaysZero9);
- if (SD->Always1 != 0x31) //1970
+ if (SD->Always1 != 0x31) //1970
isyslog ("EEPGDEBUG: SummAlways1:%02x.", SD->Always1);
if (SD->Always9 != 0x39)
isyslog ("EEPGDEBUG: SummAlways9:%02x.", SD->Always9);
@@ -1313,114 +1422,109 @@ char *cFilterEEPG::GetSummaryTextNagra (const u_char * DataStart, long int Offse
if (SD->Always0 != 0x30)
isyslog ("EEPGDEBUG: SummAlways0:%02x.", SD->Always0);
- if (SD->Always0x01 != 0x01) // 0x01 byte
+ if (SD->Always0x01 != 0x01) // 0x01 byte
isyslog ("EEPGDEBUG: Summ0x01 byte:%02x.", SD->Always0x01);
}
u_char *p2 = (u_char *) DataStart + HILO32 (SD->SummTxtOffset);
-/* esyslog
- ("EEPGDEBUG: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x.",
- HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2, SD->Unknown1,
- SD->Unknown2);
-*/
- unsigned char *Text = NULL; //makes first realloc work like malloc
- int TotLength = 0; //and also makes empty summaries if *p2 != 0x4e
+ /* esyslog
+ ("EEPGDEBUG: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x.",
+ HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2, SD->Unknown1,
+ SD->Unknown2);
+ */
+ unsigned char *Text = NULL; //makes first realloc work like malloc
+ int TotLength = 0; //and also makes empty summaries if *p2 != 0x4e
if (SD->NumberOfBlocks > 1) {
switch (*p2) {
- case 0x4e: //valid summary text follows
- { //prevents compiler from complaining
- bool LastTextBlock = false;
-
- do { //for all text parts
- sSummaryTextNagraGuide *ST = (sSummaryTextNagraGuide *) p2;
- p2 += 8; //skip fixed block
- if (VERBOSE >= 3)
- if (ST->AlwaysZero1 != 0)
- isyslog ("EEPGDEBUG: ST AlwaysZero1 is NOT ZERO:%x.", ST->AlwaysZero1);
- if (ST->Always0x4e != 0x4e) {
- isyslog ("EEPGDEBUG: ST Always0x4e is NOT 0x4e:%x.", ST->AlwaysZero1);
- return 0; //fatal error, empty text
- }
- //esyslog ("EEPGDEBUG: Textnr %i, Lasttxt %i.", ST->TextNr, ST->LastTextNr);
- int SummaryLength = ST->Textlength;
-
- Text = (unsigned char *) realloc (Text, SummaryLength + TotLength);
- if (Text == NULL) {
- esyslog ("EEPG: Summaries memory allocation error.");
- return 0; //empty text
- }
- memcpy (Text + TotLength, p2, SummaryLength); //append new textpart
- TotLength += SummaryLength;
- p2 += ST->Textlength; //skip text
-
- 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
-// isyslog ("EEPGDEBUG: Full Text:%s.", Text);
-
- break;
- } //prevents compiler from complaining
- case 0x8c: //"Geen uitzending" "Geen informatie beschikbaar" e.d.
- { //prevents compiler from complaining
- sSummaryGBRNagraGuide *GBR = (sSummaryGBRNagraGuide *) p2;
-
- p2 += 16; //skip fixed part, point to byte after Nextlength
- if (VERBOSE >= 3) {
- if (GBR->AlwaysZero1 != 0)
- isyslog ("EEPGDEBUG: GBR AlwaysZero1 is NOT ZERO:%x.", GBR->AlwaysZero1);
- if (GBR->AlwaysZero2 != 0)
- isyslog ("EEPGDEBUG: GBR AlwaysZero2 is NOT ZERO:%x.", GBR->AlwaysZero2);
- if (GBR->AlwaysZero3 != 0)
- isyslog ("EEPGDEBUG: GBR AlwaysZero3 is NOT ZERO:%x.", GBR->AlwaysZero3);
- if (GBR->AlwaysZero4 != 0)
- isyslog ("EEPGDEBUG: GBR AlwaysZero4 is NOT ZERO:%x.", GBR->AlwaysZero4);
-
- isyslog ("EEPGDEBUG: Blocklength: %02x Data %02x %02x %02x %02x %02x %02x %02x %02x %02x", GBR->Blocklength,
- GBR->Un1, GBR->Un2, GBR->Un3, GBR->Un4, GBR->Un5, GBR->Un6, GBR->Un7, GBR->Un8, GBR->Un9);
- for (int i = 0; i < GBR->Nextlength; i += 2)
- isyslog ("GBR Extradata %02x %02x.", *(p2 + i), *(p2 + i + 1));
- }
- } //prevents compiler from complaining
+ case 0x4e: //valid summary text follows
+ {
+ bool LastTextBlock = false;
+
+ do { //for all text parts
+ sSummaryTextNagraGuide *ST = (sSummaryTextNagraGuide *) p2;
+ p2 += 8; //skip fixed block
+ if (ST->AlwaysZero1 != 0)
+ LogD(3, prep("DEBUG: ST AlwaysZero1 is NOT ZERO:%x."), ST->AlwaysZero1);
+ if (ST->Always0x4e != 0x4e) {
+ LogI(0, prep("DEBUG: ST Always0x4e is NOT 0x4e:%x."), ST->AlwaysZero1);
+ return 0; //fatal error, empty text
+ }
+ LogI(5, prep("DEBUG: Textnr %i, Lasttxt %i."), ST->TextNr, ST->LastTextNr);
+ int SummaryLength = ST->Textlength;
+
+ Text = (unsigned char *) REALLOC (Text, SummaryLength + TotLength);
+ if (Text == NULL) {
+ LogI(0, prep("Summaries memory allocation error."));
+ return 0; //empty text
+ }
+ memcpy (Text + TotLength, p2, SummaryLength); //append new textpart
+ TotLength += SummaryLength;
+ p2 += ST->Textlength; //skip text
+
+ LastTextBlock = ((ST->LastTextNr == 0) || (ST->TextNr >= ST->LastTextNr));
+ } while (!LastTextBlock);
+ Text = (unsigned char *) REALLOC (Text, 1 + TotLength); //allocate 1 extra byte
+ Text[TotLength] = '\0'; //terminate string by NULL char
+ LogD(5, prep("DEBUG: Full Text:%s."), Text);
+
break;
+ }
+ case 0x8c: //"Geen uitzending" "Geen informatie beschikbaar" e.d.
+ {
+ sSummaryGBRNagraGuide *GBR = (sSummaryGBRNagraGuide *) p2;
+
+ p2 += 16; //skip fixed part, point to byte after Nextlength
+ if (CheckLevel(3)) {
+ if (GBR->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero1 is NOT ZERO:%x.", GBR->AlwaysZero1);
+ if (GBR->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero2 is NOT ZERO:%x.", GBR->AlwaysZero2);
+ if (GBR->AlwaysZero3 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero3 is NOT ZERO:%x.", GBR->AlwaysZero3);
+ if (GBR->AlwaysZero4 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero4 is NOT ZERO:%x.", GBR->AlwaysZero4);
+
+ isyslog ("EEPGDEBUG: Blocklength: %02x Data %02x %02x %02x %02x %02x %02x %02x %02x %02x", GBR->Blocklength,
+ GBR->Un1, GBR->Un2, GBR->Un3, GBR->Un4, GBR->Un5, GBR->Un6, GBR->Un7, GBR->Un8, GBR->Un9);
+ for (int i = 0; i < GBR->Nextlength; i += 2)
+ isyslog ("GBR Extradata %02x %02x.", *(p2 + i), *(p2 + i + 1));
+ }
+ }
+ break;
default:
- esyslog
- ("EEPG: ERROR *p2 has strange value: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x.",
- HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2,
- SD->Unknown1, SD->Unknown2);
+ LogE(0, prep("ERROR *p2 has strange value: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x."),
+ HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2,
+ SD->Unknown1, SD->Unknown2);
break;
- } //end of switch
- } //NrOfBlocks > 1
+ } //end of switch
+ } //NrOfBlocks > 1
if (TotLength == 0)
Text = NULL;
- p += 29; //skip fixed part of block
+ p += 29; //skip fixed part of block
if (SD->NumberOfBlocks == 1)
- p -= 4; //in this case there is NO summarytext AND no GBR??!!
+ p -= 4; //in this case there is NO summarytext AND no GBR??!!
for (int i = 1; i < (SD->NumberOfBlocks - 1); i++) {
- if (VERBOSE >= 3)
- isyslog ("EEPGDEBUG: Extra Blockinfo: %02x %02x %02x %02x.", *p, *(p + 1), *(p + 2), *(p + 3));
- p += 4; //skip this extra blockinfo
+ LogD(3, prep("DEBUG: Extra Blockinfo: %02x %02x %02x %02x."), *p, *(p + 1), *(p + 2), *(p + 3));
+ p += 4; //skip this extra blockinfo
}
return (char *) Text;
}
-void cFilterEEPG::PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]) //gets a channel and returns an array of schedules that WriteToSchedule can write to. Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
+void cFilterEEPG::PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]) //gets a channel and returns an array of schedules that WriteToSchedule can write to. Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
{
for (int eq = 0; eq < C->NumberOfEquivalences; eq++) {
tChannelID channelID = tChannelID (C->Src[eq], C->Nid[eq], C->Tid[eq], C->Sid[eq]);
#ifdef USE_NOEPG
if (allowedEPG (channelID) && (channelID.Valid ()))
#else
- if (channelID.Valid ()) //only add channels that are known to vdr
+ if (channelID.Valid ()) //only add channels that are known to vdr
#endif /* NOEPG */
- ps[eq] = s->AddSchedule (channelID); //open a a schedule for each equivalent channel
+ ps[eq] = s->AddSchedule (channelID); //open a a schedule for each equivalent channel
else {
ps[eq] = NULL;
- if (VERBOSE >= 5)
- esyslog
- ("EEPG ERROR: Titleblock has invalid (equivalent) channel ID: Equivalence: %i, Source:%x, C->Nid:%x,C->Tid:%x,C->Sid:%x.",
- eq, C->Src[eq], C->Nid[eq], C->Tid[eq], C->Sid[eq]);
+ LogE(5, prep("ERROR: Titleblock has invalid (equivalent) channel ID: Equivalence: %i, Source:%x, C->Nid:%x,C->Tid:%x,C->Sid:%x."),
+ eq, C->Src[eq], C->Nid[eq], C->Tid[eq], C->Sid[eq]);
}
}
}
@@ -1434,8 +1538,13 @@ void cFilterEEPG::FinishWriteToSchedule (sChannel * C, cSchedules * s, cSchedule
}
}
-void cFilterEEPG::WriteToSchedule (cSchedule * ps[MAX_EQUIVALENCES], unsigned short int NumberOfEquivalences, unsigned int EventId, unsigned int StartTime, unsigned int Duration, char *Text, char *SummText, unsigned short int ThemeId, unsigned short int TableId, unsigned short int Version, char Rating) //ps points to array of schedules ps[eq], where eq is equivalence number of the channel. If channelId is invalid then ps[eq]=NULL
- //Duration in minutes
+/**
+ * \brief write event to schedule
+ *
+ * \param Duration the Duration of the event in minutes
+ * \param ps points to array of schedules ps[eq], where eq is equivalence number of the channel. If channelId is invalid then ps[eq]=NULL
+ */
+void cFilterEEPG::WriteToSchedule (cSchedule * ps[MAX_EQUIVALENCES], unsigned short int NumberOfEquivalences, unsigned int EventId, unsigned int StartTime, unsigned int Duration, char *Text, char *SummText, unsigned short int ThemeId, unsigned short int TableId, unsigned short int Version, char Rating)
{
bool WrittenTitle = false;
bool WrittenSummary = false;
@@ -1443,111 +1552,114 @@ void cFilterEEPG::WriteToSchedule (cSchedule * ps[MAX_EQUIVALENCES], unsigned sh
if (ps[eq]) {
cEvent *Event = NULL;
- Event = (cEvent *) ps[eq]->GetEvent (EventId); //since Nagra uses consistent EventIds, try this first
+ Event = (cEvent *) ps[eq]->GetEvent (EventId); //since Nagra uses consistent EventIds, try this first
bool TableIdMatches = false;
if (Event)
- TableIdMatches = (Event->TableID() == TableId);
- if (!Event || !TableIdMatches) //if EventId does not match, or it matched with wrong TableId, then try with StartTime
- Event = (cEvent *) ps[eq]->GetEvent (EventId, StartTime);
+ TableIdMatches = (Event->TableID() == TableId);
+ if (!Event || !TableIdMatches || abs(Event->StartTime() - (time_t) StartTime) > Duration * 60) //if EventId does not match, or it matched with wrong TableId, then try with StartTime
+ Event = (cEvent *) ps[eq]->GetEvent (EventId, StartTime);
cEvent *newEvent = NULL;
- if (!Event) { //event is new
- Event = newEvent = new cEvent (EventId);
- Event->SetSeen ();
- }
- else if (Event->TableID() < TableId) { //existing table may not be overwritten
- RejectTableId++;
- //esyslog ("EEPGDEBUG: Rejecting Event, existing TableID:%x, new TableID:%x.", Event->TableID (),
- // TableId);
- Event = NULL;
+ if (!Event) { //event is new
+ Event = newEvent = new cEvent (EventId);
+ Event->SetSeen ();
+ } else if (Event->TableID() < TableId) { //existing table may not be overwritten
+ RejectTableId++;
+ //esyslog ("EEPGDEBUG: Rejecting Event, existing TableID:%x, new TableID:%x.", Event->TableID (),
+ // TableId);
+ Event = NULL;
}
if (Event) {
- Event->SetEventID (EventId); //otherwise the summary cannot be added later
- Event->SetTableID (TableId); //TableID 0 is reserved for external epg, will not be overwritten; the lower the TableID, the more actual it is
- Event->SetVersion (Version); //TODO use version and tableID to decide whether to update; TODO add language code
- Event->SetStartTime (StartTime);
- Event->SetDuration (Duration * 60);
- if (Rating){
- Event->SetParentalRating(Rating);
- }
- char *tmp;
- if (Text != 0x00) {
- WrittenTitle = true;
- CleanString ((uchar *) Text);
- Event->SetTitle (Text);
- }
- asprintf (&tmp, "%s - %d\'", Themes[ThemeId], Duration);
- Event->SetShortText (tmp);
- //strreplace(t, '|', '\n');
- if (SummText != 0x00) {
- WrittenSummary = true;
- CleanString ((uchar *) SummText);
- Event->SetDescription (SummText);
- }
- free (tmp);
- if (newEvent)
- ps[eq]->AddEvent (newEvent);
- //newEvent->FixEpgBugs (); causes segfault
+ Event->SetEventID (EventId); //otherwise the summary cannot be added later
+ Event->SetTableID (TableId); //TableID 0 is reserved for external epg, will not be overwritten; the lower the TableID, the more actual it is
+ Event->SetVersion (Version); //TODO use version and tableID to decide whether to update; TODO add language code
+ Event->SetStartTime (StartTime);
+ Event->SetDuration (Duration * 60);
+ if (Rating) {
+ Event->SetParentalRating(Rating);
+ }
+ char *tmp;
+ if (Text != 0x00) {
+ WrittenTitle = true;
+ CleanString ((uchar *) Text);
+ Event->SetTitle (Text);
+ }
+ Asprintf (&tmp, "%s - %d\'", Themes[ThemeId], Duration);
+ Event->SetShortText (tmp);
+ //strreplace(t, '|', '\n');
+ if (SummText != 0x00) {
+ WrittenSummary = true;
+ CleanString ((uchar *) SummText);
+ Event->SetDescription (SummText);
+ }
+ free (tmp);
+ if (newEvent)
+ ps[eq]->AddEvent (newEvent);
+ //newEvent->FixEpgBugs (); causes segfault
}
-/* else
- esyslog ("EEPG: ERROR, somehow not able to add/update event.");*///at this moment only reports RejectTableId events
- if (VERBOSE >= 4) {
- isyslog ("EEPG: Title:%i, Summary:%i I would put into schedule:", TitleCounter, SummaryCounter);
- //isyslog ("C %s-%i-%i-%i\n", *cSource::ToString (C->Src[eq]), C->Nid[eq], C->Tid[eq], C->Sid[eq]);
- isyslog ("E %u %u %u 01 FF\n", EventId, StartTime, Duration * 60);
- isyslog ("T %s\n", Text);
- isyslog ("S %s - %d\'\n", Themes[ThemeId], Duration);
- isyslog ("D %s\n", SummText);
- isyslog ("e\nc\n.\n");
+ /* else
+ esyslog ("EEPG: ERROR, somehow not able to add/update event.");*///at this moment only reports RejectTableId events
+ if (CheckLevel(4)) {
+ isyslog ("EEPG: Title:%i, Summary:%i I would put into schedule:", TitleCounter, SummaryCounter);
+ //isyslog ("C %s-%i-%i-%i\n", *cSource::ToString (C->Src[eq]), C->Nid[eq], C->Tid[eq], C->Sid[eq]);
+ isyslog ("E %u %u %u 01 FF\n", EventId, StartTime, Duration * 60);
+ isyslog ("T %s\n", Text);
+ isyslog ("S %s - %d\'\n", Themes[ThemeId], Duration);
+ isyslog ("D %s\n", SummText);
+ isyslog ("e\nc\n.\n");
}
- } //if ps[eq]
- } //for eq
+ } //if ps[eq]
+ } //for eq
if (WrittenTitle)
TitleCounter++;
if (WrittenSummary)
SummaryCounter++;
}
-void cFilterEEPG::GetTitlesNagra (const u_char * Data, int Length, unsigned short TableIdExtension) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
-{ //TableIdExtension is the TIE from the relevant summary sections!
+/**
+ * \brief Get Nagra titles
+ *
+ * \param TableIdExtension the TIE from the relevant summary sections!
+ */
+void cFilterEEPG::GetTitlesNagra (const u_char * Data, int Length, unsigned short TableIdExtension)
+{
u_char *p = (u_char *) Data;
u_char *DataEnd = (u_char *) Data + Length;
u_char *next_p;
- unsigned short int MonthdayTitles = ((TableIdExtension & 0x1ff) >> 4); //Day is coded in day of the month
+ unsigned short int MonthdayTitles = ((TableIdExtension & 0x1ff) >> 4); //Day is coded in day of the month
time_t timeLocal;
struct tm *tmCurrent;
timeLocal = time (NULL);
- tmCurrent = gmtime (&timeLocal); //gmtime gives UTC; only used for getting current year and current day of the month...
+ tmCurrent = gmtime (&timeLocal); //gmtime gives UTC; only used for getting current year and current day of the month...
unsigned short int CurrentMonthday = tmCurrent->tm_mday;
unsigned short int CurrentYear = tmCurrent->tm_year;
unsigned short int CurrentMonth = tmCurrent->tm_mon;
//esyslog("EEPGDEBUG: CurrentMonthday=%i, TableIdExtension:%04x, MonthdayTitles=%i.",CurrentMonthday,TableIdExtension, MonthdayTitles);
cSchedulesLock SchedulesLock (true);
cSchedules *s = (cSchedules *) cSchedules::Schedules (SchedulesLock);
- do { //process each block of titles
+ do { //process each block of titles
sTitleBlockNagraGuide *TB = (sTitleBlockNagraGuide *) p;
int ChannelId = HILO16 (TB->ChannelId);
int Blocklength = HILO16 (TB->Blocklength);
long int NumberOfTitles = HILO32 (TB->NumberOfTitles);
- if (VERBOSE >= 3)
- isyslog ("EEPGDEBUG: ChannelId %04x, Blocklength %04x, NumberOfTitles %lu.", ChannelId, Blocklength,
- NumberOfTitles);
- p += 4; //skip ChannelId and Blocklength
+ LogD(3, prep("DEBUG: ChannelId %04x, Blocklength %04x, NumberOfTitles %lu."), ChannelId, Blocklength,
+ NumberOfTitles);
+ p += 4; //skip ChannelId and Blocklength
next_p = p + Blocklength;
- if (next_p > DataEnd) { //only process if block is complete
- esyslog ("EEPG: ERROR, Block exceeds end of Data. p:%p, Blocklength:%x,DataEnd:%p.", p, Blocklength, DataEnd);
- return; //fatal error, this should never happen
+ if (next_p > DataEnd) { //only process if block is complete
+ LogE(0, prep("ERROR, Block exceeds end of Data. p:%p, Blocklength:%x,DataEnd:%p."), p, Blocklength, DataEnd);
+ return; //fatal error, this should never happen
}
- p += 4; //skip Titlenumber
+ p += 4; //skip Titlenumber
- sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
+ sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
cSchedule *ps[MAX_EQUIVALENCES];
PrepareToWriteToSchedule (C, s, ps);
- for (int i = 0; i < NumberOfTitles; i++) { //process each title within block
+ for (int i = 0; i < NumberOfTitles; i++) { //process each title within block
sTitleNagraGuide *Title = (sTitleNagraGuide *) p;
unsigned int EventId = HILO32 (Title->EventId);
@@ -1560,331 +1672,308 @@ void cFilterEEPG::GetTitlesNagra (const u_char * Data, int Length, unsigned shor
tmCurrent->tm_mon = CurrentMonth;
tmCurrent->tm_mday = MonthdayTitles;
tmCurrent->tm_hour = 0;
- tmCurrent->tm_min = StartTime; //if starttime is bigger than 1 hour, mktime will correct this!
+ tmCurrent->tm_min = StartTime; //if starttime is bigger than 1 hour, mktime will correct this!
tmCurrent->tm_sec = 0;
- tmCurrent->tm_isdst = -1; //now correct with daylight savings
- if (MonthdayTitles < CurrentMonthday - 7) //the titles that are older than one week are not from the past, but from next month!
- //at first this was set at -1 day (= yesterday), but sometimes providers send old data which then
- //end up in next months schedule ...
- tmCurrent->tm_mon++; //if a year border is passed, mktime will take care of this!
- StartTime = UTC2LocalTime (mktime (tmCurrent)); //VDR stores its times in UTC, but wants its input in local time...
+ tmCurrent->tm_isdst = -1; //now correct with daylight savings
+ if (MonthdayTitles < CurrentMonthday - 7) //the titles that are older than one week are not from the past, but from next month!
+ //at first this was set at -1 day (= yesterday), but sometimes providers send old data which then
+ //end up in next months schedule ...
+ tmCurrent->tm_mon++; //if a year border is passed, mktime will take care of this!
+ StartTime = UTC2LocalTime (mktime (tmCurrent)); //VDR stores its times in UTC, but wants its input in local time...
char *Text = NULL;
u_char *t = (u_char *) Data + HILO32 (Title->OffsetToText);
//u_char *t2 = (u_char *) Data + HILO32 (Title->OffsetToText2);
if (t >= DataEnd)
- esyslog ("EEPG: ERROR, Title Text out of range: t:%p, DataEnd:%p, Data:%p, Length:%i.", t, DataEnd, Data,
- Length);
+ LogE(0, prep("ERROR, Title Text out of range: t:%p, DataEnd:%p, Data:%p, Length:%i."), t, DataEnd, Data,
+ Length);
else {
- asprintf (&Text, "%.*s", *t, t + 1); //FIXME second text string is not processed right now
- //asprintf (&Text, "%.*s %.*s", *t, t + 1, *t2, t2 + 1);
-
- //now get summary texts
- u_char *DataStartSummaries = buffer[TableIdExtension] + 4;
- unsigned int DataLengthSummaries = bufsize[TableIdExtension] - 4;
- char *SummText = NULL;
- if (HILO32 (Title->SumDataOffset) >= DataLengthSummaries)
- esyslog ("EEPG: ERROR, SumDataOffset out of range: Title->SumDataOffset:%i, DataLengthSummaries:%i.", HILO32 (Title->SumDataOffset),DataLengthSummaries);
- else
- SummText = GetSummaryTextNagra (DataStartSummaries, HILO32 (Title->SumDataOffset), EventId);
-
- if (VERBOSE >= 3)
- isyslog
- ("EEPGDEBUG: Eventid: %08x ChannelId:%x, Starttime %02i:%02i, Duration %i, OffsetToText:%08x, OffsetToText2:%08x, SumDataOffset:%08x ThemeId:%x Title:%s \n SummaryText:%s",
- EventId, ChannelId, Hours, Minutes,
- Title->Duration, HILO32 (Title->OffsetToText), HILO32 (Title->OffsetToText2),
- HILO32 (Title->SumDataOffset), Title->ThemeId, Text, SummText);
-
- if (Themes[Title->ThemeId][0] == 0x00) //if detailed themeid is not known, get global themeid
- Title->ThemeId &= 0xf0;
- WriteToSchedule (ps, C->NumberOfEquivalences, EventId, StartTime, Title->Duration, Text, SummText,
- Title->ThemeId, NAGRA_TABLE_ID, Version);
-
- if (Text != NULL)
- free (Text);
- Text = NULL;
- if (SummText != NULL)
- free (SummText);
- SummText = NULL;
+ Asprintf (&Text, "%.*s", *t, t + 1);
+ //asprintf (&Text, "%.*s %.*s", *t, t + 1, *t2, t2 + 1); //FIXME second text string is not processed right now
+
+ //now get summary texts
+ u_char *DataStartSummaries = buffer[TableIdExtension] + 4;
+ unsigned int DataLengthSummaries = bufsize[TableIdExtension] - 4;
+ char *SummText = NULL;
+ if (HILO32 (Title->SumDataOffset) >= DataLengthSummaries)
+ LogE(0, prep("ERROR, SumDataOffset out of range: Title->SumDataOffset:%i, DataLengthSummaries:%i."), HILO32 (Title->SumDataOffset),DataLengthSummaries);
+ else
+ SummText = GetSummaryTextNagra (DataStartSummaries, HILO32 (Title->SumDataOffset), EventId);
+
+ LogD(3, prep("DEBUG: Eventid: %08x ChannelId:%x, Starttime %02i:%02i, Duration %i, OffsetToText:%08x, OffsetToText2:%08x, SumDataOffset:%08x ThemeId:%x Title:%s \n SummaryText:%s"),
+ EventId, ChannelId, Hours, Minutes, Title->Duration,
+ HILO32 (Title->OffsetToText), HILO32 (Title->OffsetToText2),
+ HILO32 (Title->SumDataOffset), Title->ThemeId, Text, SummText);
+
+ if (Themes[Title->ThemeId][0] == 0x00) //if detailed themeid is not known, get global themeid
+ Title->ThemeId &= 0xf0;
+ WriteToSchedule (ps, C->NumberOfEquivalences, EventId, StartTime, Title->Duration, Text, SummText,
+ Title->ThemeId, NAGRA_TABLE_ID, Version);
+
+ if (Text != NULL)
+ free (Text);
+ Text = NULL;
+ if (SummText != NULL)
+ free (SummText);
+ SummText = NULL;
}
- if (VERBOSE >= 3) {
- if (Title->AlwaysZero16 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero16 (3bits) is NOT ZERO:%x.", Title->AlwaysZero16);
- if (Title->AlwaysZero17 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero17 is NOT ZERO:%x.", Title->AlwaysZero17);
- if (Title->AlwaysZero1 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero1 is NOT ZERO:%x.", Title->AlwaysZero1);
- if (Title->AlwaysZero2 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero2 is NOT ZERO:%x.", Title->AlwaysZero2);
- if (Title->AlwaysZero3 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero3 is NOT ZERO:%x.", Title->AlwaysZero3);
- if (Title->AlwaysZero4 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero4 is NOT ZERO:%x.", Title->AlwaysZero4);
- if (Title->AlwaysZero5 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero5 is NOT ZERO:%x.", Title->AlwaysZero5);
- if (Title->AlwaysZero8 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero8 is NOT ZERO:%x.", Title->AlwaysZero8);
- if (Title->AlwaysZero9 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero9 is NOT ZERO:%x.", Title->AlwaysZero9);
- if (Title->AlwaysZero10 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero10 is NOT ZERO:%x.", Title->AlwaysZero10);
- if (Title->AlwaysZero11 != 0)
- isyslog ("EEPGDEBUG: TitleAlwaysZero11 is NOT ZERO:%x.", Title->AlwaysZero11);
+ if (CheckLevel(3)) {
+ if (Title->AlwaysZero16 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero16 (3bits) is NOT ZERO:%x.", Title->AlwaysZero16);
+ if (Title->AlwaysZero17 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero17 is NOT ZERO:%x.", Title->AlwaysZero17);
+ if (Title->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero1 is NOT ZERO:%x.", Title->AlwaysZero1);
+ if (Title->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero2 is NOT ZERO:%x.", Title->AlwaysZero2);
+ if (Title->AlwaysZero3 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero3 is NOT ZERO:%x.", Title->AlwaysZero3);
+ if (Title->AlwaysZero4 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero4 is NOT ZERO:%x.", Title->AlwaysZero4);
+ if (Title->AlwaysZero5 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero5 is NOT ZERO:%x.", Title->AlwaysZero5);
+ if (Title->AlwaysZero8 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero8 is NOT ZERO:%x.", Title->AlwaysZero8);
+ if (Title->AlwaysZero9 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero9 is NOT ZERO:%x.", Title->AlwaysZero9);
+ if (Title->AlwaysZero10 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero10 is NOT ZERO:%x.", Title->AlwaysZero10);
+ if (Title->AlwaysZero11 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero11 is NOT ZERO:%x.", Title->AlwaysZero11);
}
- p += 30; //next title
- } //end for titles
+ p += 30; //next title
+ } //end for titles
FinishWriteToSchedule (C, s, ps);
p = next_p;
- } while (p < DataEnd); //end of TitleBlock
+ } 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
+ u_char *p = DataStart; //TODO Language code terminated by 0 is ignored
u_char *DataEnd = DataStart + Length;
u_char *DataStartTitles = buffer[TableIdExtension] + 4;
u_char *DataEndTitles = DataStartTitles + bufsize[TableIdExtension] - 4;
if (Length == 0) {
- if (VERBOSE >= 1)
- isyslog ("EEPG: NO THEMES FOUND");
+ LogI(1, prep("NO THEMES FOUND"));
return 2;
}
int NumberOfThemes = (*p << 24) | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
- p += 4; //skip number of themes block
+ p += 4; //skip number of themes block
//isyslog ("EEPG: found %i themes.", NumberOfThemes);
- if ((VERBOSE >= 1) && (nThemes == 0))
- isyslog ("-------------THEMES FOUND--------------");
+ if ((nThemes == 0))
+ LogI(1, "-------------THEMES FOUND--------------");
for (int i = 0; i < NumberOfThemes; i++) {
int Textlength = *p;
- p++; //skip textlength byte
+ p++; //skip textlength byte
u_char *Text = p;
u_char ThemeId = 0;
- p += Textlength; //skip text
+ p += Textlength; //skip text
int NrOfBlocks = (*p << 8) | *(p + 1);
- p += 2; //skip nrofblocks
+ p += 2; //skip nrofblocks
bool AnyDoubt = false;
u_char *p2 = p;
p += NrOfBlocks * 8;
for (int j = 0; j < NrOfBlocks; j++) {
sThemesTitlesNagraGuide *TT = (sThemesTitlesNagraGuide *) p2;
- p2 += 8; //skip block
+ p2 += 8; //skip block
u_char *NewThemeId = DataStartTitles + HILO32 (TT->TitleOffset) + 28;
if (NewThemeId >= DataEndTitles)
- esyslog ("EEPG: ERROR, ThemeId out of range: NewThemeId:%p, DataEndTitles:%p, DataStartTitles:%p.", NewThemeId,
- DataEndTitles, DataStartTitles);
+ LogE(0, prep("ERROR, ThemeId out of range: NewThemeId:%p, DataEndTitles:%p, DataStartTitles:%p."), NewThemeId,
+ DataEndTitles, DataStartTitles);
else {
- //esyslog("EEPGDEBUG: NewThemeId:%02x, Text:%s.",*NewThemeId, Text);
- if (Themes[*NewThemeId][0] != 0x00) { //theme is already filled, break off
- AnyDoubt = true;
- break;
- }
- if (j == 0) //first block
- ThemeId = *NewThemeId;
- else if (ThemeId != *NewThemeId) { //different theme ids in block
- if ((ThemeId & 0xf0) != (*NewThemeId & 0xf0)) { //major nible of themeid does not correspond
- if (VERBOSE >= 3)
- esyslog
- ("EEPG: ERROR, Theme has multiple indices which differ in major nibble, old index = %x, new index = %x. Ignoring both indices.",
- ThemeId, *NewThemeId);
- AnyDoubt = true;
- break;
- }
- else if ((ThemeId & 0x0f) != 0) //ThemeId is like 1a, 2a, not like 10,20. So it is minor in tree-structure, and it should be labeled in major part of tree
- ThemeId = *NewThemeId; //lets hope new themeid is major, if not, it has not worsened....
- }
- } //else NewThemeId >= DataEndTitles
- if (VERBOSE >= 3) {
- if (TT->Always1 != 1)
- isyslog ("EEPGDEBUG: TT Always1 is NOT 1:%x.", TT->Always1);
- if (TT->AlwaysZero1 != 0)
- isyslog ("EEPGDEBUG: TT AlwaysZero1 is NOT ZERO:%x.", TT->AlwaysZero1);
- if (TT->AlwaysZero2 != 0)
- isyslog ("EEPGDEBUG: TT AlwaysZero2 is NOT ZERO:%x.", TT->AlwaysZero2);
+ //esyslog("EEPGDEBUG: NewThemeId:%02x, Text:%s.",*NewThemeId, Text);
+ if (Themes[*NewThemeId][0] != 0x00) { //theme is already filled, break off
+ AnyDoubt = true;
+ break;
+ }
+ if (j == 0) //first block
+ ThemeId = *NewThemeId;
+ else if (ThemeId != *NewThemeId) { //different theme ids in block
+ if ((ThemeId & 0xf0) != (*NewThemeId & 0xf0)) { //major nible of themeid does not correspond
+ LogE(3, prep("ERROR, Theme has multiple indices which differ in major nibble, old index = %x, new index = %x. Ignoring both indices."),
+ ThemeId, *NewThemeId);
+ AnyDoubt = true;
+ break;
+ } else if ((ThemeId & 0x0f) != 0) //ThemeId is like 1a, 2a, not like 10,20. So it is minor in tree-structure, and it should be labeled in major part of tree
+ ThemeId = *NewThemeId; //lets hope new themeid is major, if not, it has not worsened....
+ }
+ } //else NewThemeId >= DataEndTitles
+ if (CheckLevel(3)) {
+ if (TT->Always1 != 1)
+ isyslog ("EEPGDEBUG: TT Always1 is NOT 1:%x.", TT->Always1);
+ if (TT->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: TT AlwaysZero1 is NOT ZERO:%x.", TT->AlwaysZero1);
+ if (TT->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: TT AlwaysZero2 is NOT ZERO:%x.", TT->AlwaysZero2);
}
- } //for nrofblocks
+ } //for nrofblocks
// esyslog("EEPGDEBUG: AnyDoubt:%x.",AnyDoubt);
if (!AnyDoubt) {
if (Textlength > 63)
- Textlength = 63; //leave room for trailing NULL
+ Textlength = 63; //leave room for trailing NULL
if (Themes[ThemeId][0] != 0) {
- esyslog
- ("EEPG: Trying to add new theme, but Id already exists. ThemeId = %x, Old theme with this Id:%s, new theme: %s.",
- ThemeId, Themes[ThemeId], Text);
- continue;
+ LogE(0, prep("Trying to add new theme, but Id already exists. ThemeId = %x, Old theme with this Id:%s, new theme: %s."),
+ ThemeId, Themes[ThemeId], Text);
+ continue;
}
memcpy (&Themes[ThemeId], Text, Textlength);
- Themes[ThemeId][Textlength] = NULL; //trailing NULL
+ Themes[ThemeId][Textlength] = '\0'; //trailing NULL
CleanString (Themes[ThemeId]);
nThemes++;
- if (VERBOSE >= 1)
- isyslog ("%02x %s", ThemeId, Themes[ThemeId]);
+ LogI(1, prep("%02x %s"), ThemeId, Themes[ThemeId]);
}
- } //for NumberOfThemes
+ } //for NumberOfThemes
if (p != DataEnd) {
- esyslog ("EEPG: Themes error: buffer is smaller or bigger than sum of entries. p:%p,DataEnd:%p", p, DataEnd);
+ LogE(0, prep("Themes error: buffer is smaller or bigger than sum of entries. p:%p,DataEnd:%p"), p, DataEnd);
return 0;
- }
- else
+ } else
return 2;
}
-int cFilterEEPG::GetChannelsNagra (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get Nagra channels
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetChannelsNagra (const u_char * Data, int Length)
{
u_char *DataStart = (u_char *) Data;
u_char *p = DataStart;
u_char *DataEnd = DataStart + Length;
nChannels = (*p << 24) | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
- p += 4; //skip numberofchannels
- if (VERBOSE >= 1) {
+ p += 4; //skip numberofchannels
+ if (CheckLevel(1)) {
isyslog ("| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
isyslog ("|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
- "-----------------------------", "--------------------");
+ "-----------------------------", "--------------------");
}
for (int j = 0; j < nChannels; j++) {
sChannelsNagraGuide *Channel = (sChannelsNagraGuide *) p;
sChannel *C = &sChannels[j];
- C->ChannelId = j + 1; //Nagra starts numbering at 1
- ChannelSeq[C->ChannelId] = j; //fill lookup table to go from channel-id to sequence nr in table; lookuptable starts with 0
+ C->ChannelId = j + 1; //Nagra starts numbering at 1
+ 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->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->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);
-
- if (VERBOSE >= 1) {
- char *ChID;
- asprintf (&ChID, "%s-%i-%i-%i-0", *cSource::ToString (C->Src[0]), C->Nid[0], C->Tid[0], C->Sid[0]);
- char *IsF;
- if (IsFound)
- asprintf (&IsF, " %-3.3s |", "YES");
- else
- asprintf (&IsF, " %-3.3s |", "NO");
- isyslog ("|% 5d | %-26.26s | %-22.22s |%s % 6d |\n", C->ChannelId, ChID, C->Name, IsF, C->SkyNumber);
- free (ChID);
- free (IsF);
- }
- if (VERBOSE >= 4)
- isyslog ("EEPGDEBUG: start : %s", cs_hexdump (0, p, 9));
+ 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);
- p += 8; //skip to first 0x8c if non-FTA, or 0x00 if FTA
+ LogD(4, prep("DEBUG: start : %s"), cs_hexdump (0, p, 9));
+
+ p += 8; //skip to first 0x8c if non-FTA, or 0x00 if FTA
for (int i = 0; i < Channel->Nr8cBlocks; i++) {
if (*p != 0x8c) {
- esyslog ("EEPGDEBUG: ERROR in Channel Table, expected value of 0x8c is %02x", *p);
- return 0; //fatal error
+ LogD(0, prep("DEBUG: ERROR in Channel Table, expected value of 0x8c is %02x"), *p);
+ return 0; //fatal error
}
- p++; //skip 8c byte
- if (VERBOSE >= 4)
- isyslog ("EEPGDEBUG: 8c string: %s", cs_hexdump (0, p + 1, *p));
- p += *p; //skip 8c block
- p++; //forgot to skip length byte
+ p++; //skip 8c byte
+ LogD(4, prep("DEBUG: 8c string: %s"), cs_hexdump (0, p + 1, *p));
+ p += *p; //skip 8c block
+ p++; //forgot to skip length byte
}
//start last non 8c block here
if (*p != 0x00) {
- esyslog ("EEPGDEBUG: ERROR in Channel Table, expected value of 0x00 is %02x", *p);
- return 0; //fatal error
+ LogE(0, prep("ERROR in Channel Table, expected value of 0x00 is %02x"), *p);
+ return 0; //fatal error
}
- p++; //skip 0x00 byte
- if (VERBOSE >= 4)
- isyslog ("EEPGDEBUG: endstring: %s", cs_hexdump (0, p + 1, *p * 4));
- p += (*p * 4); //p points to nrofblocks, each block is 4 bytes
- p++; //forgot to skip nrofblocks byte
-
-/*
- if (Channel->AlwaysZero1 != 0)
- isyslog ("EEPGDEBUG: AlwaysZero1 is NOT ZERO:%x.", Channel->AlwaysZero1);
- if (Channel->AlwaysZero2 != 0)
- isyslog ("EEPGDEBUG: AlwaysZero2 is NOT ZERO:%x.", Channel->AlwaysZero2);
- if (Channel->Always0x8c != 0x8c)
- isyslog ("EEPGDEBUG: Always0x8c is NOT 0x8c:%x.", Channel->Always0x8c);
- if (Channel->Always0x08 != 0x08)
- isyslog ("EEPGDEBUG: Always0x08 is NOT 0x08:%x.", Channel->Always0x08);
- if (Channel->Always0x02 != 0x02)
- isyslog ("EEPGDEBUG: Always0x02 is NOT 0x02:%x.", Channel->Always0x02);
- if (Channel->Always0x01 != 0x01)
- isyslog ("EEPGDEBUG: Always0x01 is NOT 0x01:%x.", Channel->Always0x01);
- if (Channel->Always0x20 != 0x20)
- isyslog ("EEPGDEBUG: Always0x20 is NOT 0x20:%x.", Channel->Always0x20);
- if (Channel->Always0x0a != 0x0a)
- isyslog ("EEPGDEBUG: Always0x0a is NOT 0x0a:%x.", Channel->Always0x0a);
- if (Channel->Always0x81 != 0x81)
- isyslog ("EEPGDEBUG: Always0x81 is NOT 0x81:%x.", Channel->Always0x81);
- if (Channel->Always0x44 != 0x44)
- isyslog ("EEPGDEBUG: Always0x44 is NOT 0x44:%x.", Channel->Always0x44);
-*/
+ p++; //skip 0x00 byte
+ LogD(4, prep("DEBUG: endstring: %s"), cs_hexdump (0, p + 1, *p * 4));
+ p += (*p * 4); //p points to nrofblocks, each block is 4 bytes
+ p++; //forgot to skip nrofblocks byte
+
+ /*
+ if (Channel->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: AlwaysZero1 is NOT ZERO:%x.", Channel->AlwaysZero1);
+ if (Channel->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: AlwaysZero2 is NOT ZERO:%x.", Channel->AlwaysZero2);
+ if (Channel->Always0x8c != 0x8c)
+ isyslog ("EEPGDEBUG: Always0x8c is NOT 0x8c:%x.", Channel->Always0x8c);
+ if (Channel->Always0x08 != 0x08)
+ isyslog ("EEPGDEBUG: Always0x08 is NOT 0x08:%x.", Channel->Always0x08);
+ if (Channel->Always0x02 != 0x02)
+ isyslog ("EEPGDEBUG: Always0x02 is NOT 0x02:%x.", Channel->Always0x02);
+ if (Channel->Always0x01 != 0x01)
+ isyslog ("EEPGDEBUG: Always0x01 is NOT 0x01:%x.", Channel->Always0x01);
+ if (Channel->Always0x20 != 0x20)
+ isyslog ("EEPGDEBUG: Always0x20 is NOT 0x20:%x.", Channel->Always0x20);
+ if (Channel->Always0x0a != 0x0a)
+ isyslog ("EEPGDEBUG: Always0x0a is NOT 0x0a:%x.", Channel->Always0x0a);
+ if (Channel->Always0x81 != 0x81)
+ isyslog ("EEPGDEBUG: Always0x81 is NOT 0x81:%x.", Channel->Always0x81);
+ if (Channel->Always0x44 != 0x44)
+ isyslog ("EEPGDEBUG: Always0x44 is NOT 0x44:%x.", Channel->Always0x44);
+ */
}
if (p != DataEnd)
- esyslog ("EEPG: Warning, possible problem at end of channel table; p = %p, DataEnd = %p", p, DataEnd);
+ LogE(0, prep("Warning, possible problem at end of channel table; p = %p, DataEnd = %p"), p, DataEnd);
LoadEquivalentChannels ();
- return 2; //obviously, when you get here, channels are read succesfully, but since all channels are sent at once, you can stop now
+ return 2; //obviously, when you get here, channels are read succesfully, but since all channels are sent at once, you can stop now
}
-int cFilterEEPG::GetNagra (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get Nagra extended EPG
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetNagra (const u_char * Data, int Length)
{
sTitleBlockHeaderNagraGuide *TBH = (sTitleBlockHeaderNagraGuide *) Data;
- if (InitialTitle[0] == 0x00) { //InitialTitle is empty, so we are waiting for the start marker
- if (TBH->TableIdExtensionHigh == 0x00 && TBH->TableIdExtensionLow == 0x00) { //this is the start of the data
+ if (InitialTitle[0] == 0x00) { //InitialTitle is empty, so we are waiting for the start marker
+ if (TBH->TableIdExtensionHigh == 0x00 && TBH->TableIdExtensionLow == 0x00) { //this is the start of the data
if (TBH->VersionNumber == LastVersionNagra) {
- isyslog ("EEPG: Nagra EEPG already up-to-date with version %i", LastVersionNagra);
- return 2;
+ LogI(0, prep("Nagra EEPG already up-to-date with version %i"), LastVersionNagra);
+ return 2;
}
Version = TBH->VersionNumber;
- isyslog ("EEPG: initialized Nagraguide, version %i", Version);
+ LogI(0, prep("initialized Nagraguide, version %i"), Version);
//u_char *p = (u_char *) Data + 11;
u_char *p = (u_char *) Data + 8;
if (*p != 0x01) {
- esyslog
- ("EEPG: Error, Nagra first byte in table_id_extension 0x0000 is not 0x01 but %02x. Format unknown, exiting.",
- *p);
- return 0; //fatal error
+ LogE(0, prep("Error, Nagra first byte in table_id_extension 0x00 is not 0x01 but %02x. Format unknown, exiting."),
+ *p);
+ return 0; //fatal error
}
- p++; //skip 0x01 byte
+ p++; //skip 0x01 byte
unsigned short int l = ((*p << 8) | *(p + 1));
- u_char *p_end = p + l - 3; //this ensures a full block of 4 bytes is there to process
- p += 2; //skip length bytes
+ u_char *p_end = p + l - 3; //this ensures a full block of 4 bytes is there to process
+ p += 2; //skip length bytes
while (p < p_end) {
- sSection0000BlockNagraGuide *S = (sSection0000BlockNagraGuide *) p;
- int TTT = ((S->TableIdExtensionHigh << 10) | (S->TableIdExtensionLow << 3) | (S->TIE200 << 9));
- if (VERBOSE >= 4)
- isyslog ("EEPGDEBUG: TableIdExtension %04x, Unknown1 %02x Version %02x Always 0xd6 %02x DayCounter %02x",
- TTT, S->Unknown1, S->VersionNumber, S->Always0xd6, S->DayCounter);
- if ((TTT > 0x0400) && (TTT < 0x0600)) //take high byte and compare with summarie tables in 0x0400 and 0x0500 range;
- NagraTIE[NagraCounter++] = TTT; //only store TIEs of titlessummaries, all others can be derived; they are stored in the order of the 0x0000 index table,
- //lets hope first entry corresponds with today, next with tomorrow etc.
- p += 4;
+ sSection0000BlockNagraGuide *S = (sSection0000BlockNagraGuide *) p;
+ int TTT = ((S->TableIdExtensionHigh << 10) | (S->TableIdExtensionLow << 3) | (S->TIE200 << 9));
+ LogD(4, prep("DEBUG: TableIdExtension %04x, Unknown1 %02x Version %02x Always 0xd6 %02x DayCounter %02x"),
+ TTT, S->Unknown1, S->VersionNumber, S->Always0xd6, S->DayCounter);
+ if ((TTT > 0x0400) && (TTT < 0x0600)) //take high byte and compare with summarie tables in 0x0400 and 0x0500 range;
+ NagraTIE[NagraCounter++] = TTT; //only store TIEs of titlessummaries, all others can be derived; they are stored in the order of the 0x0000 index table,
+ //lets hope first entry corresponds with today, next with tomorrow etc.
+ p += 4;
}
- buffer.clear (); //clear buffer maps
- bufsize.clear (); //clear buffer maps
- InitialTitle[0] = 0xff; //copy data into initial title
+ buffer.clear (); //clear buffer maps
+ bufsize.clear (); //clear buffer maps
+ InitialTitle[0] = 0xff; //copy data into initial title
}
return (1);
}
@@ -1892,35 +1981,35 @@ int cFilterEEPG::GetNagra (const u_char * Data, int Length) //return code 0 = fa
unsigned short TableIdExtension = HILO16 (TBH->TableIdExtension);
if (TableIdExtension == 0x0000) {
LastVersionNagra = Version;
- return (2); //done
+ return (2); //done
}
-/*
-Table_id_extensions:
-(0x0000)
-(0x0010) per channel, nr_of_channels entries, every entry is 8 bytes, first 4 bytes gives nr. of titles in corresponding title table
-(0x0020) per channel info day 2 of the month
-(0x01F0) per channel info day 31 of the month
-(0x0200) leeg; letop op je leest gemakkelijk door naar 0x0210!
-(0x0210) titles day 1 of the month
-(0x0220) titles day 2 of the month
-(0x03F0) titles day 31 of the month
-(0x0400) channel info
-(0x0410) summaries day 1 of the month
-(0x0420) summaries day 2 of the month
-(0x05F0) summaries day 31 of the month
-(0x0610) themes/title reference sunday, correspond to titles 0x0400 lower...
-(0x0620) themes/title reference monday
-... this goes on until 0x07f0
-(0x0810) bouquet info; references to channels within a package, day 1 of the month
-(0x0820) same day 2 of the month
-(0x09f0) same day 31 of the month
-*/
-
- if (!(TBH->TableIdExtensionHigh >= 0x02 && TBH->TableIdExtensionHigh <= 0x07)) //here we regulate which tables we are testing
+ /*
+ Table_id_extensions:
+ (0x0000)
+ (0x0010) per channel, nr_of_channels entries, every entry is 8 bytes, first 4 bytes gives nr. of titles in corresponding title table
+ (0x0020) per channel info day 2 of the month
+ (0x01F0) per channel info day 31 of the month
+ (0x0200) leeg; letop op je leest gemakkelijk door naar 0x0210!
+ (0x0210) titles day 1 of the month
+ (0x0220) titles day 2 of the month
+ (0x03F0) titles day 31 of the month
+ (0x0400) channel info
+ (0x0410) summaries day 1 of the month
+ (0x0420) summaries day 2 of the month
+ (0x05F0) summaries day 31 of the month
+ (0x0610) themes/title reference sunday, correspond to titles 0x0400 lower...
+ (0x0620) themes/title reference monday
+ ... this goes on until 0x07f0
+ (0x0810) bouquet info; references to channels within a package, day 1 of the month
+ (0x0820) same day 2 of the month
+ (0x09f0) same day 31 of the month
+ */
+
+ if (!(TBH->TableIdExtensionHigh >= 0x02 && TBH->TableIdExtensionHigh <= 0x07)) //here we regulate which tables we are testing
return (1);
- if (TableIdExtension == 0x0200) //table 0x0200 only contains language code, because it is for day 0 of the month, and 0x0400 is used for channels
+ if (TableIdExtension == 0x0200) //table 0x0200 only contains language code, because it is for day 0 of the month, and 0x0400 is used for channels
return 1;
- if (TBH->SectionNumber == 0) { //first section, create a table
+ if (TBH->SectionNumber == 0) { //first section, create a table
buffer[TableIdExtension] = NULL;
bufsize[TableIdExtension] = 0;
NumberOfTables++;
@@ -1929,131 +2018,140 @@ Table_id_extensions:
//since the data has to be stored anyway; summaries do not seem to have channelid included, so storing titles and separately storing summaries will not work...
//GetEventId only works for a specific Schedule for a specific ChannelId....
buffer[TableIdExtension] =
- (unsigned char *) realloc (buffer[TableIdExtension], SectionLength - 9 + bufsize[TableIdExtension]);
- memcpy (buffer[TableIdExtension] + bufsize[TableIdExtension], Data + 8, SectionLength - 9); //append new section
+ (unsigned char *) REALLOC (buffer[TableIdExtension], SectionLength - 9 + bufsize[TableIdExtension]);
+ memcpy (buffer[TableIdExtension] + bufsize[TableIdExtension], Data + 8, SectionLength - 9); //append new section
bufsize[TableIdExtension] += SectionLength - 9;
if (TBH->SectionNumber >= TBH->LastSectionNumber) {
- if (VERBOSE >= 1)
- isyslog ("EEPG: found %04x lastsection nr:%i.", TableIdExtension, TBH->SectionNumber);
+ LogI(1, prep("found %04x lastsection nr:%i."), TableIdExtension, TBH->SectionNumber);
// if (TBH->TableIdExtensionHigh == 0x04 || TBH->TableIdExtensionHigh == 0x05) {
if (TableIdExtension == 0x0400) {
- int Result = GetChannelsNagra (buffer[TableIdExtension] + 4, bufsize[TableIdExtension] - 4); //TODO language code terminated by 0 is ignored
+ int Result = GetChannelsNagra (buffer[TableIdExtension] + 4, bufsize[TableIdExtension] - 4); //TODO language code terminated by 0 is ignored
free (buffer[TableIdExtension]);
buffer[TableIdExtension] = NULL;
NumberOfTables--;
if (Result == 0)
- return 0; //fatal error; TODO this exit should also free all other, non-Channel sections that are stored!
+ return 0; //fatal error; TODO this exit should also free all other, non-Channel sections that are stored!
}
- } //if lastsection read
- return (1); //return and continue, nonfatal
+ } //if lastsection read
+ return (1); //return and continue, nonfatal
}
void cFilterEEPG::ProcessNagra ()
{
- for (int i = 0; i < MAX_THEMES; i++) //clear all themes
- Themes[i][0] = NULL;
+ for (int i = 0; i < MAX_THEMES; i++) //clear all themes
+ Themes[i][0] = '\0';
- for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes
+ for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes
unsigned short int TableIdExtension = NagraTIE[i];
- int TIE = TableIdExtension + 0x0200; //from 0x0400 to 0x0600 -> themes
- if (VERBOSE >= 3)
- isyslog ("EEPG: Processing Theme with TableIdExtension:%04x", TIE);
- GetThemesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension - 0x0200); //assume theme is completed //TODO Language code terminatd by 0 is ignored
+ int TIE = TableIdExtension + 0x0200; //from 0x0400 to 0x0600 -> themes
+ LogI(3, prep("Processing Theme with TableIdExtension:%04x"), TIE);
+ GetThemesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension - 0x0200); //assume theme is completed //TODO Language code terminatd by 0 is ignored
free (buffer[TIE]);
buffer[TIE] = NULL;
NumberOfTables--;
}
- for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes
+ for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes
unsigned short int TableIdExtension = NagraTIE[i];
- int TIE = TableIdExtension - 0x0200; //from 0x0400 to 0x0200 -> titles
- isyslog ("EEPG: Processing TableIdExtension:%04x", TableIdExtension);
- GetTitlesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension); //assume title-reading is completed //TODO Language code terminatd by 0 is ignored
+ int TIE = TableIdExtension - 0x0200; //from 0x0400 to 0x0200 -> titles
+ LogI(0, prep("Processing TableIdExtension:%04x"), TableIdExtension);
+ GetTitlesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension); //assume title-reading is completed //TODO Language code terminatd by 0 is ignored
free (buffer[TIE]);
buffer[TIE] = NULL;
NumberOfTables--;
- free (buffer[TableIdExtension]); //summaries
+ free (buffer[TableIdExtension]); //summaries
buffer[TableIdExtension] = NULL;
NumberOfTables--;
}
if (NumberOfTables != 0)
- esyslog ("EEPG: ERROR, Not all tables processed and stream is already repeating. NumberOfTables = %i.",
- NumberOfTables);
+ LogE(0, prep("ERROR, Not all tables processed and stream is already repeating. NumberOfTables = %i."),
+ NumberOfTables);
}
-int cFilterEEPG::GetTitlesMHW1 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get MHW1 Titles
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetTitlesMHW1 (const u_char * Data, int Length)
{
if (Length >= 42) {
sTitleMHW1 *Title = (sTitleMHW1 *) Data;
- if (Title->ChannelId == 0xff) { //FF is separator packet
- if (memcmp (InitialTitle, Data, 46) == 0) //data is the same as initial title //TODO use easier notation
- return 2;
+ if (Title->ChannelId == 0xff) { //FF is separator packet
+ if (memcmp (InitialTitle, Data, 46) == 0) { //data is the same as initial title //TODO use easier notation
+ LogD(2, prep("End procesing titles"));
+ return 2;
+ }
if (nTitles == 0)
- memcpy (InitialTitle, Data, 46); //copy data into initial title
+ memcpy (InitialTitle, Data, 46); //copy data into initial title
int Day = Title->Day;
int Hours = Title->Hours;
if (Hours > 15)
- Hours -= 4;
+ Hours -= 4;
else if (Hours > 7)
- Hours -= 2;
+ Hours -= 2;
else
- Day++;
+ Day++;
if (Day > 6)
- Day = Day - 7;
+ Day = Day - 7;
Day -= Yesterday;
if (Day < 1)
- Day = 7 + Day;
+ Day = 7 + Day;
//if (Day == 1 && Hours < 6)
if (Day == 0 && Hours < 6)
- Day = 7;
+ Day = 7;
//Day = 8;
MHWStartTime = (Day * 86400) + (Hours * 3600) + YesterdayEpochUTC;
- if (VERBOSE >= 3)
- isyslog ("EEPG Titles: FF PACKET, seqnr:%02x.", Data[5]);
- }
- else if (InitialTitle[0] != 0x00) { //if initialized this should always be 0x90 = tableid!
+ LogI(3, prep("Titles: FF PACKET, seqnr:%02x."), Data[5]);
+ } else if (InitialTitle[0] != 0x00) { //if initialized this should always be 0x90 = tableid!
if (nTitles < MAX_TITLES) {
- Title_t *T;
- T = (Title_t *) malloc (sizeof (Title_t));
- Titles[nTitles] = T;
- int Minutes = Title->Minutes;
- int StartTime = MHWStartTime + (Minutes * 60);
- T->ChannelId = Title->ChannelId - 1;
- T->ThemeId = Title->ThemeId;
- T->MjdTime = 0; //only used at MHW2 and SKY
- T->EventId = HILO32 (Title->ProgramId);
- T->StartTime = LocalTime2UTC (StartTime); //here also Daylight Savings correction is done
- T->Duration = HILO16 (Title->Duration) * 60;
- T->SummaryAvailable = Title->SummaryAvailable;
- T->Text = (unsigned char *) malloc (23 + 1);
- if (T->Text == NULL) {
- esyslog ("EEPG: Titles memory allocation error.");
- return 0;
- }
- T->Text[23] = NULL; //end string with NULL character
- memcpy (T->Text, &Title->Title, 23);
- CleanString (T->Text);
- if (VERBOSE >= 3)
- isyslog ("EEPG: EventId:%08x,ChannelId:%x, Titlenr:%d:, StartTime(epoch):%i, SummAv:%x,Name:%s.", T->EventId,
- T->ChannelId, nTitles, T->StartTime, T->SummaryAvailable, T->Text);
- nTitles++;
- } //nTitles < MaxTitles
+ Title_t *T;
+ T = (Title_t *) malloc (sizeof (Title_t));
+ Titles[nTitles] = T;
+ int Minutes = Title->Minutes;
+ int StartTime = MHWStartTime + (Minutes * 60);
+ T->ChannelId = Title->ChannelId - 1;
+ T->ThemeId = Title->ThemeId;
+ T->TableId = Title->TableId;
+ T->MjdTime = 0; //only used at MHW2 and SKY
+ T->EventId = HILO32 (Title->ProgramId);
+ T->StartTime = LocalTime2UTC (StartTime); //here also Daylight Savings correction is done
+ T->Duration = HILO16 (Title->Duration) * 60;
+ T->SummaryAvailable = Title->SummaryAvailable;
+ T->Text = (unsigned char *) malloc (47);
+ if (T->Text == NULL) {
+ LogE(0, prep("Titles memory allocation error."));
+ return 0;
+ }
+ 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);
+ LogI(3, prep("EvId:%08x,ChanId:%x, Titlenr:%d:, StartTime(epoch):%i, SummAv:%x,Name:%s."), T->EventId,
+ T->ChannelId, nTitles, T->StartTime, T->SummaryAvailable, T->Text);
+ nTitles++;
+ } //nTitles < MaxTitles
else {
- esyslog ("EEPG: Error, titles found more than %i", MAX_TITLES);
- return 0;
+ LogE(0, prep("Error, %i titles found more than %i"), nTitles, MAX_TITLES);
+ return 0;
}
- } //else if InitialTitle
- } //Length==46
+ } //else if InitialTitle
+ } //Length==46
else {
- esyslog ("EEPG: Error, length of title package < 42.");
- return 1; //non fatal
+ LogE(0, prep("Error, length of title package < 42."));
+ return 1; //non fatal
}
return 1;
}
-int cFilterEEPG::GetTitlesMHW2 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get MHW2 Titles
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetTitlesMHW2 (const u_char * Data, int Length)
{
if (Length > 18) {
int Pos = 18;
@@ -2063,248 +2161,259 @@ int cFilterEEPG::GetTitlesMHW2 (const u_char * Data, int Length) //return code 0
Check = false;
Pos += 7;
if (Pos < Length) {
- Pos += 3;
- if (Pos < Length)
- if (Data[Pos] > 0xc0) {
- Pos += (Data[Pos] - 0xc0);
- Pos += 4;
- if (Pos < Length) {
- if (Data[Pos] == 0xff) {
- Pos += 1;
- Check = true;
- }
- }
- }
+ Pos += 3;
+ if (Pos < Length)
+ if (Data[Pos] > 0xc0) {
+ Pos += (Data[Pos] - 0xc0);
+ Pos += 4;
+ if (Pos < Length) {
+ if (Data[Pos] == 0xff) {
+ Pos += 1;
+ Check = true;
+ }
+ }
+ }
}
if (Check == false){
- isyslog ("EEPGDebug: Check==false");
- return 1; // I assume nonfatal error or success
- }
+ isyslog ("EEPGDebug: Check==false");
+ return 1; // I assume nonfatal error or success
+ }
}*/
- if (memcmp (InitialTitle, Data, 16) == 0) //data is the same as initial title
- {
- return 2; //last item processed
- }
- else {
+ if (memcmp (InitialTitle, Data, 16) == 0) { //data is the same as initial title
+ return 2; //last item processed
+ } else {
if (nTitles == 0)
- memcpy (InitialTitle, Data, 16); //copy data into initial title
+ memcpy (InitialTitle, Data, 16); //copy data into initial title
//Pos = 18;
while (Pos < Length) {
- Title_t *T;
- T = (Title_t *) malloc (sizeof (Title_t));
- Titles[nTitles] = T;
- T->ChannelId = Data[Pos];
- Pos+=11;//The date time starts here
- //isyslog ("EEPGDebug: ChannelID:%d", T->ChannelId);
- unsigned int MjdTime = (Data[Pos] << 8) | Data[Pos + 1];
- T->MjdTime = 0; //not used for matching MHW2
- T->StartTime = ((MjdTime - 40587) * 86400)
- + (((((Data[Pos + 2] & 0xf0) >> 4) * 10) + (Data[Pos + 2] & 0x0f)) * 3600)
- + (((((Data[Pos + 3] & 0xf0) >> 4) * 10) + (Data[Pos + 3] & 0x0f)) * 60);
- T->Duration = (((Data[Pos + 5] << 8) | Data[Pos + 6]) >> 4) * 60;
- Len = Data[Pos + 7] & 0x3f;
- //isyslog ("EEPGDebug: Len:%d", Len);
- T->Text = (unsigned char *) malloc (Len + 2);
- if (T->Text == NULL) {
- esyslog ("EEPG: Titles memory allocation error.");
- return 0; //fatal error
- }
- T->Text[Len] = NULL; //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);
- Pos += Len + 8; // Sub Theme starts here
- T->ThemeId = ((Data[7] & 0x3f) << 6) | (Data[Pos] & 0x3f);
- T->EventId = (Data[Pos + 1] << 8) | Data[Pos + 2];
- T->SummaryAvailable = (T->EventId != 0xFFFF);
- if (VERBOSE >= 3)
- isyslog ("EEPG: EventId %04x Titlenr %d:SummAv:%x,Name:%s.", T->EventId, nTitles,
- T->SummaryAvailable, T->Text);
- Pos += 3;
- nTitles++;
- if (nTitles > MAX_TITLES) {
- esyslog ("EEPG: Error, titles found more than %i", MAX_TITLES);
- return 0; //fatal error
- }
+ Title_t *T;
+ T = (Title_t *) malloc (sizeof (Title_t));
+ Titles[nTitles] = T;
+ T->ChannelId = Data[Pos];
+ Pos+=11;//The date time starts here
+ //isyslog ("EEPGDebug: ChannelID:%d", T->ChannelId);
+ unsigned int MjdTime = (Data[Pos] << 8) | Data[Pos + 1];
+ T->MjdTime = 0; //not used for matching MHW2
+ T->StartTime = ((MjdTime - 40587) * 86400)
+ + (((((Data[Pos + 2] & 0xf0) >> 4) * 10) + (Data[Pos + 2] & 0x0f)) * 3600)
+ + (((((Data[Pos + 3] & 0xf0) >> 4) * 10) + (Data[Pos + 3] & 0x0f)) * 60);
+ T->Duration = (((Data[Pos + 5] << 8) | Data[Pos + 6]) >> 4) * 60;
+ Len = Data[Pos + 7] & 0x3f;
+ //isyslog ("EEPGDebug: Len:%d", Len);
+ T->Text = (unsigned char *) malloc (Len + 2);
+ if (T->Text == NULL) {
+ LogE(0, prep("Titles memory allocation error."));
+ return 0; //fatal error
+ }
+ 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);
+ Pos += Len + 8; // Sub Theme starts here
+ T->ThemeId = ((Data[7] & 0x3f) << 6) | (Data[Pos] & 0x3f);
+ T->TableId = DEFAULT_TABLE_ID; //TODO locate the actual table id
+ T->EventId = (Data[Pos + 1] << 8) | Data[Pos + 2];
+ T->SummaryAvailable = (T->EventId != 0xFFFF);
+ LogI(3, prep("EventId %04x Titlenr %d:SummAv:%x,Name:%s."), T->EventId,
+ nTitles, T->SummaryAvailable, T->Text);
+ Pos += 3;
+ nTitles++;
+ if (nTitles > MAX_TITLES) {
+ LogE(0, prep("Error, %i titles found more than %i"), nTitles, MAX_TITLES);
+ return 0; //fatal error
+ }
}
- return 1; //success
- } //else memcmp
- } //if length
- return 1; //non fatal error
+ return 1; //success
+ } //else memcmp
+ } //if length
+ return 1; //non fatal error
}
-int cFilterEEPG::GetSummariesMHW1 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get MHW1 Summaries
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetSummariesMHW1 (const u_char * Data, int Length)
{
sSummaryMHW1 *Summary = (sSummaryMHW1 *) Data;
if (Length >= 11) {
- if (Summary->NumReplays < 10) { //Why limit this at 10?
+ if (Summary->NumReplays < 10) { //Why limit this at 10?
if (Length >= (11 + (Summary->NumReplays * 7))) {
- if (Summary->Byte7 == 0xff && Summary->Byte8 == 0xff && Summary->Byte9 == 0xff) {
- if (memcmp (InitialSummary, Data, 20) == 0) { //data is equal to initial buffer
- return 2;
- }
- else if (nSummaries < MAX_TITLES) {
- if (nSummaries == 0)
- memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
- int SummaryOffset = 11 + (Summary->NumReplays * 7);
- int SummaryLength = Length - SummaryOffset;
- unsigned char *Text = (unsigned char *) malloc (2*SummaryLength + 1);
- if (Text == NULL) {
- esyslog ("EEPG: Summaries memory allocation error.");
- return 0;
- }
- Text[SummaryLength+1] = NULL; //end string with NULL character
- memcpy (Text, &Data[SummaryOffset], SummaryLength);
- decodeText2(&Data[SummaryOffset], SummaryLength, (char*)Text, 2*SummaryLength + 1);
-// CleanString (Text);
+ if (Summary->Byte7 == 0xff && Summary->Byte8 == 0xff && Summary->Byte9 == 0xff) {
+ if (memcmp (InitialSummary, Data, 20) == 0) { //data is equal to initial buffer
+ return 2;
+ } else if (nSummaries < MAX_TITLES) {
+ if (nSummaries == 0)
+ memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
+ int SummaryOffset = 11 + (Summary->NumReplays * 7);
+ int SummaryLength = Length - SummaryOffset;
+ unsigned char *Text = (unsigned char *) malloc (2*SummaryLength + 1);
+ if (Text == NULL) {
+ LogE(0, prep("Summaries memory allocation error."));
+ return 0;
+ }
+ 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);
// if (Summary->NumReplays != 0)
// esyslog ("EEPG: Number of replays:%i.", Summary->NumReplays);
- //int Replays = Summary->NumReplays;
- int ReplayOffset = 11;
- Summary_t *S;
- S = (Summary_t *) malloc (sizeof (Summary_t));
- Summaries[nSummaries] = S;
- S->NumReplays = Summary->NumReplays;
- S->EventId = HILO32 (Summary->ProgramId);
- S->Text = Text;
- int i = 0;
- do {
- S->Replays[i].MjdTime = 0; //only used for SKY
- //if (Summary->NumReplays == 0) {
- //S->ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
- //S->StartTime = 0;
- //}
- //else {
- S->Replays[i].ChannelId = Data[ReplayOffset++] - 1;
- unsigned int Date_hi = Data[ReplayOffset++];
- unsigned int Date_lo = Data[ReplayOffset++];
- unsigned short int Hour = Data[ReplayOffset++];
- unsigned short int Minute = Data[ReplayOffset++];
- unsigned short int Sec = Data[ReplayOffset++];
- ReplayOffset++; //makes total of 7 bytes
-
- S->Replays[i].StartTime = MjdToEpochTime (Date) + (((((Hour & 0xf0) >> 4) * 10) + (Hour & 0x0f)) * 3600)
- + (((((Minute & 0xf0) >> 4) * 10) + (Minute & 0x0f)) * 60)
- + ((((Sec & 0xf0) >> 4) * 10) + (Sec & 0x0f));
+ //int Replays = Summary->NumReplays;
+ int ReplayOffset = 11;
+ Summary_t *S;
+ S = (Summary_t *) malloc (sizeof (Summary_t));
+ Summaries[nSummaries] = S;
+ S->NumReplays = Summary->NumReplays;
+ S->EventId = HILO32 (Summary->ProgramId);
+ S->Text = Text;
+ int i = 0;
+ do {
+ S->Replays[i].MjdTime = 0; //only used for SKY
+ //if (Summary->NumReplays == 0) {
+ //S->ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
+ //S->StartTime = 0;
+ //}
+ //else {
+ S->Replays[i].ChannelId = Data[ReplayOffset++] - 1;
+ unsigned int Date_hi = Data[ReplayOffset++];
+ unsigned int Date_lo = Data[ReplayOffset++];
+ unsigned short int Hour = Data[ReplayOffset++];
+ unsigned short int Minute = Data[ReplayOffset++];
+ unsigned short int Sec = Data[ReplayOffset++];
+ ReplayOffset++; //makes total of 7 bytes
+
+ LogI(4, prep("EvId:%08x ChanId:%x, ChanName %s, Time: %02d:%02d:%02d."),
+ S->EventId, S->Replays[i].ChannelId,
+ sChannels[ChannelSeq[S->Replays[i].ChannelId]].Name, Hour, Minute, Sec);
+
+ S->Replays[i].StartTime = MjdToEpochTime (Date) + (((((Hour & 0xf0) >> 4) * 10) + (Hour & 0x0f)) * 3600)
+ + (((((Minute & 0xf0) >> 4) * 10) + (Minute & 0x0f)) * 60)
+ + ((((Sec & 0xf0) >> 4) * 10) + (Sec & 0x0f));
// summary -> time[i] = ProviderLocalTime2UTC (summary -> time[i]);
- S->Replays[i].StartTime = LocalTime2UTC (S->Replays[i].StartTime);
- //}
- i++;
- } while (i < Summary->NumReplays);
- //} while (Replays-- >= 0);
- if (VERBOSE >= 3)
- isyslog ("EEPG: Eventid:%08x Channelid:%x, Summnr %d:%.30s.", S->EventId, S->Replays[0].ChannelId, //TODO log channel id above
- nSummaries, S->Text);
- nSummaries++;
- }
- else {
- esyslog ("EEPG: Error, summaries found more than %i", MAX_TITLES);
- return 0;
- }
- } //0xff
- else {
- esyslog ("EEPG: Warning, Summary bytes not as expected.");
- return 1; //it is not a success, but error is not fatal
- }
- } //numreplays length
+ S->Replays[i].StartTime = LocalTime2UTC (S->Replays[i].StartTime);
+ //}
+ i++;
+ } while (i < Summary->NumReplays);
+ //} while (Replays-- >= 0);
+ LogI(3, prep("EvId:%08x ChanId:%x, Replays:%d, Summnr %d:%.35s."), S->EventId,
+ S->Replays[0].ChannelId, S->NumReplays, nSummaries, S->Text);
+ nSummaries++;
+ } else {
+ LogE(0, prep("Error, %i summaries found more than %i"), nSummaries, MAX_TITLES);
+ return 0;
+ }
+ } //0xff
+ else {
+ LogE(0, prep("Warning, Summary bytes not as expected."));
+ return 1; //it is not a success, but error is not fatal
+ }
+ } //numreplays length
else {
- esyslog ("EEPG: Warning, number of replays is not conforming to length.");
- return 1; //nonfatal error
+ LogE(0, prep("Warning, number of replays is not conforming to length."));
+ return 1; //nonfatal error
}
- } //numreplays <10
+ } //numreplays <10
else {
- esyslog ("EEPG: Warning, number of replays %d > 10, cannot process.", Summary->NumReplays);
- return 1; //nonfatal error
+ LogE(0, prep("Warning, number of replays %d > 10, cannot process."),
+ Summary->NumReplays);
+ return 1; //nonfatal error
}
- } //length >11
+ } //length >11
else {
- esyslog ("EEPG: Summary length too small:%s", cs_hexdump (0, Data, Length));
- return 1; //nonfatal error
+ LogE(0, prep("Summary length too small:%s"), cs_hexdump (0, Data, Length));
+ return 1; //nonfatal error
}
- return 1; //success
+ return 1; //success
}
-int cFilterEEPG::GetSummariesMHW2 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get MHW2 Summaries
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetSummariesMHW2 (const u_char * Data, int Length)
{
if (Length > (Data[14] + 17)) {
- if (memcmp (InitialSummary, Data, 16) == 0) //data is equal to initial buffer
+ if (memcmp (InitialSummary, Data, 16) == 0) //data is equal to initial buffer
return 2;
else {
if (nSummaries == 0)
- memcpy (InitialSummary, Data, 16); //copy this data in initial buffer
+ memcpy (InitialSummary, Data, 16); //copy this data in initial buffer
if (nSummaries < MAX_TITLES) {
- int lenText = Data[14];
- int SummaryLength = lenText;
- int Pos = 15;
- int Loop = Data[Pos + SummaryLength] & 0x0f;
- Summary_t *S;
- S = (Summary_t *) malloc (sizeof (Summary_t));
- Summaries[nSummaries] = S;
-
- S->Replays[0].ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
- S->Replays[0].StartTime = 0; //not used
- S->Replays[0].MjdTime = 0; //not used
- S->NumReplays = 0; //not used
- S->EventId = (Data[3] << 8) | Data[4];
- unsigned char tmp[4096]; //TODO do this smarter
- memcpy (tmp, &Data[Pos], lenText);
- tmp[SummaryLength] = '\n';
- SummaryLength += 1;
- Pos += (lenText + 1);
- if (Loop > 0) {
- while (Loop > 0) {
- lenText = Data[Pos];
- Pos += 1;
- if ((Pos + lenText) < Length) {
- memcpy (&tmp[SummaryLength], &Data[Pos], lenText);
- SummaryLength += lenText;
- if (Loop > 1) {
- tmp[SummaryLength] = '\n';
- SummaryLength += 1;
- }
- }
- else
- break;
- Pos += lenText;
- Loop--;
- }
- }
- S->Text = (unsigned char *) malloc (SummaryLength + 2);
- S->Text[SummaryLength] = NULL; //end string with NULL character
- if (S->Text == NULL) {
- esyslog ("EEPG: Summaries memory allocation error.");
- return 0; //fatal error
- }
- //memcpy (S->Text, tmp, SummaryLength);
- decodeText2(tmp,SummaryLength,(char*)S->Text,SummaryLength + 1);
- CleanString (S->Text);
- if (VERBOSE >= 3)
- isyslog ("EEPG: EventId %08x Summnr %d:%.30s.", S->EventId, nSummaries, S->Text);
- nSummaries++;
+ int lenText = Data[14];
+ int SummaryLength = lenText;
+ int Pos = 15;
+ int Loop = Data[Pos + SummaryLength] & 0x0f;
+ Summary_t *S;
+ S = (Summary_t *) malloc (sizeof (Summary_t));
+ Summaries[nSummaries] = S;
+
+ S->Replays[0].ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
+ S->Replays[0].StartTime = 0; //not used
+ S->Replays[0].MjdTime = 0; //not used
+ S->NumReplays = 0; //not used
+ S->EventId = (Data[3] << 8) | Data[4];
+ unsigned char tmp[4096]; //TODO do this smarter
+ memcpy (tmp, &Data[Pos], lenText);
+ tmp[SummaryLength] = '\n';
+ SummaryLength += 1;
+ Pos += (lenText + 1);
+ if (Loop > 0) {
+ while (Loop > 0) {
+ lenText = Data[Pos];
+ Pos += 1;
+ if ((Pos + lenText) < Length) {
+ memcpy (&tmp[SummaryLength], &Data[Pos], lenText);
+ SummaryLength += lenText;
+ if (Loop > 1) {
+ tmp[SummaryLength] = '\n';
+ SummaryLength += 1;
+ }
+ } else
+ break;
+ Pos += lenText;
+ Loop--;
+ }
+ }
+ S->Text = (unsigned char *) malloc (SummaryLength + 2);
+ S->Text[SummaryLength] = '\0'; //end string with NULL character
+ if (S->Text == NULL) {
+ LogE(0, prep("Summaries memory allocation error."));
+ return 0; //fatal error
+ }
+ //memcpy (S->Text, tmp, SummaryLength);
+ decodeText2(tmp,SummaryLength,(char*)S->Text,SummaryLength + 1);
+ CleanString (S->Text);
+ LogI(3, prep("EventId %08x Summnr %d:%.30s."), S->EventId, nSummaries, S->Text);
+ nSummaries++;
+ } else {
+ LogE(0, prep("Error, %i summaries found more than %i"), nSummaries, MAX_TITLES);
+ return 0; //fatal error
}
- else {
- esyslog ("EEPG: Error, summaries found more than %i", MAX_TITLES);
- return 0; //fatal error
- }
- } //else
- } //if length
- return 1; //succes or nonfatal error
+ } //else
+ } //if length
+ return 1; //succes or nonfatal error
}
-int cFilterEEPG::GetChannelsSKYBOX (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get SKYBOX Channels
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetChannelsSKYBOX (const u_char * Data, int Length)
{
- if (memcmp (InitialChannel, Data, 8) == 0) { //data is the same as initial title
+ if (memcmp (InitialChannel, Data, 8) == 0) { //data is the same as initial title
LoadEquivalentChannels ();
return 2;
- }
- else {
+ } else {
if (nChannels == 0)
- memcpy (InitialChannel, Data, 8); //copy data into initial title
- if (VERBOSE >= 1 && nChannels == 0) {
- isyslog ("| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
- isyslog ("|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
- "-----------------------------", "--------------------");
+ memcpy (InitialChannel, Data, 8); //copy data into initial title
+ if (nChannels == 0) {
+ LogI(1, "| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+ LogI(1, "|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+ "-----------------------------", "--------------------");
}
// unsigned short int BouquetId = (Data[3] << 8) | Data[4];
int BouquetDescriptorsLength = ((Data[8] & 0x0f) << 8) | Data[9];
@@ -2319,81 +2428,75 @@ int cFilterEEPG::GetChannelsSKYBOX (const u_char * Data, int Length) //return co
p1 += (TransportDescriptorsLength + 6);
TransportStreamLoopLength -= (TransportDescriptorsLength + 6);
while (TransportDescriptorsLength > 0) {
- unsigned char DescriptorTag = Data[p2];
- int DescriptorLength = Data[p2 + 1];
- int p3 = (p2 + 2);
- p2 += (DescriptorLength + 2);
- TransportDescriptorsLength -= (DescriptorLength + 2);
- switch (DescriptorTag) { //TODO switch with only 1 case??? replace this by template
- case 0xb1:
- p3 += 2;
- DescriptorLength -= 2;
- while (DescriptorLength > 0) {
- // 0x01 = Video Channel
- // 0x02 = Audio Channel
- // 0x05 = Other Channel
- //if( Data[p3+2] == 0x01 || Data[p3+2] == 0x02 || Data[p3+2] == 0x05 )
- //{
- unsigned short int Sid = (Data[p3] << 8) | Data[p3 + 1];
- unsigned short int ChannelId = (Data[p3 + 3] << 8) | Data[p3 + 4];
- unsigned short int SkyNumber = (Data[p3 + 5] << 8) | Data[p3 + 6];
- if (SkyNumber > 100 && SkyNumber < 1000) {
- if (ChannelId > 0) {
- sChannel *C;
- if (ChannelSeq.count (ChannelId) == 0) //not found
- {
- C = &sChannels[nChannels];
- C->ChannelId = ChannelId;
- 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->Nid[0] = Nid;
- C->Tid[0] = Tid;
- C->Sid[0] = Sid;
- C->SkyNumber = SkyNumber;
- tChannelID channelID = tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]);
- cChannel *VC = Channels.GetByChannelID (channelID, true);
- bool IsFound = (VC);
- if (IsFound)
- strncpy ((char *) C->Name, VC->Name (), 64);
- else
- C->Name[0] = NULL; //empty string
-
- if (VERBOSE >= 1) {
- char *ChID;
- asprintf (&ChID, " %s-%i-%i-%i-0", *cSource::ToString (C->Src[0]), C->Nid[0], C->Tid[0], C->Sid[0]);
- char *IsF;
- if (IsFound)
- asprintf (&IsF, " %-3.3s |", "YES");
- else
- asprintf (&IsF, " %-3.3s |", "NO");
- isyslog ("|% 5d | %-26.26s | %-22.22s |%s % 6d |\n", C->ChannelId, ChID, C->Name, IsF,
- C->SkyNumber);
- free (ChID);
- free (IsF);
- }
- ChannelSeq[C->ChannelId] = nChannels; //fill lookup table to go from channel-id to sequence nr in table
- nChannels++;
- if (nChannels >= MAX_CHANNELS) {
- esyslog ("EEPG: Error, channels found more than %i", MAX_CHANNELS);
- return 0;
- }
- }
- }
- }
- p3 += 9;
- DescriptorLength -= 9;
- }
- break;
- default:
- break;
- } //switch descriptortag
+ unsigned char DescriptorTag = Data[p2];
+ int DescriptorLength = Data[p2 + 1];
+ int p3 = (p2 + 2);
+ p2 += (DescriptorLength + 2);
+ TransportDescriptorsLength -= (DescriptorLength + 2);
+ switch (DescriptorTag) { //TODO switch with only 1 case??? replace this by template
+ case 0xb1:
+ p3 += 2;
+ DescriptorLength -= 2;
+ while (DescriptorLength > 0) {
+ // 0x01 = Video Channel
+ // 0x02 = Audio Channel
+ // 0x05 = Other Channel
+ //if( Data[p3+2] == 0x01 || Data[p3+2] == 0x02 || Data[p3+2] == 0x05 )
+ //{
+ unsigned short int Sid = (Data[p3] << 8) | Data[p3 + 1];
+ unsigned short int ChannelId = (Data[p3 + 3] << 8) | Data[p3 + 4];
+ unsigned short int SkyNumber = (Data[p3 + 5] << 8) | Data[p3 + 6];
+ if (SkyNumber > 100 && SkyNumber < 1000) {
+ if (ChannelId > 0) {
+ sChannel *C;
+ if (ChannelSeq.count (ChannelId) == 0) { //not found
+ C = &sChannels[nChannels];
+ C->ChannelId = ChannelId;
+ 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->Nid[0] = Nid;
+ C->Tid[0] = Tid;
+ C->Sid[0] = Sid;
+ C->SkyNumber = SkyNumber;
+ tChannelID channelID = tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]);
+ cChannel *VC = Channels.GetByChannelID (channelID, true);
+ bool IsFound = (VC);
+ if (IsFound)
+ strncpy ((char *) C->Name, VC->Name (), 64);
+ else
+ 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);
+
+ ChannelSeq[C->ChannelId] = nChannels; //fill lookup table to go from channel-id to sequence nr in table
+ nChannels++;
+ if (nChannels >= MAX_CHANNELS) {
+ LogE(0, prep("Error, %i channels found more than %i"), nChannels, MAX_CHANNELS);
+ return 0;
+ }
+ }
+ }
+ }
+ p3 += 9;
+ DescriptorLength -= 9;
+ }
+ break;
+ default:
+ break;
+ } //switch descriptortag
}
- } //while
+ } //while
return 1;
- } //else part of memcmp
+ } //else part of memcmp
}
-int cFilterEEPG::GetTitlesSKYBOX (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get SKYBOX Titles
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetTitlesSKYBOX (const u_char * Data, int Length)
{
int p;
unsigned short int ChannelId;
@@ -2402,99 +2505,102 @@ int cFilterEEPG::GetTitlesSKYBOX (const u_char * Data, int Length) //return code
int Len2;
if (Length < 20)
- return 1; //nonfatal error
- if (memcmp (InitialTitle, Data, 20) == 0) //data is the same as initial title
+ return 1; //nonfatal error
+ if (memcmp (InitialTitle, Data, 20) == 0) //data is the same as initial title
return 2;
else {
if (nTitles == 0)
- memcpy (InitialTitle, Data, 20); //copy data into initial title
+ memcpy (InitialTitle, Data, 20); //copy data into initial title
ChannelId = (Data[3] << 8) | Data[4];
MjdTime = ((Data[8] << 8) | Data[9]);
if (ChannelId > 0) {
if (MjdTime > 0) {
- p = 10;
- do {
- Title_t *T;
- T = (Title_t *) malloc (sizeof (Title_t));
- Titles[nTitles] = T;
- T->ChannelId = ChannelId;
- T->MjdTime = MjdTime; //only date, no time. Is used to match titles and summaries, SKYBOX only
- T->EventId = (Data[p] << 8) | Data[p + 1];
- Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
- if (Data[p + 4] != 0xb5) {
- if (DEBUG) {
- esyslog ("EEPG: Data error signature for title");
- }
- break;
- }
- if (Len1 > Length) {
- if (DEBUG) {
- esyslog ("EEPG: Data error length for title");
- }
- break;
- }
- p += 4;
- Len2 = Data[p + 1] - 7;
- T->StartTime = ((MjdTime - 40587) * 86400) + ((Data[p + 2] << 9) | (Data[p + 3] << 1));
- T->Duration = ((Data[p + 4] << 9) | (Data[p + 5] << 1));
- T->ThemeId = Data[p + 6];
- int quality = Data[p + 7];
- switch (Data[p + 8] & 0x0F){
- case 0x01:
- T->Rating = 0x00; //"U"
- break;
- case 0x02:
- T->Rating = 0x08; //"PG"
- break;
- case 0x03:
- T->Rating = 0x0C; //"12"
- break;
- case 0x04:
- T->Rating = 0x0F; //"15"
- break;
- case 0x05:
- T->Rating = 0x12; //"18"
- break;
- default:
- T->Rating = 0x00; //"-"
- break;
- }
- T->Unknown1 = Data[p + 4 - 13]; //FIXME
- T->Unknown2 = Data[p + 4 - 12]; //FIXME
- T->Unknown3 = Data[p + 4 - 11]; //FIXME
- unsigned char tmp[4096]; //TODO smarter
- Len2 = DecodeHuffmanCode (&Data[p + 9], Len2, tmp);
- if (Len2 == 0) {
- esyslog ("EEPG: Warning, could not huffman-decode title-text, skipping title.");
- return 1; //non-fatal error
- }
- T->Text = (unsigned char *) malloc (Len2 + 1);
- if (T->Text == NULL) {
- esyslog ("EEPG: Titles memory allocation error.");
- return 0;
- }
- T->Text[Len2] = NULL; //end string with NULL character
- memcpy (T->Text, tmp, Len2);
- CleanString (T->Text);
- T->SummaryAvailable = 1; //TODO I assume this is true?
-
- if (VERBOSE >= 3)
- isyslog ("EEPG: EventId %08x Titlenr %d,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s.", T->EventId,
- nTitles, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
- p += Len1;
- nTitles++;
- if (nTitles >= MAX_TITLES) {
- esyslog ("EEPG: Error, titles found more than %i", MAX_TITLES);
- return 0; //fatal error
- }
- } while (p < Length);
+ p = 10;
+ do {
+ Title_t *T;
+ T = (Title_t *) malloc (sizeof (Title_t));
+ Titles[nTitles] = T;
+ T->ChannelId = ChannelId;
+ T->MjdTime = MjdTime; //only date, no time. Is used to match titles and summaries, SKYBOX only
+ T->EventId = (Data[p] << 8) | Data[p + 1];
+ Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
+ if (Data[p + 4] != 0xb5) {
+ LogD(5, prep("Data error signature for title - Data[p + 4] != 0xb5"));
+ break;
+ }
+ if (Len1 > Length) {
+ LogD(5, prep("Data error signature for title - Len1 > Length"));
+ break;
+ }
+ p += 4;
+ Len2 = Data[p + 1] - 7;
+ T->StartTime = ((MjdTime - 40587) * 86400) + ((Data[p + 2] << 9) | (Data[p + 3] << 1));
+ T->Duration = ((Data[p + 4] << 9) | (Data[p + 5] << 1));
+ T->ThemeId = Data[p + 6];
+ T->TableId = DEFAULT_TABLE_ID; //TODO locate the actual table id
+ //TODO Data[p + 7] is Quality value add it to description
+ //int quality = Data[p + 7];
+ switch (Data[p + 8] & 0x0F) {
+ case 0x01:
+ T->Rating = 0x00; //"U"
+ break;
+ case 0x02:
+ T->Rating = 0x08; //"PG"
+ break;
+ case 0x03:
+ T->Rating = 0x0C; //"12"
+ break;
+ case 0x04:
+ T->Rating = 0x0F; //"15"
+ break;
+ case 0x05:
+ T->Rating = 0x12; //"18"
+ break;
+ default:
+ T->Rating = 0x00; //"-"
+ break;
+ }
+ T->Unknown1 = Data[p + 4 - 13]; //FIXME
+ T->Unknown2 = Data[p + 4 - 12]; //FIXME
+ T->Unknown3 = Data[p + 4 - 11]; //FIXME
+ unsigned char tmp[4096]; //TODO smarter
+ Len2 = sky_huffman_decode (&Data[p + 9], Len2, tmp);
+ if (Len2 == 0) {
+ LogE(0, prep("Warning, could not huffman-decode title-text, skipping title."));
+ return 1; //non-fatal error
+ }
+ T->Text = (unsigned char *) malloc (Len2 + 1);
+ if (T->Text == NULL) {
+ LogE(0, prep("Titles memory allocation error."));
+ return 0;
+ }
+ 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?
+
+ LogI(3, prep("EventId %08x Titlenr %d,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s."),
+ T->EventId, nTitles, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
+
+ p += Len1;
+ nTitles++;
+ if (nTitles >= MAX_TITLES) {
+ LogE(0, prep("Error, %i titles found more than %i"), nTitles, MAX_TITLES);
+ return 0; //fatal error
+ }
+ } while (p < Length);
}
}
}
- return 1; //success
+ return 1; //success
}
-int cFilterEEPG::GetSummariesSKYBOX (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+/**
+ * \brief Get SKYBOX Summaries
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetSummariesSKYBOX (const u_char * Data, int Length)
{
int p;
unsigned short int ChannelId;
@@ -2503,65 +2609,60 @@ int cFilterEEPG::GetSummariesSKYBOX (const u_char * Data, int Length) //return c
int Len2;
if (Length < 20) {
- return 1; //non fatal error I assume
+ return 1; //non fatal error I assume
}
- if (memcmp (InitialSummary, Data, 20) == 0) //data is equal to initial buffer
+ if (memcmp (InitialSummary, Data, 20) == 0) //data is equal to initial buffer
return 2;
// else if (nSummaries < MAX_SUMMARIES) {
else {
if (nSummaries == 0)
- memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
+ memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
ChannelId = (Data[3] << 8) | Data[4];
MjdTime = ((Data[8] << 8) | Data[9]);
if (ChannelId > 0) {
if (MjdTime > 0) {
- p = 10;
- do {
- Summary_t *S;
- S = (Summary_t *) malloc (sizeof (Summary_t));
- Summaries[nSummaries] = S;
- S->Replays[0].ChannelId = ChannelId;
- S->Replays[0].MjdTime = MjdTime;
- S->NumReplays = 0; //not used
- S->EventId = (Data[p] << 8) | Data[p + 1];
- Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
- if (Data[p + 4] != 0xb9) {
- if (DEBUG) {
- esyslog ("EEPG: Data error signature for summary");
- }
- break;
- }
- if (Len1 > Length) {
- if (DEBUG) {
- esyslog ("EEPG: Data error length for summary");
- }
- break;
- }
- p += 4;
- Len2 = Data[p + 1];
- unsigned char tmp[4096]; //TODO can this be done better?
- Len2 = DecodeHuffmanCode (&Data[p + 2], Len2, tmp);
- if (Len2 == 0) {
- esyslog ("EEPG: Warning, could not huffman-decode text, skipping summary.");
- return 1; //non-fatal error
- }
- S->Text = (unsigned char *) malloc (Len2 + 1);
- if (S->Text == NULL) {
- esyslog ("EEPG: Summaries memory allocation error.");
- return 0;
- }
- memcpy (S->Text, tmp, Len2);
- S->Text[Len2] = NULL; //end string with NULL character
- CleanString (S->Text);
- if (VERBOSE >= 3)
- isyslog ("EEPG: EventId %08x Summnr %d:%.30s.", S->EventId, nSummaries, S->Text);
- p += Len1;
- nSummaries++;
- if (nSummaries >= MAX_TITLES) {
- esyslog ("EEPG: Error, summaries found more than %i", MAX_TITLES);
- return 0;
- }
- } while (p < Length);
+ p = 10;
+ do {
+ Summary_t *S;
+ S = (Summary_t *) malloc (sizeof (Summary_t));
+ Summaries[nSummaries] = S;
+ S->Replays[0].ChannelId = ChannelId;
+ S->Replays[0].MjdTime = MjdTime;
+ S->NumReplays = 0; //not used
+ S->EventId = (Data[p] << 8) | Data[p + 1];
+ Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
+ if (Data[p + 4] != 0xb9) {
+ LogD(5, prep("Data error signature for title - Data[p + 4] != 0xb5"));
+ break;
+ }
+ if (Len1 > Length) {
+ LogD(5, prep("Data error signature for title - Len1 > Length"));
+ break;
+ }
+ p += 4;
+ Len2 = Data[p + 1];
+ unsigned char tmp[4096]; //TODO can this be done better?
+ Len2 = sky_huffman_decode (&Data[p + 2], Len2, tmp);
+ if (Len2 == 0) {
+ LogE(0, prep("Warning, could not huffman-decode text, skipping summary."));
+ return 1; //non-fatal error
+ }
+ S->Text = (unsigned char *) malloc (Len2 + 1);
+ if (S->Text == NULL) {
+ LogE(0, prep("Summaries memory allocation error."));
+ return 0;
+ }
+ memcpy (S->Text, tmp, Len2);
+ 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;
+ nSummaries++;
+ if (nSummaries >= MAX_TITLES) {
+ LogI(0, prep("Error, %i summaries found more than %i"), nSummaries, MAX_TITLES);
+ return 0;
+ }
+ } while (p < Length);
}
}
}
@@ -2571,17 +2672,16 @@ int cFilterEEPG::GetSummariesSKYBOX (const u_char * Data, int Length) //return c
void cFilterEEPG::FreeSummaries (void)
{
if (Format == MHW1 || Format == MHW2 || Format == SKY_IT || Format == SKY_UK) {
- Summary_t *S; //TODO do I need this?
- Summary_t *S2; //TODO do I need this?
+ Summary_t *S; //TODO do I need this?
+ Summary_t *S2; //TODO do I need this?
for (int i = 0; i < nSummaries; i++) {
S = Summaries[i];
if (i < nSummaries - 1) {
- S2 = Summaries[i + 1]; //look at next summary
- if (S->Text != S2->Text && S->Text != 0x00) //this is the last summary that points to this textblock; needed in case NumReplays > 1, multiple pointers to same textblock
- free (S->Text);
- }
- else if (S->Text != 0x00)
- free (S->Text);
+ S2 = Summaries[i + 1]; //look at next summary
+ if (S->Text != S2->Text && S->Text != 0x00) //this is the last summary that points to this textblock; needed in case NumReplays > 1, multiple pointers to same textblock
+ free (S->Text);
+ } else if (S->Text != 0x00)
+ free (S->Text);
free (S);
}
}
@@ -2603,10 +2703,9 @@ void cFilterEEPG::FreeTitles (void)
void cFilterEEPG::LoadIntoSchedule (void)
{
- int i, j, k;
+ int i, j;
i = 0;
j = 0;
- k = 0;
bool foundtitle;
foundtitle = false;
Title_t *T;
@@ -2628,111 +2727,114 @@ void cFilterEEPG::LoadIntoSchedule (void)
S = Summaries[j];
foundtitle = false;
- while ((i < nTitles) && (!foundtitle)) { //find next title that has summary
- T = Titles[i];
- if (T->SummaryAvailable)
- foundtitle = true;
- else {
- NoSummary++;
- i++;
- }
+ while ((i < nTitles) && (!foundtitle)) { //find next title that has summary
+ T = Titles[i];
+ if (T->SummaryAvailable)
+ foundtitle = true;
+ else {
+ NoSummary++;
+ i++;
+ }
}
//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...
- isyslog("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
- remembersummary = -1; //reset summary searcher
- //int Replays = S->NumReplays;
-
- int index = 0;
- do {
- unsigned short int ChannelId;
- time_t StartTime;
- if (S->NumReplays == 0) {
- ChannelId = T->ChannelId;
- StartTime = T->StartTime;
- }
- else {
- ChannelId = S->Replays[index].ChannelId;
- StartTime = S->Replays[index].StartTime;
- }
-
- //channelids are sequentially numbered and sent in MHW1 and MHW2, but not in SKY, so we need to lookup the table index
- sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
- cSchedule *p[MAX_EQUIVALENCES];
- PrepareToWriteToSchedule (C, s, p);
-
+ if (!foundtitle) //no more titles with summaries
+ 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
+ remembersummary = -1; //reset summary searcher
+ //int Replays = S->NumReplays;
+
+ int index = 0;
+ do {
+ unsigned short int ChannelId;
+ time_t StartTime;
+ if (S->NumReplays == 0) {
+ ChannelId = T->ChannelId;
+ StartTime = T->StartTime;
+ } else {
+ ChannelId = S->Replays[index].ChannelId;
+ StartTime = S->Replays[index].StartTime;
+ }
+
+ //channelids are sequentially numbered and sent in MHW1 and MHW2, but not in SKY, so we need to lookup the table index
+ sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
+ cSchedule *p[MAX_EQUIVALENCES];
+ PrepareToWriteToSchedule (C, s, p);
+
char rating = 0x00;
- if ((Format == SKY_IT || Format == SKY_UK) && T->Rating){ //TODO only works on OTV for now
- rating = T->Rating;
- }
-
- WriteToSchedule (p, C->NumberOfEquivalences, T->EventId, StartTime, T->Duration / 60, (char *) T->Text,
- (char *) S->Text, T->ThemeId, DEFAULT_TABLE_ID, 0, rating);
-
- FinishWriteToSchedule (C, s, p);
- //Replays--;
- //if ((S->NumReplays != 0) && (Replays > 0)) { //when replays are used, all summaries of the replays are stored consecutively; currently only CSAT
- //j++; //move to next summary
- //if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
- //j = 0;
- //S = Summaries[j]; //next summary within replay range
- //}
- index++;
- } //while
- while (index < S->NumReplays);
+ if ((Format == SKY_IT || Format == SKY_UK) && T->Rating) { //TODO only works on OTV for now
+ rating = T->Rating;
+ }
+ unsigned short int TableId = DEFAULT_TABLE_ID;
+ if (T->TableId) {
+ TableId = T->TableId;
+ }
+
+ WriteToSchedule (p, C->NumberOfEquivalences, T->EventId, StartTime, T->Duration / 60, (char *) T->Text,
+ (char *) S->Text, T->ThemeId, TableId, 0, rating);
+
+ FinishWriteToSchedule (C, s, p);
+ //Replays--;
+ //if ((S->NumReplays != 0) && (Replays > 0)) { //when replays are used, all summaries of the replays are stored consecutively; currently only CSAT
+ //j++; //move to next summary
+ //if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
+ //j = 0;
+ //S = Summaries[j]; //next summary within replay range
+ //}
+ index++;
+ } //while
+ while (index < S->NumReplays);
//TODO: why load events that have already past, and then run Cleanup
//end of putting title and summary in schedule
- i++; //move to next title
- } //if T->EventId == S->EventId
+ i++; //move to next title
+ } //if T->EventId == S->EventId
else {
// esyslog("EEPG ERROR: ProgramIds not matching, title:%d,summary%d, T->EventId:%u, S->Eventid:%u.",i,j,T->EventId,S->EventId);
- NotMatching++;
- if (remembersummary == -1) { //I am not in search loop yet
- remembersummary = j;
- if (remembersummary == 0)
- remembersummary = nSummaries; //or next test will never be succesfull for remembersummary = 0
- LostSync++;
+ NotMatching++;
+ if (remembersummary == -1) { //I am not in search loop yet
+ remembersummary = j;
+ if (remembersummary == 0)
+ remembersummary = nSummaries; //or next test will never be succesfull for remembersummary = 0
+ LostSync++;
// esyslog("EEPG Error: lost sync at title %d, summary %d.",i,j);
- }
- else if (j == (remembersummary - 1)) { //the last summary to be checked has failed also
- //esyslog ("EEPG Error: could not find summary for summary-available Title %d.", i);
- esyslog
- ("EEPG: Error, summary not found for EventId %08x Titlenr %d:SummAv:%x,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s.",
- T->EventId, i, T->SummaryAvailable, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
-
- /* write Title info to schedule */
- sChannel *C = &sChannels[ChannelSeq[T->ChannelId]]; //find channel
- cSchedule *p[MAX_EQUIVALENCES];
- PrepareToWriteToSchedule (C, s, p);
+ } else if (j == (remembersummary - 1)) { //the last summary to be checked has failed also
+ //esyslog ("EEPG Error: could not find summary for summary-available Title %d.", i);
+ esyslog
+ ("EEPG: Error, summary not found for EventId %08x Titlenr %d:SummAv:%x,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s.",
+ T->EventId, i, T->SummaryAvailable, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
+
+ /* write Title info to schedule */
+ sChannel *C = &sChannels[ChannelSeq[T->ChannelId]]; //find channel
+ cSchedule *p[MAX_EQUIVALENCES];
+ PrepareToWriteToSchedule (C, s, p);
char rating = 0x00;
- if ((Format == SKY_IT || Format == SKY_UK) && T->Rating){ //TODO only works on OTV for now
- rating = T->Rating;
- }
- WriteToSchedule (p, C->NumberOfEquivalences, T->EventId, T->StartTime, T->Duration / 60, (char *) T->Text,
- NULL, T->ThemeId, DEFAULT_TABLE_ID, 0, rating);
- FinishWriteToSchedule (C, s, p);
+ if ((Format == SKY_IT || Format == SKY_UK) && T->Rating) { //TODO only works on OTV for now
+ rating = T->Rating;
+ }
+ WriteToSchedule (p, C->NumberOfEquivalences, T->EventId, T->StartTime, T->Duration / 60, (char *) T->Text,
+ NULL, T->ThemeId, DEFAULT_TABLE_ID, 0, rating);
+ FinishWriteToSchedule (C, s, p);
- SummariesNotFound++;
- i++; //move to next title, for this one no summary can be found
- }
+ SummariesNotFound++;
+ i++; //move to next title, for this one no summary can be found
+ }
// esyslog("Trying again for this title %d, remember summary %d, but advancing one Summary to %d.",i,remembersummary,j);
}
- j++; //move to next summary
- if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
- j = 0;
- } //while title
- } // if s
+ j++; //move to next summary
+ if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
+ j = 0;
+ } //while title
+ } // if s
else
esyslog ("EEPG Error: could not lock schedules.");
- cSchedules::Cleanup (true); //deletes all past events
+ cSchedules::Cleanup (true); //deletes all past events
isyslog ("EEPG: found %i equivalents channels", nEquivChannels);
isyslog ("EEPG: found %i themes", nThemes);
@@ -2742,14 +2844,13 @@ void cFilterEEPG::LoadIntoSchedule (void)
isyslog ("EEPG: found %i summaries", nSummaries);
if (SummariesNotFound != 0)
esyslog ("EEPG: %i summaries not found", SummariesNotFound);
- else if (VERBOSE >= 1)
- isyslog ("EEPG: %i summaries not found", SummariesNotFound);
if (NotMatching > nSummaries)
- isyslog ("EEPG Warning: lost sync %i times, summary did not match %i times.", LostSync, NotMatching);
+ LogI (0, prep("Warning: lost sync %i times, summary did not match %i times."),
+ LostSync, NotMatching);
- FreeSummaries (); //do NOT free channels, themes and bouquets here because they will be reused in SKY!
+ FreeSummaries (); //do NOT free channels, themes and bouquets here because they will be reused in SKY!
FreeTitles ();
- if (!((Format == SKY_IT) || (Format == SKY_UK))) { //everything but SKY; SKY is the only protocol where LoadIntoSchedule is called repeatedly
+ if (!((Format == SKY_IT) || (Format == SKY_UK))) { //everything but SKY; SKY is the only protocol where LoadIntoSchedule is called repeatedly
ChannelSeq.clear ();
}
}
@@ -2758,7 +2859,7 @@ void cFilterEEPG::AddFilter (u_short Pid, u_char Tid)
{
if (!Matches (Pid, Tid)) {
Add (Pid, Tid);
- esyslog ("Filter Pid:%x,Tid:%x added.", Pid, Tid);
+ esyslog (prep("Filter Pid:%x,Tid:%x added."), Pid, Tid);
}
}
@@ -2766,498 +2867,625 @@ void cFilterEEPG::AddFilter (u_short Pid, u_char Tid, unsigned char Mask)
{
if (!Matches (Pid, Tid)) {
Add (Pid, Tid, Mask);
- esyslog ("Filter Pid:%x,Tid:%x,Mask:%x added.", Pid, Tid, Mask);
+ esyslog (prep("Filter Pid:%x,Tid:%x,Mask:%x added."), Pid, Tid, 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);
+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::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool OnlyRunningStatus)
+ : SI::EIT (Data, false)
+{
+ //LogD(2, prep("cEIT2::cEIT2"));
+ if (Tid > 0 && Format == DISH_BEV) Tid--;
-#ifdef USE_NOEPG
- bool cEIT2::allowedEPG (tChannelID kanalID)
- {
- bool rc;
+ if (!CheckCRCAndParse ()) {
+ LogD(2, prep("!CheckCRCAndParse ()"));
+ return;
+ }
- 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;
- }
+ bool searchOtherSatPositions = Format == DISH_BEV;
- return rc;
+ tChannelID channelID (Source, getOriginalNetworkId (), getTransportStreamId (), getServiceId ());
+ cChannel *channel = GetChannelByID (channelID, searchOtherSatPositions);
+ if (!channel) {
+ LogD(3, prep("!channel channelID: %s"), *channelID.ToString());
+ return; // only collect data for known channels
}
-#endif /* NOEPG */
-
- cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool OnlyRunningStatus)
-: SI::EIT (Data, false) {
- if (!CheckCRCAndParse ())
- return;
- tChannelID channelID (Source, getOriginalNetworkId (), getTransportStreamId (), getServiceId ());
- cChannel *channel = Channels.GetByChannelID (channelID, true);
- if (!channel)
- 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
- tChannelID kanalID;
- kanalID = channel->GetChannelID ();
- if (!allowedEPG (kanalID))
- return;
+ // only use epg from channels not blocked by noEPG-patch
+ tChannelID kanalID;
+ kanalID = channel->GetChannelID ();
+ if (!allowedEPG (kanalID))
+ return;
#endif /* NOEPG */
- cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channel, true);
-
- bool Empty = true;
- bool Modified = false;
- bool HasExternalData = false;
- time_t SegmentStart = 0;
- time_t SegmentEnd = 0;
-
- SI::EIT::Event SiEitEvent;
- for (SI::Loop::Iterator it; eventLoop.getNext (SiEitEvent, it);) {
- bool ExternalData = false;
- // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number.
- if (SiEitEvent.getStartTime () == 0 || (SiEitEvent.getStartTime () > 0 && SiEitEvent.getDuration () == 0))
- continue;
- Empty = false;
- if (!SegmentStart)
- SegmentStart = SiEitEvent.getStartTime ();
- SegmentEnd = SiEitEvent.getStartTime () + SiEitEvent.getDuration ();
- cEvent *newEvent = NULL;
- cEvent *rEvent = NULL;
- cEvent *pEvent = (cEvent *) pSchedule->GetEvent (SiEitEvent.getEventId (), SiEitEvent.getStartTime ());
- if (!pEvent) {
- if (OnlyRunningStatus)
- continue;
- // If we don't have that event yet, we create a new one.
- // Otherwise we copy the information into the existing event anyway, because the data might have changed.
- pEvent = newEvent = new cEvent (SiEitEvent.getEventId ());
- if (!pEvent)
- continue;
- }
- else {
- // We have found an existing event, either through its event ID or its start time.
- pEvent->SetSeen ();
- // If the existing event has a zero table ID it was defined externally and shall
- // not be overwritten.
- if (pEvent->TableID () == 0x00) {
+ cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channel, true);
+
+ bool Empty = true;
+ bool Modified = false;
+ bool HasExternalData = false;
+ time_t SegmentStart = 0;
+ time_t SegmentEnd = 0;
+
+ SI::EIT::Event SiEitEvent;
+ for (SI::Loop::Iterator it; eventLoop.getNext (SiEitEvent, it);) {
+ bool ExternalData = false;
+ // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number.
+ if (SiEitEvent.getStartTime () == 0 || (SiEitEvent.getStartTime () > 0 && SiEitEvent.getDuration () == 0))
+ continue;
+ Empty = false;
+ if (!SegmentStart)
+ SegmentStart = SiEitEvent.getStartTime ();
+ SegmentEnd = SiEitEvent.getStartTime () + SiEitEvent.getDuration ();
+ cEvent *newEvent = NULL;
+ cEvent *rEvent = NULL;
+ cEvent *pEvent = (cEvent *) pSchedule->GetEvent (SiEitEvent.getEventId (), SiEitEvent.getStartTime ());
+ if (!pEvent) {
+ if (OnlyRunningStatus)
+ continue;
+ // If we don't have that event yet, we create a new one.
+ // Otherwise we copy the information into the existing event anyway, because the data might have changed.
+ pEvent = newEvent = new cEvent (SiEitEvent.getEventId ());
+ if (!pEvent)
+ continue;
+ } else {
+ // We have found an existing event, either through its event ID or its start time.
+ pEvent->SetSeen ();
+ // If the existing event has a zero table ID it was defined externally and shall
+ // not be overwritten.
+ if (pEvent->TableID () == 0x00) {
#ifdef USE_DDEPGENTRY
- if (pEvent->Version () == getVersionNumber ()) {
- if (Setup.MixEpgAction == 0)
- continue;
- //printf("in");
- //printf("%s", pEvent->GetTimeString());
- // to use the info of the original epg, update the extern one,
- // if it has less info
- SI::Descriptor * d;
- SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL;
- //SI::ExtendedEventDescriptor *eed = NULL;
- SI::ShortEventDescriptor * ShortEventDescriptor = NULL;
- //SI::ShortEventDescriptor *sed = NULL;
- //SI::TimeShiftedEventDescriptor *tsed = NULL;
- //cLinkChannels *LinkChannels = NULL;
- for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext (it2));) {
- if (d->getDescriptorTag () == SI::ShortEventDescriptorTag) {
- int LanguagePreferenceShort = -1;
- SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
- if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
- || !ShortEventDescriptor) {
- delete ShortEventDescriptor;
- ShortEventDescriptor = sed;
- d = NULL; // so that it is not deleted
- }
- }
- else if (d->getDescriptorTag () == SI::ExtendedEventDescriptorTag) {
- int LanguagePreferenceExt = -1;
- bool UseExtendedEventDescriptor = false;
- SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
- if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
- || !ExtendedEventDescriptors) {
- delete ExtendedEventDescriptors;
- ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
- UseExtendedEventDescriptor = true;
- }
- if (UseExtendedEventDescriptor) {
- ExtendedEventDescriptors->Add (eed);
- d = NULL; // so that it is not deleted
- }
- if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
- UseExtendedEventDescriptor = false;
- }
- delete d;
- }
- if (pEvent) {
- if (ShortEventDescriptor) {
- char buffer[256];
- if (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)) && pEvent->ShortText ()
- && (strlen (ShortEventDescriptor->text.getText (buffer, sizeof (buffer))) >
- strlen (pEvent->ShortText ()))) {
- pEvent->SetShortText (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)));
- pEvent->FixEpgBugs ();
- }
- }
- if (ExtendedEventDescriptors) {
- char buffer[ExtendedEventDescriptors->getMaximumTextLength (": ") + 1];
- //pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": "));
- if (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")
- && pEvent->Description ()
- && (strlen (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")) >
- strlen (pEvent->Description ()))) {
- pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
- pEvent->FixEpgBugs ();
- }
- }
- }
- delete ExtendedEventDescriptors;
- delete ShortEventDescriptor;
- continue;
- }
+ if (pEvent->Version () == getVersionNumber ()) {
+ if (Setup.MixEpgAction == 0)
+ continue;
+ //printf("in");
+ //printf("%s", pEvent->GetTimeString());
+ // to use the info of the original epg, update the extern one,
+ // if it has less info
+ SI::Descriptor * d;
+ SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL;
+ //SI::ExtendedEventDescriptor *eed = NULL;
+ SI::ShortEventDescriptor * ShortEventDescriptor = NULL;
+ //SI::ShortEventDescriptor *sed = NULL;
+ //SI::TimeShiftedEventDescriptor *tsed = NULL;
+ //cLinkChannels *LinkChannels = NULL;
+ for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext (it2));) {
+ if (d->getDescriptorTag () == SI::ShortEventDescriptorTag) {
+ int LanguagePreferenceShort = -1;
+ SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+ || !ShortEventDescriptor) {
+ delete ShortEventDescriptor;
+ ShortEventDescriptor = sed;
+ d = NULL; // so that it is not deleted
+ }
+ } else if (d->getDescriptorTag () == SI::ExtendedEventDescriptorTag) {
+ int LanguagePreferenceExt = -1;
+ bool UseExtendedEventDescriptor = false;
+ SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+ || !ExtendedEventDescriptors) {
+ delete ExtendedEventDescriptors;
+ ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+ UseExtendedEventDescriptor = true;
+ }
+ if (UseExtendedEventDescriptor) {
+ ExtendedEventDescriptors->Add (eed);
+ d = NULL; // so that it is not deleted
+ }
+ if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
+ UseExtendedEventDescriptor = false;
+ }
+ delete d;
+ }
+ if (pEvent) {
+ if (ShortEventDescriptor) {
+ char buffer[256];
+ if (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)) && pEvent->ShortText ()
+ && (strlen (ShortEventDescriptor->text.getText (buffer, sizeof (buffer))) >
+ strlen (pEvent->ShortText ()))) {
+ pEvent->SetShortText (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)));
+ pEvent->FixEpgBugs ();
+ }
+ }
+ if (ExtendedEventDescriptors) {
+ char buffer[ExtendedEventDescriptors->getMaximumTextLength (": ") + 1];
+ //pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": "));
+ if (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")
+ && pEvent->Description ()
+ && (strlen (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")) >
+ strlen (pEvent->Description ()))) {
+ pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
+ pEvent->FixEpgBugs ();
+ }
+ }
+ }
+ delete ExtendedEventDescriptors;
+ delete ShortEventDescriptor;
+ continue;
+ }
#else
- if (pEvent->Version () == getVersionNumber ())
- continue;
+ if (pEvent->Version () == getVersionNumber ())
+ continue;
#endif /* DDEPGENTRY */
- HasExternalData = ExternalData = true;
- }
- // If the new event has a higher table ID, let's skip it.
- // The lower the table ID, the more "current" the information.
- else if (Tid > pEvent->TableID ())
- continue;
- // If the new event comes from the same table and has the same version number
- // as the existing one, let's skip it to avoid unnecessary work.
- // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like
- // 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 ())
- continue;
+ HasExternalData = ExternalData = true;
}
- if (!ExternalData) {
- pEvent->SetEventID (SiEitEvent.getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-(
- pEvent->SetTableID (Tid);
- pEvent->SetStartTime (SiEitEvent.getStartTime ());
- pEvent->SetDuration (SiEitEvent.getDuration ());
- }
- if (newEvent)
- pSchedule->AddEvent (newEvent);
- if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
+ // If the new event has a higher table ID, let's skip it.
+ // The lower the table ID, the more "current" the information.
+ else if (Tid > pEvent->TableID ())
+ continue;
+ // If the new event comes from the same table and has the same version number
+ // as the existing one, let's skip it to avoid unnecessary work.
+ // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like
+ // 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())
+ continue;
+ }
+ if (!ExternalData) {
+ pEvent->SetEventID (SiEitEvent.getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-(
+ pEvent->SetTableID (Tid);
+ pEvent->SetStartTime (SiEitEvent.getStartTime ());
+ pEvent->SetDuration (SiEitEvent.getDuration ());
+ }
+ if (newEvent)
+ pSchedule->AddEvent (newEvent);
+ if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
#ifdef USE_DDEPGENTRY
- if (Setup.DisableVPS == 0 && SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning)
+ if (Setup.DisableVPS == 0 && SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning)
#else
- if (SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning)
+ if (SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning)
#endif /* DDEPGENTRY */
- pSchedule->SetRunningStatus (pEvent, SiEitEvent.getRunningStatus (), channel);
+ pSchedule->SetRunningStatus (pEvent, SiEitEvent.getRunningStatus (), channel);
+ }
+ if (OnlyRunningStatus)
+ continue; // do this before setting the version, so that the full update can be done later
+ pEvent->SetVersion (getVersionNumber());
+
+ int LanguagePreferenceShort = -1;
+ int LanguagePreferenceExt = -1;
+ bool UseExtendedEventDescriptor = false;
+ 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;
}
- if (OnlyRunningStatus)
- continue; // do this before setting the version, so that the full update can be done later
- pEvent->SetVersion (getVersionNumber ());
-
- int LanguagePreferenceShort = -1;
- int LanguagePreferenceExt = -1;
- bool UseExtendedEventDescriptor = false;
- SI::Descriptor * d;
- SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL;
- SI::ShortEventDescriptor * ShortEventDescriptor = NULL;
- cLinkChannels *LinkChannels = NULL;
- cComponents *Components = NULL;
- for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext (it2));) {
- if (ExternalData && d->getDescriptorTag () != SI::ComponentDescriptorTag) {
- delete d;
- continue;
- }
- switch (d->getDescriptorTag ()) {
- case SI::ExtendedEventDescriptorTag:{
- SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
- if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
- || !ExtendedEventDescriptors) {
- delete ExtendedEventDescriptors;
- ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
- UseExtendedEventDescriptor = true;
- }
- if (UseExtendedEventDescriptor) {
- ExtendedEventDescriptors->Add (eed);
- d = NULL; // so that it is not deleted
- }
- if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
- UseExtendedEventDescriptor = false;
- }
- break;
- case SI::ShortEventDescriptorTag:{
- SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
- if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
- || !ShortEventDescriptor) {
- delete ShortEventDescriptor;
- ShortEventDescriptor = sed;
- d = NULL; // so that it is not deleted
- }
- }
- break;
+
+ //LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x)"), d->getDescriptorTag ());
+
+ switch (d->getDescriptorTag ()) {
+ case SI::ExtendedEventDescriptorTag: {
+ SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+ || !ExtendedEventDescriptors) {
+ delete ExtendedEventDescriptors;
+ ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+ UseExtendedEventDescriptor = true;
+ }
+ if (UseExtendedEventDescriptor) {
+ ExtendedEventDescriptors->Add (eed);
+ d = NULL; // so that it is not deleted
+ }
+ if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
+ UseExtendedEventDescriptor = false;
+ }
+ break;
+ case SI::ShortEventDescriptorTag: {
+ SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+ || !ShortEventDescriptor) {
+ delete ShortEventDescriptor;
+ ShortEventDescriptor = sed;
+ d = NULL; // so that it is not deleted
+ }
+ }
+ break;
#if APIVERSNUM > 10711
- case SI::ContentDescriptorTag:{
- SI::ContentDescriptor *cd = (SI::ContentDescriptor *)d;
- SI::ContentDescriptor::Nibble Nibble;
- int NumContents = 0;
- uchar Contents[MaxEventContents] = { 0 };
- for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3); ) {
- if (NumContents < MaxEventContents) {
- Contents[NumContents] = ((Nibble.getContentNibbleLevel1() & 0xF) << 4) | (Nibble.getContentNibbleLevel2() & 0xF);
- NumContents++;
- }
- }
- pEvent->SetContents(Contents);
- }
- break;
+ case SI::ContentDescriptorTag: {
+ SI::ContentDescriptor *cd = (SI::ContentDescriptor *)d;
+ SI::ContentDescriptor::Nibble Nibble;
+ int NumContents = 0;
+ uchar Contents[MaxEventContents] = { 0 };
+ for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3); ) {
+ if (NumContents < MaxEventContents) {
+ 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);
+ }
+ break;
#endif
- case SI::ParentalRatingDescriptorTag:{
- int LanguagePreferenceRating = -1;
- SI::ParentalRatingDescriptor *prd = (SI::ParentalRatingDescriptor *)d;
- SI::ParentalRatingDescriptor::Rating Rating;
- for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3); ) {
- if (I18nIsPreferredLanguage(Setup.EPGLanguages, Rating.languageCode, LanguagePreferenceRating)) {
- int ParentalRating = (Rating.getRating() & 0xFF);
- switch (ParentalRating) {
- // values defined by the DVB standard (minimum age = rating + 3 years):
- case 0x01 ... 0x0F: ParentalRating += 3; break;
- // values defined by broadcaster CSAT (now why didn't they just use 0x07, 0x09 and 0x0D?):
- case 0x11: ParentalRating = 10; break;
- case 0x12: ParentalRating = 12; break;
- case 0x13: ParentalRating = 16; break;
- default: ParentalRating = 0;
- }
- pEvent->SetParentalRating(ParentalRating);
- }
- }
- }
- break;
- case SI::PDCDescriptorTag:{
- SI::PDCDescriptor * pd = (SI::PDCDescriptor *) d;
- time_t now = time (NULL);
- struct tm tm_r;
- struct tm t = *localtime_r (&now, &tm_r); // this initializes the time zone in 't'
- t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
- int month = t.tm_mon;
- t.tm_mon = pd->getMonth () - 1;
- t.tm_mday = pd->getDay ();
- t.tm_hour = pd->getHour ();
- t.tm_min = pd->getMinute ();
- t.tm_sec = 0;
- if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan
- t.tm_year++;
- else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec
- t.tm_year--;
- time_t vps = mktime (&t);
- pEvent->SetVps (vps);
- }
- break;
- case SI::TimeShiftedEventDescriptorTag:{
- SI::TimeShiftedEventDescriptor * tsed = (SI::TimeShiftedEventDescriptor *) d;
- cSchedule *rSchedule =
- (cSchedule *) Schedules->
- GetSchedule (tChannelID (Source, channel->Nid (), channel->Tid (), tsed->getReferenceServiceId ()));
- if (!rSchedule)
- break;
- rEvent = (cEvent *) rSchedule->GetEvent (tsed->getReferenceEventId ());
- if (!rEvent)
- break;
- pEvent->SetTitle (rEvent->Title ());
- pEvent->SetShortText (rEvent->ShortText ());
- pEvent->SetDescription (rEvent->Description ());
- }
- break;
- case SI::LinkageDescriptorTag:{
- SI::LinkageDescriptor * ld = (SI::LinkageDescriptor *) d;
- tChannelID linkID (Source, ld->getOriginalNetworkId (), ld->getTransportStreamId (), ld->getServiceId ());
- if (ld->getLinkageType () == 0xB0) { // Premiere World
- time_t now = time (NULL);
- bool hit = SiEitEvent.getStartTime () <= now
- && now < SiEitEvent.getStartTime () + SiEitEvent.getDuration ();
- if (hit) {
- char linkName[ld->privateData.getLength () + 1];
- strn0cpy (linkName, (const char *) ld->privateData.getData (), sizeof (linkName));
- // TODO is there a standard way to determine the character set of this string?
- cChannel *link = Channels.GetByChannelID (linkID);
- if (link != channel) { // only link to other channels, not the same one
- //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX
- if (link) {
- if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
- link->SetName (linkName, "", "");
- }
- else if (Setup.UpdateChannels >= 4) {
- cChannel *transponder = channel;
- if (channel->Tid () != ld->getTransportStreamId ())
- transponder = Channels.GetByTransponderID (linkID);
- link =
- Channels.NewChannel (transponder, linkName, "", "", ld->getOriginalNetworkId (),
- ld->getTransportStreamId (), ld->getServiceId ());
- //XXX patFilter->Trigger();
- }
- if (link) {
- if (!LinkChannels)
- LinkChannels = new cLinkChannels;
- LinkChannels->Add (new cLinkChannel (link));
- }
- }
- else
- channel->SetPortalName (linkName);
- }
- }
- }
- break;
- case SI::ComponentDescriptorTag:{
- SI::ComponentDescriptor * cd = (SI::ComponentDescriptor *) d;
- uchar Stream = cd->getStreamContent ();
- uchar Type = cd->getComponentType ();
- if (1 <= Stream && Stream <= 3 && Type != 0) { // 1=video, 2=audio, 3=subtitles
- if (!Components)
- Components = new cComponents;
- char buffer[Utf8BufSize (256)];
- Components->SetComponent (Components->NumComponents (), Stream, Type,
- I18nNormalizeLanguageCode (cd->languageCode),
- cd->description.getText (buffer, sizeof (buffer)));
- }
- }
- break;
- default:;
- }
- delete d;
+ case SI::ParentalRatingDescriptorTag: {
+ int LanguagePreferenceRating = -1;
+ SI::ParentalRatingDescriptor *prd = (SI::ParentalRatingDescriptor *)d;
+ SI::ParentalRatingDescriptor::Rating Rating;
+ for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3); ) {
+ if (I18nIsPreferredLanguage(Setup.EPGLanguages, Rating.languageCode, LanguagePreferenceRating)) {
+ int ParentalRating = (Rating.getRating() & 0xFF);
+ switch (ParentalRating) {
+ // values defined by the DVB standard (minimum age = rating + 3 years):
+ case 0x01 ... 0x0F:
+ ParentalRating += 3;
+ break;
+ // values defined by broadcaster CSAT (now why didn't they just use 0x07, 0x09 and 0x0D?):
+ case 0x11:
+ ParentalRating = 10;
+ break;
+ case 0x12:
+ ParentalRating = 12;
+ break;
+ case 0x13:
+ ParentalRating = 16;
+ break;
+ default:
+ ParentalRating = 0;
+ }
+ pEvent->SetParentalRating(ParentalRating);
+ }
+ }
}
+ break;
+ case SI::PDCDescriptorTag: {
+ SI::PDCDescriptor * pd = (SI::PDCDescriptor *) d;
+ time_t now = time (NULL);
+ struct tm tm_r;
+ struct tm t = *localtime_r (&now, &tm_r); // this initializes the time zone in 't'
+ t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
+ int month = t.tm_mon;
+ t.tm_mon = pd->getMonth () - 1;
+ t.tm_mday = pd->getDay ();
+ t.tm_hour = pd->getHour ();
+ t.tm_min = pd->getMinute ();
+ t.tm_sec = 0;
+ if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan
+ t.tm_year++;
+ else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec
+ t.tm_year--;
+ time_t vps = mktime (&t);
+ pEvent->SetVps (vps);
+ }
+ break;
+ case SI::TimeShiftedEventDescriptorTag: {
+ SI::TimeShiftedEventDescriptor * tsed = (SI::TimeShiftedEventDescriptor *) d;
+ cSchedule *rSchedule =
+ (cSchedule *) Schedules->
+ GetSchedule (tChannelID (Source, channel->Nid (), channel->Tid (), tsed->getReferenceServiceId ()));
+ if (!rSchedule)
+ break;
+ rEvent = (cEvent *) rSchedule->GetEvent (tsed->getReferenceEventId ());
+ if (!rEvent)
+ break;
+ pEvent->SetTitle (rEvent->Title ());
+ pEvent->SetShortText (rEvent->ShortText ());
+ pEvent->SetDescription (rEvent->Description ());
+ }
+ break;
+ case SI::LinkageDescriptorTag: {
+ SI::LinkageDescriptor * ld = (SI::LinkageDescriptor *) d;
+ tChannelID linkID (Source, ld->getOriginalNetworkId (), ld->getTransportStreamId (), ld->getServiceId ());
+ if (ld->getLinkageType () == 0xB0) { // Premiere World
+ time_t now = time (NULL);
+ bool hit = SiEitEvent.getStartTime () <= now
+ && now < SiEitEvent.getStartTime () + SiEitEvent.getDuration ();
+ if (hit) {
+ char linkName[ld->privateData.getLength () + 1];
+ strn0cpy (linkName, (const char *) ld->privateData.getData (), sizeof (linkName));
+ // TODO is there a standard way to determine the character set of this string?
+ cChannel *link = Channels.GetByChannelID (linkID);
+ if (link != channel) { // only link to other channels, not the same one
+ //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX
+ if (link) {
+ if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
+ link->SetName (linkName, "", "");
+ } else if (Setup.UpdateChannels >= 4) {
+ cChannel *transponder = channel;
+ if (channel->Tid () != ld->getTransportStreamId ())
+ transponder = Channels.GetByTransponderID (linkID);
+ link =
+ Channels.NewChannel (transponder, linkName, "", "", ld->getOriginalNetworkId (),
+ ld->getTransportStreamId (), ld->getServiceId ());
+ }
+ if (link) {
+ if (!LinkChannels)
+ LinkChannels = new cLinkChannels;
+ LinkChannels->Add (new cLinkChannel (link));
+ }
+ } else
+ channel->SetPortalName (linkName);
+ }
+ }
+ }
+ break;
+ case SI::ComponentDescriptorTag: {
+ SI::ComponentDescriptor * cd = (SI::ComponentDescriptor *) d;
+ uchar Stream = cd->getStreamContent ();
+ uchar Type = cd->getComponentType ();
+ //if (1 <= Stream && Stream <= 3 && Type != 0) { // 1=video, 2=audio, 3=subtitles
+ if (1 <= Stream && Stream <= 6 && Type != 0) { // 1=MPEG2-video, 2=MPEG1-audio, 3=subtitles, 4=AC3-audio, 5=H.264-video, 6=HEAAC-audio
+ if (!Components)
+ Components = new cComponents;
+ char buffer[Utf8BufSize (256)];
+ Components->SetComponent (Components->NumComponents (), Stream, Type,
+ I18nNormalizeLanguageCode (cd->languageCode),
+ cd->description.getText (buffer, sizeof (buffer)));
+ }
+ }
+ 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;
+ }
+ delete d;
+ }
- if (!rEvent) {
- if (ShortEventDescriptor) {
- char buffer[Utf8BufSize (256)];
- unsigned char *f;
- int l = ShortEventDescriptor->name.getLength ();
- f = (unsigned char *) ShortEventDescriptor->name.getData ().getData ();
- decodeText2 (f, l, buffer, sizeof (buffer));
- pEvent->SetTitle (buffer);
- l = ShortEventDescriptor->text.getLength ();
- f = (unsigned char *) ShortEventDescriptor->text.getData ().getData ();
- decodeText2 (f, l, buffer, sizeof (buffer));
- pEvent->SetShortText (buffer);
- }
- else if (!HasExternalData) {
- pEvent->SetTitle (NULL);
- pEvent->SetShortText (NULL);
- }
- if (ExtendedEventDescriptors) {
- char buffer[Utf8BufSize (ExtendedEventDescriptors->getMaximumTextLength (": ")) + 1];
- pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
- }
- else if (!HasExternalData)
- pEvent->SetDescription (NULL);
+ if (!rEvent) {
+ if (ShortEventDescriptor) {
+ char buffer[Utf8BufSize (256)];
+ unsigned char *f;
+ int l = ShortEventDescriptor->name.getLength();
+ f = (unsigned char *) ShortEventDescriptor->name.getData().getData();
+ decodeText2 (f, l, buffer, sizeof (buffer));
+ //ShortEventDescriptor->name.getText(buffer, sizeof(buffer));
+ LogD(2, prep("Title: %s Decoded: %s"), f, buffer);
+ pEvent->SetTitle (buffer);
+ l = ShortEventDescriptor->text.getLength();
+ f = (unsigned char *) ShortEventDescriptor->text.getData().getData();
+ decodeText2 (f, l, buffer, sizeof (buffer));
+ //ShortEventDescriptor->text.getText(buffer, sizeof(buffer));
+ pEvent->SetShortText (buffer);
+ LogD(2, prep("ShortText: %s Decoded: %s"), f, buffer);
+ } else if (!HasExternalData) {
+ pEvent->SetTitle (NULL);
+ pEvent->SetShortText (NULL);
+ LogD(2, prep("!HasExternalData"));
}
- delete ExtendedEventDescriptors;
- delete ShortEventDescriptor;
+ if (ExtendedEventDescriptors) {
+ char buffer[Utf8BufSize (ExtendedEventDescriptors->getMaximumTextLength (": ")) + 1];
+ 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);
- pEvent->SetComponents (Components);
+// LogD(2, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title());
- if (!HasExternalData)
- pEvent->FixEpgBugs ();
- if (LinkChannels)
- channel->SetLinkChannels (LinkChannels);
- Modified = true;
+// 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)
+ channel->SetLinkChannels (LinkChannels);
+ Modified = true;
#ifdef USE_DDEPGENTRY
- //to avoid double epg-entrys from ext and int epg sources :EW
- if (pEvent && pEvent->TableID () != 0x00) {
- cEvent *pPreviousEvent = (cEvent *) pSchedule->GetPreviousEvent (pEvent);
- if (pPreviousEvent) {
- if (Setup.DoubleEpgAction == 0) {
- pPreviousEvent->SetStartTime (pEvent->StartTime ());
- pPreviousEvent->SetDuration (pEvent->Duration ());
- if (Setup.DisableVPS == 0) {
- if (channel)
- pPreviousEvent->SetRunningStatus (pEvent->RunningStatus (), channel);
- else
- pPreviousEvent->SetRunningStatus (pEvent->RunningStatus ());
- }
- // to use the info of the original epg, update the extern one,
- // if it has less info
- char buffer_short_intern[256];
- char buffer_short_extern[256];
- int len_short_intern = 0;
- int len_short_extern = 0;
- if (pEvent->ShortText ())
- len_short_intern =
- snprintf (buffer_short_intern, sizeof (buffer_short_intern) - 1, "%s", pEvent->ShortText ());
- if (pPreviousEvent->ShortText ())
- len_short_extern =
- snprintf (buffer_short_extern, sizeof (buffer_short_extern) - 1, "%s", pPreviousEvent->ShortText ());
- if (len_short_intern > 0) {
- if (len_short_extern < 1)
- pPreviousEvent->SetShortText (buffer_short_intern);
- else if (len_short_intern > len_short_extern)
- pPreviousEvent->SetShortText (buffer_short_intern);
- }
- if (pEvent->Description ()) {
- char buffer_title_intern[4096];
- char buffer_title_extern[4096];
- int len_title_intern = 0;
- int len_title_extern = 0;
- if (pEvent->Description ())
- len_title_intern =
- snprintf (buffer_title_intern, sizeof (buffer_title_intern) - 1, "%s", pEvent->Description ());
- if (pPreviousEvent->Description ())
- len_title_extern =
- snprintf (buffer_title_extern, sizeof (buffer_title_extern) - 1, "%s",
- pPreviousEvent->Description ());
- if (len_title_intern > 0) {
- if (len_title_extern < 1)
- pPreviousEvent->SetDescription (buffer_title_intern);
- else if (len_title_intern > len_title_extern)
- pPreviousEvent->SetDescription (buffer_title_intern);
- }
- }
- if (pPreviousEvent->Vps () == 0 && pEvent->Vps () != 0)
- pPreviousEvent->SetVps (pEvent->Vps ());
- pSchedule->DelEvent (pEvent);
- pPreviousEvent->FixEpgBugs ();
- }
- else
- pSchedule->DelEvent (pPreviousEvent);
- }
+ //to avoid double epg-entrys from ext and int epg sources :EW
+ if (pEvent && pEvent->TableID () != 0x00) {
+ cEvent *pPreviousEvent = (cEvent *) pSchedule->GetPreviousEvent (pEvent);
+ if (pPreviousEvent) {
+ if (Setup.DoubleEpgAction == 0) {
+ pPreviousEvent->SetStartTime (pEvent->StartTime ());
+ pPreviousEvent->SetDuration (pEvent->Duration ());
+ if (Setup.DisableVPS == 0) {
+ if (channel)
+ pPreviousEvent->SetRunningStatus (pEvent->RunningStatus (), channel);
+ else
+ pPreviousEvent->SetRunningStatus (pEvent->RunningStatus ());
+ }
+ // to use the info of the original epg, update the extern one,
+ // if it has less info
+ char buffer_short_intern[256];
+ char buffer_short_extern[256];
+ int len_short_intern = 0;
+ int len_short_extern = 0;
+ if (pEvent->ShortText ())
+ len_short_intern =
+ snprintf (buffer_short_intern, sizeof (buffer_short_intern) - 1, "%s", pEvent->ShortText ());
+ if (pPreviousEvent->ShortText ())
+ len_short_extern =
+ snprintf (buffer_short_extern, sizeof (buffer_short_extern) - 1, "%s", pPreviousEvent->ShortText ());
+ if (len_short_intern > 0) {
+ if (len_short_extern < 1)
+ pPreviousEvent->SetShortText (buffer_short_intern);
+ else if (len_short_intern > len_short_extern)
+ pPreviousEvent->SetShortText (buffer_short_intern);
+ }
+ if (pEvent->Description ()) {
+ char buffer_title_intern[4096];
+ char buffer_title_extern[4096];
+ int len_title_intern = 0;
+ int len_title_extern = 0;
+ if (pEvent->Description ())
+ len_title_intern =
+ snprintf (buffer_title_intern, sizeof (buffer_title_intern) - 1, "%s", pEvent->Description ());
+ if (pPreviousEvent->Description ())
+ len_title_extern =
+ snprintf (buffer_title_extern, sizeof (buffer_title_extern) - 1, "%s",
+ pPreviousEvent->Description ());
+ if (len_title_intern > 0) {
+ if (len_title_extern < 1)
+ pPreviousEvent->SetDescription (buffer_title_intern);
+ else if (len_title_intern > len_title_extern)
+ pPreviousEvent->SetDescription (buffer_title_intern);
+ }
+ }
+ if (pPreviousEvent->Vps () == 0 && pEvent->Vps () != 0)
+ pPreviousEvent->SetVps (pEvent->Vps ());
+ pSchedule->DelEvent (pEvent);
+ pPreviousEvent->FixEpgBugs ();
+ } else
+ pSchedule->DelEvent (pPreviousEvent);
}
-#endif /* DDEPGENTRY */
- }
- if (Empty && Tid == 0x4E && getSectionNumber () == 0)
- // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
- pSchedule->ClrRunningStatus (channel);
- if (Tid == 0x4E)
- pSchedule->SetPresentSeen ();
- if (OnlyRunningStatus)
- return;
- if (Modified) {
- pSchedule->Sort ();
- if (!HasExternalData)
- pSchedule->DropOutdated (SegmentStart, SegmentEnd, Tid, getVersionNumber ());
- Schedules->SetModified (pSchedule);
}
+#endif /* DDEPGENTRY */
+ }
+ if (Empty && Tid == 0x4E && getSectionNumber () == 0)
+ // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
+ pSchedule->ClrRunningStatus (channel);
+ if (Tid == 0x4E)
+ pSchedule->SetPresentSeen ();
+ if (OnlyRunningStatus) {
+ LogD(4, prep("OnlyRunningStatus"));
+ return;
}
+ if (Modified) {
+ pSchedule->Sort ();
+ if (!HasExternalData)
+ pSchedule->DropOutdated (SegmentStart, SegmentEnd, Tid, getVersionNumber ());
+ Schedules->SetModified (pSchedule);
+ }
+ LogD(4, prep("end of cEIT2"));
+
+}
//end of cEIT2
-} //end namespace SI
+
+} //end namespace SI
void cFilterEEPG::ProcessNextFormat (bool FirstTime = false)
{
-/* for (int i = 0; i <= HIGHEST_FORMAT; i++)
- esyslog ("EEPGDEBUG: Format %i on pid %x", i, UnprocessedFormat[i]); */
+ /* for (int i = 0; i <= HIGHEST_FORMAT; i++)
+ esyslog ("EEPGDEBUG: Format %i on pid %x", i, UnprocessedFormat[i]); */
if (!FirstTime) {
isyslog ("EEPG: found %i equivalents channels", nEquivChannels);
@@ -3269,19 +3497,20 @@ void cFilterEEPG::ProcessNextFormat (bool FirstTime = false)
isyslog ("EEPG: written %i summaries", SummaryCounter);
isyslog ("EEPG: rejected %i titles/summaries because of higher TableId", RejectTableId);
//Send message when finished
- if (SetupPE.DisplayMessage) {
- char *mesg;
- asprintf(&mesg, "EEPG: written %i summaries", SummaryCounter);
- Skins.QueueMessage(mtInfo, mesg, 2);
- free(mesg);
- }
+ if (SetupPE.DisplayMessage) {
+ char *mesg;
+ Asprintf(&mesg, "EEPG: written %i summaries", SummaryCounter);
+ Skins.QueueMessage(mtInfo, mesg, 2);
+ free(mesg);
+ }
+
TitleCounter = 0;
SummaryCounter = 0;
/*if (SummariesNotFound != 0)
esyslog ("EEPG: %i summaries not found", SummariesNotFound);
else if (VERBOSE >= 1)
isyslog ("EEPG: %i summaries not found", SummariesNotFound); */
- UnprocessedFormat[Format] = 0; //clear previously processed format
+ UnprocessedFormat[Format] = 0; //clear previously processed format
//Next few lines prevent eepg from reading multiple eepg-systems on one transponder e.g. CDNL
//isyslog ("EEPG: Ended all processing");
@@ -3292,32 +3521,35 @@ void cFilterEEPG::ProcessNextFormat (bool FirstTime = false)
TitleCounter = 0;
SummaryCounter = 0;
RejectTableId = 0;
- //cleanup mess of last processing
+ //cleanup mess of last processing
ChannelSeq.clear ();
FreeTitles ();
FreeSummaries ();
//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
+ pid = UnprocessedFormat[Format]; //and reinstall its pid
memset (&InitialChannel, 0, 8);
memset (&InitialTitle, 0, 64);
memset (&InitialSummary, 0, 64);
NagraCounter = 0;
- Version = -1; //because 0 can be a valid version number...
+ Version = -1; //because 0 can be a valid version number...
nEquivChannels = 0;
nChannels = 0;
nThemes = 0;
@@ -3329,628 +3561,397 @@ void cFilterEEPG::ProcessNextFormat (bool FirstTime = false)
Add (pid, 0xA0);
break;
case MHW1:
- AddFilter (0xd3, 0x92); //ThemesMHW1//TODO: all filters are serialized, strictly speaking Themes is non-fatal...
+ AddFilter (0xd3, 0x92); //ThemesMHW1//TODO: all filters are serialized, strictly speaking Themes is non-fatal...
break;
case MHW2:
- AddFilter (0x231, 0xc8); //MHW2 Channels & Themes
+ AddFilter (0x231, 0xc8); //MHW2 Channels & Themes
break;
case SKY_IT:
case SKY_UK:
- AddFilter (0x11, 0x4a); //Sky Channels
+ AddFilter (0x11, 0x4a); //Sky Channels
+ break;
+ case FREEVIEW: //Freeview, CONT mode //TODO streamline this for other modes
+ InitDictionary ();
+ AddFilter (pid, 0x4e, 0xfe); //event info, actual(0x4e)/other(0x4f) TS, present/following
+ AddFilter (pid, 0x50, 0xf0); //event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
+ AddFilter (pid, 0x60, 0xf0); //event info, other TS, schedule(0x60)/schedule for future days(0x6X)
+ AddFilter (0x39, 0x50, 0xf0); //event info, actual TS, Viasat
+ AddFilter (0x39, 0x60, 0xf0); //event info, other TS, Viasat
break;
- case FREEVIEW: //Freeview, CONT mode //TODO streamline this for other modes
- ReadFileDictionary ();
- AddFilter (pid, 0x4e, 0xfe); //event info, actual(0x4e)/other(0x4f) TS, present/following
- AddFilter (pid, 0x50, 0xf0); //event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
- AddFilter (pid, 0x60, 0xf0); //event info, other TS, schedule(0x60)/schedule for future days(0x6X)
- AddFilter (0x39, 0x50, 0xf0); //event info, actual TS, Viasat
- AddFilter (0x39, 0x60, 0xf0); //event info, other TS, Viasat
case NAGRA:
- // isyslog ("EEPG: NagraGuide Extended EPG detected.");
- AddFilter (pid, 0xb0); //perhaps TID is equal to first data byte?
+ 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(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)
- NextPmt ();
+ NextPmt ();
if (!pmtpid) {
- SI::PAT pat (Data, false);
- if (pat.CheckCRCAndParse ()) {
- SI::PAT::Association assoc;
- int idx = 0;
- for (SI::Loop::Iterator it; pat.associationLoop.getNext (assoc, it);) {
- if (!assoc.isNITPid ()) {
- //if (!assoc.isNITPid () && Scanning) {
- if (idx++ == pmtidx) {
- pmtpid = assoc.getPid ();
- pmtsid = assoc.getServiceId ();
- Add (pmtpid, 0x02);
- pmtnext = now + PMT_SCAN_TIMEOUT;
- if (VERBOSE >= 3)
- esyslog ("PMT pid now 0x%04x (idx=%d)\n", pmtpid, pmtidx);
- break;
- }
- }
- }
- if (!pmtpid) {
- pmtidx = 0;
- pmtnext = now + PMT_SCAN_IDLE;
- if (VERBOSE >= 1)
- esyslog ("PMT scan idle\n");
-
- Del (0, 0); //this effectively kills the PMT_SCAN_IDLE functionality
-
- //now after the scan is completed, start processing
- ProcessNextFormat (true); //FirstTime flag is set
- }
- }
+ SI::PAT pat (Data, false);
+ if (pat.CheckCRCAndParse ()) {
+ SI::PAT::Association assoc;
+ int idx = 0;
+ for (SI::Loop::Iterator it; pat.associationLoop.getNext (assoc, it);) {
+ if (!assoc.isNITPid ()) {
+ //if (!assoc.isNITPid () && Scanning) {
+ if (idx++ == pmtidx) {
+ pmtpid = assoc.getPid ();
+ pmtsid = assoc.getServiceId ();
+ Add (pmtpid, 0x02);
+ pmtnext = now + PMT_SCAN_TIMEOUT;
+ LogI(3, prep("PMT pid now 0x%04x (idx=%d)\n"), pmtpid, pmtidx);
+ break;
+ }
+ }
+ }
+ if (!pmtpid) {
+ pmtidx = 0;
+ pmtnext = now + PMT_SCAN_IDLE;
+ LogI(1, prep("PMT scan idle\n"));
+
+ Del (0, 0); //this effectively kills the PMT_SCAN_IDLE functionality
+
+ //now after the scan is completed, start processing
+ ProcessNextFormat (true); //FirstTime flag is set
+ }
+ }
}
}
- }
- else if (pmtpid > 0 && Pid == pmtpid && Tid == SI::TableIdPMT && Source () && Transponder ()) {
+ } else if (pmtpid > 0 && Pid == pmtpid && Tid == SI::TableIdPMT && Source () && Transponder ()) {
SI::PMT pmt (Data, false);
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
- SI::CharArray data = stream.getData ();
- if ((data[1] & 0xE0) == 0xE0 && (data[3] & 0xF0) == 0xF0) {
- bool prvData = false, usrData = false;
- bool prvOTV = false, prvFRV = false;
- int usrOTV = 0, usrFRV = 0;
- if(data[2]==0x39) {//TODO Test This
- prvFRV = true;
- usrFRV = 1;
- }
- //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);
- switch (d->getDescriptorTag ()) {
- case SI::PrivateDataSpecifierDescriptorTag:
- //esyslog ("prv: %d %08x\n", d->getLength (), d->getData ().FourBytes (2));
- if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x000000be)
- prvData = true;
- if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x4f545600) //OpenTV
- prvOTV = true;
- if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x46534154) //Freeview
- prvFRV = true;
- break;
- case 0x52:
- //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));
- if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x0000ffff)
- usrData = true;
- if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb600)) //SKY IT //TODO ugly!
- //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;
- case 0xc1: //MHW1, MHW2
+ LogD(4, 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;
+ bool prvOTV = false, prvFRV = false;
+ int usrOTV = 0, usrFRV = 0;
+ if (data[2]==0x39) {//TODO Test This
+ prvFRV = true;
+ usrFRV = 1;
+ LogD(4, 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));) {
+ LogD(4, 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));
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x000000be)
+ prvData = true;
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x4f545600) //OpenTV
+ prvOTV = true;
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x46534154) //Freeview
+ prvFRV = true;
+ break;
+ case 0x52:
+ //if (d->getLength () == 3 && d->getData ().FourBytes (2) == 0xb07ea882) {
+ if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb000))
+ UnprocessedFormat[NAGRA] = stream.getPid ();
+ break;
+ case 0x90:
+ //esyslog ("usr: %d %08x\n", d->getLength (), d->getData ().FourBytes (2));
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x0000ffff)
+ usrData = true;
+ if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb600)) //SKY IT //TODO ugly!
+ //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
+ usrOTV = SKY_UK;
+ //Format = SKY_UK;
+ break;
+ case 0xc1: //MHW1, MHW2
// esyslog("EEPGDEBUG:d->getDescriptorTAG:%d %08x\n",d->getLength(),d->getData().FourBytes(2));
- if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x50555348) //MHw1 Cyfra
- UnprocessedFormat[MHW1] = stream.getPid ();
- break;
- 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
- if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0x0100))
- usrFRV = 0x01;
- //01 = EIT pid 3842
- //03 04 = SDT Service Description Table pid 3841
- //07 = still undocumented, definition of buch of transport streams pid 3840
- //02 = ATSC reserved, find out what huffman encoded text is sent here! pid 3843
- //05 06 = TOT Time Offset Table pid 3844
- break;
-
-/* case 0xfe: //SKY_IT
- if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x534b5900) { //SKY_IT
- Format = SKY_IT;
- }
- break;*/
- default:
- break;
- }
- delete d;
- }
- if ((prvOTV) && ((usrOTV == SKY_IT) || (usrOTV == SKY_UK)))
- UnprocessedFormat[usrOTV] = stream.getPid ();
- else if (prvFRV)
- if (usrFRV == 0x01)
- UnprocessedFormat[FREEVIEW] = stream.getPid ();
- if (prvData && usrData)
- UnprocessedFormat[PREMIERE] = 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
-// if (Format == PREMIERE) { //FIXME for Premiere you should also stop scanning when found...
+ if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x50555348) //MHw1 Cyfra
+ UnprocessedFormat[MHW1] = stream.getPid ();
+ break;
+ case 0xc2: //MHW1, MHW2
+ if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x45504700) //MHw1 CanDigNL and CSat
+ UnprocessedFormat[MHW1] = stream.getPid ();
+ else if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x46494348) { //MHW2
+ UnprocessedFormat[MHW2] = stream.getPid ();
+ }
+ break;
+ case 0xd1: //Freeview
+ LogD(4, prep("case 0xd1: //Freeview"));
+ if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0x0100))
+ usrFRV = 0x01;
+ //01 = EIT pid 3842
+ //03 04 = SDT Service Description Table pid 3841
+ //07 = still undocumented, definition of buch of transport streams pid 3840
+ //02 = ATSC reserved, find out what huffman encoded text is sent here! pid 3843
+ //05 06 = TOT Time Offset Table pid 3844
+ break;
+
+ /* case 0xfe: //SKY_IT
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x534b5900) { //SKY_IT
+ Format = SKY_IT;
+ }
+ break;*/
+ default:
+ break;
+ }
+ delete d;
+ }
+ if ((prvOTV) && ((usrOTV == SKY_IT) || (usrOTV == SKY_UK)))
+ UnprocessedFormat[usrOTV] = stream.getPid ();
+ else if (prvFRV)
+ if (usrFRV == 0x01)
+ UnprocessedFormat[FREEVIEW] = stream.getPid ();
+ if (prvData && usrData)
+ UnprocessedFormat[PREMIERE] = stream.getPid ();
+ //TODO DPE DISH/BEV filters are always ON on provided transponders,
+ // but there is no knowledge for the loop of the data at the moment.
+ //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
+ } //for loop that walks through streams
NextPmt ();
pmtnext = 0;
-/* }
- else {
- Del (pmtpid, 0x02);
- Del (0, 0);
- pmtidx = 0;
- pmtnext = now + PMT_SCAN_IDLE;
- isyslog ("PMT scan forced idle\n");
- }*/
- } //checkCRC
- } //if pmtpid
+ /* }
+ else {
+ Del (pmtpid, 0x02);
+ Del (0, 0);
+ pmtidx = 0;
+ pmtnext = now + PMT_SCAN_IDLE;
+ isyslog ("PMT scan forced idle\n");
+ }*/
+ } //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:
+ case 0xA0: //TODO DPE test this missing break but it seems a bug
if ((Pid < 0x30) || (Pid > 0x37)) {
- SI::PremiereCIT cit (Data, false);
- if (cit.CheckCRCAndParse ()) {
- cSchedulesLock SchedulesLock (true, 10);
- cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock);
- if (Schedules) {
- int nCount = 0;
- SI::ExtendedEventDescriptors * ExtendedEventDescriptors = 0;
- SI::ShortEventDescriptor * ShortEventDescriptor = 0;
- char *order = 0, *rating = 0;
- {
- time_t firstTime = 0;
- SI::Descriptor * d;
- bool UseExtendedEventDescriptor = false;
- int LanguagePreferenceShort = -1;
- int LanguagePreferenceExt = -1;
- for (SI::Loop::Iterator it; (d = cit.eventDescriptors.getNext (it));) {
- switch (d->getDescriptorTag ()) {
- case 0xF0: // order information
- if (SetupPE.OrderInfo) {
- static const char *text[] = {
- trNOOP ("Ordernumber"),
- trNOOP ("Price"),
- trNOOP ("Ordering"),
- trNOOP ("SMS"),
- trNOOP ("WWW")
- };
- char buff[512];
- int p = 0;
- const unsigned char *data = d->getData ().getData () + 2;
- for (int i = 0; i < 5; i++) {
- int l = data[0];
- if (l > 0)
- p += snprintf (&buff[p], sizeof (buff) - p, "\n%s: %.*s", tr (text[i]), l, &data[1]);
- data += l + 1;
- }
- if (p > 0)
- order = strdup (buff);
- }
- break;
- case 0xF1: // parental rating
- if (SetupPE.RatingInfo) {
- char buff[512];
- int p = 0;
- const unsigned char *data = d->getData ().getData () + 2;
- p +=
- snprintf (&buff[p], sizeof (buff) - p, "\n%s: %d %s", tr ("Rating"), data[0] + 3, tr ("years"));
- data += 7;
- int l = data[0];
- if (l > 0)
- p += snprintf (&buff[p], sizeof (buff) - p, " (%.*s)", l, &data[1]);
- if (p > 0)
- rating = strdup (buff);
- }
- break;
- case SI::PremiereContentTransmissionDescriptorTag:
- if (nCount >= 0) {
- SI::PremiereContentTransmissionDescriptor * pct = (SI::PremiereContentTransmissionDescriptor *) d;
- nCount++;
- SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
- SI::Loop::Iterator it;
- if (pct->startDayLoop.getNext (sd, it)) {
- SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
- SI::Loop::Iterator it2;
- if (sd.startTimeLoop.getNext (st, it2)) {
- time_t StartTime = st.getStartTime (sd.getMJD ());
- if (nCount == 1)
- firstTime = StartTime;
- else if (firstTime < StartTime - 5 * 50 || firstTime > StartTime + 5 * 60)
- nCount = -1;
- }
- }
- }
- break;
- case SI::ExtendedEventDescriptorTag:
- {
- SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
- if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
- || !ExtendedEventDescriptors) {
- delete ExtendedEventDescriptors;
- ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
- UseExtendedEventDescriptor = true;
- }
- if (UseExtendedEventDescriptor) {
- ExtendedEventDescriptors->Add (eed);
- d = NULL; // so that it is not deleted
- }
- if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
- UseExtendedEventDescriptor = false;
- }
- break;
- case SI::ShortEventDescriptorTag:
- {
- SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
- if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
- || !ShortEventDescriptor) {
- delete ShortEventDescriptor;
- ShortEventDescriptor = sed;
- d = NULL; // so that it is not deleted
- }
- }
- break;
- default:
- break;
- }
- delete d;
- }
- }
-
- {
- bool Modified = false;
- int optCount = 0;
- unsigned int crc[3];
- crc[0] = cit.getContentId ();
- SI::PremiereContentTransmissionDescriptor * pct;
- for (SI::Loop::Iterator it;
- (pct =
- (SI::PremiereContentTransmissionDescriptor *) cit.eventDescriptors.getNext (it,
- SI::
- PremiereContentTransmissionDescriptorTag));)
- {
- int nid = pct->getOriginalNetworkId ();
- int tid = pct->getTransportStreamId ();
- int sid = pct->getServiceId ();
- if (SetupPE.FixEpg) {
- if (nid == 133) {
- if (tid == 0x03 && sid == 0xf0) {
- tid = 0x02;
- sid = 0xe0;
- }
- else if (tid == 0x03 && sid == 0xf1) {
- tid = 0x02;
- sid = 0xe1;
- }
- else if (tid == 0x03 && sid == 0xf5) {
- tid = 0x03;
- sid = 0xdc;
- }
- else if (tid == 0x04 && sid == 0xd2) {
- tid = 0x11;
- sid = 0xe2;
- }
- else if (tid == 0x11 && sid == 0xd3) {
- tid = 0x11;
- sid = 0xe3;
- }
- }
- }
- tChannelID channelID (Source (), nid, tid, sid);
- cChannel *channel = Channels.GetByChannelID (channelID, true);
-#ifdef USE_NOEPG
- // only use epg from channels not blocked by noEPG-patch
- if (!allowedEPG (channelID))
- continue;
-#endif /* NOEPG */
- if (!channel)
- continue;
-
- cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channelID);
- if (!pSchedule) {
- pSchedule = new cSchedule (channelID);
- Schedules->Add (pSchedule);
- }
-
- optCount++;
- SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
- int index = 0;
- for (SI::Loop::Iterator it; pct->startDayLoop.getNext (sd, it);) {
- int mjd = sd.getMJD ();
- SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
- for (SI::Loop::Iterator it2; sd.startTimeLoop.getNext (st, it2);) {
- time_t StartTime = st.getStartTime (mjd);
- time_t EndTime = StartTime + cit.getDuration ();
- int runningStatus = (StartTime < now
- && now < EndTime) ? SI::RunningStatusRunning : ((StartTime - 30 < now
- && now <
- StartTime) ? SI::
- RunningStatusStartsInAFewSeconds
- : SI::RunningStatusNotRunning);
- bool isOpt = false;
- if (index++ == 0 && nCount > 1)
- isOpt = true;
- crc[1] = isOpt ? optCount : 0;
- crc[2] = StartTime / STARTTIME_BIAS;
- tEventID EventId = ((('P' << 8) | 'W') << 16) | crc16 (0, (unsigned char *) crc, sizeof (crc));
- if (VERBOSE >= 2)
- isyslog ("%s R%d %04x/%.4x %d %d/%d %s +%d ", *channelID.ToString (), runningStatus,
- EventId & 0xFFFF, cit.getContentId (), index, isOpt, optCount,
- stripspace (ctime (&StartTime)), (int) cit.getDuration () / 60);
- if (EndTime + Setup.EPGLinger * 60 < now) {
- if (VERBOSE >= 2)
- isyslog ("(old)\n");
- continue;
- }
-
- bool newEvent = false;
- cEvent *pEvent = (cEvent *) pSchedule->GetEvent (EventId, -1);
- if (!pEvent) {
- if (VERBOSE >= 2)
- isyslog ("(new)\n");
- pEvent = new cEvent (EventId);
- if (!pEvent)
- continue;
- newEvent = true;
- }
- else {
- if (VERBOSE >= 2)
- isyslog ("(upd)\n");
- pEvent->SetSeen ();
- if (pEvent->TableID () == 0x00 || pEvent->Version () == cit.getVersionNumber ()) {
- if (pEvent->RunningStatus () != runningStatus)
- pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
- continue;
- }
- }
- pEvent->SetEventID (EventId);
- pEvent->SetTableID (Tid);
- pEvent->SetVersion (cit.getVersionNumber ());
- pEvent->SetStartTime (StartTime);
- pEvent->SetDuration (cit.getDuration ());
-
- if (ShortEventDescriptor) {
- char buffer[256];
- ShortEventDescriptor->name.getText (buffer, sizeof (buffer));
- if (isOpt) {
- char buffer2[sizeof (buffer) + 32];
- snprintf (buffer2, sizeof (buffer2), optPats[SetupPE.OptPat], buffer, optCount);
- pEvent->SetTitle (buffer2);
- }
- else
- pEvent->SetTitle (buffer);
- if (VERBOSE >= 2)
- isyslog ("title: %s\n", pEvent->Title ());
- pEvent->SetShortText (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)));
- }
- if (ExtendedEventDescriptors) {
- char buffer[ExtendedEventDescriptors->getMaximumTextLength (": ") + 1];
- pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
- }
- if (order || rating) {
- int len = (pEvent->Description ()? strlen (pEvent->Description ()) : 0) +
- (order ? strlen (order) : 0) + (rating ? strlen (rating) : 0);
- char buffer[len + 32];
- buffer[0] = 0;
- if (pEvent->Description ())
- strcat (buffer, pEvent->Description ());
- if (rating)
- strcat (buffer, rating);
- if (order)
- strcat (buffer, order);
- pEvent->SetDescription (buffer);
- }
-
- if (newEvent)
- pSchedule->AddEvent (pEvent);
-
- pEvent->FixEpgBugs ();
- if (pEvent->RunningStatus () != runningStatus)
- pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
- pSchedule->DropOutdated (StartTime, EndTime, Tid, cit.getVersionNumber ());
- Modified = true;
- }
- }
- if (Modified) {
- pSchedule->Sort ();
- Schedules->SetModified (pSchedule);
- }
- delete pct;
- }
- }
- delete ExtendedEventDescriptors;
- delete ShortEventDescriptor;
- free (order);
- free (rating);
- }
- } //if checkcrcandpars
- break;
- } //if citpid == 0xb11 Premiere
+ ProcessPremiere(Data);
+ break;
+ } //if citpid == 0xb11 Premiere
case 0xa1:
case 0xa2:
case 0xa3:
Result = GetTitlesSKYBOX (Data, Length - 4);
- if (Result != 1) //when fatal error or finished
- Del (Pid, 0xa0, 0xfc); //kill filter
- if (Result == 0) { //fatal error
- esyslog ("EEPG: Fatal error reading titles.");
- ProcessNextFormat (); //and go process other formats
+ if (Result != 1) //when fatal error or finished
+ Del (Pid, 0xa0, 0xfc); //kill filter
+ if (Result == 0) { //fatal error
+ esyslog ("EEPG: Fatal error reading titles.");
+ ProcessNextFormat (); //and go process other formats
}
if (Result == 2)
- AddFilter (Pid + 0x10, 0xa8, 0xfc); //Set filter that processes summaries of this batch
+ AddFilter (Pid + 0x10, 0xa8, 0xfc); //Set filter that processes summaries of this batch
break;
case 0xa8:
case 0xa9:
case 0xaa:
case 0xab:
Result = GetSummariesSKYBOX (Data, Length - 4);
- if (Result != 1) //when fatal error or finished
- Del (Pid, 0xa8, 0xfc); //kill filter
+ if (Result != 1) //when fatal error or finished
+ Del (Pid, 0xa8, 0xfc); //kill filter
if (Result == 0) {
- esyslog ("EEPG: Fatal error reading summaries.");
- ProcessNextFormat ();
+ esyslog ("EEPG: Fatal error reading summaries.");
+ ProcessNextFormat ();
}
if (Result == 2) {
- LoadIntoSchedule ();
- if (Pid < 0x47) //this is not the last batch//FIXME chaining is easy on the PIDs and the CPU, but error when Pid,Tid is not used at the moment...
- AddFilter (Pid - 0x0F, 0xa0, 0xfc); //next pid, first tid
- else //last pid was processed
- ProcessNextFormat ();
+ LoadIntoSchedule ();
+ if (Pid < 0x47) //this is not the last batch//FIXME chaining is easy on the PIDs and the CPU, but error when Pid,Tid is not used at the moment...
+ AddFilter (Pid - 0x0F, 0xa0, 0xfc); //next pid, first tid
+ else //last pid was processed
+ ProcessNextFormat ();
}
break;
case 0x90:
if (Pid == 0xd2) {
- Result = GetTitlesMHW1 (Data, Length);
- if (Result != 1) //fatal error or last processed
- Del (Pid, Tid);
- if (Result == 0) {
- esyslog ("EEPG: Fatal error reading titles.");
- ProcessNextFormat ();
- }
- if (Result == 2)
- AddFilter (0xd3, 0x90); //SummariesMHW1
- }
- else if (Pid == 0xd3) {
- Result = GetSummariesMHW1 (Data, Length);
- if (Result != 1) //fatal error or last processed
- Del (Pid, Tid);
- if (Result == 0) {
- esyslog ("EEPG: Fatal error reading summaries.");
- }
- if (Result == 2) {
- LoadIntoSchedule ();
- }
- if (Result != 1) {
- ProcessNextFormat ();
- }
+ Result = GetTitlesMHW1 (Data, Length);
+ if (Result != 1) //fatal error or last processed
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading titles.");
+ ProcessNextFormat ();
+ }
+ if (Result == 2)
+ AddFilter (0xd3, 0x90); //SummariesMHW1
+ } else if (Pid == 0xd3) {
+ Result = GetSummariesMHW1 (Data, Length);
+ if (Result != 1) //fatal error or last processed
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading summaries.");
+ }
+ if (Result == 2) {
+ LoadIntoSchedule ();
+ }
+ if (Result != 1) {
+ ProcessNextFormat ();
+ }
}
break;
- case 0xc8: //GetChannelsMHW2 or GetThemesMHW2
+ case 0xc8: //GetChannelsMHW2 or GetThemesMHW2
if (Pid == 0x231) {
- if (Data[3] == 0x01) { //Themes it will be
- Result = GetThemesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
- //break;
- if (Result != 1)
- EndThemes = true; //also set Endthemes on true on fatal error
- } //if Data
- else if (Data[3] == 0x00) { //Channels it will be
- Result = GetChannelsMHW (Data, Length, 2); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
- if (Result != 1)
- EndChannels = true; //always remove filter, code 1 should never be returned since MHW2 always reads all channels..
- ChannelsOk = (Result == 2);
- }
- if (EndChannels && EndThemes) { //those are only set withing MHW2
- Del (0x231, 0xc8); //stop reading MHW2 themes and channels
- if (ChannelsOk) //No channels = fatal, no themes = nonfatal
- AddFilter (0x234, 0xe6); //start reading MHW2 titles
- else {
- esyslog ("EEPG: Fatal error reading channels.");
- ProcessNextFormat ();
- }
- }
- } //if Pid == 0x231
+ if (Data[3] == 0x01) { //Themes it will be
+ Result = GetThemesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ //break;
+ if (Result != 1)
+ EndThemes = true; //also set Endthemes on true on fatal error
+ } //if Data
+ else if (Data[3] == 0x00) { //Channels it will be
+ Result = GetChannelsMHW (Data, Length, 2); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ if (Result != 1)
+ EndChannels = true; //always remove filter, code 1 should never be returned since MHW2 always reads all channels..
+ ChannelsOk = (Result == 2);
+ }
+ if (EndChannels && EndThemes) { //those are only set withing MHW2
+ Del (0x231, 0xc8); //stop reading MHW2 themes and channels
+ if (ChannelsOk) //No channels = fatal, no themes = nonfatal
+ AddFilter (0x234, 0xe6); //start reading MHW2 titles
+ else {
+ esyslog ("EEPG: Fatal error reading channels.");
+ ProcessNextFormat ();
+ }
+ }
+ } //if Pid == 0x231
break;
case 0x91:
- Result = GetChannelsMHW (Data, Length, 1); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
- Del (Pid, Tid); //always remove filter, code 1 should never be returned since MHW1 always reads all channels...
+ Result = GetChannelsMHW (Data, Length, 1); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ Del (Pid, Tid); //always remove filter, code 1 should never be returned since MHW1 always reads all channels...
if (Result == 2)
- AddFilter (0xd2, 0x90); //TitlesMHW1
+ AddFilter (0xd2, 0x90); //TitlesMHW1
else {
- esyslog ("EEPG: Fatal error reading channels.");
- ProcessNextFormat ();
+ esyslog ("EEPG: Fatal error reading channels.");
+ ProcessNextFormat ();
}
break;
case 0x92:
- Result = GetThemesMHW1 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ Result = GetThemesMHW1 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
if (Result != 1)
- Del (Pid, Tid);
+ Del (Pid, Tid);
if (Result == 2)
- AddFilter (0xd3, 0x91); //ChannelsMHW1
+ AddFilter (0xd3, 0x91); //ChannelsMHW1
else {
- esyslog ("EEPG: Fatal error reading themes."); //doesnt have to be fatal...
- ProcessNextFormat ();
+ esyslog ("EEPG: Fatal error reading themes."); //doesnt have to be fatal...
+ ProcessNextFormat ();
}
break;
- case 0xe6: //TitlesMHW2
+ case 0xe6: //TitlesMHW2
if (Pid == 0x234) {
- Result = GetTitlesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
- if (Result != 1)
- Del (Pid, Tid);
- if (Result == 0) {
- esyslog ("EEPG: Fatal error reading titles.");
- ProcessNextFormat ();
- }
- if (Result == 2)
- AddFilter (0x236, 0x96); //start reading MHW2 summaries....
+ Result = GetTitlesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ if (Result != 1)
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading titles.");
+ ProcessNextFormat ();
+ }
+ if (Result == 2)
+ AddFilter (0x236, 0x96); //start reading MHW2 summaries....
}
break;
- case 0x96: //Summaries MHW2
+ case 0x96: //Summaries MHW2
if (Pid == 0x236) {
- Result = GetSummariesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
- if (Result != 1)
- Del (Pid, Tid);
- if (Result == 0) {
- esyslog ("EEPG: Fatal error reading summaries.");
- }
- if (Result == 2)
- LoadIntoSchedule ();
- if (Result != 1) {
- ProcessNextFormat ();
- }
- } //if pid
+ Result = GetSummariesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ if (Result != 1)
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading summaries.");
+ }
+ if (Result == 2)
+ LoadIntoSchedule ();
+ if (Result != 1) {
+ ProcessNextFormat ();
+ }
+ } //if pid
break;
- case 0x4a: //Sky channels
+ case 0x4a: //Sky channels
if (Pid == 0x11) {
- Result = GetChannelsSKYBOX (Data, Length - 4);
- if (Result != 1) //only breakoff on completion or error; do NOT clean up after success, because then not all bouquets will be read
- Del (Pid, Tid); //Read all channels, clean up filter
- if (Result == 2) {
- GetThemesSKYBOX (); //Sky Themes from file; must be called AFTER first channels to have lThemes initialized FIXME
- if (ReadFileDictionary ())
- AddFilter (0x30, 0xa0, 0xfc); //SKY Titles batch 0 of 7
- else {
- esyslog ("EEPG: Fatal error reading huffman table.");
- ProcessNextFormat ();
- }
- }
-
- } //if Pid == 0x11
+ Result = GetChannelsSKYBOX (Data, Length - 4);
+ if (Result != 1) //only breakoff on completion or error; do NOT clean up after success, because then not all bouquets will be read
+ Del (Pid, Tid); //Read all channels, clean up filter
+ if (Result == 2) {
+ GetThemesSKYBOX (); //Sky Themes from file; must be called AFTER first channels to have lThemes initialized FIXME
+ if (InitDictionary ())
+ AddFilter (0x30, 0xa0, 0xfc); //SKY Titles batch 0 of 7
+ else {
+ esyslog ("EEPG: Fatal error reading huffman table.");
+ ProcessNextFormat ();
+ }
+ }
+
+ } //if Pid == 0x11
break;
- case 0xb0: //NagraGuide
+ case 0xb0: //NagraGuide
if (Pid == 0xc8) {
- Result = GetNagra (Data, Length);
- if (Result != 1)
- Del (Pid, Tid);
- if (Result == 0) {
- esyslog ("EEPG: Fatal error processing NagraGuide. End of processing.");
- }
- if (Result == 2) {
- ProcessNagra ();
- cSchedules::Cleanup (true); //deletes all past events
- isyslog ("EEPG: Ended processing Nagra");
- }
- if (Result != 1) {
- ProcessNextFormat ();
- }
+ Result = GetNagra (Data, Length);
+ if (Result != 1)
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error processing NagraGuide. End of processing.");
+ }
+ if (Result == 2) {
+ ProcessNagra ();
+ cSchedules::Cleanup (true); //deletes all past events
+ isyslog ("EEPG: Ended processing Nagra");
+ }
+ if (Result != 1) {
+ ProcessNextFormat ();
+ }
}
break;
@@ -3998,50 +3999,311 @@ 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;
default:
break;
- } //end switch
- } //closes SOURCE()
-} //end of closing
+ } //end switch
+ } //closes SOURCE()
+} //end of closing
// --- cPluginEEPG ------------------------------------------------------
+void cFilterEEPG::ProcessPremiere(const u_char *& Data)
+
+{
+
+ SI::PremiereCIT cit(Data, false);
+
+ if (cit.CheckCRCAndParse ()) {
+ cSchedulesLock SchedulesLock (true, 10);
+ cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+ if (Schedules) {
+ int now = time (0);
+ int nCount = 0;
+ int nRating = 0;
+ unsigned char Tid = 0xa0; // TODO maybe default TableID
+ SI::ExtendedEventDescriptors * ExtendedEventDescriptors = 0;
+ SI::ShortEventDescriptor * ShortEventDescriptor = 0;
+ char *order = 0, *rating = 0;
+ {
+ time_t firstTime = 0;
+ SI::Descriptor * d;
+ bool UseExtendedEventDescriptor = false;
+ int LanguagePreferenceShort = -1;
+ int LanguagePreferenceExt = -1;
+ for (SI::Loop::Iterator it; (d = cit.eventDescriptors.getNext (it));) {
+ switch (d->getDescriptorTag ()) {
+ case 0xF0: // order information
+ if (SetupPE.OrderInfo) {
+ static const char *text[] = {
+ trNOOP ("Ordernumber"),
+ trNOOP ("Price"),
+ trNOOP ("Ordering"),
+ trNOOP ("SMS"),
+ trNOOP ("WWW")
+ };
+ char buff[512];
+ int p = 0;
+ const unsigned char *data = d->getData ().getData () + 2;
+ for (int i = 0; i < 5; i++) {
+ int l = data[0];
+ if (l > 0)
+ p += snprintf (&buff[p], sizeof (buff) - p, "\n%s: %.*s", tr (text[i]), l, &data[1]);
+ data += l + 1;
+ }
+ if (p > 0)
+ order = strdup (buff);
+ }
+ break;
+ case 0xF1: // parental rating
+ if (SetupPE.RatingInfo) {
+ char buff[512];
+ int p = 0;
+ const unsigned char *data = d->getData ().getData () + 2;
+ nRating = data[0] + 3;
+ p += snprintf (&buff[p], sizeof (buff) - p, "\n%s: %d %s", tr ("Rating"), nRating, tr ("years"));
+ data += 7;
+ int l = data[0];
+ if (l > 0)
+ p += snprintf (&buff[p], sizeof (buff) - p, " (%.*s)", l, &data[1]);
+ if (p > 0)
+ rating = strdup (buff);
+ }
+ break;
+ case SI::PremiereContentTransmissionDescriptorTag:
+ if (nCount >= 0) {
+ SI::PremiereContentTransmissionDescriptor * pct = (SI::PremiereContentTransmissionDescriptor *) d;
+ nCount++;
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
+ SI::Loop::Iterator it;
+ if (pct->startDayLoop.getNext (sd, it)) {
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
+ SI::Loop::Iterator it2;
+ if (sd.startTimeLoop.getNext (st, it2)) {
+ time_t StartTime = st.getStartTime (sd.getMJD ());
+ if (nCount == 1)
+ firstTime = StartTime;
+ else if (firstTime < StartTime - 5 * 50 || firstTime > StartTime + 5 * 60)
+ nCount = -1;
+ }
+ }
+ }
+ break;
+ case SI::ExtendedEventDescriptorTag: {
+ SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+ || !ExtendedEventDescriptors) {
+ delete ExtendedEventDescriptors;
+ ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+ UseExtendedEventDescriptor = true;
+ }
+ if (UseExtendedEventDescriptor) {
+ ExtendedEventDescriptors->Add (eed);
+ d = NULL; // so that it is not deleted
+ }
+ if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
+ UseExtendedEventDescriptor = false;
+ }
+ break;
+ case SI::ShortEventDescriptorTag: {
+ SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+ || !ShortEventDescriptor) {
+ delete ShortEventDescriptor;
+ ShortEventDescriptor = sed;
+ d = NULL; // so that it is not deleted
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ delete d;
+ }
+ }
+
+ {
+ bool Modified = false;
+ int optCount = 0;
+ unsigned int crc[3];
+ crc[0] = cit.getContentId ();
+ SI::PremiereContentTransmissionDescriptor * pct;
+ for (SI::Loop::Iterator it;
+ (pct =
+ (SI::PremiereContentTransmissionDescriptor *) cit.eventDescriptors.getNext (it,
+ SI::
+ PremiereContentTransmissionDescriptorTag));) {
+ int nid = pct->getOriginalNetworkId ();
+ int tid = pct->getTransportStreamId ();
+ int sid = pct->getServiceId ();
+ if (SetupPE.FixEpg) {
+ if (nid == 133) {
+ if (tid == 0x03 && sid == 0xf0) {
+ tid = 0x02;
+ sid = 0xe0;
+ } else if (tid == 0x03 && sid == 0xf1) {
+ tid = 0x02;
+ sid = 0xe1;
+ } else if (tid == 0x03 && sid == 0xf5) {
+ tid = 0x03;
+ sid = 0xdc;
+ } else if (tid == 0x04 && sid == 0xd2) {
+ tid = 0x11;
+ sid = 0xe2;
+ } else if (tid == 0x11 && sid == 0xd3) {
+ tid = 0x11;
+ sid = 0xe3;
+ }
+ }
+ }
+ tChannelID channelID (Source (), nid, tid, sid);
+ cChannel *channel = Channels.GetByChannelID (channelID, true);
+#ifdef USE_NOEPG
+ // only use epg from channels not blocked by noEPG-patch
+ if (!allowedEPG (channelID))
+ continue;
+#endif /* NOEPG */
+
+ if (!channel)
+ continue;
+
+ cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channelID);
+ if (!pSchedule) {
+ pSchedule = new cSchedule (channelID);
+ Schedules->Add (pSchedule);
+ }
+
+ optCount++;
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
+ int index = 0;
+ for (SI::Loop::Iterator it; pct->startDayLoop.getNext (sd, it);) {
+ int mjd = sd.getMJD ();
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
+ for (SI::Loop::Iterator it2; sd.startTimeLoop.getNext (st, it2);) {
+ time_t StartTime = st.getStartTime (mjd);
+ time_t EndTime = StartTime + cit.getDuration ();
+ int runningStatus = (StartTime < now
+ && now < EndTime) ? SI::RunningStatusRunning : ((StartTime - 30 < now
+ && now <
+ StartTime) ? SI::
+ RunningStatusStartsInAFewSeconds
+ : SI::RunningStatusNotRunning);
+ bool isOpt = false;
+ if (index++ == 0 && nCount > 1)
+ isOpt = true;
+ crc[1] = isOpt ? optCount : 0;
+ crc[2] = StartTime / STARTTIME_BIAS;
+ tEventID EventId = ((('P' << 8) | 'W') << 16) | crc16 (0, (unsigned char *) crc, sizeof (crc));
+ LogI(2, "%s R%d %04x/%.4x %d %d/%d %s +%d ", *channelID.ToString (), runningStatus,
+ EventId & 0xFFFF, cit.getContentId (), index, isOpt, optCount,
+ stripspace (ctime (&StartTime)), (int) cit.getDuration () / 60);
+ if (EndTime + Setup.EPGLinger * 60 < now) {
+ LogI(2, "(old)\n");
+ continue;
+ }
+
+ bool newEvent = false;
+ cEvent *pEvent = (cEvent *) pSchedule->GetEvent (EventId, -1);
+ if (!pEvent) {
+ LogI(2, "(new)\n");
+ pEvent = new cEvent (EventId);
+ if (!pEvent)
+ continue;
+ newEvent = true;
+ } else {
+ LogI(2, "(upd)\n");
+ pEvent->SetSeen ();
+ if (pEvent->TableID () == 0x00 || pEvent->Version () == cit.getVersionNumber ()) {
+ if (pEvent->RunningStatus () != runningStatus)
+ pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
+ continue;
+ }
+ }
+ pEvent->SetEventID (EventId);
+ pEvent->SetTableID (Tid);
+ pEvent->SetVersion (cit.getVersionNumber ());
+ pEvent->SetStartTime (StartTime);
+ pEvent->SetDuration (cit.getDuration ());
+
+ if (ShortEventDescriptor) {
+ char buffer[256];
+ ShortEventDescriptor->name.getText (buffer, sizeof (buffer));
+ if (isOpt) {
+ char buffer2[sizeof (buffer) + 32];
+ snprintf (buffer2, sizeof (buffer2), optPats[SetupPE.OptPat], buffer, optCount);
+ pEvent->SetTitle (buffer2);
+ } else
+ pEvent->SetTitle (buffer);
+ LogI(2, "title: %s\n", pEvent->Title ());
+ pEvent->SetShortText (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)));
+ }
+ if (ExtendedEventDescriptors) {
+ char buffer[ExtendedEventDescriptors->getMaximumTextLength (": ") + 1];
+ pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
+ }
+ if (order || rating) {
+ int len = (pEvent->Description ()? strlen (pEvent->Description ()) : 0) +
+ (order ? strlen (order) : 0) + (rating ? strlen (rating) : 0);
+ char buffer[len + 32];
+ buffer[0] = 0;
+ if (pEvent->Description ())
+ strcat (buffer, pEvent->Description ());
+ if (rating) {
+ strcat (buffer, rating);
+ pEvent->SetParentalRating(nRating);
+ }
+ if (order)
+ strcat (buffer, order);
+ pEvent->SetDescription (buffer);
+ }
+
+ if (newEvent)
+ pSchedule->AddEvent (pEvent);
+
+ pEvent->FixEpgBugs ();
+ if (pEvent->RunningStatus () != runningStatus)
+ pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
+ pSchedule->DropOutdated (StartTime, EndTime, Tid, cit.getVersionNumber ());
+ Modified = true;
+ }
+ }
+ if (Modified) {
+ pSchedule->Sort ();
+ Schedules->SetModified (pSchedule);
+ }
+ delete pct;
+ }
+ }
+ delete ExtendedEventDescriptors;
+ delete ShortEventDescriptor;
+ free (order);
+ free (rating);
+ }
+ }
+
+}
+
+
class cPluginEEPG:public cPlugin
{
private:
- struct
- {
+ struct {
cFilterEEPG *filter;
cDevice *device;
} epg[MAXDVBDEVICES];
+
+ void CheckCreateFile(const char* Name, const char *fileContent[]);
+
public:
cPluginEEPG (void);
- virtual const char *Version (void)
- {
+ virtual const char *Version (void) {
return VERSION;
}
- virtual const char *Description (void)
- {
+ virtual const char *Description (void) {
return tr (DESCRIPTION);
}
virtual bool Start (void);
@@ -4055,6 +4317,30 @@ cPluginEEPG::cPluginEEPG (void)
memset (epg, 0, sizeof (epg));
}
+void cPluginEEPG::CheckCreateFile(const char* Name, const char *fileContent[])
+{
+ FILE *File;
+ string FileName = string(ConfDir) + "/" + Name;
+ File = fopen(FileName.c_str(), "r");
+ if (File == NULL) {
+ LogE (0, prep("Error opening file '%s', %s"), FileName.c_str(), strerror (errno));
+ File = fopen (FileName.c_str(), "w");
+ if (File == NULL) {
+ LogE (0, prep("Error creating file '%s', %s"), FileName.c_str(), strerror (errno));
+ } else {
+ int i = 0;
+ while (fileContent[i] != NULL) {
+ fprintf (File, "%s\n", fileContent[i]);
+ i++;
+ }
+ LogI (0, prep("Success creating file '%s'"), FileName.c_str());
+ fclose (File);
+ }
+ } else {
+ fclose (File);
+ }
+}
+
bool cPluginEEPG::Start (void)
{
#if APIVERSNUM < 10507
@@ -4070,199 +4356,47 @@ bool cPluginEEPG::Start (void)
}
ConfDir = NULL;
// Initialize any background activities the plugin shall perform.
- char *FileName;
DIR *ConfigDir;
- FILE *File;
if (ConfDir == NULL) {
- asprintf (&ConfDir, "%s/eepg", cPlugin::ConfigDirectory ());
+ Asprintf (&ConfDir, "%s/eepg", cPlugin::ConfigDirectory ());
}
ConfigDir = opendir (ConfDir);
if (ConfigDir == NULL) {
esyslog ("EEPG: Error opening directory '%s', %s", ConfDir, strerror (errno));
if (mkdir (ConfDir, 0777) < 0) {
esyslog ("EEPG: Error creating directory '%s', %s", ConfDir, strerror (errno));
- }
- else {
+ } else {
isyslog ("EEPG: Success creating directory '%s'", ConfDir);
}
}
- asprintf (&FileName, "%s/%s", ConfDir, EEPG_FILE_EQUIV);
- File = fopen (FileName, "r");
- if (File == NULL) {
- esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
- File = fopen (FileName, "w");
- if (File == NULL) {
- esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
- }
- else {
- int i = 0;
- while (FileEquivalences[i] != NULL) {
- fprintf (File, "%s\n", FileEquivalences[i]);
- i++;
- }
- isyslog ("EEPG: Success creating file '%s'", FileName);
- fclose (File);
- }
- }
- else {
- fclose (File);
- }
- free (FileName);
- asprintf (&FileName, "%s/%s", ConfDir, "sky_it.dict");
- File = fopen (FileName, "r");
- if (File == NULL) {
- esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
- File = fopen (FileName, "w");
- if (File == NULL) {
- esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
- }
- else {
- int i = 0;
- while (SkyItDictionary[i] != NULL) {
- fprintf (File, "%s\n", SkyItDictionary[i]);
- i++;
- }
- isyslog ("EEPG: Success creating file '%s'", FileName);
- fclose (File);
- }
- }
- else {
- fclose (File);
- }
- free (FileName);
- asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.dict");
- File = fopen (FileName, "r");
- if (File == NULL) {
- esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
- File = fopen (FileName, "w");
- if (File == NULL) {
- esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
- }
- else {
- int i = 0;
- while (SkyUkDictionary[i] != NULL) {
- fprintf (File, "%s\n", SkyUkDictionary[i]);
- i++;
- }
- isyslog ("EEPG: Success creating file '%s'", FileName);
- fclose (File);
- }
- }
- else {
- fclose (File);
- }
- free (FileName);
- asprintf (&FileName, "%s/%s", ConfDir, "sky_it.themes");
- File = fopen (FileName, "r");
- if (File == NULL) {
- esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
- File = fopen (FileName, "w");
- if (File == NULL) {
- esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
- }
- else {
- for (int i = 0; i < 256; i++) {
- if (SkyItThemes[i]) {
- fprintf (File, "0x%02x=%s\n", i, SkyItThemes[i]);
- }
- else {
- fprintf (File, "0x%02x=\n", i);
- }
- }
- isyslog ("EEPG: Success creating file '%s'", FileName);
- fclose (File);
- }
- }
- else {
- fclose (File);
- }
- free (FileName);
- asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.themes");
- File = fopen (FileName, "r");
- if (File == NULL) {
- esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
- File = fopen (FileName, "w");
- if (File == NULL) {
- esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
- }
- else {
- for (int i = 0; i < 256; i++) {
- if (SkyUkThemes[i]) {
- fprintf (File, "0x%02x=%s\n", i, SkyUkThemes[i]);
- }
- else {
- fprintf (File, "0x%02x=\n", i);
- }
- }
- isyslog ("EEPG: Success creating file '%s'", FileName);
- fclose (File);
- }
- }
- else {
- fclose (File);
- }
- free (FileName);
- asprintf (&FileName, "%s/%s", ConfDir, "freesat.t1");
- File = fopen (FileName, "r");
- if (File == NULL) {
- esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
- File = fopen (FileName, "w");
- if (File == NULL) {
- esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
- }
- else {
- int i = 0;
- while (FreesatT1[i] != NULL) {
- fprintf (File, "%s\n", FreesatT1[i]);
- i++;
- }
- isyslog ("EEPG: Success creating file '%s'", FileName);
- fclose (File);
- }
- }
- else {
- fclose (File);
- }
- free (FileName);
- asprintf (&FileName, "%s/%s", ConfDir, "freesat.t2");
- File = fopen (FileName, "r");
- if (File == NULL) {
- esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
- File = fopen (FileName, "w");
- if (File == NULL) {
- esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
- }
- else {
- int i = 0;
- while (FreesatT2[i] != NULL) {
- fprintf (File, "%s\n", FreesatT2[i]);
- i++;
- }
- isyslog ("EEPG: Success creating file '%s'", FileName);
- fclose (File);
- }
- }
- else {
- fclose (File);
- }
- free (FileName);
-
- //store all available sources, so when a channel is not found on current satellite, we can look for alternate sat positions.
+ CheckCreateFile(EEPG_FILE_EQUIV, FileEquivalences);
+ CheckCreateFile("sky_it.dict", SkyItDictionary);
+ CheckCreateFile("sky_uk.dict", SkyUkDictionary);
+ CheckCreateFile("sky_it.themes", SkyItThemes);
+ CheckCreateFile("sky_uk.themes", SkyUkThemes);
+ CheckCreateFile("freesat.t1", FreesatT1);
+ CheckCreateFile("freesat.t2", FreesatT2);
+ CheckCreateFile("sky_uk.themes", SkyUkThemes);
+
+ sky_tables[0] = NULL;
+ sky_tables[1] = NULL;
+ tables[0][0] = NULL;
+ //store all available sources, so when a channel is not found on current satellite, we can look for alternate sat positions.
//perhaps this can be done smarter through existing VDR function???
for (cChannel * Channel = Channels.First (); Channel; Channel = Channels.Next (Channel)) {
if (!Channel->GroupSep ()) {
bool found = false;
for (int i = 0; (i < NumberOfAvailableSources) && (!found); i++)
- found = (Channel->Source () == AvailableSources[i]);
+ found = (Channel->Source () == AvailableSources[i]);
if (!found)
- AvailableSources[NumberOfAvailableSources++] = Channel->Source ();
+ AvailableSources[NumberOfAvailableSources++] = Channel->Source ();
}
}
- if (VERBOSE >= 3)
+ if (CheckLevel(3))
for (int i = 0; i < NumberOfAvailableSources; i++)
isyslog ("EEPG: Available sources:%s.", *cSource::ToString (AvailableSources[i]));
-
+ closedir(ConfigDir);
return true;
}
@@ -4276,10 +4410,17 @@ void cPluginEEPG::Stop (void)
epg[i].device = 0;
epg[i].filter = 0;
}
+
// Clean up after yourself!
if (ConfDir) {
free (ConfDir);
}
+ if (sky_tables[0]) {
+ free(sky_tables[0]);
+ }
+ if (sky_tables[1]) {
+ free(sky_tables[1]);
+ }
}
cMenuSetupPage *cPluginEEPG::SetupMenu (void)
@@ -4289,6 +4430,18 @@ cMenuSetupPage *cPluginEEPG::SetupMenu (void)
bool cPluginEEPG::SetupParse (const char *Name, const char *Value)
{
+// LogF(0, "!!!! Dime test LogF");
+// LogF(0, "!!!! Dime test LogF %d", 2);
+// LogI(0, "!!!! Dime test LogI");
+// LogI(0, "!!!! Dime test LogI %d", 2);
+// LogI(0, prep2("!!!! Dime test prep"));
+// LogI(0, prep2("!!!! Dime test prep %d"), 2);
+// LogD(0, "!!!! Dime test LogD");
+// LogD(0, "!!!! Dime test LogD %d", 2);
+// LogE(0, "!!!! Dime test LogE");
+// LogE(0, "!!!! Dime test LogE %d", 2);
+
+
if (!strcasecmp (Name, "OptionPattern"))
SetupPE.OptPat = atoi (Value);
else if (!strcasecmp (Name, "OrderInfo"))
@@ -4299,9 +4452,13 @@ bool cPluginEEPG::SetupParse (const char *Name, const char *Value)
SetupPE.FixEpg = atoi (Value);
else if (!strcasecmp (Name, "DisplayMessage"))
SetupPE.DisplayMessage = atoi (Value);
+#ifdef DEBUG
+ else if (!strcasecmp (Name, "LogLevel"))
+ SetupPE.LogLevel = atoi (Value);
+#endif
else
return false;
return true;
}
-VDRPLUGINCREATOR (cPluginEEPG); // Don't touch this!
+VDRPLUGINCREATOR (cPluginEEPG); // Don't touch this!