diff -ruN vdr-1.4.1-3/CONTRIBUTORS vdr-1.4.1-4/CONTRIBUTORS
--- vdr-1.4.1-3/CONTRIBUTORS	2006-08-05 14:06:11.000000000 +0200
+++ vdr-1.4.1-4/CONTRIBUTORS	2006-08-13 10:58:50.000000000 +0200
@@ -639,6 +639,7 @@
  against invalid data
  for reporting a problem in extracting APIVERSION with older versions of 'sed'
  for fixing broken APIVERSION extraction line in 'newplugin'
+ for making VDR no longer stop removing empty directories if an error occurs
 
 Reinhard Walter Buchner <rw.buchner@freenet.de>
  for adding some satellites to 'sources.conf'
@@ -1460,6 +1461,8 @@
  for reporting that the shutdown message "Recording in ... minutes, shut down anyway?"
  may have been given with a negative number of minutes
  for fixing getting the next active timer when shutting down
+ for reporting a problem with cPlugin::ConfigDirectory() in case a plugin calls it
+ from a separate thread
 
 Sven Kreiensen <svenk@kammer.uni-hannover.de>
  for his help in keeping 'channels.conf.terr' up to date
@@ -1621,6 +1624,8 @@
  for fixing several spelling errors
  for reporting that the call to pthread_setschedparam(childTid, SCHED_RR, 0) in
  thread.c caused a compiler warning with g++ 4.1.1
+ for fixing converting the port number in the "connect from..." log message of SVDRP
+ for reporting that there are places where ntohs() is assigned to different types
 
 Steffen Beyer <cpunk@reactor.de>
  for fixing setting the colored button help after deleting a recording in case the next
@@ -1953,6 +1958,7 @@
  for a patch that was used to implement processing the "frequency list descriptor"
  for suggesting that cDevice::GetDevice() should prefer any device that's already
  receiving and doesn't require detatching receivers
+ for improving handling Transfer Mode devices when selecting a device to receive
 
 Antti Hartikainen <ami+vdr@ah.fi>
  for updating 'S13E' in 'sources.conf'
@@ -1970,3 +1976,7 @@
 Frank Schmirler <vdr@schmirler.de>
  for fixing handling client side termination of SVDRP connections
  for fixing assigning schedules to channels in case there is no initial EPG information
+
+Jörn Reder <joern@zyn.de>
+ for reporting that a recording may unnecessarily block a device with a CAM, while
+ it could record on the primary device as well
diff -ruN vdr-1.4.1-3/HISTORY vdr-1.4.1-4/HISTORY
--- vdr-1.4.1-3/HISTORY	2006-08-06 11:20:04.000000000 +0200
+++ vdr-1.4.1-4/HISTORY	2006-08-13 10:58:17.000000000 +0200
@@ -4858,3 +4858,19 @@
   a negative number of minutes (reported by Udo Richter).
 - Fixed getting the next active timer when shutting down (thanks to Udo Richter).
 - Modified the cSVDRP::Close() function to avoid code duplication.
+
+2006-08-13: Version 1.4.1-4
+
+- Fixed converting the port number in the "connect from..." log message of SVDRP
+  (thanks to Ville Skyttä).
+- Made the cCiSession members sessionId and resourceId uint16_t and uint32_t,
+  respectively, to match their types in the CI session data (thanks to Ville Skyttä
+  for reporting that there are places where ntohs() is assigned to different types).
+- Changed the way a device is selected for receiving in order to keep devices with
+  CAMs better available, even if this means recording on the primary device (reported
+  by Jörn Reder; thanks to Anssi Hannula for improving handling Transfer Mode devices
+  in this).
+- No longer stopping removing empty directories if an error occurs (thanks to
+  Oliver Endriss).
+- Added a log error message to cPlugin::ConfigDirectory() in case a plugin calls it
+  from a separate thread (reported by Udo Richter).
diff -ruN vdr-1.4.1-3/ci.c vdr-1.4.1-4/ci.c
--- vdr-1.4.1-3/ci.c	2006-07-22 15:40:30.000000000 +0200
+++ vdr-1.4.1-4/ci.c	2006-08-12 12:14:27.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: ci.c 1.43 2006/07/22 13:40:30 kls Exp $
+ * $Id: ci.c 1.44 2006/08/12 10:14:27 kls Exp $
  */
 
 #include "ci.h"
