diff -ruN vdr-1.4.0/CONTRIBUTORS vdr-1.4.1/CONTRIBUTORS
--- vdr-1.4.0/CONTRIBUTORS	2006-04-29 15:23:15.000000000 +0200
+++ vdr-1.4.1/CONTRIBUTORS	2006-06-11 11:13:20.000000000 +0200
@@ -218,6 +218,7 @@
  for suggesting that the SVDRP command GRAB should allow file names without extension
  again
  for reporting a problem with channel up/down switching on single card systems
+ for fixing the PremiereContentTransmissionDescriptor in 'libsi'
 
 Ulrich Röder <roeder@efr-net.de>
  for pointing out that there are channels that have a symbol rate higher than 27500
@@ -274,6 +275,7 @@
  for pointing out a problem with the ERR macro defined by ncurses.h
  for a patch that contained a fix for checking toFile in cCuttingThread::Action()
  for improving cUnbufferedFile
+ for fixing calculating the cache size in cUnbufferedFile::Read()
 
 Werner Fink <werner@suse.de>
  for making I/O more robust by handling EINTR
@@ -309,6 +311,8 @@
  and firmware can handle live DD without the need of a Transfer Mode
  for fixing cDvbDevice::SetAudioBypass() in case setTransferModeForDolbyDigital is
  false
+ for a patch that was used as a base to fix handling Transfer Mode when replaying
+ Dolby Digital audio and the option '-a' was given
 
 Rolf Hakenes <hakenes@hippomi.de>
  for providing 'libdtv' and adapting the EIT mechanisms to it
@@ -442,6 +446,9 @@
  for making the "Play" key in live viewing mode resume a previous replay session
  for suggesting to allow defining key macros for all non-modeless keys
  for reporting a bug in entering '0' in a cMenuEditIntItem
+ for reporting that moving channels sometimes stopped the current replay session
+ for reporting a problem with deleting channels in case the current channel's
+ number changes
 
 Michael Rakowski <mrak@gmx.de>
  for translating OSD texts to the Polish language
@@ -538,6 +545,7 @@
 
 Joerg Riechardt <J.Riechardt@gmx.de>
  for filling in some missing teletext PIDs
+ for improving the repeat function for LIRC remote controls
 
 Holger Wächtler <holger@qanu.de>
  for some valuable advice during adapting to the NEWSTRUCT driver
@@ -563,6 +571,9 @@
  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
+ for reporting a problem with the "Press any key on the RC unit" step when learning
+ LIRC remote control codes
+ for suggesting to reduce the logging for the SVDRP GRAB command
 
 Jeremy Hall <jhall@UU.NET>
  for fixing an incomplete initialization of the filter parameters in eit.c
@@ -1271,6 +1282,8 @@
  for reporting a spelling error in 'canceling'
  for adding some 'mkdir -p' to the Makefile's 'install' target
  for reporting some missing braces in remux.c
+ for suggesting to modifiy the Makefile to copy and clean up additional libraries
+ a plugin might provide
 
 Marco Schlüßler <marco@lordzodiac.de>
  for fixing handling colors in cDvbSpuPalette::yuv2rgb()
@@ -1422,6 +1435,11 @@
  for providing a shorter version of the 'sed' expression for extracting APIVERSION
  for fixing a bug in handling the "Power" key in case a recording is going on and
  no plugin is active
+ for suggesting to add 'eval' to the $VDRCMD call in 'runvdr' to avoid problems with
+ quoting
+ for fixing handling the "Power" key in case a timer is about to start recording
+ for fixing calculating the start time of repeated timers with "first day"
+ for setting a timer's cached start time to 0 after a call to Skip()
 
 Sven Kreiensen <svenk@kammer.uni-hannover.de>
  for his help in keeping 'channels.conf.terr' up to date
@@ -1581,6 +1599,8 @@
  for reporting an obsolete entry 'S21.5E' in the default 'diseqc.conf'
  for updating the GPL copies
  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
 
 Steffen Beyer <cpunk@reactor.de>
  for fixing setting the colored button help after deleting a recording in case the next
@@ -1677,6 +1697,7 @@
  for reporting that a menu was automatically closed when a replay ends
  for suggesting to ignore k_Repeat when deciding whether the same key has been
  pressed in string input fields
+ for fixing missing ',' in the Italian and Polish OSD texts
 
 Patrick Rother <krd-vdr@gulu.net>
  for reporting a bug in defining timers that only differ in the day of week
@@ -1750,6 +1771,7 @@
  for his idea of going directly into the "Edit timer" menu for a timer created
  from the "Schedule" menu in case it starts withing the next two minutes
  for reporting a problem with a format string in recording.c on 64bit systems
+ for reporting a problem with the device selection in case of timer conflicts
 
 Thiemo Gehrke <tgehrke@reel-multimedia.com>
  for suggesting to add a setup option to turn off the automatic timeout of the
@@ -1828,8 +1850,10 @@
  font if set to '3' - even if it would have been a fixed font
  for reporting a bug in initializing 'noapiv' in the Makefile
 
-Bárta Vladimír <vladimir.barta@k2atmitec.cz>
+Vladimír Bárta <vladimir.barta@k2atmitec.cz>
  for translating OSD texts to the Czech language
+ for fixing the character 'r' in fontosd and fontsml for iso8859-2
+ for fixing the character #207 in fontosd for iso8859-2
 
 Christoph Haubrich <christoph1.haubrich@arcor.de>
  for making the "Ok" key in the "Jump" mode of the replay progress display confirm
@@ -1865,6 +1889,7 @@
  for suggesting to use geteuid() to check whether VDR is running as user 'root'
  for fixing a memory leak in handling external EPG data
  for fixing a memory leak in closing the video file during replay
+ for fixing deleting the 'skinDescriptions' in cMenuSetupOSD::~cMenuSetupOSD()
 
 Helge Lenz <h.lenz@gmx.de>
  for reporting a bug in setting the 'Delta' parameter when calling the shutdown
@@ -1894,3 +1919,12 @@
 Dominique Simon <d.simon@gmx.net>
  for reporting a bug in handling the "Power" key in case a recording is going on and
  no plugin is active
+
+M. Kiesel <vdr@continuity.cjb.net>
+ for reporting that the 'runvdr' script still used DVBDIR
+
+Prakash Punnoor <prakash@punnoor.de>
+ for suggesting to remove -fPIC from VDR's and libsi's Makefile
+
+Anssi Hannula <anssi.hannula@gmail.com>
+ for a patch that was used to implement processing the "frequency list descriptor"
diff -ruN vdr-1.4.0/HISTORY vdr-1.4.1/HISTORY
--- vdr-1.4.0/HISTORY	2006-04-30 10:51:32.000000000 +0200
+++ vdr-1.4.1/HISTORY	2006-06-11 11:14:22.000000000 +0200
@@ -4283,7 +4283,7 @@
 - Speeded up cVideoRepacker (thanks to Reinhard Nissl).
 - Added an 'Id' parameter to cDevice::PlayAudio() to allow plugins to easier
   process the audio data (thanks to Marco Schlüßler).
-- Added Czech language texts (thanks to Bárta Vladimír).
+- Added Czech language texts (thanks to Vladimír Bárta).
   Plugin authors may want to add the new entries to their I18N texts and contact
   the translators to have their texts translated. Note that there are now 21
   different OSD languages, so please make sure you have 21 versions for each of
@@ -4687,3 +4687,98 @@
 - Fixed a memory leak in closing the video file during replay (thanks to Tobias Grimm).
 - Updated the Italian OSD texts (thanks to Nino Gerbino and Antonio Ospite).
 - Updated the Estonian OSD texts (thanks to Arthur Konovalov).
+
+2006-05-14: Version 1.4.0-1
+
+- Updated 'S110W' in 'sources.conf'.
+- Adjusted the 'runvdr' script so that the user can fill in the functions to
+  detect, load and unload the necessary driver modules (thanks to M. Kiesel for
+  reporting that it still used DVBDIR).
+- Added 'eval' to the $VDRCMD call in 'runvdr' to avoid problems with quoting
+  (suggested by Udo Richter).
+- Fixed missing ',' in the Italian and Polish OSD texts (thanks to Marko Mäkelä).
+- Updated the Czech OSD texts (thanks to Vladimír Bárta).
+- Fixed handling the "Power" key in case a timer is about to start recording
+  (thanks to Udo Richter).
+- Fixed the character 'r' in fontosd and fontsml for iso8859-2 (thanks to Vladimír
+  Bárta).
+- When checking whether a VPS timer has entered the "VPS margin", the event's start
+  time is now used instead of the timer's start time, because otherwise events that
+  start way off of their VPS time wouldn't be recorded correctly.
+- If VPS timers are active, their events are now being kept up to date if there
+  are any free devices available.
+- Fixed the character #207 in fontosd for iso8859-2 (thanks to Vladimír Bárta).
+- Fixed handling unknown codes when learning LIRC remote control codes (reported
+  by Helmut Auer).
+- Since some channels (especially the Austrian ORF) randomly change the ids of their
+  EPG events, VDR now gives the start time precedence when searching for existing
+  events.
+- Fixed automatically updating the CAM menu in case the whole operation (for
+  instance a firmware update) takes longer than the menu timeout.
+
+2006-05-28: Version 1.4.0-2
+
+- Removed leftover LSMOD=... line from 'runvdr'.
+- Modified the Makefile to copy additional libraries a plugin might provide (suggested
+  by Wayne Keer). See PLUGINS.html for details.
+- Fixed handling Transfer Mode when replaying Dolby Digital audio and the option
+  '-a' was given (based on a patch from Werner Fink). To avoid having to increment
+  the API version, several #if checks have been introduced around this. These will
+  be removed once the API version actually needs to be incremented.
+- Fixed deleting the 'skinDescriptions' in cMenuSetupOSD::~cMenuSetupOSD() (thanks
+  to Tobias Grimm).
+- Fixed calculating the start time of repeated timers with "first day" (thanks to
+  Udo Richter).
+- Now setting a timer's cached start time to 0 after a call to Skip() (thanks to
+  Udo Richter).
+- Fixed handling the running status of EPG events in case the "Schedule" menu is
+  currently open (i.e. a write lock on the schedules data can't be achieved).
+- Fixed handling VPS timers in case the EPG event hasn't been 'seen' in a while.
+- Fixed calculating the cache size in cUnbufferedFile::Read() (thanks to Artur Skawina).
+- Removed -fPIC from VDR's and libsi's Makefile (suggested by Prakash Punnoor).
+- Modifed the device selection to better handle timer conflicts (reported by
+  Christian Wieninger).
+- Avoiding a compiler warning in libsi's TypeLoop::operator[].
+- Now processing the "frequency list descriptor" (based on a patch from Anssi Hannula).
+- Improved the repeat function for LIRC remote controls (thanks to Joerg Riechardt).
+- Fixed moving channels, which sometimes stopped the current replay session
+  (reported by Mirko Dölle).
+- Fixed deleting channels in case the current channel's number changes (reported
+  by Mirko Dölle).
+
+2006-06-04: Version 1.4.0-3
+
+- Fixed the PremiereContentTransmissionDescriptor in 'libsi' (thanks to Stefan
+  Huelswitt).
+- Removed all the compatibility '#if APIVERSNUM...' stuff and instead increased
+  the API version number - plugins will have to be recompiled.
+- Removed the call to pthread_setschedparam(childTid, SCHED_RR, 0) in thread.c,
+  because it caused a compiler warning with post-2.4 glibc (reported by Ville Skyttä).
+  Since the third parameter has to be non-null to have any effect, the call was
+  presumably a NOP, anyway.
+- Fixed the 'clean-plugins' target in the Makefile to also remove additional
+  plugin libraries (thanks to Wayne Keer).
+- Applied the fixes to moving and deleting channels from version 1.4.0-2 to the
+  SVDRP commands MOVC and DELC as well.
+- Fixed handling the display of the '*' indicator in the "What's on now/next?"
+  menu, so that events that haven't been "seen" in the data stream within 30
+  seconds won't be shown as "running".
+- Fixed handling tabbed item display in 'skincurses'.
+- Increased the column spacing in the "Recordings" menu (was too small for the
+  'skincurses' plugin).
+- When the 'skincurses' plugin is loaded, it automatically sets the 'curses'
+  skin as the current one. This doesn't modify the Setup.OSDSkin parameter, so
+  that after using 'skincurses' (for instance for debugging) the previously
+  selected skin will be used again.
+- Added some log messages when setting the current skin.
+- Only making a second attempt to set the current skin at startup if the first
+  attempt has failed.
+- Now switching to non-VPS timers' channels 60 seconds before the timer starts
+  (if a free device is available), to allow for the updating of EPG data and CA
+  descriptors before the actual recording starts.
+
+2006-06-11: Version 1.4.1
+
+- Changed the log messages when grabbing an image from 'isyslog()' to 'dsyslog()'
+  so that they can be suppressed in normal operation mode to avoid clogging the
+  log file in case this function is used frequently (suggested by Helmut Auer).
diff -ruN vdr-1.4.0/INSTALL vdr-1.4.1/INSTALL
--- vdr-1.4.0/INSTALL	2006-04-28 15:07:14.000000000 +0200
+++ vdr-1.4.1/INSTALL	2006-05-01 15:35:40.000000000 +0200
@@ -133,6 +133,9 @@
 VDR will go into 'daemon' mode and the initial program call will return
 immediately! 'runvdr' needs to be started as user 'root'. Use the '-u'
 option to run the actual 'vdr' program under a different user id.
