summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatti Lehtimäki <matti.lehtimaki@gmail.com>2012-05-12 14:42:01 +0300
committerMatti Lehtimäki <matti.lehtimaki@gmail.com>2012-05-12 14:42:01 +0300
commit6b488dcedf24cf9b4890505eba992d683eedecac (patch)
tree51347d76c4b2891568e54348d9ce0ab99304bd0b
parent548e0a6bc35d4c776039f7467c0d67eabf9ef46a (diff)
downloadvdr-plugin-epgfixer-6b488dcedf24cf9b4890505eba992d683eedecac.tar.gz
vdr-plugin-epgfixer-6b488dcedf24cf9b4890505eba992d683eedecac.tar.bz2
Support for ignoring and copying EPG data. Bug fixes.
Fix character set conversion for selected channels. Fix and improve Makefile (thanks to Ville Skyttä and Rolf Ahrenberg). Fix compiling with g++-4.7.
-rw-r--r--HISTORY9
-rw-r--r--Makefile2
-rw-r--r--README31
-rw-r--r--blacklist.c36
-rw-r--r--blacklist.h27
-rw-r--r--charset.c48
-rw-r--r--charset.h9
-rw-r--r--epgclone.c91
-rw-r--r--epgclone.h31
-rw-r--r--epgfixer.c41
-rw-r--r--epgfixer/blacklist.conf3
-rw-r--r--epgfixer/charset.conf10
-rw-r--r--epgfixer/epgclone.conf2
-rw-r--r--epghandler.c14
-rw-r--r--epghandler.h2
-rw-r--r--po/fi_FI.po24
-rw-r--r--regexp.c13
-rw-r--r--regexp.h6
-rw-r--r--setup_menu.c48
-rw-r--r--tools.c88
-rw-r--r--tools.h44
21 files changed, 481 insertions, 98 deletions
diff --git a/HISTORY b/HISTORY
index 8c1a1c0..6d0bce3 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,5 +1,14 @@
VDR Plugin 'epgfixer' Revision History
--------------------------------------
+
+2012-??-??: Version 0.2.0
+
+- Support for ignoring EPG data for selected channels.
+- Support for copying EPG data from one channel to another.
+- Fix character set conversion for selected channels.
+- Fix and improve Makefile (thanks to Ville Skyttä and Rolf Ahrenberg).
+- Fix compiling with g++-4.7.
+
2012-05-05: Version 0.1.0
- Support for character set conversion for selected channels.
diff --git a/Makefile b/Makefile
index 90871de..3a64ae7 100644
--- a/Makefile
+++ b/Makefile
@@ -62,7 +62,7 @@ endif
### The object files (add further files here):
-OBJS = $(PLUGIN).o charset.o config.o epghandler.o regexp.o setup_menu.o tools.o
+OBJS = $(PLUGIN).o blacklist.o charset.o config.o epgclone.o epghandler.o regexp.o setup_menu.o tools.o
ifeq ($(REGEXLIB), pcre)
LIBS += $(shell pcre-config --libs-posix)
diff --git a/README b/README
index 68ddf32..4211d60 100644
--- a/README
+++ b/README
@@ -23,9 +23,11 @@ Features:
- Modifying EPG data using regular expressions. Correctly named back references
are placed to the named EPG field.
- Character set conversions for channel using incorrect encoding.
-- Both regular expressions and character set conversions can be applied to
+- Blacklists for ignoring EPG data from stream.
+- Regular expressions, character set conversions and blacklists can be applied to
either all channels or only to selected channels.
-- Editing regular expressions and character set conversions through setup menu.
+- Cloning EPG data from one channel to another.
+- Editing all settings through setup menu.
- EPG bug fixes included in VDR individually selectable from
setup menu.
@@ -42,10 +44,11 @@ make plugins
Configuration:
-Regular expressions and character set conversions are defined in regexp.conf
-and charset.conf, respectively, located in VDR's configuration directory for
-plugins. Check the example configuration files under "epgfixer" subdirectory
-for further information.
+Regular expressions, character set conversions, blacklists and EPG clonings
+are defined in regexp.conf, charset.conf, blacklist.conf and epgclone.conf,
+respectively, located in "epgfixer" subdirectory of VDR's configuration
+directory for plugins. Check the example configuration files under "epgfixer"
+subdirectory for further information.
General syntax of configuration files:
- Lines beginning with # are regarded as comments.
@@ -65,5 +68,17 @@ Syntax of regexp.conf line is "Channel_list:Parsed_epg_field=Regexp" with:
content of the target EPG field, respectively.
- Several regular expressions may be applied to same field.
-Syntax of charset.conf line is "Channel_list:OriginalCharSet" with:
-- OriginalCharSet is a name of a character set (e.g. iso8859-1).
+Syntax of charset.conf line is "Channel_list:BroadcastCharset=OriginalCharSet"
+with:
+- OriginalCharSet and BroadcastCharset are names of a character set
+ (e.g. iso8859-1).
+- OriginalCharSet is the real character set of EPG data.
+- BroadcastCharset is the optional incorrect character set received in data
+ stream.
+- If no BroadcastCharset is defined ISO6937 is assumed.
+
+Syntax of blacklist.conf line is "Channel_list" with:
+- Only comma separated list of channel to be ignored.
+
+Syntax of epgclone.conf line is "FromChannel=ToChannel" with:
+- Copy EPG data of FromChannel into ToChannel.
diff --git a/blacklist.c b/blacklist.c
new file mode 100644
index 0000000..4bacf2c
--- /dev/null
+++ b/blacklist.c
@@ -0,0 +1,36 @@
+/*
+ * blacklist.c: Blacklist list item
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include "blacklist.h"
+
+/* Global instance */
+cEpgfixerList<cBlacklist, cChannel> EpgfixerBlacklists;
+
+
+bool cBlacklist::Apply(cChannel *Channel)
+{
+ if (enabled && IsActive(Channel->GetChannelID()))
+ return true;
+ return false;
+}
+
+void cBlacklist::SetFromString(char *s, bool Enabled)
+{
+ Free();
+ enabled = Enabled;
+ if (s[0] == '!')
+ string = strdup(s+1);
+ else
+ string = strdup(s);
+ if (s[0] == '!' || s[0] == '#')
+ enabled = false;
+ char *p = (s[0] == '#') ? NULL : s;
+ if (p) {
+ char *p = (s[0] == '!') ? s+1 : s;
+ numchannels = LoadChannelsFromString(p);
+ }
+}
diff --git a/blacklist.h b/blacklist.h
new file mode 100644
index 0000000..1d60185
--- /dev/null
+++ b/blacklist.h
@@ -0,0 +1,27 @@
+/*
+ * blacklist.h: Blacklist list item
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#ifndef __EPGFIXER_BLACKLIST_H_
+#define __EPGFIXER_BLACKLIST_H_
+
+#include "tools.h"
+#include <vdr/epg.h>
+
+class cBlacklist : public cListItem
+{
+public:
+ cBlacklist() {}
+ virtual ~cBlacklist() {}
+ using cListItem::Apply;
+ virtual bool Apply(cChannel *Channel);
+ void SetFromString(char *string, bool Enabled);
+};
+
+// Global instance
+extern cEpgfixerList<cBlacklist, cChannel> EpgfixerBlacklists;
+
+#endif //__EPGFIXER_BLACKLIST_H_
diff --git a/charset.c b/charset.c
index 84056bf..c502e90 100644
--- a/charset.c
+++ b/charset.c
@@ -6,39 +6,45 @@
*/
#include "charset.h"
-#include <unistd.h>
/* Global instance */
-cEpgfixerList<cCharSet> EpgfixerCharSets;
+cEpgfixerList<cCharSet, cEvent> EpgfixerCharSets;
cCharSet::cCharSet()
{
- charset = NULL;
+ origcharset = NULL;
+ realcharset = NULL;
}
cCharSet::~cCharSet(void)
{
- free(charset);
+ free(origcharset);
+ free(realcharset);
}
bool cCharSet::Apply(cEvent *Event)
{
if (enabled && IsActive(Event->ChannelID())) {
- cCharSetConv conv(charset, cCharSetConv::SystemCharacterTable());
- Event->SetTitle(conv.Convert(Event->Title()));
- Event->SetShortText(conv.Convert(Event->ShortText()));
- Event->SetDescription(conv.Convert(Event->Description()));
+ cCharSetConv backconv(cCharSetConv::SystemCharacterTable(), origcharset ? origcharset : "iso6937");
+ cString title(backconv.Convert(Event->Title()));
+ cString shortText(backconv.Convert(Event->ShortText()));
+ cString description(backconv.Convert(Event->Description()));
+ cCharSetConv conv(realcharset, cCharSetConv::SystemCharacterTable());
+ Event->SetTitle(conv.Convert(title));
+ Event->SetShortText(conv.Convert(shortText));
+ Event->SetDescription(conv.Convert(description));
}
return false;
}
void cCharSet::SetFromString(char *s, bool Enabled)
{
- FREE(charset);
+ FREE(origcharset);
+ FREE(realcharset);
Free();
enabled = Enabled;
if (s[0] == '!')
- string = strdup(s+1);
+ string = strdup(s + 1);
else
string = strdup(s);
if (s[0] == '!' || s[0] == '#')
@@ -46,19 +52,19 @@ void cCharSet::SetFromString(char *s, bool Enabled)
char *p = (s[0] == '#') ? NULL : s;
if (p) {
char *p = (s[0] == '!') ? s+1 : s;
- char *f = strchr(p, ':');
- if (f) {
- *f = 0;
- charset = strdup(f + 1);
+ char *r = strchr(p, ':');
+ if (r) {
+ *r = 0;
numchannels = LoadChannelsFromString(p);
+ p = r + 1;
+ }
+ r = strchr(p, '=');
+ if (r) {
+ *r = 0;
+ origcharset = strdup(p);
+ realcharset = strdup(r + 1);
}
else
- charset = strdup(p);
+ realcharset = strdup(p);
}
}
-
-void cCharSet::PrintConfigLineToFile(FILE *f)
-{
- if (f)
- fprintf(f, "%s%s\n", enabled ? "" : "!", string);
-}
diff --git a/charset.h b/charset.h
index f73a964..cfcee79 100644
--- a/charset.h
+++ b/charset.h
@@ -10,22 +10,21 @@
#include "tools.h"
#include <vdr/epg.h>
-#include <vdr/tools.h>
-#include <stdio.h>
class cCharSet : public cListItem
{
private:
- char *charset;
+ char *origcharset;
+ char *realcharset;
public:
cCharSet();
virtual ~cCharSet();
+ using cListItem::Apply;
virtual bool Apply(cEvent *Event);
void SetFromString(char *string, bool Enabled);
- virtual void PrintConfigLineToFile(FILE *f);
};
// Global instance
-extern cEpgfixerList<cCharSet> EpgfixerCharSets;
+extern cEpgfixerList<cCharSet, cEvent> EpgfixerCharSets;
#endif //__EPGFIXER_CHARSET_H_
diff --git a/epgclone.c b/epgclone.c
new file mode 100644
index 0000000..9fcff8e
--- /dev/null
+++ b/epgclone.c
@@ -0,0 +1,91 @@
+/*
+ * epgclone.c: EpgClone list item
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include "epgclone.h"
+
+/* Global instance */
+cEpgfixerList<cEpgClone, cEvent> EpgfixerEpgClones;
+
+cEpgClone::cEpgClone()
+{
+ dest_num = 0;
+ dest_str = NULL;
+}
+
+cEpgClone::~cEpgClone()
+{
+ free(dest_str);
+}
+
+void cEpgClone::CloneEvent(cEvent *Source, cEvent *Dest) {
+ Dest->SetEventID(Source->EventID());
+ Dest->SetTableID(Source->TableID());
+ Dest->SetVersion(Source->Version());
+ Dest->SetRunningStatus(Source->RunningStatus());
+ Dest->SetTitle(Source->Title());
+ Dest->SetShortText(Source->ShortText());
+ Dest->SetDescription(Source->Description());
+ cComponents *components = new cComponents();
+ if (Source->Components()) {
+ for (int i = 0; i < Source->Components()->NumComponents(); ++i)
+ components->SetComponent(i, Source->Components()->Component(i)->ToString());
+ }
+ Dest->SetComponents(components);
+ uchar contents[MaxEventContents];
+ for (int i = 0; i < MaxEventContents; ++i)
+ contents[i] = Source->Contents(i);
+ Dest->SetContents(contents);
+ Dest->SetParentalRating(Source->ParentalRating());
+ Dest->SetStartTime(Source->StartTime());
+ Dest->SetDuration(Source->Duration());
+ Dest->SetVps(Source->Vps());
+ if (Source->Seen())
+ Dest->SetSeen();
+ tChannelID channelID;
+ if (dest_num)
+ channelID = Channels.GetByNumber(dest_num)->GetChannelID();
+ else
+ channelID.FromString(dest_str);
+ AddEvent(Dest, channelID);
+}
+
+bool cEpgClone::Apply(cEvent *Event)
+{
+ if (Event && enabled && IsActive(Event->ChannelID())) {
+ cEvent *event = new cEvent(Event->EventID());
+ CloneEvent(Event, event);
+ return true;
+ }
+ return false;
+}
+
+void cEpgClone::SetFromString(char *s, bool Enabled)
+{
+ dest_num = 0;
+ FREE(dest_str);
+ Free();
+ enabled = Enabled;
+ if (s[0] == '!')
+ string = strdup(s+1);
+ else
+ string = strdup(s);
+ if (s[0] == '!' || s[0] == '#')
+ enabled = false;
+ char *p = (s[0] == '#') ? NULL : s;
+ if (p) {
+ char *p = (s[0] == '!') ? s+1 : s;
+ char *f = strchr(p, '=');
+ if (f) {
+ *f = 0;
+ if (atoi(f + 1))
+ dest_num = atoi(f + 1);
+ else
+ dest_str = strdup(f + 1);
+ numchannels = LoadChannelsFromString(p);
+ }
+ }
+}
diff --git a/epgclone.h b/epgclone.h
new file mode 100644
index 0000000..e0a4aa7
--- /dev/null
+++ b/epgclone.h
@@ -0,0 +1,31 @@
+/*
+ * epgclone.h: EpgClone list item
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#ifndef __EPGFIXER_EPGCLONE_H_
+#define __EPGFIXER_EPGCLONE_H_
+
+#include "tools.h"
+#include <vdr/epg.h>
+
+class cEpgClone : public cListItem
+{
+private:
+ int dest_num;
+ char *dest_str;
+ void CloneEvent(cEvent *Source, cEvent *Dest);
+public:
+ cEpgClone();
+ virtual ~cEpgClone();
+ using cListItem::Apply;
+ virtual bool Apply(cEvent *Event);
+ void SetFromString(char *string, bool Enabled);
+};
+
+// Global instance
+extern cEpgfixerList<cEpgClone, cEvent> EpgfixerEpgClones;
+
+#endif //__EPGFIXER_EPGCLONE_H_
diff --git a/epgfixer.c b/epgfixer.c
index 7308b0c..bbf635b 100644
--- a/epgfixer.c
+++ b/epgfixer.c
@@ -7,7 +7,9 @@
#include <vdr/plugin.h>
#include <vdr/i18n.h>
+#include "blacklist.h"
#include "charset.h"
+#include "epgclone.h"
#include "regexp.h"
#include "setup_menu.h"
#include "epghandler.h"
@@ -20,7 +22,7 @@
#define GITVERSION ""
#endif
-static const char VERSION[] = "0.1.0" GITVERSION;
+static const char VERSION[] = "0.2.0" GITVERSION;
static const char DESCRIPTION[] = trNOOP("Fix bugs in EPG");
class cPluginEpgfixer : public cPlugin {
@@ -80,6 +82,10 @@ bool cPluginEpgfixer::Initialize(void)
EpgfixerRegexps.ReloadConfigFile();
EpgfixerCharSets.SetConfigFile(AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "charset.conf")); // allowed only via main thread!);
EpgfixerCharSets.ReloadConfigFile();
+ EpgfixerBlacklists.SetConfigFile(AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "blacklist.conf")); // allowed only via main thread!);
+ EpgfixerBlacklists.ReloadConfigFile();
+ EpgfixerEpgClones.SetConfigFile(AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "epgclone.conf")); // allowed only via main thread!);
+ EpgfixerEpgClones.ReloadConfigFile();
return new cEpgfixerEpgHandler();
}
@@ -149,10 +155,16 @@ bool cPluginEpgfixer::Service(const char *Id, void *Data)
const char **cPluginEpgfixer::SVDRPHelpPages(void)
{
static const char *HelpPages[] = {
+ "RLAL\n"
+ " Reload all configs.",
"RLRE\n"
" Reload regexp.conf.",
"RLCH\n"
" Reload charset.conf.",
+ "RLBL\n"
+ " Reload blacklist.conf.",
+ "RLEP\n"
+ " Reload epgclone.conf.",
NULL
};
return HelpPages;
@@ -176,6 +188,33 @@ cString cPluginEpgfixer::SVDRPCommand(const char *Command, const char *Option, i
return cString("Reloading charset.conf failed");
}
}
+ else if (strcasecmp(Command, "RLBL") == 0) {
+ if (EpgfixerBlacklists.ReloadConfigFile()) {
+ return cString("Reloaded blacklist.conf");
+ } else {
+ ReplyCode = 554; // Requested action failed
+ return cString("Reloading blacklist.conf failed");
+ }
+ }
+ else if (strcasecmp(Command, "RLEP") == 0) {
+ if (EpgfixerEpgClones.ReloadConfigFile()) {
+ return cString("Reloaded epgclone.conf");
+ } else {
+ ReplyCode = 554; // Requested action failed
+ return cString("Reloading epgclone.conf failed");
+ }
+ }
+ else if (strcasecmp(Command, "REL") == 0) {
+ if (EpgfixerCharSets.ReloadConfigFile() &&
+ EpgfixerCharSets.ReloadConfigFile() &&
+ EpgfixerBlacklists.ReloadConfigFile() &&
+ EpgfixerEpgClones.ReloadConfigFile()) {
+ return cString("Reloaded all configs");
+ } else {
+ ReplyCode = 554; // Requested action failed
+ return cString("Reloading all or some configs failed");
+ }
+ }
return NULL;
}
diff --git a/epgfixer/blacklist.conf b/epgfixer/blacklist.conf
new file mode 100644
index 0000000..7cd9ced
--- /dev/null
+++ b/epgfixer/blacklist.conf
@@ -0,0 +1,3 @@
+# Ignore EPG data for channels 1, 2 and 3
+#1,2,3
+
diff --git a/epgfixer/charset.conf b/epgfixer/charset.conf
index 18788c8..d2b14b3 100644
--- a/epgfixer/charset.conf
+++ b/epgfixer/charset.conf
@@ -1,6 +1,8 @@
# Convert character set of channels 1, 2 and 3 from iso8859-1 to character set
-# used by VDR
-#1,2,3:iso8859-1
+# used by VDR. Used for channels which broadcast incorrect character set
+# (in this example iso8859-9).
+#1,2,3:iso8859-9=iso8859-1
# Convert character set of all channels from iso8859-1 to character set
-# used by VDR
-#iso8859-1
+# used by VDR. Used for channels which do not broadcast any character set but
+# use a non-standard character set.
+#1,2,3:iso8859-1
diff --git a/epgfixer/epgclone.conf b/epgfixer/epgclone.conf
new file mode 100644
index 0000000..11ba183
--- /dev/null
+++ b/epgfixer/epgclone.conf
@@ -0,0 +1,2 @@
+# Copy EPG data from channel 1 to 3
+#1=3
diff --git a/epghandler.c b/epghandler.c
index 68e7a28..2dadd33 100644
--- a/epghandler.c
+++ b/epghandler.c
@@ -6,8 +6,10 @@
*/
#include "epghandler.h"
-#include "config.h"
+#include "blacklist.h"
#include "charset.h"
+#include "config.h"
+#include "epgclone.h"
#include "regexp.h"
#include <vdr/tools.h>
#include <string.h>
@@ -267,3 +269,13 @@ bool cEpgfixerEpgHandler::FixEpgBugs(cEvent *Event)
FixBugs(Event);
return false;
}
+
+bool cEpgfixerEpgHandler::HandleEvent(cEvent *Event)
+{
+ return EpgfixerEpgClones.Apply(Event);
+}
+
+bool cEpgfixerEpgHandler::IgnoreChannel(const cChannel *Channel)
+{
+ return EpgfixerBlacklists.Apply((cChannel *)Channel);
+}
diff --git a/epghandler.h b/epghandler.h
index cc38378..657fffc 100644
--- a/epghandler.h
+++ b/epghandler.h
@@ -19,6 +19,8 @@ private:
void StripHTML(cEvent *Event);
public:
cEpgfixerEpgHandler(void) {};
+ virtual bool HandleEvent(cEvent *Event);
+ virtual bool IgnoreChannel(const cChannel *Channel);
virtual bool FixEpgBugs(cEvent *Event);
};
diff --git a/po/fi_FI.po b/po/fi_FI.po
index de11e7c..d4b8b00 100644
--- a/po/fi_FI.po
+++ b/po/fi_FI.po
@@ -5,10 +5,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: vdr-epgfixer 0.1.0\n"
+"Project-Id-Version: vdr-epgfixer 0.2.0\n"
"Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2012-05-05 19:01+0300\n"
-"PO-Revision-Date: 2012-05-05 18:25+0300\n"
+"POT-Creation-Date: 2012-05-09 23:25+0300\n"
+"PO-Revision-Date: 2012-05-09 23:20+0300\n"
"Last-Translator: Matti Lehtimäki <matti.lehtimaki@gmail.com>\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n"
"MIME-Version: 1.0\n"
@@ -19,7 +19,7 @@ msgstr ""
msgid "Fix bugs in EPG"
msgstr "Korjaa virheitä EPG:ssä"
-msgid " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%~\\/?!()[]{}<>$^*.,:;-=#"
+msgid "RegexpChars$ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%~\\/?!()[]{}<>$^*.,:;-=#"
msgstr " abcdefghijklmnopqrstuvwxyzåäöABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ0123456789%~\\/?!()[]{}<>$^*.,:;-=#"
msgid "Button$Cancel"
@@ -37,8 +37,20 @@ msgstr "Merkistömuunnokset"
msgid "Edit character set conversions."
msgstr "Muokkaa merkistömuunnoksia."
+msgid "EPG blacklists"
+msgstr "Ohjelmaoppaan mustat listat"
+
+msgid "Edit EPG blacklists."
+msgstr "Muokkaa ohjelmaoppaan mustia listoja. Mustilla listoilla voi estää ohjelmatietojen käsittelyn valituilta kanavilta."
+
+msgid "EPG cloning"
+msgstr "Ohjelmatietojen kopiointi"
+
+msgid "Edit EPG data cloning."
+msgstr "Muokkaa ohjelmatietojen kopiointia. Tällä voit kopioida kanavan ohjelmatiedot toiselle kanavalle."
+
msgid "--- EPG bugfixes ---"
-msgstr "--- EPG korjaukset ---"
+msgstr "--- Ohjelmaoppaan korjaukset ---"
msgid "Remove quotes from ShortText"
msgstr "Poista lainaukset lyhyestä kuvauksesta"
@@ -54,7 +66,7 @@ msgstr ""
"Otsikko\n"
"\"Lyhyt kuvaus\". Kuvaus"
-msgid "Move Description from ShortText."
+msgid "Move Description from ShortText"
msgstr "Siirrä kuvaus lyhyeen kuvaukseen"
msgid ""
diff --git a/regexp.c b/regexp.c
index dd6856c..bef3590 100644
--- a/regexp.c
+++ b/regexp.c
@@ -6,10 +6,9 @@
*/
#include "regexp.h"
-#include <unistd.h>
/* Global instance */
-cEpgfixerList<cRegexp> EpgfixerRegexps;
+cEpgfixerList<cRegexp, cEvent> EpgfixerRegexps;
const char *strSources[] = { "title","shorttext","description","undefined" };
@@ -178,16 +177,6 @@ bool cRegexp::Apply(cEvent *Event)
return false;
}
-void cRegexp::PrintConfigLineToFile(FILE *f)
-{
- if (f) {
- if (source == REGEXP_UNDEFINED)
- fprintf(f, "%s\n", string);
- else
- fprintf(f, "%s%s\n", enabled ? "" : "!", string);
- }
-}
-
void cRegexp::ToggleEnabled(void)
{
if (source != REGEXP_UNDEFINED)
diff --git a/regexp.h b/regexp.h
index 4e00897..67270c2 100644
--- a/regexp.h
+++ b/regexp.h
@@ -10,8 +10,6 @@
#include "tools.h"
#include <vdr/epg.h>
-#include <vdr/tools.h>
-#include <stdio.h>
#ifdef HAVE_PCREPOSIX
#include <pcre.h>
@@ -31,14 +29,14 @@ private:
public:
cRegexp();
virtual ~cRegexp();
+ using cListItem::Apply;
virtual bool Apply(cEvent *Event);
void SetFromString(char *string, bool Enabled);
int GetSource() { return source; };
void ToggleEnabled(void);
- virtual void PrintConfigLineToFile(FILE *f);
};
// Global instance
-extern cEpgfixerList<cRegexp> EpgfixerRegexps;
+extern cEpgfixerList<cRegexp, cEvent> EpgfixerRegexps;
#endif //__EPGFIXER_REGEXP_H_
diff --git a/setup_menu.c b/setup_menu.c
index 1e5fc3f..2719115 100644
--- a/setup_menu.c
+++ b/setup_menu.c
@@ -8,21 +8,23 @@
#include "setup_menu.h"
#include <vdr/config.h>
#include <vdr/i18n.h>
-#include "tools.h"
+#include "blacklist.h"
#include "charset.h"
+#include "epgclone.h"
#include "regexp.h"
+#include "tools.h"
//--- cMenuSetupConfigEditor ------------------------------------------------------
#define MAXREGEXPLENGTH 512
-const char *RegexpChars =
- trNOOP(" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%~\\/?!()[]{}<>$^*.,:;-=#");
+const char *RegexpChars =
+ trNOOP("RegexpChars$ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789%~\\/?!()[]{}<>$^*.,:;-=#");
-template<class T> class cMenuSetupConfigEditor : public cMenuSetupPage
+template<class LISTITEM, class PARAMETER> class cMenuSetupConfigEditor : public cMenuSetupPage
{
private:
- cEpgfixerList<T> *list;
+ cEpgfixerList<LISTITEM, PARAMETER> *list;
const char *fileName;
char **lines;
char **numlines;
@@ -30,11 +32,11 @@ private:
{
lines = (char **)malloc(sizeof(char *)*(list->Count()));
int i = 0;
- T *item = (T *)list->First();
+ LISTITEM *item = (LISTITEM *)list->First();
while (item) {
lines[i] = (char *)malloc(sizeof(char)*MAXREGEXPLENGTH);
snprintf(lines[i], MAXREGEXPLENGTH, "%s", item->GetString());
- item = (T *)item->Next();
+ item = (LISTITEM *)item->Next();
++i;
}
}
@@ -53,10 +55,10 @@ private:
if (fileName && access(fileName, F_OK) == 0) {
FILE *f = fopen(fileName, "w");
if (f) {
- T *item = (T *)list->First();
+ LISTITEM *item = (LISTITEM *)list->First();
while (item) {
item->PrintConfigLineToFile(f);
- item = (T *)item->Next();
+ item = (LISTITEM *)item->Next();
}
fclose(f);
}
@@ -67,10 +69,10 @@ protected:
{
// Store regular expressions back to list
int i = 0;
- T *item = (T *)list->First();
+ LISTITEM *item = (LISTITEM *)list->First();
while (i < list->Count()) {
item->SetFromString(lines[i], item->Enabled());
- item = (T *)item->Next();
+ item = (LISTITEM *)item->Next();
++i;
}
}
@@ -78,17 +80,17 @@ protected:
{
Clear();
int i = 0;
- T *item = (T *)list->First();
+ LISTITEM *item = (LISTITEM *)list->First();
while (i < list->Count()) {
Add(new cMenuEditStrItem(item->Enabled() ? "+" : "-", lines[i], MAXREGEXPLENGTH, tr(RegexpChars)));
- item = (T *)item->Next();
+ item = (LISTITEM *)item->Next();
++i;
}
SetHelp(trVDR("Button$On/Off"), trVDR("Button$New"), trVDR("Button$Delete"), tr("Button$Cancel"));
Display();
}
public:
- cMenuSetupConfigEditor(cEpgfixerList<T> *l)
+ cMenuSetupConfigEditor(cEpgfixerList<LISTITEM, PARAMETER> *l)
{
list = l;
cEitFilter::SetDisableUntil(time(NULL) + 1000);
@@ -117,7 +119,7 @@ public:
case kGreen:
Store();
FreeArray();
- list->Add(new T());
+ list->Add(new LISTITEM());
LoadListToArray();
Set();
Display();
@@ -166,6 +168,10 @@ void cMenuSetupEpgfixer::Set(void)
help.Append(tr("Edit regular expressions."));
Add(new cOsdItem(tr("Character set conversions"), osUser2));
help.Append(tr("Edit character set conversions."));
+ Add(new cOsdItem(tr("EPG blacklists"), osUser3));
+ help.Append(tr("Edit EPG blacklists."));
+ Add(new cOsdItem(tr("EPG cloning"), osUser4));
+ help.Append(tr("Edit EPG data cloning."));
Add(new cOsdItem(tr("--- EPG bugfixes ---"), osUnknown, false));
help.Append("");
@@ -173,7 +179,7 @@ void cMenuSetupEpgfixer::Set(void)
Add(new cMenuEditBoolItem(tr("Remove quotes from ShortText"),
&newconfig.quotedshorttext));
help.Append(tr("EPG bugfix level >= 1: Some channels put the ShortText in quotes and use either the ShortText or the Description field, depending on how long the string is:\n\nTitle\n\"ShortText\". Description"));
- Add(new cMenuEditBoolItem(tr("Move Description from ShortText."),
+ Add(new cMenuEditBoolItem(tr("Move Description from ShortText"),
&newconfig.blankbeforedescription));
help.Append(tr("EPG bugfix level >= 1: Some channels put the Description into the ShortText (preceded by a blank) if there is no actual ShortText and the Description is short enough:\n\nTitle\n Description"));
Add(new cMenuEditBoolItem(tr("Remove repeated title from ShortText"),
@@ -232,6 +238,8 @@ eOSState cMenuSetupEpgfixer::ProcessKey(eKeys Key)
Skins.Message(mtInfo, tr("Loading configuration files..."));
EpgfixerRegexps.ReloadConfigFile();
EpgfixerCharSets.ReloadConfigFile();
+ EpgfixerBlacklists.ReloadConfigFile();
+ EpgfixerEpgClones.ReloadConfigFile();
Skins.Message(mtInfo, NULL);
state = osContinue;
break;
@@ -252,8 +260,12 @@ eOSState cMenuSetupEpgfixer::ProcessKey(eKeys Key)
}
}
else if (state == osUser1)
- return AddSubMenu(new cMenuSetupConfigEditor<cRegexp>(&EpgfixerRegexps));
+ return AddSubMenu(new cMenuSetupConfigEditor<cRegexp, cEvent>(&EpgfixerRegexps));
else if (state == osUser2)
- return AddSubMenu(new cMenuSetupConfigEditor<cCharSet>(&EpgfixerCharSets));
+ return AddSubMenu(new cMenuSetupConfigEditor<cCharSet, cEvent>(&EpgfixerCharSets));
+ else if (state == osUser3)
+ return AddSubMenu(new cMenuSetupConfigEditor<cBlacklist, cChannel>(&EpgfixerBlacklists));
+ else if (state == osUser4)
+ return AddSubMenu(new cMenuSetupConfigEditor<cEpgClone, cEvent>(&EpgfixerEpgClones));
return state;
}
diff --git a/tools.c b/tools.c
index c15c983..afc3848 100644
--- a/tools.c
+++ b/tools.c
@@ -6,6 +6,7 @@
*/
#include "tools.h"
+#include <vdr/thread.h>
//
// HTML conversion code taken from RSS Reader plugin for VDR
@@ -152,6 +153,81 @@ char *striphtml(char *str)
return NULL;
}
+// --- cAddEventThread ----------------------------------------
+
+class cAddEventListItem : public cListObject
+{
+protected:
+ cEvent *event;
+ tChannelID channelID;
+public:
+ cAddEventListItem(cEvent *Event, tChannelID ChannelID) { event = Event; channelID = ChannelID; }
+ tChannelID GetChannelID() { return channelID; }
+ cEvent *GetEvent() { return event; }
+ ~cAddEventListItem() { }
+};
+
+class cAddEventThread : public cThread
+{
+private:
+ time_t LastHandleEvent;
+ cList<cAddEventListItem> *list;
+protected:
+ virtual void Action(void);
+public:
+ cAddEventThread(void);
+ ~cAddEventThread(void) { list->cList::Clear(); }
+ void AddEvent(cEvent *Event, tChannelID ChannelID);
+};
+
+cAddEventThread::cAddEventThread(void)
+:cThread("add events to schedule")
+{
+ LastHandleEvent = time(NULL);
+ list = new cList<cAddEventListItem>;
+ SetPriority(19);
+}
+
+void cAddEventThread::Action(void)
+{
+ if (Running()) {
+ cAddEventListItem *e = list->First();
+ while (e) {
+ cAddEventListItem *d = NULL;
+ cSchedulesLock SchedulesLock(true, 10);
+ cSchedules *schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
+ if (schedules) {
+ ((cSchedule *)schedules->GetSchedule(Channels.GetByChannelID(e->GetChannelID()), true))->AddEvent(e->GetEvent());
+ d = e;
+ }
+ e = list->Next(e);
+ if (d)
+ list->Del(d);
+ }
+ if (time(NULL) - LastHandleEvent > 10)
+ Cancel();
+ }
+}
+
+void cAddEventThread::AddEvent(cEvent *Event, tChannelID ChannelID)
+{
+ LastHandleEvent = time(NULL);
+ list->Add(new cAddEventListItem(Event, ChannelID));
+}
+
+static cAddEventThread AddEventThread;
+
+// ---
+
+void AddEvent(cEvent *Event, tChannelID ChannelID)
+{
+ if (!AddEventThread.Active())
+ AddEventThread.Start();
+ AddEventThread.AddEvent(Event, ChannelID);
+}
+
+// --- Listitem ----------------------------------------
+
cListItem::cListItem()
{
enabled = false;
@@ -205,7 +281,7 @@ bool cListItem::IsActive(tChannelID ChannelID)
bool found = false;
int i = 0;
while (i < numchannels) {
- if ((Channels.GetByChannelID(ChannelID)->Number() == GetChannelNum(i)) ||
+ if ((Channels.GetByChannelID(ChannelID)->Number() == GetChannelNum(i)) ||
(GetChannelID(i) && strcmp(*(ChannelID.ToString()), GetChannelID(i)) == 0)) {
found = true;
break;
@@ -239,9 +315,9 @@ int cListItem::LoadChannelsFromString(const char *string)
while (i < numchannels) {
// Use channel numbers
if (atoi(string))
- (channels_num)[i] = atoi(pc);
+ channels_num[i] = atoi(pc);
else// use channel IDs
- (channels_str)[i] = strdup(pc);
+ channels_str[i] = strdup(pc);
pc = strtok(NULL, ",");
++i;
}
@@ -254,3 +330,9 @@ void cListItem::ToggleEnabled(void)
{
enabled = !enabled;
}
+
+void cListItem::PrintConfigLineToFile(FILE *f)
+{
+ if (f)
+ fprintf(f, "%s%s\n", (!enabled && string && *string != '#') ? "!" : "", string);
+}
diff --git a/tools.h b/tools.h
index bf49fac..ebeeb76 100644
--- a/tools.h
+++ b/tools.h
@@ -17,6 +17,8 @@
#define FREE(x) { free(x); x = NULL; }
+void AddEvent(cEvent *event, tChannelID ChannelID);
+
char *striphtml(char *str);
class cListItem : public cListObject
@@ -35,62 +37,76 @@ protected:
public:
cListItem();
virtual ~cListItem();
+ virtual bool Apply(cChannel *Channel) { return 0; }
virtual bool Apply(cEvent *Event) { return 0; }
void SetFromString(char *string, bool Enabled);
const char *GetString() { return string; }
bool Enabled(void) { return enabled; }
void ToggleEnabled(void);
- virtual void PrintConfigLineToFIle(FILE *f) {}
+ void PrintConfigLineToFile(FILE *f);
};
-template<class T> class cEpgfixerList : public cList<T>
+template<class LISTITEM, class PARAMETER> class cEpgfixerList : public cList<LISTITEM>
{
protected:
char *fileName;
- bool LoadConfigFile(const char *FileName = NULL, bool AllowComments = true)
+ bool LoadConfigFile(bool AllowComments = true)
{
bool result = false;
- if (FileName && access(FileName, F_OK) == 0) {
- FILE *f = fopen(FileName, "r");
+ if (fileName && access(fileName, F_OK) == 0) {
+ FILE *f = fopen(fileName, "r");
if (f) {
char *s;
+ int line = 0;
+ int count = 0;
cReadLine ReadLine;
+ cString logmsg("");
+ logmsg = cString::sprintf("%s%s loaded. Active lines:", *logmsg, fileName);
while ((s = ReadLine.Read(f)) != NULL) {
+ ++line;
if (!isempty(s)) {
- this->Add(new T());
- cList<T>::Last()->SetFromString(s, true);
+ this->Add(new LISTITEM());
+ cList<LISTITEM>::Last()->SetFromString(s, true);
+ if (cList<LISTITEM>::Last()->Enabled()) {
+ ++count;
+ logmsg = cString::sprintf("%s%s%i", *logmsg, count == 1 ? " " : ",", line);
+ }
}
}
fclose(f);
+ if (count == 0)
+ logmsg = cString::sprintf("%s none", *logmsg);
+ isyslog("%s", *logmsg);
}
else {
- LOG_ERROR_STR(FileName);
+ LOG_ERROR_STR(fileName);
result = false;
}
}
+ ;
return result;
}
public:
cEpgfixerList() { fileName = NULL; }
~cEpgfixerList() { free(fileName); }
- void Clear(void) { cList<T>::Clear(); }
+ void Clear(void) { cList<LISTITEM>::Clear(); }
bool ReloadConfigFile(bool AllowComments = true)
{
Clear();
- return LoadConfigFile(fileName, AllowComments);
+ return LoadConfigFile(AllowComments);
}
- bool Apply(cEvent *Event)
+ bool Apply(PARAMETER *Parameter)
{
int res = false;
- T *item = (T *)(cList<T>::First());
+ LISTITEM *item = (LISTITEM *)(cList<LISTITEM>::First());
while (item) {
if (item->Enabled()) {
- int ret = item->Apply(Event);
+ int ret = item->LISTITEM::Apply(Parameter);
if (ret && !res)
res = true;
}
- item = (T *)(item->Next());
+ item = (LISTITEM *)(item->Next());
}
return res;
}