diff -ruN vdr-1.4.1-1/CONTRIBUTORS vdr-1.4.1-2/CONTRIBUTORS
--- vdr-1.4.1-1/CONTRIBUTORS	2006-06-17 11:48:50.000000000 +0200
+++ vdr-1.4.1-2/CONTRIBUTORS	2006-07-23 11:48:51.000000000 +0200
@@ -219,6 +219,7 @@
  again
  for reporting a problem with channel up/down switching on single card systems
  for fixing the PremiereContentTransmissionDescriptor in 'libsi'
+ for reporting a double fdopen() in cPipe::Open()
 
 Ulrich Röder <roeder@efr-net.de>
  for pointing out that there are channels that have a symbol rate higher than 27500
@@ -340,6 +341,8 @@
  for reporting a bug in handling min/max borders when entering integer values
  for reporting a problem with replaying in fast forward mode if the video directory
  is mounted via a Samba share
+ for suggesting to make menu items that are derived from cMenuEditIntItem loop
+ though their values if they have a dedicated minimum or maximum limit
 
 Thomas Heiligenmann <thomas@heiligenmann.de>
  for implementing the SVDRP commands LSTR and DELR
@@ -1221,6 +1224,8 @@
  for reporting a problem in handling Transfer Mode for radio channels
  for reporting a problem with messages when a cOsdObject uses the raw OSD
  for implementing palette replace mode in the OSD bitmaps
+ for fixing handling numeric keys in the channel display after switching channel
+ groups
 
 Thomas Bergwinkl <Thomas.Bergwinkl@vr-web.de>
  for fixing the validity check for channel IDs, because some providers use TIDs
@@ -1364,6 +1369,8 @@
  and PremiereContentTransmissionDescriptor to 'libsi'
  for pointing out that plugins might be compiled with different DVB driver header
  files than VDR itself
+ for adding a missing initialization of 'mutex' in cCiMenu::cCiMenu() and removing
+ some superfluous semicolons in ci.c
 
 Jürgen Schmitz <j.schmitz@web.de>
  for reporting a bug in displaying the current channel when switching via the SVDRP
@@ -1442,6 +1449,7 @@
  for setting a timer's cached start time to 0 after a call to Skip()
  for adding "-fPIC" to the compiler options in Make.config.template when compiling
  plugins
+ for reporting a missing '--vfat' in the vdr.1 man page
 
 Sven Kreiensen <svenk@kammer.uni-hannover.de>
  for his help in keeping 'channels.conf.terr' up to date
@@ -1932,6 +1940,21 @@
 
 Anssi Hannula <anssi.hannula@gmail.com>
  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
 
 Antti Hartikainen <ami+vdr@ah.fi>
  for updating 'S13E' in 'sources.conf'
+
+Bernd Melcher <bernd@bernd-melcher.de>
+ for reporting a problem with the 'servicedemo' plugin having no PLUGIN macro
+
+Patrick Maier <maierp@informatik.tu-muenchen.de>
+ for fixing handling network masks in the svdrphosts.conf file
+
+Norbert Wentz <norbert.wentz@online.de>
+ for reporting a bug in handling relative volume settings in the call to
+ cStatus::MsgSetVolume()
+
+Frank Schmirler <vdr@schmirler.de>
+ for fixing handling client side termination of SVDRP connections
diff -ruN vdr-1.4.1-1/HISTORY vdr-1.4.1-2/HISTORY
--- vdr-1.4.1-1/HISTORY	2006-06-18 10:50:04.000000000 +0200
+++ vdr-1.4.1-2/HISTORY	2006-07-23 11:47:48.000000000 +0200
@@ -4801,3 +4801,36 @@
   Patrick Cernko).
 - Now making sure a VPS timer has a schedule in case the epg.data file didn't
   contain one when VDR was started.