+Note that the 'runvdr' script needs to be adjusted to your particular
+requirements before you can actually use it. See the comments inside
+the script for more information.
 
 Setting the system time:
 ------------------------
diff -ruN vdr-1.4.0/Make.config.template vdr-1.4.1/Make.config.template
--- vdr-1.4.0/Make.config.template	2006-04-15 14:28:03.000000000 +0200
+++ vdr-1.4.1/Make.config.template	2006-05-26 12:41:46.000000000 +0200
@@ -6,15 +6,15 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: Make.config.template 1.8 2006/04/15 12:28:03 kls Exp $
+# $Id: Make.config.template 1.9 2006/05/26 10:41:46 kls Exp $
 
 ### The C compiler and options:
 
 CC       = gcc
-CFLAGS   = -O2
+CFLAGS   = -g -O2 -Wall
 
 CXX      = g++
-CXXFLAGS = -fPIC -g -O2 -Wall -Woverloaded-virtual
+CXXFLAGS = -g -O2 -Wall -Woverloaded-virtual
 
 ### The directory environment:
 
diff -ruN vdr-1.4.0/Makefile vdr-1.4.1/Makefile
--- vdr-1.4.0/Makefile	2006-04-24 19:18:06.000000000 +0200
+++ vdr-1.4.1/Makefile	2006-06-02 16:45:33.000000000 +0200
@@ -4,15 +4,15 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: Makefile 1.91 2006/04/24 17:18:06 kls Exp $
+# $Id: Makefile 1.94 2006/06/02 14:45:33 kls Exp $
 
 .DELETE_ON_ERROR:
 
 CC       ?= gcc
-CFLAGS   ?= -O2
+CFLAGS   ?= -g -O2 -Wall
 
 CXX      ?= g++
-CXXFLAGS ?= -fPIC -g -O2 -Wall -Woverloaded-virtual
+CXXFLAGS ?= -g -O2 -Wall -Woverloaded-virtual
 
 LSIDIR   = ./libsi
 MANDIR   = /usr/local/man
@@ -191,7 +191,7 @@
 
 clean-plugins:
 	@for i in `ls $(PLUGINDIR)/src | grep -v '[^a-z0-9]'`; do $(MAKE) -C "$(PLUGINDIR)/src/$$i" clean; done
-	@-rm -f $(PLUGINDIR)/lib/libvdr-*.so.$(APIVERSION)
+	@-rm -f $(PLUGINDIR)/lib/lib*-*.so.$(APIVERSION)
 
 # Install the files:
 
@@ -223,7 +223,7 @@
 
 install-plugins: plugins
 	@mkdir -p $(PLUGINLIBDIR)
-	@cp $(PLUGINDIR)/lib/libvdr-*.so.$(APIVERSION) $(PLUGINLIBDIR)
+	@cp $(PLUGINDIR)/lib/lib*-*.so.$(APIVERSION) $(PLUGINLIBDIR)
 
 # Source documentation:
 
diff -ruN vdr-1.4.0/PLUGINS/src/skincurses/HISTORY vdr-1.4.1/PLUGINS/src/skincurses/HISTORY
--- vdr-1.4.0/PLUGINS/src/skincurses/HISTORY	2006-04-14 13:36:41.000000000 +0200
+++ vdr-1.4.1/PLUGINS/src/skincurses/HISTORY	2006-06-03 16:31:33.000000000 +0200
@@ -29,3 +29,9 @@
 2006-04-14: Version 0.0.6
 
 - Added a missing "Key$" in skincurses.c.
+
+2006-06-03: Version 0.0.7
+
+- Fixed handling tabbed item display.
+- When the 'skincurses' plugin is loaded, it automatically sets the 'curses'
+  skin as the current one.
diff -ruN vdr-1.4.0/PLUGINS/src/skincurses/skincurses.c vdr-1.4.1/PLUGINS/src/skincurses/skincurses.c
--- vdr-1.4.0/PLUGINS/src/skincurses/skincurses.c	2006-04-14 13:35:59.000000000 +0200
+++ vdr-1.4.1/PLUGINS/src/skincurses/skincurses.c	2006-06-03 16:20:39.000000000 +0200
@@ -3,7 +3,7 @@
  *
  * See the README file for copyright information and how to reach the author.
  *
- * $Id: skincurses.c 1.8 2006/04/14 11:35:59 kls Exp $
+ * $Id: skincurses.c 1.10 2006/06/03 14:20:39 kls Exp $
  */
 
 #include <ncurses.h>
@@ -11,7 +11,7 @@
 #include <vdr/plugin.h>
 #include <vdr/skins.h>
 
-static const char *VERSION        = "0.0.6";
+static const char *VERSION        = "0.0.7";
 static const char *DESCRIPTION    = "A text only skin";
 static const char *MAINMENUENTRY  = NULL;
 
@@ -277,6 +277,7 @@
   virtual void SetEvent(const cEvent *Event);
   virtual void SetRecording(const cRecording *Recording);
   virtual void SetText(const char *Text, bool FixedFont);
+  virtual const cFont *GetTextAreaFont(bool FixedFont) const { return &Font; }
   virtual void Flush(void);
   };
 
@@ -366,13 +367,13 @@
   for (int i = 0; i < MaxTabs; i++) {
       const char *s = GetTabbedText(Text, i);
       if (s) {
-         int xt = Tab(i);
+         int xt = Tab(i) / 12;// Tab() is in "pixel" - see also skins.c!!!
          osd->DrawText(xt, y, s, ColorFg, ColorBg, &Font, OsdWidth - xt);
          }
       if (!Tab(i + 1))
          break;
       }
-  SetEditableWidth(OsdWidth - Tab(1));
+  SetEditableWidth(OsdWidth - Tab(1) / 12); // Tab() is in "pixel" - see also skins.c!!!
 }
 
 void cSkinCursesDisplayMenu::SetEvent(const cEvent *Event)
@@ -786,7 +787,9 @@
 bool cPluginSkinCurses::Start(void)
 {
   // Start any background activities the plugin shall perform.
-  new cSkinCurses;
+  cSkin *Skin = new cSkinCurses;
+  // This skin is normally used for debugging, so let's make it the current one:
+  Skins.SetCurrent(Skin->Name());
   return true;
 }
 
diff -ruN vdr-1.4.0/PLUGINS.html vdr-1.4.1/PLUGINS.html
--- vdr-1.4.0/PLUGINS.html	2006-04-28 15:05:28.000000000 +0200
+++ vdr-1.4.1/PLUGINS.html	2006-05-19 14:11:36.000000000 +0200
@@ -6,7 +6,7 @@
 
 <center><h1>The VDR Plugin System</h1></center>
 
-<center><b>Version 1.4</b></center>
+<center><b>Version 1.4.1</b></center>
 <p>
 <center>
 Copyright &copy; 2006 Klaus Schmidinger<br>
@@ -192,6 +192,16 @@
 should lead to the current version of the plugin you want to use. This way you can
 have several different versions of a plugin source (like <tt>hello-0.0.1</tt> and
 <tt>hello-0.0.2</tt>) and define which one to actually use through the symbolic link.
+<p>
+If a plugin needs library files of its own, it can copy them to the <tt>lib</tt>
+directory following the naming convention <tt>lib<i>name</i>-<i>library</i>.so.0.0.1</tt>,
+where <i>name</i> is the name of the plugin, and <i>library</i> identifies the
+plugin's additional library. If the plugin <tt>hello</tt> would require the two
+additional libraries <tt>foo</tt> and <tt>bar</tt>, the  names would be
+<p>
+<tt>libhello-foo.so.0.0.1</tt><br>
+<tt>libhello-bar.so.0.0.1</tt>
+<p>
 
 <a name="Initializing a new plugin directory"><hr><h2>Initializing a new plugin directory</h2>
 
diff -ruN vdr-1.4.0/audio.c vdr-1.4.1/audio.c
--- vdr-1.4.0/audio.c	2005-02-12 13:40:51.000000000 +0100
+++ vdr-1.4.1/audio.c	2006-05-28 17:03:24.000000000 +0200
@@ -4,11 +4,12 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: audio.c 1.3 2005/02/12 12:40:51 kls Exp $
+ * $Id: audio.c 1.5 2006/05/28 15:03:24 kls Exp $
  */
 
 #include "audio.h"
-#include "stdlib.h"
+#include <stdlib.h>
+#include "dvbdevice.h"
 
 // --- cAudio ----------------------------------------------------------------
 
