diff options
-rw-r--r-- | HISTORY.h | 11 | ||||
-rw-r--r-- | Make.config | 9 | ||||
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | README | 3 | ||||
-rw-r--r-- | epg2vdr.c | 32 | ||||
-rw-r--r-- | epg2vdr.h | 1 | ||||
-rw-r--r-- | lib/Makefile | 6 | ||||
-rw-r--r-- | lib/test.c | 12 | ||||
-rw-r--r-- | menu.h | 6 | ||||
-rw-r--r-- | menusched.c | 91 | ||||
-rw-r--r-- | patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch | 65 | ||||
-rw-r--r-- | patches/vdr-1.7.27-to-epghandler-of-1.7.31.patch | 219 | ||||
-rw-r--r-- | patches/vdr-1.7.28-epghandledexternally.diff | 118 | ||||
-rw-r--r-- | patches/vdr-1.7.29-epgIsUpdate.diff | 52 | ||||
-rw-r--r-- | patches/vdr-2.2.0-aux.patch | 79 | ||||
-rw-r--r-- | patches/vdr-2.3.1.patch | 11 | ||||
-rw-r--r-- | patches/vdr-2.3.2-aux.patch | 79 | ||||
-rw-r--r-- | service.c | 44 | ||||
-rw-r--r-- | service.h | 47 | ||||
-rw-r--r-- | ttools.c | 100 | ||||
-rw-r--r-- | ttools.h | 3 | ||||
-rw-r--r-- | update.c | 116 | ||||
-rw-r--r-- | update.h | 8 |
23 files changed, 348 insertions, 778 deletions
@@ -5,8 +5,8 @@ * */ -#define _VERSION "1.1.52" -#define VERSION_DATE "2103.2017" +#define _VERSION "1.1.54" +#define VERSION_DATE "23.03.2017" #define DB_API 4 @@ -19,7 +19,12 @@ /* * ------------------------------------ -2017-03-21 version 1.1.52(horchi) +2017-03-22 version 1.1.53 (horchi) + - change: Removed old patches for vdr < 2.2.0 + - added: Patch to extend cEvent with aux field like cTimer + - change: Moved user defines from Makefile to Make.config + +2017-03-21 version 1.1.52 (horchi) - bugfix: crash in EPG menu 2017-03-20: version 1.1.51 (horchi) diff --git a/Make.config b/Make.config index 66bf692..6deeb4c 100644 --- a/Make.config +++ b/Make.config @@ -7,7 +7,14 @@ # user defined stuff -PREFIX = /usr/local +PREFIX = /usr/local + +# enable AUX patch, in VDR >= 2.3.3 not needed! +WITH_AUX_PATCH = 1 + +# enable graphtftng and/or pin plugin support if autodetection below don't work +#WITH_GTFT = 1 +#WITH_PIN = 1 DEBUG = 1 #USE_CLANG = 1 @@ -8,10 +8,6 @@ HISTFILE = "HISTORY.h" include Make.config -# enable graphtftng and/or pin plugin support if autodetection below don't work -#WITH_GTFT = 1 -#WITH_PIN = 1 - ### The version number of this plugin (taken from the main source file): VERSION = $(shell grep 'define _VERSION ' $(HISTFILE) | awk '{ print $$3 }' | sed -e 's/[";]//g') @@ -71,8 +67,10 @@ OBJS = $(PLUGIN).o \ menu.o menusched.o menutimers.o menudone.o menusearchtimer.o LIBS = $(HLIB) -LIBS += -lrt -larchive -lcrypto -luuid -LIBS += $(shell mysql_config --libs_r) $(shell python-config --libs) $(shell pkg-config --cflags --libs jansson) +LIBS += -lrt -larchive -lcrypto +LIBS += $(shell pkg-config --libs uuid) +LIBS += $(shell pkg-config --libs tinyxml2) +LIBS += $(shell mysql_config --libs_r) $(shell python-config --libs) $(shell pkg-config --libs jansson) EPG2VDR_DATA_DIR = "/var/cache/vdr" @@ -84,6 +82,10 @@ ifdef WITH_PIN DEFINES += -DWITH_PIN endif +ifdef WITH_AUX_PATCH + DEFINES += -DWITH_AUX_PATCH +endif + ifdef EPG2VDR_DATA_DIR DEFINES += -DEPG2VDR_DATA_DIR='$(EPG2VDR_DATA_DIR)' endif @@ -25,6 +25,7 @@ Requirements: - python libpython libpython-dev python-dev - libjansson4 libjansson-dev - uuid-dev + - libtinyxml2-dev Ubuntu (16.04): - libarchive13, libarchive-dev @@ -32,7 +33,7 @@ Ubuntu (16.04): - libjansson4 libjansson-dev - python libpython libpython-dev python-dev - uuid-dev - + - libtinyxml2-dev Description: ------------ @@ -872,14 +872,6 @@ bool cPluginEPG2VDR::Service(const char* id, void* data) return timerService(ts); } - else if (strcmp(id, EPG2VDR_EVENT_SERVICE) == 0) - { - cEpgEvent_Service_V1* es = (cEpgEvent_Service_V1*)data; - - if (es) - return eventService(es); - } - exitDb(); } @@ -919,30 +911,6 @@ int cPluginEPG2VDR::timerService(cEpgTimer_Service_V1* ts) } //*************************************************************************** -// Event Service -//*************************************************************************** - -int cPluginEPG2VDR::eventService(cEpgEvent_Service_V1* es) -{ - int status = false; - - es->out = 0; - - if (!es->in) - return false; - - es->out = createEventCopy(es->in); - - useeventsDb->clear(); - useeventsDb->setValue("USEID", (int)es->in->EventID()); - - enrichEvent((cEpgEvent*)es->out, useeventsDb, selectEventById); - status = true; - - return status; -} - -//*************************************************************************** // Initialize //*************************************************************************** @@ -64,7 +64,6 @@ class cPluginEPG2VDR : public cPlugin int exitDb(); int timerService(cEpgTimer_Service_V1* ts); - int eventService(cEpgEvent_Service_V1* es); private: diff --git a/lib/Makefile b/lib/Makefile index 789bf93..5e4f4b3 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -12,7 +12,7 @@ HLIB = -L. -lhorchi DEMO = demo TEST = tst -LIBOBJS = common.o config.o db.o epgservice.o dbdict.o json.o +LIBOBJS = common.o config.o db.o epgservice.o dbdict.o json.o xml.o ifdef USEJPEG LIBOBJS += imgtools.o @@ -29,6 +29,7 @@ BASELIBS = -lrt BASELIBS += $(shell mysql_config --libs_r) BASELIBS += $(shell pkg-config --libs uuid) BASELIBS += $(shell pkg-config --libs zlib) +BASELIBS += $(shell pkg-config --libs tinyxml2) ifdef USECURL BASELIBS += -lcurl @@ -105,7 +106,8 @@ db.o : db.c $(HEADER) db.h epgservice.o : epgservice.c $(HEADER) epgservice.h dbdict.o : dbdict.c $(HEADER) dbdict.h json.o : json.c $(HEADER) json.h -python.o : python.c $(HEADER) python.h +xml.o : xml.c $(HEADER) xml.h +python.o : python.c $(HEADER) python.h searchtimer.o : searchtimer.c $(HEADER) searchtimer.h demo.o : demo.c $(HEADER) @@ -17,6 +17,7 @@ #include "db.h" #include "epgservice.h" #include "dbdict.h" +#include "xml.h" //#include "wol.h" cDbConnection* connection = 0; @@ -643,6 +644,17 @@ int main(int argc, char** argv) cEpgConfig::logstdout = yes; cEpgConfig::loglevel = 2; + + cXml xml; + + xml.set("<epg2vdr><imagecount>3</imagecount><scrseriesid>255974</scrseriesid><year>2017</year><category>Serie</category><country>D</country><genre>Thiller</genre><director>Franzi Hörisch</director><actor>Cheryl Shepard (Sydney), Mickey Hardt (Mathis), David C. Bunners (Holger), Constantin Lücke (Patrick), Gerry Hungbauer (Thomas), Brigitte Antonius (Johanna), Hermann Toelcke (Gunter), Anja Franke (Merle), Claus Dieter Clausnitzer (Hannes), Maria Fuchs (Carla), Joachim Kretzer (Torben), Madeleine Lierck-Wien (Erika), Jelena Mitschke (Britta), Hakim-Michael Meziani (Ben)</actor><source>DVB/TVSP</source><longdescription>Killer ...Verbundenheit mit der Familie seines Vaters.</longdescription></epg2vdr>"); + + for (XMLElement* e = xml.getFirst(); e; e = xml.getNext(e)) + printf("%s [%s]\n", e->Name(), e->GetText()); + + printf("[%s]\n", xml.toText()); + return 0; + tell(0, "'%s' - '%s'", getIpOf("enp3s0"), getMacOf("enp3s0")); return 0; @@ -410,10 +410,9 @@ class cMenuEpgScheduleItem : public cOsdItem virtual int Compare(const cListObject &ListObject) const; virtual bool Update(bool Force = false); - virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); + virtual void SetMenuItem(cSkinDisplayMenu* DisplayMenu, int Index, bool Current, bool Selectable); - cEpgEvent* epgEvent; - const cEvent* vdrEvent; + const cEvent* event; const cChannel* channel; bool withDate; int timerMatch; @@ -421,7 +420,6 @@ class cMenuEpgScheduleItem : public cOsdItem private: cMenuDb* menuDb; - int eventReady; static eScheduleSortMode sortMode; }; diff --git a/menusched.c b/menusched.c index 7dbf30c..1b66c60 100644 --- a/menusched.c +++ b/menusched.c @@ -64,7 +64,7 @@ eOSState cEpgCommandMenu::ProcessKey(eKeys key) case osUser1: { if (item) - return AddSubMenu(new cMenuEpgWhatsOn(item->epgEvent)); + return AddSubMenu(new cMenuEpgWhatsOn(item->event)); break; } @@ -72,7 +72,7 @@ eOSState cEpgCommandMenu::ProcessKey(eKeys key) case osUser2: { if (item) - return AddSubMenu(new cMenuEpgMatchRecordings(menuDb, item->epgEvent)); + return AddSubMenu(new cMenuEpgMatchRecordings(menuDb, item->event)); break; } @@ -194,29 +194,8 @@ cMenuEpgScheduleItem::eScheduleSortMode cMenuEpgScheduleItem::sortMode = ssmAllT cMenuEpgScheduleItem::cMenuEpgScheduleItem(cMenuDb* db, const cEvent* Event, const cChannel* Channel, bool WithDate) { - epgEvent = 0; - eventReady = no; menuDb = db; - vdrEvent = Event; - - if (Event) - { - FILE* inMem = 0; - char* bp; - size_t size; - - if ((inMem = open_memstream(&bp, &size))) - { - Event->Dump(inMem, "", yes); - fflush(inMem); - fclose(inMem); - - epgEvent = new cEpgEvent(Event->EventID()); - inMem = fmemopen(bp, strlen(bp), "r"); - epgEvent->Read(inMem); - fclose(inMem); - } - } + event = Event; channel = Channel; withDate = WithDate; @@ -226,7 +205,6 @@ cMenuEpgScheduleItem::cMenuEpgScheduleItem(cMenuDb* db, const cEvent* Event, cMenuEpgScheduleItem::~cMenuEpgScheduleItem() { - delete epgEvent; } //*************************************************************************** @@ -239,10 +217,10 @@ int cMenuEpgScheduleItem::Compare(const cListObject &ListObject) const int r = -1; if (sortMode != ssmAllThis) - r = strcoll(vdrEvent->Title(), p->vdrEvent->Title()); + r = strcoll(event->Title(), p->event->Title()); if (sortMode == ssmAllThis || r == 0) - r = vdrEvent->StartTime() - p->vdrEvent->StartTime(); + r = event->StartTime() - p->event->StartTime(); return r; } @@ -260,39 +238,39 @@ bool cMenuEpgScheduleItem::Update(bool Force) int oldTimerMatch = timerMatch; int remote = no; - if (epgEvent) - menuDb->lookupTimer(epgEvent, timerMatch, remote); // -> loads timerDb, vdrDb and set ther timerMatch + if (event) + menuDb->lookupTimer(event, timerMatch, remote); // -> loads timerDb, vdrDb and set ther timerMatch if (Force || timerMatch != oldTimerMatch) { - if (timerMatch && epgEvent) - tell(0, "Timer match for '%s'", epgEvent->Title()); + if (timerMatch && event) + tell(0, "Timer match for '%s'", event->Title()); cString buffer; char t = !remote ? TimerMatchChars[timerMatch] : TimerMatchCharsRemote[timerMatch]; - char v = !epgEvent ? ' ' : epgEvent->Vps() && (epgEvent->Vps() - epgEvent->StartTime()) ? 'V' : ' '; - char r = !epgEvent ? ' ' : epgEvent->SeenWithin(30) && epgEvent->IsRunning() ? '*' : ' '; + char v = !event ? ' ' : event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' '; + char r = !event ? ' ' : event->SeenWithin(30) && event->IsRunning() ? '*' : ' '; const char* csn = channel ? channel->ShortName(true) : 0; - cString eds = !epgEvent ? "" : epgEvent->GetDateString(); + cString eds = !event ? "" : event->GetDateString(); if (channel && withDate) buffer = cString::sprintf("%d\t%.*s\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 999), csn, Utf8SymChars(eds, 6), *eds, - !epgEvent ? "" : *epgEvent->GetTimeString(), + !event ? "" : *event->GetTimeString(), t, v, r, - !epgEvent ? "" : epgEvent->Title()); + !event ? "" : event->Title()); else if (channel) buffer = cString::sprintf("%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 999), csn, - !epgEvent ? "" : *epgEvent->GetTimeString(), + !event ? "" : *event->GetTimeString(), t, v, r, - !epgEvent ? "" : epgEvent->Title()); + !event ? "" : event->Title()); else buffer = cString::sprintf("%.*s\t%s\t%c%c%c\t%s", Utf8SymChars(eds, 6), *eds, - !epgEvent ? "" : *epgEvent->GetTimeString(), - t, v, r, !epgEvent ? "" : - !epgEvent ? "" : epgEvent->Title()); + !event ? "" : *event->GetTimeString(), + t, v, r, !event ? "" : + !event ? "" : event->Title()); SetText(buffer); result = true; @@ -308,18 +286,7 @@ bool cMenuEpgScheduleItem::Update(bool Force) void cMenuEpgScheduleItem::SetMenuItem(cSkinDisplayMenu* DisplayMenu, int Index, bool Current, bool Selectable) { - if (epgEvent && !eventReady) - { - // lookup and enrich event with data of events table - - menuDb->useeventsDb->clear(); - menuDb->useeventsDb->setValue("USEID", (int)epgEvent->EventID()); - - enrichEvent(epgEvent, menuDb->useeventsDb, menuDb->selectEventById); - eventReady = yes; - } - - if (!DisplayMenu->SetItemEvent(epgEvent, Index, Current, Selectable, channel, + if (!DisplayMenu->SetItemEvent(event, Index, Current, Selectable, channel, withDate, (eTimerMatch)timerMatch)) { DisplayMenu->SetItem(Text(), Index, Current, Selectable); @@ -681,7 +648,7 @@ int cMenuEpgWhatsOn::LoadAt() if (item) { - scheduleEvent = item->epgEvent; + scheduleEvent = item->event; if (item->channel) currentChannel = item->channel->Number(); @@ -919,8 +886,8 @@ void cMenuEpgWhatsOn::Display() { int ni = 0; - for (cOsdItem *item = First(); item; item = Next(item)) - cStatus::MsgOsdEventItem(((cMenuEpgScheduleItem*)item)->epgEvent, item->Text(), ni++, Count()); + for (cOsdItem* item = First(); item; item = Next(item)) + cStatus::MsgOsdEventItem(((cMenuEpgScheduleItem*)item)->event, item->Text(), ni++, Count()); } #endif } @@ -1035,7 +1002,7 @@ eOSState cMenuEpgWhatsOn::Record() if (!item) return osContinue; - if ((timerid = menuDb->lookupTimer(item->epgEvent, timerMatch, remote))) // -> loads timerDb and vdrDb + if ((timerid = menuDb->lookupTimer(item->event, timerMatch, remote))) // -> loads timerDb and vdrDb { menuDb->timerDb->clear(); menuDb->timerDb->setValue("ID", timerid); @@ -1054,7 +1021,7 @@ eOSState cMenuEpgWhatsOn::Record() // neuen Timer anlegen - cDbRow* timerRow = newTimerRowFromEvent(item->vdrEvent); + cDbRow* timerRow = newTimerRowFromEvent(item->event); char timerDefaultVDRuuid[150+TB] = ""; menuDb->getParameter(menuDb->user.c_str(), "timerDefaultVDRuuid", timerDefaultVDRuuid); @@ -1124,7 +1091,7 @@ eOSState cMenuEpgWhatsOn::ProcessKey(eKeys Key) cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); if (item) - return AddSubMenu(new cMenuEpgWhatsOn(item->epgEvent)); + return AddSubMenu(new cMenuEpgWhatsOn(item->event)); } break; @@ -1137,7 +1104,7 @@ eOSState cMenuEpgWhatsOn::ProcessKey(eKeys Key) cMenuEpgScheduleItem* item = (cMenuEpgScheduleItem*)Get(Current()); if (item) - return AddSubMenu(new cMenuEpgMatchRecordings(menuDb, item->epgEvent)); + return AddSubMenu(new cMenuEpgMatchRecordings(menuDb, item->event)); } break; @@ -1165,7 +1132,7 @@ eOSState cMenuEpgWhatsOn::ProcessKey(eKeys Key) if (mi) { - scheduleEvent = mi->epgEvent; + scheduleEvent = mi->event; currentChannel = mi->channel->Number(); LoadSchedule(); } @@ -1209,7 +1176,7 @@ eOSState cMenuEpgWhatsOn::ProcessKey(eKeys Key) if (item) { - const cEvent* event = item->vdrEvent; + const cEvent* event = item->event; if (Count() && event) return AddSubMenu(new cMenuEpgEvent(menuDb, event, schedules, diff --git a/patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch b/patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch deleted file mode 100644 index 8374a66..0000000 --- a/patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch +++ /dev/null @@ -1,65 +0,0 @@ ---- ../vdr-2.0.2.plain//eit.c 2012-12-04 12:10:10.000000000 +0100 -+++ eit.c 2013-05-22 16:49:37.635027462 +0200 -@@ -46,6 +46,8 @@ - return; - } - -+ EpgHandlers.BeginSegmentTransfer(channel, OnlyRunningStatus); -+ - bool handledExternally = EpgHandlers.HandledExternally(channel); - cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true); - -@@ -310,6 +312,7 @@ - Schedules->SetModified(pSchedule); - } - Channels.Unlock(); -+ EpgHandlers.EndSegmentTransfer(Modified, OnlyRunningStatus); - } - - // --- cTDT ------------------------------------------------------------------ ---- ../vdr-2.0.2.plain//epg.c 2013-02-17 15:12:07.000000000 +0100 -+++ epg.c 2013-05-22 16:50:29.043029281 +0200 -@@ -1537,3 +1537,19 @@ - } - Schedule->DropOutdated(SegmentStart, SegmentEnd, TableID, Version); - } -+ -+void cEpgHandlers::BeginSegmentTransfer(const cChannel *Channel, bool OnlyRunningStatus) -+{ -+ for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -+ if (eh->BeginSegmentTransfer(Channel, OnlyRunningStatus)) -+ return; -+ } -+} -+ -+void cEpgHandlers::EndSegmentTransfer(bool Modified, bool OnlyRunningStatus) -+{ -+ for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -+ if (eh->EndSegmentTransfer(Modified, OnlyRunningStatus)) -+ return; -+ } -+} ---- ../vdr-2.0.2.plain//epg.h 2012-09-24 14:53:53.000000000 +0200 -+++ epg.h 2013-05-22 16:50:16.867028850 +0200 -@@ -273,6 +273,12 @@ - virtual bool DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version) { return false; } - ///< Takes a look at all EPG events between SegmentStart and SegmentEnd and - ///< drops outdated events. -+ virtual bool BeginSegmentTransfer(const cChannel *Channel, bool OnlyRunningStatus) { return false; } -+ ///< called directly after IgnoreChannel before any other handler method called -+ ///< designed to give handlers the ossibility to prepare a transaction -+ virtual bool EndSegmentTransfer(bool Modified, bool OnlyRunningStatus) { return false; } -+ ///< called at last after the segment data is processed -+ ///< at this oint handlers should close/commt/rollback their transactions - }; - - class cEpgHandlers : public cList<cEpgHandler> { -@@ -295,6 +301,8 @@ - void HandleEvent(cEvent *Event); - void SortSchedule(cSchedule *Schedule); - void DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version); -+ void BeginSegmentTransfer(const cChannel *Channel, bool OnlyRunningStatus); -+ void EndSegmentTransfer(bool Modified, bool OnlyRunningStatus); - }; - - extern cEpgHandlers EpgHandlers; diff --git a/patches/vdr-1.7.27-to-epghandler-of-1.7.31.patch b/patches/vdr-1.7.27-to-epghandler-of-1.7.31.patch deleted file mode 100644 index 7be1802..0000000 --- a/patches/vdr-1.7.27-to-epghandler-of-1.7.31.patch +++ /dev/null @@ -1,219 +0,0 @@ ---- /home/wendel/vdr-1.7.27.plain//eit.c 2012-03-14 11:11:15.000000000 +0100 -+++ eit.c 2012-10-01 09:38:51.526839349 +0200 -@@ -45,6 +45,7 @@ - return; - } - -+ bool handledExternally = EpgHandlers.HandledExternally(channel); - cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true); - - bool Empty = true; -@@ -70,14 +71,18 @@ - cEvent *newEvent = NULL; - cEvent *rEvent = NULL; - cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), StartTime); -- if (!pEvent) { -+ if (!pEvent || handledExternally) { - if (OnlyRunningStatus) - continue; -+ if (handledExternally) -+ if (!EpgHandlers.IsUpdate(SiEitEvent.getEventId(), StartTime, Tid, getVersionNumber())) -+ 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()); - newEvent->SetStartTime(StartTime); - newEvent->SetDuration(Duration); -+ if (!handledExternally) - pSchedule->AddEvent(newEvent); - } - else { -@@ -290,6 +295,9 @@ - channel->SetLinkChannels(LinkChannels); - Modified = true; - EpgHandlers.HandleEvent(pEvent); -+ -+ if (handledExternally) -+ delete pEvent; - } - if (Tid == 0x4E) { - if (Empty && getSectionNumber() == 0) ---- /home/wendel/vdr-1.7.27.plain//epg.c 2012-03-10 14:14:27.000000000 +0100 -+++ epg.c 2012-10-01 09:41:35.010845128 +0200 -@@ -18,6 +18,7 @@ - #include "timers.h" - - #define RUNNINGSTATUSTIMEOUT 30 // seconds before the running status is considered unknown -+#define EPGDATAWRITEDELTA 600 // seconds between writing the epg.data file - - // --- tComponent ------------------------------------------------------------ - -@@ -1109,6 +1110,47 @@ - return false; - } - -+// --- cEpgDataWriter --------------------------------------------------------- -+ -+class cEpgDataWriter : public cThread { -+private: -+ cMutex mutex; -+protected: -+ virtual void Action(void); -+public: -+ cEpgDataWriter(void); -+ void Perform(void); -+ }; -+ -+cEpgDataWriter::cEpgDataWriter(void) -+:cThread("epg data writer") -+{ -+} -+ -+void cEpgDataWriter::Action(void) -+{ -+ SetPriority(19); -+ SetIOPriority(7); -+ Perform(); -+} -+ -+void cEpgDataWriter::Perform(void) -+{ -+ cMutexLock MutexLock(&mutex); // to make sure fore- and background calls don't cause parellel dumps! -+ { -+ cSchedulesLock SchedulesLock(true, 1000); -+ cSchedules *s = (cSchedules *)cSchedules::Schedules(SchedulesLock); -+ if (s) { -+ time_t now = time(NULL); -+ for (cSchedule *p = s->First(); p; p = s->Next(p)) -+ p->Cleanup(now); -+ } -+ } -+ cSchedules::Dump(); -+} -+ -+static cEpgDataWriter EpgDataWriter; -+ - // --- cSchedulesLock -------------------------------------------------------- - - cSchedulesLock::cSchedulesLock(bool WriteLock, int TimeoutMs) -@@ -1152,28 +1194,13 @@ - if (Force) - lastDump = 0; - time_t now = time(NULL); -- struct tm tm_r; -- struct tm *ptm = localtime_r(&now, &tm_r); -- if (now - lastCleanup > 3600) { -- isyslog("cleaning up schedules data"); -- cSchedulesLock SchedulesLock(true, 1000); -- cSchedules *s = (cSchedules *)Schedules(SchedulesLock); -- if (s) { -- for (cSchedule *p = s->First(); p; p = s->Next(p)) -- p->Cleanup(now); -- } -- lastCleanup = now; -- if (ptm->tm_hour == 5) -- ReportEpgBugFixStats(true); -- } -- if (epgDataFileName && now - lastDump > 600) { -- cSafeFile f(epgDataFileName); -- if (f.Open()) { -- Dump(f); -- f.Close(); -+ if (now - lastDump > EPGDATAWRITEDELTA) { -+ if (epgDataFileName) { -+ if (Force) -+ EpgDataWriter.Perform(); -+ else if (!EpgDataWriter.Active()) -+ EpgDataWriter.Start(); - } -- else -- LOG_ERROR; - lastDump = now; - } - } -@@ -1207,8 +1234,23 @@ - cSchedulesLock SchedulesLock; - cSchedules *s = (cSchedules *)Schedules(SchedulesLock); - if (s) { -+ cSafeFile *sf = NULL; -+ if (!f) { -+ sf = new cSafeFile(epgDataFileName); -+ if (sf->Open()) -+ f = *sf; -+ else { -+ LOG_ERROR; -+ delete sf; -+ return false; -+ } -+ } - for (cSchedule *p = s->First(); p; p = s->Next(p)) - p->Dump(f, Prefix, DumpMode, AtTime); -+ if (sf) { -+ sf->Close(); -+ delete sf; -+ } - return true; - } - return false; -@@ -1329,6 +1371,24 @@ - return true; - } - return false; -+} -+ -+bool cEpgHandlers::HandledExternally(const cChannel *Channel) -+{ -+ for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -+ if (eh->HandledExternally(Channel)) -+ return true; -+ } -+ return false; -+} -+ -+bool cEpgHandlers::IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version) -+{ -+ for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -+ if (eh->IsUpdate(EventID, StartTime, TableID, Version)) -+ return true; -+ } -+ return false; - } - - void cEpgHandlers::SetEventID(cEvent *Event, tEventID EventID) ---- /home/wendel/vdr-1.7.27.plain//epg.h 2012-03-10 14:50:10.000000000 +0100 -+++ epg.h 2012-10-01 09:43:28.162849134 +0200 -@@ -207,7 +207,7 @@ - static void Cleanup(bool Force = false); - static void ResetVersions(void); - static bool ClearAll(void); -- static bool Dump(FILE *f, const char *Prefix = "", eDumpMode DumpMode = dmAll, time_t AtTime = 0); -+ static bool Dump(FILE *f = NULL, const char *Prefix = "", eDumpMode DumpMode = dmAll, time_t AtTime = 0); - static bool Read(FILE *f = NULL); - cSchedule *AddSchedule(tChannelID ChannelID); - const cSchedule *GetSchedule(tChannelID ChannelID) const; -@@ -244,6 +244,16 @@ - ///< EPG handlers are queried to see if any of them would like to do the - ///< complete processing by itself. TableID and Version are from the - ///< incoming section data. -+ virtual bool HandledExternally(const cChannel *Channel) { return false; } -+ ///< If any EPG handler returns true in this function, it is assumed that -+ ///< the EPG for the given Channel is handled completely from some external -+ ///< source. Incoming EIT data is processed as usual, but any new EPG event -+ ///< will not be added to the respective schedule. It's up to the EPG -+ ///< handler to take care of this. -+ virtual bool IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version) { return false; } -+ ///< VDR can't perform the update check (version, tid) for external handled events -+ ///< therefore the handle have to take care. Otherwise the parsing of 'non' updates will -+ ///< take a lot of resources - virtual bool SetEventID(cEvent *Event, tEventID EventID) { return false; } - virtual bool SetTitle(cEvent *Event, const char *Title) { return false; } - virtual bool SetShortText(cEvent *Event, const char *ShortText) { return false; } -@@ -269,6 +279,8 @@ - public: - bool IgnoreChannel(const cChannel *Channel); - bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version); -+ bool HandledExternally(const cChannel *Channel); -+ bool IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version); - void SetEventID(cEvent *Event, tEventID EventID); - void SetTitle(cEvent *Event, const char *Title); - void SetShortText(cEvent *Event, const char *ShortText); diff --git a/patches/vdr-1.7.28-epghandledexternally.diff b/patches/vdr-1.7.28-epghandledexternally.diff deleted file mode 100644 index 52dfab6..0000000 --- a/patches/vdr-1.7.28-epghandledexternally.diff +++ /dev/null @@ -1,118 +0,0 @@ ---- ./eit.c 2012/06/02 14:05:22 2.17 -+++ ./eit.c 2012/06/04 10:10:11 -@@ -45,6 +45,7 @@ - return; - } - -+ bool handledExternally = EpgHandlers.HandledExternally(channel); - cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(channel, true); - - bool Empty = true; -@@ -70,7 +71,7 @@ - cEvent *newEvent = NULL; - cEvent *rEvent = NULL; - cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), StartTime); -- if (!pEvent) { -+ if (!pEvent || handledExternally) { - if (OnlyRunningStatus) - continue; - // If we don't have that event yet, we create a new one. -@@ -78,7 +79,8 @@ - pEvent = newEvent = new cEvent(SiEitEvent.getEventId()); - newEvent->SetStartTime(StartTime); - newEvent->SetDuration(Duration); -- pSchedule->AddEvent(newEvent); -+ if (!handledExternally) -+ pSchedule->AddEvent(newEvent); - } - else { - // We have found an existing event, either through its event ID or its start time. -@@ -290,11 +292,8 @@ - channel->SetLinkChannels(LinkChannels); - Modified = true; - EpgHandlers.HandleEvent(pEvent); -- -- if (EpgHandlers.DeleteEvent(pEvent)) { -- pSchedule->DelEvent(pEvent); -- pEvent = NULL; -- } -+ if (handledExternally) -+ delete pEvent; - } - if (Tid == 0x4E) { - if (Empty && getSectionNumber() == 0) ---- ./epg.c 2012/06/02 14:08:12 2.14 -+++ ./epg.c 2012/06/04 10:06:22 -@@ -1331,6 +1331,15 @@ - return false; - } - -+bool cEpgHandlers::HandledExternally(const cChannel *Channel) -+{ -+ for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -+ if (eh->HandledExternally(Channel)) -+ return true; -+ } -+ return false; -+} -+ - void cEpgHandlers::SetEventID(cEvent *Event, tEventID EventID) - { - for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -@@ -1429,15 +1438,6 @@ - } - } - --bool cEpgHandlers::DeleteEvent(const cEvent *Event) --{ -- for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -- if (eh->DeleteEvent(Event)) -- return true; -- } -- return false; --} -- - void cEpgHandlers::SortSchedule(cSchedule *Schedule) - { - for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { ---- ./epg.h 2012/06/02 14:07:51 2.10 -+++ ./epg.h 2012/06/04 10:05:21 -@@ -244,6 +244,12 @@ - ///< EPG handlers are queried to see if any of them would like to do the - ///< complete processing by itself. TableID and Version are from the - ///< incoming section data. -+ virtual bool HandledExternally(const cChannel *Channel) { return false; } -+ ///< If any EPG handler returns true in this function, it is assumed that -+ ///< the EPG for the given Channel is handled completely from some external -+ ///< source. Incoming EIT data is processed as usual, but any new EPG event -+ ///< will not be added to the respective schedule. It's up to the EPG -+ ///< handler to take care of this. - virtual bool SetEventID(cEvent *Event, tEventID EventID) { return false; } - virtual bool SetTitle(cEvent *Event, const char *Title) { return false; } - virtual bool SetShortText(cEvent *Event, const char *ShortText) { return false; } -@@ -258,9 +264,6 @@ - virtual bool HandleEvent(cEvent *Event) { return false; } - ///< After all modifications of the Event have been done, the EPG handler - ///< can take a final look at it. -- virtual bool DeleteEvent(const cEvent *Event) { return false; } -- ///< After the complete processing of the Event is finished, an EPG handler -- ///< can decide that this Event shall be deleted from its schedule. - virtual bool SortSchedule(cSchedule *Schedule) { return false; } - ///< Sorts the Schedule after the complete table has been processed. - virtual bool DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version) { return false; } -@@ -272,6 +275,7 @@ - public: - bool IgnoreChannel(const cChannel *Channel); - bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version); -+ bool HandledExternally(const cChannel *Channel); - void SetEventID(cEvent *Event, tEventID EventID); - void SetTitle(cEvent *Event, const char *Title); - void SetShortText(cEvent *Event, const char *ShortText); -@@ -283,7 +287,6 @@ - void SetVps(cEvent *Event, time_t Vps); - void FixEpgBugs(cEvent *Event); - void HandleEvent(cEvent *Event); -- bool DeleteEvent(const cEvent *Event); - void SortSchedule(cSchedule *Schedule); - void DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version); - }; diff --git a/patches/vdr-1.7.29-epgIsUpdate.diff b/patches/vdr-1.7.29-epgIsUpdate.diff deleted file mode 100644 index 61549ca..0000000 --- a/patches/vdr-1.7.29-epgIsUpdate.diff +++ /dev/null @@ -1,52 +0,0 @@ ---- ../vdr-1.7.29.plain//eit.c 2012-06-04 12:26:10.000000000 +0200 -+++ eit.c 2012-07-30 10:19:34.841894485 +0200 -@@ -74,6 +74,9 @@ - if (!pEvent || handledExternally) { - if (OnlyRunningStatus) - continue; -+ if (handledExternally) -+ if (!EpgHandlers.IsUpdate(SiEitEvent.getEventId(), StartTime, Tid, getVersionNumber())) -+ 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()); ---- ../vdr-1.7.29.plain//epg.c 2012-06-04 12:26:10.000000000 +0200 -+++ epg.c 2012-07-30 10:21:51.153899306 +0200 -@@ -1340,6 +1340,15 @@ - return false; - } - -+bool cEpgHandlers::IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version) -+{ -+ for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { -+ if (eh->IsUpdate(EventID, StartTime, TableID, Version)) -+ return true; -+ } -+ return false; -+} -+ - void cEpgHandlers::SetEventID(cEvent *Event, tEventID EventID) - { - for (cEpgHandler *eh = First(); eh; eh = Next(eh)) { ---- ../vdr-1.7.29.plain//epg.h 2012-06-04 12:26:10.000000000 +0200 -+++ epg.h 2012-07-30 10:20:15.705895929 +0200 -@@ -250,6 +250,10 @@ - ///< source. Incoming EIT data is processed as usual, but any new EPG event - ///< will not be added to the respective schedule. It's up to the EPG - ///< handler to take care of this. -+ virtual bool IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version) { return false; } -+ ///< VDR can't perform the update check (version, tid) for external handled events -+ ///< therefore the handle have to take care. Otherwise the parsing of 'non' updates will -+ ///< take a lot of resources - virtual bool SetEventID(cEvent *Event, tEventID EventID) { return false; } - virtual bool SetTitle(cEvent *Event, const char *Title) { return false; } - virtual bool SetShortText(cEvent *Event, const char *ShortText) { return false; } -@@ -277,6 +281,7 @@ - bool IgnoreChannel(const cChannel *Channel); - bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version); - bool HandledExternally(const cChannel *Channel); -+ bool IsUpdate(tEventID EventID, time_t StartTime, uchar TableID, uchar Version); - void SetEventID(cEvent *Event, tEventID EventID); - void SetTitle(cEvent *Event, const char *Title); - void SetShortText(cEvent *Event, const char *ShortText); - diff --git a/patches/vdr-2.2.0-aux.patch b/patches/vdr-2.2.0-aux.patch new file mode 100644 index 0000000..749fb49 --- /dev/null +++ b/patches/vdr-2.2.0-aux.patch @@ -0,0 +1,79 @@ +--- ../vdr-2.2.0.plain/epg.c 2013-12-28 12:33:08.000000000 +0100 ++++ epg.c 2017-03-22 16:21:34.266665706 +0100 +@@ -122,6 +122,7 @@ + shortText = NULL; + description = NULL; + components = NULL; ++ aux = NULL; + memset(contents, 0, sizeof(contents)); + parentalRating = 0; + startTime = 0; +@@ -135,6 +136,7 @@ + free(title); + free(shortText); + free(description); ++ free(aux); + delete components; + } + +@@ -235,6 +237,12 @@ + seen = time(NULL); + } + ++void cEvent::SetAux(const char *Aux) ++{ ++ free(aux); ++ aux = Aux ? strdup(Aux) : NULL; ++} ++ + cString cEvent::ToDescr(void) const + { + char vpsbuf[64] = ""; +@@ -458,6 +466,11 @@ + } + if (vps) + fprintf(f, "%sV %ld\n", Prefix, vps); ++ if (!isempty(aux)) { ++ strreplace(aux, '\n', '|'); ++ fprintf(f, "%s@ %s\n", Prefix, aux); ++ strreplace(aux, '|', '\n'); ++ } + if (!InfoOnly) + fprintf(f, "%se\n", Prefix); + } +@@ -496,6 +509,9 @@ + break; + case 'V': SetVps(atoi(t)); + break; ++ case '@': strreplace(t, '|', '\n'); ++ SetAux(t); ++ break; + default: esyslog("ERROR: unexpected tag while reading EPG data: %s", s); + return false; + } +--- ../vdr-2.2.0.plain/epg.h 2013-08-23 12:50:05.000000000 +0200 ++++ epg.h 2017-03-22 16:23:28.096287585 +0100 +@@ -87,6 +87,7 @@ + int duration; // Duration of this event in seconds + time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL) + time_t seen; // When this event was last seen in the data stream ++ char *aux; + public: + cEvent(tEventID EventID); + ~cEvent(); +@@ -109,6 +110,7 @@ + time_t Vps(void) const { return vps; } + time_t Seen(void) const { return seen; } + bool SeenWithin(int Seconds) const { return time(NULL) - seen < Seconds; } ++ const char *Aux(void) const { return aux; } + bool HasTimer(void) const; + bool IsRunning(bool OrAboutToStart = false) const; + static const char *ContentToString(uchar Content); +@@ -131,6 +133,7 @@ + void SetDuration(int Duration); + void SetVps(time_t Vps); + void SetSeen(void); ++ void SetAux(const char *Aux); + cString ToDescr(void) const; + void Dump(FILE *f, const char *Prefix = "", bool InfoOnly = false) const; + bool Parse(char *s); diff --git a/patches/vdr-2.3.1.patch b/patches/vdr-2.3.1.patch deleted file mode 100644 index c37bb54..0000000 --- a/patches/vdr-2.3.1.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- ../vdr-2.3.2.plain/./epg.h 2015-08-09 13:25:04.000000000 +0200 -+++ ./epg.h 2017-02-08 14:42:26.304063928 +0100 -@@ -66,7 +66,7 @@ - - class cSchedule; - --typedef u_int16_t tEventID; -+typedef u_int32_t tEventID; - - class cEvent : public cListObject { - friend class cSchedule; diff --git a/patches/vdr-2.3.2-aux.patch b/patches/vdr-2.3.2-aux.patch new file mode 100644 index 0000000..fd3fe26 --- /dev/null +++ b/patches/vdr-2.3.2-aux.patch @@ -0,0 +1,79 @@ +--- ../vdr-2.3.2.plain//epg.c 2015-09-10 12:58:19.000000000 +0200 ++++ epg.c 2017-03-22 11:44:51.917258845 +0100 +@@ -124,6 +124,7 @@ + shortText = NULL; + description = NULL; + components = NULL; ++ aux = NULL; + memset(contents, 0, sizeof(contents)); + parentalRating = 0; + startTime = 0; +@@ -137,6 +138,7 @@ + free(title); + free(shortText); + free(description); ++ free(aux); + delete components; + } + +@@ -237,6 +239,12 @@ + seen = time(NULL); + } + ++void cEvent::SetAux(const char *Aux) ++{ ++ free(aux); ++ aux = Aux ? strdup(Aux) : NULL; ++} ++ + cString cEvent::ToDescr(void) const + { + char vpsbuf[64] = ""; +@@ -469,6 +477,11 @@ + } + if (vps) + fprintf(f, "%sV %ld\n", Prefix, vps); ++ if (!isempty(aux)) { ++ strreplace(aux, '\n', '|'); ++ fprintf(f, "%s@ %s\n", Prefix, aux); ++ strreplace(aux, '|', '\n'); ++ } + if (!InfoOnly) + fprintf(f, "%se\n", Prefix); + } +@@ -507,6 +520,9 @@ + break; + case 'V': SetVps(atoi(t)); + break; ++ case '@': strreplace(t, '|', '\n'); ++ SetAux(t); ++ break; + default: esyslog("ERROR: unexpected tag while reading EPG data: %s", s); + return false; + } +--- ../vdr-2.3.2.plain//epg.h 2015-08-09 13:25:04.000000000 +0200 ++++ epg.h 2017-03-22 11:33:19.319728545 +0100 +@@ -89,6 +89,7 @@ + int duration; // Duration of this event in seconds + time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL) + time_t seen; // When this event was last seen in the data stream ++ char *aux; + public: + cEvent(tEventID EventID); + ~cEvent(); +@@ -111,6 +112,7 @@ + time_t Vps(void) const { return vps; } + time_t Seen(void) const { return seen; } + bool SeenWithin(int Seconds) const { return time(NULL) - seen < Seconds; } ++ const char *Aux(void) const { return aux; } + void IncNumTimers(void) const; + void DecNumTimers(void) const; + bool HasTimer(void) const { return numTimers > 0; } +@@ -135,6 +137,7 @@ + void SetDuration(int Duration); + void SetVps(time_t Vps); + void SetSeen(void); ++ void SetAux(const char *Aux); + cString ToDescr(void) const; + void Dump(FILE *f, const char *Prefix = "", bool InfoOnly = false) const; + bool Parse(char *s); @@ -59,47 +59,3 @@ void cEpgTimer::setVdr(const char* name, const char* uuid, int running) if (!isEmpty(vdrUuid) && strcmp(vdrUuid, Epg2VdrConfig.uuid) != 0) local = no; } - -//*************************************************************************** -// Class cEpgEvent -//*************************************************************************** - -cEpgEvent::cEpgEvent(tEventID EventID) - : cEpgEvent_Interface_V1(EventID) -{ - -} - -bool cEpgEvent::Read(FILE *f) -{ - char *s; - int line = 0; - cReadLine ReadLine; - - while ((s = ReadLine.Read(f)) != NULL) { - line++; - char *t = skipspace(s + 1); - switch (*s) { - case 'E': { - unsigned int EventID; - time_t StartTime; - int Duration; - unsigned int TableID = 0; - unsigned int Version = 0xFF; // actual value is ignored - int n = sscanf(t, "%u %ld %d %X %X", &EventID, &StartTime, &Duration, &TableID, &Version); - if (n >= 3 && n <= 5) { - SetTableID(TableID); - SetStartTime(StartTime); - SetDuration(Duration); - } - break; - } - default: if (!Parse(s)) { - esyslog("ERROR: EPG data problem in line %d", line); - return false; - } - } - } - - return true; -} @@ -15,24 +15,6 @@ #include <map> //*************************************************************************** -// Event - Skin Interface -//*************************************************************************** - -class cEpgEvent_Interface_V1 : public cEvent -{ - public: - - cEpgEvent_Interface_V1(tEventID EventID) : cEvent(EventID) {} - - const char* getValue(const char* name) { return epg2vdrData[name].c_str(); } - const std::map<std::string,std::string>* getValues() const { return &epg2vdrData; } - - protected: - - std::map<std::string,std::string> epg2vdrData; -}; - -//*************************************************************************** // Timer - Skin Interface //*************************************************************************** @@ -87,18 +69,6 @@ struct cEpgTimer_Service_V1 #define EPG2VDR_TIMER_UPDATED "Epg2Vdr_Timer_Updated-v1.0" #define EPG2VDR_TIMER_SERVICE "Epg2Vdr_Timer_Service-v1.0" -//*************************************************************************** -// Event Service Interfaces -//*************************************************************************** - -struct cEpgEvent_Service_V1 -{ - const cEvent* in; - cEpgEvent_Interface_V1* out; -}; - -#define EPG2VDR_EVENT_SERVICE "Epg2Vdr_Event_Service-v1.0" - #ifdef EPG2VDR //*************************************************************************** @@ -108,23 +78,6 @@ struct cEpgEvent_Service_V1 //*************************************************************************** //*************************************************************************** -// Class cEpgEvent -//*************************************************************************** - -class cEpgEvent : public cEpgEvent_Interface_V1 -{ - public: - - cEpgEvent(tEventID EventID); - virtual ~cEpgEvent() {} - - bool Read(FILE *f); - - void setValue(const char* name, const char* value) { epg2vdrData[name] = value; } - void setValue(const char* name, long value) { epg2vdrData[name] = std::to_string(value); } -}; - -//*************************************************************************** // Class cEpgTimer //*************************************************************************** @@ -582,103 +582,3 @@ int updateTimerObjectFromRow(cTimer* timer, cDbRow* timerRow, const cEvent* even return done; } - -//*************************************************************************** -// Enrich Event -//*************************************************************************** - -int enrichEvent(cEpgEvent* event, cDbTable* table, cDbStatement* select) -{ - if (select->find()) - { - const char* fields[] = - { - "imagecount", // int - "numrating", // int - - "year", // ascii 10 - "channelid", // ascii 50 - "category", // ascii 50 - "country", // ascii 50 - "audio", // ascii 50 - - "txtrating", // ascii 100 - "genre", // ascii 100 - "flags", // ascii 100 - "commentator", // ascii 200 - "tipp", // ascii 250 - "rating", // ascii 250 - "moderator", // ascii 250 - "music", // ascii 250 - "screenplay", // ascii 500 - "shortreview", // ascii 500 - - "guest", // text 1000 - "producer", // text 1000 - "camera", // text 1000 - "director", // text 1000 - "topic", // ascii 1000 - - "other", // text 2000 - "shortdescription", // mtext 3000 - "actor", // mtext 5000 - "longdescription", // mtext 25000 - "cntlongdescription", // MText 25000 - - 0 - }; - - for (int i = 0; fields[i]; i++) - { - cDbValue* value = table->getValue(fields[i]); - - if (!value || value->isEmpty()) - continue; - - if (value->getField()->hasFormat(cDBS::ffAscii) || value->getField()->hasFormat(cDBS::ffText) || value->getField()->hasFormat(cDBS::ffMText)) - event->setValue(fields[i], value->getStrValue()); - else - event->setValue(fields[i], value->getIntValue()); - } - - std::string source = table->getStrValue("CNTSOURCE") + std::string("/") + table->getStrValue("SUBSOURCE"); - source = strReplace("vdr", "dvb", source); - // source = regex_replace(source, regex("vdr"), "dvb"); - event->setValue("source", source.c_str()); - } - else - { - tell(0, "Info: Event (%d) not found", event->EventID()); - } - - select->freeResult(); - - return done; -} - -//*************************************************************************** -// Copy Event -//*************************************************************************** - -cEpgEvent* createEventCopy(const cEvent* event) -{ - FILE* inMem = 0; - char* bp; - size_t size; - - if ((inMem = open_memstream(&bp, &size))) - { - event->Dump(inMem, "", yes); - fflush(inMem); - fclose(inMem); - - cEpgEvent* epgEvent = new cEpgEvent(event->EventID()); - inMem = fmemopen(bp, strlen(bp), "r"); - epgEvent->Read(inMem); - fclose(inMem); - - return epgEvent; - } - - return 0; -} @@ -37,9 +37,6 @@ int updateRowByTimer(cDbRow* timerDb, const cTimer* t); cEpgTimer* newTimerObjectFromRow(cDbRow* timerRow, cDbRow* vdrRow); int updateTimerObjectFromRow(cTimer* timer, cDbRow* timerRow, const cEvent* event); -int enrichEvent(cEpgEvent* event, cDbTable* table, cDbStatement* select); -cEpgEvent* createEventCopy(const cEvent* event); - //*************************************************************************** #endif // _TTOOLS_H_ @@ -10,11 +10,66 @@ #include <vdr/videodir.h> #include <vdr/tools.h> +#include "lib/xml.h" #include "epg2vdr.h" #include "update.h" #include "handler.h" //*************************************************************************** +// Events AUX Fields - stored as XML in cEvent:aux +//*************************************************************************** + +const char* cUpdate::auxFields[] = +{ +// field name type max size + + "imagecount", // int + "scrseriesid", // int + "scrseriesepisode", // int + "scrmovieid", // int + "numrating", // int + + "year", // ascii 10 + "category", // ascii 50 + "country", // ascii 50 + "audio", // ascii 50 + + "txtrating", // ascii 100 + "genre", // ascii 100 + "flags", // ascii 100 + "commentator", // ascii 200 + "tipp", // ascii 250 + "rating", // ascii 250 + "moderator", // ascii 250 + "music", // ascii 250 + "screenplay", // ascii 500 + "shortreview", // ascii 500 + + "guest", // text 1000 + "producer", // text 1000 + "camera", // text 1000 + "director", // text 1000 + "topic", // ascii 1000 + + "other", // text 2000 + "shortdescription", // mtext 3000 + "actor", // mtext 5000 + + "episodename", // ascii 100 + "episodeshortname", // ascii 100 + "episodepartname", // ascii 300 + "episodeextracol1", // ascii 250 + "episodeextracol2", // ascii 250 + "episodeextracol3", // ascii 250 + "episodeseason", // int + "episodepart", // int + "episodeparts", // int + "episodenumber", // int + + 0 +}; + +//*************************************************************************** // ctor //*************************************************************************** @@ -84,7 +139,9 @@ cUpdate::cUpdate(cPluginEPG2VDR* aPlugin) selectMaxUpdSp = 0; selectPendingTimerActions = 0; - dvbDescription = 0; + viewDescription = 0; + viewMergeSource = 0; + viewLongDescription = 0; // @@ -271,7 +328,9 @@ int cUpdate::initDb() // ------------------------------------------- // init db values - dvbDescription = new cDbValue("description", cDBS::ffText, 50000); + viewDescription = new cDbValue("description", cDBS::ffText, 50000); + viewMergeSource = new cDbValue("mergesource", cDBS::ffAscii, 25); + viewLongDescription = new cDbValue("longdescription", cDBS::ffText, 50000); // ------------------------------------------- // init statements @@ -403,7 +462,9 @@ int cUpdate::initDb() selectUpdEvents->bind("PARENTALRATING", cDBS::bndOut, ", "); selectUpdEvents->bind("VPS", cDBS::bndOut, ", "); selectUpdEvents->bind("CONTENTS", cDBS::bndOut, ", "); - selectUpdEvents->bind(dvbDescription, cDBS::bndOut, ", "); + selectUpdEvents->bind(viewDescription, cDBS::bndOut, ", "); + selectUpdEvents->bind(viewMergeSource, cDBS::bndOut, ", "); + selectUpdEvents->bind(viewLongDescription, cDBS::bndOut, ", "); selectUpdEvents->build(" from eventsview where "); selectUpdEvents->bind("CHANNELID", cDBS::bndIn | cDBS::bndSet); selectUpdEvents->bindCmp(0, "UPDSP", 0, ">", " and "); @@ -704,7 +765,9 @@ int cUpdate::exitDb() delete recordingDirDb; recordingDirDb = 0; delete recordingListDb; recordingListDb = 0; - delete dvbDescription; dvbDescription = 0; + delete viewDescription; viewDescription = 0; + delete viewMergeSource; viewMergeSource = 0; + delete viewLongDescription; viewLongDescription = 0; delete connection; connection = 0; @@ -1538,9 +1601,10 @@ cEvent* cUpdate::createEventFromRow(const cDbRow* row) e->SetDuration(row->getIntValue("DURATION")); e->SetParentalRating(row->getIntValue("PARENTALRATING")); e->SetVps(row->getIntValue("VPS")); - e->SetDescription(dvbDescription->getStrValue()); + e->SetDescription(viewDescription->getStrValue()); e->SetComponents(0); + // ------------ // contents uchar contents[MaxEventContents] = { 0 }; @@ -1556,6 +1620,7 @@ cEvent* cUpdate::createEventFromRow(const cDbRow* row) e->SetContents(contents); + // ------------ // components if (row->hasValue("SOURCE", "vdr")) @@ -1583,6 +1648,47 @@ cEvent* cUpdate::createEventFromRow(const cDbRow* row) delete components; } +#if (defined (APIVERSNUM) && (APIVERSNUM >= 20303)) || (WITH_AUX_PATCH) + + // ------------ + // aux + + useeventsDb->clear(); + useeventsDb->setValue("USEID", row->getIntValue("USEID")); + + if (selectEventById->find()) + { + cXml xml; + + xml.create("epg2vdr"); + + for (int i = 0; auxFields[i]; i++) + { + cDbValue* value = useeventsDb->getValue(auxFields[i]); + + if (!value || value->isEmpty()) + continue; + + if (value->getField()->hasFormat(cDBS::ffAscii) || value->getField()->hasFormat(cDBS::ffText) || value->getField()->hasFormat(cDBS::ffMText)) + xml.appendElement(auxFields[i], value->getStrValue()); + else + xml.appendElement(auxFields[i], value->getIntValue()); + } + + // finally add some fields of the view + + xml.appendElement("source", viewMergeSource->getStrValue()); + xml.appendElement("longdescription", viewLongDescription->getStrValue()); + + // set to events aux field + + e->SetAux(xml.toText()); + } + + selectEventById->freeResult(); + +#endif // WITH_AUX_PATCH + return e; } @@ -65,7 +65,7 @@ class cRunningRecording : public cListObject }; //*************************************************************************** -// Event Details +// Event Details (Recording Info Files) //*************************************************************************** class cEventDetails @@ -269,10 +269,14 @@ class cUpdate : public cThread, public cStatus, public cParameters cDbValue imageSize; cDbValue masterId; - cDbValue* dvbDescription; + cDbValue* viewDescription; + cDbValue* viewMergeSource; + cDbValue* viewLongDescription; std::queue<std::string> pendingNewRecordings; // recordings to store details std::vector<TimerId> deletedTimers; + + static const char* auxFields[]; }; //*************************************************************************** |