diff -ruN vdr-1.3.44/CONTRIBUTORS vdr-1.3.45/CONTRIBUTORS
--- vdr-1.3.44/CONTRIBUTORS	2006-02-26 16:10:02.000000000 +0100
+++ vdr-1.3.45/CONTRIBUTORS	2006-03-26 11:46:58.000000000 +0200
@@ -307,6 +307,8 @@
  for enabling a device to detach all receivers for a given PID
  for modifying switching to Dolby Digital audio in live mode, if the driver
  and firmware can handle live DD without the need of a Transfer Mode
+ for fixing cDvbDevice::SetAudioBypass() in case setTransferModeForDolbyDigital is
+ false
 
 Rolf Hakenes <hakenes@hippomi.de>
  for providing 'libdtv' and adapting the EIT mechanisms to it
@@ -556,6 +558,8 @@
  items at the beginning of the menu
  for a patch that was used to implement stopping scanning the video directory if
  there are too many levels of symbolic links
+ for reporting that an attempt to call a plugin's main menu function while a
+ message is being displayed didn't work
 
 Jeremy Hall <jhall@UU.NET>
  for fixing an incomplete initialization of the filter parameters in eit.c
@@ -964,6 +968,7 @@
  exceeds the maximum channel number
  for suggesting to also set the language codes when setting the audio track descriptions
  for reporting a problem in setting the audio language codes in 'Transfer-Mode'
+ for fixing cReadLine::Read() for lines that end with the infamous "\r\n"
 
 Ralf Klueber <ralf.klueber@vodafone.com>
  for reporting a bug in cutting a recording if there is only a single editing mark
@@ -1063,6 +1068,8 @@
  for adding a mutex to synchronize cDevice::PlayPesPacket() and SetCurrentAudioTrack()
  for a suggestion that lead to implementing cDevice::Transferring()
  for fixing replaying recordings of radio channels with many audio tracks
+ for speeding up cRemux::ScanVideoPacket()
+ for implementing cDevice::ForceTransferMode()
 
 Richard Robson <richard_robson@beeb.net>
  for reporting freezing replay if a timer starts while in Transfer Mode from the
@@ -1454,6 +1461,7 @@
  for suggesting to open the file handle in the SVDRP GRAB command in a way that
  it won't follow symbolic links, and to canonicalize the file name
  for making all font and image data 'const'
+ for fixing format string handling
 
 Sean Carlos <seanc@libero.it>
  for translating OSD texts to the Italian language
@@ -1616,6 +1624,8 @@
 Hardy Flor <HFlor@web.de>
  for a patch that was used as a base to implement SVDRP commands for plugins
  for implementing the SVDRP command PLAY
+ for reporting that RemoveEmptyVideoDirectories() was called for every single
+ recording that has been deleted
 
 Harald Milz <hm@seneca.muc.de>
  for his CUTR patch, which was used as a base to implement the SVDRP command EDIT
@@ -1767,7 +1777,22 @@
 Christoph Haubrich <christoph1.haubrich@arcor.de>
  for making the "Ok" key in the "Jump" mode of the replay progress display confirm
  the jump instead of closing the display
+ for reporting that the log message "deleting plugin: ..." is irritating when
+ calling "vdr --help"
 
 Pekka Mauno <pekka.mauno@iki.fi>
  for fixing cSchedule::GetFollowingEvent() in case there is currently no present
  event running
+
+Alexander Wenzel <hondansx@gmx.de>
+ for fixing the shutdown timeout
+
+Jan Lenz <email@JanLenz.de>
+ for reporting a bug in deleting recordings that have been removed externally when
+ running out of disk space
+
+Oleg Roitburd <oleg@roitburd.de>
+ for translating OSD texts to the Russian language
+
+Marius Heidenstecker <marius@heidenstecker.de>
+ for suggesting to make cMenuRecordings::GetRecording() 'protected'
diff -ruN vdr-1.3.44/HISTORY vdr-1.3.45/HISTORY
--- vdr-1.3.44/HISTORY	2006-02-26 16:09:14.000000000 +0100
+++ vdr-1.3.45/HISTORY	2006-03-26 16:38:46.000000000 +0200
@@ -3838,7 +3838,7 @@
 - The 'new' indicator in the Recordings menu is now kept up-to-date (thanks to
   Thomas Günther).
 - Updated the Romanian OSD texts (thanks to Lucian Muresan).
-- Updated the Russian OSD texts (thanks to Oleg ???).
+- Updated the Russian OSD texts (thanks to Oleg Roitburd).
 - The '.update' file in the video directory is now touched when a recording is
   added or deleted, so that other VDR instances can update their lists (thanks to
   Alexander Rieger).
@@ -4414,3 +4414,44 @@
   to be drawn with a transparent background (thanks to Alexander Hans).
 - Fixed cSchedule::GetFollowingEvent() in case there is currently no present event
   running (thanks to Pekka Mauno).
+
+2006-03-26: Version 1.3.45
+
+- Fixed updating the "Info" button in the "Timers" menu.
+- Reduced the number of events to actually check when setting events to timers.
+- cMenuEditIntItem now checks the given value and forces it to be between the
+  given min and max limits.
+- The status changes of EPG events are now logged for all channels that have timers.
+- Removed the log message "deleting plugin: ..." when shutting down VDR (thanks to
+  Christoph Haubrich for reporting that this is irritating when calling "vdr --help").
+- Fixed cReadLine::Read() for lines that end with the infamous "\r\n" (thanks to
+  Rolf Ahrenberg).
+- Fixed cDvbDevice::SetAudioBypass() in case setTransferModeForDolbyDigital is false
+  (thanks to Werner Fink).
+- Updated 'sources.conf'.
+- Fixed the shutdown timeout (thanks to Alexander Wenzel).
+- Only calling RemoveEmptyVideoDirectories() once in case a recording has been
+  deleted (reported by Hardy Flor).
+- Fixed deleting recordings that have been removed externally when running out of
+  disk space (reported by Jan Lenz).
+- Fixed handling repeating VPS timers (they stopped recording too early).
+- Timer log messages now show "VPS" if this is a VPS timer.
+- Fixed getting the present EPG event in case none is currently 'running' (it
+  then returns the one that just ended).
+- Fixed calling a plugin's main menu function while a message is being displayed
+  (reported by Helmut Auer).
+- Updated the Russian OSD texts (thanks to Oleg Roitburd).
+- Made cMenuRecordings::GetRecording() 'protected' (suggested by Marius Heidenstecker).
+- Speeded up cRemux::ScanVideoPacket() (thanks to Reinhard Nissl).
+- Enhanced logging EPG event data.
+- Fixed format string handling (thanks to Darren Salt).
+- The new function cDevice::ForceTransferMode() can be used to force the primary
+  device into transfer mode (thanks to Reinhard Nissl).
+- The 'version' of EPG events is now ignored when reading EPG data from 'epg.data'
+  or via SVDRP/PUTE to avoid problems with double EPG events.
+- The 'running status' of EPG events is now only set to SI::RunningStatusNotRunning
+  for events before the present event.
+- Fixed some #include sequences.
+- Single shot VPS timers are now only considered 'expired' if their associated
+  EPG event has been explicitly set to SI::RunningStatusNotRunning.
+- The check for timers to be deleted is now done only every 30 seconds.
diff -ruN vdr-1.3.44/PLUGINS/src/sky/HISTORY vdr-1.3.45/PLUGINS/src/sky/HISTORY
--- vdr-1.3.44/PLUGINS/src/sky/HISTORY	2005-09-17 12:41:01.000000000 +0200
+++ vdr-1.3.45/PLUGINS/src/sky/HISTORY	2006-03-26 11:26:11.000000000 +0200
@@ -41,3 +41,7 @@
 2005-09-17: Version 0.3.4
 
 - Added a missing include statement.
+
+2006-03-26: Version 0.3.5
+
+- Fixed format string handling.
diff -ruN vdr-1.3.44/PLUGINS/src/sky/sky.c vdr-1.3.45/PLUGINS/src/sky/sky.c
--- vdr-1.3.44/PLUGINS/src/sky/sky.c	2005-09-17 12:39:35.000000000 +0200
+++ vdr-1.3.45/PLUGINS/src/sky/sky.c	2006-03-26 11:21:10.000000000 +0200
@@ -3,7 +3,7 @@
  *
  * See the README file for copyright information and how to reach the author.
  *
- * $Id: sky.c 1.12 2005/09/17 10:39:35 kls Exp $
+ * $Id: sky.c 1.13 2006/03/26 09:21:10 kls Exp $
  */
 
 #include <sys/socket.h>
@@ -15,7 +15,7 @@
 #include <vdr/plugin.h>
 #include <vdr/sources.h>
 
-static const char *VERSION        = "0.3.4";
+static const char *VERSION        = "0.3.5";
 static const char *DESCRIPTION    = "Sky Digibox interface";
 
 // --- cDigiboxDevice --------------------------------------------------------