@@ -61,6 +62,7 @@
   if (command && !mute) {
      if (pipe || pipe.Open(command, "w")) {
         if (0x80 <= Id && Id <= 0x87 || Id == 0xBD) { // AC3
+           cDvbDevice::SetTransferModeForDolbyDigital(2);
            int written = Data[8] + 9; // skips the PES header
            if (Id != 0xBD)
               written += 4; // skips AC3 bytes
diff -ruN vdr-1.4.0/channels.c vdr-1.4.1/channels.c
--- vdr-1.4.0/channels.c	2006-04-17 14:18:57.000000000 +0200
+++ vdr-1.4.1/channels.c	2006-05-28 17:03:40.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: channels.c 1.51 2006/04/17 12:18:57 kls Exp $
+ * $Id: channels.c 1.53 2006/05/28 15:03:40 kls Exp $
  */
 
 #include "channels.h"
@@ -925,6 +925,14 @@
   return channel ? Idx : -1;
 }
 
+int cChannels::GetPrevNormal(int Idx)
+{
+  cChannel *channel = Get(--Idx);
+  while (channel && channel->GroupSep())
+        channel = Get(--Idx);
+  return channel ? Idx : -1;
+}
+
 void cChannels::ReNumber( void )
 {
   channelsHashSid.Clear();
diff -ruN vdr-1.4.0/channels.h vdr-1.4.1/channels.h
--- vdr-1.4.0/channels.h	2006-02-28 14:52:49.000000000 +0100
+++ vdr-1.4.1/channels.h	2006-05-28 17:03:56.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: channels.h 1.40 2006/02/28 13:52:49 kls Exp $
+ * $Id: channels.h 1.42 2006/05/28 15:03:56 kls Exp $
  */
 
 #ifndef __CHANNELS_H
@@ -233,6 +233,7 @@
   int GetNextGroup(int Idx);   // Get next channel group
   int GetPrevGroup(int Idx);   // Get previous channel group
   int GetNextNormal(int Idx);  // Get next normal channel (not group)
+  int GetPrevNormal(int Idx);  // Get previous normal channel (not group)
   void ReNumber(void);         // Recalculate 'number' based on channel type
   cChannel *GetByNumber(int Number, int SkipGap = 0);
   cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID);
diff -ruN vdr-1.4.0/config.h vdr-1.4.1/config.h
--- vdr-1.4.0/config.h	2006-04-29 11:24:07.000000000 +0200
+++ vdr-1.4.1/config.h	2006-06-11 10:57:35.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.255 2006/04/29 09:24:07 kls Exp $
+ * $Id: config.h 1.260 2006/06/11 08:57:35 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -21,13 +21,13 @@
 
 // VDR's own version number:
 
-#define VDRVERSION  "1.4.0"
-#define VDRVERSNUM   10400  // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION  "1.4.1"
+#define VDRVERSNUM   10401  // Version * 10000 + Major * 100 + Minor
 
 // The plugin API's version number:
 
-#define APIVERSION  "1.4.0"
-#define APIVERSNUM   10400  // Version * 10000 + Major * 100 + Minor
+#define APIVERSION  "1.4.1"
+#define APIVERSNUM   10401  // Version * 10000 + Major * 100 + Minor
 
 // When loading plugins, VDR searches them by their APIVERSION, which
 // may be smaller than VDRVERSION in case there have been no changes to
diff -ruN vdr-1.4.0/device.c vdr-1.4.1/device.c
--- vdr-1.4.0/device.c	2006-04-14 16:34:43.000000000 +0200
+++ vdr-1.4.1/device.c	2006-05-27 13:14:42.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.128 2006/04/14 14:34:43 kls Exp $
+ * $Id: device.c 1.130 2006/05/27 11:14:42 kls Exp $
  */
 
 #include "device.h"
@@ -281,32 +281,20 @@
 cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
 {
   cDevice *d = NULL;
-  int select = INT_MAX;
-
+  uint Impact = 0xFFFFFFFF;
   for (int i = 0; i < numDevices; i++) {
       bool ndr;
       if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
-         int pri;
-         if (device[i]->Receiving() && !ndr)
-            pri = 0; // receiving and allows additional receivers
-         else if (!device[i]->Receiving(true) && d && device[i]->ProvidesCa(Channel) < d->ProvidesCa(Channel))
-            pri = 1; // free and fewer Ca's
-         else if (!device[i]->Receiving() && !device[i]->HasDecoder())
-            pri = 2; // free and not a full featured card
-         else if (!device[i]->Receiving() && device[i] != ActualDevice())
-            pri = 3; // free and not the actual device
-         else if (!device[i]->Receiving() && !device[i]->IsPrimaryDevice())
-            pri = 4; // free and not the primary device
-         else if (!device[i]->Receiving())
-            pri = 5; // free
-         else if (d && device[i]->Priority() < d->Priority())
-            pri = 6; // receiving but priority is lower
-         else if (d && device[i]->Priority() == d->Priority() && device[i]->ProvidesCa(Channel) < d->ProvidesCa(Channel))
-            pri = 7; // receiving with same priority but fewer Ca's
-         else
-            pri = 8; // all others
-         if (pri <= select) {
-            select = pri;
+         uint imp = 0;
+         imp <<= 1; imp |= !device[i]->Receiving() || ndr;
+         imp <<= 1; imp |= device[i]->Receiving();
+         imp <<= 1; imp |= device[i] == ActualDevice();
+         imp <<= 1; imp |= device[i]->IsPrimaryDevice();
+         imp <<= 1; imp |= device[i]->HasDecoder();
+         imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF);
+         imp <<= 8; imp |= min(max(device[i]->ProvidesCa(Channel), 0), 0xFF);
+         if (imp < Impact) {
+            Impact = imp;
             d = device[i];
             if (NeedsDetachReceivers)
                *NeedsDetachReceivers = ndr;
@@ -613,7 +601,7 @@
      StopReplay();
 
   // If this card is switched to an other transponder, any receivers still
-  // attached to it ineed to be automatically detached:
+  // attached to it need to be automatically detached:
   bool NeedsDetachReceivers = false;
 
   // If this card can't receive this channel, we must not actually switch
diff -ruN vdr-1.4.0/device.h vdr-1.4.1/device.h
--- vdr-1.4.0/device.h	2006-04-14 16:35:13.000000000 +0200
+++ vdr-1.4.1/device.h	2006-05-28 17:04:24.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.75 2006/04/14 14:35:13 kls Exp $
+ * $Id: device.h 1.78 2006/05/28 15:04:24 kls Exp $
  */
 
 #ifndef __DEVICE_H
@@ -169,7 +169,7 @@
   int CardIndex(void) const { return cardIndex; }
          ///< Returns the card index of this device (0 ... MAXDEVICES - 1).
   int DeviceNumber(void) const;
-         ///< Returns the number of this device (0 ... MAXDEVICES - 1).
+         ///< Returns the number of this device (0 ... numDevices).
   virtual int ProvidesCa(const cChannel *Channel) const;
          ///< Checks whether this device provides the conditional access
          ///< facilities to decrypt the given Channel.
@@ -239,6 +239,10 @@
 public:
   static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
          ///< Returns the number of the current channel on the primary device.
+  static void SetCurrentChannel(const cChannel *Channel) { currentChannel = Channel ? Channel->Number() : 0; }
+         ///< Sets the number of the current channel on the primary device, without
+         ///< actually switching to it. This can be used to correct the current
+         ///< channel number while replaying.
   void ForceTransferMode(void);
          ///< Forces the device into transfermode for the current channel.
   virtual bool HasLock(int TimeoutMs = 0);//XXX PLUGINS.html
diff -ruN vdr-1.4.0/dvbdevice.c vdr-1.4.1/dvbdevice.c
--- vdr-1.4.0/dvbdevice.c	2006-04-01 16:19:43.000000000 +0200
+++ vdr-1.4.1/dvbdevice.c	2006-06-11 11:03:55.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.156 2006/04/01 14:19:43 kls Exp $
+ * $Id: dvbdevice.c 1.159 2006/06/11 09:03:55 kls Exp $
  */
 
 #include "dvbdevice.h"
@@ -356,7 +356,7 @@
 // --- cDvbDevice ------------------------------------------------------------
 
 int cDvbDevice::devVideoOffset = -1;
-bool cDvbDevice::setTransferModeForDolbyDigital = true;
+int cDvbDevice::setTransferModeForDolbyDigital = 1;
 
 cDvbDevice::cDvbDevice(int n)
 {
@@ -570,7 +570,7 @@
                  if (Quality < 0)
                     Quality = 100;
 
-                 isyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, vm.width, vm.height);
+                 dsyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, vm.width, vm.height);
                  if (Jpeg) {
                     // convert to JPEG:
                     result = RgbToJpeg(mem, vm.width, vm.height, Size, Quality);
@@ -653,7 +653,7 @@
 
 bool cDvbDevice::SetAudioBypass(bool On)
 {
-  if (!setTransferModeForDolbyDigital)
+  if (setTransferModeForDolbyDigital != 1)
      return false;
   return ioctl(fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0;
 }
@@ -914,9 +914,9 @@
      }
 }
 
-void cDvbDevice::SetTransferModeForDolbyDigital(bool On)
+void cDvbDevice::SetTransferModeForDolbyDigital(int Mode)
 {
-  setTransferModeForDolbyDigital = On;
+  setTransferModeForDolbyDigital = Mode;
 }
 
 void cDvbDevice::SetAudioTrackDevice(eTrackType Type)
@@ -932,7 +932,7 @@
            }
         }
      else if (IS_DOLBY_TRACK(Type)) {
-        if (!setTransferModeForDolbyDigital)
+        if (setTransferModeForDolbyDigital == 0)
            return;
         // Currently this works only in Transfer Mode
         ForceTransferMode();
diff -ruN vdr-1.4.0/dvbdevice.h vdr-1.4.1/dvbdevice.h
--- vdr-1.4.0/dvbdevice.h	2006-04-01 16:18:59.000000000 +0200
+++ vdr-1.4.1/dvbdevice.h	2006-05-28 17:05:19.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: dvbdevice.h 1.39 2006/04/01 14:18:59 kls Exp $
+ * $Id: dvbdevice.h 1.41 2006/05/28 15:05:19 kls Exp $
  */
 
 #ifndef __DVBDEVICE_H
@@ -104,14 +104,19 @@
 
 private:
   bool digitalAudio;
-  static bool setTransferModeForDolbyDigital;
+  static int setTransferModeForDolbyDigital;
 protected:
   virtual int GetAudioChannelDevice(void);
   virtual void SetAudioChannelDevice(int AudioChannel);
   virtual void SetVolumeDevice(int Volume);
   virtual void SetDigitalAudioDevice(bool On);
 public:
-  static void SetTransferModeForDolbyDigital(bool On);
+  static void SetTransferModeForDolbyDigital(int Mode);
+         ///< Controls how the DVB device handles Transfer Mode when replaying
+         ///< Dolby Digital audio.
+         ///< 0 = don't set "audio bypass" in driver/firmware, don't force Transfer Mode
+         ///< 1 = set "audio bypass" in driver/firmware, force Transfer Mode (default)
+         ///< 2 = don't set "audio bypass" in driver/firmware, force Transfer Mode
 
 // Player facilities
 
diff -ruN vdr-1.4.0/eit.c vdr-1.4.1/eit.c
--- vdr-1.4.0/eit.c	2006-04-29 13:38:37.000000000 +0200
+++ vdr-1.4.1/eit.c	2006-05-25 16:35:19.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.117 2006/04/29 11:38:37 kls Exp $
+ * $Id: eit.c 1.118 2006/05/25 14:35:19 kls Exp $
  */
 
 #include "eit.h"
@@ -21,10 +21,10 @@
 
 class cEIT : public SI::EIT {
 public:
-  cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data);
+  cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bool OnlyRunningStatus = false);
   };
 
-cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data)
+cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bool OnlyRunningStatus)
 :SI::EIT(Data, false)
 {
   if (!CheckCRCAndParse())
@@ -57,6 +57,8 @@
       cEvent *rEvent = NULL;
       cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), SiEitEvent.getStartTime());
       if (!pEvent) {
+         if (OnlyRunningStatus)
+            continue;
          // If we don't have that event yet, we create a new one.
          // Otherwise we copy the information into the existing event anyway, because the data might have changed.
          pEvent = newEvent = new cEvent(SiEitEvent.getEventId());
@@ -92,6 +94,12 @@
          pEvent->SetStartTime(SiEitEvent.getStartTime());
          pEvent->SetDuration(SiEitEvent.getDuration());
          }
+      if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
+         if (SiEitEvent.getRunningStatus() >= SI::RunningStatusNotRunning)
+            pSchedule->SetRunningStatus(pEvent, SiEitEvent.getRunningStatus(), channel);
+         }
+      if (OnlyRunningStatus)
+         continue; // do this before setting the version, so that the full update can be done later
       pEvent->SetVersion(getVersionNumber());
 
       int LanguagePreferenceShort = -1;
@@ -240,15 +248,13 @@
       pEvent->FixEpgBugs();
       if (LinkChannels)
          channel->SetLinkChannels(LinkChannels);