+
+2006-07-23: Version 1.4.1-2
+
+- Fixed the Makefile of the 'servicedemo' plugin, so that it defines the
+  PLUGIN macro, which allows the Make.config file to react properly when
+  compiling the plugin (reported by Bernd Melcher).
+  Note to all plugin developers: a plugin's Makefile *must* define the PLUGIN
+  macro, even if it doesn't use it itself!
+- Added a comment regarding the PLUGIN macro to the 'newplugin' script.
+- Added '--vfat' to the vdr.1 man page (reported by Udo Richter).
+- Removed a double fdopen() in cPipe::Open() (reported by Stefan Huelswitt).
+- Fixed handling the running status of EPG events before the currently running one,
+  in case they are added after the current event.
+- cEIT::cEIT() now calls pSchedule->SetPresentSeen() even if OnlyRunningStatus is
+  true.
+- Newlines in title and short text of an EPG event are now changed into blanks only
+  after all other fixes, because a short text might become a description.
+- Fixed handling network masks in the svdrphosts.conf file (thanks to Patrick
+  Maier).
+- Fixed handling relative volume settings in the call to cStatus::MsgSetVolume()
+  (reported by Norbert Wentz).
+- Added a missing initialization of 'mutex' in cCiMenu::cCiMenu() and removed
+  some superfluous semicolons in ci.c (thanks to Marco Schlüßler).
+- Fixed handling client side termination of SVDRP connections (thanks to Frank
+  Schmirler).
+- cDevice::GetDevice() now prefers any device that's already receiving and doesn't
+  require detatching receivers (suggested by Anssi Hannula).
+- Fixed handling numeric keys in the channel display after switching channel groups
+  (thanks to Andreas Regel).
+- Menu items derived from cMenuEditIntItem now loop though their values if they
+  have a dedicated minimum or maximum limit (suggested by Andy Grobb). Looping is
+  only done for normal keypresses, not for repeated ones. This allows the user to
+  scroll the value all the way to the limit by keeping the key pressed.
diff -ruN vdr-1.4.1-1/PLUGINS/src/servicedemo/Makefile vdr-1.4.1-2/PLUGINS/src/servicedemo/Makefile
--- vdr-1.4.1-1/PLUGINS/src/servicedemo/Makefile	2006-04-24 19:21:01.000000000 +0200
+++ vdr-1.4.1-2/PLUGINS/src/servicedemo/Makefile	2006-06-24 11:09:54.000000000 +0200
@@ -1,12 +1,13 @@
 #
 # Makefile for a Video Disk Recorder plugin
 #
-# $Id: Makefile 1.6 2006/04/24 17:21:01 kls Exp $
+# $Id: Makefile 1.7 2006/06/24 09:09:54 kls Exp $
 
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
 # By default the main source file also carries this name.
 #
+PLUGIN  = servicedemo # dummy name for Make.config
 PLUGIN1 = svccli
 PLUGIN2 = svcsvr
 
diff -ruN vdr-1.4.1-1/ci.c vdr-1.4.1-2/ci.c
--- vdr-1.4.1-1/ci.c	2006-01-07 16:07:16.000000000 +0100
+++ vdr-1.4.1-2/ci.c	2006-07-22 15:40:30.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.42 2006/01/07 15:07:16 kls Exp $
+ * $Id: ci.c 1.43 2006/07/22 13:40:30 kls Exp $
  */
 
 #include "ci.h"
@@ -1387,6 +1387,7 @@
 cCiMenu::cCiMenu(cCiMMI *MMI, bool Selectable)
 {
   mmi = MMI;
+  mutex = NULL;
   selectable = Selectable;
   titleText = subTitleText = bottomText = NULL;
   numEntries = 0;
@@ -1445,8 +1446,8 @@
 {
   mmi = MMI;
   text = NULL;
-  blind = false;;
-  expectedLength = 0;;
+  blind = false;
+  expectedLength = 0;
 }
 
 cCiEnquiry::~cCiEnquiry()
diff -ruN vdr-1.4.1-1/config.c vdr-1.4.1-2/config.c
--- vdr-1.4.1-1/config.c	2006-04-17 14:43:57.000000000 +0200
+++ vdr-1.4.1-2/config.c	2006-07-22 13:57:51.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.c 1.145 2006/04/17 12:43:57 kls Exp $
+ * $Id: config.c 1.146 2006/07/22 11:57:51 kls Exp $
  */
 
 #include "config.h"
@@ -106,8 +106,10 @@
      *(char *)p = 0; // yes, we know it's 'const' - will be restored!
      if (m == 0)
         mask = 0;
-     else
-        mask >>= (32 - m);
+     else {
+        mask <<= (32 - m);
+        mask = htonl(mask);
+        }
      }
   int result = inet_aton(s, &addr);
   if (p)