@@ -108,9 +108,8 @@
 
 void cDigiboxDevice::LircSend(const char *s)
 {
-  const char *c = "SEND_ONCE SKY %s\n";
   char buf[100];
-  sprintf(buf, c, s);
+  snprintf(buf, sizeof(buf), "SEND_ONCE SKY %s\n", s);
   dsyslog(buf);//XXX
   if (write(fd_lirc, buf, strlen(buf)) < 0)
      LOG_ERROR;//XXX _STR
diff -ruN vdr-1.3.44/channels.c vdr-1.3.45/channels.c
--- vdr-1.3.44/channels.c	2006-01-14 16:51:02.000000000 +0100
+++ vdr-1.3.45/channels.c	2006-02-28 14:54:34.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: channels.c 1.48 2006/01/14 15:51:02 kls Exp $
+ * $Id: channels.c 1.49 2006/02/28 13:54:34 kls Exp $
  */
 
 #include "channels.h"
@@ -12,6 +12,7 @@
 #include <ctype.h>
 #include "device.h"
 #include "epg.h"
+#include "timers.h"
 
 // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
 // format characters in order to allow any number of blanks after a numeric
@@ -248,6 +249,15 @@
   return tf;
 }
 
+bool cChannel::HasTimer(void) const
+{
+  for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) {
+      if (Timer->Channel() == this)
+         return true;
+      }
+  return false;
+}
+
 int cChannel::Modification(int Mask)
 {
   int Result = modification & Mask;
diff -ruN vdr-1.3.44/channels.conf vdr-1.3.45/channels.conf
--- vdr-1.3.44/channels.conf	2006-02-26 16:37:22.000000000 +0100
+++ vdr-1.3.45/channels.conf	2006-03-26 16:47:14.000000000 +0200
@@ -1,4 +1,4 @@
-RTL Television,RTL;RTL World:12187:hC34:S19.2E:27500:163:104=deu:105:0:12003:1:1089:0
+RTL Television,RTL;RTL World:12187:hC34:S19.2E:27500:163:104=deu;106=deu:105:0:12003:1:1089:0
 SAT.1;ProSiebenSat.1:12480:vC34:S19.2E:27500:1791:1792=deu;1795=deu:34:0:46:133:33:0
 ProSieben;ProSiebenSat.1:12480:vC34:S19.2E:27500:255:256=deu;257=deu:32:0:898:133:33:0
 RTL2;RTL World:12187:hC34:S19.2E:27500:166:128=deu:68:0:12020:1:1089:0
@@ -8,15 +8,15 @@
 NDR FS MV;ARD:12109:hC34:S19.2E:27500:2401:2402=deu:2404:0:28224:1:1073:0
 SR SÜDWEST Ferns.;ARD:12265:hC34:S19.2E:27500:1301:1302=deu:1304:0:28486:1:1093:0
 WDR Köln;ARD:11836:hC34:S19.2E:27500:601:602=deu:604:0:28111:1:1101:0
-BR-alpha;ARD:11836:hC34:S19.2E:27500:701:702=deu:704:0:28112:1:1101:0
+BR-alpha;ARD:11836:hC34:S19.2E:27500:701:702=deu;706=deu:704:0:28112:1:1101:0
 SÜDWEST Ferns. BW;ARD:11836:hC34:S19.2E:27500:801:802=deu:804:0:28113:1:1101:0
 Phoenix;ARD:11836:hC34:S19.2E:27500:901:902=deu:904:0:28114:1:1101:0
 ZDF;ZDFvision:11953:hC34:S19.2E:27500:110:120=deu,121=2ch;125=dd:130:0:28006:1:1079:0
 3sat;ZDFvision:11953:hC34:S19.2E:27500:210:220=deu,221=2ch;225=dd:230:0:28007:1:1079:0
 KiKa;ZDFvision:11953:hC34:S19.2E:27500:310:320=deu:330:0:28008:1:1079:0
 arte;ARD:11836:hC34:S19.2E:27500:401:402=deu,403=fra:404:0:28109:1:1101:0
-ORF1;ORF:12692:hC56:S19.2E:22000:160:161=deu;163=deu:165:1762,D05,1801,1702:13001:1:1117:0
-ORF2;ORF:12692:hC56:S19.2E:22000:500:501=deu;503=deu:505:1762,D05,1801,1702:13002:1:1117:0
+ORF1;ORF:12692:hC56:S19.2E:22000:160:161=deu;163=deu:165:1762,D05,1702,1801:13001:1:1117:0
+ORF2;ORF:12692:hC56:S19.2E:22000:500:501=deu;503=deu:505:1762,D05,1702,1801:13002:1:1117:0
 ZDFinfokanal;ZDFvision:11953:hC34:S19.2E:27500:610:620=deu:130:0:28011:1:1079:0
 CNN Int.;CNN:11778:vC34:S19.2E:27500:165:100=eng:47:0:28522:1:1068:0
 Super RTL,S RTL;RTL World:12187:hC34:S19.2E:27500:165:120=deu:65:0:12040:1:1089:0
@@ -44,20 +44,20 @@
 MDR FERNSEHEN;ARD:12109:hC34:S19.2E:27500:401:402=deu:404:0:28204:1:1073:0
 rbb Berlin;ARD:12109:hC34:S19.2E:27500:601:602=deu:604:0:28206:1:1073:0
 :Premiere World
-PREMIERE START,START;PREMIERE:11797:hC34:S19.2E:27500:255:256=deu:32:1801,1722,1702:8:133:2:0
-PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:32:1801,1722,1702:10:133:2:0
-PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu,1793=deu;1795=deu:32:1801,1722,1702:11:133:2:0
-PREMIERE 3,PREM 3;PREMIERE:11797:hC34:S19.2E:27500:2303:2304=deu,2305=deu:32:1722,1702,1801:43:133:2:0
-PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu:32:1801,1722,1702:9:133:2:0
-PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu:32:1722,1702,1801:29:133:2:0
-PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1801,1722,1702:41:133:2:0
-PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1801,1702,1722:20:133:2:0
-DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:32:1801,1722,1702:34:133:17:0
+PREMIERE START,START;PREMIERE:11797:hC34:S19.2E:27500:255:256=deu:32:1722,1801,1702:8:133:2:0
+PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu;515=deu:32:1:10:133:2:0
+PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu;1795=deu:32:1:11:133:2:0
+PREMIERE 3,PREM 3;PREMIERE:11797:hC34:S19.2E:27500:2303:2304=deu,2305=deu:32:1:43:133:2:0
+PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu:32:1:9:133:2:0
+PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu,1281=deu:32:1:29:133:2:0
+PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1:41:133:2:0
+PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1702,1801,1722:20:133:2:0
+DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:32:1:34:133:17:0
 :Premiere Direkt
 PREMIERE DIREKT,DIREKT;PREMIERE:12031:hC34:S19.2E:27500:2815:2816=deu,2817=deu;2819=deu:0:0:18:133:4:0
 :PW Erotic
 BEATE-UHSE.TV,B-UHSE;PREMIERE:11758:hC34:S19.2E:27500:1791:1792=deu:32:1722,1702,1801:21:133:17:0
-EROTIK - AB 18!,AB 18!;PREMIERE:12031:hC34:S19.2E:27500:1279:1280=deu:0:1801,1702,1722,1810:513:133:4:0
+EROTIK - AB 18!,AB 18!;PREMIERE:12031:hC34:S19.2E:27500:1279:1280=deu:0:1722,1801,1702,1810:513:133:4:0
 :Sportsworld
 PREMIERE SPORT PORTAL,SPORT PORTAL;PREMIERE:11719:hC34:S19.2E:27500:255:256=deu,257=deu:32:1722,1801,1702:17:133:3:0
 PREMIERE WIN,WIN;PREMIERE:12031:hC34:S19.2E:27500:3839:3840=deu:33:0:27:133:4:0
@@ -108,7 +108,7 @@
 Sky One;BSkyB:12226:hC23:S28.2E:27500:515+8190:643=eng:579:960,961:4705:2:2027:0
 Sky Two;BSkyB:12226:hC23:S28.2E:27500:514+8190:642=eng,662=NAR:578:960,961:5104:2:2027:0
 ITV2;BSkyB:10758:vC56:S28.2E:22000:2314:2315=eng,2363=NAR:2317:0:10070:2:2044:0
-Sci-Fi;BSkyB:12148:hC23:S28.2E:27500:512+8190:640=eng,660=NAR:576:960,961:4905:2:2023:0
+SCI FI;BSkyB:12148:hC23:S28.2E:27500:512+8190:640=eng,660=NAR:576:960,961:4905:2:2023:0
 ParaComedy 1;BSkyB:12187:hC23:S28.2E:27500:518+8190:666=eng,686=NAR:582:960,961:5904:2:2025:0
 Paramount;BSkyB:11526:vC23:S28.2E:27500:2317+2306:2318=eng:2319:960,961:50305:2:2404:0
 ParaComedy 2;BSkyB:11914:hC23:S28.2E:27500:514+8190:642=eng,662=NAR:578:960,961:4504:2:2011:0
diff -ruN vdr-1.3.44/channels.h vdr-1.3.45/channels.h
--- vdr-1.3.44/channels.h	2006-02-19 15:39:43.000000000 +0100
+++ vdr-1.3.45/channels.h	2006-02-28 14:52:49.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: channels.h 1.39 2006/02/19 14:39:43 kls Exp $
+ * $Id: channels.h 1.40 2006/02/28 13:52:49 kls Exp $
  */
 
 #ifndef __CHANNELS_H
@@ -202,6 +202,7 @@
   bool IsSat(void) const { return cSource::IsSat(source); }
   bool IsTerr(void) const { return cSource::IsTerr(source); }
   tChannelID GetChannelID(void) const { return tChannelID(source, nid, (nid || tid) ? tid : Transponder(), sid, rid); }
+  bool HasTimer(void) const;
   int Modification(int Mask = CHANNELMOD_ALL);
   void CopyTransponderData(const cChannel *Channel);
   bool SetSatTransponderData(int Source, int Frequency, char Polarization, int Srate, int CoderateH);
diff -ruN vdr-1.3.44/config.h vdr-1.3.45/config.h
--- vdr-1.3.44/config.h	2006-02-25 15:12:20.000000000 +0100
+++ vdr-1.3.45/config.h	2006-02-28 13:23:28.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.h 1.246 2006/02/25 14:12:20 kls Exp $
+ * $Id: config.h 1.247 2006/02/28 12:23:28 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -19,8 +19,8 @@
 #include "i18n.h"
 #include "tools.h"
 
-#define VDRVERSION  "1.3.44"
-#define VDRVERSNUM   10344  // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION  "1.3.45"
+#define VDRVERSNUM   10345  // Version * 10000 + Major * 100 + Minor
 
 #define MAXPRIORITY 99
 #define MAXLIFETIME 99
diff -ruN vdr-1.3.44/device.c vdr-1.3.45/device.c
--- vdr-1.3.44/device.c	2006-02-24 15:05:26.000000000 +0100
+++ vdr-1.3.45/device.c	2006-03-26 11:42:48.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.124 2006/02/24 14:05:26 kls Exp $
+ * $Id: device.c 1.125 2006/03/26 09:42:48 kls Exp $
  */
 
 #include "device.h"
@@ -697,6 +697,15 @@
   return Result;
 }
 
