]> git.vomp.tv Git - vompserver.git/commitdiff
Compatibilty updates for VDR 2.3.1 & 2.3.2
authorChris Tallon <chris@vomp.tv>
Thu, 16 Feb 2017 17:10:01 +0000 (17:10 +0000)
committerChris Tallon <chris@vomp.tv>
Thu, 16 Feb 2017 17:10:01 +0000 (17:10 +0000)
mvpreceiver.c [changed mode: 0644->0755]
mvpreceiver.h [changed mode: 0644->0755]
picturereader.c [changed mode: 0644->0755]
recplayer.c [changed mode: 0644->0755]
recplayer.h [changed mode: 0644->0755]
ringbuffer.c [changed mode: 0644->0755]
ringbuffer.h [changed mode: 0644->0755]
vompclient.c [changed mode: 0644->0755]
vompclient.h [changed mode: 0644->0755]
vompclientrrproc.c

old mode 100644 (file)
new mode 100755 (executable)
index 6cdc5be..3ffb4b7
@@ -113,6 +113,7 @@ void MVPReceiver::detachMVPReceiver()
   Detach();
 }
 
+
 void MVPReceiver::Receive(UCHAR* data, int length)
 {
   pthread_mutex_lock(&processedRingLock);
@@ -120,6 +121,14 @@ void MVPReceiver::Receive(UCHAR* data, int length)
   if (processed.getContent() > streamChunkSize) threadSignal();
   pthread_mutex_unlock(&processedRingLock);
 }
