diff options
-rw-r--r-- | config.c | 43 | ||||
-rw-r--r-- | config.h | 11 | ||||
-rw-r--r-- | epgfixer.c | 24 | ||||
-rw-r--r-- | epghandler.c | 266 | ||||
-rw-r--r-- | epghandler.h | 6 | ||||
-rw-r--r-- | regexp.c | 74 | ||||
-rw-r--r-- | regexp.h | 1 | ||||
-rw-r--r-- | setup_menu.c | 4 | ||||
-rw-r--r-- | tools.c | 272 | ||||
-rw-r--r-- | tools.h | 15 |
10 files changed, 351 insertions, 365 deletions
@@ -5,8 +5,6 @@ * */ -#include <stdlib.h> -#include <string.h> #include "config.h" /* Global instance */ @@ -25,44 +23,3 @@ cEpgfixerSetup::cEpgfixerSetup() components = 0; striphtml = 0; } - -cString cEpgfixerSetup::m_ProcessedArgs; - -bool cEpgfixerSetup::ProcessArg(const char *Name, const char *Value) -{ - if (SetupParse(Name, Value)) { - m_ProcessedArgs = cString::sprintf("%s%s ", *m_ProcessedArgs ? *m_ProcessedArgs : " ", Name); - return true; - } - return false; -} - -bool cEpgfixerSetup::ProcessArgs(int argc, char *argv[]) -{ - return true; -} - -bool cEpgfixerSetup::SetupParse(const char *Name, const char *Value) -{ - const char *pt; - if (*m_ProcessedArgs && NULL != (pt = strstr(m_ProcessedArgs + 1, Name)) && - *(pt - 1) == ' ' && *(pt + strlen(Name)) == ' ') { - dsyslog("Skipping configuration entry %s=%s (overridden in command line)", Name, Value); - return true; - } - - if (!strcasecmp(Name, "RemoveQuotesFromShortText")) quotedshorttext = atoi(Value); - else if (!strcasecmp(Name, "MoveDescriptionFromShortText")) blankbeforedescription = atoi(Value); - else if (!strcasecmp(Name, "RemoveRepeatedTitleFromShortText")) repeatedtitle = atoi(Value); - else if (!strcasecmp(Name, "RemoveDoubleQuotesFromShortText")) doublequotedshorttext = atoi(Value); - else if (!strcasecmp(Name, "RemoveUselessFormatting")) removeformatting = atoi(Value); - else if (!strcasecmp(Name, "MoveLongShortTextToDescription")) longshorttext = atoi(Value); - else if (!strcasecmp(Name, "PreventEqualShortTextAndDescription")) equalshorttextanddescription = atoi(Value); - else if (!strcasecmp(Name, "ReplaceBackticksWithSingleQuotes")) nobackticks = atoi(Value); - else if (!strcasecmp(Name, "FixStreamComponentDescriptions")) components = atoi(Value); - else if (!strcasecmp(Name, "StripHTMLEntities")) striphtml = atoi(Value); - else - return false; - - return true; -} @@ -8,11 +8,8 @@ #ifndef __EPGFIXER_CONFIG_H_ #define __EPGFIXER_CONFIG_H_ -#include <vdr/tools.h> - -class cEpgfixerSetup +struct cEpgfixerSetup { -public: int quotedshorttext; int blankbeforedescription; int repeatedtitle; @@ -24,12 +21,6 @@ public: int components; int striphtml; cEpgfixerSetup(); - bool SetupParse(const char *Name, const char *Value); - bool ProcessArgs(int argc, char *argv[]); - -protected: - bool ProcessArg(const char *Name, const char *Value); - static cString m_ProcessedArgs; }; // Global instance @@ -145,7 +145,29 @@ cMenuSetupPage *cPluginEpgfixer::SetupMenu(void) bool cPluginEpgfixer::SetupParse(const char *Name, const char *Value) { // Parse your own setup parameters and store their values. - return EpgfixerSetup.SetupParse(Name, Value); + cString m_ProcessedArgs; + // Parse your own setup parameters and store their values. + const char *pt; + if (*m_ProcessedArgs && NULL != (pt = strstr(m_ProcessedArgs + 1, Name)) && + *(pt - 1) == ' ' && *(pt + strlen(Name)) == ' ') { + dsyslog("Skipping configuration entry %s=%s (overridden in command line)", Name, Value); + return true; + } + + if (!strcasecmp(Name, "RemoveQuotesFromShortText")) EpgfixerSetup.quotedshorttext = atoi(Value); + else if (!strcasecmp(Name, "MoveDescriptionFromShortText")) EpgfixerSetup.blankbeforedescription = atoi(Value); + else if (!strcasecmp(Name, "RemoveRepeatedTitleFromShortText")) EpgfixerSetup.repeatedtitle = atoi(Value); + else if (!strcasecmp(Name, "RemoveDoubleQuotesFromShortText")) EpgfixerSetup.doublequotedshorttext = atoi(Value); + else if (!strcasecmp(Name, "RemoveUselessFormatting")) EpgfixerSetup.removeformatting = atoi(Value); + else if (!strcasecmp(Name, "MoveLongShortTextToDescription")) EpgfixerSetup.longshorttext = atoi(Value); + else if (!strcasecmp(Name, "PreventEqualShortTextAndDescription")) EpgfixerSetup.equalshorttextanddescription = atoi(Value); + else if (!strcasecmp(Name, "ReplaceBackticksWithSingleQuotes")) EpgfixerSetup.nobackticks = atoi(Value); + else if (!strcasecmp(Name, "FixStreamComponentDescriptions")) EpgfixerSetup.components = atoi(Value); + else if (!strcasecmp(Name, "StripHTMLEntities")) EpgfixerSetup.striphtml = atoi(Value); + else + return false; + + return true; } bool cPluginEpgfixer::Service(const char *Id, void *Data) diff --git a/epghandler.c b/epghandler.c index b30ee1a..de898fc 100644 --- a/epghandler.c +++ b/epghandler.c @@ -5,272 +5,10 @@ * */ -#include <string.h> -#include <vdr/tools.h> -#include "epghandler.h" #include "blacklist.h" -#include "charset.h" -#include "config.h" #include "epgclone.h" -#include "regexp.h" - -// -// Original VDR bug fixes adapted from epg.c of VDR -// by Klaus Schmidinger -// - -static void StripControlCharacters(char *s) -{ - if (s) { - int len = strlen(s); - while (len > 0) { - int l = Utf8CharLen(s); - uchar *p = (uchar *)s; - if (l == 2 && *p == 0xC2) // UTF-8 sequence - p++; - if (*p == 0x86 || *p == 0x87) { - memmove(s, p + 1, len - l + 1); // we also copy the terminating 0! - len -= l; - l = 0; - } - s += l; - len -= l; - } - } -} - -void cEpgfixerEpgHandler::FixOriginalEpgBugs(cEvent *event) -{ - // Copy event title, shorttext and description to temporary variables - // we don't want any "(null)" titles - char *title = event->Title() ? strdup(event->Title()) : strdup("No title"); - char *shortText = event->ShortText() ? strdup(event->ShortText()) : NULL; - char *description = event->Description() ? strdup(event->Description()) : NULL; - - // Some TV stations apparently have their own idea about how to fill in the - // EPG data. Let's fix their bugs as good as we can: - - // Some channels put the ShortText in quotes and use either the ShortText - // or the Description field, depending on how long the string is: - // - // Title - // "ShortText". Description - // - if (EpgfixerSetup.quotedshorttext && (shortText == NULL) != (description == NULL)) { - char *p = shortText ? shortText : description; - if (*p == '"') { - const char *delim = "\"."; - char *e = strstr(p + 1, delim); - if (e) { - *e = 0; - char *s = strdup(p + 1); - char *d = strdup(e + strlen(delim)); - free(shortText); - free(description); - shortText = s; - description = d; - } - } - } - - // Some channels put the Description into the ShortText (preceded - // by a blank) if there is no actual ShortText and the Description - // is short enough: - // - // Title - // Description - // - if (EpgfixerSetup.blankbeforedescription && shortText && !description) { - if (*shortText == ' ') { - memmove(shortText, shortText + 1, strlen(shortText)); - description = shortText; - shortText = NULL; - } - } - - // Sometimes they repeat the Title in the ShortText: - // - // Title - // Title - // - if (EpgfixerSetup.repeatedtitle && shortText && strcmp(title, shortText) == 0) { - free(shortText); - shortText = NULL; - } - - // Some channels put the ShortText between double quotes, which is nothing - // but annoying (some even put a '.' after the closing '"'): - // - // Title - // "ShortText"[.] - // - if (EpgfixerSetup.doublequotedshorttext && shortText && *shortText == '"') { - int l = strlen(shortText); - if (l > 2 && (shortText[l - 1] == '"' || (shortText[l - 1] == '.' && shortText[l - 2] == '"'))) { - memmove(shortText, shortText + 1, l); - char *p = strrchr(shortText, '"'); - if (p) - *p = 0; - } - } - - // Some channels apparently try to do some formatting in the texts, - // which is a bad idea because they have no way of knowing the width - // of the window that will actually display the text. - // Remove excess whitespace: - if (EpgfixerSetup.removeformatting) { - title = compactspace(title); - shortText = compactspace(shortText); - description = compactspace(description); - } - -#define MAX_USEFUL_EPISODE_LENGTH 40 - // Some channels put a whole lot of information in the ShortText and leave - // the Description totally empty. So if the ShortText length exceeds - // MAX_USEFUL_EPISODE_LENGTH, let's put this into the Description - // instead: - if (EpgfixerSetup.longshorttext && !isempty(shortText) && isempty(description)) { - if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { - free(description); - description = shortText; - shortText = NULL; - } - } - - // Some channels put the same information into ShortText and Description. - // In that case we delete one of them: - if (EpgfixerSetup.equalshorttextanddescription && shortText && description && strcmp(shortText, description) == 0) { - if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { - free(shortText); - shortText = NULL; - } - else { - free(description); - description = NULL; - } - } - - // Some channels use the ` ("backtick") character, where a ' (single quote) - // would be normally used. Actually, "backticks" in normal text don't make - // much sense, so let's replace them: - if (EpgfixerSetup.nobackticks) { - strreplace(title, '`', '\''); - strreplace(shortText, '`', '\''); - strreplace(description, '`', '\''); - } - - // The stream components have a "description" field which some channels - // apparently have no idea of how to set correctly: - const cComponents *components = event->Components(); - if (EpgfixerSetup.components && components) { - for (int i = 0; i < components->NumComponents(); ++i) { - tComponent *p = components->Component(i); - switch (p->stream) { - case 0x01: { // video - if (p->description) { - if (strcasecmp(p->description, "Video") == 0 || - strcasecmp(p->description, "Bildformat") == 0) { - // Yes, we know it's video - that's what the 'stream' code - // is for! But _which_ video is it? - free(p->description); - p->description = NULL; - } - } - if (!p->description) { - switch (p->type) { - case 0x01: - case 0x05: p->description = strdup("4:3"); break; - case 0x02: - case 0x03: - case 0x06: - case 0x07: p->description = strdup("16:9"); break; - case 0x04: - case 0x08: p->description = strdup(">16:9"); break; - case 0x09: - case 0x0D: p->description = strdup("HD 4:3"); break; - case 0x0A: - case 0x0B: - case 0x0E: - case 0x0F: p->description = strdup("HD 16:9"); break; - case 0x0C: - case 0x10: p->description = strdup("HD >16:9"); break; - default: ; - } - } - } - break; - case 0x02: { // audio - if (p->description) { - if (strcasecmp(p->description, "Audio") == 0) { - // Yes, we know it's audio - that's what the 'stream' code - // is for! But _which_ audio is it? - free(p->description); - p->description = NULL; - } - } - if (!p->description) { - switch (p->type) { - case 0x05: p->description = strdup("Dolby Digital"); break; - default: ; // all others will just display the language - } - } - } - break; - default: ; - } - } - } - - // VDR can't usefully handle newline characters in the title, shortText or component description of EPG - // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel): - strreplace(title, '\n', ' '); - strreplace(shortText, '\n', ' '); - if (components) { - for (int i = 0; i < components->NumComponents(); ++i) { - tComponent *p = components->Component(i); - if (p->description) - strreplace(p->description, '\n', ' '); - } - } - // Same for control characters: - StripControlCharacters(title); - StripControlCharacters(shortText); - StripControlCharacters(description); - // Set modified data back to event - event->SetTitle(title); - event->SetShortText(shortText); - event->SetDescription(description); - - free(title); - free(shortText); - free(description); -} - -bool cEpgfixerEpgHandler::FixBugs(cEvent *Event) -{ - return EpgfixerRegexps.Apply(Event); -} - -bool cEpgfixerEpgHandler::FixCharSets(cEvent *Event) -{ - return EpgfixerCharSets.Apply(Event); -} - -void cEpgfixerEpgHandler::StripHTML(cEvent *Event) -{ - if (EpgfixerSetup.striphtml) { - char *tmpstring = NULL; - tmpstring = Event->Title() ? strdup(Event->Title()) : NULL; - Event->SetTitle(striphtml(tmpstring)); - FREE(tmpstring); - tmpstring = Event->ShortText() ? strdup(Event->ShortText()) : NULL; - Event->SetShortText(striphtml(tmpstring)); - FREE(tmpstring); - tmpstring = Event->Description() ? strdup(Event->Description()) : NULL; - Event->SetDescription(striphtml(tmpstring)); - FREE(tmpstring); - } -} +#include "tools.h" +#include "epghandler.h" bool cEpgfixerEpgHandler::FixEpgBugs(cEvent *Event) { diff --git a/epghandler.h b/epghandler.h index cd5d51e..de090af 100644 --- a/epghandler.h +++ b/epghandler.h @@ -13,12 +13,6 @@ class cEpgfixerEpgHandler : public cEpgHandler { -private: - void FixOriginalEpgBugs(cEvent *event); - bool FixCharSets(cEvent *Event); - bool FixBugs(cEvent *Event); - void StripHTML(cEvent *Event); - public: cEpgfixerEpgHandler(void) {}; virtual bool HandleEvent(cEvent *Event); @@ -78,6 +78,44 @@ void cRegexp::FreeCompiled() } } + +int cRegexp::ParseModifiers(char *modstring, int substitution) +{ + int i = 0; + int mods = 0; + // handle all modifiers + while (*(modstring + i) != 0) { + switch (*(modstring + i)) { + case 'g': + if (substitution) + replace = GLOBAL; + break; + case 'i': + mods |= PCRE_CASELESS; + break; + case 'm': + mods |= PCRE_MULTILINE; + break; + case 's': + mods |= PCRE_DOTALL; + break; + case 'u': + mods |= PCRE_UTF8; + break; + case 'x': + mods |= PCRE_EXTENDED; + break; + case 'X': + mods |= PCRE_EXTRA; + break; + default: + break; + } + i++; + } + return mods; +} + void cRegexp::ParseRegexp(char *restring) { if (restring) { @@ -87,37 +125,7 @@ void cRegexp::ParseRegexp(char *restring) char *l = strrchr(restring, '/'); if (l) { *l = 0; - int i = 1; - // handle all modifiers - while (*(l + i) != 0) { - switch (*(l + i)) { - case 'g': - if (restring[0] == 's') - replace = GLOBAL; - break; - case 'i': - modifiers = modifiers | PCRE_CASELESS; - break; - case 'm': - modifiers = modifiers | PCRE_MULTILINE; - break; - case 's': - modifiers = modifiers | PCRE_DOTALL; - break; - case 'u': - modifiers = modifiers | PCRE_UTF8; - break; - case 'x': - modifiers = modifiers | PCRE_EXTENDED; - break; - case 'X': - modifiers = modifiers | PCRE_EXTRA; - break; - default: - break; - } - i++; - } + modifiers = ParseModifiers(l + 1, restring[0] == 's'); } // parse regexp format 's///' if (restring[0] == 's') { @@ -200,13 +208,13 @@ bool cRegexp::Apply(cEvent *Event) } if (!*tmpstring) tmpstring = ""; + int tmpstringlen = strlen(*tmpstring); int ovector[OVECCOUNT]; int rc = 0; if (replace != NONE) {// find and replace int last_match_end = -1; int options = 0; int start_offset = 0; - int tmpstringlen = strlen(*tmpstring); cString resultstring = ""; // loop through matches while ((rc = pcre_exec(re, sd, *tmpstring, tmpstringlen, start_offset, options, ovector, OVECCOUNT)) > 0) { @@ -243,7 +251,7 @@ bool cRegexp::Apply(cEvent *Event) } else {// use backreferences const char *capturestring; - rc = pcre_exec(re, sd, *tmpstring, strlen(*tmpstring), 0, 0, ovector, OVECCOUNT); + rc = pcre_exec(re, sd, *tmpstring, tmpstringlen, 0, 0, ovector, OVECCOUNT); if (rc == 0) { error("maximum number of captured substrings is %d\n", OVECCOUNT / 3 - 1); } @@ -30,6 +30,7 @@ private: pcre_extra *sd; void Compile(); void FreeCompiled(); + int ParseModifiers(char *modstring, int substitution = 0); void ParseRegexp(char *restring); public: diff --git a/setup_menu.c b/setup_menu.c index 19f84a2..06dbaae 100644 --- a/setup_menu.c +++ b/setup_menu.c @@ -167,7 +167,7 @@ public: cMenuSetupEpgfixer::cMenuSetupEpgfixer(void) { - memcpy(&newconfig, &EpgfixerSetup, sizeof(cEpgfixerSetup)); + newconfig = EpgfixerSetup; Set(); } @@ -223,7 +223,7 @@ void cMenuSetupEpgfixer::Set(void) void cMenuSetupEpgfixer::Store(void) { - memcpy(&EpgfixerSetup, &newconfig, sizeof(cEpgfixerSetup)); + EpgfixerSetup = newconfig; SetupStore("RemoveQuotesFromShortText", EpgfixerSetup.quotedshorttext); SetupStore("MoveDescriptionFromShortText", EpgfixerSetup.blankbeforedescription); @@ -8,10 +8,270 @@ #include <stdlib.h> #include <string.h> #include <vdr/thread.h> - +#include "charset.h" +#include "config.h" +#include "regexp.h" #include "tools.h" // +// Original VDR bug fixes adapted from epg.c of VDR +// by Klaus Schmidinger +// + +static void StripControlCharacters(char *s) +{ + if (s) { + int len = strlen(s); + while (len > 0) { + int l = Utf8CharLen(s); + uchar *p = (uchar *)s; + if (l == 2 && *p == 0xC2) // UTF-8 sequence + p++; + if (*p == 0x86 || *p == 0x87) { + memmove(s, p + 1, len - l + 1); // we also copy the terminating 0! + len -= l; + l = 0; + } + s += l; + len -= l; + } + } +} + +void FixOriginalEpgBugs(cEvent *event) +{ + // Copy event title, shorttext and description to temporary variables + // we don't want any "(null)" titles + char *title = event->Title() ? strdup(event->Title()) : strdup("No title"); + char *shortText = event->ShortText() ? strdup(event->ShortText()) : NULL; + char *description = event->Description() ? strdup(event->Description()) : NULL; + + // Some TV stations apparently have their own idea about how to fill in the + // EPG data. Let's fix their bugs as good as we can: + + // Some channels put the ShortText in quotes and use either the ShortText + // or the Description field, depending on how long the string is: + // + // Title + // "ShortText". Description + // + if (EpgfixerSetup.quotedshorttext && (shortText == NULL) != (description == NULL)) { + char *p = shortText ? shortText : description; + if (*p == '"') { + const char *delim = "\"."; + char *e = strstr(p + 1, delim); + if (e) { + *e = 0; + char *s = strdup(p + 1); + char *d = strdup(e + strlen(delim)); + free(shortText); + free(description); + shortText = s; + description = d; + } + } + } + + // Some channels put the Description into the ShortText (preceded + // by a blank) if there is no actual ShortText and the Description + // is short enough: + // + // Title + // Description + // + if (EpgfixerSetup.blankbeforedescription && shortText && !description) { + if (*shortText == ' ') { + memmove(shortText, shortText + 1, strlen(shortText)); + description = shortText; + shortText = NULL; + } + } + + // Sometimes they repeat the Title in the ShortText: + // + // Title + // Title + // + if (EpgfixerSetup.repeatedtitle && shortText && strcmp(title, shortText) == 0) { + free(shortText); + shortText = NULL; + } + + // Some channels put the ShortText between double quotes, which is nothing + // but annoying (some even put a '.' after the closing '"'): + // + // Title + // "ShortText"[.] + // + if (EpgfixerSetup.doublequotedshorttext && shortText && *shortText == '"') { + int l = strlen(shortText); + if (l > 2 && (shortText[l - 1] == '"' || (shortText[l - 1] == '.' && shortText[l - 2] == '"'))) { + memmove(shortText, shortText + 1, l); + char *p = strrchr(shortText, '"'); + if (p) + *p = 0; + } + } + + // Some channels apparently try to do some formatting in the texts, + // which is a bad idea because they have no way of knowing the width + // of the window that will actually display the text. + // Remove excess whitespace: + if (EpgfixerSetup.removeformatting) { + title = compactspace(title); + shortText = compactspace(shortText); + description = compactspace(description); + } + +#define MAX_USEFUL_EPISODE_LENGTH 40 + // Some channels put a whole lot of information in the ShortText and leave + // the Description totally empty. So if the ShortText length exceeds + // MAX_USEFUL_EPISODE_LENGTH, let's put this into the Description + // instead: + if (EpgfixerSetup.longshorttext && !isempty(shortText) && isempty(description)) { + if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { + free(description); + description = shortText; + shortText = NULL; + } + } + + // Some channels put the same information into ShortText and Description. + // In that case we delete one of them: + if (EpgfixerSetup.equalshorttextanddescription && shortText && description && strcmp(shortText, description) == 0) { + if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) { + free(shortText); + shortText = NULL; + } + else { + free(description); + description = NULL; + } + } + + // Some channels use the ` ("backtick") character, where a ' (single quote) + // would be normally used. Actually, "backticks" in normal text don't make + // much sense, so let's replace them: + if (EpgfixerSetup.nobackticks) { + strreplace(title, '`', '\''); + strreplace(shortText, '`', '\''); + strreplace(description, '`', '\''); + } + + // The stream components have a "description" field which some channels + // apparently have no idea of how to set correctly: + const cComponents *components = event->Components(); + if (EpgfixerSetup.components && components) { + for (int i = 0; i < components->NumComponents(); ++i) { + tComponent *p = components->Component(i); + switch (p->stream) { + case 0x01: { // video + if (p->description) { + if (strcasecmp(p->description, "Video") == 0 || + strcasecmp(p->description, "Bildformat") == 0) { + // Yes, we know it's video - that's what the 'stream' code + // is for! But _which_ video is it? + free(p->description); + p->description = NULL; + } + } + if (!p->description) { + switch (p->type) { + case 0x01: + case 0x05: p->description = strdup("4:3"); break; + case 0x02: + case 0x03: + case 0x06: + case 0x07: p->description = strdup("16:9"); break; + case 0x04: + case 0x08: p->description = strdup(">16:9"); break; + case 0x09: + case 0x0D: p->description = strdup("HD 4:3"); break; + case 0x0A: + case 0x0B: + case 0x0E: + case 0x0F: p->description = strdup("HD 16:9"); break; + case 0x0C: + case 0x10: p->description = strdup("HD >16:9"); break; + default: ; + } + } + } + break; + case 0x02: { // audio + if (p->description) { + if (strcasecmp(p->description, "Audio") == 0) { + // Yes, we know it's audio - that's what the 'stream' code + // is for! But _which_ audio is it? + free(p->description); + p->description = NULL; + } + } + if (!p->description) { + switch (p->type) { + case 0x05: p->description = strdup("Dolby Digital"); break; + default: ; // all others will just display the language + } + } + } + break; + default: ; + } + } + } + + // VDR can't usefully handle newline characters in the title, shortText or component description of EPG + // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel): + strreplace(title, '\n', ' '); + strreplace(shortText, '\n', ' '); + if (components) { + for (int i = 0; i < components->NumComponents(); ++i) { + tComponent *p = components->Component(i); + if (p->description) + strreplace(p->description, '\n', ' '); + } + } + // Same for control characters: + StripControlCharacters(title); + StripControlCharacters(shortText); + StripControlCharacters(description); + // Set modified data back to event + event->SetTitle(title); + event->SetShortText(shortText); + event->SetDescription(description); + + free(title); + free(shortText); + free(description); +} + +bool FixBugs(cEvent *Event) +{ + return EpgfixerRegexps.Apply(Event); +} + +bool FixCharSets(cEvent *Event) +{ + return EpgfixerCharSets.Apply(Event); +} + +void StripHTML(cEvent *Event) +{ + if (EpgfixerSetup.striphtml) { + char *tmpstring = NULL; + tmpstring = Event->Title() ? strdup(Event->Title()) : NULL; + Event->SetTitle(striphtml(tmpstring)); + FREE(tmpstring); + tmpstring = Event->ShortText() ? strdup(Event->ShortText()) : NULL; + Event->SetShortText(striphtml(tmpstring)); + FREE(tmpstring); + tmpstring = Event->Description() ? strdup(Event->Description()) : NULL; + Event->SetDescription(striphtml(tmpstring)); + FREE(tmpstring); + } +} + +// // HTML conversion code taken from RSS Reader plugin for VDR // http://www.saunalahti.fi/~rahrenbe/vdr/rssreader/ // by Rolf Ahrenberg @@ -210,10 +470,12 @@ void cAddEventThread::Action(void) Lock(); while (schedules && (e = list->First()) != NULL) { cSchedule *schedule = (cSchedule *)schedules->GetSchedule(Channels.GetByChannelID(e->GetChannelID()), true); - schedule->AddEvent(e->GetEvent()); - EpgHandlers.SortSchedule(schedule); - EpgHandlers.DropOutdated(schedule, e->GetEvent()->StartTime(), e->GetEvent()->EndTime(), e->GetEvent()->TableID(), e->GetEvent()->Version()); - list->Del(e); + if (schedule) { + schedule->AddEvent(e->GetEvent()); + EpgHandlers.SortSchedule(schedule); + EpgHandlers.DropOutdated(schedule, e->GetEvent()->StartTime(), e->GetEvent()->EndTime(), e->GetEvent()->TableID(), e->GetEvent()->Version()); + list->Del(e); + } } Unlock(); cCondWait::SleepMs(10); @@ -13,10 +13,23 @@ #include <vdr/epg.h> #include <vdr/tools.h> -#define error(x...) esyslog("EPGFixer: " x); +#ifdef DEBUG +#define debug(x...) dsyslog("EPGFixer: " x); +#else +#define debug(x...) ; +#endif +#define error(x...) esyslog("ERROR: " x); + #define FREE(x) { free(x); x = NULL; } +// --- EPG bug fixes ---------------------------------------------------- + +void FixOriginalEpgBugs(cEvent *event); +bool FixCharSets(cEvent *Event); +bool FixBugs(cEvent *Event); +void StripHTML(cEvent *Event); + // --- Add event to schedule -------------------------------------------- void AddEvent(cEvent *event, tChannelID ChannelID); |