[vdr-plugin-epgsearch] 01/16: New upstream version 1.0.1~beta6+git20151104

Tobias Grimm tiber-guest at moszumanska.debian.org
Wed Dec 27 13:51:27 UTC 2017


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to branch master
in repository vdr-plugin-epgsearch.

commit 61c2053b4eb673357ced3d2d65dc8dff6cd03670
Author: Tobias Grimm <etobi at debian.org>
Date:   Sun Jan 8 09:59:27 2017 +0100

    New upstream version 1.0.1~beta6+git20151104
---
 MANUAL                                        |   1 +
 Makefile                                      |   2 +-
 README                                        |   2 +-
 README.DE                                     |   1 +
 blacklist.c                                   |  51 ++++++--
 blacklist.h                                   |  10 +-
 changrp.c                                     |  60 ++++++---
 changrp.h                                     |   6 +-
 conflictcheck.c                               |  41 ++++--
 conflictcheck.h                               |  17 ++-
 conflictcheck_thread.c                        |   2 +
 epgsearch.c                                   |  40 ++++--
 epgsearchext.c                                |  95 ++++++++++----
 epgsearchext.h                                |  12 +-
 epgsearchsvdrp.c                              |  44 +++++--
 epgsearchtools.c                              |  21 ++-
 epgsearchtools.h                              |  10 +-
 mail.c                                        |  37 +++++-
 mail.h                                        |   4 +-
 menu_blacklistedit.c                          |  10 +-
 menu_commands.c                               |  41 ++++--
 menu_conflictcheck.c                          |  83 +++++++++---
 menu_conflictcheck.h                          |   4 +-
 menu_deftimercheckmethod.c                    |  18 ++-
 menu_dirselect.c                              |  16 ++-
 menu_event.c                                  |  28 +++-
 menu_favorites.c                              |   8 +-
 menu_main.c                                   |  97 +++++++++++---
 menu_main.h                                   |   4 +-
 menu_myedittimer.c                            |  75 +++++++++--
 menu_quicksearch.c                            |  10 +-
 menu_searchedit.c                             |  10 +-
 menu_searchresults.c                          |  96 +++++++++++---
 menu_searchresults.h                          |   8 +-
 menu_switchtimers.c                           |   8 +-
 menu_templateedit.c                           |  10 +-
 menu_timersdone.c                             |   8 +-
 menu_whatson.c                                | 102 +++++++++++----
 menu_whatson.h                                |  16 +--
 patches/vdr.epgsearch-exttimeredit-2.3.1.diff | 114 +++++++++++++++++
 pending_notifications.c                       |   8 +-
 recdone.c                                     |  18 ++-
 recdone.h                                     |   2 +-
 recstatus.c                                   |  26 +++-
 recstatus.h                                   |  11 +-
 searchtimer_thread.c                          | 114 +++++++++++++----
 searchtimer_thread.h                          |  12 +-
 services.c                                    |  16 ++-
 recstatus.c => status_thread.c                | 177 ++++++++++++--------------
 recstatus.h => status_thread.h                |  52 +++++---
 switchtimer.c                                 |  17 ++-
 switchtimer_thread.c                          |  10 +-
 templatefile.c                                |   6 +
 timer_thread.c                                |   6 +
 timerdone.c                                   |  21 ++-
 uservars.h                                    |  42 +++++-
 56 files changed, 1337 insertions(+), 423 deletions(-)

diff --git a/MANUAL b/MANUAL
new file mode 120000
index 0000000..3631c85
--- /dev/null
+++ b/MANUAL
@@ -0,0 +1 @@
+./doc/en/epgsearch.4.txt
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 2ded06a..908fbdb 100644
--- a/Makefile
+++ b/Makefile
@@ -132,7 +132,7 @@ ifeq ($(WITHOUT_QUICKSEARCH), 0)
   ALL += libvdr-$(PLUGIN4).so
 endif
 
-OBJS = afuzzy.o blacklist.o changrp.o confdloader.o conflictcheck.o conflictcheck_thread.o distance.o $(PLUGIN).o epgsearchcats.o epgsearchcfg.o epgsearchext.o epgsearchsetup.o  epgsearchsvdrp.o epgsearchtools.o mail.o md5.o menu_announcelist.o menu_blacklistedit.o menu_blacklists.o menu_commands.o menu_conflictcheck.o menu_deftimercheckmethod.o menu_dirselect.o menu_event.o menu_favorites.o menu_main.o menu_myedittimer.o menu_quicksearch.o menu_recsdone.o menu_search.o menu_searchaction [...]
+OBJS = afuzzy.o blacklist.o changrp.o confdloader.o conflictcheck.o conflictcheck_thread.o distance.o $(PLUGIN).o epgsearchcats.o epgsearchcfg.o epgsearchext.o epgsearchsetup.o  epgsearchsvdrp.o epgsearchtools.o mail.o md5.o menu_announcelist.o menu_blacklistedit.o menu_blacklists.o menu_commands.o menu_conflictcheck.o menu_deftimercheckmethod.o menu_dirselect.o menu_event.o menu_favorites.o menu_main.o menu_myedittimer.o menu_quicksearch.o menu_recsdone.o menu_search.o menu_searchaction [...]
 
 ifeq ($(REGEXLIB), pcre)
 LIBS += $(shell pcre-config --libs-posix)
diff --git a/README b/README
index b16bb82..b18b191 120000
--- a/README
+++ b/README
@@ -1 +1 @@
-./doc/en/epgsearch.1.txt
\ No newline at end of file
+README.git
\ No newline at end of file
diff --git a/README.DE b/README.DE
new file mode 120000
index 0000000..f25d9bf
--- /dev/null
+++ b/README.DE
@@ -0,0 +1 @@
+./doc/de/epgsearch.1.txt
\ No newline at end of file
diff --git a/blacklist.c b/blacklist.c
index f6fd471..9f77155 100644
--- a/blacklist.c
+++ b/blacklist.c
@@ -47,8 +47,14 @@ cBlacklist::cBlacklist(void)
     startTime = 0000;
     stopTime = 2359;
     useChannel = false;
-    channelMin = Channels.GetByNumber(cDevice::CurrentChannel());
-    channelMax = Channels.GetByNumber(cDevice::CurrentChannel());
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    channelMin = vdrchannels->GetByNumber(cDevice::CurrentChannel());
+    channelMax = vdrchannels->GetByNumber(cDevice::CurrentChannel());
     channelGroup = NULL;
     useCase = false;
     mode = 0;