+void MVPReceiver::Receive(const UCHAR* data, int length)
+{
+  pthread_mutex_lock(&processedRingLock);
+  processed.put(data, length);
+  if (processed.getContent() > streamChunkSize) threadSignal();
+  pthread_mutex_unlock(&processedRingLock);
+}
+
 
 void MVPReceiver::threadMethod()
 {
old mode 100644 (file)
new mode 100755 (executable)
index eb4649e..747e925
@@ -56,7 +56,8 @@ class MVPReceiver : public cReceiver, public Thread
 
     // cReciever stuff
     void Activate(bool On);
-    void Receive(UCHAR *Data, int Length);
+    void Receive(UCHAR *Data, int Length); // VDR 2.2.0
+    void Receive(const UCHAR *Data, int Length); // > VDR 2.2.0
     void sendStreamEnd();
 
     static int numMVPReceivers;
old mode 100644 (file)
new mode 100755 (executable)
index 53e3d11..59353b7
@@ -191,9 +191,14 @@ std::string PictureReader::getPictName(TVMediaRequest & req)
    } break;
    case 3: { // I do not know
    // First get the recording
-      cRecordings Recordings;
-      Recordings.Load();
-      cRecording *recording = Recordings.GetByName((char*) req.primary_name.c_str());
+#if VDRVERSNUM >= 20301
+      LOCK_RECORDINGS_READ;
+      const cRecordings* tRecordings = Recordings;
+#else
+      cThreadLock RecordingsLock(&Recordings);
+      cRecordings* tRecordings = &Recordings;
+#endif
+      const cRecording *recording = tRecordings->GetByName((char*) req.primary_name.c_str());
       ScraperGetPosterThumb getter;
       getter.recording = recording;
       getter.event = NULL;
@@ -206,14 +211,31 @@ std::string PictureReader::getPictName(TVMediaRequest & req)
    }; break;
    case 4: { // I do not know
    // First get the schedules
+
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  cChannels* tChannels = &Channels;
+#endif
+
+
+#if VDRVERSNUM < 10300
+      cMutexLock MutexLock;
+      const cSchedules *tSchedules = cSIProcessor::Schedules(MutexLock);
+#elif VDRVERSNUM < 20301
       cSchedulesLock MutexLock;
-      const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
+      const cSchedules *tSchedules = cSchedules::Schedules(MutexLock);
+#else
+      LOCK_SCHEDULES_READ;
+      const cSchedules *tSchedules = Schedules;
+#endif
+
       const cSchedule *Schedule = NULL;
-      if (Schedules)
+      if (tSchedules)
       {
-        cChannel * channel = Channels.GetByChannelID(
-                       tChannelID::FromString(req.primary_name.c_str()));
-        Schedule = Schedules->GetSchedule(channel);
+        const cChannel* channel = tChannels->GetByChannelID(tChannelID::FromString(req.primary_name.c_str()));
+        Schedule = tSchedules->GetSchedule(channel);
       }
       const cEvent *event = NULL;
       if (Schedule) event=Schedule->GetEvent(req.primary_id);
old mode 100644 (file)
new mode 100755 (executable)
index e2e3da7..ce01e26
@@ -26,7 +26,7 @@
 
 #include <fcntl.h>
 
-RecPlayer::RecPlayer(cRecording* rec)
+RecPlayer::RecPlayer(const cRecording* rec)
 {
   log = Log::getInstance();
   file = NULL;
@@ -206,7 +206,7 @@ ULLONG RecPlayer::getLastPosition()
   return lastPosition;
 }
 
-cRecording* RecPlayer::getCurrentRecording()
+const cRecording* RecPlayer::getCurrentRecording()
 {
   return recording;
 }
old mode 100644 (file)
new mode 100755 (executable)
index 95f310a..288e60d
@@ -37,14 +37,14 @@ class Segment
 class RecPlayer
 {
   public:
-    RecPlayer(cRecording* rec);
+    RecPlayer(const cRecording* rec);
     ~RecPlayer();
     ULLONG getLengthBytes();
     ULONG getLengthFrames();
     unsigned long getBlock(unsigned char* buffer, ULLONG position, unsigned long amount);
     int openFile(int index);
     ULLONG getLastPosition();
-    cRecording* getCurrentRecording();
+    const cRecording* getCurrentRecording();
     void scan();
     ULLONG positionFromFrameNumber(ULONG frameNumber);
     ULONG frameNumberFromPosition(ULLONG position);
@@ -52,7 +52,7 @@ class RecPlayer
 
   private:
     Log* log;
-    cRecording* recording;
+    const cRecording* recording;
     cIndexFile* indexFile;
     FILE* file;
     int fileOpen;
old mode 100644 (file)
new mode 100755 (executable)
index 20db41c..9de4be9
@@ -49,7 +49,7 @@ int Ringbuffer::init(size_t size)
   return 1;
 }
 
-int Ringbuffer::put(UCHAR* from, size_t amount)
+int Ringbuffer::put(const UCHAR* from, size_t amount)
 {
   if (amount > capacity) return 0;
 
old mode 100644 (file)
new mode 100755 (executable)
index c5a6e14..139eb72
@@ -33,7 +33,7 @@ class Ringbuffer
     Ringbuffer();
     ~Ringbuffer();
     int init(size_t size);
-    int put(UCHAR* from, size_t amount);
+    int put(const UCHAR* from, size_t amount);
     int get(UCHAR* to, size_t amount);
     int getContent();
 
old mode 100644 (file)
new mode 100755 (executable)
index f83c76e..37de93c
@@ -49,7 +49,6 @@ VompClient::VompClient(Config* cfgBase, char* tconfigDir, char* tlogoDir,
 #ifndef VOMPSTANDALONE
   lp = NULL;
   recplayer = NULL;
-  recordingManager = NULL;
   pict = new PictureReader(this);
   if (!scraper) scrapQuery();
   logoDir = tlogoDir;
@@ -89,9 +88,7 @@ VompClient::~VompClient()
     writeResumeData();
 
     delete recplayer;
-    delete recordingManager;
     recplayer = NULL;
-    recordingManager = NULL;
   }
 #endif
   //if (loggedIn) cleanConfig();
old mode 100644 (file)
new mode 100755 (executable)
index b715ce6..7a4f20c
@@ -48,7 +48,6 @@
 class RecPlayer;
 class MVPReceiver;
 class cChannel;
-class cRecordings;
 class cPlugin;
 #endif
 
@@ -108,7 +107,6 @@ class VompClient
     void writeResumeData();
 
     MVPReceiver* lp;
-    cRecordings* recordingManager;
     RecPlayer* recplayer;
     static cPlugin * scraper;
     static time_t lastScrapQuery;
index ba253c5130da62866d8c46caa19caafb48954a51..a9e3d2e69463986a3af0735c05d0443c854aa1d9 100755 (executable)
@@ -59,6 +59,39 @@ ULONG VompClientRRProc::VOMP_PROTOCOL_VERSION_MAX = 0x00000302;
 // Increase the minimal protocol version everytime you break compatibility for a certain 
 // command. 
 
+
+/* Locking information from VDR:
+
+  + Instead of directly accessing the global variables Timers, Channels or Recordings,
+    they need to set up a cStateKey variable and call the proper getter function,
+    as in
+      cStateKey StateKey;
+      if (const cTimers *Timers = cTimers::GetTimersRead(StateKey)) {
+         // access the timers
+         StateKey.Remove();
+         }
+    and
+      cStateKey StateKey;
+      if (cTimers *Timers = cTimers::GetTimersWrite(StateKey)) {
+         // access the timers
+         StateKey.Remove();
+         }
+    See timers.h, thread.h and tools.h for details on this new locking mechanism.
+  + There are convenience macros for easily accessing these lists without having
+    to explicitly set up a cStateKey and calling its Remove() function. These macros
+    have the form LOCK_*_READ/WRITE (with '*' being TIMERS, CHANNELS, SCHEDULES or
+    RECORDINGS). Simply put such a macro before the point where you need to access
+    the respective list, and there will be a pointer named Timers, Channels, Schedules
+    or Recordings, respectively, which is valid until the end of the current block.
+  + If a plugin needs to access several of the global lists in parallel, locking must
+    always be done in the sequence Timers, Channels, Recordings, Schedules. This is
+    necessary to make sure that different threads that need to lock several lists at
+    the same time don't end up in a deadlock.
+
+    */
+
+// TODO: Use VDRs recording->ChangeName(option)) for move recording ?
+
 ULONG VompClientRRProc::getProtocolVersionMin()
 {
   return VOMP_PROTOCOL_VERSION_MIN;
@@ -716,11 +749,16 @@ int VompClientRRProc::processGetRecordingsList()
   resp->addULONG(Total);
   resp->addULONG(FreeMB);
   resp->addULONG(Percent);
-  
-  cRecordings Recordings;
-  Recordings.Load();
 
-  for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording))
+#if VDRVERSNUM >= 20301
+  LOCK_RECORDINGS_READ;
+  const cRecordings* tRecordings = Recordings;
+#else
+  cThreadLock RecordingsLock(&Recordings);
+  const cRecordings* tRecordings = &Recordings;
+#endif
+
+  for (const cRecording *recording = tRecordings->First(); recording; recording = tRecordings->Next(recording))
   {
 #if VDRVERSNUM < 10721
     resp->addULONG(recording->start);
@@ -744,10 +782,15 @@ int VompClientRRProc::processDeleteRecording()
 {
   // data is a pointer to the fileName string
 
-  cRecordings Recordings;
-  Recordings.Load(); // probably have to do this
+#if VDRVERSNUM >= 20301
+  LOCK_RECORDINGS_WRITE;
+  cRecordings* tRecordings = Recordings;
+#else
+  cThreadLock RecordingsLock(&Recordings);
+  cRecordings* tRecordings = &Recordings;
+#endif
 
-  cRecording* recording = Recordings.GetByName((char*)req->data);
+  cRecording* recording = tRecordings->GetByName((char*)req->data);
 
   log->log("RRProc", Log::DEBUG, "recording pointer %p", recording);
 
@@ -755,13 +798,17 @@ int VompClientRRProc::processDeleteRecording()
   {
     log->log("RRProc", Log::DEBUG, "deleting recording: %s", recording->Name());
 
+// TODO: Switch to using: cRecording::IsInUse(void) const
     cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
     if (!rc)
     {
       if (recording->Delete())
       {
+#if VDRVERSNUM >= 20301
+         tRecordings->DelByName(recording->FileName());
+         tRecordings->SetModified();
+#elif VDRVERSNUM > 10300
         // Copy svdrp's way of doing this, see if it works
-#if VDRVERSNUM > 10300
         ::Recordings.DelByName(recording->FileName());
 #endif
         resp->addULONG(1);
@@ -803,15 +850,22 @@ int VompClientRRProc::processMoveRecording()
   }
   if (!newPath) return 0;
 
-  cRecordings Recordings;
-  Recordings.Load(); // probably have to do this
 
-  cRecording* recording = Recordings.GetByName((char*)fileName);
+#if VDRVERSNUM >= 20301
+  LOCK_RECORDINGS_WRITE;
+  cRecordings* tRecordings = Recordings;
+#else
+  cThreadLock RecordingsLock(&Recordings);
+  cRecordings* tRecordings = &Recordings;
+#endif
+
+  cRecording* recording = tRecordings->GetByName((char*)fileName);
 
   log->log("RRProc", Log::DEBUG, "recording pointer %p", recording);
 
   if (recording)
   {
+    // TODO: Switch to using: int cRecording::IsInUse(void) const
     cRecordControl *rc = cRecordControls::GetRecordControl(recording->FileName());
     if (!rc)
     {
@@ -906,6 +960,7 @@ int VompClientRRProc::processMoveRecording()
         return 1;
       }
 
+
       // Ok, the directory container has been made, or it pre-existed.
 
       char* newDir = new char[strlen(newContainer) + 1 + strlen(dateDirName) + 1];
@@ -922,12 +977,10 @@ int VompClientRRProc::processMoveRecording()
         log->log("RRProc", Log::DEBUG, "len: %i, cp: %i, strlen: %i, oldtitledir: %s", k+1, k, strlen(oldTitleDir), oldTitleDir);
         rmdir(oldTitleDir); // can't do anything about a fail result at this point.
         delete[] oldTitleDir;
-      }
 
-      if (renameret == 0)
-      {
-#if VDRVERSNUM > 10311
-        // Tell VDR
+#if VDRVERSNUM >= 20301
+        tRecordings->SetModified();
+#elif VDRVERSNUM > 10311
         ::Recordings.Update();
 #endif
         // Success. Send a different packet from just a ulong
@@ -972,7 +1025,14 @@ int VompClientRRProc::processGetChannelsList()
   int allChans = 1;
   if (chanConfig) allChans = strcasecmp(chanConfig, "FTA only");
 
-  for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  const cChannels* tChannels = &Channels;
+#endif
+
+  for (const cChannel *channel = tChannels->First(); channel; channel = tChannels->Next(channel))
   {
 #if VDRVERSNUM < 10300
     if (!channel->GroupSep() && (!channel->Ca() || allChans))
@@ -1013,7 +1073,14 @@ int VompClientRRProc::processGetChannelPids()
 {
   ULONG channelNumber = ntohl(*(ULONG*)req->data);
 
-  const cChannel* channel = Channels.GetByNumber(channelNumber);
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  cChannels* tChannels = &Channels;
+#endif
+
+  const cChannel* channel = tChannels->GetByNumber(channelNumber);
   if (!channel)
   {
     resp->addULONG(0);
@@ -1188,7 +1255,14 @@ int VompClientRRProc::processStartStreamingChannel()
   log->log("RRProc", Log::DEBUG, "req->dataLength = %i", req->dataLength);
   ULONG channelNumber = ntohl(*(ULONG*)req->data);
 
-  const cChannel* channel = Channels.GetByNumber(channelNumber);
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  cChannels* tChannels = &Channels;
+#endif
+
+  const cChannel* channel = tChannels->GetByNumber(channelNumber);
   if (!channel)
   {
     resp->addULONG(0);
@@ -1259,9 +1333,7 @@ int VompClientRRProc::processStopStreaming()
     x.writeResumeData();
 
     delete x.recplayer;
-    delete x.recordingManager;
     x.recplayer = NULL;
-    x.recordingManager = NULL;
   }
 
   resp->addULONG(1);
@@ -1316,10 +1388,15 @@ int VompClientRRProc::processStartStreamingRecording()
 {
   // data is a pointer to the fileName string
 
-  x.recordingManager = new cRecordings;
-  x.recordingManager->Load();
+#if VDRVERSNUM >= 20301
+  LOCK_RECORDINGS_READ;
+  const cRecordings* tRecordings = Recordings;
+#else
+  cThreadLock RecordingsLock(&Recordings);
+  cRecordings* tRecordings = &Recordings;
+#endif
 
-  cRecording* recording = x.recordingManager->GetByName((char*)req->data);
+  const cRecording* recording = tRecordings->GetByName((char*)req->data);
 
   log->log("RRProc", Log::DEBUG, "recording pointer %p", recording);
 
@@ -1341,11 +1418,7 @@ int VompClientRRProc::processStartStreamingRecording()
     
     log->log("RRProc", Log::DEBUG, "written totalLength");
   }
-  else
-  {
-    delete x.recordingManager;
-    x.recordingManager = NULL;
-  }
+
   return 1;
 }
 
@@ -1450,7 +1523,14 @@ int VompClientRRProc::processGetChannelSchedule()
 
   log->log("RRProc", Log::DEBUG, "get schedule called for channel %lu", channelNumber);
 
-  const cChannel* channel = Channels.GetByNumber(channelNumber);
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  cChannels* tChannels = &Channels;
+#endif
+
+  const cChannel* channel = tChannels->GetByNumber(channelNumber);
   if (!channel)
   {
     resp->addULONG(0);
@@ -1465,12 +1545,16 @@ int VompClientRRProc::processGetChannelSchedule()
 
 #if VDRVERSNUM < 10300
   cMutexLock MutexLock;
-  const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
-#else
+  const cSchedules *tSchedules = cSIProcessor::Schedules(MutexLock);
+#elif VDRVERSNUM < 20301
   cSchedulesLock MutexLock;
-  const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
+  const cSchedules *tSchedules = cSchedules::Schedules(MutexLock);
+#else
+  LOCK_SCHEDULES_READ;
+  const cSchedules *tSchedules = Schedules;
 #endif
-  if (!Schedules)
+
+  if (!tSchedules)
   {
     resp->addULONG(0);
     resp->finalise();
@@ -1482,7 +1566,7 @@ int VompClientRRProc::processGetChannelSchedule()
 
   log->log("RRProc", Log::DEBUG, "Got schedule!s! object");
 
-  const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
+  const cSchedule *Schedule = tSchedules->GetSchedule(channel->GetChannelID());
   if (!Schedule)
   {
     resp->addULONG(0);
@@ -1574,14 +1658,21 @@ int VompClientRRProc::processGetChannelSchedule()
 
 int VompClientRRProc::processGetTimers()
 {
-  cTimer *timer;
-  int numTimers = Timers.Count();
+#if VDRVERSNUM >= 20301
+  LOCK_TIMERS_READ;
+  const cTimers* tTimers = Timers;
+#else
+  const cTimers* tTimers = &Timers;
+#endif
+
+  const cTimer *timer;
+  int numTimers = tTimers->Count();
 
   resp->addULONG(numTimers);
 
   for (int i = 0; i < numTimers; i++)
   {
-    timer = Timers.Get(i);
+    timer = tTimers->Get(i);
 
 #if VDRVERSNUM < 10300
     resp->addULONG(timer->Active());
@@ -1646,36 +1737,43 @@ int VompClientRRProc::processSetTimer()
   log->log("RRProc", Log::DEBUG, "%s", timerString);
 
   cTimer *timer = new cTimer;
-  if (timer->Parse((char*)timerString))
+  if (!timer->Parse((char*)timerString))
   {
-    cTimer *t = Timers.GetTimer(timer);
-    if (!t)
-    {
-      Timers.Add(timer);
-#if VDRVERSNUM < 10300
-      Timers.Save();
+    resp->addULONG(2);
+    resp->finalise();
+    x.tcp.sendPacket(resp->getPtr(), resp->getLen());
+    delete timer;
+    return 1;
+  }
+
+#if VDRVERSNUM >= 20301
+  LOCK_TIMERS_WRITE;
+  cTimers* tTimers = Timers;
 #else
-      Timers.SetModified();
+  cTimers* tTimers = &Timers;
 #endif
-      resp->addULONG(0);
-      resp->finalise();
-      x.tcp.sendPacket(resp->getPtr(), resp->getLen());
-      return 1; // FIXME - cTimer* timer is leaked here!
-    }
-    else
-    {
-      resp->addULONG(1);
-      resp->finalise();
-      x.tcp.sendPacket(resp->getPtr(), resp->getLen());
-    }
-  }
-  else
+
+  cTimer *t = tTimers->GetTimer(timer);
+  if (t)
   {
-    resp->addULONG(2);
+    resp->addULONG(1);
     resp->finalise();
     x.tcp.sendPacket(resp->getPtr(), resp->getLen());
+    delete timer;
+    return 1;
   }
-  delete timer;
+
+  timer->ClrFlags(tfRecording);
+  tTimers->Add(timer);
+#if VDRVERSNUM < 10300
+  tTimers->Save();
+#elif VDRVERSNUM < 20301
+  tTimers->SetModified();
+#endif
+
+  resp->addULONG(0);
+  resp->finalise();
+  x.tcp.sendPacket(resp->getPtr(), resp->getLen());
   return 1;
 }
 
@@ -1691,9 +1789,16 @@ int VompClientRRProc::processDeleteTimer()
   INT delDay = ntohl(*(ULONG*)&req->data[position]); position += 4;  
   INT delStart = ntohl(*(ULONG*)&req->data[position]); position += 4;  
   INT delStop = ntohl(*(ULONG*)&req->data[position]); position += 4;
-    
+
+#if VDRVERSNUM >= 20301
+  LOCK_TIMERS_WRITE;
+  cTimers* tTimers = Timers;
+#else
+  cTimers* tTimers = &Timers;
+#endif
+
   cTimer* ti = NULL;
-  for (ti = Timers.First(); ti; ti = Timers.Next(ti))
+  for (ti = tTimers->First(); ti; ti = tTimers->Next(ti))
   {
     if  ( (ti->Channel()->Number() == delChannel)
      &&   ((ti->WeekDays() && (ti->WeekDays() == delWeekdays)) || (!ti->WeekDays() && (ti->Day() == delDay)))
@@ -1709,45 +1814,49 @@ int VompClientRRProc::processDeleteTimer()
     x.tcp.sendPacket(resp->getPtr(), resp->getLen());
     return 1;
   }
-          
-  if (!Timers.BeingEdited())
-  {
-    if (!ti->Recording())
-    {
-      Timers.Del(ti);
-      Timers.SetModified();
-      resp->addULONG(10);
-      resp->finalise();
-      x.tcp.sendPacket(resp->getPtr(), resp->getLen());
-      return 1;
-    }
-    else
-    {
-      log->log("RRProc", Log::ERR, "Unable to delete timer - timer is running");
-      resp->addULONG(3);
-      resp->finalise();
-      x.tcp.sendPacket(resp->getPtr(), resp->getLen());
-      return 1;
-    }  
-  }
-  else
+
+#if VDRVERSNUM < 20301
+// I suppose with the new locking this just can't happen
+  if (tTimers->BeingEdited())
   {
     log->log("RRProc", Log::ERR, "Unable to delete timer - timers being edited at VDR");
     resp->addULONG(1);
     resp->finalise();
     x.tcp.sendPacket(resp->getPtr(), resp->getLen());
     return 1;
-  }  
+  }
+#endif
+
+  if (ti->Recording())
+  {
+    log->log("RRProc", Log::ERR, "Unable to delete timer - timer is running");
+    resp->addULONG(3);
+    resp->finalise();
+    x.tcp.sendPacket(resp->getPtr(), resp->getLen());
+    return 1;
+  }
+
+  tTimers->Del(ti);
+  tTimers->SetModified();
+
+  resp->addULONG(10);
+  resp->finalise();
+  x.tcp.sendPacket(resp->getPtr(), resp->getLen());
+  return 1;
 }
 
 int VompClientRRProc::processGetRecInfo()
 {
   // data is a pointer to the fileName string
-  
-  cRecordings Recordings;
-  Recordings.Load(); // probably have to do this
+#if VDRVERSNUM >= 20301
+  LOCK_RECORDINGS_READ;
+  const cRecordings* tRecordings = Recordings;
+#else
+  cThreadLock RecordingsLock(&Recordings);
+  cRecordings* tRecordings = &Recordings;
+#endif
 
-  cRecording *recording = Recordings.GetByName((char*)req->data);
+  const cRecording *recording = tRecordings->GetByName((char*)req->data);
 
   time_t timerStart = 0;
   time_t timerStop = 0;
@@ -1970,17 +2079,20 @@ int VompClientRRProc::processReScanRecording()
 int VompClientRRProc::processGetMarks()
 {
   // data is a pointer to the fileName string
+#if VDRVERSNUM >= 20301
+  LOCK_RECORDINGS_READ;
+  const cRecordings* tRecordings = Recordings;
+#else
+  cThreadLock RecordingsLock(&Recordings);
+  cRecordings* tRecordings = &Recordings;
+#endif
 
-  cMarks Marks;
-  cRecordings Recordings;
-  Recordings.Load(); // probably have to do this
-
-  cRecording *recording = Recordings.GetByName((char*)req->data);
-
+  const cRecording *recording = tRecordings->GetByName((char*)req->data);
   log->log("RRProc", Log::DEBUG, "recording pointer %p", recording);
 
   if (recording)
   {
+    cMarks Marks;
 #if VDRVERSNUM < 10703
     Marks.Load(recording->FileName());
 #else
@@ -2028,22 +2140,30 @@ int VompClientRRProc::processVDRShutdown()
 
 int VompClientRRProc::processGetRecScraperEventType()
 {
-  Recordings.Load(); // probably have to do this
+#if VDRVERSNUM >= 20301
+  LOCK_RECORDINGS_READ;
+  const cRecordings* tRecordings = Recordings;
+#else
+  cThreadLock RecordingsLock(&Recordings);
+  cRecordings* tRecordings = &Recordings;
+#endif
 
-  cRecording *recording = Recordings.GetByName((char*)req->data);
+  const cRecording *recording = tRecordings->GetByName((char*)req->data);
   ScraperGetEventType call;
   call.type = tNone;
 
   if (recording && x.scrapQuery()) 
   {
      call.recording = recording;
-     x.scraper->Service("GetEventType",&call);
+     x.scraper->Service("GetEventType", &call);
   }
   resp->addUCHAR(call.type);
   if (call.type == tMovie)
   {
      resp->addLONG(call.movieId);
-  } else if (call.type == tSeries){
+  }
+  else if (call.type == tSeries)
+  {
      resp->addLONG(call.seriesId);
      resp->addLONG(call.episodeId);
   }
@@ -2060,19 +2180,30 @@ int VompClientRRProc::processGetEventScraperEventType()
   ULONG channelid = ntohl(*(ULONG*)req->data);
   ULONG eventid = ntohl(*(ULONG*)(req->data+4));
   const cEvent *event = NULL; 
-  
-  const cChannel* channel = Channels.GetByNumber(channelid);
+
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  cChannels* tChannels = &Channels;
+#endif
+
+  const cChannel* channel = tChannels->GetByNumber(channelid);
 
 #if VDRVERSNUM < 10300
   cMutexLock MutexLock;
-  const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
-#else
+  const cSchedules *tSchedules = cSIProcessor::Schedules(MutexLock);
+#elif VDRVERSNUM < 20301
   cSchedulesLock MutexLock;
-  const cSchedules *Schedules = cSchedules::Schedules(MutexLock);
+  const cSchedules *tSchedules = cSchedules::Schedules(MutexLock);
+#else
+  LOCK_SCHEDULES_READ;
+  const cSchedules *tSchedules = Schedules;
 #endif
-  if (Schedules && channel)
+
+  if (tSchedules && channel)
   {
-     const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
+     const cSchedule *Schedule = tSchedules->GetSchedule(channel->GetChannelID());
      if (Schedule) {
         event = Schedule->GetEvent(eventid);
     }
@@ -2276,7 +2407,15 @@ int VompClientRRProc::processLoadTvMediaEventThumb()
    UINT channelid = ntohl(*(ULONG*)req->data);
    tvreq.primary_id = ntohl(*(ULONG*)(req->data+4));
    tvreq.secondary_id = 0;
-   const cChannel* channel = Channels.GetByNumber(channelid);
+
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  cChannels* tChannels = &Channels;
+#endif
+
+   const cChannel* channel = tChannels->GetByNumber(channelid);
 
    if (channel) tvreq.primary_name = std::string((const char*)channel->GetChannelID().ToString());
    tvreq.type_pict = 1;
@@ -2301,7 +2440,15 @@ int VompClientRRProc::processLoadChannelLogo()
    UINT channelid = ntohl(*(ULONG*)req->data);
    tvreq.primary_id = channelid;
    tvreq.secondary_id = 0;
-   const cChannel* channel = Channels.GetByNumber(channelid);
+
+#if VDRVERSNUM >= 20301
+  LOCK_CHANNELS_READ;
+  const cChannels* tChannels = Channels;
+#else
+  cChannels* tChannels = &Channels;
+#endif
+
+   const cChannel* channel = tChannels->GetByNumber(channelid);
 
    if (channel) tvreq.primary_name = std::string((const char*)channel->Name());
    tvreq.type_pict = 1;
@@ -2318,7 +2465,6 @@ int VompClientRRProc::processLoadChannelLogo()
    return 1;
 }