+void cDevice::ForceTransferMode(void)
+{
+  if (!cTransferControl::ReceiverDevice()) {
+     cChannel *Channel = Channels.GetByNumber(CurrentChannel());
+     if (Channel)
+        SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
+     }
+}
+
 bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
 {
   return false;
diff -ruN vdr-1.3.44/device.h vdr-1.3.45/device.h
--- vdr-1.3.44/device.h	2006-02-04 15:22:08.000000000 +0100
+++ vdr-1.3.45/device.h	2006-03-26 11:42:40.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.h 1.72 2006/02/04 14:22:08 kls Exp $
+ * $Id: device.h 1.73 2006/03/26 09:42:40 kls Exp $
  */
 
 #ifndef __DEVICE_H
@@ -236,6 +236,8 @@
 public:
   static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
          ///< Returns the number of the current channel on the primary device.
+  void ForceTransferMode(void);
+         ///< Forces the device into transfermode for the current channel.
   virtual bool HasLock(int TimeoutMs = 0);//XXX PLUGINS.html
          ///< Returns true if the device has a lock on the requested transponder.
          ///< Default is true, a specific device implementation may return false
diff -ruN vdr-1.3.44/dvbdevice.c vdr-1.3.45/dvbdevice.c
--- vdr-1.3.44/dvbdevice.c	2006-02-19 14:52:04.000000000 +0100
+++ vdr-1.3.45/dvbdevice.c	2006-03-26 11:42:54.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: dvbdevice.c 1.153 2006/02/19 13:52:04 kls Exp $
+ * $Id: dvbdevice.c 1.155 2006/03/26 09:42:54 kls Exp $
  */
 
 #include "dvbdevice.h"
@@ -653,6 +653,8 @@
 
 bool cDvbDevice::SetAudioBypass(bool On)
 {
+  if (!setTransferModeForDolbyDigital)
+     return false;
   return ioctl(fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0;
 }
 
@@ -928,9 +930,7 @@
         if (!setTransferModeForDolbyDigital)
            return;
         // Currently this works only in Transfer Mode
-        cChannel *Channel = Channels.GetByNumber(CurrentChannel());
-        if (Channel)
-           SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
+        ForceTransferMode();
         }
      }
 }
diff -ruN vdr-1.3.44/epg.c vdr-1.3.45/epg.c
--- vdr-1.3.44/epg.c	2006-02-26 16:07:17.000000000 +0100
+++ vdr-1.3.45/epg.c	2006-03-26 16:06:11.000000000 +0200
@@ -7,14 +7,14 @@
  * 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.64 2006/02/26 15:07:17 kls Exp $
+ * $Id: epg.c 1.70 2006/03/26 14:06:11 kls Exp $
  */
 
 #include "epg.h"
-#include "libsi/si.h"
-#include "timers.h"
 #include <ctype.h>
 #include <time.h>
+#include "libsi/si.h"
+#include "timers.h"
 
 #define RUNNINGSTATUSTIMEOUT 30 // seconds before the running status is considered unknown
 
@@ -103,7 +103,7 @@
   eventID = EventID;
   tableID = 0;
   version = 0xFF; // actual version numbers are 0..31
-  runningStatus = 0;
+  runningStatus = SI::RunningStatusUndefined;
   title = NULL;
   shortText = NULL;
   description = NULL;
@@ -156,9 +156,8 @@
 
 void cEvent::SetRunningStatus(int RunningStatus, cChannel *Channel)
 {
-  if (Channel && runningStatus != RunningStatus && (RunningStatus > SI::RunningStatusNotRunning || runningStatus > SI::RunningStatusUndefined))
-     if (Channel->Number() <= 30)//XXX maybe log only those that have timers???
-     isyslog("channel %d (%s) event %s '%s' status %d", Channel->Number(), Channel->Name(), *GetTimeString(), Title(), RunningStatus);
+  if (Channel && runningStatus != RunningStatus && (RunningStatus > SI::RunningStatusNotRunning || runningStatus > SI::RunningStatusUndefined) && Channel->HasTimer())
+     isyslog("channel %d (%s) event %s status %d", Channel->Number(), Channel->Name(), *ToDescr(), RunningStatus);
   runningStatus = RunningStatus;
 }
 
@@ -209,6 +208,14 @@
   seen = time(NULL);
 }
 
