summaryrefslogtreecommitdiff
path: root/patches
diff options
context:
space:
mode:
authorhorchi <vdr@jwendel.de>2017-03-05 14:51:57 +0100
committerhorchi <vdr@jwendel.de>2017-03-05 14:51:57 +0100
commit5eacf5bf36ddbac082a9e40a2bcdfd0f04fd3f9f (patch)
tree392875cb707b94aaba9d8941113eae35efaf2ec2 /patches
downloadvdr-plugin-epg2vdr-5eacf5bf36ddbac082a9e40a2bcdfd0f04fd3f9f.tar.gz
vdr-plugin-epg2vdr-5eacf5bf36ddbac082a9e40a2bcdfd0f04fd3f9f.tar.bz2
commit of actual revision1.1.441.1.42
Diffstat (limited to 'patches')
-rw-r--r--patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch65
-rw-r--r--patches/vdr-1.7.27-to-epghandler-of-1.7.31.patch219
-rw-r--r--patches/vdr-1.7.28-epghandledexternally.diff118
-rw-r--r--patches/vdr-1.7.29-epgIsUpdate.diff52
-rw-r--r--patches/vdr-2.3.1.patch11
-rw-r--r--patches/vdr-2.3.2.patch56
6 files changed, 521 insertions, 0 deletions
diff --git a/patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch b/patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch
new file mode 100644
index 0000000..8374a66
--- /dev/null
+++ b/patches/pre-vdr-2.1.x--epghandler-segment-transfer.patch
@@ -0,0 +1,65 @@
+--- ../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
new file mode 100644
index 0000000..7be1802
--- /dev/null
+++ b/patches/vdr-1.7.27-to-epghandler-of-1.7.31.patch
@@ -0,0 +1,219 @@
+--- /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
new file mode 100644
index 0000000..52dfab6
--- /dev/null
+++ b/patches/vdr-1.7.28-epghandledexternally.diff
@@ -0,0 +1,118 @@
+--- ./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
new file mode 100644
index 0000000..61549ca
--- /dev/null
+++ b/patches/vdr-1.7.29-epgIsUpdate.diff
@@ -0,0 +1,52 @@
+--- ../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.3.1.patch b/patches/vdr-2.3.1.patch
new file mode 100644
index 0000000..c37bb54
--- /dev/null
+++ b/patches/vdr-2.3.1.patch
@@ -0,0 +1,11 @@
+--- ../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.patch b/patches/vdr-2.3.2.patch
new file mode 100644
index 0000000..102b362
--- /dev/null
+++ b/patches/vdr-2.3.2.patch
@@ -0,0 +1,56 @@
+--- ../vdr-2.3.2.plain//./epg.c 2015-09-10 12:58:19.000000000 +0200
++++ ./epg.c 2017-02-09 18:40:29.597671711 +0100
+@@ -1527,12 +1527,13 @@
+ Schedule->DropOutdated(SegmentStart, SegmentEnd, TableID, Version);
+ }
+
+-void cEpgHandlers::BeginSegmentTransfer(const cChannel *Channel)
++bool cEpgHandlers::BeginSegmentTransfer(const cChannel *Channel)
+ {
+ for (cEpgHandler *eh = First(); eh; eh = Next(eh)) {
+- if (eh->BeginSegmentTransfer(Channel, false))
+- return;
++ if (!eh->BeginSegmentTransfer(Channel, false))
++ return false;
+ }
++ return true;
+ }
+
+ void cEpgHandlers::EndSegmentTransfer(bool Modified)
+--- ../vdr-2.3.2.plain//./eit.c 2015-08-23 12:43:36.000000000 +0200
++++ ./eit.c 2017-02-09 18:40:29.597671711 +0100
+@@ -67,8 +67,13 @@
+ return;
+ }
+
++ if (!EpgHandlers.BeginSegmentTransfer(Channel)) {
++ SchedulesStateKey.Remove(false);
++ ChannelsStateKey.Remove(false);
++ return;
++ }
++
+ bool ChannelsModified = false;
+- EpgHandlers.BeginSegmentTransfer(Channel);
+ bool handledExternally = EpgHandlers.HandledExternally(Channel);
+ cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(Channel, true);
+
+--- ../vdr-2.3.2.plain//./epg.h 2015-08-09 13:25:04.000000000 +0200
++++ ./epg.h 2017-02-09 18:40:29.601671655 +0100
+@@ -66,7 +66,7 @@
+
+ class cSchedule;
+
+-typedef u_int16_t tEventID;
++typedef u_int32_t tEventID;
+
+ class cEvent : public cListObject {
+ friend class cSchedule;
+@@ -311,7 +311,7 @@
+ 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 BeginSegmentTransfer(const cChannel *Channel);
+ void EndSegmentTransfer(bool Modified);
+ };
+