-      if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
-         if (SiEitEvent.getRunningStatus() >= SI::RunningStatusNotRunning)
-            pSchedule->SetRunningStatus(pEvent, SiEitEvent.getRunningStatus(), channel);
-         }
       Modified = true;
       }
   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 (Modified) {
@@ -312,6 +318,16 @@
          cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
          if (Schedules)
             cEIT EIT(Schedules, Source(), Tid, Data);
+         else {
+            // If we don't get a write lock, let's at least get a read lock, so
+            // that we can set the running status and 'seen' timestamp (well, actually
+            // with a read lock we shouldn't be doing that, but it's only integers that
+            // get changed, so it should be ok)
+            cSchedulesLock SchedulesLock;
+            cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
+            if (Schedules)
+               cEIT EIT(Schedules, Source(), Tid, Data, true);
+            }
          }
          break;
     case 0x14: {
diff -ruN vdr-1.4.0/epg.c vdr-1.4.1/epg.c
--- vdr-1.4.0/epg.c	2006-04-22 14:02:47.000000000 +0200
+++ vdr-1.4.1/epg.c	2006-05-25 16:55:36.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.72 2006/04/22 12:02:47 kls Exp $
+ * $Id: epg.c 1.75 2006/05/25 14:55:36 kls Exp $
  */
 
 #include "epg.h"
@@ -227,7 +227,7 @@
 
 bool cEvent::IsRunning(bool OrAboutToStart) const
 {
-  return SeenWithin(RUNNINGSTATUSTIMEOUT) && runningStatus >= (OrAboutToStart ? SI::RunningStatusStartsInAFewSeconds : SI::RunningStatusPausing);
+  return runningStatus >= (OrAboutToStart ? SI::RunningStatusStartsInAFewSeconds : SI::RunningStatusPausing);
 }
 
 cString cEvent::GetDateString(void) const
@@ -327,8 +327,10 @@
                              cEvent *newEvent = NULL;
                              if (Event)
                                 DELETENULL(Event->components);
-                             if (!Event)
+                             if (!Event) {
                                 Event = newEvent = new cEvent(EventID);
+                                Event->seen = 0;
+                                }
                              if (Event) {
                                 Event->SetTableID(TableID);
                                 Event->SetStartTime(StartTime);
@@ -710,12 +712,12 @@
 
 const cEvent *cSchedule::GetEvent(tEventID EventID, time_t StartTime) const
 {
-  // Returns either the event info with the given EventID or, if that one can't
-  // be found, the one with the given StartTime (or NULL if neither can be found)
-  cEvent *pt = eventsHashID.Get(EventID);
-  if (!pt && StartTime > 0) // 'StartTime < 0' is apparently used with NVOD channels
-     pt = eventsHashStartTime.Get(StartTime);
-  return pt;
+  // Returns the event info with the given StartTime or, if no actual StartTime
+  // is given, the one with the given EventID.
+  if (StartTime > 0) // 'StartTime < 0' is apparently used with NVOD channels
+     return eventsHashStartTime.Get(StartTime);
+  else
+     return eventsHashID.Get(EventID);
 }
 
 const cEvent *cSchedule::GetEventAround(time_t Time) const
diff -ruN vdr-1.4.0/fontosd-iso8859-2.c vdr-1.4.1/fontosd-iso8859-2.c
--- vdr-1.4.0/fontosd-iso8859-2.c	2006-02-05 14:50:05.000000000 +0100
+++ vdr-1.4.1/fontosd-iso8859-2.c	2006-05-07 13:36:15.000000000 +0200
@@ -2471,34 +2471,34 @@
      0x0000000C,  // .........**..
   },
   {             // 114
-     10, 27,
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x000000CE,  // ..**..***.
-     0x000000FE,  // ..*******.
-     0x000000E0,  // ..***.....
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x000000C0,  // ..**......
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
-     0x00000000,  // ..........
+     8, 27,
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x0000000E,  // ....***.
+     0x0000003E,  // ..*****.
+     0x00000038,  // ..***...
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000030,  // ..**....
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
+     0x00000000,  // ........
   },
   {             // 115
      12, 27,
@@ -5261,34 +5261,34 @@
      0x00000000,  // ........
   },
   {             // 207
-     6, 27,
-     0x00000000,  // ......
-     0x00000033,  // **..**
-     0x00000033,  // **..**
-     0x00000033,  // **..**
-     0x00000000,  // ......
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x0000000C,  // ..**..
-     0x00000000,  // ......
-     0x00000000,  // ......
-     0x00000000,  // ......
-     0x00000000,  // ......
-     0x00000000,  // ......
+     17, 27,
+     0x00001860,  // ....**....**.....
+     0x00000CC0,  // .....**..**......
+     0x00000780,  // ......****.......
+     0x00000300,  // .......**........
+     0x00000000,  // .................
+     0x00007FC0,  // ..*********......
+     0x00007FF0,  // ..***********....
+     0x00006078,  // ..**......****...
+     0x00006018,  // ..**........**...
+     0x00006018,  // ..**........**...
+     0x0000600C,  // ..**.........**..
+     0x0000600C,  // ..**.........**..
+     0x0000600C,  // ..**.........**..
+     0x0000600C,  // ..**.........**..
+     0x0000600C,  // ..**.........**..
+     0x0000600C,  // ..**.........**..
+     0x0000600C,  // ..**.........**..
+     0x00006018,  // ..**........**...
+     0x00006018,  // ..**........**...
+     0x00006070,  // ..**......***....
+     0x00007FF0,  // ..***********....
+     0x00007FC0,  // ..*********......
+     0x00000000,  // .................
+     0x00000000,  // .................
+     0x00000000,  // .................
+     0x00000000,  // .................
+     0x00000000,  // .................
   },
   {             // 208 iso8859-2
      17, 27,
diff -ruN vdr-1.4.0/fontsml-iso8859-2.c vdr-1.4.1/fontsml-iso8859-2.c
--- vdr-1.4.0/fontsml-iso8859-2.c	2006-02-05 14:50:14.000000000 +0100
+++ vdr-1.4.1/fontsml-iso8859-2.c	2006-05-04 19:57:09.000000000 +0200
@@ -2132,30 +2132,30 @@
      0x00000006,  // ........**.
   },
   {             // 114
-     9, 23,
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x000000CC,  // .**..**..
-     0x000000F8,  // .*****...
-     0x000000E0,  // .***.....
-     0x000000C0,  // .**......
-     0x000000C0,  // .**......
-     0x000000C0,  // .**......
-     0x000000C0,  // .**......
-     0x000000C0,  // .**......
-     0x000000C0,  // .**......
-     0x000000C0,  // .**......
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
-     0x00000000,  // .........
+     6, 23,
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x0000001B,  // .**.**
+     0x0000001B,  // .**.**
+     0x0000001C,  // .***..
+     0x00000018,  // .**...
+     0x00000018,  // .**...
+     0x00000018,  // .**...
+     0x00000018,  // .**...
+     0x00000018,  // .**...
+     0x00000018,  // .**...
+     0x00000018,  // .**...
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
+     0x00000000,  // ......
   },
   {             // 115
      9, 23,
diff -ruN vdr-1.4.0/i18n.c vdr-1.4.1/i18n.c
--- vdr-1.4.0/i18n.c	2006-04-30 10:51:10.000000000 +0200
+++ vdr-1.4.1/i18n.c	2006-05-05 15:26:09.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.279 2006/04/30 08:51:10 kls Exp $
+ * $Id: i18n.c 1.281 2006/05/05 13:26:09 kls Exp $
  *
  * Translations provided by:
  *
@@ -484,7 +484,7 @@
   { "This event - all channels",
     "Diese Sendung - alle Kanäle",
     "Ta oddaja - vsi kanali",
-    "Questo evento - tutti i canali"
+    "Questo evento - tutti i canali",
     "",//TODO
     "",//TODO
     "Cet événement - toutes les chaînes",
@@ -1703,7 +1703,7 @@
     "Aucun cryptage",
     "",//TODO
     "vapaa",
-    "nieszyfrowany"
+    "nieszyfrowany",
     "en abierto",
     "",//TODO
     "Okodad",
@@ -2310,7 +2310,7 @@
     "",//TODO
     "VPS salvestamine tulekul!",
     "VPS optagelse starter snart!",
-    "",//TODO
+    "Brzo zaène nahrávání VPS!",
   },
   { "No free DVB device to record!",
     "Keine freie DVB-Karte zum Aufnehmen!",
@@ -3764,7 +3764,7 @@
     "",// TODO
     "ainult PID-id",
     "kun PIDs",
-    "",// TODO
+    "jen PIDs",
   },
   { "names and PIDs",
     "Namen und PIDs",
@@ -4490,7 +4490,7 @@
     "",// TODO
     "Kanal käivitamisel",
     "Kanal ved opstart",
-    "",// TODO
+    "Kanál po spu¹tìní",
   },
   { "Setup.Miscellaneous$Initial volume",
     "Lautstärke beim Einschalten",
@@ -4512,7 +4512,7 @@
     "",// TODO
     "Helitugevus käivitamisel",
     "Lydstyrke ved opstart",
-    "",// TODO
+    "Hlasitost po spu¹tìní",
   },
   { "Setup.Miscellaneous$as before",
     "wie vorher",
@@ -4534,7 +4534,7 @@
     "",// TODO
     "nagu enne",
     "som før",
-    "",// TODO
+    "jako naposledy",
   },
   // The days of the week:
   { "MTWTFSS",
@@ -5353,7 +5353,7 @@
     "",// TODO
     "Järgmine",
     "Fremad",
-    "",// TODO
+    "Dále",
   },
   { "Key$Prev",
     "Zurück",
@@ -5375,7 +5375,7 @@
     "",// TODO
     "Eelmine",
     "Tilbage",
-    "",// TODO
+    "Zpìt",
   },
   { "Key$Power",
     "Ausschalten",
@@ -5463,7 +5463,7 @@
     "",// TODO
     "Eelmine kanal",
     "Foregående kanal",
-    "",// TODO
+    "Pøedcházející kanál",
   },
   { "Key$Volume+",
     "Lautstärke+",
diff -ruN vdr-1.4.0/libsi/Makefile vdr-1.4.1/libsi/Makefile
--- vdr-1.4.0/libsi/Makefile	2005-05-29 13:47:12.000000000 +0200
+++ vdr-1.4.1/libsi/Makefile	2006-05-26 12:40:19.000000000 +0200
@@ -1,12 +1,12 @@
 #
 # Makefile for a libsi
 #
-# $Id: Makefile 1.5 2005/05/29 11:47:12 kls Exp $
+# $Id: Makefile 1.6 2006/05/26 10:40:19 kls Exp $
 
 ### The C++ compiler and options:
 
 CXX      ?= g++
-CXXFLAGS ?= -fPIC -O2 -g -Wall -Woverloaded-virtual
+CXXFLAGS ?= -O2 -g -Wall -Woverloaded-virtual
 AR = ar
 ARFLAGS = ru
 RANLIB = ranlib
diff -ruN vdr-1.4.0/libsi/descriptor.c vdr-1.4.1/libsi/descriptor.c
--- vdr-1.4.0/libsi/descriptor.c	2006-04-17 14:19:15.000000000 +0200
+++ vdr-1.4.1/libsi/descriptor.c	2006-05-28 16:25:30.000000000 +0200
@@ -6,7 +6,7 @@
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   (at your option) any later version.                                   *
  *                                                                         *
- *   $Id: descriptor.c 1.20 2006/04/17 12:19:15 kls Exp $
+ *   $Id: descriptor.c 1.21 2006/05/28 14:25:30 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -806,21 +806,34 @@
    return HILO(s->service_id);
 }
 
-int PremiereContentTransmissionDescriptor::getMJD() const {
+void PremiereContentTransmissionDescriptor::Parse() {
+   s=data.getData<const descr_premiere_content_transmission>();
+   startDayLoop.setData(data+sizeof(descr_premiere_content_transmission), getLength()-sizeof(descr_premiere_content_transmission));
+}
+
+int PremiereContentTransmissionDescriptor::StartDayEntry::getMJD() const {
    return HILO(s->mjd);
 }
 
-void PremiereContentTransmissionDescriptor::Parse() {
-   s=data.getData<const descr_premiere_content_transmission>();
-   startTimeLoop.setData(data+sizeof(descr_premiere_content_transmission), getLength()-sizeof(descr_premiere_content_transmission));
+int PremiereContentTransmissionDescriptor::StartDayEntry::getLoopLength() const {
+   return s->start_time_loop;
+}
+
+int PremiereContentTransmissionDescriptor::StartDayEntry::getLength() {
+   return sizeof(item_premiere_content_transmission_day)+getLoopLength();
+}
+
+void PremiereContentTransmissionDescriptor::StartDayEntry::Parse() {
+   s=data.getData<const item_premiere_content_transmission_day>();
+   startTimeLoop.setData(data+sizeof(item_premiere_content_transmission_day), getLoopLength());
 }
 
-time_t PremiereContentTransmissionDescriptor::StartTimeEntry::getStartTime(int mjd) const {
+time_t PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry::getStartTime(int mjd) const {
    return DVBTime::getTime(mjd >> 8, mjd & 0xff, s->start_time_h, s->start_time_m, s->start_time_s);
 }
 
-void PremiereContentTransmissionDescriptor::StartTimeEntry::Parse() {
-   s=data.getData<const item_premiere_content_transmission_reference>();
+void PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry::Parse() {
+   s=data.getData<const item_premiere_content_transmission_time>();
 }
 
 void ApplicationSignallingDescriptor::Parse() {
diff -ruN vdr-1.4.0/libsi/descriptor.h vdr-1.4.1/libsi/descriptor.h
--- vdr-1.4.0/libsi/descriptor.h	2006-04-14 12:53:44.000000000 +0200
+++ vdr-1.4.1/libsi/descriptor.h	2006-05-28 16:25:30.000000000 +0200
@@ -6,7 +6,7 @@
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   (at your option) any later version.                                   *
  *                                                                         *
- *   $Id: descriptor.h 1.14 2006/04/14 10:53:44 kls Exp $
+ *   $Id: descriptor.h 1.15 2006/05/28 14:25:30 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -490,20 +490,30 @@
 
 class PremiereContentTransmissionDescriptor : public Descriptor {
 public:
-   class StartTimeEntry : public LoopElement {
+   class StartDayEntry : public LoopElement {
    public:
-      virtual int getLength() { return sizeof(item_premiere_content_transmission_reference); }
-      time_t getStartTime(int mjd) const; //UTC
+      class StartTimeEntry : public LoopElement {
+      public:
+         virtual int getLength() { return sizeof(item_premiere_content_transmission_time); }
+         time_t getStartTime(int mjd) const; //UTC
+      protected:
+         virtual void Parse();
+      private:
+         const item_premiere_content_transmission_time *s;
+      };
+      StructureLoop<StartTimeEntry> startTimeLoop;
+      virtual int getLength();
+      int getMJD() const;
+      int getLoopLength() const;
    protected:
       virtual void Parse();
    private:
-      const item_premiere_content_transmission_reference *s;
+      const item_premiere_content_transmission_day *s;
    };
-   StructureLoop<StartTimeEntry> startTimeLoop;
+   StructureLoop<StartDayEntry> startDayLoop;
    int getOriginalNetworkId() const;
    int getTransportStreamId() const;
    int getServiceId() const;
-   int getMJD() const;
 protected:
    virtual void Parse();
 private:
diff -ruN vdr-1.4.0/libsi/headers.h vdr-1.4.1/libsi/headers.h
--- vdr-1.4.0/libsi/headers.h	2006-04-14 12:53:44.000000000 +0200
+++ vdr-1.4.1/libsi/headers.h	2006-05-28 16:25:30.000000000 +0200
@@ -10,7 +10,7 @@
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   (at your option) any later version.                                   *
  *                                                                         *
- *   $Id: headers.h 1.6 2006/04/14 10:53:44 kls Exp $
+ *   $Id: headers.h 1.7 2006/05/28 14:25:30 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -1790,7 +1790,7 @@
 // 0xF2  Content Transmission Descriptor
 // http://dvbsnoop.sourceforge.net/examples/example-private-section.html
 
-#define DESCR_PREMIERE_CONTENT_TRANSMISSION_LEN 11
+#define DESCR_PREMIERE_CONTENT_TRANSMISSION_LEN 8
 
 struct descr_premiere_content_transmission {
    u_char descriptor_tag                         :8;
@@ -1801,14 +1801,19 @@
    u_char original_network_id_lo                 :8;
    u_char service_id_hi                          :8;
    u_char service_id_lo                          :8;
+};
+
+#define ITEM_PREMIERE_CONTENT_TRANSMISSION_DAY_LEN 3
+
+struct item_premiere_content_transmission_day {
    u_char mjd_hi                                 :8;
    u_char mjd_lo                                 :8;
    u_char start_time_loop                        :8;
 };
 
-#define ITEM_PREMIERE_CONTENT_TRANSMISSION_LEN 3
+#define ITEM_PREMIERE_CONTENT_TRANSMISSION_TIME_LEN 3
 
-struct item_premiere_content_transmission_reference {
+struct item_premiere_content_transmission_time {
    u_char start_time_h                           :8;
    u_char start_time_m                           :8;
    u_char start_time_s                           :8;
diff -ruN vdr-1.4.0/libsi/si.h vdr-1.4.1/libsi/si.h
--- vdr-1.4.0/libsi/si.h	2006-04-14 12:53:44.000000000 +0200
+++ vdr-1.4.1/libsi/si.h	2006-05-27 15:07:20.000000000 +0200
@@ -6,7 +6,7 @@
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   (at your option) any later version.                                   *
  *                                                                         *
- *   $Id: si.h 1.14 2006/04/14 10:53:44 kls Exp $
+ *   $Id: si.h 1.15 2006/05/27 13:07:20 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -399,6 +399,7 @@
          case 8:
             return (SixtyFourBit(data.FourBytes(index)) << 32) | data.FourBytes(index+4);
          }
+         return 0; // just to avoid a compiler warning
       }
    T getNext(Iterator &it) const
       {
diff -ruN vdr-1.4.0/lirc.c vdr-1.4.1/lirc.c
--- vdr-1.4.0/lirc.c	2006-01-27 16:59:47.000000000 +0100
+++ vdr-1.4.1/lirc.c	2006-05-28 10:48:13.000000000 +0200
@@ -6,16 +6,16 @@
  *
  * LIRC support added by Carsten Koch <Carsten.Koch@icem.de>  2000-06-16.
  *
- * $Id: lirc.c 1.14 2006/01/27 15:59:47 kls Exp $
+ * $Id: lirc.c 1.15 2006/05/28 08:48:13 kls Exp $
  */
 
 #include "lirc.h"
 #include <netinet/in.h>
 #include <sys/socket.h>
 
-#define REPEATLIMIT  20 // ms
 #define REPEATDELAY 350 // ms
-#define KEYPRESSDELAY 150 // ms
+#define REPEATFREQ 100 // ms
+#define REPEATTIMEOUT 500 // ms
 #define RECONNECTDELAY 3000 // ms
 
 cLircRemote::cLircRemote(const char *DeviceName)
@@ -94,7 +94,7 @@
               continue;
               }
            if (count == 0) {
-              if (strcmp(KeyName, LastKeyName) == 0 && FirstTime.Elapsed() < KEYPRESSDELAY)
+              if (strcmp(KeyName, LastKeyName) == 0 && FirstTime.Elapsed() < REPEATDELAY)
                  continue; // skip keys coming in too fast
               if (repeat)
                  Put(LastKeyName, false, true);
@@ -104,8 +104,10 @@
               timeout = -1;
               }
            else {
+              if (LastTime.Elapsed() < REPEATFREQ)
+                 continue; // repeat function kicks in after a short delay (after last key instead of first key)
               if (FirstTime.Elapsed() < REPEATDELAY)
-                 continue; // repeat function kicks in after a short delay
+                 continue; // skip keys coming in too fast (for count != 0 as well)
               repeat = true;
               timeout = REPEATDELAY;
               }
@@ -113,7 +115,7 @@
            Put(KeyName, repeat);
            }
         else if (repeat) { // the last one was a repeat, so let's generate a release
-           if (LastTime.Elapsed() >= REPEATDELAY) {
+           if (LastTime.Elapsed() >= REPEATTIMEOUT) {
               Put(LastKeyName, false, true);
               repeat = false;
               *LastKeyName = 0;
diff -ruN vdr-1.4.0/menu.c vdr-1.4.1/menu.c
--- vdr-1.4.0/menu.c	2006-04-28 14:48:01.000000000 +0200
+++ vdr-1.4.1/menu.c	2006-06-03 15:32:42.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.435 2006/04/28 12:48:01 kls Exp $
+ * $Id: menu.c 1.441 2006/06/03 13:32:42 kls Exp $
  */
 
 #include "menu.h"
@@ -499,6 +499,8 @@
 eOSState cMenuChannels::Delete(void)
 {
   if (!HasSubMenu() && Count() > 0) {
+     int CurrentChannelNr = cDevice::CurrentChannel();
+     cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
      int Index = Current();
      cChannel *channel = GetChannel(Current());
      int DeletedChannel = channel->Number();
@@ -508,10 +510,23 @@
         return osContinue;
         }
      if (Interface->Confirm(tr("Delete channel?"))) {
+        if (CurrentChannel && channel == CurrentChannel) {
+           int n = Channels.GetNextNormal(CurrentChannel->Index());
+           if (n < 0)
+              n = Channels.GetPrevNormal(CurrentChannel->Index());
+           CurrentChannel = Channels.Get(n);
+           CurrentChannelNr = 0; // triggers channel switch below
+           }
         Channels.Del(channel);
         cOsdMenu::Del(Index);
         Propagate();
         isyslog("channel %d deleted", DeletedChannel);
+        if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
+           if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
+              Channels.SwitchTo(CurrentChannel->Number());
+           else
+              cDevice::SetCurrentChannel(CurrentChannel);
+           }
         }
      }
   return osContinue;
@@ -530,8 +545,12 @@
      cOsdMenu::Move(From, To);
      Propagate();
      isyslog("channel %d moved to %d", FromNumber, ToNumber);
-     if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr)
-        Channels.SwitchTo(CurrentChannel->Number());
+     if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
+        if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
+           Channels.SwitchTo(CurrentChannel->Number());
+        else
+           cDevice::SetCurrentChannel(CurrentChannel);
+        }
      }
 }
 
@@ -1029,7 +1048,7 @@
      char *buffer = NULL;
      char t = TimerMatchChars[timerMatch];
      char v = event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' ';
-     char r = event->IsRunning() ? '*' : ' ';
+     char r = event->SeenWithin(30) && event->IsRunning() ? '*' : ' ';
      if (channel && withDate)
         asprintf(&buffer, "%d\t%.*s\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), 6, channel->ShortName(true), 6, *event->GetDateString(), *event->GetTimeString(), t, v, r, event->Title());
      else if (channel)
@@ -1828,7 +1847,7 @@
 // --- cMenuRecordings -------------------------------------------------------
 
 cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
-:cOsdMenu(Base ? Base : tr("Recordings"), 8, 6)
+:cOsdMenu(Base ? Base : tr("Recordings"), 9, 7)
 {
   base = Base ? strdup(Base) : NULL;
   level = Setup.RecordingDirs ? Level : -1;
@@ -2131,7 +2150,7 @@
 cMenuSetupOSD::~cMenuSetupOSD()
 {
   cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
-  delete skinDescriptions;
+  delete[] skinDescriptions;
 }
 
 void cMenuSetupOSD::Set(void)
diff -ruN vdr-1.4.0/menuitems.c vdr-1.4.1/menuitems.c
--- vdr-1.4.0/menuitems.c	2006-04-25 17:59:02.000000000 +0200
+++ vdr-1.4.1/menuitems.c	2006-06-03 15:20:01.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.44 2006/04/25 15:59:02 kls Exp $
+ * $Id: menuitems.c 1.45 2006/06/03 13:20:01 kls Exp $
  */
 
 #include "menuitems.h"
@@ -296,7 +296,10 @@
   char buf[1000];
 
   if (InEditMode()) {
-     const cFont *font = cFont::GetFont(fontOsd);
+     // This is an ugly hack to make editing strings work with the 'skincurses' plugin.
+     const cFont *font = dynamic_cast<cSkinDisplayMenu *>(cSkinDisplay::Current())->GetTextAreaFont(false);
+     if (!font || font->Width("W") != 1) // all characters have with == 1 in the font used by 'skincurses'
+        font = cFont::GetFont(fontOsd);
      strncpy(buf, value, pos);
      snprintf(buf + pos, sizeof(buf) - pos - 2, insert && newchar ? "[]%c%s" : "[%c]%s", *(value + pos), value + pos + 1);
      int width = cSkinDisplay::Current()->EditableWidth();
diff -ruN vdr-1.4.0/nit.c vdr-1.4.1/nit.c
--- vdr-1.4.0/nit.c	2006-04-15 16:10:42.000000000 +0200
+++ vdr-1.4.1/nit.c	2006-05-27 17:35:16.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: nit.c 1.11 2006/04/15 14:10:42 kls Exp $
+ * $Id: nit.c 1.12 2006/05/27 15:35:16 kls Exp $
  */
 
 #include "nit.h"
@@ -48,7 +48,7 @@
                    if (nits[j].hasTransponder) {
                       networkId = nits[j].networkId;
                       //printf("taking NIT with network ID %d\n", networkId);
-                      //XXX what if more than one NIT contaisn this transponder???
+                      //XXX what if more than one NIT contains this transponder???
                       break;
                       }
                    }
@@ -95,46 +95,84 @@
   SI::NIT::TransportStream ts;
   for (SI::Loop::Iterator it; nit.transportStreamLoop.getNext(ts, it); ) {
       SI::Descriptor *d;
+
+      SI::Loop::Iterator it2;
+      SI::FrequencyListDescriptor *fld = (SI::FrequencyListDescriptor *)ts.transportStreamDescriptors.getNext(it2, SI::FrequencyListDescriptorTag);
+      int NumFrequencies = fld ? fld->frequencies.getCount() + 1 : 1;
+      int Frequencies[NumFrequencies];
+      if (fld) {
+         int ct = fld->getCodingType();
+         if (ct > 0) {
+            int n = 1;
+            for (SI::Loop::Iterator it3; fld->frequencies.hasNext(it3); ) {
+                int f = fld->frequencies.getNext(it3);
+                switch (ct) {
+                  case 1: f = BCD2INT(f) / 100; break;
+                  case 2: f = BCD2INT(f) / 10; break;
+                  case 3: f = f * 10;  break;
+                  }
+                Frequencies[n++] = f;
+                }
+            }
+         else
+            NumFrequencies = 1;
+         }
+      delete fld;
+
       for (SI::Loop::Iterator it2; (d = ts.transportStreamDescriptors.getNext(it2)); ) {
           switch (d->getDescriptorTag()) {
             case SI::SatelliteDeliverySystemDescriptorTag: {
                  SI::SatelliteDeliverySystemDescriptor *sd = (SI::SatelliteDeliverySystemDescriptor *)d;
                  int Source = cSource::FromData(cSource::stSat, BCD2INT(sd->getOrbitalPosition()), sd->getWestEastFlag());
-                 int Frequency = BCD2INT(sd->getFrequency()) / 100;
+                 int Frequency = Frequencies[0] = BCD2INT(sd->getFrequency()) / 100;
                  static char Polarizations[] = { 'h', 'v', 'l', 'r' };
                  char Polarization = Polarizations[sd->getPolarization()];
                  static int CodeRates[] = { FEC_NONE, FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_NONE };
                  int CodeRate = CodeRates[sd->getFecInner()];
                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
                  if (ThisNIT >= 0) {
-                    if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) {
-                       nits[ThisNIT].hasTransponder = true;
-                       //printf("has transponder %d\n", Transponder());
-                       }
+                    for (int n = 0; n < NumFrequencies; n++) {
+                        if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), Transponder())) {
+                           nits[ThisNIT].hasTransponder = true;
+                           //printf("has transponder %d\n", Transponder());
+                           break;
+                           }
+                        }
                     break;
                     }
                  bool found = false;
                  for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
                      if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
-                        if (Setup.UpdateChannels >= 5)
+                        if (Setup.UpdateChannels >= 5) {
+                           if (!ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Channel->Transponder())) {
+                              for (int n = 0; n < NumFrequencies; n++) {
+                                  if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), Channel->Transponder())) {
+                                     Frequency = Frequencies[n];
+                                     break;
+                                     }
+                                  }
+                              }
                            Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate);
+                           }
                         found = true;
                         }
                      }
                  if (!found && Setup.UpdateChannels >= 5) {
-                    cChannel *Channel = new cChannel;
-                    Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
-                    if (Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate))
-                       EITScanner.AddTransponder(Channel);
-                    else
-                       delete Channel;
+                    for (int n = 0; n < NumFrequencies; n++) {
+                        cChannel *Channel = new cChannel;
+                        Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
+                        if (Channel->SetSatTransponderData(Source, Frequencies[n], Polarization, SymbolRate, CodeRate))
+                           EITScanner.AddTransponder(Channel);
+                        else
+                           delete Channel;
+                        }
                     }
                  }
                  break;
             case SI::CableDeliverySystemDescriptorTag: {
                  SI::CableDeliverySystemDescriptor *sd = (SI::CableDeliverySystemDescriptor *)d;
                  int Source = cSource::FromData(cSource::stCable);
-                 int Frequency = BCD2INT(sd->getFrequency()) / 10;
+                 int Frequency = Frequencies[0] = BCD2INT(sd->getFrequency()) / 10;
                  //XXX FEC_outer???
                  static int CodeRates[] = { FEC_NONE, FEC_1_2, FEC_2_3, FEC_3_4, FEC_5_6, FEC_7_8, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_AUTO, FEC_NONE };
                  int CodeRate = CodeRates[sd->getFecInner()];
@@ -142,34 +180,48 @@
                  int Modulation = Modulations[min(sd->getModulation(), 6)];
                  int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
                  if (ThisNIT >= 0) {
-                    if (ISTRANSPONDER(Frequency / 1000, Transponder())) {
-                       nits[ThisNIT].hasTransponder = true;
-                       //printf("has transponder %d\n", Transponder());
-                       }
+                    for (int n = 0; n < NumFrequencies; n++) {
+                        if (ISTRANSPONDER(Frequencies[n] / 1000, Transponder())) {
+                           nits[ThisNIT].hasTransponder = true;
+                           //printf("has transponder %d\n", Transponder());
+                           break;
+                           }
+                        }
                     break;
                     }
                  bool found = false;
                  for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
                      if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
-                        if (Setup.UpdateChannels >= 5)
+                        if (Setup.UpdateChannels >= 5) {
+                           if (!ISTRANSPONDER(Frequency / 1000, Channel->Transponder())) {
+                              for (int n = 0; n < NumFrequencies; n++) {
+                                  if (ISTRANSPONDER(Frequencies[n] / 1000, Channel->Transponder())) {
+                                     Frequency = Frequencies[n];
+                                     break;
+                                     }
+                                  }
+                              }
                            Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate);
+                           }
                         found = true;
                         }
                      }
                  if (!found && Setup.UpdateChannels >= 5) {
-                    cChannel *Channel = new cChannel;
-                    Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
-                    if (Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate))
-                       EITScanner.AddTransponder(Channel);
-                    else
-                       delete Channel;
+                    for (int n = 0; n < NumFrequencies; n++) {
+                        cChannel *Channel = new cChannel;
+                        Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
+                        if (Channel->SetCableTransponderData(Source, Frequencies[n], Modulation, SymbolRate, CodeRate))
+                           EITScanner.AddTransponder(Channel);
+                        else
+                           delete Channel;
+                        }
                     }
                  }
                  break;
             case SI::TerrestrialDeliverySystemDescriptorTag: {
                  SI::TerrestrialDeliverySystemDescriptor *sd = (SI::TerrestrialDeliverySystemDescriptor *)d;
                  int Source = cSource::FromData(cSource::stTerr);
-                 int Frequency = sd->getFrequency() * 10;
+                 int Frequency = Frequencies[0] = sd->getFrequency() * 10;
                  static int Bandwidths[] = { BANDWIDTH_8_MHZ, BANDWIDTH_7_MHZ, BANDWIDTH_6_MHZ, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO, BANDWIDTH_AUTO };
                  int Bandwidth = Bandwidths[sd->getBandwidth()];
                  static int Constellations[] = { QPSK, QAM_16, QAM_64, QAM_AUTO };
@@ -184,27 +236,41 @@
                  static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_AUTO, TRANSMISSION_MODE_AUTO };
                  int TransmissionMode = TransmissionModes[sd->getTransmissionMode()];
                  if (ThisNIT >= 0) {
-                    if (ISTRANSPONDER(Frequency / 1000000, Transponder())) {
-                       nits[ThisNIT].hasTransponder = true;
-                       //printf("has transponder %d\n", Transponder());
-                       }
+                    for (int n = 0; n < NumFrequencies; n++) {
+                        if (ISTRANSPONDER(Frequencies[n] / 1000000, Transponder())) {
+                           nits[ThisNIT].hasTransponder = true;
+                           //printf("has transponder %d\n", Transponder());
+                           break;
+                           }
+                        }
                     break;
                     }
                  bool found = false;
                  for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
                      if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) {
-                        if (Setup.UpdateChannels >= 5)
+                        if (Setup.UpdateChannels >= 5) {
+                           if (!ISTRANSPONDER(Frequency / 1000000, Channel->Transponder())) {
+                              for (int n = 0; n < NumFrequencies; n++) {
+                                  if (ISTRANSPONDER(Frequencies[n] / 1000000, Channel->Transponder())) {
+                                     Frequency = Frequencies[n];
+                                     break;
+                                     }
+                                  }
+                              }
                            Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode);
+                           }
                         found = true;
                         }
                      }
                  if (!found && Setup.UpdateChannels >= 5) {
-                    cChannel *Channel = new cChannel;
-                    Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
-                    if (Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode))
-                       EITScanner.AddTransponder(Channel);
-                    else
-                       delete Channel;
+                    for (int n = 0; n < NumFrequencies; n++) {
+                        cChannel *Channel = new cChannel;
+                        Channel->SetId(ts.getOriginalNetworkId(), ts.getTransportStreamId(), 0, 0);
+                        if (Channel->SetTerrTransponderData(Source, Frequencies[n], Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode))
+                           EITScanner.AddTransponder(Channel);
+                        else
+                           delete Channel;
+                        }
                     }
                  }
                  break;