+cString cEvent::ToDescr(void) const
+{
+  char vpsbuf[64] = "";
+  if (Vps())
+     sprintf(vpsbuf, "(VPS: %s) ", *GetVpsString());
+  return cString::sprintf("%s %s-%s %s'%s'", *GetDateString(), *GetTimeString(), *GetEndTimeString(), vpsbuf, Title());
+}
+
 bool cEvent::HasTimer(void) const
 {
   for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) {
@@ -313,7 +320,7 @@
                           time_t StartTime;
                           int Duration;
                           unsigned int TableID = 0;
-                          unsigned int Version = 0xFF;
+                          unsigned int Version = 0xFF; // actual value is ignored
                           int n = sscanf(t, "%u %ld %d %X %X", &EventID, &StartTime, &Duration, &TableID, &Version);
                           if (n >= 3 && n <= 5) {
                              Event = (cEvent *)Schedule->GetEvent(EventID, StartTime);
@@ -324,8 +331,6 @@
                                 Event = newEvent = new cEvent(EventID);
                              if (Event) {
                                 Event->SetTableID(TableID);
-                                if (TableID >= 0x50) // makes sure the running status flag is set from the actual data stream
-                                   Event->SetVersion(Version);
                                 Event->SetStartTime(StartTime);
                                 Event->SetDuration(Duration);
                                 if (newEvent)
@@ -678,8 +683,10 @@
   const cEvent *pe = NULL;
   time_t now = time(NULL);
   for (cEvent *p = events.First(); p; p = events.Next(p)) {
-      if (p->StartTime() <= now && now < p->EndTime())
+      if (p->StartTime() <= now)
          pe = p;
+      else if (p->StartTime() > now + 3600)
+         break;
       if (p->SeenWithin(RUNNINGSTATUSTIMEOUT) && p->RunningStatus() >= SI::RunningStatusPausing)
          return p;
       }
@@ -728,9 +735,11 @@
 void cSchedule::SetRunningStatus(cEvent *Event, int RunningStatus, cChannel *Channel)
 {
   for (cEvent *p = events.First(); p; p = events.Next(p)) {
-      if (p == Event)
-         p->SetRunningStatus(RunningStatus, Channel);
-      else if (RunningStatus >= SI::RunningStatusPausing && p->RunningStatus() > SI::RunningStatusNotRunning)
+      if (p == Event) {
+         if (p->RunningStatus() > SI::RunningStatusNotRunning || RunningStatus > SI::RunningStatusNotRunning)
+            p->SetRunningStatus(RunningStatus, Channel);
+         }
+      else if (RunningStatus >= SI::RunningStatusPausing && p->StartTime() < Event->StartTime())
          p->SetRunningStatus(SI::RunningStatusNotRunning);
       }
   if (RunningStatus >= SI::RunningStatusPausing)
diff -ruN vdr-1.3.44/epg.h vdr-1.3.45/epg.h
--- vdr-1.3.44/epg.h	2006-02-26 14:58:57.000000000 +0100
+++ vdr-1.3.45/epg.h	2006-03-25 13:39:39.000000000 +0100
@@ -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.h 1.33 2006/02/26 13:58:57 kls Exp $
+ * $Id: epg.h 1.34 2006/03/25 12:39:39 kls Exp $
  */
 
 #ifndef __EPG_H
@@ -103,6 +103,7 @@
   void SetDuration(int Duration);
   void SetVps(time_t Vps);
   void SetSeen(void);
+  cString ToDescr(void) const;
   void Dump(FILE *f, const char *Prefix = "", bool InfoOnly = false) const;
   bool Parse(char *s);
   static bool Read(FILE *f, cSchedule *Schedule);
diff -ruN vdr-1.3.44/i18n.c vdr-1.3.45/i18n.c
--- vdr-1.3.44/i18n.c	2006-02-25 15:21:28.000000000 +0100
+++ vdr-1.3.45/i18n.c	2006-03-26 11:17:58.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: i18n.c 1.250 2006/02/25 14:21:28 kls Exp $
+ * $Id: i18n.c 1.252 2006/03/26 09:17:58 kls Exp $
  *
  * Translations provided by:
  *
@@ -22,7 +22,7 @@
  * Romanian    Paul Lacatus <paul@campina.iiruc.ro>, Lucian Muresan <lucianm@users.sourceforge.net>
  * Hungarian   Istvan Koenigsberger <istvnko@hotmail.com>, Guido Josten <guido.josten@t-online.de>
  * Catalanian  Marc Rovira Vall <tm05462@salleURL.edu>, Ramon Roca <ramon.roca@xcombo.com>, Jordi Vilà <jvila@tinet.org>
- * Russian     Vyacheslav Dikonov <sdiconov@mail.ru>
+ * Russian     Vyacheslav Dikonov <sdiconov@mail.ru>, Oleg Roitburd <oleg@roitburd.de>
  * Croatian    Drazen Dupor <drazen.dupor@dupor.com>, Dino Ravnic <dino.ravnic@fer.hr>
  * Estonian    Arthur Konovalov <kasjas@hot.ee>
  * Danish      Mogens Elneff <mogens@elneff.dk>
@@ -475,7 +475,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "ÍâÐ ßÕàÕÔÐçÐ - %s",
     "",//TODO
     "See sündmus - %s",
     "Denne udsendelse - %s",
@@ -497,7 +497,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "ÍâÐ ßÕàÕÔÐçÐ - ÒáÕ ÚÐÝÐÛë",
     "",//TODO
     "See sündmus - kõik kanalid",
     "Denne udsendelse - alle kanaler",
@@ -519,7 +519,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "²áÕ ßÕàÕÔÐçØ - ÒáÕ ÚÐÝÐÛë",
     "",//TODO
     "Kõik sündmused - kõik kanalid",
     "Alle udsendelser - alle kanaler",
@@ -696,7 +696,7 @@
     "",// TODO
     "",// TODO
     "",// TODO
-    "",// TODO
+    "ÂÐÙÜÕà",
     "",// TODO
     "Taimer",
     "Timer",
@@ -1319,27 +1319,27 @@
     "Optagelse igang - sluk alligevel?",
     "Systém je zaneprázdnìn - pøesto vypnout?",
   },
-  { "Recording in %d minutes, shut down anyway?",
-    "Aufnahme in %d Minuten - trotzdem ausschalten?",
-    "Snemanje èez %d minut, zares izklopi?",
-    "Registrazione fra %d minuti - spengo comunque?",
-    "Opname in %d minuten - toch uitschakelen?",
-    "Em gravação dentro de %d minutos - quer mesmo desligar?",
-    "Enregistrement dans %d minutes - confirmez l'arrêt",
-    "Skal gjøre opptak om %d minutter - slå av likevel?",
-    "Tallennus alkaa %d min kuluttua - sammutetaanko?",
-    "Nagrywanie za %d minut - wy³±czyæ mimo to?",
-    "Grabación dentro de %d minutos, ¿apagar realmente?",
-    "ÁíáìÝíåôáé åããñáöÞ óÝ %d ëåðôÜ - ÔåëéêÜ íá ôåñìáôéóôåß?",
-    "Inspelning startar om %d minuter, vill du avsluta?",
-    "Înregistrez peste %d minute - închid, totuºi?",
-    "Felvétel %d perc mulva kezdödik - mégis kikapcsolni?",
-    "Hi ha una gravació en %d minuts - Apagar de totes maneres?",
-    "ÇÕàÕ× %d ÜØÝãâ ÝÐçÝñâáï ×ÐßØáì - ÔÕÙáâÒØâÕÛìÝÞ ÒëÚÛîçØâì?",
-    "Snimanje za %d minuta - svejedno iskljuèiti?",
-    "Salvestamine algab %d minuti pärast - lülitan välja?",
-    "Optagelse om %d minutter - sluk alligevel?",
-    "Nahrávání zaène za %d minut - pøesto vypnout?",
+  { "Recording in %ld minutes, shut down anyway?",
+    "Aufnahme in %ld Minuten - trotzdem ausschalten?",
+    "Snemanje èez %ld minut, zares izklopi?",
+    "Registrazione fra %ld minuti - spengo comunque?",
+    "Opname in %ld minuten - toch uitschakelen?",
+    "Em gravação dentro de %ld minutos - quer mesmo desligar?",
+    "Enregistrement dans %ld minutes - confirmez l'arrêt",
+    "Skal gjøre opptak om %ld minutter - slå av likevel?",
+    "Tallennus alkaa %ld min kuluttua - sammutetaanko?",
+    "Nagrywanie za %ld minut - wy³±czyæ mimo to?",
+    "Grabación dentro de %ld minutos, ¿apagar realmente?",
+    "ÁíáìÝíåôáé åããñáöÞ óÝ %ld ëåðôÜ - ÔåëéêÜ íá ôåñìáôéóôåß?",
+    "Inspelning startar om %ld minuter, vill du avsluta?",
+    "Înregistrez peste %ld minute - închid, totuºi?",
+    "Felvétel %ld perc mulva kezdödik - mégis kikapcsolni?",
+    "Hi ha una gravació en %ld minuts - Apagar de totes maneres?",
+    "ÇÕàÕ× %ld ÜØÝãâ ÝÐçÝñâáï ×ÐßØáì - ÔÕÙáâÒØâÕÛìÝÞ ÒëÚÛîçØâì?",
+    "Snimanje za %ld minuta - svejedno iskljuèiti?",
+    "Salvestamine algab %ld minuti pärast - lülitan välja?",
+    "Optagelse om %ld minutter - sluk alligevel?",
+    "Nahrávání zaène za %ld minut - pøesto vypnout?",
   },
   { "Press any key to cancel shutdown",
     "Taste drücken, um Shutdown abzubrechen",
@@ -1666,7 +1666,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "FTA (ÝÕ×ÐÚÞÔØàÞÒÐÝÞ)",
     "",//TODO
     "FTA",
     "Free To Air",
@@ -1688,7 +1688,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "×ÐÚÞÔØàÞÒÐÝÞ",
     "",//TODO
     "krüptitud",
     "kodet",
@@ -2460,7 +2460,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "½ÕÔÞáâÐâÞçÝÞ ÜÕáâÐ ÝÐ ÔØáÚÕ ÔÛï ÝÐçÐÛÐ ×ÐßØáØ",
     "",//TODO
     "Ebapiisavalt kettaruumi salvestamise alustamiseks!",
     "For lidt harddisk plads til optagelse!",
@@ -2504,7 +2504,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "¾âÚàëÒÐî ÜÕÝî ÜÞÔãÛï ãáÛÞÒÝÞÓÞ ÔÞáâãßÐ (CAM)",
     "",//TODO
     "CAM-menüü avamine...",
     "Åbner CAM menu...",
@@ -2548,7 +2548,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "¿ÕàÕÓàã×ÚÐ CAM...",
     "",//TODO
     "CAM mooduli taaskäivitus...",
     "Nulstiller CAM...",
@@ -2614,7 +2614,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "½ÐÖÜØâÕ %d æØäàë",
     "",//TODO
     "Palun sisesta %d numbrit!",
     "Indtast venligst %d cifre!",
@@ -3232,7 +3232,7 @@
     "", // TODO
     "", // TODO
     "", // TODO
-    "", // TODO
+    "¸ÝäÞàÜÐæØî Þ ÚÐÝÐÛÕ ×ÐÚàëâì",
     "", // TODO
     "Kanaliinfo kuvamise ajapiirang",
     "Timeout ved anmodet kanal info",
@@ -3298,7 +3298,7 @@
     "",// TODO
     "",// TODO
     "",// TODO
-    "",// TODO
+    "ºÝÞßÚã ¼ÕÝî ×ÐÚàëâì",
     "",// TODO
     "Sulgemine Menüü klahviga",
     "Menu taste lukker",
@@ -4399,7 +4399,7 @@
     "LMMJVSD",
     "HKSCPSV",
     "LMCJVSG",
-    "¿²ÁÇ¿²Á",
+    "¿²ÁÇ¿Á²",
     "PUSÈPSN", // hrv
     "ETKNRLP",
     "MTOTFLS",
@@ -5151,7 +5151,7 @@
     "Derulare înainte",
     "Elöre pörgetni",
     "Endavant ràpidament",
-    "²ßÕàñÔ",
+    "¿àÞÚàãâÚÐ ÒßÕàñÔ",
     "Naprijed",
     "Edasikerimine",
     "Spol fremad",
@@ -5173,7 +5173,7 @@
     "Derulare înapoi",
     "Vissza pörgetni",
     "Enrera ràpidament",
-    "½Ð×ÐÔ",
+    "¿àÞÚàãâÚÐ ÝÐ×ÐÔ",
     "Nazad",
     "Tagasikerimine",
     "Spol tilbage",
@@ -5768,7 +5768,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
+    "·ÐßØáì ÝÐçÐâÐ",
     "",//TODO
     "Salvestamine algas",
     "Optagelse startet",
diff -ruN vdr-1.3.44/i18n.h vdr-1.3.45/i18n.h
--- vdr-1.3.44/i18n.h	2006-02-04 11:41:16.000000000 +0100
+++ vdr-1.3.45/i18n.h	2006-03-26 11:08:00.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: i18n.h 1.17 2006/02/04 10:41:16 kls Exp $
+ * $Id: i18n.h 1.18 2006/03/26 09:08:00 kls Exp $
  */
 
 #ifndef __I18N_H
@@ -18,7 +18,7 @@
 
 void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin);
 
-const char *I18nTranslate(const char *s, const char *Plugin = NULL);
+const char *I18nTranslate(const char *s, const char *Plugin = NULL) __attribute_format_arg__(1);
 
 const char * const * I18nLanguages(void);
 const char * const * I18nCharSets(void);
diff -ruN vdr-1.3.44/interface.c vdr-1.3.45/interface.c
--- vdr-1.3.44/interface.c	2006-01-29 13:35:50.000000000 +0100
+++ vdr-1.3.45/interface.c	2006-03-25 12:50:55.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: interface.c 1.73 2006/01/29 12:35:50 kls Exp $
+ * $Id: interface.c 1.74 2006/03/25 11:50:55 kls Exp $
  */
 
 #include "interface.h"
@@ -52,7 +52,7 @@
       if (ISRAWKEY(Key) || time(NULL) > timeout || interrupted)
          break;
       }
-  if (KeepChar && ISRAWKEY(Key))
+  if (KeepChar && ISRAWKEY(Key) || Key == k_Plugin)
      cRemote::Put(Key);
   interrupted = false;
   return Key;
diff -ruN vdr-1.3.44/menu.c vdr-1.3.45/menu.c
--- vdr-1.3.44/menu.c	2006-02-25 16:41:40.000000000 +0100
+++ vdr-1.3.45/menu.c	2006-02-28 14:58:00.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menu.c 1.422 2006/02/25 15:41:40 kls Exp $
+ * $Id: menu.c 1.424 2006/02/28 13:58:00 kls Exp $
  */
 
 #include "menu.h"
@@ -500,12 +500,10 @@
      cChannel *channel = GetChannel(Current());
      int DeletedChannel = channel->Number();
      // Check if there is a timer using this channel:
-     for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) {
-         if (ti->Channel() == channel) {
-            Skins.Message(mtError, tr("Channel is being used by a timer!"));
-            return osContinue;
-            }
-         }
+     if (channel->HasTimer()) {
+        Skins.Message(mtError, tr("Channel is being used by a timer!"));
+        return osContinue;
+        }
      if (Interface->Confirm(tr("Delete channel?"))) {
         Channels.Del(channel);
         cOsdMenu::Del(Index);
@@ -690,8 +688,8 @@
                              *timer = data;
                           if (addIfConfirmed)
                              Timers.Add(timer);
-                          timer->Matches();
                           timer->SetEventFromSchedule();
+                          timer->Matches();
                           Timers.SetModified();
                           isyslog("timer %s %s (%s)", *timer->ToDescr(), addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive");
                           addIfConfirmed = false;
@@ -787,8 +785,10 @@
 :cOsdMenu(tr("Timers"), 2, CHNUMWIDTH, 10, 6, 6)
 {
   helpKeys = -1;
-  for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer))
+  for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
+      timer->SetEventFromSchedule(); // make sure the event is current
       Add(new cMenuTimerItem(timer));
+      }
   Sort();
   SetCurrent(First());
   SetHelpKeys();
@@ -900,7 +900,7 @@
        case kOk:     return Edit();
        case kRed:    state = OnOff(); break; // must go through SetHelpKeys()!
        case kGreen:  return New();
-       case kYellow: return Delete();
+       case kYellow: state = Delete(); break;
        case kBlue:   return Info();
                      break;
        default: break;
diff -ruN vdr-1.3.44/menu.h vdr-1.3.45/menu.h
--- vdr-1.3.44/menu.h	2006-02-25 14:41:21.000000000 +0100
+++ vdr-1.3.45/menu.h	2006-03-25 13:15:19.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menu.h 1.84 2006/02/25 13:41:21 kls Exp $
+ * $Id: menu.h 1.85 2006/03/25 12:15:19 kls Exp $
  */
 
 #ifndef __MENU_H
@@ -165,13 +165,14 @@
   int helpKeys;
   void SetHelpKeys(void);
   void Set(bool Refresh = false);
-  cRecording *GetRecording(cMenuRecordingItem *Item);
   bool Open(bool OpenSubMenus = false);
   eOSState Play(void);
   eOSState Rewind(void);
   eOSState Delete(void);
   eOSState Info(void);
   eOSState Commands(eKeys Key = kNone);
+protected:
+  cRecording *GetRecording(cMenuRecordingItem *Item);
 public:
   cMenuRecordings(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false);
   ~cMenuRecordings();
diff -ruN vdr-1.3.44/menuitems.c vdr-1.3.45/menuitems.c
--- vdr-1.3.44/menuitems.c	2006-02-12 11:31:08.000000000 +0100
+++ vdr-1.3.45/menuitems.c	2006-03-26 11:10: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.32 2006/02/12 10:31:08 kls Exp $
+ * $Id: menuitems.c 1.34 2006/03/26 09:10:17 kls Exp $
  */
 
 #include "menuitems.h"
@@ -51,6 +51,10 @@
   value = Value;
   min = Min;
   max = Max;
+  if (*value < min)
+     *value = min;
+  else if (*value > max)
+     *value = max;
   Set();
 }
 
@@ -286,12 +290,11 @@
 void cMenuEditStrItem::Set(void)
 {
   char buf[1000];
-  const char *fmt = insert && newchar ? "[]%c%s" : "[%c]%s";
 
   if (InEditMode()) {
      const cFont *font = cFont::GetFont(fontOsd);
      strncpy(buf, value, pos);
-     snprintf(buf + pos, sizeof(buf) - pos - 2, fmt, *(value + pos), value + pos + 1);
+     snprintf(buf + pos, sizeof(buf) - pos - 2, insert && newchar ? "[]%c%s" : "[%c]%s", *(value + pos), value + pos + 1);
      int width = cSkinDisplay::Current()->EditableWidth();
      if (font->Width(buf) <= width) {
         // the whole buffer fits on the screen
diff -ruN vdr-1.3.44/pat.h vdr-1.3.45/pat.h
--- vdr-1.3.44/pat.h	2004-03-07 17:22:01.000000000 +0100
+++ vdr-1.3.45/pat.h	2006-03-26 16:09:43.000000000 +0200
@@ -4,14 +4,14 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: pat.h 1.4 2004/03/07 16:22:01 kls Exp $
+ * $Id: pat.h 1.5 2006/03/26 14:09:43 kls Exp $
  */
 
 #ifndef __PAT_H
 #define __PAT_H
 
-#include "filter.h"
 #include <stdint.h>
+#include "filter.h"
 
 #define MAXPMTENTRIES 64
 
diff -ruN vdr-1.3.44/plugin.c vdr-1.3.45/plugin.c
--- vdr-1.3.44/plugin.c	2006-01-08 12:40:05.000000000 +0100
+++ vdr-1.3.45/plugin.c	2006-02-28 15:16:54.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: plugin.c 1.16 2006/01/08 11:40:05 kls Exp $
+ * $Id: plugin.c 1.17 2006/02/28 14:16:54 kls Exp $
  */
 
 #include "plugin.h"
@@ -427,10 +427,6 @@
 void cPluginManager::Shutdown(void)
 {
   cDll *dll;
-  while ((dll = dlls.Last()) != NULL) {
-        cPlugin *p = dll->Plugin();
-        if (p)
-           isyslog("deleting plugin: %s", p->Name());
+  while ((dll = dlls.Last()) != NULL)
         dlls.Del(dll);
-        }
 }
diff -ruN vdr-1.3.44/receiver.c vdr-1.3.45/receiver.c
--- vdr-1.3.44/receiver.c	2005-01-16 15:03:01.000000000 +0100
+++ vdr-1.3.45/receiver.c	2006-03-26 16:07:21.000000000 +0200
@@ -4,12 +4,12 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: receiver.c 1.4 2005/01/16 14:03:01 kls Exp $
+ * $Id: receiver.c 1.5 2006/03/26 14:07:21 kls Exp $
  */
 
+#include "receiver.h"
 #include <stdarg.h>
 #include <stdio.h>
-#include "receiver.h"
 #include "tools.h"
 
 cReceiver::cReceiver(int Ca, int Priority, int Pid, const int *Pids1, const int *Pids2, const int *Pids3)
diff -ruN vdr-1.3.44/recording.c vdr-1.3.45/recording.c
--- vdr-1.3.44/recording.c	2006-02-26 12:59:59.000000000 +0100
+++ vdr-1.3.45/recording.c	2006-03-26 11:11:00.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: recording.c 1.140 2006/02/26 11:59:59 kls Exp $
+ * $Id: recording.c 1.143 2006/03/26 09:11:00 kls Exp $
  */
 
 #include "recording.h"
@@ -83,6 +83,7 @@
   // Make sure only one instance of VDR does this:
   cLockFile LockFile(VideoDirectory);
   if (LockFile.Lock()) {
+     bool deleted = false;
      cThreadLock DeletedRecordingsLock(&DeletedRecordings);
      for (cRecording *r = DeletedRecordings.First(); r; ) {
          if (r->deleted && time(NULL) - r->deleted > DELETEDLIFETIME) {
@@ -90,11 +91,13 @@
             r->Remove();
             DeletedRecordings.Del(r);
             r = next;
-            RemoveEmptyVideoDirectories();
+            deleted = true;
             continue;
             }
          r = DeletedRecordings.Next(r);
          }
+     if (deleted)
+        RemoveEmptyVideoDirectories();
      }
 }
 
@@ -801,11 +804,16 @@
      strncpy(ext, DELEXT, strlen(ext));
      if (access(NewName, F_OK) == 0) {
         // the new name already exists, so let's remove that one first:
-        isyslog("removing recording %s", NewName);
+        isyslog("removing recording '%s'", NewName);
         RemoveVideoFile(NewName);
         }
-     isyslog("deleting recording %s", FileName());
-     result = RenameVideoFile(FileName(), NewName);
+     isyslog("deleting recording '%s'", FileName());
+     if (access(FileName(), F_OK) == 0)
+        result = RenameVideoFile(FileName(), NewName);
+     else {
+        isyslog("recording '%s' vanished", FileName());
+        result = true; // well, we were going to delete it, anyway
+        }
      }
   free(NewName);
   return result;
@@ -1049,7 +1057,7 @@
 
 bool cMark::Save(FILE *f)
 {
-  return fprintf(f, ToText()) > 0;
+  return fprintf(f, "%s", *ToText()) > 0;
 }
 
 // --- cMarks ----------------------------------------------------------------
diff -ruN vdr-1.3.44/remux.c vdr-1.3.45/remux.c
--- vdr-1.3.44/remux.c	2006-02-03 17:19:02.000000000 +0100
+++ vdr-1.3.45/remux.c	2006-03-25 13:27:30.000000000 +0100
@@ -11,7 +11,7 @@
  * The cRepacker family's code was originally written by Reinhard Nissl <rnissl@gmx.de>,
  * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de.
  *
- * $Id: remux.c 1.54 2006/02/03 16:19:02 kls Exp $
+ * $Id: remux.c 1.55 2006/03/25 12:27:30 kls Exp $
  */
 
 #include "remux.h"
@@ -1429,7 +1429,9 @@
 #define IPACKS 2048
 
 // Start codes:
-#define SC_PICTURE 0x00  // "picture header"
+#define SC_SEQUENCE 0xB3  // "sequence header code"
+#define SC_GROUP    0xB8  // "group start code"
+#define SC_PICTURE  0x00  // "picture start code"
 
 #define MAXNONUSEFULDATA (10*1024*1024)
 #define MAXNUMUPTERRORS  10
@@ -1925,14 +1927,38 @@
   if (Length > 0) {
      int PesPayloadOffset = 0;
      if (AnalyzePesHeader(Data + Offset, Length, PesPayloadOffset) >= phMPEG1) {
-        for (int i = Offset + PesPayloadOffset; i < Offset + Length - 5; i++) {
-            if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1) {
-               switch (Data[i + 3]) {
-                 case SC_PICTURE: PictureType = (Data[i + 5] >> 3) & 0x07;
-                                  return Length;
+        const uchar *p = Data + Offset + PesPayloadOffset + 2;
+        const uchar *pLimit = Data + Offset + Length - 3;
+#ifdef TEST_cVideoRepacker
+        // cVideoRepacker ensures that a new PES packet is started for a new sequence,
+        // group or picture which allows us to easily skip scanning through a huge
+        // amount of video data.
+        if (p < pLimit) {
+           if (p[-2] || p[-1] || p[0] != 0x01)
+              pLimit = 0; // skip scanning: packet doesn't start with 0x000001
+           else {
+              switch (p[1]) {
+                case SC_SEQUENCE:
+                case SC_GROUP:
+                case SC_PICTURE:
+                     break;
+                default: // skip scanning: packet doesn't start a new sequence, group or picture
+                     pLimit = 0;
+                }
+              }
+           }
+#endif
+        while (p < pLimit && (p = (const uchar *)memchr(p, 0x01, pLimit - p))) {
+              if (!p[-2] && !p[-1]) { // found 0x000001
+                 switch (p[1]) {
+                   case SC_PICTURE: PictureType = (p[3] >> 3) & 0x07;
+                                    return Length;
+                   }
+                 p += 4; // continue scanning after 0x01ssxxyy
                  }
-               }
-            }
+              else
+                 p += 3; // continue scanning after 0x01xxyy
+              }
         }
      PictureType = NO_PICTURE;
      return Length;
diff -ruN vdr-1.3.44/remux.h vdr-1.3.45/remux.h
--- vdr-1.3.44/remux.h	2005-08-26 15:22:19.000000000 +0200
+++ vdr-1.3.45/remux.h	2006-03-25 13:27:30.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remux.h 1.15 2005/08/26 13:22:19 kls Exp $
+ * $Id: remux.h 1.16 2006/03/25 12:27:30 kls Exp $
  */
 
 #ifndef __REMUX_H
@@ -46,8 +46,6 @@
   cRingBufferLinear *resultBuffer;
   int resultSkipped;
   int GetPid(const uchar *Data);
-  int GetPacketLength(const uchar *Data, int Count, int Offset);
-  int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
 public:
   cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false);
        ///< Creates a new remuxer for the given PIDs. VPid is the video PID, while
@@ -79,6 +77,8 @@
        ///< Clears the remuxer of all data it might still contain, keeping the PID
        ///< settings as they are.
   static void SetBrokenLink(uchar *Data, int Length);
+  static int GetPacketLength(const uchar *Data, int Count, int Offset);
+  static int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType);
   };
 
 #endif // __REMUX_H