@@ -331,7 +337,13 @@ bool cBlacklist::Parse(const char *s)
 			char *channelMaxbuffer = NULL;
 			int channels = sscanf(value, "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer);
 #endif
-			channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
+#if VDRVERSNUM > 20300
+			LOCK_CHANNELS_READ;
+			const cChannels *vdrchannels = Channels;
+#else
+			cChannels *vdrchannels = &Channels;
+#endif
+			channelMin = vdrchannels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
 			if (!channelMin)
 			{
 			    LogFile.eSysLog("ERROR: channel %s not defined", channelMinbuffer);
@@ -342,7 +354,7 @@ bool cBlacklist::Parse(const char *s)
 			    channelMax = channelMin;
 			else
 			{
-			    channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
+			    channelMax = vdrchannels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
 			    if (!channelMax)
 			    {
 				LogFile.eSysLog("ERROR: channel %s not defined", channelMaxbuffer);
@@ -512,10 +524,10 @@ bool cBlacklist::Save(FILE *f)
   return fprintf(f, "%s\n", ToText()) > 0;
 }
 
-cEvent * cBlacklist::GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop)
+const cEvent * cBlacklist::GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop)
 {
-  cEvent *pe = NULL;
-  cEvent *p1 = NULL;
+  const cEvent *pe = NULL;
+  const cEvent *p1 = NULL;
 
   if (Start)
       p1 = schedules->Events()->Next(Start);
@@ -545,7 +557,7 @@ cEvent * cBlacklist::GetEventByBlacklist(const cSchedule *schedules, const cEven
       maxSearchDuration = maxDuration/100*60 + maxDuration%100;
   }
 
-  for (cEvent *p = p1; p; p = schedules->Events()->Next(p))
+  for (const cEvent *p = p1; p; p = schedules->Events()->Next(p))
   {
      if(!p)
      {
@@ -633,9 +645,14 @@ cSearchResults* cBlacklist::Run(cSearchResults* pSearchResults, int MarginStop)
 {
     LogFile.Log(3,"start search for blacklist '%s'", search);
 
-    cSchedulesLock schedulesLock;
     const cSchedules *schedules;
+#if VDRVERSNUM > 20300
+    LOCK_SCHEDULES_READ;
+    schedules = Schedules;
+#else
+    cSchedulesLock schedulesLock;
     schedules = cSchedules::Schedules(schedulesLock);
+#endif
     if(!schedules) {
 	LogFile.Log(1,"schedules are currently locked! try again later.");
 	return NULL;
@@ -644,7 +661,13 @@ cSearchResults* cBlacklist::Run(cSearchResults* pSearchResults, int MarginStop)
     const cSchedule *Schedule = schedules->First();
 
     while (Schedule) {
-	cChannel* channel = Channels.GetByChannelID(Schedule->ChannelID(),true,true);
+#if VDRVERSNUM > 20300
+	LOCK_CHANNELS_READ;
+	const cChannels *vdrchannels = Channels;
+#else
+	cChannels *vdrchannels = &Channels;
+#endif
+	const cChannel* channel = vdrchannels->GetByChannelID(Schedule->ChannelID(),true,true);
 	if (!channel)
 	{
 	    Schedule = (const cSchedule *)schedules->Next(Schedule);
@@ -682,7 +705,13 @@ cSearchResults* cBlacklist::Run(cSearchResults* pSearchResults, int MarginStop)
         do {
 	    const cEvent* event = GetEventByBlacklist(Schedule, pPrevEvent, MarginStop);
 	    pPrevEvent = event;
-	    if (event && Channels.GetByChannelID(event->ChannelID(),true,true))
+#if VDRVERSNUM > 20300
+	    LOCK_CHANNELS_READ;
+	    const cChannels *vdrchannels = Channels;
+#else
+	    cChannels *vdrchannels = &Channels;
+#endif
+	    if (event && vdrchannels->GetByChannelID(event->ChannelID(),true,true))
 	    {
 		if (!pSearchResults) pSearchResults = new cSearchResults;
 		pSearchResults->Add(new cSearchResult(event, this));
diff --git a/blacklist.h b/blacklist.h
index c38ea60..183b940 100644
--- a/blacklist.h
+++ b/blacklist.h
@@ -39,8 +39,8 @@ public:
   int      startTime;
   int      stopTime;
   int      useChannel;
-  cChannel *channelMin;
-  cChannel *channelMax;
+  const cChannel *channelMin;
+  const cChannel *channelMax;
   char*    channelGroup;
   int      useCase;
   int      mode;
@@ -70,9 +70,9 @@ public:
   int StartTime(void) { return startTime; }
   int StopTime(void) { return stopTime; }
   int UseChannel(void) { return useChannel; }
-  cChannel *ChannelMin(void) { return channelMin; }
-  cChannel *ChannelMax(void) { return channelMax; }
-  cEvent * GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop = 0);
+  const cChannel *ChannelMin(void) { return channelMin; }
+  const cChannel *ChannelMax(void) { return channelMax; }
+  const cEvent * GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop = 0);
   bool MatchesExtEPGInfo(const cEvent* e);
   const char *ToText(void);
   bool Parse(const char *s);
diff --git a/changrp.c b/changrp.c
index 66cd6a1..223273f 100644
--- a/changrp.c
+++ b/changrp.c
@@ -82,7 +82,13 @@ bool cChannelGroup::Parse(const char *s)
 #endif
 		if (numChannels == 1)
 		{
-		    cChannel* channel = Channels.GetByChannelID(tChannelID::FromString(channelbuffer), true, true);
+#if VDRVERSNUM > 20300
+		    LOCK_CHANNELS_READ;
+		    const cChannels *vdrchannels = Channels;
+#else
+		    cChannels *vdrchannels = &Channels;
+#endif
+		    const cChannel* channel = vdrchannels->GetByChannelID(tChannelID::FromString(channelbuffer), true, true);
 		    if (channel)
 		    {
 			cChannelGroupItem* channelitem = new cChannelGroupItem(channel);
@@ -110,7 +116,7 @@ const char *cChannelGroup::ToText(void)
     int index = 0;
     while (ChannelGroupItem)
     {
-	cChannel* channel = ChannelGroupItem->channel;
+	const cChannel* channel = ChannelGroupItem->channel;
 	if (index++ == 0)
 	    channelbuffer = strdup(CHANNELSTRING(channel));
 	else
@@ -129,14 +135,20 @@ const char *cChannelGroup::ToText(void)
 
 int* cChannelGroup::CreateChannelSel()
 {
-    int* channelSel = (int*) malloc(Channels.Count() * sizeof(int));
-    cChannel* channel = Channels.First();
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    int* channelSel = (int*) malloc(vdrchannels->Count() * sizeof(int));
+    const cChannel* channel = vdrchannels->First();
     int index = 0;
     while (channel)
     {
 	if (channel->GroupSep())
 	{
-	    channel = Channels.Next(channel);
+	    channel = vdrchannels->Next(channel);
 	    continue;
 	}
 	channelSel[index] = 0;
@@ -151,7 +163,7 @@ int* cChannelGroup::CreateChannelSel()
 	    channelInGroup = channels.Next(channelInGroup);
 	}
 	index++;
-	channel = Channels.Next(channel);
+	channel = vdrchannels->Next(channel);
     }
     return channelSel;
 }
@@ -159,7 +171,13 @@ int* cChannelGroup::CreateChannelSel()
 void cChannelGroup::CreateChannelList(int* channelSel)
 {
     channels.Clear();
-    cChannel* channel = Channels.First();
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel* channel = vdrchannels->First();
     int index = 0;
     while (channel)
     {
@@ -169,7 +187,7 @@ void cChannelGroup::CreateChannelList(int* channelSel)
 		channels.Add(new cChannelGroupItem(channel));
 	    index++;
 	}
-	channel = Channels.Next(channel);
+	channel = vdrchannels->Next(channel);
     }
 }
 
@@ -178,7 +196,7 @@ bool cChannelGroup::Save(FILE *f)
     return fprintf(f, "%s\n", ToText()) > 0;
 }
 
-bool cChannelGroup::ChannelInGroup(cChannel* channel)
+bool cChannelGroup::ChannelInGroup(const cChannel* channel)
 {
     cChannelGroupItem* channelInGroup = channels.First();
     while (channelInGroup)
@@ -432,17 +450,23 @@ void cMenuEditChannelGroup::Set()
     Clear();
 
     Add(new cMenuEditStrItem( tr("Group name"), name, sizeof(group->name), trVDR(FileNameChars)));
-    cChannel* channel = Channels.First();
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel* channel = vdrchannels->First();
     int index = 0;
     while (channel)
     {
 	if (channel->GroupSep())
 	{
-	    channel = Channels.Next(channel);
+	    channel = vdrchannels->Next(channel);
 	    continue;
 	}
 	Add(new cMenuEditBoolItem( CHANNELNAME(channel), &channelSel[index++], trVDR("no"), trVDR("yes")));
-	channel = Channels.Next(channel);
+	channel = vdrchannels->Next(channel);
     }
 
     SetCurrent(Get(current));
@@ -507,19 +531,25 @@ eOSState cMenuEditChannelGroup::ProcessKey(eKeys Key)
 	  case kGreen:
 	  case kYellow:
 	  {
-	      cChannel* channel = Channels.First();
+#if VDRVERSNUM > 20300
+	      LOCK_CHANNELS_READ;
+	      const cChannels *vdrchannels = Channels;
+#else
+	      cChannels *vdrchannels = &Channels;
+#endif
+	      const cChannel* channel = vdrchannels->First();
 	      int index = 0;
 	      while (channel)
 	      {
 		  if (channel->GroupSep())
 		  {
-		      channel = Channels.Next(channel);
+		      channel = vdrchannels->Next(channel);
 		      continue;
 		  }
 
 		  channelSel[index] = (Key == kGreen?1:(Key == kRed?1-channelSel[index]:0));
 		  index++;
-		  channel = Channels.Next(channel);
+		  channel = vdrchannels->Next(channel);
 	      }
 	      Set();
 	      Display();
diff --git a/changrp.h b/changrp.h
index 99a1ecc..1c5deb6 100644
--- a/changrp.h
+++ b/changrp.h
@@ -33,9 +33,9 @@ class cSearchExt;
 // --- cChannelGroupItem --------------------------------------------------------
 class cChannelGroupItem : public cListObject {
 public:
-    cChannel* channel;
+    const cChannel* channel;
 public:
-  cChannelGroupItem(cChannel* ch) : channel(ch) {}
+  cChannelGroupItem(const cChannel* ch) : channel(ch) {}
 };
 
 // --- cChannelGroup --------------------------------------------------------
@@ -52,7 +52,7 @@ public:
   bool Save(FILE *f);
   int* CreateChannelSel();
   void CreateChannelList(int*);
-  bool ChannelInGroup(cChannel*);
+  bool ChannelInGroup(const cChannel*);
 };
 
 // --- cChannelGroups --------------------------------------------------------
diff --git a/conflictcheck.c b/conflictcheck.c
index eb7fa57..4e9e2d3 100644
--- a/conflictcheck.c
+++ b/conflictcheck.c
@@ -73,12 +73,17 @@ const cEvent* cConflictCheckTimerObj::Event()
 
 const cEvent* cConflictCheckTimerObj::SetEventFromSchedule()
 {
+#if VDRVERSNUM > 20300
+    LOCK_SCHEDULES_READ;
+    const cSchedules *schedules = Schedules;
+#else
     cSchedulesLock SchedulesLock;
-    const cSchedules* Schedules = NULL;
-    if (!(Schedules = cSchedules::Schedules(SchedulesLock)))
+    const cSchedules* schedules = cSchedules::Schedules(SchedulesLock);
+#endif
+    if (!schedules)
 	return NULL;
 
-    const cSchedule *Schedule = Schedules->GetSchedule(timer->Channel());
+    const cSchedule *Schedule = schedules->GetSchedule(timer->Channel());
     if (Schedule && Schedule->Events()->First())
     {
 	const cEvent *Event = NULL;
@@ -262,8 +267,14 @@ cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList()
 
     // collect single event timers
     time_t tMax = 0;
-    cTimer* ti = NULL;
-    for (ti = Timers.First(); ti; ti = Timers.Next(ti))
+#if VDRVERSNUM > 20300
+    LOCK_TIMERS_READ;
+    const cTimers *vdrtimers = Timers;
+#else
+    const cTimers *vdrtimers = &Timers;
+#endif
+    const cTimer* ti = NULL;
+    for (ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti))
     {
 	tMax = max(tMax, ti->StartTime());
 	if (!ti->IsSingleEvent()) continue;
@@ -291,7 +302,7 @@ cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList()
     // collect repeating timers from now until the date of the timer with tMax
     time_t maxCheck = time(NULL) + min(14,EPGSearchConfig.checkMaxDays) * SECSINDAY;
     tMax = max(tMax, maxCheck);
-    for (ti = Timers.First(); ti; ti = Timers.Next(ti))
+    for (ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti))
     {
 	if (ti->IsSingleEvent()) continue;
 	time_t day = time(NULL);
@@ -669,7 +680,7 @@ void cConflictCheck::AddConflict(cConflictCheckTimerObj* TimerObj, cConflictChec
     LogFile.Log(3,"conflict found for timer '%s' (%s, channel %s)", TimerObj->timer->File(), DAYDATETIME(TimerObj->start), CHANNELNAME(TimerObj->timer->Channel()));
 }
 
-bool cConflictCheck::TimerInConflict(cTimer* timer)
+bool cConflictCheck::TimerInConflict(const cTimer* timer)
 {
     for(cConflictCheckTime* checkTime = failedList->First(); checkTime; checkTime = failedList->Next(checkTime))
     {
@@ -683,7 +694,13 @@ bool cConflictCheck::TimerInConflict(cTimer* timer)
 		{
 		    for (it2 = (*it)->concurrentTimers->begin(); it2 != (*it)->concurrentTimers->end(); ++it2)
 		    {
-			if ((*it2)->OrigTimer() == timer)
+#if VDRVERSNUM > 20300
+			LOCK_TIMERS_READ;
+			const cTimers *vdrtimers = Timers;
+#else
+			cTimers *vdrtimers = &Timers;
+#endif
+			if ((*it2)->OrigTimer(vdrtimers) == timer)
 			    return true;
 		    }
 		}
@@ -706,7 +723,13 @@ void cConflictCheck::EvaluateConflCheckCmd()
 	    if ((*it) && !(*it)->ignore)
 	      {
 		string result = EPGSearchConfig.conflCheckCmd;
-		if (!(*it)->OrigTimer())
+#if VDRVERSNUM > 20300
+		LOCK_TIMERS_READ;
+		const cTimers *vdrtimers = Timers;
+#else
+		cTimers *vdrtimers = &Timers;
+#endif
+		if (!(*it)->OrigTimer(vdrtimers))
 		  {
 		    LogFile.Log(3,"timer has disappeared meanwhile");
 		    continue;
diff --git a/conflictcheck.h b/conflictcheck.h
index 089c367..940f864 100644
--- a/conflictcheck.h
+++ b/conflictcheck.h
@@ -59,7 +59,20 @@ class cConflictCheckTimerObj : public cTimerObj
     const cEvent* Event();
     const cEvent* SetEventFromSchedule();
     int Matches(const cEvent *Event, int *Overlap) const;
-    cTimer* OrigTimer() {return Timers.GetTimer(timer); }
+    const cTimer* OrigTimer(const cTimers* timers) const
+    {
+      // http://www.vdr-portal.de/board1-news/board2-vdr-news/p1255344-/#post1255344
+      // if patch is accepted, change to
+      //return timers->GetTimer(timer);
+      return ((cTimers*)timers)->GetTimer((cTimer*)timer);
+    }
+    cTimer* OrigTimer(cTimers* timers)
+    {
+      // http://www.vdr-portal.de/board1-news/board2-vdr-news/p1255344-/#post1255344
+      // if patch is accepted, change to
+      //return timers->GetTimer(timer);
+      return timers->GetTimer((cTimer*)timer);
+    }
 };
 
 class TimerObjSort
@@ -280,7 +293,7 @@ class cConflictCheck
     cList<cConflictCheckTimerObj>* GetTimers() { return timerList; }
     void AddConflict(cConflictCheckTimerObj* TimerObj, cConflictCheckTime* Checktime, std::set<cConflictCheckTimerObj*>& pendingTimers);
     int ProcessCheckTime(cConflictCheckTime* checkTime);
-    bool TimerInConflict(cTimer*);
+    bool TimerInConflict(const cTimer*);
     void EvaluateConflCheckCmd();
     eModuleStatus CamSlotModuleStatus(cCamSlot *CamSlot);
 };
diff --git a/conflictcheck_thread.c b/conflictcheck_thread.c
index d224ccf..a81bd8b 100644
--- a/conflictcheck_thread.c
+++ b/conflictcheck_thread.c
@@ -102,11 +102,13 @@ void cConflictCheckThread::Action(void)
 	if (now >= nextUpdate || m_forceUpdate)
 	{
 	    m_forceUpdate = false;
+#if VDRVERSNUM < 20300
 	    if (Timers.BeingEdited())
 	    {
 		Wait.Wait(1000);
 		continue;
 	    }
+#endif
 	    LogFile.iSysLog("timer conflict check started");
 
 	    cConflictCheck conflictCheck;
diff --git a/epgsearch.c b/epgsearch.c
index 83a12b6..08c5d1f 100644
--- a/epgsearch.c
+++ b/epgsearch.c
@@ -156,9 +156,15 @@ bool cPluginEpgsearch::ProcessArgs(int argc, char *argv[])
       strn0cpy(SearchExt->search,argv[2], sizeof(SearchExt->search));
       if (atoi(argv[3]) > 0)
       {
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
          SearchExt->useChannel = true;
-         SearchExt->channelMin = Channels.GetByNumber(atoi(argv[3]));
-         SearchExt->channelMax = Channels.GetByNumber(atoi(argv[3]));
+         SearchExt->channelMin = vdrchannels->GetByNumber(atoi(argv[3]));
+         SearchExt->channelMax = vdrchannels->GetByNumber(atoi(argv[3]));
       }
       SearchExt->mode = atoi(argv[4]);
       SearchExt->useTitle = atoi(argv[5]);
@@ -237,9 +243,15 @@ bool cPluginEpgsearch::Service(const char *Id, void *Data)
       strn0cpy(SearchExt->search,searchData->query, sizeof(SearchExt->search)); 
       if (searchData->channelNr > 0)
       {
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
          SearchExt->useChannel = true;
-         SearchExt->channelMin = Channels.GetByNumber(searchData->channelNr);
-         SearchExt->channelMax = Channels.GetByNumber(searchData->channelNr);
+         SearchExt->channelMin = vdrchannels->GetByNumber(searchData->channelNr);
+         SearchExt->channelMax = vdrchannels->GetByNumber(searchData->channelNr);
       }
       SearchExt->mode = searchData->mode;
       SearchExt->useTitle = searchData->useTitle;
@@ -332,9 +344,15 @@ bool cPluginEpgsearch::Service(const char *Id, void *Data)
       strn0cpy(SearchExt->search,searchData->query, sizeof(SearchExt->search));
       if (searchData->channelNr > 0)
       {
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
          SearchExt->useChannel = true;
-         SearchExt->channelMin = Channels.GetByNumber(searchData->channelNr);
-         SearchExt->channelMax = Channels.GetByNumber(searchData->channelNr);
+         SearchExt->channelMin = vdrchannels->GetByNumber(searchData->channelNr);
+         SearchExt->channelMax = vdrchannels->GetByNumber(searchData->channelNr);
       }
       SearchExt->mode = searchData->mode;
       SearchExt->useTitle = searchData->useTitle;
@@ -510,9 +528,15 @@ cOsdObject *cPluginEpgsearch::DoInitialSearch(char* rcFilename)
       strn0cpy(SearchExt->search,rcFile.Search, sizeof(SearchExt->search));
       if (rcFile.ChannelNr != -1)
       {
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
          SearchExt->useChannel = true;
-         SearchExt->channelMin = Channels.GetByNumber(rcFile.ChannelNr);
-         SearchExt->channelMax = Channels.GetByNumber(rcFile.ChannelNr);
+         SearchExt->channelMin = vdrchannels->GetByNumber(rcFile.ChannelNr);
+         SearchExt->channelMax = vdrchannels->GetByNumber(rcFile.ChannelNr);
       }
       SearchExt->mode = rcFile.SearchMode;
       SearchExt->useTitle = rcFile.UseTitle;
diff --git a/epgsearchext.c b/epgsearchext.c
index 9d11c3b..0c981dc 100644
--- a/epgsearchext.c
+++ b/epgsearchext.c
@@ -58,8 +58,14 @@ cSearchExt::cSearchExt(void)
    startTime = 0000;
    stopTime = 2359;
    useChannel = false;
-   channelMin = Channels.GetByNumber(cDevice::CurrentChannel());
-   channelMax = Channels.GetByNumber(cDevice::CurrentChannel());
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   channelMin = vdrchannels->GetByNumber(cDevice::CurrentChannel());
+   channelMax = vdrchannels->GetByNumber(cDevice::CurrentChannel());
    channelGroup = NULL;
    useCase = false;
    mode = 0;
@@ -228,7 +234,7 @@ cSearchExt& cSearchExt::operator= (const cSearchExt &SearchExt)
    recordingsKeep = templ->recordingsKeep;
    blacklistMode = templ->blacklistMode;
    blacklists.Clear();
-   cBlacklistObject* blacklistObj = templ->blacklists.First();
+   const cBlacklistObject* blacklistObj = templ->blacklists.First();
    while(blacklistObj)
    {
       blacklists.Add(new cBlacklistObject(blacklistObj->blacklist));
@@ -480,7 +486,13 @@ bool cSearchExt::Parse(const char *s)
                         char *channelMaxbuffer = NULL;
                         int channels = sscanf(value, "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer);
 #endif
-                        channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
+#if VDRVERSNUM > 20300
+                        LOCK_CHANNELS_READ;
+                        const cChannels *vdrchannels = Channels;
+#else
+                        cChannels *vdrchannels = &Channels;
+#endif
+                        channelMin = vdrchannels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
                         if (!channelMin)
                         {
                            LogFile.eSysLog("ERROR: channel '%s' not defined", channelMinbuffer);
@@ -492,7 +504,7 @@ bool cSearchExt::Parse(const char *s)
                            channelMax = channelMin;
                         else
                         {
-                           channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
+                           channelMax = vdrchannels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
                            if (!channelMax)
                            {
                               LogFile.eSysLog("ERROR: channel '%s' not defined", channelMaxbuffer);
@@ -858,12 +870,12 @@ bool cSearchExt::Save(FILE *f)
    return fprintf(f, "%s\n", ToText()) > 0;
 }
 
-cEvent * cSearchExt::GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin)
+const cEvent * cSearchExt::GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin)
 {
    if (!schedules) return NULL;
 
-   cEvent *pe = NULL;
-   cEvent *p1 = NULL;
+   const cEvent *pe = NULL;
+   const cEvent *p1 = NULL;
 
    const cList<cEvent>* Events = schedules->Events();
    if (Start)
@@ -893,7 +905,7 @@ cEvent * cSearchExt::GetEventBySearchExt(const cSchedule *schedules, const cEven
    if (!useCase)
       ToLower(searchText);
 
-   for (cEvent *p = p1; p; p = Events->Next(p))
+   for (const cEvent *p = p1; p; p = Events->Next(p))
    {
       if(!p)
       {
@@ -1011,9 +1023,14 @@ cSearchResults* cSearchExt::Run(int PayTVMode, bool inspectTimerMargin, int eval
 {
    LogFile.Log(3,"start search for search timer '%s'", search);
 
-   cSchedulesLock schedulesLock;
    const cSchedules *schedules;
+#if VDRVERSNUM > 20300
+   LOCK_SCHEDULES_READ;
+   schedules = Schedules;
+#else
+   cSchedulesLock schedulesLock;
    schedules = cSchedules::Schedules(schedulesLock);
+#endif
    if(!schedules) {
       LogFile.Log(1,"schedules are currently locked! try again later.");
       return NULL;
@@ -1031,8 +1048,14 @@ cSearchResults* cSearchExt::Run(int PayTVMode, bool inspectTimerMargin, int eval
    cSearchResults* pBlacklistResults = GetBlacklistEvents(inspectTimerMargin?MarginStop:0);
 
    int counter = 0;
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
    while (Schedule) {
-      cChannel* channel = Channels.GetByChannelID(Schedule->ChannelID(),true,true);
+      const cChannel* channel = vdrchannels->GetByChannelID(Schedule->ChannelID(),true,true);
       if (!channel)
       {
          Schedule = (const cSchedule *)schedules->Next(Schedule);
@@ -1084,7 +1107,7 @@ cSearchResults* cSearchExt::Run(int PayTVMode, bool inspectTimerMargin, int eval
             if (tNow + evalLimitMins*60 <= event->EndTime())
                break;
          }
-         if (event && Channels.GetByChannelID(event->ChannelID(),true,true))
+         if (event && vdrchannels->GetByChannelID(event->ChannelID(),true,true))
          {
             if (pBlacklistResults && pBlacklistResults->Lookup(event))
             {
@@ -1165,6 +1188,12 @@ void cSearchExt::CheckRepeatTimers(cSearchResults* pResults)
    }
 
    cSearchResult* pResultObj = NULL;
+#if VDRVERSNUM > 20300
+   LOCK_TIMERS_READ;
+   const cTimers* vdrtimers = Timers;
+#else
+   cTimers* vdrtimers = &Timers;
+#endif
    for (pResultObj = pResults->First(); pResultObj; pResultObj = pResults->Next(pResultObj))
    {
       if (action != searchTimerActionRecord) // only announce if there is no timer for the event
@@ -1253,7 +1282,7 @@ void cSearchExt::CheckRepeatTimers(cSearchResults* pResults)
          }
       }
       bool dummy;
-      cTimer* timer = cSearchTimerThread::GetTimer(this, pEvent, dummy);
+      const cTimer* timer = cSearchTimerThread::GetTimer(vdrtimers, this, pEvent, dummy);
       if (timer && !timer->HasFlags(tfActive))
       {
          LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d), existing timer disabled", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent));
@@ -1337,39 +1366,55 @@ bool cSearchExt::MatchesExtEPGInfo(const cEvent* e)
 
 void cSearchExt::OnOffTimers(bool bOn)
 {
-   for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti))
+#if VDRVERSNUM > 20300
+   LOCK_TIMERS_WRITE;
+   cTimers *vdrtimers = Timers;
+#else
+   cTimers *vdrtimers = &Timers;
+#endif
+   for (cTimer *ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti))
    {
       if (((!bOn && ti->HasFlags(tfActive)) || (bOn && !ti->HasFlags(tfActive))) && TriggeredFromSearchTimerID(ti) == ID)
          ti->OnOff();
    }
+#if VDRVERSNUM < 20300
    Timers.SetModified();
+#endif
 }
 
 void cSearchExt::DeleteAllTimers()
 {
    cList<cTimerObj> DelTimers;
-   cTimer *ti = Timers.First();
+#if VDRVERSNUM > 20300
+   LOCK_TIMERS_WRITE;
+   cTimers *vdrtimers = Timers;
+#else
+   cTimers *vdrtimers = &Timers;
+#endif
+   cTimer *ti = vdrtimers->First();
    while(ti)
    {
       if (!ti->Recording() && TriggeredFromSearchTimerID(ti) == ID)
       {
-         cTimer* tiNext = Timers.Next(ti);
+         cTimer* tiNext = vdrtimers->Next(ti);
          LogFile.iSysLog("deleting timer %s", *ti->ToDescr());
-         Timers.Del(ti);
-         Timers.SetModified();
+         vdrtimers->Del(ti);
+#if VDRVERSNUM < 20300
+         vdrtimers->SetModified();
+#endif
          ti = tiNext;
       }
       else
-         ti = Timers.Next(ti);
+         ti = vdrtimers->Next(ti);
    };
 }
 
-cTimerObjList* cSearchExt::GetTimerList(cTimerObjList* timerList)
+cTimerObjList* cSearchExt::GetTimerList(const cTimers* vdrtimers, cTimerObjList* timerList)
 {
    if (!timerList)
       timerList = new cTimerObjList;
 
-   for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti))
+   for (const cTimer *ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti))
    {
       if (TriggeredFromSearchTimerID(ti) == ID)
       {
@@ -1395,7 +1440,13 @@ int cSearchExt::GetCountRecordings()
 {
    int countRecs = 0;
 
-   for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
+#if VDRVERSNUM > 20300
+   LOCK_RECORDINGS_READ;
+   const cRecordings *vdrrecordings = Recordings;
+#else
+   cRecordings *vdrrecordings = &Recordings;
+#endif
+   for (const cRecording *recording = vdrrecordings->First(); recording; recording = vdrrecordings->Next(recording))
    {
       if (recording->IsEdited()) continue; // ignore recordings edited
       if (!recording->Info()) continue;
diff --git a/epgsearchext.h b/epgsearchext.h
index eee3cf4..3d4b9c5 100644
--- a/epgsearchext.h
+++ b/epgsearchext.h
@@ -140,8 +140,8 @@ public:
   std::string contentsFilter;
   int      useExtEPGInfo;
   char**   catvalues;
-  cChannel *channelMin;
-  cChannel *channelMax;
+  const cChannel *channelMin;
+  const cChannel *channelMax;
   char*    channelGroup;
   int      avoidRepeats;
   int      compareTitle;
@@ -181,9 +181,9 @@ public:
   int StartTime(void) { return startTime; }
   int StopTime(void) { return stopTime; }
   int UseChannel(void) { return useChannel; }
-  cChannel *ChannelMin(void) { return channelMin; }
-  cChannel *ChannelMax(void) { return channelMax; }
-  cEvent * GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin = false);
+  const cChannel *ChannelMin(void) { return channelMin; }
+  const cChannel *ChannelMax(void) { return channelMax; }
+  const cEvent * GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin = false);
   bool MatchesExtEPGInfo(const cEvent* e);
   const char *ToText();
   bool Parse(const char *s);
@@ -199,7 +199,7 @@ public:
   cSearchResults* GetBlacklistEvents(int MarginStop = 0);
   void OnOffTimers(bool);
   void DeleteAllTimers();
-  cTimerObjList* GetTimerList(cTimerObjList* timerList);
+  cTimerObjList* GetTimerList(const cTimers* vdrtimers, cTimerObjList* timerList);
   int GetCountRecordings();
   bool IsActiveAt(time_t t);
   bool HasContent(int contentID);
diff --git a/epgsearchsvdrp.c b/epgsearchsvdrp.c
index f181013..6b3c039 100644
--- a/epgsearchsvdrp.c
+++ b/epgsearchsvdrp.c
@@ -232,8 +232,12 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option,
             {
                LogFile.Log(1,"search '%s' deleted via SVDRP", search->search);
                cMutexLock SearchExtsLock(&SearchExts);
-               if (delTimers && !Timers.BeingEdited())
-                  search->DeleteAllTimers();
+               if (delTimers
+#if VDRVERSNUM < 20300
+                   && !Timers.BeingEdited()
+#endif
+                  )
+                search->DeleteAllTimers();
                SearchExts.Del(search);
                SearchExts.Save();
                RecsDone.RemoveSearchID(SID);
@@ -562,13 +566,25 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option,
 
             eTimerMatch timerMatch;
             bool hasTimer = false;
-            if (Timers.GetMatch(pEvent, &timerMatch))
+#if VDRVERSNUM > 20300
+            LOCK_TIMERS_READ;
+            const cTimers *vdrtimers = Timers;
+#else
+            cTimers *vdrtimers = &Timers;
+#endif
+            if (vdrtimers->GetMatch(pEvent, &timerMatch))
                hasTimer = (timerMatch == tmFull);
 
             if (!result->search->useAsSearchTimer)
                result->needsTimer = false;
 
-            cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true,true);
+#if VDRVERSNUM > 20300
+            LOCK_CHANNELS_READ;
+            const cChannels *vdrchannels = Channels;
+#else
+            cChannels *vdrchannels = &Channels;
+#endif
+            const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true,true);
             int timerMode = hasTimer?1:(result->needsTimer?2:0);
 
             string title = pEvent->Title()?ReplaceAll(pEvent->Title(), "|", "!^pipe!^"):"";
@@ -1043,7 +1059,13 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option,
                   ReplyCode = 901;
                   return cString::sprintf("invalid channel id");
                }
-               cChannel *ch = Channels.GetByChannelID(chID,true,true);
+#if VDRVERSNUM > 20300
+               LOCK_CHANNELS_READ;
+               const cChannels *vdrchannels = Channels;
+#else
+               cChannels *vdrchannels = &Channels;
+#endif
+               const cChannel *ch = vdrchannels->GetByChannelID(chID,true,true);
                if (!ch)
                {
                   ReplyCode = 901;
@@ -1053,12 +1075,18 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option,
             }
             else
             {
+#if VDRVERSNUM > 20300
+               LOCK_CHANNELS_READ;
+               const cChannels *vdrchannels = Channels;
+#else
+               cChannels *vdrchannels = &Channels;
+#endif
                string sBuffer;
-               for (int i = 0; i < Channels.Count(); i++)
+               for (int i = 0; i < vdrchannels->Count(); i++)
                {
-                  cChannel* ch = Channels.Get(i);
+                  const cChannel* ch = vdrchannels->Get(i);
                   if (ch && !ch->GroupSep())
-                     sBuffer += string(*ch->GetChannelID().ToString()) + string(": ") + NumToString(DefTimerCheckModes.GetMode(ch)) + string((i<Channels.Count()-1)?"\n":"");
+                     sBuffer += string(*ch->GetChannelID().ToString()) + string(": ") + NumToString(DefTimerCheckModes.GetMode(ch)) + string((i<vdrchannels->Count()-1)?"\n":"");
                }
                return sBuffer.c_str();
             }
diff --git a/epgsearchtools.c b/epgsearchtools.c
index 6f7485a..09ad7b3 100644
--- a/epgsearchtools.c
+++ b/epgsearchtools.c
@@ -519,7 +519,7 @@ bool DescriptionMatches(const char* eDescr, const char* rDescr, int matchLimit)
    return false;
 }
 
-const cEvent* GetEvent(cTimer* timer)
+const cEvent* GetEvent(const cTimer* timer)
 {
    const cEvent* event = NULL;
    const cChannel *channel = timer->Channel();
@@ -527,10 +527,15 @@ const cEvent* GetEvent(cTimer* timer)
    for (int seconds = 0; seconds <= 3; seconds++)
    {
       {
+#if VDRVERSNUM > 20300
+         LOCK_SCHEDULES_READ;
+         const cSchedules *schedules = Schedules;
+#else
          cSchedulesLock SchedulesLock;
-         const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
-         if (Schedules) {
-            const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
+         const cSchedules *schedules = cSchedules::Schedules(SchedulesLock);
+#endif
+         if (schedules) {
+            const cSchedule *Schedule = schedules->GetSchedule(channel->GetChannelID());
             if (Schedule) {
                event = Schedule->GetEventAround(Time);
                if (event) return event;
@@ -709,7 +714,13 @@ int ChannelNrFromEvent(const cEvent* pEvent)
 {
    if (!pEvent)
       return -1;
-   cChannel* channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   const cChannel* channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true);
    if (!channel)
       return -1;
    else
diff --git a/epgsearchtools.h b/epgsearchtools.h
index dc68f8b..7227970 100644
--- a/epgsearchtools.h
+++ b/epgsearchtools.h
@@ -70,7 +70,7 @@ using std::string;
 #undef CONFIGDIR
 #define CONFIGDIR (!ConfigDir?cPlugin::ConfigDirectory():ConfigDir)
 
-#define CHNUMWIDTH  (numdigits(Channels.MaxNumber()) + 2)
+#define CHNUMWIDTH  (numdigits(vdrchannels->MaxNumber()) + 2)
 
 #define SHORTTEXT(EVENT) \
   (EVENT && EPGSearchConfig.showShortText && !isempty((EVENT)->ShortText()))?" ~ ":"", \
@@ -157,7 +157,7 @@ cSearchExt* TriggeredFromSearchTimer(const cTimer* timer);
 int TriggeredFromSearchTimerID(const cTimer* timer);
 double FuzzyMatch(const char* s1, const char* s2, int maxLength);
 bool DescriptionMatches(const char* eDescr, const char* rDescr, int matchLimit = 90);
-const cEvent* GetEvent(cTimer* timer);
+const cEvent* GetEvent(const cTimer* timer);
 char* GetRawDescription(const char* descr);
 void PrepareTimerFile(const cEvent* event, cTimer* timer);
 int CompareEventTime(const void *p1, const void *p2);
@@ -188,15 +188,15 @@ long getAddrFromString(const char* hostnameOrIp, struct sockaddr_in* addr);
 // --- cTimerObj --------------------------------------------------------
 class cTimerObj : public cListObject {
 public:
-    cTimer* timer;
-    cTimerObj(cTimer* Timer) : timer(Timer) {}
+    const cTimer* timer;
+    cTimerObj(const cTimer* Timer) : timer(Timer) {}
     virtual ~cTimerObj() { timer = NULL;  } // do not delete anything!
 };
 
 // --- cTimerObjList --------------------------------------------------------
 class cTimerObjList : public cList<cTimerObj> {
 public:
-    void DelTimer(cTimer* t)
+    void DelTimer(const cTimer* t)
 	{
 	    for (cTimerObj* pTObj = First(); pTObj; pTObj = Next(pTObj))
 		if (pTObj->timer == t)
diff --git a/mail.c b/mail.c
index 65c9caa..369cbfa 100644
--- a/mail.c
+++ b/mail.c
@@ -50,7 +50,13 @@ string cMailTimerNotification::Format(const string& templ) const
     if (!pEvent) return "";
 
     eTimerMatch TimerMatch = tmNone;
-    cTimer* pTimer = Timers.GetMatch(pEvent, &TimerMatch);
+#if VDRVERSNUM > 20300
+    LOCK_TIMERS_READ;
+    const cTimers *vdrtimers = Timers;
+#else
+    cTimers *vdrtimers = &Timers;
+#endif
+    const cTimer* pTimer = vdrtimers->GetMatch(pEvent, &TimerMatch);
     if (!pTimer) return "";
 
     string result = templ;
@@ -70,8 +76,13 @@ string cMailTimerNotification::Format(const string& templ) const
 
 const cEvent* cMailTimerNotification::GetEvent() const
 {
+#if VDRVERSNUM > 20300
+    LOCK_SCHEDULES_READ;
+    const cSchedules *schedules = Schedules;
+#else
     cSchedulesLock schedulesLock;
     const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+#endif
     if (!schedules) return NULL;
     const cSchedule *schedule = schedules->GetSchedule(channelID);
     if (!schedule) return NULL;
@@ -80,8 +91,14 @@ const cEvent* cMailTimerNotification::GetEvent() const
 
 bool cMailTimerNotification::operator< (const cMailTimerNotification &N) const
 {
-    const cChannel* channel = Channels.GetByChannelID(channelID,true,true);
-    const cChannel* channelOther = Channels.GetByChannelID(N.channelID,true,true);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel* channel = vdrchannels->GetByChannelID(channelID,true,true);
+    const cChannel* channelOther = vdrchannels->GetByChannelID(N.channelID,true,true);
     if (!channel || !channelOther)
 	return false;
     const cEvent* event = GetEvent();
@@ -98,7 +115,7 @@ bool cMailTimerNotification::operator< (const cMailTimerNotification &N) const
 
 // -------------------------
 // cMailDelTimerNotification
-cMailDelTimerNotification::cMailDelTimerNotification(cTimer* pTimer, const cEvent* pEvent, const string& templ)
+cMailDelTimerNotification::cMailDelTimerNotification(const cTimer* pTimer, const cEvent* pEvent, const string& templ)
 {
     if (!pTimer || !pTimer->Channel()) return;
 
@@ -121,8 +138,14 @@ cMailDelTimerNotification::cMailDelTimerNotification(const string& Formatted, tC
 
 bool cMailDelTimerNotification::operator< (const cMailDelTimerNotification &N) const
 {
-    const cChannel* channel = Channels.GetByChannelID(channelID,true,true);
-    const cChannel* channelOther = Channels.GetByChannelID(N.channelID,true,true);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel* channel = vdrchannels->GetByChannelID(channelID,true,true);
+    const cChannel* channelOther = vdrchannels->GetByChannelID(N.channelID,true,true);
     if (!channel || !channelOther)
 	return false;
     if (channel != channelOther)
@@ -338,7 +361,7 @@ void cMailUpdateNotifier::AddModTimerNotification(tEventID EventID, tChannelID C
   modTimers.insert(N);
 }
 
-void cMailUpdateNotifier::AddRemoveTimerNotification(cTimer* t, const cEvent* e)
+void cMailUpdateNotifier::AddRemoveTimerNotification(const cTimer* t, const cEvent* e)
 {
     string templTimer = GetTemplValue(mailTemplate, "timer");
     cMailDelTimerNotification N(t, e, templTimer);
diff --git a/mail.h b/mail.h
index f62bda0..b2f0894 100644
--- a/mail.h
+++ b/mail.h
@@ -82,7 +82,7 @@ class cMailDelTimerNotification
  public:
     string formatted;
 
-    cMailDelTimerNotification(cTimer* t, const cEvent* pEvent, const string& templ);
+    cMailDelTimerNotification(const cTimer* t, const cEvent* pEvent, const string& templ);
     cMailDelTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start);
     bool operator< (const cMailDelTimerNotification &N) const;
     string Format(const string& templ) const { return formatted; }
@@ -110,7 +110,7 @@ class cMailUpdateNotifier : public cMailNotifier
     cMailUpdateNotifier();
     void AddNewTimerNotification(tEventID EventID, tChannelID ChannelID);
     void AddModTimerNotification(tEventID EventID, tChannelID ChannelID, uint timerMod = tmNoChange);
-    void AddRemoveTimerNotification(cTimer* t, const cEvent* e = NULL);
+    void AddRemoveTimerNotification(const cTimer* t, const cEvent* e = NULL);
     void AddRemoveTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start);
     void AddAnnounceEventNotification(tEventID EventID, tChannelID ChannelID, int SearchExtID);
     void SendUpdateNotifications();
diff --git a/menu_blacklistedit.c b/menu_blacklistedit.c
index 4173cdb..ef5a1c3 100644
--- a/menu_blacklistedit.c
+++ b/menu_blacklistedit.c
@@ -351,7 +351,13 @@ eOSState cMenuBlacklistEdit::ProcessKey(eKeys Key)
 	    case kOk:
 		if (data.useChannel==1)
 		{
-		    cChannel *ch = Channels.GetByNumber(channelMin);
+#if VDRVERSNUM > 20300
+		    LOCK_CHANNELS_READ;
+		    const cChannels *vdrchannels = Channels;
+#else
+		    cChannels *vdrchannels = &Channels;
+#endif
+		    const cChannel *ch = vdrchannels->GetByNumber(channelMin);
 		    if (ch)
 			data.channelMin = ch;
 		    else
@@ -359,7 +365,7 @@ eOSState cMenuBlacklistEdit::ProcessKey(eKeys Key)
 		      ERROR(tr("*** Invalid Channel ***"));
 		      break;
 		    }
-		    ch = Channels.GetByNumber(channelMax);
+		    ch = vdrchannels->GetByNumber(channelMax);
 		    if (ch)
 			data.channelMax = ch;
 		    else
diff --git a/menu_commands.c b/menu_commands.c
index 174cf7f..1bc3a21 100644
--- a/menu_commands.c
+++ b/menu_commands.c
@@ -102,7 +102,13 @@ void cMenuSearchCommands::LoadCommands()
 
 eOSState cMenuSearchCommands::Switch(void)
 {
-   cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   const cChannel *channel = vdrchannels->GetByChannelID(event->ChannelID(), true, true);
    if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
       return osEnd;
    else
@@ -122,7 +128,13 @@ eOSState cMenuSearchCommands::Record(void)
    if (!event) return osContinue;
 
    eTimerMatch timerMatch = tmNone;
-   cTimer* timer = Timers.GetMatch(event, &timerMatch);
+#if VDRVERSNUM > 20300
+   LOCK_TIMERS_WRITE;
+   cTimers *vdrtimers = Timers;
+#else
+   cTimers *vdrtimers = &Timers;
+#endif
+   cTimer* timer = vdrtimers->GetMatch(event, &timerMatch);
    if (timerMatch == tmFull)
    {
       if (EPGSearchConfig.useVDRTimerEditMenu)
@@ -133,7 +145,7 @@ eOSState cMenuSearchCommands::Record(void)
 
    timer = new cTimer(event);
    PrepareTimerFile(event, timer);
-   cTimer *t = Timers.GetTimer(timer);
+   cTimer *t = vdrtimers->GetTimer(timer);
 
    if (EPGSearchConfig.onePressTimerCreation == 0 || t || (!t && event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL)))
    {
@@ -170,10 +182,11 @@ eOSState cMenuSearchCommands::Record(void)
 #endif
 
       SetAux(timer, fullaux);
-      Timers.Add(timer);
+      vdrtimers->Add(timer);
       timer->Matches();
-      Timers.SetModified();
-
+#if VDRVERSNUM < 20300
+      vdrtimers->SetModified();
+#endif
       LogFile.iSysLog("timer %s added (active)", *timer->ToDescr());
       return osBack;
    }
@@ -232,7 +245,13 @@ eOSState cMenuSearchCommands::CreateSearchTimer(void)
 
    cSearchExt* pNew = new cSearchExt;
    strcpy(pNew->search, event->Title());
-   pNew->channelMin = pNew->channelMax = Channels.GetByChannelID(event->ChannelID());
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   pNew->channelMin = pNew->channelMax = vdrchannels->GetByChannelID(event->ChannelID());
    return AddSubMenu(new cMenuEditSearchExt(pNew, true, false, true));
 }
 
@@ -280,12 +299,18 @@ eOSState cMenuSearchCommands::Execute(void)
 	buffer = cString::sprintf("%s...", command->Title());
 	Skins.Message(mtStatus, buffer);
 
+#if VDRVERSNUM > 20300
+	LOCK_CHANNELS_READ;
+	const cChannels *vdrchannels = Channels;
+#else
+	cChannels *vdrchannels = &Channels;
+#endif
 	buffer = cString::sprintf("'%s' %ld %ld %d '%s' '%s'",
 				  EscapeString(event->Title()).c_str(),
 				  event->StartTime(),
 				  event->EndTime(),
 				  ChannelNrFromEvent(event),
-				  EscapeString(Channels.GetByChannelID(event->ChannelID(), true, true)->Name()).c_str(),
+				  EscapeString(vdrchannels->GetByChannelID(event->ChannelID(), true, true)->Name()).c_str(),
 				  EscapeString(event->ShortText()?event->ShortText():"").c_str());
 	const char *Result = command->Execute(buffer);
 	Skins.Message(mtStatus, NULL);
diff --git a/menu_conflictcheck.c b/menu_conflictcheck.c
index 562842e..cf10fd0 100644
--- a/menu_conflictcheck.c
+++ b/menu_conflictcheck.c
@@ -50,7 +50,7 @@ cMenuConflictCheckItem::cMenuConflictCheckItem(cConflictCheckTime* Ct, cConflict
     }
     else
     {
-	cTimer* t = timerObj->timer;
+	const cTimer* t = timerObj->timer;
 	int recPart = timerObj->recDuration * 100 / (timerObj->stop - timerObj->start);
 	buffer = cString::sprintf("%d\t%s\t%d\t%2d%%\t%s", t->Channel()->Number(), t->Channel()->ShortName(true), t->Priority(), recPart, t->File());
     }
@@ -165,17 +165,23 @@ eOSState cMenuConflictCheck::ProcessKey(eKeys Key)
 cMenuConflictCheckDetailsItem::cMenuConflictCheckDetailsItem(cConflictCheckTimerObj* TimerObj)
 {
     timerObj = TimerObj;
-    hasTimer = timerObj->OrigTimer()?timerObj->OrigTimer()->HasFlags(tfActive):false;
-    Update(true);
+#if VDRVERSNUM > 20300
+    LOCK_TIMERS_READ;
+    const cTimers *vdrtimers = Timers;
+#else
+    cTimers *vdrtimers = &Timers;
+#endif
+    hasTimer = timerObj->OrigTimer(vdrtimers)?timerObj->OrigTimer(vdrtimers)->HasFlags(tfActive):false;
+    Update(vdrtimers, true);
 }
 
-bool cMenuConflictCheckDetailsItem::Update(bool Force)
+bool cMenuConflictCheckDetailsItem::Update(const cTimers* vdrtimers, bool Force)
 {
     bool oldhasTimer = hasTimer;
-    hasTimer = timerObj->OrigTimer()?timerObj->OrigTimer()->HasFlags(tfActive):false;
+    hasTimer = timerObj->OrigTimer(vdrtimers)?timerObj->OrigTimer(vdrtimers)->HasFlags(tfActive):false;
     if (Force || hasTimer != oldhasTimer)
     {
-	cTimer* timer = timerObj->timer;
+	const cTimer* timer = timerObj->timer;
 	char device[2]="";
 	if (hasTimer)
 	{
@@ -266,19 +272,28 @@ eOSState cMenuConflictCheckDetails::Commands(eKeys Key)
 
 eOSState cMenuConflictCheckDetails::ToggleTimer(cConflictCheckTimerObj* TimerObj)
 {
-  if (!TimerObj || !TimerObj->OrigTimer()) return osContinue;
-  TimerObj->OrigTimer()->OnOff();
-  Timers.SetModified();
-  Update();
+  cTimers *vdrtimers;
+#if VDRVERSNUM > 20300
+  LOCK_TIMERS_WRITE;
+  vdrtimers = Timers;
+#else
+  vdrtimers = &Timers;
+#endif
+  if (!TimerObj || !TimerObj->OrigTimer(vdrtimers)) return osContinue;
+  TimerObj->OrigTimer(vdrtimers)->OnOff();  // Toggles Timer Flag
+#if VDRVERSNUM < 20300
+  vdrtimers->SetModified();
+#endif
+  Update(vdrtimers);
   Display();
   return osContinue;
 }
 
-bool cMenuConflictCheckDetails::Update(bool Force)
+bool cMenuConflictCheckDetails::Update(const cTimers* vdrtimers, bool Force)
 {
     bool result = false;
     for (cOsdItem *item = First(); item; item = Next(item)) {
-	if (item->Selectable() && ((cMenuConflictCheckDetailsItem *)item)->Update(Force))
+	if (item->Selectable() && ((cMenuConflictCheckDetailsItem *)item)->Update(vdrtimers, Force))
 	    result = true;
     }
     return result;
@@ -286,22 +301,34 @@ bool cMenuConflictCheckDetails::Update(bool Force)
 
 eOSState cMenuConflictCheckDetails::DeleteTimer(cConflictCheckTimerObj* TimerObj)
 {
-  cTimer* timer = TimerObj->OrigTimer();
+#if VDRVERSNUM > 20300
+  LOCK_TIMERS_WRITE;
+  cTimers *vdrtimers = Timers;
+#else
+  cTimers *vdrtimers = &Timers;
+#endif
+  cTimer* timer = TimerObj->OrigTimer(vdrtimers);
   // Check if this timer is active:
   if (timer) {
     if (Interface->Confirm(trVDR("Delete timer?"))) {
       if (timer->Recording()) {
 	if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) {
 	  timer->Skip();
+#if VDRVERSNUM > 20300
+	  cRecordControls::Process(vdrtimers, time(NULL));
+#else
 	  cRecordControls::Process(time(NULL));
+#endif
 	}
 	else
 	  return osContinue;
       }
       LogFile.iSysLog("deleting timer %s", *timer->ToDescr());
-      Timers.Del(timer);
+      vdrtimers->Del(timer);
       cOsdMenu::Del(Current());
-      Timers.SetModified();
+#if VDRVERSNUM < 20300
+      vdrtimers->SetModified();
+#endif
       Display();
       return osBack;
     }
@@ -319,7 +346,13 @@ eOSState cMenuConflictCheckDetails::ShowSummary()
     const cEvent *ei = curTimerObj->Event();
     if (ei)
     {
-	cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+	LOCK_CHANNELS_READ;
+	const cChannels *vdrchannels = Channels;
+#else
+	cChannels *vdrchannels = &Channels;
+#endif
+	const cChannel *channel = vdrchannels->GetByChannelID(ei->ChannelID(), true, true);
 	if (channel)
 	    return AddSubMenu(new cMenuEventSearchSimple(ei, eventObjects));
     }
@@ -408,10 +441,16 @@ eOSState cMenuConflictCheckDetails::ProcessKey(eKeys Key)
 		for (it = timerObj->concurrentTimers->begin(); it != timerObj->concurrentTimers->end(); ++it)
 		{
 		    bool found = false;
-		    for(cTimer* checkT = Timers.First(); checkT; checkT = Timers.Next(checkT))
+#if VDRVERSNUM > 20300
+		    LOCK_TIMERS_WRITE;
+		    cTimers *vdrtimers = Timers;
+#else
+		    cTimers *vdrtimers = &Timers;
+#endif
+		    for(cTimer* checkT = vdrtimers->First(); checkT; checkT = vdrtimers->Next(checkT))
 		    {
 			checkT->Matches();
-			if (checkT == (*it)->OrigTimer()) // ok -> found, check for changes
+			if (checkT == (*it)->OrigTimer(vdrtimers)) // ok -> found, check for changes
 			{
 			    if (checkT->IsSingleEvent())
 			    {
@@ -444,7 +483,13 @@ eOSState cMenuConflictCheckDetails::ProcessKey(eKeys Key)
 
 	if (Key != kNone)
 	    SetHelpKeys();
-	if ((HadSubMenu || gl_TimerProgged) && Update(true))
+#if VDRVERSNUM > 20300
+        LOCK_TIMERS_READ;
+        const cTimers *vdrtimers = Timers;
+#else
+        cTimers *vdrtimers = &Timers;
+#endif
+	if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers, true))
 	{
 	    if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP
 	    {
diff --git a/menu_conflictcheck.h b/menu_conflictcheck.h
index e8d48d0..e7a858e 100644
--- a/menu_conflictcheck.h
+++ b/menu_conflictcheck.h
@@ -56,7 +56,7 @@ class cMenuConflictCheckDetailsItem : public cOsdItem {
 public:
     cConflictCheckTimerObj* timerObj;
     cMenuConflictCheckDetailsItem(cConflictCheckTimerObj* TimerObj = NULL);
-    bool Update(bool Force = false);
+    bool Update(const cTimers *vdrtimers, bool Force = false);
 };
 
 // --- cMenuConflictCheckDetails ------------------------------------------------------
@@ -73,7 +73,7 @@ private:
     void SetHelpKeys();
     eOSState ToggleTimer(cConflictCheckTimerObj* TimerObj);
     eOSState DeleteTimer(cConflictCheckTimerObj* TimerObj);
-    bool Update(bool Force = false);
+    bool Update(const cTimers* vdrtimers, bool Force = false);
     bool BuildList();
     eOSState ShowSummary();
     void UpdateCurrent();
diff --git a/menu_deftimercheckmethod.c b/menu_deftimercheckmethod.c
index 0476211..c776c43 100644
--- a/menu_deftimercheckmethod.c
+++ b/menu_deftimercheckmethod.c
@@ -142,9 +142,15 @@ void cMenuDefTimerCheckMethod::Set()
     Clear();
 
     delete modes;
-    modes = new int[Channels.Count()];
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    modes = new int[vdrchannels->Count()];
     int i=0;
-    for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel), i++)
+    for (const cChannel *channel = vdrchannels->First(); channel; channel = vdrchannels->Next(channel), i++)
     {
 	if (!channel->GroupSep() && *channel->Name())
 	{
@@ -164,7 +170,13 @@ eOSState cMenuDefTimerCheckMethod::ProcessKey(eKeys Key)
 	    case kOk:
 	    {
 		int i=0;
-		for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel), i++)
+#if VDRVERSNUM > 20300
+		LOCK_CHANNELS_READ;
+		const cChannels *vdrchannels = Channels;
+#else
+		cChannels *vdrchannels = &Channels;
+#endif
+		for (const cChannel *channel = vdrchannels->First(); channel; channel = vdrchannels->Next(channel), i++)
 		    if (!channel->GroupSep() && *channel->Name())
 			DefTimerCheckModes.SetMode(channel, modes[i]);
 		DefTimerCheckModes.Save();
diff --git a/menu_dirselect.c b/menu_dirselect.c
index 2fc24a8..3064c09 100644
--- a/menu_dirselect.c
+++ b/menu_dirselect.c
@@ -132,9 +132,15 @@ void cMenuDirSelect::CreateDirSet(bool extraDirs)
     directorySet.clear();
 
     // add distinct directories from current recordings
+#if VDRVERSNUM > 20300
+    LOCK_RECORDINGS_READ;
+    const cRecordings *vdrrecordings = Recordings;
+#else
+    cRecordings *vdrrecordings = &Recordings;
     if (Recordings.Count() == 0)
 	Recordings.Load();
-    for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
+#endif
+    for (const cRecording *recording = vdrrecordings->First(); recording; recording = vdrrecordings->Next(recording))
     {
 	if (recording->HierarchyLevels() > 0)
 	{
@@ -156,7 +162,13 @@ void cMenuDirSelect::CreateDirSet(bool extraDirs)
 	}
     }
     // add distinct directories from current timers
-    for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer))
+#if VDRVERSNUM > 20300
+    LOCK_TIMERS_READ;
+    const cTimers *vdrtimers = Timers;
+#else
+    const cTimers *vdrtimers = &Timers;
+#endif
+    for (const cTimer *timer = vdrtimers->First(); timer; timer = vdrtimers->Next(timer))
     {
 	char* dir = strdup(timer->File());
 	// strip the trailing name dir
diff --git a/menu_event.c b/menu_event.c
index 77a03a6..7c29114 100644
--- a/menu_event.c
+++ b/menu_event.c
@@ -84,7 +84,13 @@ void cMenuEventSearch::Set()
 
    if (event)
    {
-      cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+      LOCK_CHANNELS_READ;
+      const cChannels *vdrchannels = Channels;
+#else
+      cChannels *vdrchannels = &Channels;
+#endif
+      const cChannel *channel = vdrchannels->GetByChannelID(event->ChannelID(), true, true);
       bool canSwitch = false;
       if (channel)
       {
@@ -96,7 +102,13 @@ void cMenuEventSearch::Set()
       cEventObj* eventObjNext = GetNext(event);
 
       eTimerMatch timerMatch = tmNone;
-      Timers.GetMatch(event, &timerMatch);
+#if VDRVERSNUM > 20300
+      LOCK_TIMERS_READ;
+      const cTimers *vdrtimers = Timers;
+#else
+      cTimers *vdrtimers = &Timers;
+#endif
+      vdrtimers->GetMatch(event, &timerMatch);
       const char* szRed = trVDR("Button$Record");
       if (timerMatch == tmFull)
          szRed = trVDR("Button$Timer");
@@ -112,9 +124,9 @@ void cMenuEventSearch::Set()
       else if (surfMode == SurfModeChannel)
       {
          if (eventObjPrev && eventObjPrev->Event())
-            szGreen = strdup(CHANNELNAME(Channels.GetByChannelID(eventObjPrev->Event()->ChannelID(), true, true)));
+            szGreen = strdup(CHANNELNAME(vdrchannels->GetByChannelID(eventObjPrev->Event()->ChannelID(), true, true)));
          if (eventObjNext && eventObjNext->Event())
-            szYellow = strdup(CHANNELNAME(Channels.GetByChannelID(eventObjNext->Event()->ChannelID(), true, true)));
+            szYellow = strdup(CHANNELNAME(vdrchannels->GetByChannelID(eventObjNext->Event()->ChannelID(), true, true)));
          SetHelp(szRed, szGreen, szYellow, canSwitch ? trVDR("Button$Switch") : NULL);
       }
    }
@@ -236,7 +248,13 @@ void cMenuEventSearchSimple::Set()
 
    if (event)
    {
-      cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+      LOCK_CHANNELS_READ;
+      const cChannels *vdrchannels = Channels;
+#else
+      cChannels *vdrchannels = &Channels;
+#endif
+      const cChannel *channel = vdrchannels->GetByChannelID(event->ChannelID(), true, true);
       if (channel)
       {
          SetTitle(channel->Name());
diff --git a/menu_favorites.c b/menu_favorites.c
index d2dce45..f04aea2 100644
--- a/menu_favorites.c
+++ b/menu_favorites.c
@@ -122,7 +122,13 @@ eOSState cMenuFavorites::OnYellow()
       cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current());
       if (item && item->event)
       {
-         cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
+         const cChannel *channel = vdrchannels->GetByChannelID(item->event->ChannelID(), true, true);
          cMenuWhatsOnSearch::scheduleChannel = channel;
          cMenuWhatsOnSearch::currentShowMode = showNow;
       }
diff --git a/menu_main.c b/menu_main.c
index 5203e35..69af173 100644
--- a/menu_main.c
+++ b/menu_main.c
@@ -58,8 +58,19 @@ cMenuSearchMain::cMenuSearchMain(void)
   shiftTime = 0;
   InWhatsOnMenu = false;
   InFavoritesMenu = false;
-  cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
+#if VDRVERSNUM > 20300
+  LOCK_CHANNELS_READ;
+  const cChannels *vdrchannels = Channels;
+#else
+  cChannels *vdrchannels = &Channels;
+#endif
+  const cChannel *channel = vdrchannels->GetByNumber(cDevice::CurrentChannel());
+#if VDRVERSNUM > 20300
+  LOCK_SCHEDULES_READ;
+  schedules = Schedules;
+#else
   schedules = cSchedules::Schedules(schedulesLock);
+#endif
   if (channel) {
     cMenuWhatsOnSearch::SetCurrentChannel(channel->Number());
     if (EPGSearchConfig.StartMenu == 0 || forceMenu != 0)
@@ -108,7 +119,7 @@ int cMenuSearchMain::GetTab(int Tab)
     return cTemplFile::GetTemplateByName("MenuSchedule")->Tab(Tab-1);
 }
 
-void cMenuSearchMain::PrepareSchedule(cChannel *Channel)
+void cMenuSearchMain::PrepareSchedule(const cChannel *Channel)
 {
     Clear();
     cString buffer = cString::sprintf("%s - %s", trVDR("Schedule"), Channel->Name());
@@ -163,11 +174,11 @@ void cMenuSearchMain::PrepareSchedule(cChannel *Channel)
     }
 }
 
-bool cMenuSearchMain::Update(void)
+bool cMenuSearchMain::Update(const cTimers* vdrtimers)
 {
   bool result = false;
   for (cOsdItem *item = First(); item; item = Next(item)) {
-      if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update())
+      if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update(vdrtimers))
          result = true;
       }
   return result;
@@ -177,10 +188,16 @@ eOSState cMenuSearchMain::Record(void)
 {
   cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current());
   if (item) {
+#if VDRVERSNUM > 20300
+      LOCK_TIMERS_WRITE;
+      cTimers *vdrtimers = Timers;
+#else
+      cTimers *vdrtimers = &Timers;
+#endif
       if (item->timerMatch == tmFull)
       {
 	  eTimerMatch tm = tmNone;
-	  cTimer *timer = Timers.GetMatch(item->event, &tm);
+	  cTimer *timer = vdrtimers->GetMatch(item->event, &tm);
 	  if (timer)
 	    {
 	      if (EPGSearchConfig.useVDRTimerEditMenu)
@@ -192,7 +209,7 @@ eOSState cMenuSearchMain::Record(void)
 
      cTimer *timer = new cTimer(item->event);
      PrepareTimerFile(item->event, timer);
-     cTimer *t = Timers.GetTimer(timer);
+     cTimer *t = vdrtimers->GetTimer(timer);
      if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL)))
      {
 	 if (t)
@@ -229,15 +246,17 @@ eOSState cMenuSearchMain::Record(void)
 #endif
 
 	 SetAux(timer, fullaux);
-	 Timers.Add(timer);
+	 vdrtimers->Add(timer);
 	 gl_timerStatusMonitor->SetConflictCheckAdvised();
 	 timer->Matches();
-	 Timers.SetModified();
+#if VDRVERSNUM < 20300
+	 vdrtimers->SetModified();
+#endif
 	 LogFile.iSysLog("timer %s added (active)", *timer->ToDescr());
 
 	 if (HasSubMenu())
 	     CloseSubMenu();
-	 if (Update())
+	 if (Update(vdrtimers))
 	     Display();
 	 SetHelpKeys();
      }
@@ -249,7 +268,13 @@ eOSState cMenuSearchMain::Switch(void)
 {
   cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current());
   if (item) {
-     cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+     LOCK_CHANNELS_READ;
+     const cChannels *vdrchannels = Channels;
+#else
+     cChannels *vdrchannels = &Channels;
+#endif
+     const cChannel *channel = vdrchannels->GetByChannelID(item->event->ChannelID(), true, true);
      if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
         return osEnd;
      }
@@ -306,8 +331,14 @@ void cMenuSearchMain::SetHelpKeys(bool Force)
 	  SetHelp((EPGSearchConfig.redkeymode==0?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), trVDR("Button$Now"), trVDR("Button$Next"), EPGSearchConfig.bluekeymode==0?trVDR("Button$Switch"):tr("Button$Search"));
 	else
 	  {
-	    const char* szGreenToggled = CHANNELNAME(Channels.GetByNumber(currentChannel-1,-1));
-	    const char* szYellowToggled = CHANNELNAME(Channels.GetByNumber(currentChannel+1,1));
+#if VDRVERSNUM > 20300
+     LOCK_CHANNELS_READ;
+     const cChannels *vdrchannels = Channels;
+#else
+     cChannels *vdrchannels = &Channels;
+#endif
+	    const char* szGreenToggled = CHANNELNAME(vdrchannels->GetByNumber(currentChannel-1,-1));
+	    const char* szYellowToggled = CHANNELNAME(vdrchannels->GetByNumber(currentChannel+1,1));
 
 	    SetHelp((EPGSearchConfig.redkeymode==1?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), (EPGSearchConfig.toggleGreenYellow==0?trVDR("Button$Now"):szGreenToggled), (EPGSearchConfig.toggleGreenYellow==0?trVDR("Button$Next"):szYellowToggled), EPGSearchConfig.bluekeymode==1?trVDR("Button$Switch"):tr("Button$Search"));
 
@@ -319,7 +350,13 @@ void cMenuSearchMain::SetHelpKeys(bool Force)
 eOSState cMenuSearchMain::Shift(int iMinutes)
 {
     shiftTime += iMinutes;
-    cChannel *channel = Channels.GetByNumber(currentChannel);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel *channel = vdrchannels->GetByNumber(currentChannel);
     PrepareSchedule(channel);
     Display();
     SetHelpKeys();
@@ -433,7 +470,13 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key)
 			 cMenuMyScheduleItem* Item = (cMenuMyScheduleItem *)Get(Current());
 			 if (Item && Item->event)
 			 {
-			     cChannel *channel = Channels.GetByChannelID(Item->event->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+			     LOCK_CHANNELS_READ;
+			     const cChannels *vdrchannels = Channels;
+#else
+			     cChannels *vdrchannels = &Channels;
+#endif
+			     const cChannel *channel = vdrchannels->GetByChannelID(Item->event->ChannelID(), true, true);
 			     if (channel)
 				 ChannelNr = channel->Number();
 			 }
@@ -451,7 +494,13 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key)
 		 }
 		 else
 		 {
-		     cChannel *channel = Channels.GetByNumber(currentChannel-1,-1);
+#if VDRVERSNUM > 20300
+		     LOCK_CHANNELS_READ;
+		     const cChannels *vdrchannels = Channels;
+#else
+		     cChannels *vdrchannels = &Channels;
+#endif
+		     const cChannel *channel = vdrchannels->GetByNumber(currentChannel-1,-1);
 
 		     if (channel) {
 			 PrepareSchedule(channel);
@@ -483,7 +532,13 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key)
 		 }
 		 else
 		 {
-		     cChannel *channel = Channels.GetByNumber(currentChannel+1,1);
+#if VDRVERSNUM > 20300
+		     LOCK_CHANNELS_READ;
+		     const cChannels *vdrchannels = Channels;
+#else
+		     cChannels *vdrchannels = &Channels;
+#endif
+		     const cChannel *channel = vdrchannels->GetByNumber(currentChannel+1,1);
 		     if (channel) {
 			 PrepareSchedule(channel);
 			 if (channel->Number() != cDevice::CurrentChannel()) {
@@ -517,9 +572,15 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key)
 	}
     }
     if (!HasSubMenu()) {
-      cChannel *ch = cMenuWhatsOnSearch::ScheduleChannel();
+      const cChannel *ch = cMenuWhatsOnSearch::ScheduleChannel();
       InWhatsOnMenu = false;
       InFavoritesMenu = false;
+#if VDRVERSNUM > 20300
+      LOCK_TIMERS_READ;
+      const cTimers *vdrtimers = Timers;
+#else
+      cTimers *vdrtimers = &Timers;
+#endif
       if (ch) {
 	// when switch from the other menus to the schedule, try to keep the same time
        	if (cMenuWhatsOnSearch::shiftTime)
@@ -536,7 +597,7 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key)
 	}
 	Display();
       }
-      else if ((HadSubMenu || gl_TimerProgged) && Update())
+      else if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers))
       {
 	  if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP
 	  {
diff --git a/menu_main.h b/menu_main.h
index e4a6bb8..26452bf 100644
--- a/menu_main.h
+++ b/menu_main.h
@@ -38,7 +38,7 @@ class cMenuSearchMain : public cOsdMenu {
   int currentChannel;
   eOSState Record(void);
   eOSState ExtendedSearch(void);
-  void PrepareSchedule(cChannel *Channel);
+  void PrepareSchedule(const cChannel *Channel);
   eOSState Commands(eKeys Key);
   void SetHelpKeys(bool Force = false);
   int GetTab(int Tab);
@@ -53,7 +53,7 @@ class cMenuSearchMain : public cOsdMenu {
   eOSState Switch(void);
   eOSState Shift(int iMinutes);
   eOSState ShowSummary();
-  bool Update(void);
+  bool Update(const cTimers *vdrtimers);
   void UpdateCurrent();
 #ifdef USE_GRAPHTFT
   virtual const char* MenuKind() { return "MenuEpgsSchedule"; }
diff --git a/menu_myedittimer.c b/menu_myedittimer.c
index a6529a4..a9baaf6 100644
--- a/menu_myedittimer.c
+++ b/menu_myedittimer.c
@@ -76,7 +76,9 @@ cMenuMyEditTimer::cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* Event,
 	Set();
 	SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, NULL, NULL);
     }
+#if VDRVERSNUM < 20300
   Timers.IncBeingEdited();
+#endif
 }
 
 void cMenuMyEditTimer::SplitFile()
@@ -130,7 +132,13 @@ void cMenuMyEditTimer::Set()
 #ifdef USE_PINPLUGIN
     if (cOsd::pinValid || !fskProtection) Add(new cMenuEditChanItem(tr("Channel"), &channel));
     else {
-      cString buf = cString::sprintf("%s\t%s", tr("Channel"), Channels.GetByNumber(channel)->Name());
+#if VDRVERSNUM > 20300
+        LOCK_CHANNELS_READ;
+        const cChannels *vdrchannels = Channels;
+#else
+        cChannels *vdrchannels = &Channels;
+#endif
+      cString buf = cString::sprintf("%s\t%s", tr("Channel"), vdrchannels->GetByNumber(channel)->Name());
       Add(new cOsdItem(buf));
     }
 #else
@@ -162,7 +170,13 @@ void cMenuMyEditTimer::Set()
     }
     else if (IsSingleEvent() && event)
     {
-	checkmode = DefTimerCheckModes.GetMode(Channels.GetByNumber(channel));
+#if VDRVERSNUM > 20300
+	LOCK_CHANNELS_READ;
+	const cChannels *vdrchannels = Channels;
+#else
+	cChannels *vdrchannels = &Channels;
+#endif
+	checkmode = DefTimerCheckModes.GetMode(vdrchannels->GetByNumber(channel));
 	char* checkmodeAux = GetAuxValue(timer, "update");
 	if (checkmodeAux)
 	{
@@ -196,7 +210,9 @@ cMenuMyEditTimer::~cMenuMyEditTimer()
 {
   if (timer && addIfConfirmed)
      delete timer; // apparently it wasn't confirmed
+#if VDRVERSNUM < 20300
   Timers.DecBeingEdited();
+#endif
 }
 
 void cMenuMyEditTimer::HandleSubtitle()
@@ -233,21 +249,41 @@ bool cMenuMyEditTimer::IsSingleEvent(void) const
 eOSState cMenuMyEditTimer::DeleteTimer()
 {
     // Check if this timer is active:
+#if VDRVERSNUM > 20300
+    LOCK_TIMERS_WRITE;
+    cTimers *vdrtimers = Timers;
+#else
+    cTimers *vdrtimers = &Timers;
+#endif
     if (timer && !addIfConfirmed) {
 	if (Interface->Confirm(trVDR("Delete timer?"))) {
 	    if (timer->Recording()) {
 		if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) {
 		    timer->Skip();
+#if VDRVERSNUM > 20300
+		    cRecordControls::Process(vdrtimers, time(NULL));
+#else
 		    cRecordControls::Process(time(NULL));
+#endif
 		}
 		else
 		    return osContinue;
 	    }
 	    LogFile.iSysLog("deleting timer %s", *timer->ToDescr());
-	    Timers.Del(timer);
-	    gl_timerStatusMonitor->SetConflictCheckAdvised();
-	    Timers.SetModified();
-	    return osBack;
+            if (vdrtimers)
+            {
+	       vdrtimers->Del(timer);
+
+	       gl_timerStatusMonitor->SetConflictCheckAdvised();
+#if VDRVERSNUM < 20300
+	       Timers.SetModified();
+#endif
+	       return osBack;
+            }
+            else
+            {
+               LogFile.iSysLog("EPGSEARCH deleting timer failed");
+            }
         }
     }
     return osContinue;
@@ -324,7 +360,13 @@ eOSState cMenuMyEditTimer::ProcessKey(eKeys Key)
 	{
 	    case kOk:
 	    {
-		cChannel *ch = Channels.GetByNumber(channel);
+#if VDRVERSNUM > 20300
+		LOCK_CHANNELS_READ;
+		const cChannels *vdrchannels = Channels;
+#else
+		cChannels *vdrchannels = &Channels;
+#endif
+		const cChannel *ch = vdrchannels->GetByNumber(channel);
 		if (!ch)
 		{
 		  ERROR(tr("*** Invalid Channel ***"));
@@ -405,12 +447,27 @@ eOSState cMenuMyEditTimer::ProcessKey(eKeys Key)
                     free(tmpFile);
                     free(tmpDir);
 
-                    if (addIfConfirmed)
-                      Timers.Add(timer);
+#if VDRVERSNUM > 20300
+                    {
+                    LOCK_TIMERS_WRITE;
+                    cTimers* vdrtimers = Timers;
+#else
+                    cTimers* vdrtimers = &Timers;
+#endif
+                    if (addIfConfirmed && vdrtimers != NULL)
+                      vdrtimers->Add(timer);
+#if VDRVERSNUM > 20300
+                    }
+                    LOCK_SCHEDULES_READ;
+                    timer->SetEventFromSchedule(Schedules);
+#else
                     timer->SetEventFromSchedule();
+#endif
                     timer->Matches();
                     gl_timerStatusMonitor->SetConflictCheckAdvised();
+#if VDRVERSNUM < 20300
                     Timers.SetModified();
+#endif
                     addIfConfirmed = false;
                 } else {
 		    free(tmpFile);
diff --git a/menu_quicksearch.c b/menu_quicksearch.c
index 069d5d8..53aeff5 100644
--- a/menu_quicksearch.c
+++ b/menu_quicksearch.c
@@ -248,7 +248,13 @@ eOSState cMenuQuickSearch::ProcessKey(eKeys Key)
 	    case kOk:
 		if (data.useChannel==1)
 		{
-		    cChannel *ch = Channels.GetByNumber(channelMin);
+#if VDRVERSNUM > 20300
+		    LOCK_CHANNELS_READ;
+		    const cChannels *vdrchannels = Channels;
+#else
+		    cChannels *vdrchannels = &Channels;
+#endif
+		    const cChannel *ch = vdrchannels->GetByNumber(channelMin);
 		    if (ch)
 			data.channelMin = ch;
 		    else
@@ -256,7 +262,7 @@ eOSState cMenuQuickSearch::ProcessKey(eKeys Key)
 		      ERROR(tr("*** Invalid Channel ***"));
 		      break;
 		    }
-		    ch = Channels.GetByNumber(channelMax);
+		    ch = vdrchannels->GetByNumber(channelMax);
 		    if (ch)
 			data.channelMax = ch;
 		    else
diff --git a/menu_searchedit.c b/menu_searchedit.c
index e44e8c8..9328e5b 100644
--- a/menu_searchedit.c
+++ b/menu_searchedit.c
@@ -643,7 +643,13 @@ eOSState cMenuEditSearchExt::ProcessKey(eKeys Key)
          case kOk:
             if (data.useChannel==1)
             {
-               cChannel *ch = Channels.GetByNumber(channelMin);
+#if VDRVERSNUM > 20300
+               LOCK_CHANNELS_READ;
+               const cChannels *vdrchannels = Channels;
+#else
+               cChannels *vdrchannels = &Channels;
+#endif
+               const cChannel *ch = vdrchannels->GetByNumber(channelMin);
                if (ch)
                   data.channelMin = ch;
                else
@@ -651,7 +657,7 @@ eOSState cMenuEditSearchExt::ProcessKey(eKeys Key)
 		 ERROR(tr("*** Invalid Channel ***"));
 		 break;
                }
-               ch = Channels.GetByNumber(channelMax);
+               ch = vdrchannels->GetByNumber(channelMax);
                if (ch)
                   data.channelMax = ch;
                else
diff --git a/menu_searchresults.c b/menu_searchresults.c
index dd46d95..396c9d6 100644
--- a/menu_searchresults.c
+++ b/menu_searchresults.c
@@ -67,10 +67,16 @@ cMenuSearchResultsItem::cMenuSearchResultsItem(const cEvent *EventInfo, bool Epi
    menuTemplate = MenuTemplate?MenuTemplate:cTemplFile::GetTemplateByName("MenuSearchResults");
    search = Search;
    inSwitchList = false;
-   Update(true);
+#if VDRVERSNUM > 20300
+   LOCK_TIMERS_READ;
+   const cTimers *vdrtimers = Timers;
+#else
+   cTimers *vdrtimers = &Timers;
+#endif
+   Update(vdrtimers, true);
 }
 
-bool cMenuSearchResultsItem::Update(bool Force)
+bool cMenuSearchResultsItem::Update(const cTimers* vdrtimers, bool Force)
 {
    if (!menuTemplate)
       return false;
@@ -80,8 +86,12 @@ bool cMenuSearchResultsItem::Update(bool Force)
    eTimerMatch OldTimerMatch = timerMatch;
    bool OldInSwitchList = inSwitchList;
    bool hasMatch = false;
-   cTimer* timer = NULL;
-   if (event) timer = Timers.GetMatch(event, &timerMatch);
+   const cTimer* timer = NULL;
+#if VDRVERSNUM > 20300
+   if (event) timer = vdrtimers->GetMatch(event, &timerMatch);
+#else
+   if (event) timer = ((cTimers*)vdrtimers)->GetMatch(event, &timerMatch);
+#endif
    if (event) inSwitchList = (SwitchTimers.InSwitchList(event)!=NULL);
    if (timer) hasMatch = true;
 
@@ -171,7 +181,7 @@ bool cMenuSearchResultsItem::Update(bool Force)
    return result;
 }
 
-cMenuSearchResultsItem::cMenuSearchResultsItem(cRecording *Recording)
+cMenuSearchResultsItem::cMenuSearchResultsItem(const cRecording *Recording)
 {
    previewTimer = false;
    episodeOnly = false;
@@ -187,7 +197,13 @@ cMenuSearchResultsItem::cMenuSearchResultsItem(cRecording *Recording)
 void cMenuSearchResultsItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable)
 {
 #if APIVERSNUM >= 10733
-  cChannel *channel = event?Channels.GetByChannelID(event->ChannelID(), true, true):NULL;
+#if VDRVERSNUM > 20300
+  LOCK_CHANNELS_READ;
+  const cChannels *vdrchannels = Channels;
+#else
+  cChannels *vdrchannels = &Channels;
+#endif
+  const cChannel *channel = event?vdrchannels->GetByChannelID(event->ChannelID(), true, true):NULL;
   if (!event)
      DisplayMenu->SetItem(Text(), Index, Current, Selectable);
   else if (!DisplayMenu->SetItemEvent(event, Index, Current, Selectable, channel, true, timerMatch))
@@ -222,11 +238,11 @@ int cMenuSearchResults::GetTab(int Tab)
    return menuTemplate->Tab(Tab-1);
 }
 
-bool cMenuSearchResults::Update(void)
+bool cMenuSearchResults::Update(const cTimers* vdrtimers)
 {
    bool result = false;
    for (cOsdItem *item = First(); item; item = Next(item)) {
-      if (((cMenuSearchResultsItem *)item)->Update())
+      if (((cMenuSearchResultsItem *)item)->Update(vdrtimers))
          result = true;
    }
    return result;
@@ -237,10 +253,16 @@ eOSState cMenuSearchResults::Record(void)
    UpdateCurrent();
    cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current());
    if (item) {
+#if VDRVERSNUM > 20300
+      LOCK_TIMERS_WRITE;
+      cTimers *vdrtimers = Timers;
+#else
+      cTimers *vdrtimers = &Timers;
+#endif
       if (item->timerMatch == tmFull)
       {
          eTimerMatch tm = tmNone;
-         cTimer *timer = Timers.GetMatch(item->event, &tm);
+         cTimer *timer = vdrtimers->GetMatch(item->event, &tm);
          if (timer)
 	   {
 	     if (EPGSearchConfig.useVDRTimerEditMenu)
@@ -252,7 +274,7 @@ eOSState cMenuSearchResults::Record(void)
 
       cTimer *timer = new cTimer(item->event);
       PrepareTimerFile(item->event, timer);
-      cTimer *t = Timers.GetTimer(timer);
+      cTimer *t = vdrtimers->GetTimer(timer);
       if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL)))
       {
          if (t)
@@ -290,15 +312,17 @@ eOSState cMenuSearchResults::Record(void)
 #endif
 
          SetAux(timer, fullaux);
-         Timers.Add(timer);
+         vdrtimers->Add(timer);
 	 gl_timerStatusMonitor->SetConflictCheckAdvised();
          timer->Matches();
+#if VDRVERSNUM < 20300
          Timers.SetModified();
+#endif
          LogFile.iSysLog("timer %s added (active)", *timer->ToDescr());
 
          if (HasSubMenu())
             CloseSubMenu();
-         if (Update())
+         if (Update(vdrtimers))
             Display();
          SetHelpKeys();
       }
@@ -312,7 +336,13 @@ eOSState cMenuSearchResults::Switch(void)
    UpdateCurrent();
    cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current());
    if (item) {
-      cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+      LOCK_CHANNELS_READ;
+      const cChannels *vdrchannels = Channels;
+#else
+      cChannels *vdrchannels = &Channels;
+#endif
+      const cChannel *channel = vdrchannels->GetByChannelID(item->event->ChannelID(), true, true);
       if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
          return osEnd;
    }
@@ -342,7 +372,13 @@ eOSState cMenuSearchResults::ShowSummary()
       const cEvent *ei = ((cMenuSearchResultsItem *)Get(Current()))->event;
       if (ei)
       {
-         cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
+         const cChannel *channel = vdrchannels->GetByChannelID(ei->ChannelID(), true, true);
          if (channel)
             return AddSubMenu(new cMenuEventSearch(ei, eventObjects));
       }
@@ -454,7 +490,13 @@ eOSState cMenuSearchResults::ProcessKey(eKeys Key)
    }
    if (!HasSubMenu())
    {
-      if ((HadSubMenu || gl_TimerProgged) && Update())
+#if VDRVERSNUM > 20300
+      LOCK_TIMERS_READ;
+      const cTimers *vdrtimers = Timers;
+#else
+      cTimers *vdrtimers = &Timers;
+#endif
+      if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers))
       {
          if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP
          {
@@ -768,12 +810,18 @@ cMenuSearchResultsForRecs::cMenuSearchResultsForRecs(const char *query)
 
 bool cMenuSearchResultsForRecs::BuildList()
 {
-   cRecording **pArray = NULL;
+   const cRecording **pArray = NULL;
    int num = 0;
 
    int current = Current();
    Clear();
-   for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+#if VDRVERSNUM > 20300
+   LOCK_RECORDINGS_READ;
+   const cRecordings *vdrrecordings = Recordings;
+#else
+   cRecordings *vdrrecordings = &Recordings;
+#endif
+   for (const cRecording *recording = vdrrecordings->First(); recording; recording = vdrrecordings->Next(recording)) {
      const cRecordingInfo *recInfo = recording->Info();
      if (!recInfo) continue;
      string s1 = (recInfo && recInfo->Title())?recInfo->Title():"";
@@ -808,7 +856,7 @@ bool cMenuSearchResultsForRecs::BuildList()
        }
 
      if (match) {
-       cRecording **tmp = (cRecording **)realloc(pArray, (num + 1) * sizeof(cRecording *));
+       const cRecording **tmp = (const cRecording **)realloc(pArray, (num + 1) * sizeof(cRecording *));
        if (tmp)
        {
            pArray=tmp;
@@ -829,9 +877,15 @@ bool cMenuSearchResultsForRecs::BuildList()
    return true;
 }
 
-cRecording *cMenuSearchResultsForRecs::GetRecording(cMenuSearchResultsItem *Item)
+const cRecording *cMenuSearchResultsForRecs::GetRecording(cMenuSearchResultsItem *Item)
 {
-   cRecording *recording = Recordings.GetByName(Item->FileName());
+#if VDRVERSNUM > 20300
+   LOCK_RECORDINGS_READ;
+   const cRecordings *vdrrecordings = Recordings;
+#else
+   cRecordings *vdrrecordings = &Recordings;
+#endif
+   const cRecording *recording = vdrrecordings->GetByName(Item->FileName());
    if (!recording)
      ERROR(tr("Error while accessing recording!"));
    return recording;
@@ -842,7 +896,7 @@ eOSState cMenuSearchResultsForRecs::Play(void)
    cMenuSearchResultsItem *ri = (cMenuSearchResultsItem*)Get(Current());
    if (ri)
    {
-      cRecording *recording = GetRecording(ri);
+      const cRecording *recording = GetRecording(ri);
       if (recording) {
 #if APIVERSNUM < 10728
          cReplayControl::SetRecording(recording->FileName(), recording->Title());
diff --git a/menu_searchresults.h b/menu_searchresults.h
index 05d5660..f31d9c0 100644
--- a/menu_searchresults.h
+++ b/menu_searchresults.h
@@ -58,8 +58,8 @@ class cMenuSearchResultsItem : public cOsdItem {
     cMenuSearchResultsItem(const cEvent *EventInfo, bool EpisodeOnly = false,
                            bool PreviewTimer = false, cMenuTemplate* MenuTemplate = NULL,
                            const cSearchExt* Search = NULL);
-    cMenuSearchResultsItem(cRecording *Recording);
-    bool Update(bool Force = false);
+    cMenuSearchResultsItem(const cRecording *Recording);
+    bool Update(const cTimers* vdrtimers, bool Force = false);
     void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable);
 };
 
@@ -83,7 +83,7 @@ class cMenuSearchResults : public cOsdMenu {
     eOSState Commands(eKeys Key, cSearchExt* SearchExt = NULL);
     int GetTab(int Tab);
     virtual void SetHelpKeys(bool Force=false)=0;
-    bool Update(void);
+    bool Update(const cTimers* vdrtimers);
     void UpdateCurrent();
 
     static const cEvent *scheduleEventInfo;
@@ -131,7 +131,7 @@ class cMenuSearchResultsForRecs : public cMenuSearchResultsForQuery {
     virtual bool BuildList();
     eOSState ProcessKey(eKeys Key);
     eOSState Play(void);
-    cRecording *GetRecording(cMenuSearchResultsItem *Item);
+    const cRecording *GetRecording(cMenuSearchResultsItem *Item);
   public:
    cMenuSearchResultsForRecs(const char *query);
 };
diff --git a/menu_switchtimers.c b/menu_switchtimers.c
index 1a8139a..7c1bc72 100644
--- a/menu_switchtimers.c
+++ b/menu_switchtimers.c
@@ -136,7 +136,13 @@ void cMenuSwitchTimerItem::Set()
     tm *tm = localtime_r(&startTime, &tm_r);
     strftime(datebuf, sizeof(datebuf), "%d.%m", tm);
 
-    cChannel* channel = Channels.GetByChannelID(switchTimer->channelID,true,true);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel* channel = vdrchannels->GetByChannelID(switchTimer->channelID,true,true);
 
     msprintf(&buffer, "%s\t%d\t%s\t%s\t%d\'\t%s~%s", switchTimer->mode==1?"":">", channel?channel->Number():-1, datebuf, TIMESTRING(startTime), switchTimer->switchMinsBefore, event->Title()?event->Title():"", event->ShortText()?event->ShortText():"");
     SetText(buffer, false);
diff --git a/menu_templateedit.c b/menu_templateedit.c
index f1c02b3..fc7d9c3 100644
--- a/menu_templateedit.c
+++ b/menu_templateedit.c
@@ -187,7 +187,13 @@ eOSState cMenuEditTemplate::ProcessKey(eKeys Key)
          case kOk:
             if (data.useChannel==1)
             {
-               cChannel *ch = Channels.GetByNumber(channelMin);
+#if VDRVERSNUM > 20300
+               LOCK_CHANNELS_READ;
+               const cChannels *vdrchannels = Channels;
+#else
+               cChannels *vdrchannels = &Channels;
+#endif
+               const cChannel *ch = vdrchannels->GetByNumber(channelMin);
                if (ch)
                   data.channelMin = ch;
                else
@@ -195,7 +201,7 @@ eOSState cMenuEditTemplate::ProcessKey(eKeys Key)
 		 ERROR(tr("*** Invalid Channel ***"));
 		 break;
                }
-               ch = Channels.GetByNumber(channelMax);
+               ch = vdrchannels->GetByNumber(channelMax);
                if (ch)
                   data.channelMax = ch;
                else
diff --git a/menu_timersdone.c b/menu_timersdone.c
index a239892..6eb370d 100644
--- a/menu_timersdone.c
+++ b/menu_timersdone.c
@@ -44,7 +44,13 @@ void cMenuTimerDoneItem::Set(void)
    tm *tm = localtime_r(&timerDone->start, &tm_r);
    strftime(buf, sizeof(buf), "%d.%m.%y %H:%M", tm);
 
-   const cChannel* ch = Channels.GetByChannelID(timerDone->channelID, true, true);
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   const cChannel* ch = vdrchannels->GetByChannelID(timerDone->channelID, true, true);
    msprintf(&buffer, "%d\t%s\t%s~%s", ch?ch->Number():0, buf, timerDone->title.c_str(), timerDone->shorttext.c_str());
    SetText(buffer, false);
 }
diff --git a/menu_whatson.c b/menu_whatson.c
index daa4359..51fa7e0 100644
--- a/menu_whatson.c
+++ b/menu_whatson.c
@@ -55,7 +55,7 @@ extern bool isUTF8;
 int gl_InfoConflict = 0;
 
 // --- cMenuMyScheduleItem ------------------------------------------------------
-cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, cChannel *Channel, showMode Mode, cMenuTemplate* MenuTemplate)
+cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, const cChannel *Channel, showMode Mode, cMenuTemplate* MenuTemplate)
 {
    event = Event;
    channel = Channel;
@@ -63,10 +63,16 @@ cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, cChannel *Channel,
    timerMatch = tmNone;
    inSwitchList = false;
    menuTemplate = MenuTemplate;
-   Update(true);
+#if VDRVERSNUM > 20300
+   LOCK_TIMERS_READ;
+   const cTimers *vdrtimers = Timers;
+#else
+   cTimers *vdrtimers = &Timers;
+#endif
+   Update(vdrtimers, true);
 }
 
-bool cMenuMyScheduleItem::Update(bool Force)
+bool cMenuMyScheduleItem::Update(const cTimers* vdrtimers, bool Force)
 {
    if (!menuTemplate)
       return false;
@@ -80,8 +86,12 @@ bool cMenuMyScheduleItem::Update(bool Force)
    eTimerMatch OldTimerMatch = timerMatch;
    bool OldInSwitchList = inSwitchList;
    bool hasMatch = false;
-   cTimer* timer = NULL;
-   if (event) timer = Timers.GetMatch(event, &timerMatch);
+   const cTimer* timer = NULL;
+#if VDRVERSNUM > 20300
+   if (event) timer = vdrtimers->GetMatch(event, &timerMatch);
+#else
+   if (event) timer = ((cTimers*)vdrtimers)->GetMatch(event, &timerMatch);
+#endif
    if (event) inSwitchList = (SwitchTimers.InSwitchList(event)!=NULL);
    if (timer) hasMatch = true;
 
@@ -257,14 +267,20 @@ void cMenuMyScheduleItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index,
 }
 
 // --- cMenuMyScheduleSepItem ------------------------------------------------------
-cMenuMyScheduleSepItem::cMenuMyScheduleSepItem(const cEvent *Event, cChannel *Channel)
+cMenuMyScheduleSepItem::cMenuMyScheduleSepItem(const cEvent *Event, const cChannel *Channel)
   : cMenuMyScheduleItem(Event, Channel, showNow, NULL)
 {
    event = Event;
    channel = Channel;
    dummyEvent = NULL;
    SetSelectable(false);
-   Update(true);
+#if VDRVERSNUM > 20300
+   LOCK_TIMERS_READ;
+   const cTimers *vdrtimers = Timers;
+#else
+   cTimers *vdrtimers = &Timers;
+#endif
+   Update(vdrtimers, true);
 }
 
 cMenuMyScheduleSepItem::~cMenuMyScheduleSepItem()
@@ -273,7 +289,7 @@ cMenuMyScheduleSepItem::~cMenuMyScheduleSepItem()
     delete dummyEvent;
 }
 
-bool cMenuMyScheduleSepItem::Update(bool Force)
+bool cMenuMyScheduleSepItem::Update(const cTimers* vdrtimer, bool Force)
 {
   if (channel)
     SetText(cString::sprintf("%s\t %s %s", MENU_SEPARATOR_ITEMS, channel->Name(), MENU_SEPARATOR_ITEMS));
@@ -300,7 +316,7 @@ void cMenuMyScheduleSepItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Inde
 
 int cMenuWhatsOnSearch::currentChannel = 0;
 showMode cMenuWhatsOnSearch::currentShowMode = showNow;
-cChannel *cMenuWhatsOnSearch::scheduleChannel = NULL;
+const cChannel *cMenuWhatsOnSearch::scheduleChannel = NULL;
 extern const char *ShowModes[];
 cList<cShowMode> cMenuWhatsOnSearch::showModes;
 time_t cMenuWhatsOnSearch::seekTime = 0;
@@ -429,7 +445,13 @@ void cMenuWhatsOnSearch::LoadSchedules()
    if (currentChannel > maxChannel)
       maxChannel = 0;
 
-   for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel))
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   for (const cChannel *Channel = vdrchannels->First(); Channel; Channel = vdrchannels->Next(Channel))
    {
       if (!Channel->GroupSep())
       {
@@ -544,9 +566,9 @@ cShowMode* cMenuWhatsOnSearch::GetShowMode(showMode mode)
    return NULL;
 }
 
-cChannel *cMenuWhatsOnSearch::ScheduleChannel(cChannel *force_channel)
+const cChannel *cMenuWhatsOnSearch::ScheduleChannel(const cChannel *force_channel)
 {
-   cChannel *ch = force_channel?force_channel:scheduleChannel;
+   const cChannel *ch = force_channel?force_channel:scheduleChannel;
    scheduleChannel = NULL;
    return ch;
 }
@@ -568,10 +590,16 @@ eOSState cMenuWhatsOnSearch::Record(void)
    cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current());
    if (item)
    {
+#if VDRVERSNUM > 20300
+      LOCK_TIMERS_WRITE;
+      cTimers *vdrtimers = Timers;
+#else
+      cTimers *vdrtimers = &Timers;
+#endif
       if (item->timerMatch == tmFull)
       {
          eTimerMatch tm = tmNone;
-         cTimer *timer = Timers.GetMatch(item->event, &tm);
+         cTimer *timer = vdrtimers->GetMatch(item->event, &tm);
          if (timer)
 	   {
 	     if (EPGSearchConfig.useVDRTimerEditMenu)
@@ -588,9 +616,13 @@ eOSState cMenuWhatsOnSearch::Record(void)
          PrepareTimerFile(item->event, timer);
       }
       else
+#if VDRVERSNUM > 20300
          timer = new cTimer(false, false, item->channel);
+#else
+         timer = new cTimer(false, false, (cChannel*)item->channel);
+#endif
 
-      cTimer *t = Timers.GetTimer(timer);
+      cTimer *t = vdrtimers->GetTimer(timer);
       if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL)))
       {
          if (t)
@@ -627,15 +659,17 @@ eOSState cMenuWhatsOnSearch::Record(void)
          fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux);
 #endif
          SetAux(timer, fullaux);
-         Timers.Add(timer);
+         vdrtimers->Add(timer);
 	 gl_timerStatusMonitor->SetConflictCheckAdvised();
          timer->Matches();
+#if VDRVERSNUM < 20300
          Timers.SetModified();
+#endif
          LogFile.iSysLog("timer %s added (active)", *timer->ToDescr());
 
          if (HasSubMenu())
             CloseSubMenu();
-         if (Update())
+         if (Update(vdrtimers))
             Display();
          SetHelpKeys();
       }
@@ -643,11 +677,11 @@ eOSState cMenuWhatsOnSearch::Record(void)
    return osContinue;
 }
 
-bool cMenuWhatsOnSearch::Update(void)
+bool cMenuWhatsOnSearch::Update(const cTimers* vdrtimers)
 {
    bool result = false;
    for (cOsdItem *item = First(); item; item = Next(item)) {
-      if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update())
+      if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update(vdrtimers))
          result = true;
    }
    return result;
@@ -725,7 +759,13 @@ eOSState cMenuWhatsOnSearch::Shift(int iMinutes)
    if (mi)
    {
       currentChannel = mi->channel->Number();
-      scheduleChannel = Channels.GetByNumber(currentChannel);
+#if VDRVERSNUM > 20300
+      LOCK_CHANNELS_READ;
+      const cChannels *vdrchannels = Channels;
+#else
+      cChannels *vdrchannels = &Channels;
+#endif
+      scheduleChannel = vdrchannels->GetByNumber(currentChannel);
    }
    LoadSchedules();
    Display();
@@ -741,7 +781,13 @@ eOSState cMenuWhatsOnSearch::ShowSummary()
       const cEvent *ei = ((cMenuMyScheduleItem *)Get(Current()))->event;
       if (ei)
       {
-         cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
+         const cChannel *channel = vdrchannels->GetByChannelID(ei->ChannelID(), true, true);
          if (channel)
             return AddSubMenu(new cMenuEventSearch(ei, eventObjects, SurfModeChannel));
       }
@@ -866,7 +912,13 @@ eOSState cMenuWhatsOnSearch::ProcessKey(eKeys Key)
                   if (mi && mi->Selectable())
                   {
                      currentChannel = mi->channel->Number();
-                     scheduleChannel = Channels.GetByNumber(currentChannel);
+#if VDRVERSNUM > 20300
+                     LOCK_CHANNELS_READ;
+                     const cChannels *vdrchannels = Channels;
+#else
+                     cChannels *vdrchannels = &Channels;
+#endif
+                     scheduleChannel = vdrchannels->GetByNumber(currentChannel);
                   }
                }
                else
@@ -904,7 +956,13 @@ eOSState cMenuWhatsOnSearch::ProcessKey(eKeys Key)
    }
    if (!HasSubMenu())
    {
-      if ((HadSubMenu || gl_TimerProgged) && Update())
+#if VDRVERSNUM > 20300
+      LOCK_TIMERS_READ;
+      const cTimers *vdrtimers = Timers;
+#else
+      cTimers *vdrtimers = &Timers;
+#endif
+      if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers))
       {
          if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP
          {
diff --git a/menu_whatson.h b/menu_whatson.h
index 3fd028d..34d6de3 100644
--- a/menu_whatson.h
+++ b/menu_whatson.h
@@ -33,14 +33,14 @@ The project's page is at http://winni.vdr-developer.org/epgsearch
 class cMenuMyScheduleItem : public cOsdItem {
 public:
   const cEvent *event;
-  cChannel *channel;
+  const cChannel *channel;
   showMode mode;
   eTimerMatch timerMatch;
   bool inSwitchList;
   cMenuTemplate* menuTemplate;
 
-  cMenuMyScheduleItem(const cEvent *Event, cChannel *Channel = NULL, showMode ShowMode = showNow, cMenuTemplate* menuTemplate = NULL);
-  virtual bool Update(bool Force = false);
+  cMenuMyScheduleItem(const cEvent *Event, const cChannel *Channel = NULL, showMode ShowMode = showNow, cMenuTemplate* menuTemplate = NULL);
+  virtual bool Update(const cTimers* vdrtimers, bool Force = false);
   virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable);
 
 };
@@ -52,9 +52,9 @@ class cMenuMyScheduleSepItem : public cMenuMyScheduleItem {
                       // if VDR had a SetItemSeparator function for this
 public:
 
-  cMenuMyScheduleSepItem(const cEvent *Event, cChannel *Channel = NULL);
+  cMenuMyScheduleSepItem(const cEvent *Event, const cChannel *Channel = NULL);
   ~cMenuMyScheduleSepItem();
-  virtual bool Update(bool Force = false);
+  virtual bool Update(const cTimers* vdrtimers, bool Force = false);
   virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable);
 };
 
@@ -68,7 +68,7 @@ private:
   static int currentChannel;
   cEventObjects eventObjects;
  public:
-  static cChannel *scheduleChannel;
+  static const cChannel *scheduleChannel;
   static cList<cShowMode> showModes;
   static showMode currentShowMode;
   static int shiftTime;
@@ -80,7 +80,7 @@ private:
   void LoadSchedules();
   static int CurrentChannel(void) { return currentChannel; }
   static void SetCurrentChannel(int ChannelNr) { currentChannel = ChannelNr; }
-  static cChannel *ScheduleChannel(cChannel* forceChannel = NULL);
+  static const cChannel *ScheduleChannel(const cChannel* forceChannel = NULL);
   virtual eOSState ProcessKey(eKeys Key);
   virtual eOSState Switch(void);
   virtual eOSState Shift(int);
@@ -88,7 +88,7 @@ private:
   virtual eOSState ShowSummary();
   void SetHelpKeys(bool Force = false);
   int GetTab(int Tab);
-  bool Update(void);
+  bool Update(const cTimers* vdrtimers);
   void CreateShowModes();
   static cShowMode* GetShowMode(showMode mode);
   void UpdateCurrent();
diff --git a/patches/vdr.epgsearch-exttimeredit-2.3.1.diff b/patches/vdr.epgsearch-exttimeredit-2.3.1.diff
new file mode 100644
index 0000000..cd453e1
--- /dev/null
+++ b/patches/vdr.epgsearch-exttimeredit-2.3.1.diff
@@ -0,0 +1,114 @@
+Index: current/menu.c
+===================================================================
+--- menu.c.orig	2015-11-02 11:54:55.310709767 +0100
++++ menu.c	2015-11-02 11:54:55.310709767 +0100
+@@ -1190,6 +1190,7 @@
+ class cMenuTimerItem : public cOsdItem {
+ private:
+   const cTimer *timer;
++  void DoSet(void);
+ public:
+   cMenuTimerItem(const cTimer *Timer);
+   virtual int Compare(const cListObject &ListObject) const;
+@@ -1201,7 +1202,7 @@
+ cMenuTimerItem::cMenuTimerItem(const cTimer *Timer)
+ {
+   timer = Timer;
+-  Set();
++  DoSet();
+ }
+ 
+ int cMenuTimerItem::Compare(const cListObject &ListObject) const
+@@ -1211,6 +1212,19 @@
+ 
+ void cMenuTimerItem::Set(void)
+ {
++  // check for deleted timer
++  LOCK_TIMERS_READ;
++  for (const cTimer *t = Timers->First(); ; t = Timers->Next(t)) {
++     if (t == timer)
++       break;  // timer still there
++     if (t == NULL)
++       return; // no matching timer found
++     }
++  DoSet();
++}
++
++void cMenuTimerItem::DoSet(void)
++{
+   cString day, name("");
+   if (timer->WeekDays())
+      day = timer->PrintDay(0, timer->WeekDays(), false);
+@@ -1258,8 +1273,7 @@
+   cStateKey timersStateKey;
+   int helpKeys;
+   void Set(void);
+-  eOSState Edit(void);
+-  eOSState New(void);
++  eOSState Edit(bool New = false);
+   eOSState Delete(void);
+   eOSState OnOff(void);
+   eOSState Info(void);
+@@ -1351,20 +1365,29 @@
+   return osContinue;
+ }
+ 
+-eOSState cMenuTimers::Edit(void)
+-{
+-  if (HasSubMenu() || Count() == 0)
+-     return osContinue;
+-  return AddSubMenu(new cMenuEditTimer(GetTimer()));
+-}
+-
+-eOSState cMenuTimers::New(void)
++eOSState cMenuTimers::Edit(bool New)
+ {
+-  if (HasSubMenu())
++  if (HasSubMenu() || Count() == 0 && !New)
+      return osContinue;
+   cTimer *Timer = new cTimer;
+   if (*Setup.SVDRPDefaultHost)
+      Timer->SetRemote(Setup.SVDRPDefaultHost);
++  // Data structure for service "Epgsearch-exttimeredit-v1.0"
++  struct Epgsearch_exttimeredit_v1_0
++  {
++    // in
++    cTimer* timer;          // pointer to the timer to edit
++    bool bNew;              // flag that indicates, if this is a new timer or an existing one
++    const cEvent* event;    // pointer to the event corresponding to this timer (may be NULL)
++    // out
++    cOsdMenu* pTimerMenu;   // pointer to the menu of results
++  } exttimeredit;
++  exttimeredit.timer = New ? (new cTimer) : GetTimer();
++  exttimeredit.bNew = New;
++  exttimeredit.event = exttimeredit.timer->Event();
++  if (cPluginManager::CallFirstService("Epgsearch-exttimeredit-v1.0", &exttimeredit))
++    return AddSubMenu(exttimeredit.pTimerMenu);
++
+   return AddSubMenu(new cMenuEditTimer(Timer, true));
+ }
+ 
+@@ -1423,7 +1446,7 @@
+      switch (Key) {
+        case kOk:     return Edit();
+        case kRed:    state = OnOff(); break; // must go through SetHelpKeys()!
+-       case kGreen:  return New();
++       case kGreen:  return Edit(true);
+        case kYellow: state = Delete(); break;
+        case kInfo:
+        case kBlue:   return Info();
+@@ -1437,6 +1460,14 @@
+      Add(new cMenuTimerItem(Timer), true);
+      Display();
+      }
++  if (!HasSubMenu()) {
++     LOCK_TIMERS_READ;
++     if (Timers->Count()<Count()) {
++       // timer was deleted
++       cOsdMenu::Del(Current());
++       Display();
++       }
++     }
+   if (Key != kNone)
+      SetHelpKeys();
+   return state;
diff --git a/pending_notifications.c b/pending_notifications.c
index 4ce480f..8d3046d 100644
--- a/pending_notifications.c
+++ b/pending_notifications.c
@@ -121,7 +121,13 @@ const char *cPendingNotification::ToText(void) const
 	free(buffer);
     buffer = NULL;
 
-    cChannel *channel = Channels.GetByChannelID(channelID, true, true);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true);
     if (!channel)
 	LogFile.Log(3,"invalid channel in pending notifications!");
 
diff --git a/recdone.c b/recdone.c
index 7270c67..e9b52e0 100644
--- a/recdone.c
+++ b/recdone.c
@@ -50,7 +50,7 @@ cRecDone::cRecDone()
     rawdescription = NULL;
 }
 
-cRecDone::cRecDone(cTimer* Timer, const cEvent* Event, cSearchExt* Search)
+cRecDone::cRecDone(const cTimer* Timer, const cEvent* Event, cSearchExt* Search)
 {
     title = shortText = description = aux = rawdescription = NULL;
     startTime = 0;
@@ -200,7 +200,13 @@ const char *cRecDone::ToText(void)
 	free(buffer);
     buffer = NULL;
 
-    cChannel *channel = Channels.GetByChannelID(channelID, true, true);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true);
     if (!channel)
 	LogFile.Log(3,"invalid channel in recs done!");
 
@@ -226,7 +232,13 @@ bool cRecDone::Save(FILE *f)
 
 int cRecDone::ChannelNr()
 {
-    cChannel* channel = Channels.GetByChannelID(channelID, true, true);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel* channel = vdrchannels->GetByChannelID(channelID, true, true);
     if (!channel)
 	return -1;
     else
diff --git a/recdone.h b/recdone.h
index 471dd65..3157305 100644
--- a/recdone.h
+++ b/recdone.h
@@ -47,7 +47,7 @@ public:
     static char *buffer;
 
     cRecDone();
-    cRecDone(cTimer*, const cEvent* event, cSearchExt* search);
+    cRecDone(const cTimer*, const cEvent* event, cSearchExt* search);
     ~cRecDone();
 
     static bool Read(FILE *f);
diff --git a/recstatus.c b/recstatus.c
index 8e6afd8..f2fd993 100644
--- a/recstatus.c
+++ b/recstatus.c
@@ -27,11 +27,14 @@ The project's page is at http://winni.vdr-developer.org/epgsearch
 #include "conflictcheck_thread.h"
 #include "epgsearchcfg.h"
 #include <math.h>
-
+#if VDRVERSNUM > 20300
+#include "status_thread.h"
+#else
 #define ALLOWED_BREAK_INSECS 2
 
 extern int updateForced;
 extern int gl_InfoConflict;
+#endif
 
 
 cRecStatusMonitor* gl_recStatusMonitor = NULL;
@@ -42,6 +45,9 @@ cRecStatusMonitor::cRecStatusMonitor()
 
 void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const char* Filename, bool On)
 {
+#if VDRVERSNUM > 20300
+   cStatusThread::Init(Device,Name,Filename,On);
+#else
    time_t now = time(NULL);
    // insert new timers currently recording in TimersRecording
    if (On && Name)
@@ -130,7 +136,13 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
                // check if recording has ended before timer end
 
                bool complete = true;
-	       cRecording *pRecording = Recordings.GetByName(Filename);
+#if VDRVERSNUM > 20300
+	       LOCK_RECORDINGS_READ;
+	       const cRecordings *vdrrecordings = Recordings;
+#else
+	       cRecordings *vdrrecordings = &Recordings;
+#endif
+	       const cRecording *pRecording = vdrrecordings->GetByName(Filename);
 	       long timerLengthSecs = tiR->timer->StopTime()-tiR->timer->StartTime();
 	       int recFraction = 100;
 	       if (pRecording && timerLengthSecs)
@@ -191,9 +203,10 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
          tiR = TimersRecording.Next(tiR);
       }
    }
+#endif
 }
 
-int cRecStatusMonitor::TimerRecDevice(cTimer* timer)
+int cRecStatusMonitor::TimerRecDevice(const cTimer* timer)
 {
    if (!timer) return 0;
    for (cRecDoneTimerObj *tiR = TimersRecording.First(); tiR; tiR = TimersRecording.Next(tiR))
@@ -201,7 +214,7 @@ int cRecStatusMonitor::TimerRecDevice(cTimer* timer)
    return 0;
 }
 
-bool cRecStatusMonitor::IsPesRecording(cRecording *pRecording)
+bool cRecStatusMonitor::IsPesRecording(const cRecording *pRecording)
 {
 #if VDRVERSNUM < 10703
   return true;
@@ -214,7 +227,7 @@ bool cRecStatusMonitor::IsPesRecording(cRecording *pRecording)
 
 #if VDRVERSNUM < 10703
 
-int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording)
+int cRecStatusMonitor::RecLengthInSecs(const cRecording *pRecording)
 {
   struct stat buf;
   cString fullname = cString::sprintf("%s%s", pRecording->FileName(), "/index.vdr");
@@ -249,7 +262,7 @@ struct tIndexTs {
   }
   };
 
-int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording)
+int cRecStatusMonitor::RecLengthInSecs(const cRecording *pRecording)
 {
   struct stat buf;
   cString fullname = cString::sprintf("%s%s", pRecording->FileName(), IsPesRecording(pRecording) ? LOC_INDEXFILESUFFIX ".vdr" : LOC_INDEXFILESUFFIX);
@@ -263,4 +276,3 @@ int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording)
   return -1;
 }
 #endif
-
diff --git a/recstatus.h b/recstatus.h
index 1195bca..0d08b6c 100644
--- a/recstatus.h
+++ b/recstatus.h
@@ -32,20 +32,23 @@ public:
     cRecDone* recDone;
     time_t lastBreak;
 public:
-    cRecDoneTimerObj(cTimer* Timer, int DeviceNr) : cTimerObj(Timer), deviceNr(DeviceNr), recDone(NULL), lastBreak(0) {}
+    cRecDoneTimerObj(const cTimer* Timer, int DeviceNr) : cTimerObj(Timer), deviceNr(DeviceNr), recDone(NULL), lastBreak(0) {}
     ~cRecDoneTimerObj() { timer = NULL; recDone = NULL; } // do not delete anything!
 };
 
 class cRecStatusMonitor : public cStatus
 {
+#if VDRVERSNUM > 20300
+public:
+#endif
     cList<cRecDoneTimerObj> TimersRecording;
 protected:
     virtual void Recording(const cDevice *Device, const char *Name, const char*, bool On);
  public:
     cRecStatusMonitor();
-    int TimerRecDevice(cTimer*);
-    bool IsPesRecording(cRecording *pRecording);
-    int RecLengthInSecs(cRecording *pRecording);
+    int TimerRecDevice(const cTimer*);
+    bool IsPesRecording(const cRecording *pRecording);
+    int RecLengthInSecs(const cRecording *pRecording);
 };
 
 extern cRecStatusMonitor* gl_recStatusMonitor;
diff --git a/searchtimer_thread.c b/searchtimer_thread.c
index 34d625f..2ad4b07 100644
--- a/searchtimer_thread.c
+++ b/searchtimer_thread.c
@@ -99,9 +99,15 @@ void cSearchTimerThread::Stop(void) {
 }
 
 
-cTimer *cSearchTimerThread::GetTimer(cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly)
+const cTimer *cSearchTimerThread::GetTimer(const cTimers* vdrtimers, cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly)
 {
-   cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true);
    if (!channel)
       return NULL;
 
@@ -129,7 +135,7 @@ cTimer *cSearchTimerThread::GetTimer(cSearchExt *searchExt, const cEvent *pEvent
 
    tm *tmStartEv = localtime_r(&eStart, &tm_r);
 
-   for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti))
+   for (const cTimer *ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti))
    {
       if (ti->Channel() != channel)
          continue;
@@ -172,7 +178,7 @@ cTimer *cSearchTimerThread::GetTimer(cSearchExt *searchExt, const cEvent *pEvent
    return NULL;
 }
 
-bool cSearchTimerThread::TimerWasModified(cTimer* t)
+bool cSearchTimerThread::TimerWasModified(const cTimer* t)
 {
    if (!t) return false;
    if (t->HasFlags(tfVps)) return false; // if timer uses VPS we ignore user changes
@@ -228,11 +234,18 @@ void cSearchTimerThread::Action(void)
 	    while(EITScanner.Active() && m_Active && Running());
   	    LogFile.Log(1,"EPG scan finished");
 	 }
+#if VDRVERSNUM > 20300
+         // wait if TimersWriteLock is set or waited for
+         {
+             LOCK_TIMERS_READ;
+         }
+#else
          if (Timers.BeingEdited())
          {
             Wait.Wait(1000);
             continue;
          }
+#endif
          LogFile.iSysLog("search timer update started");
 
          UserVars.ResetCache(); // reset internal cache of user vars
@@ -252,7 +265,15 @@ void cSearchTimerThread::Action(void)
                searchExt = localSearchExts->Next(searchExt);
                continue;
             }
-            pOutdatedTimers = searchExt->GetTimerList(pOutdatedTimers);
+           {
+#if VDRVERSNUM > 20300
+            LOCK_TIMERS_READ;
+            cTimers *vdrtimers = (cTimers *)Timers;
+#else
+            cTimers *vdrtimers = &Timers;
+#endif
+            pOutdatedTimers = searchExt->GetTimerList(vdrtimers, pOutdatedTimers);
+           } // End of Block should release ReadLock
 
             cSearchResults* pSearchResults = searchExt->Run(-1, true);
             if (!pSearchResults)
@@ -274,9 +295,17 @@ void cSearchTimerThread::Action(void)
                if (!pEvent)
                   continue;
 
-               cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true);
+               {
+#if VDRVERSNUM > 20300
+               LOCK_CHANNELS_READ;
+               const cChannels *vdrchannels = Channels;
+#else
+               cChannels *vdrchannels = &Channels;
+#endif
+               const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true);
                if (!channel)
                   continue;
+               }
 
                int index = 0;
                cTimer *timer = new cTimer(pEvent);
@@ -303,7 +332,15 @@ void cSearchTimerThread::Action(void)
 
                // search for an already existing timer
                bool bTimesMatchExactly = false;
-               cTimer *t = GetTimer(searchExt, pEvent, bTimesMatchExactly);
+#if VDRVERSNUM > 20300
+               const cTimer *t = NULL;
+               {
+               LOCK_TIMERS_READ;
+               t = GetTimer(Timers,searchExt, pEvent, bTimesMatchExactly);
+               }
+#else
+               const cTimer *t = GetTimer(&Timers,searchExt, pEvent, bTimesMatchExactly);
+#endif
 
                char* Summary = NULL;
 	       uint timerMod = tmNoChange;
@@ -494,15 +531,25 @@ void cSearchTimerThread::Action(void)
                LogFile.Log(1,"removing outdated timers");
                for(cTimerObj *tObj = pOutdatedTimers->First(); tObj; tObj = pOutdatedTimers->Next(tObj))
                {
-                  cTimer* t = tObj->timer;
+                  const cTimer* t = tObj->timer;
                   // timer could have been deleted meanwhile, so check if its still there
                   bool found = false;
-                  for(cTimer* checkT = Timers.First(); checkT; checkT = Timers.Next(checkT))
+#if VDRVERSNUM > 20300
+                  {
+                  LOCK_TIMERS_READ;
+                  const cTimers *vdrtimers = Timers;
+#else
+                  cTimers *vdrtimers = &Timers;
+#endif
+                  for(const cTimer* checkT = vdrtimers->First(); checkT; checkT = vdrtimers->Next(checkT))
                      if (checkT == t)
                      {
                         found = true;
                         break;
                      }
+#if VDRVERSNUM > 20300
+                  }
+#endif
                   if (!found) continue;
 
                   if (TimerWasModified(t)) continue;
@@ -606,7 +653,7 @@ bool cSearchTimerThread::NeedUpdate()
    return  (m_lastUpdate <= LastModifiedTime(AddDirectory(CONFIGDIR, ".epgsearchupdate")) || updateForced>0);
 }
 
-char* cSearchTimerThread::SummaryExtended(cSearchExt* searchExt, cTimer* Timer, const cEvent* pEvent)
+char* cSearchTimerThread::SummaryExtended(cSearchExt* searchExt, const cTimer* Timer, const cEvent* pEvent)
 {
    bool UseVPS = searchExt->useVPS && pEvent->Vps() && Setup.UseVps;
    time_t eStart;
@@ -657,7 +704,7 @@ char* cSearchTimerThread::SummaryExtended(cSearchExt* searchExt, cTimer* Timer,
    return tmpSummary;
 }
 
-bool cSearchTimerThread::AddModTimer(cTimer* Timer, int index, cSearchExt* searchExt, const cEvent* pEvent, int Prio, int Lifetime, char* Summary, uint timerMod)
+bool cSearchTimerThread::AddModTimer(const cTimer* Timer, int index, cSearchExt* searchExt, const cEvent* pEvent, int Prio, int Lifetime, char* Summary, uint timerMod)
 {
    char *cmdbuf = NULL;
 
@@ -745,7 +792,7 @@ bool cSearchTimerThread::AddModTimer(cTimer* Timer, int index, cSearchExt* searc
    return true;
 }
 
-void cSearchTimerThread::RemoveTimer(cTimer* t, const cEvent* e)
+void cSearchTimerThread::RemoveTimer(const cTimer* t, const cEvent* e)
 {
    if (!t) return;
    if (EPGSearchConfig.sendMailOnSearchtimers)
@@ -773,9 +820,15 @@ void cSearchTimerThread::DelRecording(int index)
 void cSearchTimerThread::CheckExpiredRecs()
 {
    LogFile.Log(1, "check for expired recordings started");
+#if VDRVERSNUM > 20300
+   LOCK_RECORDINGS_WRITE;
+   cRecordings *vdrrecordings = Recordings;
+#else
    cThreadLock RecordingsLock(&Recordings);
+   cRecordings *vdrrecordings = &Recordings;
+#endif
    cList<cRecordingObj> DelRecordings;
-   for (cRecording *recording = Recordings.First(); recording && m_Active; recording = Recordings.Next(recording))
+   for (cRecording *recording = vdrrecordings->First(); recording && m_Active; recording = vdrrecordings->Next(recording))
    {
 #if APIVERSNUM < 10721
       LogFile.Log(3, "check recording %s from %s for expiration", recording->Name(), DAYDATETIME(recording->start));
@@ -849,7 +902,7 @@ void cSearchTimerThread::CheckExpiredRecs()
          if (!recording->Delete())
             LogFile.Log(1, "error deleting recording!");
          else
-            ::Recordings.DelByName(recording->FileName());
+            vdrrecordings->DelByName(recording->FileName());
       }
       else
          LogFile.Log(1, "recording already in use by a timer!");
@@ -895,15 +948,22 @@ void cSearchTimerThread::ModifyManualTimer(const cEvent* event, const cTimer* ti
    free(cmdbuf);
 }
 
-void cSearchTimerThread::CheckManualTimers()
+void cSearchTimerThread::CheckManualTimers(void)
 {
    LogFile.Log(1, "manual timer check started");
 
-   cSchedulesLock schedulesLock;
-   const cSchedules *schedules;
-   schedules = cSchedules::Schedules(schedulesLock);
+#if VDRVERSNUM > 20300
+    LOCK_TIMERS_WRITE;  // to be checked !!!
+    cTimers *vdrtimers = (cTimers*) Timers;
+    LOCK_SCHEDULES_READ;
+    const cSchedules *schedules = Schedules;
+#else
+    cTimers *vdrtimers = &Timers;
+    cSchedulesLock SchedulesLock;
+    const cSchedules* schedules = cSchedules::Schedules(SchedulesLock);
+#endif
 
-   for (cTimer *ti = Timers.First(); ti && m_Active; ti = Timers.Next(ti))
+   for (const cTimer *ti = vdrtimers->First(); ti && m_Active; ti = vdrtimers->Next(ti))
    {
       if (TriggeredFromSearchTimerID(ti) != -1) continue; // manual timer?
 
@@ -953,7 +1013,7 @@ void cSearchTimerThread::CheckManualTimers()
          {
             // collect all events touching the old timer margins
             cSearchResults eventlist;
-            for (cEvent *testevent = schedule->Events()->First(); testevent; testevent = schedule->Events()->Next(testevent))
+            for (const cEvent *testevent = schedule->Events()->First(); testevent; testevent = schedule->Events()->Next(testevent))
             {
                if (testevent->StartTime() < ti->StopTime() && testevent->EndTime() > ti->StartTime())
                   eventlist.Add(new cSearchResult(testevent, (const cSearchExt*)NULL));
@@ -1013,15 +1073,19 @@ void cSearchTimerThread::CheckEPGHours()
 
   time_t checkTime = time(NULL) + EPGSearchConfig.checkEPGHours * 60 * 60;
 
-  cSchedulesLock schedulesLock;
-  const cSchedules *schedules;
-  schedules = cSchedules::Schedules(schedulesLock);
+#if VDRVERSNUM > 20300
+    LOCK_SCHEDULES_READ;
+    const cSchedules *schedules = Schedules;
+#else
+    cSchedulesLock SchedulesLock;
+    const cSchedules* schedules = cSchedules::Schedules(SchedulesLock);
+#endif
 
   cChannelGroup channelsWithSmallEPG;
   cChannelGroupItem* channelInGroup = channelGroup->channels.First();
   while (channelInGroup)
     {
-      cChannel* channel = channelInGroup->channel;
+      const cChannel* channel = channelInGroup->channel;
       // get the channels schedule
       const cSchedule* schedule = schedules->GetSchedule(channel);
       if (!schedule || !schedule->GetEventAround(checkTime))
@@ -1040,7 +1104,7 @@ void cSearchTimerThread::CheckEPGHours()
       channelInGroup = channelsWithSmallEPG.channels.First();
       while (channelInGroup)
 	{
-	  cChannel* channel = channelInGroup->channel;
+	  const cChannel* channel = channelInGroup->channel;
 	  if (channel)
 	    sBuffer += " " + string(channel->ShortName(true));
 	  channelInGroup = channelsWithSmallEPG.channels.Next(channelInGroup);
diff --git a/searchtimer_thread.h b/searchtimer_thread.h
index 91476ac..a5326e4 100644
--- a/searchtimer_thread.h
+++ b/searchtimer_thread.h
@@ -52,16 +52,16 @@ class cSearchTimerThread: public cThread {
 
  protected:
     virtual void Action(void);
-    bool AddModTimer(cTimer* Timer, int, cSearchExt*, const cEvent*, int Prio, int Lifetime, char* Summary = NULL, uint timerMod = tmNoChange);
-    void RemoveTimer(cTimer* Timer, const cEvent* Event = NULL);
+    bool AddModTimer(const cTimer* Timer, int, cSearchExt*, const cEvent*, int Prio, int Lifetime, char* Summary = NULL, uint timerMod = tmNoChange);
+    void RemoveTimer(const cTimer* Timer, const cEvent* Event = NULL);
     void Stop(void);
     bool NeedUpdate();
-    bool TimerWasModified(cTimer* t);
+    bool TimerWasModified(const cTimer* t);
  public:
     static cSearchResults announceList;
-    static char* SummaryExtended(cSearchExt* searchExt, cTimer* Timer, const cEvent* pEvent);
+    static char* SummaryExtended(cSearchExt* searchExt, const cTimer* Timer, const cEvent* pEvent);
     static cSearchTimerThread *m_Instance;
-    static cTimer* GetTimer(cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly);
+    static const cTimer* GetTimer(const cTimers* vdrtimers, cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly);
     static bool justRunning;
 
     cSearchTimerThread(cPluginEpgsearch* thePlugin);
@@ -70,7 +70,7 @@ class cSearchTimerThread: public cThread {
     static void Exit(void);
     void CheckExpiredRecs();
     void DelRecording(int index);
-    void CheckManualTimers();
+    void CheckManualTimers(void);
     void ModifyManualTimer(const cEvent* event, const cTimer* timer, int bstart, int bstop);
     void CheckEPGHours();
 };
diff --git a/services.c b/services.c
index c714a14..3c2dac8 100644
--- a/services.c
+++ b/services.c
@@ -145,13 +145,25 @@ std::list<std::string> cEpgsearchServiceHandler::TranslateResults(cSearchResults
 
          eTimerMatch timerMatch;
          bool hasTimer = false;
-         if (Timers.GetMatch(pEvent, &timerMatch))
+#if VDRVERSNUM > 20300
+         LOCK_TIMERS_READ;
+         const cTimers *vdrtimers = Timers;
+#else
+         cTimers *vdrtimers = &Timers;
+#endif
+         if (vdrtimers->GetMatch(pEvent, &timerMatch))
             hasTimer = (timerMatch == tmFull);
 
          if (!result->search->useAsSearchTimer)
             result->needsTimer = false;
 
-         cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true);
+#if VDRVERSNUM > 20300
+         LOCK_CHANNELS_READ;
+         const cChannels *vdrchannels = Channels;
+#else
+         cChannels *vdrchannels = &Channels;
+#endif
+         const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true);
          int timerMode = hasTimer?1:(result->needsTimer?2:0);
 
          std::string title = pEvent->Title()?ReplaceAll(pEvent->Title(), "|", "!^pipe!^"):"";
diff --git a/recstatus.c b/status_thread.c
similarity index 66%
copy from recstatus.c
copy to status_thread.c
index 8e6afd8..f9c7a3e 100644
--- a/recstatus.c
+++ b/status_thread.c
@@ -21,40 +21,96 @@ The author can be reached at cwieninger at gmx.de
 The project's page is at http://winni.vdr-developer.org/epgsearch
 */
 
+#include <string>
+#include <list>
+#ifdef __FreeBSD__
+#include <netinet/in.h>
+#endif
+#include "timer_thread.h"
+#include "epgsearchcfg.h"
 #include "epgsearchtools.h"
+#include "services.h"
+#include "svdrpclient.h"
+#include "timerstatus.h"
 #include "recstatus.h"
 #include "recdone.h"
 #include "conflictcheck_thread.h"
-#include "epgsearchcfg.h"
+#include "status_thread.h"
 #include <math.h>
 
+#include <vdr/tools.h>
+#include <vdr/plugin.h>
+
+#if VDRVERSNUM > 20300
+
 #define ALLOWED_BREAK_INSECS 2
 
 extern int updateForced;
-extern int gl_InfoConflict;
 
+cStatusThread *cStatusThread::m_Instance = NULL;
+StatusThreadStatus cStatusThread::m_Status = StatusThreadReady;
+int gl_StatusProgged=0; // Flag that indicates, when programming is finished
 
-cRecStatusMonitor* gl_recStatusMonitor = NULL;
-
-cRecStatusMonitor::cRecStatusMonitor()
+cStatusThread::cStatusThread()
+: cThread("EPGSearch: recstatus")
 {
+    m_Active = false;
+}
+
+cStatusThread::~cStatusThread() {
+    if (m_Active)
+	Stop();
+    cStatusThread::m_Instance = NULL;
+}
+
+void cStatusThread::Init(const cDevice *Device, const char *Name, const char *Filename, bool On) {
+    if (m_Instance == NULL) {
+        m_Instance = new cStatusThread;
+    }
+    else {
+        if (m_Instance->m_Active) {
+            LogFile.eSysLog("Epgsearch recstatus_thread called too fast"); //should stack
+            return;
+        }
+    }
+    m_Instance->m_device=Device;
+    m_Instance->m_name=Name;
+    m_Instance->m_filename=Filename;
+    m_Instance->m_on=On;
+    m_Instance->Start();
+}
+
+void cStatusThread::Exit(void) {
+    if (m_Instance != NULL) {
+	m_Instance->Stop();
+	DELETENULL(m_Instance);
+    }
+
+}
+
+void cStatusThread::Stop(void) {
+    m_Active = false;
+    Cancel(3);
 }
 
-void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const char* Filename, bool On)
+void cStatusThread::Action(void)
 {
+   m_Active = true;
    time_t now = time(NULL);
    // insert new timers currently recording in TimersRecording
-   if (On && Name)
+   if (m_on && m_name)
    {
       if (EPGSearchConfig.checkTimerConflOnRecording)
          cConflictCheckThread::Init((cPluginEpgsearch*)cPluginManager::GetPlugin("epgsearch"), true);
 
-      for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti))
+      LOCK_TIMERS_READ;
+
+      for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti))
          if (ti->Recording())
          {
             // check if this is a new entry
             cRecDoneTimerObj *tiRFound = NULL;
-            for (cRecDoneTimerObj *tiR = TimersRecording.First(); tiR; tiR = TimersRecording.Next(tiR))
+            for (cRecDoneTimerObj *tiR = gl_recStatusMonitor->TimersRecording.First(); tiR; tiR = gl_recStatusMonitor->TimersRecording.Next(tiR))
                if (tiR->timer == ti)
                {
                   tiRFound = tiR;
@@ -65,21 +121,21 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
             {
                if (tiRFound->lastBreak > 0 && now - tiRFound->lastBreak <= ALLOWED_BREAK_INSECS)
                {
-                  LogFile.Log(1,"accepting resume of '%s' on device %d", Name, Device->CardIndex());
+                  LogFile.Log(1,"accepting resume of '%s' on device %d", m_name, m_device->CardIndex());
                   tiRFound->lastBreak = 0;
                }
                continue;
             }
 
-            cRecDoneTimerObj* timerObj = new cRecDoneTimerObj(ti, Device->DeviceNumber());
-            TimersRecording.Add(timerObj);
+            cRecDoneTimerObj* timerObj = new cRecDoneTimerObj(ti, m_device->DeviceNumber());
+            gl_recStatusMonitor->TimersRecording.Add(timerObj);
 
             cSearchExt* search = TriggeredFromSearchTimer(ti);
             if (!search || (search->avoidRepeats == 0 && search->delMode == 0)) // ignore if not avoid repeats and no auto-delete
                continue;
 
             bool vpsUsed = ti->HasFlags(tfVps) && ti->Event() && ti->Event()->Vps();
-            LogFile.Log(1,"recording started '%s' on device %d (search timer '%s'); VPS used: %s", Name, Device->CardIndex(), search->search, vpsUsed ? "Yes": "No");
+            LogFile.Log(1,"recording started '%s' on device %d (search timer '%s'); VPS used: %s", m_name, m_device->CardIndex(), search->search, vpsUsed ? "Yes": "No");
             const cEvent* event = ti->Event();
             if (!event)
             {
@@ -103,23 +159,23 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
          }
    }
 
-   if (!On)
+   if (!m_on)
    {
       cMutexLock RecsDoneLock(&RecsDone);
       // remove timers that finished recording from TimersRecording
       // incomplete recordings are kept for a while, perhaps they will be resumed
-      cRecDoneTimerObj *tiR = TimersRecording.First();
+      cRecDoneTimerObj *tiR = gl_recStatusMonitor->TimersRecording.First();
       while(tiR)
       {
          // check if timer still exists
          bool found = false;
-         for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti))
+         LOCK_TIMERS_READ;
+         for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti))
             if (ti == tiR->timer)
             {
                found = true;
                break;
             }
-
          if (found && !tiR->timer->Recording())
          {
             if (tiR->recDone)
@@ -130,12 +186,13 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
                // check if recording has ended before timer end
 
                bool complete = true;
-	       cRecording *pRecording = Recordings.GetByName(Filename);
+	       LOCK_RECORDINGS_READ;
+	       const cRecording *pRecording = Recordings->GetByName(m_filename);
 	       long timerLengthSecs = tiR->timer->StopTime()-tiR->timer->StartTime();
 	       int recFraction = 100;
 	       if (pRecording && timerLengthSecs)
 	       {
-		  int recLen = RecLengthInSecs(pRecording);
+		  int recLen = gl_recStatusMonitor->RecLengthInSecs(pRecording);
 		  recFraction = double(recLen) * 100 / timerLengthSecs;
 	       }
 	       bool vpsUsed = tiR->timer->HasFlags(tfVps) && tiR->timer->Event() && tiR->timer->Event()->Vps();
@@ -173,8 +230,8 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
             if (tiR->lastBreak == 0 || (now - tiR->lastBreak) > ALLOWED_BREAK_INSECS)
             { // remove finished recordings or those with an unallowed break
                if (tiR->recDone) delete tiR->recDone; // clean up
-               cRecDoneTimerObj *tiRNext = TimersRecording.Next(tiR);
-               TimersRecording.Del(tiR);
+               cRecDoneTimerObj *tiRNext = gl_recStatusMonitor->TimersRecording.Next(tiR);
+               gl_recStatusMonitor->TimersRecording.Del(tiR);
                tiR = tiRNext;
                continue;
             }
@@ -183,84 +240,14 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const
          if (!found)
          {
             if (tiR->recDone) delete tiR->recDone; // clean up
-            cRecDoneTimerObj *tiRNext = TimersRecording.Next(tiR);
-            TimersRecording.Del(tiR);
+            cRecDoneTimerObj *tiRNext = gl_recStatusMonitor->TimersRecording.Next(tiR);
+            gl_recStatusMonitor->TimersRecording.Del(tiR);
             tiR = tiRNext;
             continue;
          }
-         tiR = TimersRecording.Next(tiR);
+         tiR = gl_recStatusMonitor->TimersRecording.Next(tiR);
       }
    }
-}
-
-int cRecStatusMonitor::TimerRecDevice(cTimer* timer)
-{
-   if (!timer) return 0;
-   for (cRecDoneTimerObj *tiR = TimersRecording.First(); tiR; tiR = TimersRecording.Next(tiR))
-      if (tiR->timer == timer && timer->Recording()) return tiR->deviceNr+1;
-   return 0;
-}
-
-bool cRecStatusMonitor::IsPesRecording(cRecording *pRecording)
-{
-#if VDRVERSNUM < 10703
-  return true;
-#else
-  return pRecording && pRecording->IsPesRecording();
-#endif
-}
-
-#define LOC_INDEXFILESUFFIX     "/index"
-
-#if VDRVERSNUM < 10703
-
-int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording)
-{
-  struct stat buf;
-  cString fullname = cString::sprintf("%s%s", pRecording->FileName(), "/index.vdr");
-  if (stat(fullname, &buf) == 0)
-  {
-    struct tIndex { int offset; uchar type; uchar number; short reserved; };
-    int delta = buf.st_size % sizeof(tIndex);
-    if (delta)
-    {
-      delta = sizeof(tIndex) - delta;
-      esyslog("ERROR: invalid file size (%ld) in '%s'", buf.st_size, *fullname);
-    }
-    return (buf.st_size + delta) / sizeof(tIndex) / SecondsToFrames(1);
-  }
-  else
-    return -1;
-}
-
-#else
-
-struct tIndexTs {
-  uint64_t offset:40; // up to 1TB per file (not using off_t here - must definitely be exactly 64 bit!)
-  int reserved:7;     // reserved for future use
-  int independent:1;  // marks frames that can be displayed by themselves (for trick modes)
-  uint16_t number:16; // up to 64K files per recording
-  tIndexTs(off_t Offset, bool Independent, uint16_t Number)
-  {
-    offset = Offset;
-    reserved = 0;
-    independent = Independent;
-    number = Number;
-  }
-  };
-
-int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording)
-{
-  struct stat buf;
-  cString fullname = cString::sprintf("%s%s", pRecording->FileName(), IsPesRecording(pRecording) ? LOC_INDEXFILESUFFIX ".vdr" : LOC_INDEXFILESUFFIX);
-  if (pRecording->FileName() && *fullname && access(fullname, R_OK) == 0 && stat(fullname, &buf) == 0)
-    {
-      double frames = buf.st_size ? (buf.st_size - 1) / sizeof(tIndexTs) + 1 : 0;
-      double Seconds = 0;
-      modf((frames + 0.5) / pRecording->FramesPerSecond(), &Seconds);
-      return Seconds;
-    }
-  return -1;
+   m_Active = false;
 }
 #endif
-
diff --git a/recstatus.h b/status_thread.h
similarity index 53%
copy from recstatus.h
copy to status_thread.h
index 1195bca..e2bdb6e 100644
--- a/recstatus.h
+++ b/status_thread.h
@@ -21,31 +21,45 @@ The author can be reached at cwieninger at gmx.de
 The project's page is at http://winni.vdr-developer.org/epgsearch
 */
 
+#ifndef VDR_STATUS_THREAD_H
+#define VDR_STATUS_THREAD_H
+
+#include <vdr/thread.h>
 #include <vdr/status.h>
+#include "epgsearchext.h"
 #include "recdone.h"
 #include "epgsearchtools.h"
+#include "log.h"
 
-// --- cRecDoneTimerObj --------------------------------------------------------
-class cRecDoneTimerObj : public cTimerObj {
-public:
-    int deviceNr;
-    cRecDone* recDone;
-    time_t lastBreak;
-public:
-    cRecDoneTimerObj(cTimer* Timer, int DeviceNr) : cTimerObj(Timer), deviceNr(DeviceNr), recDone(NULL), lastBreak(0) {}
-    ~cRecDoneTimerObj() { timer = NULL; recDone = NULL; } // do not delete anything!
-};
+extern int gl_StatusProgged;
 
-class cRecStatusMonitor : public cStatus
+typedef enum
 {
-    cList<cRecDoneTimerObj> TimersRecording;
+    StatusThreadReady,
+    StatusThreadWorking,
+    StatusThreadError,
+    StatusThreadDone
+} StatusThreadStatus;
+
+class cStatusThread: public cThread {
+private:
+        static cStatusThread *m_Instance;
+	const cDevice * m_device;
+	const char * m_name;
+	const char * m_filename;
+	bool m_on;
+	static StatusThreadStatus m_Status;
 protected:
-    virtual void Recording(const cDevice *Device, const char *Name, const char*, bool On);
- public:
-    cRecStatusMonitor();
-    int TimerRecDevice(cTimer*);
-    bool IsPesRecording(cRecording *pRecording);
-    int RecLengthInSecs(cRecording *pRecording);
+        virtual void Action(void);
+        void Stop(void);
+public:
+        bool m_Active;
+	StatusThreadStatus GetStatus() { return cStatusThread::m_Status; }
+	void SetStatus(StatusThreadStatus Status) { LogFile.eSysLog("%d", int(Status)); cStatusThread::m_Status = Status; }
+        cStatusThread();
+        virtual ~cStatusThread();
+        static void Init(const cDevice *Device, const char *Name, const char *Filename, bool On);
+        void Exit(void);
 };
 
-extern cRecStatusMonitor* gl_recStatusMonitor;
+#endif
diff --git a/switchtimer.c b/switchtimer.c
index 20c017b..d145c7a 100644
--- a/switchtimer.c
+++ b/switchtimer.c
@@ -114,8 +114,13 @@ const cEvent* cSwitchTimer::Event()
   const cEvent* event = NULL;
   if (startTime > now)
   {
-      cSchedulesLock schedulesLock;
-      const cSchedules* schedules = cSchedules::Schedules(schedulesLock);
+#if VDRVERSNUM > 20300
+      LOCK_SCHEDULES_READ;
+      const cSchedules *schedules = Schedules;
+#else
+      cSchedulesLock SchedulesLock;
+      const cSchedules* schedules = cSchedules::Schedules(SchedulesLock);
+#endif
       if (!schedules) return NULL;
       const cSchedule *Schedule = schedules->GetSchedule(channelID);
       if (Schedule)
@@ -136,7 +141,13 @@ cString cSwitchTimer::ToText(bool& ignore)
 	ignore = true;
 	return NULL;
     }
-    cChannel *channel = Channels.GetByChannelID(channelID, true, true);
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
+    const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true);
     if (!channel) return NULL;
     cString buffer = cString::sprintf("%s:%u:%ld:%d:%d:%d",
 				      CHANNELSTRING(channel), eventID,
diff --git a/switchtimer_thread.c b/switchtimer_thread.c
index b027b4b..3b2ce99 100644
--- a/switchtimer_thread.c
+++ b/switchtimer_thread.c
@@ -81,14 +81,20 @@ void cSwitchTimerThread::Action(void)
       if (now >= nextUpdate)
       {
          LogFile.Log(3,"locking switch timers");
-         SwitchTimers.Lock();
+         SwitchTimers.cMutex::Lock();
          LogFile.Log(3,"switch timer check started");
          cSwitchTimer* switchTimer = SwitchTimers.First();
          while (switchTimer && m_Active && Running())
          {
             if (switchTimer->startTime - now < switchTimer->switchMinsBefore*60 + MSG_DELAY + 1)
             {
-               cChannel *channel = Channels.GetByChannelID(switchTimer->channelID, true, true);
+#if VDRVERSNUM > 20300
+               LOCK_CHANNELS_READ;
+               const cChannels *vdrchannels = Channels;
+#else
+               cChannels *vdrchannels = &Channels;
+#endif
+               const cChannel *channel = vdrchannels->GetByChannelID(switchTimer->channelID, true, true);
                bool doSwitch = (switchTimer->mode == 0);
                bool doAsk = (switchTimer->mode == 2);
 	       bool doUnmute = switchTimer->unmute;
diff --git a/templatefile.c b/templatefile.c
index 44ade92..fdce3bf 100644
--- a/templatefile.c
+++ b/templatefile.c
@@ -210,6 +210,12 @@ bool cTemplFile::Parse(const char *Name, const char *Value)
 void cTemplFile::PrepareDefaultTemplates()
 {
     char channelnr[20] = "";
+#if VDRVERSNUM > 20300
+    LOCK_CHANNELS_READ;
+    const cChannels *vdrchannels = Channels;
+#else
+    cChannels *vdrchannels = &Channels;
+#endif
     sprintf(channelnr, "%%chnr%%:%d|", CHNUMWIDTH);
 
     bool text2skin = !(strcmp(Setup.OSDSkin, "soppalusikka") == 0 ||
diff --git a/timer_thread.c b/timer_thread.c
index 306d10a..e4c8be1 100644
--- a/timer_thread.c
+++ b/timer_thread.c
@@ -89,11 +89,17 @@ void cTimerThread::Action(void)
             m_Active=false;
             break;
         }
+#if VDRVERSNUM > 20300
+        {
+	LOCK_TIMERS_READ;
+        }
+#else
 	if (Timers.BeingEdited())
 	{
 	    sleepSec(1);
 	    continue;
 	}
+#endif
 	bool bSuccess = SendViaSVDRP(m_cmd);
 	if (!bSuccess)
 	{
diff --git a/timerdone.c b/timerdone.c
index b00679c..06d2b23 100644
--- a/timerdone.c
+++ b/timerdone.c
@@ -126,7 +126,13 @@ bool cTimerDone::Parse(const char *s)
 
 cString cTimerDone::ToText(void) const
 {
-   cChannel *channel = Channels.GetByChannelID(channelID, true, true);
+#if VDRVERSNUM > 20300
+   LOCK_CHANNELS_READ;
+   const cChannels *vdrchannels = Channels;
+#else
+   cChannels *vdrchannels = &Channels;
+#endif
+   const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true);
    string info = string(DAYDATETIME(start)) + " - " + string(channel?channel->Name():"");
 
    cString buffer = cString::sprintf("%s:%ld:%ld:%d:%s:%s:%s",
@@ -147,10 +153,15 @@ bool cTimerDone::Save(FILE *f)
 
 const cEvent* cTimerDone::GetEvent() const
 {
-   cSchedulesLock schedulesLock;
-   const cSchedules* Schedules = cSchedules::Schedules(schedulesLock);
-   if (!Schedules) return NULL;
-   const cSchedule *Schedule = Schedules->GetSchedule(channelID);
+#if VDRVERSNUM > 20300
+    LOCK_SCHEDULES_READ;
+    const cSchedules *schedules = Schedules;
+#else
+    cSchedulesLock SchedulesLock;
+    const cSchedules* schedules = cSchedules::Schedules(SchedulesLock);
+#endif
+   if (!schedules) return NULL;
+   const cSchedule *Schedule = schedules->GetSchedule(channelID);
    if (!Schedule) return NULL;
    const cEvent* Event = Schedule->GetEventAround(start + (stop - start)/2);
    return Event;
diff --git a/uservars.h b/uservars.h
index 9366af0..1681f25 100644
--- a/uservars.h
+++ b/uservars.h
@@ -176,7 +176,13 @@ public:
     string Evaluate(const cEvent* e, bool escapeStrings = false)
 	{
 	    if (!e) return "";
-	    cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true);
+#if VDRVERSNUM > 20300
+	    LOCK_CHANNELS_READ;
+	    const cChannels *vdrchannels = Channels;
+#else
+	    cChannels *vdrchannels = &Channels;
+#endif
+	    const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true);
 	    if (!channel) return "";
 
 	    string res(channel->GetChannelID().ToString());
@@ -415,7 +421,13 @@ public:
     string Evaluate(const cEvent* e, bool escapeStrings = false)
 	{
 	    if (!e) return "";
-	    cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true);
+#if VDRVERSNUM > 20300
+	    LOCK_CHANNELS_READ;
+	    const cChannels *vdrchannels = Channels;
+#else
+	    cChannels *vdrchannels = &Channels;
+#endif
+	    const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true);
 	    string res = channel?channel->ShortName(true):"";
 	    if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res;
 	}
@@ -427,7 +439,13 @@ public:
     string Evaluate(const cEvent* e, bool escapeStrings = false)
 	{
 	    if (!e) return "";
-	    cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true);
+#if VDRVERSNUM > 20300
+	    LOCK_CHANNELS_READ;
+	    const cChannels *vdrchannels = Channels;
+#else
+	    cChannels *vdrchannels = &Channels;
+#endif
+	    const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true);
 	    string res = channel?channel->Name():"";
 	    if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res;
 	}
@@ -439,7 +457,13 @@ class cChannelDataVar : public cInternalVar {
     string Evaluate(const cEvent* e, bool escapeStrings = false)
 	{
 	    if (!e) return "";
-	    cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true);
+#if VDRVERSNUM > 20300
+	    LOCK_CHANNELS_READ;
+	    const cChannels *vdrchannels = Channels;
+#else
+	    cChannels *vdrchannels = &Channels;
+#endif
+	    const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true);
 	    return channel?CHANNELSTRING(channel):"";
 	}
 };
@@ -451,9 +475,15 @@ public:
 	{
 	    if (!e) return "";
 	    ostringstream os;
-	    cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true);
+#if VDRVERSNUM > 20300
+	    LOCK_CHANNELS_READ;
+	    const cChannels *vdrchannels = Channels;
+#else
+	    cChannels *vdrchannels = &Channels;
+#endif
+	    const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true);
 	    while(channel && !channel->GroupSep())
-	      channel = Channels.Prev(channel);
+	      channel = vdrchannels->Prev(channel);
 	    if (!channel || !channel->Name()) return "";
 	    string grpName = channel->Name();
 	    if (escapeStrings) return "'" + EscapeString(grpName) + "'"; else return grpName;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-epgsearch.git



More information about the pkg-vdr-dvb-changes mailing list