diff -ruN vdr-1.4.0/receiver.h vdr-1.4.1/receiver.h
--- vdr-1.4.0/receiver.h	2005-01-16 15:05:10.000000000 +0100
+++ vdr-1.4.1/receiver.h	2006-05-27 11:04:22.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: receiver.h 1.3 2005/01/16 14:05:10 kls Exp $
+ * $Id: receiver.h 1.4 2006/05/27 09:04:22 kls Exp $
  */
 
 #ifndef __RECEIVER_H
@@ -44,7 +44,7 @@
                ///< Pids1...Pids3 are pointers to zero terminated lists of PIDs.
                ///< If any of these PIDs are 0, they will be silently ignored.
                ///< The total number of non-zero PIDs must not exceed MAXRECEIVEPIDS.
-               ///< Priority may be any value in the range 0..99. Negative values indicate
+               ///< Priority may be any value in the range -99..99. Negative values indicate
                ///< that this cReceiver may be detached at any time (without blocking the
                ///< cDevice it is attached to).
   virtual ~cReceiver();
diff -ruN vdr-1.4.0/remote.c vdr-1.4.1/remote.c
--- vdr-1.4.0/remote.c	2006-04-17 10:58:28.000000000 +0200
+++ vdr-1.4.1/remote.c	2006-05-12 14:40:15.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remote.c 1.50 2006/04/17 08:58:28 kls Exp $
+ * $Id: remote.c 1.51 2006/05/12 12:40:15 kls Exp $
  */
 
 #include "remote.h"