diff -ruN vdr-1.3.44/sources.conf vdr-1.3.45/sources.conf
--- vdr-1.3.44/sources.conf	2005-10-08 10:47:59.000000000 +0200
+++ vdr-1.3.45/sources.conf	2006-03-19 14:03:46.000000000 +0100
@@ -17,98 +17,169 @@
 
 # Satellites
 
+# Europe
+
 S5E     Sirius 2/3
-S7E     Eutelsat W3
-S10E    Eutelsat W1R
+S7E     Eutelsat W3A
+S10E    Eutelsat W1
 S13E    Hotbird 1-(5)-6
 S16E    Eutelsat W2
 S19.2E  Astra 1B/C/E/F/G/H/2C
-S21.5E  Eutelsat II F3
-S23.5E  Astra 3A
-S24.2E  Astra 1D
-S26E    Arabsat 2A/3A
+S21.0E  Afristar 1
+S21.6E  Eutelsat W6
+S23.5E  Astra 1D 3A
+S26E    Arabsat 2D/2C/3A
 S28.2E  Astra 2D/A/B 
-S28.5E  Eurobird
+S28.5E  Eurobird 1 & Astra 2A/B/D
 S30.5E  Arabsat 2B
-S31.3E  Türksat 1B
+S33E    Eurobird 3 & Intelsat 802
 S36E    Eutelsat W4 & Sesat