@@ -630,24 +630,24 @@
 
 class cCiSession {
 private:
-  int sessionId;
-  int resourceId;
+  uint16_t sessionId;
+  uint32_t resourceId;
   cCiTransportConnection *tc;
 protected:
   int GetTag(int &Length, const uint8_t **Data);
   const uint8_t *GetData(const uint8_t *Data, int &Length);
   int SendData(int Tag, int Length = 0, const uint8_t *Data = NULL);
 public:
-  cCiSession(int SessionId, int ResourceId, cCiTransportConnection *Tc);
+  cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc);
   virtual ~cCiSession();
   const cCiTransportConnection *Tc(void) { return tc; }
-  int SessionId(void) { return sessionId; }
-  int ResourceId(void) { return resourceId; }
+  uint16_t SessionId(void) { return sessionId; }
+  uint32_t ResourceId(void) { return resourceId; }
   virtual bool HasUserIO(void) { return false; }
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   };
 
-cCiSession::cCiSession(int SessionId, int ResourceId, cCiTransportConnection *Tc)
+cCiSession::cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc)
 {
   sessionId = SessionId;
   resourceId = ResourceId;
@@ -711,11 +711,11 @@
 private:
   int state;
 public:
-  cCiResourceManager(int SessionId, cCiTransportConnection *Tc);
+  cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   };
 
-cCiResourceManager::cCiResourceManager(int SessionId, cCiTransportConnection *Tc)
+cCiResourceManager::cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_RESOURCE_MANAGER, Tc)
 {
   dbgprotocol("New Resource Manager (session id %d)\n", SessionId);
@@ -729,12 +729,12 @@
      switch (Tag) {
        case AOT_PROFILE_ENQ: {
             dbgprotocol("%d: <== Profile Enquiry\n", SessionId());
-            int resources[] = { htonl(RI_RESOURCE_MANAGER),
-                                htonl(RI_APPLICATION_INFORMATION),
-                                htonl(RI_CONDITIONAL_ACCESS_SUPPORT),
-                                htonl(RI_DATE_TIME),
-                                htonl(RI_MMI)
-                              };
+            uint32_t resources[] = { htonl(RI_RESOURCE_MANAGER),
+                                     htonl(RI_APPLICATION_INFORMATION),
+                                     htonl(RI_CONDITIONAL_ACCESS_SUPPORT),
+                                     htonl(RI_DATE_TIME),
+                                     htonl(RI_MMI)
+                                   };
             dbgprotocol("%d: ==> Profile\n", SessionId());
             SendData(AOT_PROFILE, sizeof(resources), (uint8_t*)resources);
             state = 3;
@@ -779,14 +779,14 @@
   uint16_t manufacturerCode;
   char *menuString;
 public:
-  cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc);
+  cCiApplicationInformation(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual ~cCiApplicationInformation();
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   bool EnterMenu(void);
   const char *GetMenuString(void) { return menuString; }
   };
 
-cCiApplicationInformation::cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc)
+cCiApplicationInformation::cCiApplicationInformation(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_APPLICATION_INFORMATION, Tc)
 {
   dbgprotocol("New Application Information (session id %d)\n", SessionId);
@@ -963,14 +963,14 @@
   int numCaSystemIds;
   unsigned short caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
 public:
-  cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc);
+  cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   const unsigned short *GetCaSystemIds(void) { return caSystemIds; }
   bool SendPMT(cCiCaPmt *CaPmt);
   bool ReceivedReply(bool CanDescramble = false);
   };
 