@@ -182,11 +182,11 @@
             repeatTimeout.Set(REPEATTIMEOUT);
          return k;
          }
-      else if (!WaitMs || !keyPressed.TimedWait(mutex, WaitMs) && repeatTimeout.TimedOut()) {
-         if (learning && UnknownCode) {
-            *UnknownCode = unknownCode;
-            unknownCode = NULL;
-            }
+      else if (!WaitMs || !keyPressed.TimedWait(mutex, WaitMs) && repeatTimeout.TimedOut())
+         return kNone;
+      else if (learning && UnknownCode && unknownCode) {
+         *UnknownCode = unknownCode;
+         unknownCode = NULL;
          return kNone;
          }
       }
diff -ruN vdr-1.4.0/runvdr vdr-1.4.1/runvdr
--- vdr-1.4.0/runvdr	2006-02-04 16:20:48.000000000 +0100
+++ vdr-1.4.1/runvdr	2006-05-14 18:02:05.000000000 +0200
@@ -5,6 +5,11 @@
 # If VDR exits abnormally, the driver will be reloaded
 # and VDR restarted.
 #
+# In order to actually use this script you need to implement
+# the functions DriverLoaded(), LoadDriver() and UnloadDriver()
+# and maybe adjust the VDRPRG and VDRCMD to your particular
+# requirements.
+#
 # Since this script loads the DVB driver, it must be started
 # as user 'root'. Add the option "-u username" to run VDR
 # under the given user name.