-S39E    Hellas Sat
-S40E    Express A1R
-S42E    Turksat 1C & EurAsiaSat 1 & NewSat 1
-S45E    Europe*Star 1
-S47E    Telecom 2B
-S48E    Eutelsat II F1 
-S50E    Anatolia 1
-S53E    Gorizont 32
-S55.1E  Insat 2DT
-S56E    Most 1
+S38E    Paksat 1
+S39E    Hellas Sat 2
+S40E    Express AM1
+S42E    Turksat 1C/2A
+S45E    PAS 12
+S49E    Yamal 202
+S53E    Express AM 22
+S55E    Insat 3E & Intelsat 702
+S56E    Bonum 1
 S57E    NSS 703
 S60E    Intelsat 904
 S62E    Intelsat 902
 S64E    Intelsat 906 
 S66E    Intelsat 704
 S68.5E  PAS 7/10
+S70.5E  Eutelsat W5
 S72E    PAS 4 
-S74E    Insat 3C
+
+# Asia
+
+S74E    Insat 3C & Edusat
 S75E    LMI 1
-S76.5E  Apstar
+S76.5E  Telstar 10
 S78.5E  Thaicom 2/3
-S80E    Express 6A
-S83E    Insat 2E/3B
+S80E    Express AM2
+S83E    Insat 2E/3B/4A
+S85.2E  Intelsat 709
+S87.5E  Chinastar 1
+S88E    ST 1
+S90E    Yamal 201
+S91.5E  Measat 1
+S93.5E  Insat 3A
+S95E    NSS 6
+S96.5E  Express AM 11  
 S100.5E Asiasat 2
+S103E   Express A2
 S105.5E Asiasat 3S
-S113E   Palapa C2
+S107.7E Cakrawarta 1
+S108E   Telkom 1 & AAP 1
+S110E   N-Sat 110 & BSAT 1A/2A
+S110.5E Sinosat 1
+S113E   Palapa C2 & Koreasat 2
+S116E   Koreasat 3
+S118E   Telkom 2
+S120E   Thaicom 1A
+S122.2E Asiasat 4
+S124E   JCSAT 4a
+S128E   JCSAT 3
+S132E   N-Star A
+S134E   Apstar 6
+S136E   N-Star B
+S138E   Telstar 18
+S140E   Express AM 3
+S144E   Superbird C
+S146E   Agila 2
+S148E   Measat 2
+S150E   JCSAT R
 S152E   Optus B3
+S154E   JCSAT 2A
 S156E   Optus C1
+S158E   Superbird A
 S160E   Optus B1
+S162E   Superbird B2
+S164E   Optus A3
 S166E   PAS 8
 S169E   PAS 2