-cCiConditionalAccessSupport::cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc)
+cCiConditionalAccessSupport::cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_CONDITIONAL_ACCESS_SUPPORT, Tc)
 {
   dbgprotocol("New Conditional Access Support (session id %d)\n", SessionId);
@@ -1090,11 +1090,11 @@
   time_t lastTime;
   bool SendDateTime(void);
 public:
-  cCiDateTime(int SessionId, cCiTransportConnection *Tc);
+  cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   };
 
-cCiDateTime::cCiDateTime(int SessionId, cCiTransportConnection *Tc)
+cCiDateTime::cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_DATE_TIME, Tc)
 {
   interval = 0;
@@ -1193,7 +1193,7 @@
   cCiMenu *menu, *fetchedMenu;
   cCiEnquiry *enquiry, *fetchedEnquiry;
 public:
-  cCiMMI(int SessionId, cCiTransportConnection *Tc);
+  cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual ~cCiMMI();
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   virtual bool HasUserIO(void) { return menu || enquiry; }
@@ -1204,7 +1204,7 @@
   bool SendCloseMMI(void);
   };
 
-cCiMMI::cCiMMI(int SessionId, cCiTransportConnection *Tc)
+cCiMMI::cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_MMI, Tc)
 {
   dbgprotocol("New MMI (session id %d)\n", SessionId);
@@ -1524,12 +1524,12 @@
   return NULL;
 }
 
-int cCiHandler::ResourceIdToInt(const uint8_t *Data)
+uint32_t cCiHandler::ResourceIdToInt(const uint8_t *Data)
 {
-  return (ntohl(get_unaligned((int32_t *)Data)));
+  return (ntohl(get_unaligned((uint32_t *)Data)));
 }
 
-bool cCiHandler::Send(uint8_t Tag, int SessionId, int ResourceId, int Status)
+bool cCiHandler::Send(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId, int Status)
 {
   uint8_t buffer[16];
   uint8_t *p = buffer;
@@ -1538,7 +1538,7 @@
   if (Status >= 0)
      *p++ = Status;
   if (ResourceId) {
-     put_unaligned(htonl(ResourceId), (int32_t *)p);
+     put_unaligned(htonl(ResourceId), (uint32_t *)p);
      p += 4;
      }
   put_unaligned(htons(SessionId), (uint16_t *)p);
@@ -1547,7 +1547,7 @@
   return tc && tc->SendData(p - buffer, buffer) == OK;
 }
 