@@ -15,27 +20,42 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: runvdr 1.16 2006/02/04 15:20:48 kls Exp $
+# $Id: runvdr 1.19 2006/05/14 16:02:05 kls Exp $
 
-DVBDIR="../DVB/driver"
 VDRPRG="./vdr"
 VDRCMD="$VDRPRG -w 60 $*"
 
-LSMOD="`/sbin/lsmod | grep -w '^dvb' | wc -l`"
 KILL="/usr/bin/killall -q -TERM"
 
+# Detect whether the DVB driver is already loaded
+# and return 0 if it *is* loaded, 1 if not:
+function DriverLoaded()
+{
+  return 1
+}
+
+# Load all DVB driver modules needed for your hardware:
+function LoadDriver()
+{
+}
+
+# Unload all DVB driver modules loaded in LoadDriver():
+function UnloadDriver()
+{
+}
+
 # Load driver if it hasn't been loaded already:
-if [ $LSMOD -eq 0 ] ; then
-   (cd $DVBDIR; make insmod)
+if ! DriverLoaded; then
+   LoadDriver
    fi
 
 while (true) do
-      $VDRCMD
+      eval "$VDRCMD"
       if test $? -eq 0 -o $? -eq 2; then exit; fi
-      date
-      echo "restarting VDR"
+      echo "`date` reloading DVB driver"
       $KILL $VDRPRG
       sleep 10
-      (cd $DVBDIR; make rmmod; make insmod)
-      date
+      UnloadDriver
+      LoadDriver
+      echo "`date` restarting VDR"
       done
diff -ruN vdr-1.4.0/skins.c vdr-1.4.1/skins.c
--- vdr-1.4.0/skins.c	2006-04-09 13:25:30.000000000 +0200
+++ vdr-1.4.1/skins.c	2006-06-03 16:39:14.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: skins.c 1.9 2006/04/09 11:25:30 kls Exp $
+ * $Id: skins.c 1.11 2006/06/03 14:39:14 kls Exp $
  */
 
 #include "skins.h"
@@ -79,7 +79,7 @@
   tabs[4] = Tab4 ? tabs[3] + Tab4 : 0;
   tabs[5] = Tab5 ? tabs[4] + Tab5 : 0;
   for (int i = 1; i < MaxTabs; i++)
-      tabs[i] *= 12;//XXX average character width of font used for items!!!
+      tabs[i] *= 12;//XXX average character width of font used for items - see also skincurses.c!!!
 }
 
 void cSkinDisplayMenu::Scroll(bool Up, bool Page)
@@ -176,7 +176,6 @@
   if (theme)
      cThemes::Save(name, theme);
   Skins.Add(this);
-  Skins.SetCurrent(Name);
 }
 
 cSkin::~cSkin()
@@ -203,12 +202,17 @@
   if (Name) {
      for (cSkin *Skin = First(); Skin; Skin = Next(Skin)) {
          if (strcmp(Skin->Name(), Name) == 0) {
+            isyslog("setting current skin to \"%s\"", Name);
             current = Skin;
             return true;
             }
          }
      }
   current = First();
+  if (current)
+     isyslog("skin \"%s\" not available - using \"%s\" instead", Name, current->Name());
+  else
+     esyslog("ERROR: no skin available");
   return current != NULL;
 }
 
diff -ruN vdr-1.4.0/skins.h vdr-1.4.1/skins.h
--- vdr-1.4.0/skins.h	2006-04-09 13:23:35.000000000 +0200
+++ vdr-1.4.1/skins.h	2006-06-03 12:21:45.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: skins.h 1.13 2006/04/09 11:23:35 kls Exp $
+ * $Id: skins.h 1.14 2006/06/03 10:21:45 kls Exp $
  */
 
 #ifndef __SKINS_H
@@ -95,7 +95,7 @@
   cTextScroller textScroller;
   int Tab(int n) { return (n >= 0 && n < MaxTabs) ? tabs[n] : 0; }
        ///< Returns the offset of the given tab from the left border of the
-       ///< item display area. The value returned is in pixel.//XXX ncurses???
+       ///< item display area. The value returned is in pixel.
   const char *GetTabbedText(const char *s, int Tab);
        ///< Returns the part of the given string that follows the given
        ///< Tab (where 0 indicates the beginning of the string). If no such
@@ -104,7 +104,7 @@
   cSkinDisplayMenu(void);
   virtual void SetTabs(int Tab1, int Tab2 = 0, int Tab3 = 0, int Tab4 = 0, int Tab5 = 0);
        ///< Sets the tab columns to the given values, which are the number of
-       ///< characters in each column.//XXX ncurses???
+       ///< characters in each column.
   virtual void Scroll(bool Up, bool Page);
        ///< If this menu contains a text area that can be scrolled, this function
        ///< will be called to actually scroll the text. Up indicates whether the
diff -ruN vdr-1.4.0/sources.conf vdr-1.4.1/sources.conf
--- vdr-1.4.0/sources.conf	2006-04-17 14:19:21.000000000 +0200
+++ vdr-1.4.1/sources.conf	2006-05-01 11:34:18.000000000 +0200
@@ -164,7 +164,7 @@
 S103W   AMC1
 S105W   AMC15
 S107.3W Anik F1/F1R
-S110W   DirecTV 5 & Echostar 6/8
+S110W   DirecTV 5 & Echostar 6/8/10
 S111.1W Anik F2
 S113W   Solidaridad 2
 S119W   Echostar 7 & DirecTV 7S
diff -ruN vdr-1.4.0/svdrp.c vdr-1.4.1/svdrp.c
--- vdr-1.4.0/svdrp.c	2006-04-17 11:02:23.000000000 +0200
+++ vdr-1.4.1/svdrp.c	2006-06-11 11:04:36.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.95 2006/04/17 09:02:23 kls Exp $
+ * $Id: svdrp.c 1.97 2006/06/11 09:04:36 kls Exp $
  */
 
 #include "svdrp.h"
@@ -550,10 +550,25 @@
                      return;
                      }
                   }
+              int CurrentChannelNr = cDevice::CurrentChannel();
+              cChannel *CurrentChannel = Channels.GetByNumber(CurrentChannelNr);
+              if (CurrentChannel && channel == CurrentChannel) {
+                 int n = Channels.GetNextNormal(CurrentChannel->Index());
+                 if (n < 0)
+                    n = Channels.GetPrevNormal(CurrentChannel->Index());
+                 CurrentChannel = Channels.Get(n);
+                 CurrentChannelNr = 0; // triggers channel switch below
+                 }
               Channels.Del(channel);
               Channels.ReNumber();
               Channels.SetModified(true);
               isyslog("channel %s deleted", Option);
+              if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
+                 if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
+                    Channels.SwitchTo(CurrentChannel->Number());
+                 else
+                    cDevice::SetCurrentChannel(CurrentChannel);
+                 }
               Reply(250, "Channel \"%s\" deleted", Option);
               }
            else
@@ -764,7 +779,7 @@
            int fd = open(FileName, O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC, DEFFILEMODE);
            if (fd >= 0) {
               if (safe_write(fd, Image, ImageSize) == ImageSize) {
-                 isyslog("grabbed image to %s", FileName);
+                 dsyslog("grabbed image to %s", FileName);
                  Reply(250, "Grabbed image %s", Option);
                  }
               else {
@@ -1158,8 +1173,12 @@
                        Channels.Move(FromChannel, ToChannel);
                        Channels.ReNumber();
                        Channels.SetModified(true);
-                       if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr)
-                          Channels.SwitchTo(CurrentChannel->Number());
+                       if (CurrentChannel && CurrentChannel->Number() != CurrentChannelNr) {
+                          if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring())
+                             Channels.SwitchTo(CurrentChannel->Number());
+                          else
+                             cDevice::SetCurrentChannel(CurrentChannel);
+                          }
                        isyslog("channel %d moved to %d", FromNumber, ToNumber);
                        Reply(250,"Channel \"%d\" moved to \"%d\"", From, To);
                        }
diff -ruN vdr-1.4.0/thread.c vdr-1.4.1/thread.c
--- vdr-1.4.0/thread.c	2006-03-26 11:22:27.000000000 +0200
+++ vdr-1.4.1/thread.c	2006-06-02 15:51:39.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.54 2006/03/26 09:22:27 kls Exp $
+ * $Id: thread.c 1.55 2006/06/02 13:51:39 kls Exp $
  */
 
 #include "thread.h"