+S172E   AMC 23
 S180E   Intelsat 701
+S177W   NSS 5
 
-S1W     Thor 2/3 & Intelsat 707
-S4W     Amos 1
-S5W     Telecom 2C & Atlantic Bird 3
+# Atlantic
+
+S1W     Thor 2/3 & Intelsat 10-02
+S4W     Amos 1/2
+S5W     Atlantic Bird 3
 S7W     Nilesat 101 & 102
-S8W     Telecom 2A/2D & Atlantic Bird 2
-S11W    Express 3A
-S12.5W  Eutelsat II F2
-S14W    Gorizont 26
+S8W     Telecom 2D & Atlantic Bird 2
+S11W    Express A3
+S12.5W  Atlantic Bird 2
+S14W    Express A4
 S15W    Telstar 12
 S18W    Intelsat 901
-S21.5W  NSS 7
-S27.5W  Intelsat 605
-S30W    Hispasat 1
+S20W    Intelsat 603
+S22W    NSS 7
+S24.5W  Intelsat 905
+S27.5W  Intelsat 907
+S30W    Hispasat 1C/1D
 S31.5W  Intelsat 801
 S34.5W  Intelsat 903
-S37.5W  Telstar 11
+S37.5W  Telstar 11 & AMC 12
 S40.5W  NSS 806
-S43W    PAS 3R/6/6B
-S45W    PAS 1/5R
-S47W    TDRS 6
-S53W    Intelsat 706
+S43W    PAS 3R/6B
+S45W    PAS 1R
+S50W    Intelsat 705
+S53W    Intelsat 707
 S55.5W  Intelsat 805
 S58W    PAS 9
-S61.5W  Echostar 3
+S61W    Amazonas
+
+# America
+
+S61.5W  Echostar 3 & Rainbow 1
+S63W    Estrelo de Sul 1
+S65W    Brasilsat B2
+S70W    Brasilsat B1
+S72W    Nahuel 1 & AMC 6
+S72.5W  DirecTV 1
+S74W    SBS 6
+S77W    Echostar 4
 S79W    AMC5
+S79.5W  Nimiq 3
 S82W    Nimiq 2
-S85W    AMC2
+S83W    AMC 9
+S84W    Brasilsat B3
+S85W    AMC 2
+S85.1W  XM 3
 S87W    AMC3
-S89W    Intelsat 808
-S91W    Galaxy 11 & Nimiq 1/3
-S93W    Intelsat 806
+S89W    Intelsat Americas 8
+S91W    Galaxy 11 & Nimiq 1
+S91.5W  DirecTV 2
+S92W    Brasilsat B4
+S93W    Intelsat Americas 6
 S95W    Galaxy 3C
-S97W    Telestar 5
+S97W    Intelsat Americas 5
 S99W    Galaxy 4R
-S101W   AMC4
+S99.2W  Spaceway 2
+S101W   DirecTV 1R/4S/8 & AMC4
 S103W   AMC1
 S105W   AMC15
-S110W   Echostar 6/8
-S119W   Echostar 7
-S121W   Echostar 9 & Intelsat 813
+S107.3W Anik F1/F1R
+S110W   DirecTV 5 & Echostar 6/8
+A111.1W Anik F2
+S113W   Solidaridad 2
+S119W   Echostar 7 & DirecTV 7S
+S121W   Echostar 9 & Intelsat Americas 13
 S123W   Galaxy 10R
-S129W   Intelsat 807
+S125W   Galaxy 14
+S127W   Galaxy 13/Horizons 1
+S129W   Echostar 5 & Intelsat Americas 7
+S131W   AMC 11
+S133W   Galaxy15/1R
+S135W   AMC 10
+S137W   AMC 7
+S138.5W Echostar 10
+S139W   AMC 8
 S148W   Echostar 1/2
-S157W   Echostar 4
 
 # Cable
 
diff -ruN vdr-1.3.44/spu.c vdr-1.3.45/spu.c
--- vdr-1.3.44/spu.c	2002-09-08 16:17:41.000000000 +0200
+++ vdr-1.3.45/spu.c	2006-03-26 16:07:59.000000000 +0200
@@ -6,11 +6,11 @@
  * This code is distributed under the terms and conditions of the
  * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
  *
- * $Id: spu.c 1.1 2002/09/08 14:17:41 kls Exp $
+ * $Id: spu.c 1.2 2006/03/26 14:07:59 kls Exp $
  */
 
-#include <inttypes.h>
 #include "spu.h"
+#include <inttypes.h>
 
 // -- cSpuDecoder ----------------
 /*
diff -ruN vdr-1.3.44/svdrp.c vdr-1.3.45/svdrp.c
--- vdr-1.3.44/svdrp.c	2006-01-14 17:08:20.000000000 +0100
+++ vdr-1.3.45/svdrp.c	2006-03-26 11:14:13.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.93 2006/01/14 16:08:20 kls Exp $
+ * $Id: svdrp.c 1.94 2006/03/26 09:14:13 kls Exp $
  */
 
 #include "svdrp.h"
@@ -461,7 +461,7 @@
              q += sprintf(q, "%*s", -MAXHELPTOPIC, topic);
           }
       x = 0;
-      Reply(-214, buffer);
+      Reply(-214, "%s", buffer);
       }
 }
 
@@ -782,7 +782,7 @@
            cBase64Encoder Base64(Image, ImageSize);
            const char *s;
            while ((s = Base64.NextLine()) != NULL)
-                 Reply(-216, s);
+                 Reply(-216, "%s", s);
            Reply(216, "Grabbed image %s", Option);
            }
         free(Image);