-cCiSession *cCiHandler::GetSessionBySessionId(int SessionId)
+cCiSession *cCiHandler::GetSessionBySessionId(uint16_t SessionId)
 {
   for (int i = 0; i < MAX_CI_SESSION; i++) {
       if (sessions[i] && sessions[i]->SessionId() == SessionId)
@@ -1556,7 +1556,7 @@
   return NULL;
 }
 
-cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId, int Slot)
+cCiSession *cCiHandler::GetSessionByResourceId(uint32_t ResourceId, int Slot)
 {
   for (int i = 0; i < MAX_CI_SESSION; i++) {
       if (sessions[i] && sessions[i]->Tc()->Slot() == Slot && sessions[i]->ResourceId() == ResourceId)
@@ -1565,7 +1565,7 @@
   return NULL;
 }
 
-cCiSession *cCiHandler::CreateSession(int ResourceId)
+cCiSession *cCiHandler::CreateSession(uint32_t ResourceId)
 {
   if (!GetSessionByResourceId(ResourceId, tc->Slot())) {
      for (int i = 0; i < MAX_CI_SESSION; i++) {
@@ -1588,7 +1588,7 @@
 bool cCiHandler::OpenSession(int Length, const uint8_t *Data)
 {
   if (Length == 6 && *(Data + 1) == 0x04) {
-     int ResourceId = ResourceIdToInt(Data + 2);
+     uint32_t ResourceId = ResourceIdToInt(Data + 2);
      dbgprotocol("OpenSession %08X\n", ResourceId);
      switch (ResourceId) {
        case RI_RESOURCE_MANAGER:
@@ -1611,9 +1611,9 @@
   return false;
 }
 
-bool cCiHandler::CloseSession(int SessionId)
+bool cCiHandler::CloseSession(uint16_t SessionId)
 {
-  dbgprotocol("CloseSession %08X\n", SessionId);
+  dbgprotocol("CloseSession %d\n", SessionId);
   cCiSession *Session = GetSessionBySessionId(SessionId);
   if (Session && sessions[SessionId - 1] == Session) {
      delete Session;
@@ -1675,7 +1675,7 @@
             if (Data && Length > 1) {
                switch (*Data) {
                  case ST_SESSION_NUMBER:          if (Length > 4) {
-                                                     int SessionId = ntohs(get_unaligned((uint16_t *)&Data[2]));
+                                                     uint16_t SessionId = ntohs(get_unaligned((uint16_t *)&Data[2]));
                                                      cCiSession *Session = GetSessionBySessionId(SessionId);
                                                      if (Session)
                                                         Session->Process(Length - 4, Data + 4);
diff -ruN vdr-1.4.1-3/ci.h vdr-1.4.1-4/ci.h
--- vdr-1.4.1-3/ci.h	2006-01-07 16:03:05.000000000 +0100
+++ vdr-1.4.1-4/ci.h	2006-08-12 11:43:31.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: ci.h 1.21 2006/01/07 15:03:05 kls Exp $
+ * $Id: ci.h 1.22 2006/08/12 09:43:31 kls Exp $
  */
 
 #ifndef __CI_H
@@ -110,14 +110,14 @@
   int source;
   int transponder;
   cList<cCiCaProgramData> caProgramList;
-  int ResourceIdToInt(const uint8_t *Data);
-  bool Send(uint8_t Tag, int SessionId, int ResourceId = 0, int Status = -1);
+  uint32_t ResourceIdToInt(const uint8_t *Data);
+  bool Send(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0, int Status = -1);
   const unsigned short *GetCaSystemIds(int Slot);
-  cCiSession *GetSessionBySessionId(int SessionId);
-  cCiSession *GetSessionByResourceId(int ResourceId, int Slot);
-  cCiSession *CreateSession(int ResourceId);
+  cCiSession *GetSessionBySessionId(uint16_t SessionId);
+  cCiSession *GetSessionByResourceId(uint32_t ResourceId, int Slot);
+  cCiSession *CreateSession(uint32_t ResourceId);
   bool OpenSession(int Length, const uint8_t *Data);
-  bool CloseSession(int SessionId);
+  bool CloseSession(uint16_t SessionId);
   int CloseAllSessions(int Slot);
   cCiHandler(int Fd, int NumSlots);
   void SendCaPmt(void);
diff -ruN vdr-1.4.1-3/config.h vdr-1.4.1-4/config.h
--- vdr-1.4.1-3/config.h	2006-07-29 11:56:04.000000000 +0200
+++ vdr-1.4.1-4/config.h	2006-08-12 11:10:11.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.h 1.264 2006/07/29 09:56:04 kls Exp $
+ * $Id: config.h 1.265 2006/08/12 09:10:11 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -21,7 +21,7 @@
 
 // VDR's own version number:
 
-#define VDRVERSION  "1.4.1-3"
+#define VDRVERSION  "1.4.1-4"
 #define VDRVERSNUM   10401  // Version * 10000 + Major * 100 + Minor
 
 // The plugin API's version number:
diff -ruN vdr-1.4.1-3/device.c vdr-1.4.1-4/device.c
--- vdr-1.4.1-3/device.c	2006-07-29 12:03:56.000000000 +0200
+++ vdr-1.4.1-4/device.c	2006-08-12 13:33:34.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.c 1.134 2006/07/29 10:03:56 kls Exp $
+ * $Id: device.c 1.135 2006/08/12 11:33:34 kls Exp $
  */
 
 #include "device.h"
@@ -294,11 +294,11 @@
          uint imp = 0;
          imp <<= 1; imp |= !device[i]->Receiving(true) || ndr;                     // use receiving devices if we don't need to detach existing receivers
          imp <<= 1; imp |= device[i]->Receiving();                                 // avoid devices that are receiving
-         imp <<= 1; imp |= device[i] == ActualDevice();                            // avoid the actual device (in case of Transfer Mode)
-         imp <<= 1; imp |= device[i]->IsPrimaryDevice();                           // avoid the primary device
-         imp <<= 1; imp |= device[i]->HasDecoder();                                // avoid full featured cards
+         imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice();        // avoid the Transfer Mode receiver device
          imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF); // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
          imp <<= 8; imp |= min(max(device[i]->ProvidesCa(Channel), 0), 0xFF);      // use the device that provides the lowest number of conditional access methods
+         imp <<= 1; imp |= device[i]->IsPrimaryDevice();                           // avoid the primary device
+         imp <<= 1; imp |= device[i]->HasDecoder();                                // avoid full featured cards
          if (imp < Impact) {
             // This device has less impact than any previous one, so we take it.
             Impact = imp;
diff -ruN vdr-1.4.1-3/plugin.c vdr-1.4.1-4/plugin.c
--- vdr-1.4.1-3/plugin.c	2006-04-17 11:20:05.000000000 +0200
+++ vdr-1.4.1-4/plugin.c	2006-08-13 10:51:44.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: plugin.c 1.22 2006/04/17 09:20:05 kls Exp $
+ * $Id: plugin.c 1.23 2006/08/13 08:51:44 kls Exp $
  */
 
 #include "plugin.h"
@@ -15,6 +15,7 @@
 #include <time.h>
 #include "config.h"
 #include "interface.h"
+#include "thread.h"
 
 #define LIBVDR_PREFIX  "libvdr-"
 #define SO_INDICATOR   ".so."
@@ -137,6 +138,8 @@
 const char *cPlugin::ConfigDirectory(const char *PluginName)
 {
   static char *buffer = NULL;
+  if (!cThread::IsMainThread())
+     esyslog("ERROR: plugin '%s' called cPlugin::ConfigDirectory(), which is not thread safe!", PluginName ? PluginName : "<no name given>");
   free(buffer);
   asprintf(&buffer, "%s/plugins%s%s", configDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
   return MakeDirs(buffer, true) ? buffer : NULL;
diff -ruN vdr-1.4.1-3/svdrp.c vdr-1.4.1-4/svdrp.c
--- vdr-1.4.1-3/svdrp.c	2006-08-06 11:17:58.000000000 +0200
+++ vdr-1.4.1-4/svdrp.c	2006-08-12 11:09:55.000000000 +0200
@@ -10,7 +10,7 @@
  * and interact with the Video Disk Recorder - or write a full featured
  * graphical interface that sits on top of an SVDRP connection.
  *
- * $Id: svdrp.c 1.99 2006/08/06 09:17:58 kls Exp $
+ * $Id: svdrp.c 1.100 2006/08/12 09:09:55 kls Exp $
  */
 
 #include "svdrp.h"
@@ -120,7 +120,7 @@
            close(newsock);
            newsock = -1;
            }
-        isyslog("connect from %s, port %hd - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
+        isyslog("connect from %s, port %hu - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
         }
      else if (errno != EINTR && errno != EAGAIN)
         LOG_ERROR;
diff -ruN vdr-1.4.1-3/tools.c vdr-1.4.1-4/tools.c
--- vdr-1.4.1-3/tools.c	2006-06-17 11:45:32.000000000 +0200
+++ vdr-1.4.1-4/tools.c	2006-08-12 15:30:07.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: tools.c 1.119 2006/06/17 09:45:32 kls Exp $
+ * $Id: tools.c 1.120 2006/08/12 13:30:07 kls Exp $
  */
 
 #include "tools.h"
@@ -422,8 +422,7 @@
                  }
               else {
                  LOG_ERROR_STR(buffer);
-                 free(buffer);
-                 return false;
+                 empty = false;
                  }
               free(buffer);
               }