@@ -255,7 +255,6 @@
      active = running = true;
      if (pthread_create(&childTid, NULL, (void *(*) (void *))&StartThread, (void *)this) == 0) {
         pthread_detach(childTid); // auto-reap
-        pthread_setschedparam(childTid, SCHED_RR, 0);
         }
      else {
         LOG_ERROR;
diff -ruN vdr-1.4.0/timers.c vdr-1.4.1/timers.c
--- vdr-1.4.0/timers.c	2006-04-21 17:12:49.000000000 +0200
+++ vdr-1.4.1/timers.c	2006-05-25 16:36:37.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.58 2006/04/21 15:12:49 kls Exp $
+ * $Id: timers.c 1.61 2006/05/25 14:36:37 kls Exp $
  */
 
 #include "timers.h"
@@ -347,7 +347,7 @@
      }
   else {
      for (int i = -1; i <= 7; i++) {
-         time_t t0 = IncDay(t, i);
+         time_t t0 = IncDay(day ? max(day, t) : t, i);
          if (DayMatches(t0)) {
             time_t a = SetTime(t0, begin);
             time_t b = a + length;
@@ -359,16 +359,19 @@
             }
          }
      if (!startTime)
-        startTime = day; // just to have something that's more than a week in the future
+        startTime = IncDay(t, 7); // just to have something that's more than a week in the future
      else if (!Directly && (t > startTime || t > day + SECSINDAY + 3600)) // +3600 in case of DST change
         day = 0;
      }
 
   if (HasFlags(tfActive)) {
-     if (HasFlags(tfVps) && !Directly && event && event->Vps() && event->Schedule() && event->Schedule()->PresentSeenWithin(30)) {
-        startTime = event->StartTime();
-        stopTime = event->EndTime();
-        return event->IsRunning(true);
+     if (HasFlags(tfVps) && event && event->Vps()) {
+        if (Margin || !Directly) {
+           startTime = event->StartTime();
+           stopTime = event->EndTime();
+           if (!Margin)
+              return event->IsRunning(true);
+           }
         }
      return startTime <= t + Margin && t < stopTime; // must stop *before* stopTime to allow adjacent timers
      }
@@ -557,6 +560,7 @@
 void cTimer::Skip(void)
 {
   day = IncDay(SetTime(StartTime(), 0), 1);
+  startTime = 0;
   SetEvent(NULL);
 }
 
diff -ruN vdr-1.4.0/tools.c vdr-1.4.1/tools.c
--- vdr-1.4.0/tools.c	2006-04-21 17:12:47.000000000 +0200
+++ vdr-1.4.1/tools.c	2006-05-26 12:10:31.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.117 2006/04/21 15:12:47 kls Exp $
+ * $Id: tools.c 1.118 2006/05/26 10:10:31 kls Exp $
  */
 
 #include "tools.h"
@@ -1179,7 +1179,7 @@
            }
         else if (cachedend > ahead && cachedend - curpos > READCHUNK * 2) {
            // current position has moved back enough, shrink head window.
-           FadviseDrop(curpos + READCHUNK, cachedend - curpos + READCHUNK);
+           FadviseDrop(curpos + READCHUNK, cachedend - (curpos + READCHUNK));
            cachedend = curpos + READCHUNK;
            }
         }
diff -ruN vdr-1.4.0/vdr.c vdr-1.4.1/vdr.c
--- vdr-1.4.0/vdr.c	2006-04-29 11:14:06.000000000 +0200
+++ vdr-1.4.1/vdr.c	2006-06-04 11:04:47.000000000 +0200
@@ -22,7 +22,7 @@
  *
  * The project's page is at http://www.cadsoft.de/vdr
  *
- * $Id: vdr.c 1.267 2006/04/29 09:14:06 kls Exp $
+ * $Id: vdr.c 1.274 2006/06/04 09:04:47 kls Exp $
  */
 
 #include <getopt.h>
@@ -72,8 +72,11 @@
 #define DEVICEREADYTIMEOUT 30 // seconds to wait until all devices are ready
 #define MENUTIMEOUT       120 // seconds of user inactivity after which an OSD display is closed
 #define SHUTDOWNRETRY     300 // seconds before trying again to shut down
-#define VPSCHECKDELTA      10 // seconds between checks for timers that have entered the VPS margin
-#define VPSDEVICETIMEOUT    8 // seconds before a device used for VPS may be reused
+#define TIMERCHECKDELTA    10 // seconds between checks for timers that need to see their channel
+#define TIMERDEVICETIMEOUT  8 // seconds before a device used for timer check may be reused
+#define TIMERLOOKAHEADTIME 60 // seconds before a non-VPS timer starts and the channel is switched if possible
+#define VPSLOOKAHEADTIME   24 // hours within which VPS timers will make sure their events are up to date
+#define VPSUPTODATETIME  3600 // seconds before the event or schedule of a VPS timer needs to be refreshed
 
 #define EXIT(v) { ExitCode = (v); goto Exit; }
 
@@ -500,8 +503,9 @@
   int MaxLatencyTime = 0;
   bool ForceShutdown = false;
   bool UserShutdown = false;
-  bool TimerInVpsMargin = false;
+  bool InhibitEpgScan = false;
   bool IsInfoMenu = false;
+  cSkin *CurrentSkin = NULL;
 
   // Load plugins:
 
@@ -603,6 +607,7 @@
   new cSkinSTTNG;
   Skins.SetCurrent(Setup.OSDSkin);
   cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme());
+  CurrentSkin = Skins.Current();
 
   // Start plugins:
 
@@ -611,8 +616,10 @@
 
   // Set skin and theme in case they're implemented by a plugin:
 
-  Skins.SetCurrent(Setup.OSDSkin);
-  cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme());
+  if (!CurrentSkin || CurrentSkin == Skins.Current() && strcmp(Skins.Current()->Name(), Setup.OSDSkin) != 0) {
+     Skins.SetCurrent(Setup.OSDSkin);
+     cThemes::Load(Skins.Current()->Name(), Setup.OSDTheme, Skins.Current()->Theme());
+     }
 
   // Remote Controls:
   if (RcuDevice)
@@ -756,14 +763,35 @@
               else
                  LastTimerChannel = Timer->Channel()->Number();
               }
-           // Make sure VPS timers "see" their channel early enough:
-           static time_t LastVpsCheck = 0;
-           if (Now - LastVpsCheck > VPSCHECKDELTA) { // don't do this too often
-              TimerInVpsMargin = false;
+           // Make sure timers "see" their channel early enough:
+           static time_t LastTimerCheck = 0;
+           if (Now - LastTimerCheck > TIMERCHECKDELTA) { // don't do this too often
+              InhibitEpgScan = false;
               static time_t DeviceUsed[MAXDEVICES] = { 0 };
               for (cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) {
-                  if (Timer->HasFlags(tfActive | tfVps) && !Timer->Recording() && Timer->Matches(Now, true, Setup.VpsMargin)) {
-                     Timer->SetInVpsMargin(true);
+                  bool InVpsMargin = false;
+                  bool NeedsTransponder = false;
+                  if (Timer->HasFlags(tfActive) && !Timer->Recording()) {
+                     if (Timer->HasFlags(tfVps)) {
+                        if (Timer->Matches(Now, true, Setup.VpsMargin))
+                           InVpsMargin = true;
+                        else if (Timer->Event())
+                           NeedsTransponder = Timer->Event()->StartTime() - Now < VPSLOOKAHEADTIME * 3600 && !Timer->Event()->SeenWithin(VPSUPTODATETIME);
+                        else {
+                           cSchedulesLock SchedulesLock;
+                           const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
+                           if (Schedules) {
+                              const cSchedule *Schedule = Schedules->GetSchedule(Timer->Channel());
+                              NeedsTransponder = Schedule && !Schedule->PresentSeenWithin(VPSUPTODATETIME);
+                              }
+                           }
+                        InhibitEpgScan |= InVpsMargin | NeedsTransponder;
+                        }
+                     else
+                        NeedsTransponder = Timer->Matches(Now, true, TIMERLOOKAHEADTIME);
+                     }
+                  Timer->SetInVpsMargin(InVpsMargin);
+                  if (NeedsTransponder || InVpsMargin) {
                      // Find a device that provides the required transponder:
                      cDevice *Device = NULL;
                      for (int i = 0; i < cDevice::NumDevices(); i++) {
@@ -774,20 +802,20 @@
                                Device = d;
                                break;
                                }
-                            else if (Now - DeviceUsed[d->DeviceNumber()] > VPSDEVICETIMEOUT) {
+                            else if (Now - DeviceUsed[d->DeviceNumber()] > TIMERDEVICETIMEOUT) {
                                // only check other devices if they have been left alone for a while
                                if (d->MaySwitchTransponder())
                                   // this one can be switched without disturbing anything else
                                   Device = d;
-                               else if (!Device && !d->Receiving() && d->ProvidesTransponderExclusively(Timer->Channel()))
+                               else if (!Device && InVpsMargin && !d->Receiving() && d->ProvidesTransponderExclusively(Timer->Channel()))
                                   // use this one only if no other with less impact can be found
                                   Device = d;
                                }
                             }
                          }
-                     if (!Device) {
+                     if (!Device && InVpsMargin) {
                         cDevice *d = cDevice::ActualDevice();
-                        if (!d->Receiving() && d->ProvidesTransponder(Timer->Channel()) && Now - DeviceUsed[d->DeviceNumber()] > VPSDEVICETIMEOUT)
+                        if (!d->Receiving() && d->ProvidesTransponder(Timer->Channel()) && Now - DeviceUsed[d->DeviceNumber()] > TIMERDEVICETIMEOUT)
                            Device = d; // use the actual device as a last resort
                         }
                      // Switch the device to the transponder:
@@ -805,12 +833,9 @@
                            Skins.Message(mtInfo, tr("Upcoming VPS recording!"));
                            }
                         }
-                     TimerInVpsMargin = true;
                      }
-                  else
-                     Timer->SetInVpsMargin(false);
                   }
-              LastVpsCheck = time(NULL);
+              LastTimerCheck = time(NULL);
               }
            // Delete expired timers:
            Timers.DeleteExpired();
@@ -970,7 +995,7 @@
                   }
                break;
           // Power off:
-          case kPower:
+          case kPower: {
                isyslog("Power button pressed");
                DELETE_MENU;
                if (!Shutdown) {
@@ -985,8 +1010,20 @@
                   }
                if (cPluginManager::Active(tr("shut down anyway?")))
                   break;
+               cTimer *timer = Timers.GetNextActiveTimer();
+               time_t Next  = timer ? timer->StartTime() : 0;
+               time_t Delta = timer ? Next - time(NULL) : 0;
+               if (Next && Delta <= Setup.MinEventTimeout * 60) {
+                  char *buf;
+                  asprintf(&buf, tr("Recording in %ld minutes, shut down anyway?"), Delta / 60);
+                  bool confirm = Interface->Confirm(buf);
+                  free(buf);
+                  if (!confirm)
+                     break;
+                  }
                ForceShutdown = true;
                break;
+               }
           default: break;
           }
         Interact = Menu ? Menu : cControl::Control(); // might have been closed in the mean time
@@ -1004,6 +1041,9 @@
               else if (time(NULL) - LastActivity > MENUTIMEOUT)
                  state = osEnd;
               }
+           // TODO make the CAM menu stay open in case of automatic updates and have it return osContinue; then the following two lines can be removed again
+           else if (state == osEnd && LastActivity > 1)
+              LastActivity = time(NULL);
            switch (state) {
              case osPause:  DELETE_MENU;
                             cControl::Shutdown(); // just in case
@@ -1094,7 +1134,7 @@
              }
            }
         if (!Menu) {
-           if (!TimerInVpsMargin)
+           if (!InhibitEpgScan)
               EITScanner.Process();
            if (!cCutter::Active() && cCutter::Ended()) {
               if (cCutter::Error())
@@ -1121,15 +1161,6 @@
                     else
                        LastActivity = 1;
                     }
-                 if (UserShutdown && Next && Delta <= Setup.MinEventTimeout * 60 && !ForceShutdown) {
-                    char *buf;
-                    asprintf(&buf, tr("Recording in %ld minutes, shut down anyway?"), Delta / 60);
-                    if (Interface->Confirm(buf))
-                       ForceShutdown = true;
-                    else
-                       UserShutdown = false;
-                    free(buf);
-                    }
                  if (!Next || Delta > Setup.MinEventTimeout * 60 || ForceShutdown) {
                     ForceShutdown = false;
                     if (timer)