@@ -799,7 +799,7 @@
   if (*Option) {
      const char *hp = GetHelpPage(Option, HelpPages);
      if (hp)
-        Reply(214, hp);
+        Reply(214, "%s", hp);
      else {
         Reply(504, "HELP topic \"%s\" unknown", Option);
         return;
@@ -1332,7 +1332,7 @@
            if (*cmd && *option) {
               const char *hp = GetHelpPage(option, plugin->SVDRPHelpPages());
               if (hp) {
-                 Reply(-214, hp);
+                 Reply(-214, "%s", hp);
                  Reply(214, "End of HELP info");
                  }
               else
@@ -1358,7 +1358,7 @@
            int ReplyCode = 900;
            cString s = plugin->SVDRPCommand(cmd, option, ReplyCode);
            if (s)
-              Reply(abs(ReplyCode), *s);
+              Reply(abs(ReplyCode), "%s", *s);
            else
               Reply(500, "Command unrecognized: \"%s\"", cmd);
            }
@@ -1380,7 +1380,7 @@
 {
   delete PUTEhandler;
   PUTEhandler = new cPUTEhandler;
-  Reply(PUTEhandler->Status(), PUTEhandler->Message());
+  Reply(PUTEhandler->Status(), "%s", PUTEhandler->Message());
   if (PUTEhandler->Status() != 354)
      DELETENULL(PUTEhandler);
 }
@@ -1467,7 +1467,7 @@
   // handle PUTE data:
   if (PUTEhandler) {
      if (!PUTEhandler->Process(Cmd)) {
-        Reply(PUTEhandler->Status(), PUTEhandler->Message());
+        Reply(PUTEhandler->Status(), "%s", PUTEhandler->Message());
         DELETENULL(PUTEhandler);
         }
      return;
diff -ruN vdr-1.3.44/thread.c vdr-1.3.45/thread.c
--- vdr-1.3.44/thread.c	2006-02-12 13:24:39.000000000 +0100
+++ vdr-1.3.45/thread.c	2006-03-26 11:22:27.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.53 2006/02/12 12:24:39 kls Exp $
+ * $Id: thread.c 1.54 2006/03/26 09:22:27 kls Exp $
  */
 
 #include "thread.h"
@@ -208,7 +208,8 @@
   childTid = 0;
   childThreadId = 0;
   description = NULL;
-  SetDescription(Description);
+  if (Description)
+     SetDescription("%s", Description);
 }
 
 cThread::~cThread()
diff -ruN vdr-1.3.44/timers.c vdr-1.3.45/timers.c
--- vdr-1.3.44/timers.c	2006-02-26 11:50:47.000000000 +0100
+++ vdr-1.3.45/timers.c	2006-03-26 16:08:57.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: timers.c 1.50 2006/02/26 10:50:47 kls Exp $
+ * $Id: timers.c 1.55 2006/03/26 14:08:57 kls Exp $
  */
 
 #include "timers.h"
@@ -12,6 +12,7 @@
 #include "channels.h"
 #include "device.h"
 #include "i18n.h"
+#include "libsi/si.h"
 #include "remote.h"
 
 // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
@@ -120,7 +121,7 @@
 cString cTimer::ToDescr(void) const
 {
   char *buffer;
-  asprintf(&buffer, "%d (%d %04d-%04d '%s')", Index() + 1, Channel()->Number(), start, stop, file);
+  asprintf(&buffer, "%d (%d %04d-%04d %s'%s')", Index() + 1, Channel()->Number(), start, stop, HasFlags(tfVps) ? "VPS " : "", file);
   return cString(buffer, true);
 }
 
@@ -409,7 +410,13 @@
 
 bool cTimer::Expired(void) const
 {
-  return IsSingleEvent() && !Recording() && StopTime() + EXPIRELATENCY <= time(NULL);
+  if (IsSingleEvent() && !Recording() && StopTime() + EXPIRELATENCY <= time(NULL)) {
+     if (HasFlags(tfVps) && event && event->Vps())
+        return event->RunningStatus() == SI::RunningStatusNotRunning;
+     else
+        return true;
+     }
+  return false;
 }
 
 time_t cTimer::StartTime(void) const
@@ -426,7 +433,10 @@
   return stopTime;
 }
 
-#define EPGLIMITPAST   (2 * 3600) // time in seconds in the past within which EPG events will be taken into consideration
+#define EPGLIMITBEFORE   (1 * 3600) // Time in seconds before a timer's start time and
+#define EPGLIMITAFTER    (1 * 3600) // after its stop time within which EPG events will be taken into consideration.
+#define VPSLIMITBEFORE   (2 * 3600) // Same for VPS timers, which need to
+#define VPSLIMITAFTER   (24 * 3600) // look further into the future to catch shifted broadcasts.
 
 void cTimer::SetEventFromSchedule(const cSchedules *Schedules)
 {
@@ -438,14 +448,25 @@
      }
   const cSchedule *Schedule = Schedules->GetSchedule(Channel());
   if (Schedule) {
+     time_t now = time(NULL);
      if (!lastSetEvent || Schedule->Modified() >= lastSetEvent) {
         const cEvent *Event = NULL;
         int Overlap = 0;
         int Distance = INT_MIN;
-        time_t now = time(NULL);
+        bool UseVps = HasFlags(tfVps);
+        const cEvent *PresentEvent = UseVps ? Schedule->GetPresentEvent() : NULL;
+        const cEvent *FollowingEvent = UseVps ? Schedule->GetFollowingEvent() : NULL;
+        // Set up the time frame within which to check events:
+        Matches(0, true);
+        time_t TimeFrameBegin = StartTime() - (UseVps ? VPSLIMITBEFORE : EPGLIMITBEFORE);
+        time_t TimeFrameEnd   = StopTime()  + (UseVps ? VPSLIMITAFTER  : EPGLIMITAFTER);
         for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) {
-            if (e->EndTime() < now - EPGLIMITPAST)
-               continue; // skip old events
+            if (!UseVps || e != event && e != PresentEvent && e != FollowingEvent) { // always check these if this is a VPS timer
+               if (e->EndTime() < TimeFrameBegin)
+                  continue; // skip events way before the timer starts
+               if (e->StartTime() > TimeFrameEnd)
+                  break; // the rest is way after the timer ends
+               }
             int overlap = 0;
             Matches(e, &overlap);
             if (overlap && overlap >= Overlap) {
@@ -470,20 +491,16 @@
         if (Event && Event->EndTime() < now - EXPIRELATENCY && Overlap > FULLMATCH && !Event->IsRunning())
            Event = NULL;
         SetEvent(Event);
+        lastSetEvent = now;
         }
      }
-  lastSetEvent = time(NULL);
 }
 
 void cTimer::SetEvent(const cEvent *Event)
 {
   if (event != Event) { //XXX TODO check event data, too???
-     if (Event) {
-        char vpsbuf[64] = "";
-        if (Event->Vps())
-           sprintf(vpsbuf, "(VPS: %s) ", *Event->GetVpsString());
-        isyslog("timer %s set to event %s %s-%s %s'%s'", *ToDescr(), *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString(), vpsbuf, Event->Title());
-        }
+     if (Event)
+        isyslog("timer %s set to event %s", *ToDescr(), *Event->ToDescr());
      else
         isyslog("timer %s set to no event", *ToDescr());
      event = Event;
@@ -568,6 +585,7 @@
   state = 0;
   beingEdited = 0;;
   lastSetEvents = 0;
+  lastDeleteExpired = 0;
 }
 
 cTimer *cTimers::GetTimer(cTimer *Timer)
@@ -663,6 +681,8 @@
 
 void cTimers::DeleteExpired(void)
 {
+  if (time(NULL) - lastDeleteExpired < 30)
+     return;
   cTimer *ti = First();
   while (ti) {
         cTimer *next = Next(ti);
@@ -673,4 +693,5 @@
            }
         ti = next;
         }
+  lastDeleteExpired = time(NULL);
 }
diff -ruN vdr-1.3.44/timers.h vdr-1.3.45/timers.h
--- vdr-1.3.44/timers.h	2006-02-25 16:05:09.000000000 +0100
+++ vdr-1.3.45/timers.h	2006-03-26 12:44:01.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: timers.h 1.26 2006/02/25 15:05:09 kls Exp $
+ * $Id: timers.h 1.27 2006/03/26 10:44:01 kls Exp $
  */
 
 #ifndef __TIMERS_H
@@ -101,6 +101,7 @@
   int state;
   int beingEdited;
   time_t lastSetEvents;
+  time_t lastDeleteExpired;
 public:
   cTimers(void);
   cTimer *GetTimer(cTimer *Timer);
diff -ruN vdr-1.3.44/tools.c vdr-1.3.45/tools.c
--- vdr-1.3.44/tools.c	2006-02-05 12:05:56.000000000 +0100
+++ vdr-1.3.45/tools.c	2006-03-19 13:28:16.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: tools.c 1.114 2006/02/05 11:05:56 kls Exp $
+ * $Id: tools.c 1.115 2006/03/19 12:28:16 kls Exp $
  */
 
 #include "tools.h"
@@ -829,8 +829,14 @@
   int n = getline(&buffer, &size, f);
   if (n > 0) {
      n--;
-     if (buffer[n] == '\n')
+     if (buffer[n] == '\n') {
         buffer[n] = 0;
+        if (n > 0) {
+           n--;
+           if (buffer[n] == '\r')
+              buffer[n] = 0;
+           }
+        }
      return buffer;
      }
   return NULL;
diff -ruN vdr-1.3.44/vdr.5 vdr-1.3.45/vdr.5
--- vdr-1.3.44/vdr.5	2006-02-26 15:10:00.000000000 +0100
+++ vdr-1.3.45/vdr.5	2006-03-26 15:42:29.000000000 +0200
@@ -8,9 +8,9 @@
 .\" License as specified in the file COPYING that comes with the
 .\" vdr distribution.
 .\"
-.\" $Id: vdr.5 1.54 2006/02/26 14:10:00 kls Exp $
+.\" $Id: vdr.5 1.55 2006/03/26 13:42:29 kls Exp $
 .\"
-.TH vdr 5 "19 Feb 2006" "1.3.43" "Video Disk Recorder Files"
+.TH vdr 5 "26 Mar 2006" "1.3.45" "Video Disk Recorder Files"
 .SH NAME
 vdr file formats - the Video Disk Recorder Files
 .SH DESCRIPTION
@@ -636,7 +636,7 @@
 <start time>   @is the time (as a time_t integer) in UTC when this event starts
 <duration>     @is the time (in seconds) that this event will take
 <table id>     @is a hex number that indicates the table this event is contained in (if this is left empty or 0 this event will not be overwritten or modified by data that comes from the DVB stream)
-<version>      @is a hex number that indicates the event's version number inside its table (optional, only processed for table IDs smaller than 0x50)
+<version>      @is a hex number that indicates the event's version number inside its table (optional, ignored when reading EPG data)
 <title>        @is the title of the event
 <short text>   @is the short text of the event (typically the name of the episode etc.)
 <description>  @is the description of the event (any '|' characters will be interpreted as newlines)
diff -ruN vdr-1.3.44/vdr.c vdr-1.3.45/vdr.c
--- vdr-1.3.44/vdr.c	2006-02-05 13:57:10.000000000 +0100
+++ vdr-1.3.45/vdr.c	2006-03-26 11:16:53.000000000 +0200
@@ -22,7 +22,7 @@
  *
  * The project's page is at http://www.cadsoft.de/vdr
  *
- * $Id: vdr.c 1.249 2006/02/05 12:57:10 kls Exp $
+ * $Id: vdr.c 1.251 2006/03/26 09:16:53 kls Exp $
  */
 
 #include <getopt.h>
@@ -1067,7 +1067,7 @@
                     }
                  if (UserShutdown && Next && Delta <= Setup.MinEventTimeout * 60 && !ForceShutdown) {
                     char *buf;
-                    asprintf(&buf, tr("Recording in %d minutes, shut down anyway?"), Delta / 60);
+                    asprintf(&buf, tr("Recording in %ld minutes, shut down anyway?"), Delta / 60);
                     if (Interface->Confirm(buf))
                        ForceShutdown = true;
                     else
@@ -1090,13 +1090,16 @@
                        isyslog("executing '%s'", cmd);
                        SystemExec(cmd);
                        free(cmd);
+                       LastActivity = time(NULL) - Setup.MinUserInactivity * 60 + SHUTDOWNRETRY; // try again later
                        }
-                    else if (WatchdogTimeout > 0) {
-                       alarm(WatchdogTimeout);
-                       if (signal(SIGALRM, Watchdog) == SIG_IGN)
-                          signal(SIGALRM, SIG_IGN);
-                       }
-                    LastActivity = time(NULL) - Setup.MinUserInactivity * 60 + SHUTDOWNRETRY; // try again later
+                    else {
+                      LastActivity = Now;
+                      if (WatchdogTimeout > 0) {
+                         alarm(WatchdogTimeout);
+                         if (signal(SIGALRM, Watchdog) == SIG_IGN)
+                            signal(SIGALRM, SIG_IGN);
+                         }
+                      }
                     UserShutdown = false;
                     continue; // skip the rest of the housekeeping for now
                     }