diff -ruN vdr-1.4.1-1/config.h vdr-1.4.1-2/config.h
--- vdr-1.4.1-1/config.h	2006-06-15 11:23:21.000000000 +0200
+++ vdr-1.4.1-2/config.h	2006-06-24 11:08:46.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.261 2006/06/15 09:23:21 kls Exp $
+ * $Id: config.h 1.262 2006/06/24 09:08:46 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -21,7 +21,7 @@
 
 // VDR's own version number:
 
-#define VDRVERSION  "1.4.1-1"
+#define VDRVERSION  "1.4.1-2"
 #define VDRVERSNUM   10401  // Version * 10000 + Major * 100 + Minor
 
 // The plugin API's version number:
diff -ruN vdr-1.4.1-1/device.c vdr-1.4.1-2/device.c
--- vdr-1.4.1-1/device.c	2006-06-15 11:59:40.000000000 +0200
+++ vdr-1.4.1-2/device.c	2006-07-22 16:06:11.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.131 2006/06/15 09:59:40 kls Exp $
+ * $Id: device.c 1.133 2006/07/22 14:06:11 kls Exp $
  */
 
 #include "device.h"
@@ -292,7 +292,7 @@
          // to their individual severity, where the one listed first will make the most
          // difference, because it results in the most significant bit of the result.
          uint imp = 0;
-         imp <<= 1; imp |= !device[i]->Receiving() || ndr;                         // use receiving devices if we don't need to detach existing receivers
+         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
@@ -776,9 +776,10 @@
 
 void cDevice::SetVolume(int Volume, bool Absolute)
 {
+  int OldVolume = volume;
   volume = min(max(Absolute ? Volume : volume + Volume, 0), MAXVOLUME);
   SetVolumeDevice(volume);
-  cStatus::MsgSetVolume(volume, Absolute);
+  cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute);
   if (volume > 0) {
      mute = false;
      Audios.MuteAudio(mute);
diff -ruN vdr-1.4.1-1/eit.c vdr-1.4.1-2/eit.c
--- vdr-1.4.1-1/eit.c	2006-05-25 16:35:19.000000000 +0200
+++ vdr-1.4.1-2/eit.c	2006-07-22 11:21:59.000000000 +0200
@@ -8,7 +8,7 @@
  * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
  * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
  *
- * $Id: eit.c 1.118 2006/05/25 14:35:19 kls Exp $
+ * $Id: eit.c 1.119 2006/07/22 09:21:59 kls Exp $
  */
 
 #include "eit.h"
@@ -253,10 +253,10 @@
   if (Empty && Tid == 0x4E && getSectionNumber() == 0)
      // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
      pSchedule->ClrRunningStatus(channel);
-  if (OnlyRunningStatus)
-     return;
   if (Tid == 0x4E)
      pSchedule->SetPresentSeen();
+  if (OnlyRunningStatus)
+     return;
   if (Modified) {
      pSchedule->Sort();
      if (!HasExternalData)
diff -ruN vdr-1.4.1-1/epg.c vdr-1.4.1-2/epg.c
--- vdr-1.4.1-1/epg.c	2006-05-25 16:55:36.000000000 +0200
+++ vdr-1.4.1-2/epg.c	2006-07-22 12:13:34.000000000 +0200
@@ -7,7 +7,7 @@
  * Original version (as used in VDR before 1.3.0) written by
  * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
  *
- * $Id: epg.c 1.75 2006/05/25 14:55:36 kls Exp $
+ * $Id: epg.c 1.77 2006/07/22 10:13:34 kls Exp $
  */
 
 #include "epg.h"
@@ -435,18 +435,6 @@
 
 void cEvent::FixEpgBugs(void)
 {
-  // VDR can't usefully handle newline characters in the title and shortText of EPG
-  // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel):
-  strreplace(title, '\n', ' ');
-  strreplace(shortText, '\n', ' ');
-  // Same for control characters:
-  strreplace(title, '\x86', ' ');
-  strreplace(title, '\x87', ' ');
-  strreplace(shortText, '\x86', ' ');
-  strreplace(shortText, '\x87', ' ');
-  strreplace(description, '\x86', ' ');
-  strreplace(description, '\x87', ' ');
-
   if (isempty(title)) {
      // we don't want any "(null)" titles
      title = strcpyrealloc(title, tr("No title"));
@@ -454,7 +442,7 @@
      }
 
   if (Setup.EPGBugfixLevel == 0)
-     return;
+     goto Final;
 
   // Some TV stations apparently have their own idea about how to fill in the
   // EPG data. Let's fix their bugs as good as we can:
@@ -528,7 +516,7 @@
      }
 
   if (Setup.EPGBugfixLevel <= 1)
-     return;
+     goto Final;
 
   // Some channels apparently try to do some formatting in the texts,
   // which is a bad idea because they have no way of knowing the width
@@ -574,7 +562,7 @@
   strreplace(description, '`', '\'');
 
   if (Setup.EPGBugfixLevel <= 2)
-     return;
+     goto Final;
 
   // The stream components have a "description" field which some channels
   // apparently have no idea of how to set correctly:
@@ -638,6 +626,20 @@
            }
          }
      }
+
+Final:
+
+  // VDR can't usefully handle newline characters in the title and shortText of EPG
+  // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel):
+  strreplace(title, '\n', ' ');
+  strreplace(shortText, '\n', ' ');
+  // Same for control characters:
+  strreplace(title, '\x86', ' ');
+  strreplace(title, '\x87', ' ');
+  strreplace(shortText, '\x86', ' ');
+  strreplace(shortText, '\x87', ' ');
+  strreplace(description, '\x86', ' ');
+  strreplace(description, '\x87', ' ');
 }
 
 // --- cSchedule -------------------------------------------------------------
@@ -770,6 +772,14 @@
 void cSchedule::Sort(void)
 {
   events.Sort();
+  // Make sure there are no RunningStatusUndefined before the currently running event:
+  if (hasRunning) {
+     for (cEvent *p = events.First(); p; p = events.Next(p)) {
+         if (p->RunningStatus() > SI::RunningStatusNotRunning)
+            break;
+         p->SetRunningStatus(SI::RunningStatusNotRunning);
+         }
+     }
 }
 
 void cSchedule::DropOutdated(time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version)
diff -ruN vdr-1.4.1-1/menu.c vdr-1.4.1-2/menu.c
--- vdr-1.4.1-1/menu.c	2006-06-03 15:32:42.000000000 +0200
+++ vdr-1.4.1-2/menu.c	2006-07-23 11:23:11.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menu.c 1.441 2006/06/03 13:32:42 kls Exp $
+ * $Id: menu.c 1.443 2006/07/23 09:23:11 kls Exp $
  */
 
 #include "menu.h"
@@ -39,7 +39,7 @@
 #define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS)
 #define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
 #define MAXWAITFORCAMMENU 4 // seconds to wait for the CAM menu to open
-#define MINFREEDISK       300 // minimum free disk space required to start recording
+#define MINFREEDISK       300 // minimum free disk space (in MB) required to start recording
 #define NODISKSPACEDELTA  300 // seconds between "Not enough disk space to start recording!" messages
 
 #define CHNUMWIDTH  (numdigits(Channels.MaxNumber()) + 1)
@@ -3146,6 +3146,7 @@
             return osEnd;
             }
     case k1 ... k9:
+         group = -1;
          if (number >= 0) {
             if (number > Channels.MaxNumber())
                number = Key - k0;
diff -ruN vdr-1.4.1-1/menuitems.c vdr-1.4.1-2/menuitems.c
--- vdr-1.4.1-1/menuitems.c	2006-06-03 15:20:01.000000000 +0200
+++ vdr-1.4.1-2/menuitems.c	2006-07-23 11:42:17.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menuitems.c 1.45 2006/06/03 13:20:01 kls Exp $
+ * $Id: menuitems.c 1.46 2006/07/23 09:42:17 kls Exp $
  */
 
 #include "menuitems.h"
@@ -75,6 +75,7 @@
 
   if (state == osUnknown) {
      int newValue = *value;
+     bool IsRepeat = Key & k_Repeat;
      Key = NORMALKEY(Key);
      switch (Key) {
        case kNone: break;
@@ -88,10 +89,14 @@
        case kLeft: // TODO might want to increase the delta if repeated quickly?
             newValue = *value - 1;
             fresh = true;
+            if (!IsRepeat && newValue < min && max != INT_MAX)
+               newValue = max;
             break;
        case kRight:
             newValue = *value + 1;
             fresh = true;
+            if (!IsRepeat && newValue > max && min != INT_MIN)
+               newValue = min;
             break;
        default:
             if (*value < min) { *value = min; Set(); }
diff -ruN vdr-1.4.1-1/newplugin vdr-1.4.1-2/newplugin
--- vdr-1.4.1-1/newplugin	2006-04-24 19:18:41.000000000 +0200
+++ vdr-1.4.1-2/newplugin	2006-06-24 11:15:17.000000000 +0200
@@ -12,7 +12,7 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: newplugin 1.28 2006/04/24 17:18:41 kls Exp $
+# $Id: newplugin 1.29 2006/06/24 09:15:17 kls Exp $
 
 $PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
 
@@ -61,6 +61,8 @@
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
 # By default the main source file also carries this name.
+# IPORTANT: the presence of this macro is important for the Make.config
+# file. So it must be defined, even if it is not used here!
 #
 PLUGIN = $PLUGIN_NAME
 
diff -ruN vdr-1.4.1-1/svdrp.c vdr-1.4.1-2/svdrp.c
--- vdr-1.4.1-1/svdrp.c	2006-06-11 11:04:36.000000000 +0200
+++ vdr-1.4.1-2/svdrp.c	2006-07-22 15:59:43.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.97 2006/06/11 09:04:36 kls Exp $
+ * $Id: svdrp.c 1.98 2006/07/22 13:59:43 kls Exp $
  */
 
 #include "svdrp.h"
@@ -1594,8 +1594,12 @@
               isyslog("lost connection to SVDRP client");
               Close();
               }
-           else
-              break;
+           else {
+              isyslog("SVDRP client closed connection");
+              //TODO give cSVDRP::Close() an extra parameter to avoid this code duplication
+              file.Close();
+              DELETENULL(PUTEhandler);
+              }
            }
      if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
         isyslog("timeout on SVDRP connection");
diff -ruN vdr-1.4.1-1/thread.c vdr-1.4.1-2/thread.c
--- vdr-1.4.1-1/thread.c	2006-06-02 15:51:39.000000000 +0200
+++ vdr-1.4.1-2/thread.c	2006-06-24 12:10:58.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: thread.c 1.55 2006/06/02 13:51:39 kls Exp $
+ * $Id: thread.c 1.56 2006/06/24 10:10:58 kls Exp $
  */
 
 #include "thread.h"
@@ -423,7 +423,6 @@
         iopipe = 1;
         }
      close(fd[iopipe]);
-     f = fdopen(fd[1 - iopipe], mode);
      if ((f = fdopen(fd[1 - iopipe], mode)) == NULL) {
         LOG_ERROR;
         close(fd[1 - iopipe]);
diff -ruN vdr-1.4.1-1/vdr.1 vdr-1.4.1-2/vdr.1
--- vdr-1.4.1-1/vdr.1	2006-04-30 10:55:12.000000000 +0200
+++ vdr-1.4.1-2/vdr.1	2006-06-24 12:07:16.000000000 +0200
@@ -8,7 +8,7 @@
 .\" License as specified in the file COPYING that comes with the
 .\" vdr distribution.
 .\"
-.\" $Id: vdr.1 1.25 2006/04/30 08:55:12 kls Exp $
+.\" $Id: vdr.1 1.26 2006/06/24 10:07:16 kls Exp $
 .\"
 .TH vdr 1 "30 Apr 2006" "1.4.0" "Video Disk Recorder"
 .SH NAME
@@ -137,6 +137,10 @@
 vdr can switch to a lesser privileged user id during normal
 operation.
 .TP
+.BI \-\-vfat
+Encode special characters in recording names to avoid problems
+with VFAT file systems.
+.TP
 .BI \-v\  dir ,\ \-\-video= dir
 Use \fIdir\fR as video directory.
 The default is \fI/video\fR.
