diff -ruN vdr-1.5.0/CONTRIBUTORS vdr-1.5.1/CONTRIBUTORS
--- vdr-1.5.0/CONTRIBUTORS	2007-01-04 14:38:40.000000000 +0100
+++ vdr-1.5.1/CONTRIBUTORS	2007-02-25 14:57:19.000000000 +0100
@@ -360,6 +360,7 @@
 Thilo Wunderlich <wunderlich@speedway.org>
  for his help in keeping 'channels.conf' up to date
  for reporting a problem with accessing the epg.data file before it is fully written
+ for updating satellite names in 'sources.conf'
 
 Stephan Schreiber <stephan@sschreiber.de>
  for his support in keeping the Premiere World channels up to date in 'channels.conf.cable'
@@ -583,6 +584,7 @@
  for suggesting to reduce the logging for the SVDRP GRAB command
  for reporting that the shutdown script is given a reboot time in the past if there
  is a recording going on or about to start, and the user insists in shutting down now
+ for suggesting to make the channel entry timeout configurable
 
 Jeremy Hall <jhall@UU.NET>
  for fixing an incomplete initialization of the filter parameters in eit.c
@@ -1008,13 +1010,14 @@
  cPluginManager::Active() in menu.c to "restart anyway?"
  for adding --remove-destination to the 'cp' command for binaries in the Makefiles of
  the plugins
+ for increasing the maximum number of DVB devices to 8
 
 Ralf Klueber <ralf.klueber@vodafone.com>
  for reporting a bug in cutting a recording if there is only a single editing mark
  for reporting a bug in handling a channels.conf that contains a ":@nnn" line as
  its last entry
 
-Hermann Gausterer <mrq1@gmx.net>
+Hermann Gausterer <vdr@mrq1.org>
  for suggesting to switch to the recording channel in case the current channel
  becomes unavailable
 
@@ -1114,6 +1117,9 @@
  for changing the behaviour when hitting the end of a recording in fast forward mode
  for suggesting to give the cRemote::CallPlugin() function a boolean return value
  for fixing a possible crash in remux.c on 64-bit machines
+ for making cCommand::Execute() use cPipe instead of popen() to avoid problems
+ with open file handles when starting background commands
+ for fixing handling error status in cDvbTuner::GetFrontendStatus()
 
 Richard Robson <richard_robson@beeb.net>
  for reporting freezing replay if a timer starts while in Transfer Mode from the
@@ -1387,6 +1393,8 @@
  replay has been stopped
  for reporting a problem with displaying the replay mode symbol in case of "Multi
  speed mode"
+ for removing 'assert(0)' from cDvbSpuDecoder::setTime()
+ for adapting 'libsi' to DVB-S2
 
 Jürgen Schmitz <j.schmitz@web.de>
  for reporting a bug in displaying the current channel when switching via the SVDRP
@@ -1479,6 +1487,10 @@
  for some hints on how to improve handling cPluginManager::Active()
  for fixing a possible segfault if VDR gets terminated while a message is displayed
  for reporting an error in the INSTALL section on retrying shutdown later
+ for rewriting shutdown handling
+ for implementing cPlugin::WakeupTime() to allow plugins to request VDR to wake
+ up at a particular time
+ for making the HUP signal force a restart of VDR
 
 Sven Kreiensen <svenk@kammer.uni-hannover.de>
  for his help in keeping 'channels.conf.terr' up to date
@@ -1692,6 +1704,7 @@
 Martin Wache <M.Wache@gmx.net>
  for adding a sleep in cDvbPlayer::Action() in case there is no data to send to the
  device, which avoids a busy loop on very fast machines
+ for fixing a possible crash when loading an invalid XPM file
 
 Matthias Lenk <matthias.lenk@amd.com>
  for reporting an out-of-bounds memory access with audio language ids
@@ -1720,6 +1733,7 @@
  for reporting a bug in the initial setting of the time transponder setup parameter
  for suggesting to extend the version number reported with the '-V' option to also
  show the current APIVERSION
+ for fixing i18n characters for the Hungarian texts
 
 David Woodhouse <dwmw2@infradead.org>
  for his help in replacing the get/put_unaligned() macros from asm/unaligned.h with
@@ -1744,6 +1758,7 @@
  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
+ for pointing out that "Menu button closes" should actually be "Menu key closes"
 
 Patrick Rother <krd-vdr@gulu.net>
  for reporting a bug in defining timers that only differ in the day of week
@@ -2050,3 +2065,7 @@
 
 Peter Pinnau <vdr@unterbrecher.de>
  for reporting that 'uint32_t' requires uncluding stdint.h in font.h on some systems
+
+Petri Helin <phelin@googlemail.com>
+ for suggesting to avoid budget DVB cards with Common Interface when tuning to an
+ FTA channel
diff -ruN vdr-1.5.0/HISTORY vdr-1.5.1/HISTORY
--- vdr-1.5.0/HISTORY	2007-01-07 15:08:19.000000000 +0100
+++ vdr-1.5.1/HISTORY	2007-02-25 14:57:34.000000000 +0100
@@ -5081,3 +5081,56 @@
   without valid CA ids VDR can't decide which CAM slot to use. However, since VDR now
   automatically determines which CAM can decrypt which channel, setting fixed
   channel/device relations should no longer be necessary.
+  IF AN ENCRYPTED CHANNEL CAN'T BE DECRYPTED AND YOU HAVE A CA VALUE IN THE RANGE
+  0...F FOR THAT CHANNEL, SET IT TO 0 (FTA) AND TUNE TO THE CHANNEL AGAIN.
+
+2007-01-28: Version 1.4.5-1
+
+- Fixed i18n characters for the Hungarian texts (thanks to Thomas Günther).
+- Now using cPipe instead of popen() in cCommand::Execute() to avoid problems
+  with open file handles when starting background commands (thanks to Reinhard
+  Nissl).
+
+2007-02-24: Version 1.4.5-2
+
+- Removed 'assert(0)' from cDvbSpuDecoder::setTime() (thanks to Marco Schlüßler).
+- Fixed a possible crash when loading an invalid XPM file (thanks to Martin Wache).
+- Updated satellite names in 'sources.conf' (thanks to Thilo Wunderlich).
+- Fixed handling error status in cDvbTuner::GetFrontendStatus() (thanks to
+  Reinhard Nissl).
+
+2007-02-25: Version 1.5.1
+
+- Added cDevice::HasCi() so that devices with Common Interface can be avoided
+  when tuning to an FTA channel, thus preserving the CAM resources even on budget
+  DVB cards (suggested by Petri Helin).
+- Fixed i18n characters for the Hungarian texts (thanks to Thomas Günther).
+- Now using cPipe instead of popen() in cCommand::Execute() to avoid problems
+  with open file handles when starting background commands (thanks to Reinhard
+  Nissl).
+- Removed 'assert(0)' from cDvbSpuDecoder::setTime() (thanks to Marco Schlüßler).
+- Fixed a possible crash when loading an invalid XPM file (thanks to Martin Wache).
+- Updated satellite names in 'sources.conf' (thanks to Thilo Wunderlich).
+- Adapted 'libsi' to DVB-S2 (thanks to Marco Schlüßler).
+- Fixed handling error status in cDvbTuner::GetFrontendStatus() (thanks to
+  Reinhard Nissl).
+- Shutdown handling has been rewritten (thanks to Udo Richter).
+- Plugins can now implement the new function WakeupTime() to request VDR to wake
+  up at a particular time (thanks to Udo Richter).
+- The HUP signal now forces a restart of VDR (thanks to Udo Richter).
+- cThread::EmergencyExit() has been replaced by ShutdownHandler.RequestEmergencyExit().
+- Several references to "button" in a remote control context have been changed
+  to "key" (based on a report from Marko Mäkelä regarding the "Menu button closes"
+  text). The "MenuButtonCloses" parameter in 'setup.conf' has therefore been
+  renamed to "MenuKeyCloses", accordingly. This will result in an "unknown config
+  parameter: MenuButtonCloses" error message in the log file, so you may want to
+  remove that entry from your 'setup.conf' file.
+- Simplified the error handling in cDvbTuner::GetFrontendStatus() (based on a
+  discussion with Reinhard Nissl).
+- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
+- Increased the maximum number of DVB devices to 8 (thanks to Rolf Ahrenberg).
+- The new Setup parameter "Channel entry timeout" can be used to customize the time
+  since the last keypress until a numerically entered channel number is considered
+  complete, and the channel is switched (suggested by Helmut Auer). Setting this
+  parameter to 0 turns off the automatic channel switching, and the user will
+  have to confirm the entry by pressing the "Ok" key.
diff -ruN vdr-1.5.0/INSTALL vdr-1.5.1/INSTALL
--- vdr-1.5.0/INSTALL	2007-01-04 14:22:01.000000000 +0100
+++ vdr-1.5.1/INSTALL	2007-02-24 16:22:48.000000000 +0100
@@ -160,30 +160,33 @@
 (see the Setup parameters in MANUAL).
 
 The command given in the '-s' option will be called with five parameters.
-The first one is the time (in UTC) of the next timer event (as a time_t
-type number), and the second one is the number of seconds from the current
-time until the next timer event. Your program can choose which one to use
-for programming some sort of hardware device that makes sure the computer
-will be restarted in time before the next timer event. Your program must
-also initiate the actual shutdown procedure of the computer. After this
-your program should return to VDR. VDR will not automatically exit after
-calling the shutdown program, but will rather continue normally until it
-receives a SIGTERM when the computer is actually shut down. So in case
-the shutdown fails, or the shutdown program for some reason decides not to
-perform a shutdown, VDR will stay up and running and will call the shutdown
-program again after another five minutes.
-
-If there are currently no timers active, both parameters will be '0'.
-In that case the program shall not set the hardware for automatic restart
-and only perform the system shutdown. A program that uses the second parameter
-to set the hardware for restart must therefore also check whether the first
-parameter is '0'.
-
-The third parameter contains the number of the channel that will be recorded
-by the next timer (or 0 if no timer is present), and the fourth parameter
-contains the file name of the recording as defined in the timer (or an empty
-string if no timer is present). These can be used by the shutdown program to
-show that information on some display interface etc.
+
+The first one is the time (in UTC) of the next timer event or plugin wakeup
+time (as a time_t type number), and the second one is the number of
+seconds from the current time until the next timer event. Your program can
+choose which one to use for programming some sort of hardware device that
+makes sure the computer will be restarted in time before the next timer
+event. Your program must also initiate the actual shutdown procedure of the
+computer. VDR will not automatically exit after calling the shutdown
+program, but will rather continue normally until it receives a SIGTERM when
+the computer is actually shut down. So in case the shutdown fails, or the
+shutdown program for some reason decides not to perform a shutdown, VDR
+will stay up and running and will call the shutdown program again after a
+while. The command will be started in a separate background session, so it
+can continue to run even after VDR has terminated.
+
+If there are currently no timers active and there is no plugin wakeup
+time, both parameters will be '0'. In that case the program shall not set
+the hardware for automatic restart and only perform the system shutdown.
+A program that uses the second parameter to set the hardware for restart
+must therefore also check whether the first parameter is '0'.
+
+If the wakeup time is given by a timer, the third parameter will be the
+number of the channel that will be recorded, otherwise it will be 0. The
+fourth parameter contains the file name of the recording as defined in the
+timer, the name of the plugin that requested the wakeup time, or an empty
+string if no wakeup time is present. These can be used by the shutdown
+program to show that information on some display interface etc.
 
 The fifth parameter indicates the reason why the shutdown was requested.
 '0' means this is an automatic shutdown due to some timeout, while '1' means
diff -ruN vdr-1.5.0/MANUAL vdr-1.5.1/MANUAL
--- vdr-1.5.0/MANUAL	2006-11-18 15:50:35.000000000 +0100
+++ vdr-1.5.1/MANUAL	2007-02-25 15:14:06.000000000 +0100
@@ -112,7 +112,7 @@
   "Ok" here opens the "Edit timer" menu.
 
   Textual options, like channel names or recording file names, can be edited
-  by pressing the "Right" button (which puts brackets around the current
+  by pressing the "Right" key (which puts brackets around the current
   character as in "[R]TL"), selecting the desired character position with
   "Left" and "Right", and changing the character with the "Up" and "Down"
   keys. "Ok" then confirms the changes. The "Red" key toggles between
@@ -120,7 +120,7 @@
   insert and overwrite mode. The "Yellow" key deletes the current character
   (or the one to the right of the cursor in insert mode).
 
-  The "Red", "Green", "Yellow" and "Blue" buttons have special meanings
+  The "Red", "Green", "Yellow" and "Blue" keys have special meanings
   in various menus and are listed at the bottom of the on-screen-display.
 
   At any point in the menu system, pressing the "Menu" key again will
@@ -137,22 +137,22 @@
   displays detailed information about the selected programme. Pressing "Ok"
   again (or pressing "Back") gets you back into the "Schedule" menu.
 
-  From the "Schedule" menu, the "Green" button opens the "What's on now?"
+  From the "Schedule" menu, the "Green" key opens the "What's on now?"
   menu, which displays all programmes that are currently running on all
   channels that broadcast their programme information on the current
   transponder, or from channels that have been current lately (VDR stores
   all information it gathers in an internal list). The more channels you
   have been switching through lately, the longer this list will be.
-  The "Yellow" button opens the "What's on next?" menu, which lists all
+  The "Yellow" key opens the "What's on next?" menu, which lists all
   programmes that will start next on all channels.
 
-  Inside the "What's on now/next?" menus the "Green" button toggles between
-  the "Now" and "Next" display, and the "Yellow" button takes you to the
+  Inside the "What's on now/next?" menus the "Green" key toggles between
+  the "Now" and "Next" display, and the "Yellow" key takes you to the
   "Schedule" menu of the current channel in the list.
 
-  The "Red" button allows you to instantly program a timer to record the
-  selected programme. After pressing this button, the current event will
-  be marked with 'T', and the function of the "Red" button will change from
+  The "Red" key allows you to instantly program a timer to record the
+  selected programme. After pressing this key, the current event will
+  be marked with 'T', and the function of the "Red" key will change from
   "Record" to "Timer". Pressing "Red" on an event marked with 'T' will open
   the "Edit timer" menu for this timer, where you can make any modifications
   you may want to apply. Note that the Start and Stop time are offset by the
@@ -167,7 +167,7 @@
   directly into the "Edit timer" menu in order to allow the user to make further
   changes to timer parameters before the actual recording starts.
 
-  The "Blue" button can be pressed to switch to the channel with the selected
+  The "Blue" key can be pressed to switch to the channel with the selected
   programme.
 
   The following markers in these menus give additional information about the
@@ -192,14 +192,14 @@
 
   1. With no On Screen Menu displayed press the "Up" or "Down" key to switch
      to the next higher or lower channel.
-  2. Press the "Menu" button to bring up the On Screen Menu, select "Channels"
+  2. Press the "Menu" key to bring up the On Screen Menu, select "Channels"
      and browse through the list with the "Up" and "Down" key; to switch to the
      selected channel press "Ok".
   3. Directly type in the channel number with the numeric keys ('0'..'9');
      if no key is pressed for about one second, the digits collected so
      far will define the channel number.
   4. From the "Now", "Next" and "Event" menus (accessible through the "Schedule"
-     menu) by pressing the "Blue" button.
+     menu) by pressing the "Blue" key.
 
   Pressing the '0' key in normal viewing mode toggles between the current and
   the previous channel. A channel is considered "previous" if it has been
@@ -210,15 +210,15 @@
   'current/next' information will be displayed below this line. This display
   automatically goes away after about five seconds, or if any key is pressed.
   To bring up the channel display without switching channels you can press
-  the "Ok" button.
+  the "Ok" key.
 
 * Selecting audio tracks
 
   If the current channel or recording provides different audio tracks (for
-  different languages or Dolby Digital), the "Green" button in the "VDR" menu can
+  different languages or Dolby Digital), the "Green" key in the "VDR" menu can
   be pressed to bring up the "Audio" menu. Within this menu, the "Up" and "Down"
   keys can be used to switch between the audio tracks. If your remote control has
-  a dedicated "Audio" button, the first press of that button brings up the "Audio"
+  a dedicated "Audio" key, the first press of that key brings up the "Audio"
   menu, and every further press switches to the next available audio track.
 
   The "Left" and "Right" keys can be used to switch between "mono left", "stereo"
@@ -242,7 +242,7 @@
   If the 'channels.conf' file contains "group separators" you can switch
   through these groups by pressing the "Left" and "Right" key while no
   menu is being displayed. The channel display will show the name of the
-  group, and if you press the "Ok" button while the group name is being
+  group, and if you press the "Ok" key while the group name is being
   displayed, you will switch to the first channel of that group.
 
   Channel groups can be whatever you decide them to be. You can either
@@ -251,11 +251,11 @@
 
 * Instant Recording
 
-  You can start recording the current channel by pressing the "Red" button
+  You can start recording the current channel by pressing the "Red" key
   in the "VDR" menu. This will create a timer event named "@channelname" that
   starts at the current time and by default records for 3 hours.
   If you want to modify the recording time you need to edit the timer.
-  Stop instant recording by pressing the "Menu" button and selecting
+  Stop instant recording by pressing the "Menu" key and selecting
   "Stop Recording", or by disabling the timer. The default priority, lifetime
   and recording time can be defined in the "Setup/Recording" menu.
 
@@ -267,7 +267,7 @@
   "Record") and immediately begin replaying that recording. Replay will be
   put into "pause" mode, so you can attend to whatever it was that disturbed
   your live viewing session. Once you're back, simply press the "Up" or "Play"
-  button and you'll be watching the current channel in time shift mode, right
+  key and you'll be watching the current channel in time shift mode, right
   from the point where you left off. The instant recording VDR has started
   will use the parameters for "Pause priority" and "Pause lifetime" as defined
   in the "Setup/Recording" menu. Recording time will be the same as for
@@ -277,12 +277,12 @@
 * Replaying a Recording
 
   All recordings are listed in the "Recordings" menu. Browse through the
-  list with the "Up" and "Down" button and press "Ok" (or the "Red" button)
+  list with the "Up" and "Down" key and press "Ok" (or the "Red" key)
   to start playback. New recordings are marked with an '*'.
   If the Setup parameter RecordingDirs has been set and there are recordings
   from repeating timers organized in a subdirectory structure, only the
   directory is displayed and it can be opened by pressing "Ok" (or the "Red"
-  button). A directory entry displays the total number of recordings within
+  key). A directory entry displays the total number of recordings within
   that directory (and any possible subdirectory thereof) as well as the total
   number of new recordings (as opposed to a recording's entry, which displays
   the date and time of the recording).
@@ -295,15 +295,15 @@
   the order in which they were broadcast.
 
   Playback can be stopped via the "VDR" menu by selecting "Stop replaying",
-  or by pressing the "Blue" button outside the menu.
+  or by pressing the "Blue" key outside the menu.
   A previously stopped playback session can be resumed by pressing the "Blue"
-  button in the "VDR" menu.
+  key in the "VDR" menu.
 
 * Processing Recordings
 
   The configuration file 'reccmds.conf' can be used to define system commands
   that can be applied to the recording that is currently highlighted in the
-  "Recordings" menu. The "Red" button in the "Recordings" menu opens the "Recording
+  "Recordings" menu. The "Red" key in the "Recordings" menu opens the "Recording
   commands" menu if there are commands defined in the file 'reccmds.conf'. Pressing
   one of the keys '1'..'9' in the "Recordings" menu executes the corresponding
   command from 'reccmds.conf' (see also "Executing system commands" below).
@@ -322,20 +322,20 @@
     Right   Runs playback forward or backward at a higher speed; press
             again to resume normal speed. If in Pause mode, runs forward or
             backward at a slower speed; press again to return to pause mode.
-            Pressing and holding down the button performs the function until
-            the button is released again.
+            Pressing and holding down the key performs the function until
+            the key is released again.
             If "Multi Speed Mode" has been enabled in the "Setup" menu, the
-            function of these buttons changes in a way that gives you three
+            function of these keys changes in a way that gives you three
             fast and slow speeds, through which you can switch by pressing
-            the respective button several times.
+            the respective key several times.
   - Red     Jump to a specific location. Enter the time you want to jump to
             and then press "Left" or "Right" to jump relative to the current
             position, "Up" to jump to an absolute position, and "Down" to
             jump and pause at an absolute position.
   - Green
     Yellow  Skips about 60 seconds back or forward.
-            Pressing and holding down the button performs the function until
-            the button is released again.
+            Pressing and holding down the key performs the function until
+            the key is released again.
   - Ok      Brings up the replay progress display, which shows the date,
             time and title of the recording, a progress bar and the
             current and total time of the recording.
@@ -469,7 +469,7 @@
   First day: The date of the first day when this timer shall start recording
              (only available for repeating timers).
 
-  A timer can also be programmed by pressing the "Red" button on the "Schedule",
+  A timer can also be programmed by pressing the "Red" key on the "Schedule",
   "Now", "Next" or "Event" menus.
 
 * Parameters in the "Setup" menu
@@ -513,7 +513,7 @@
   Info on channel switch = yes
                          Turns the display of the current/next information on
                          or off when switching the channel. The information is
-                         always displayed when pressing the "Ok" button in
+                         always displayed when pressing the "Ok" key in
                          normal viewing mode.
 
   Timeout requested channel info = yes
@@ -535,10 +535,10 @@
                                (first) line of the list directly to the first (last)
                                one.
 
-  Menu button closes = no
-                         If set to "yes", pressing the "Menu" button while there is
+  Menu key closes = no
+                         If set to "yes", pressing the "Menu" key while there is
                          anything displayed on the OSD will close the OSD. If set
-                         to "no", the "Menu" button will open the main menu after
+                         to "no", the "Menu" key will open the main menu after
                          closing a temporary display, like, for instance, the channel
                          display.
 
@@ -607,7 +607,7 @@
                          different languages, the preferred languages are checked
                          in the given order to decide which one to take.
 
-  Scan                   The "Red" button in the "Setup/EPG" menu can be used to
+  Scan                   The "Red" key in the "Setup/EPG" menu can be used to
                          force an EPG scan on a single DVB card system. If pressed,
                          and the primary DVB device is currently not recording or
                          replaying, it will loop through the transponders once and
@@ -711,7 +711,7 @@
                          yes = use it (and create subdirectories)
 
   Use VPS = 0            Defines whether a timer that is created from an EPG entry
-                         (by pressing the "Record" (red) button in the "Schedules"
+                         (by pressing the "Record" (red) key in the "Schedules"
                          or "What's on now/next?" menu) will automatically use VPS
                          if the event it is created for has a VPS time.
 
@@ -723,7 +723,7 @@
 
   Mark instant recording = yes
                          Defines whether an "instant recording" (started by
-                         pressing the "Red" button in the "VDR" menu) will be
+                         pressing the "Red" key in the "VDR" menu) will be
                          marked with a '@' character to make it distinguishable
                          from timer recordings in the "Recordings" menu.
 
@@ -786,9 +786,18 @@
                          connection after which the connection is automatically
                          closed. Default is 300, a value of 0 means no timeout.
 
-  Zap Timeout = 3        The time (in seconds) until a channel counts as "previous"
+  Zap timeout = 3        The time (in seconds) until a channel counts as "previous"
                          for switching with '0'
 
+  Channel entry timeout = 1000
+                         The time (in milliseconds) after the last keypress until
+                         a numerically entered channel number is considered
+                         complete, and the channel is switched. Default is 1000,
+                         a value of 0 turns this off, so a numerically entered
+                         channel number then needs to be confirmed with the "Ok"
+                         key. Note that the total maximum is also limited by
+                         the "OSD/Channel info time" parameter.
+
   Initial channel = 0    The number of the channel that shall be tuned to when
                          VDR starts. Default is 0, which means that it will
                          tune to the channel that was on before VDR was stopped.
diff -ruN vdr-1.5.0/Makefile vdr-1.5.1/Makefile
--- vdr-1.5.0/Makefile	2006-11-11 14:55:32.000000000 +0100
+++ vdr-1.5.1/Makefile	2007-02-24 14:23:12.000000000 +0100
@@ -4,7 +4,7 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: Makefile 1.96 2006/11/11 13:55:32 kls Exp $
+# $Id: Makefile 1.97 2007/02/24 13:23:12 kls Exp $
 
 .DELETE_ON_ERROR:
 
@@ -35,7 +35,7 @@
 OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbci.o dvbosd.o\
        dvbplayer.o dvbspu.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\
        lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o rcu.o\
-       receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o\
+       receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\
        skinclassic.o skins.o skinsttng.o sources.o spu.o status.o svdrp.o themes.o thread.o\
        timers.o tools.o transfer.o vdr.o videodir.o
 
diff -ruN vdr-1.5.0/PLUGINS.html vdr-1.5.1/PLUGINS.html
--- vdr-1.5.0/PLUGINS.html	2007-01-07 15:08:55.000000000 +0100
+++ vdr-1.5.1/PLUGINS.html	2007-02-24 16:32:06.000000000 +0100
@@ -6,7 +6,7 @@
 
 <center><h1>The VDR Plugin System</h1></center>
 
-<center><b>Version 1.5.0</b></center>
+<center><b>Version 1.5.1</b></center>
 <p>
 <center>
 Copyright &copy; 2006 Klaus Schmidinger<br>
@@ -14,9 +14,12 @@
 <a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a>
 </center>
 <p>
-<!--X1.5.0--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<!--X1.5.0--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
 Important modifications introduced in version 1.5.0 are marked like this.
 <!--X1.5.0--></td></tr></table>
+<!--X1.5.1--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+Important modifications introduced in version 1.5.1 are marked like this.
+<!--X1.5.1--></td></tr></table>
 <p>
 VDR provides an easy to use plugin interface that allows additional functionality
 to be added to the program by implementing a dynamically loadable library file.
@@ -55,6 +58,9 @@
 <li><a href="#Housekeeping">Housekeeping</a>
 <li><a href="#Main thread hook">Main thread hook</a>
 <li><a href="#Activity">Activity</a>
+<!--X1.5.1--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<li><a href="#Wakeup">Wakeup</a>
+<!--X1.5.1--></td></tr></table>
 <li><a href="#Setup parameters">Setup parameters</a>
 <li><a href="#The Setup menu">The Setup menu</a>
 <li><a href="#Configuration files">Configuration files</a>
@@ -76,7 +82,7 @@
 <li><a href="#Devices">Devices</a>
 <li><a href="#Audio">Audio</a>
 <li><a href="#Remote Control">Remote Control</a>
-<!--X1.5.0--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<!--X1.5.0--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
 <li><a href="#Conditional Access">Conditional Access</a>
 <!--X1.5.0--></td></tr></table>
 </ul>
@@ -675,6 +681,41 @@
 the shutdown will take place. As soon as one prompt is not confirmed, no
 further plugins will be queried and no shutdown will be done.
 
+<!--X1.5.1--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<a name="Wakeup"><hr><h2>Wakeup</h2>
+
+<center><i><b>Wake me up before you go-go</b></i></center><p>
+
+If a plugin wants to schedule activity for a later time, or wants to perform
+periodic activity at a certain time at night, and if VDR shall wake up from
+shutdown at that time, the plugin can implement the function
+
+<p><table><tr><td bgcolor=#F0F0F0><pre>
+virtual time_t WakeupTime(void);
+</pre></td></tr></table><p>
+
+which shall return the time of the next custom wakeup time, or 0 if no wakeup
+is planned. VDR will pass the most recent wakeup time of all plugins, or the next
+timer time, whichever comes first, to the shutdown script. The following sample
+will wake up VDR every night at 1:00:
+
+<p><table><tr><td bgcolor=#F0F0F0><pre>
+time_t MyPlugin::WakeupTime(void)
+{
+  time_t Now = time(NULL);
+  time_t Time = cTimer::SetTime(Now, cTimer::TimeToInt(100));
+  if (Time &lt;= Now)
+     Time = cTimer::IncDay(Time, 1);
+  return Time;
+}
+</pre></td></tr></table><p>
+
+After wakeup, the plugin shall continue to return the wakeup time and shall
+return a string when <tt>Active()</tt> is called at that time, otherwise VDR may shut down
+again instantly. If <tt>WakeupTime()</tt> returns a time that is not in
+the future, the time will be ignored.
+<!--X1.5.1--></td></tr></table>
+
 <a name="Setup parameters"><hr><h2>Setup parameters</h2>
 
 <center><i><b>Remember me...</b></i></center><p>
@@ -2046,7 +2087,7 @@
 
 The other parameters have the same meaning as in the first version of this function.
 
-<!--X1.5.0--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<!--X1.5.0--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
 <a name="Conditional Access"><hr><h2>Conditional Access</h2>
 
 <center><i><b>Members only!</b></i></center><p>
diff -ruN vdr-1.5.0/config.c vdr-1.5.1/config.c
--- vdr-1.5.0/config.c	2006-07-22 13:57:51.000000000 +0200
+++ vdr-1.5.1/config.c	2007-02-25 14:58:45.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.c 1.146 2006/07/22 11:57:51 kls Exp $
+ * $Id: config.c 1.150 2007/02/25 13:58:45 kls Exp $
  */
 
 #include "config.h"
@@ -67,8 +67,8 @@
      asprintf(&cmdbuf, "%s %s", command, Parameters);
   const char *cmd = cmdbuf ? cmdbuf : command;
   dsyslog("executing command '%s'", cmd);
-  FILE *p = popen(cmd, "r");
-  if (p) {
+  cPipe p;
+  if (p.Open(cmd, "r")) {
      int l = 0;
      int c;
      while ((c = fgetc(p)) != EOF) {
@@ -78,7 +78,7 @@
            }
      if (result)
         result[l] = 0;
-     pclose(p);
+     p.Close();
      }
   else
      esyslog("ERROR: can't open pipe for command '%s'", cmd);
@@ -222,7 +222,7 @@
   TimeoutRequChInfo = 1;
   MenuScrollPage = 1;
   MenuScrollWrap = 0;
-  MenuButtonCloses = 0;
+  MenuKeyCloses = 0;
   MarkInstantRecord = 1;
   strcpy(NameInstantRecord, "TITLE EPISODE");
   InstantRecordTime = 180;
@@ -242,6 +242,7 @@
   EPGLinger = 0;
   SVDRPTimeout = 300;
   ZapTimeout = 3;
+  ChannelEntryTimeout = 1000;
   PrimaryLimit = 0;
   DefaultPriority = 50;
   DefaultLifetime = 99;
@@ -267,6 +268,7 @@
   SplitEditedFiles = 0;
   MinEventTimeout = 30;
   MinUserInactivity = 300;
+  NextWakeupTime = 0;
   MultiSpeedMode = 0;
   ShowReplayMode = 0;
   ResumeID = 0;
@@ -383,7 +385,7 @@
   else if (!strcasecmp(Name, "TimeoutRequChInfo"))   TimeoutRequChInfo  = atoi(Value);
   else if (!strcasecmp(Name, "MenuScrollPage"))      MenuScrollPage     = atoi(Value);
   else if (!strcasecmp(Name, "MenuScrollWrap"))      MenuScrollWrap     = atoi(Value);
-  else if (!strcasecmp(Name, "MenuButtonCloses"))    MenuButtonCloses   = atoi(Value);
+  else if (!strcasecmp(Name, "MenuKeyCloses"))       MenuKeyCloses      = atoi(Value);
   else if (!strcasecmp(Name, "MarkInstantRecord"))   MarkInstantRecord  = atoi(Value);
   else if (!strcasecmp(Name, "NameInstantRecord"))   strn0cpy(NameInstantRecord, Value, MaxFileName);
   else if (!strcasecmp(Name, "InstantRecordTime"))   InstantRecordTime  = atoi(Value);
@@ -403,6 +405,7 @@
   else if (!strcasecmp(Name, "EPGLinger"))           EPGLinger          = atoi(Value);
   else if (!strcasecmp(Name, "SVDRPTimeout"))        SVDRPTimeout       = atoi(Value);
   else if (!strcasecmp(Name, "ZapTimeout"))          ZapTimeout         = atoi(Value);
+  else if (!strcasecmp(Name, "ChannelEntryTimeout")) ChannelEntryTimeout= atoi(Value);
   else if (!strcasecmp(Name, "PrimaryLimit"))        PrimaryLimit       = atoi(Value);
   else if (!strcasecmp(Name, "DefaultPriority"))     DefaultPriority    = atoi(Value);
   else if (!strcasecmp(Name, "DefaultLifetime"))     DefaultLifetime    = atoi(Value);
@@ -428,6 +431,7 @@
   else if (!strcasecmp(Name, "SplitEditedFiles"))    SplitEditedFiles   = atoi(Value);
   else if (!strcasecmp(Name, "MinEventTimeout"))     MinEventTimeout    = atoi(Value);
   else if (!strcasecmp(Name, "MinUserInactivity"))   MinUserInactivity  = atoi(Value);
+  else if (!strcasecmp(Name, "NextWakeupTime"))      NextWakeupTime     = atoi(Value);
   else if (!strcasecmp(Name, "MultiSpeedMode"))      MultiSpeedMode     = atoi(Value);
   else if (!strcasecmp(Name, "ShowReplayMode"))      ShowReplayMode     = atoi(Value);
   else if (!strcasecmp(Name, "ResumeID"))            ResumeID           = atoi(Value);
@@ -451,7 +455,7 @@
   Store("TimeoutRequChInfo",  TimeoutRequChInfo);
   Store("MenuScrollPage",     MenuScrollPage);
   Store("MenuScrollWrap",     MenuScrollWrap);
-  Store("MenuButtonCloses",   MenuButtonCloses);
+  Store("MenuKeyCloses",      MenuKeyCloses);
   Store("MarkInstantRecord",  MarkInstantRecord);
   Store("NameInstantRecord",  NameInstantRecord);
   Store("InstantRecordTime",  InstantRecordTime);
@@ -471,6 +475,7 @@
   Store("EPGLinger",          EPGLinger);
   Store("SVDRPTimeout",       SVDRPTimeout);
   Store("ZapTimeout",         ZapTimeout);
+  Store("ChannelEntryTimeout",ChannelEntryTimeout);
   Store("PrimaryLimit",       PrimaryLimit);
   Store("DefaultPriority",    DefaultPriority);
   Store("DefaultLifetime",    DefaultLifetime);
@@ -496,6 +501,7 @@
   Store("SplitEditedFiles",   SplitEditedFiles);
   Store("MinEventTimeout",    MinEventTimeout);
   Store("MinUserInactivity",  MinUserInactivity);
+  Store("NextWakeupTime",     NextWakeupTime);
   Store("MultiSpeedMode",     MultiSpeedMode);
   Store("ShowReplayMode",     ShowReplayMode);
   Store("ResumeID",           ResumeID);
diff -ruN vdr-1.5.0/config.h vdr-1.5.1/config.h
--- vdr-1.5.0/config.h	2007-01-07 15:09:31.000000000 +0100
+++ vdr-1.5.1/config.h	2007-02-25 14:58:59.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.h 1.283 2007/01/07 14:09:31 kls Exp $
+ * $Id: config.h 1.287 2007/02/25 13:58:59 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -21,13 +21,13 @@
 
 // VDR's own version number:
 
-#define VDRVERSION  "1.5.0"
-#define VDRVERSNUM   10500  // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION  "1.5.1"
+#define VDRVERSNUM   10501  // Version * 10000 + Major * 100 + Minor
 
 // The plugin API's version number:
 
-#define APIVERSION  "1.5.0"
-#define APIVERSNUM   10500  // Version * 10000 + Major * 100 + Minor
+#define APIVERSION  "1.5.1"
+#define APIVERSNUM   10501  // 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
@@ -206,7 +206,7 @@
   int TimeoutRequChInfo;
   int MenuScrollPage;
   int MenuScrollWrap;
-  int MenuButtonCloses;
+  int MenuKeyCloses;
   int MarkInstantRecord;
   char NameInstantRecord[MaxFileName];
   int InstantRecordTime;
@@ -225,6 +225,7 @@
   int EPGLinger;
   int SVDRPTimeout;
   int ZapTimeout;
+  int ChannelEntryTimeout;
   int PrimaryLimit;
   int DefaultPriority, DefaultLifetime;
   int PausePriority, PauseLifetime;
@@ -244,6 +245,7 @@
   int MaxVideoFileSize;
   int SplitEditedFiles;
   int MinEventTimeout, MinUserInactivity;
+  time_t NextWakeupTime;
   int MultiSpeedMode;
   int ShowReplayMode;
   int ResumeID;
diff -ruN vdr-1.5.0/device.c vdr-1.5.1/device.c
--- vdr-1.5.0/device.c	2007-01-07 14:41:07.000000000 +0100
+++ vdr-1.5.1/device.c	2007-01-13 13:05:00.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.c 1.138 2007/01/07 13:41:07 kls Exp $
+ * $Id: device.c 1.139 2007/01/13 12:05:00 kls Exp $
  */
 
 #include "device.h"
@@ -334,6 +334,7 @@
              imp <<= 8; imp |= min(max((NumUsableSlots ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF);              // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
              imp <<= 1; imp |= ndr;                                                                                  // avoid devices if we need to detach existing receivers
              imp <<= 1; imp |= device[i]->IsPrimaryDevice();                                                         // avoid the primary device
+             imp <<= 1; imp |= NumUsableSlots ? 0 : device[i]->HasCi();                                              // avoid cards with Common Interface for FTA channels
              imp <<= 1; imp |= device[i]->HasDecoder();                                                              // avoid full featured cards
              imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
              if (imp < Impact) {
@@ -367,6 +368,11 @@
   return d;
 }
 
+bool cDevice::HasCi(void)
+{
+  return false;
+}
+
 void cDevice::SetCamSlot(cCamSlot *CamSlot)
 {
   camSlot = CamSlot;
diff -ruN vdr-1.5.0/device.h vdr-1.5.1/device.h
--- vdr-1.5.0/device.h	2007-01-03 15:14:29.000000000 +0100
+++ vdr-1.5.1/device.h	2007-01-13 12:33:57.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.h 1.80 2007/01/03 14:14:29 kls Exp $
+ * $Id: device.h 1.81 2007/01/13 11:33:57 kls Exp $
  */
 
 #ifndef __DEVICE_H
@@ -314,6 +314,8 @@
   time_t startScrambleDetection;
   cCamSlot *camSlot;
 public:
+  virtual bool HasCi(void);
+         ///< Returns true if this device has a Common Interface.
   void SetCamSlot(cCamSlot *CamSlot);
          ///< Sets the given CamSlot to be used with this device.
   cCamSlot *CamSlot(void) const { return camSlot; }
diff -ruN vdr-1.5.0/dvbdevice.c vdr-1.5.1/dvbdevice.c
--- vdr-1.5.0/dvbdevice.c	2007-01-05 12:09:51.000000000 +0100
+++ vdr-1.5.1/dvbdevice.c	2007-02-25 12:46:52.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: dvbdevice.c 1.161 2007/01/05 11:09:51 kls Exp $
+ * $Id: dvbdevice.c 1.164 2007/02/25 11:46:52 kls Exp $
  */
 
 #include "dvbdevice.h"
@@ -155,15 +155,12 @@
               ; // just to clear the event queue - we'll read the actual status below
         }
      }
-  do {
-     int stat = ioctl(fd_frontend, FE_READ_STATUS, &Status);
-     if (stat == 0)
-        return true;
-     if (stat < 0) {
-        if (errno == EINTR)
-           continue;
+  while (1) {
+        if (ioctl(fd_frontend, FE_READ_STATUS, &Status) != -1)
+           return true;
+        if (errno != EINTR)
+           break;
         }
-     } while (0);
   return false;
 }
 
@@ -509,6 +506,11 @@
   return spuDecoder;
 }
 
+bool cDvbDevice::HasCi(void)
+{
+  return ciAdapter;
+}
+
 uchar *cDvbDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
 {
   if (devVideoIndex < 0)
diff -ruN vdr-1.5.0/dvbdevice.h vdr-1.5.1/dvbdevice.h
--- vdr-1.5.0/dvbdevice.h	2007-01-05 11:39:52.000000000 +0100
+++ vdr-1.5.1/dvbdevice.h	2007-02-25 13:23:57.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: dvbdevice.h 1.42 2007/01/05 10:39:52 kls Exp $
+ * $Id: dvbdevice.h 1.44 2007/02/25 12:23:57 kls Exp $
  */
 
 #ifndef __DVBDEVICE_H
@@ -19,7 +19,7 @@
 #error VDR requires Linux DVB driver API version 3!
 #endif
 
-#define MAXDVBDEVICES  4
+#define MAXDVBDEVICES  8
 
 class cDvbTuner;
 
@@ -84,6 +84,11 @@
 protected:
   virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
 
+// Common Interface facilities:
+
+public:
+  virtual bool HasCi(void);
+
 // Image Grab facilities
 
 private:
diff -ruN vdr-1.5.0/dvbspu.c vdr-1.5.1/dvbspu.c
--- vdr-1.5.0/dvbspu.c	2006-04-17 14:45:05.000000000 +0200
+++ vdr-1.5.1/dvbspu.c	2007-02-03 11:13:18.000000000 +0100
@@ -8,7 +8,7 @@
  *
  * parts of this file are derived from the OMS program.
  *
- * $Id: dvbspu.c 1.21 2006/04/17 12:45:05 kls Exp $
+ * $Id: dvbspu.c 1.22 2007/02/03 10:13:18 kls Exp $
  */
 
 #include "dvbspu.h"
@@ -504,9 +504,8 @@
                 default:
                     esyslog("invalid sequence in control header (%.2x)",
                             spu[i]);
-                    assert(0);
-                    i++;
-                    break;
+                    Empty();
+                    return 0;
                 }
             }
             if (fodd != 0 && feven != 0) {
diff -ruN vdr-1.5.0/i18n.c vdr-1.5.1/i18n.c
--- vdr-1.5.0/i18n.c	2007-01-07 13:19:15.000000000 +0100
+++ vdr-1.5.1/i18n.c	2007-02-25 14:59:28.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: i18n.c 1.286 2007/01/07 12:19:15 kls Exp $
+ * $Id: i18n.c 1.291 2007/02/25 13:59:28 kls Exp $
  *
  * Translations provided by:
  *
@@ -119,7 +119,7 @@
     "iso8859-7",
     "iso8859-1",
     "iso8859-2",
-    "iso8859-1",
+    "iso8859-2",
     "iso8859-1",
     "iso8859-5",
     "iso8859-2",
@@ -231,7 +231,7 @@
     "×ñïíïðñïãñáììáôéóìïß",
     "Timers",
     "Timer-e",
-    "Idözítö",
+    "Idõzítõ",
     "Temporitzadors",
     "ÂÐÙÜÕàë",
     "Termini",
@@ -385,7 +385,7 @@
     "Ôñïðïðïßçóç ÷ñïíïðñïãñáììáôéóìïý",
     "Ändra timer",
     "Modificare timer",
-    "Idözítö megváltoztatása",
+    "Idõzítõ megváltoztatása",
     "Editar temporitzador",
     "ÃáâÐÝÞÒÚÐ âÐÙÜÕàÐ",
     "Ureðivanje termina",
@@ -694,7 +694,7 @@
     "",// TODO
     "Timer",
     "Timer",
-    "Idözítö",
+    "Idõzítõ",
     "",// TODO
     "ÂÐÙÜÕà",
     "",// TODO
@@ -936,7 +936,7 @@
     "Åðüìåíï",
     "Nästa",
     "Urmãtor",
-    "Következö",
+    "Következõ",
     "Següent",
     "´ÐÛÕÕ",
     "Slijedi",
@@ -1157,7 +1157,7 @@
     "ÄéáãñáöÞ ÷ñïíïðñïãñáììáôéóìïý;?",
     "Ta bort timern?",
     "ªterg timer-ul?",
-    "Idözítö törlése?",
+    "Idõzítõ törlése?",
     "Esborrar el temporitzador?",
     "ÃÔÐÛØâì âÐÙÜÕà?",
     "Obrisati termin?",
@@ -1341,6 +1341,28 @@
     "Optagelse igang - genstart alligevel?",
     "Systém je zaneprázdnìn - pøesto restartovat?",
   },
+  { "Editing - restart anyway?",
+    "Schnitt läuft - trotzdem neu starten?",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+  },
   { "Recording - shut down anyway?",
     "Aufnahme läuft - trotzdem ausschalten?",
     "Snemanje - zares izklopi?",
@@ -1377,7 +1399,7 @@
     "ÁíáìÝíåôáé åããñáöÞ óÝ %ld ëåðôÜ - ÔåëéêÜ íá ôåñìáôéóôåß?",
     "Inspelning startar om %ld minuter, vill du avsluta?",
     "Înregistrez peste %ld minute - închid, totuºi?",
-    "Felvétel %ld perc mulva kezdödik - mégis kikapcsolni?",
+    "Felvétel %ld perc mulva kezdõdik - mégis kikapcsolni?",
     "Hi ha una gravació en %ld minuts - Apagar de totes maneres?",
     "ÇÕàÕ× %ld ÜØÝãâ ÝÐçÝñâáï ×ÐßØáì - ÔÕÙáâÒØâÕÛìÝÞ ÒëÚÛîçØâì?",
     "Snimanje za %ld minuta - svejedno iskljuèiti?",
@@ -1407,6 +1429,116 @@
     "Tryk vilkårlig tast for at annullere sluk",
     "Jakákoliv klávesa zru¹í vypnutí",
   },
+  { "Press any key to cancel restart",
+    "Taste drücken, um Neustart abzubrechen",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+  },
+  { "VDR will shut down later - press Power to force",
+    "VDR schaltet später aus - Power zum erzwingen",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "VDR sammuu myöhemmin - pakota virtakytkimellä",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+  },
+  { "VDR will shut down in %s minutes",
+    "VDR wird in %s Minuten ausschalten",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "VDR sammuu %s minuutin kuluttua",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+  },
+  { "Editing - shut down anyway?",
+    "Schnitt läuft - trotzdem ausschalten?",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "Leikkaus kesken - sammutetaanko?",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+  },
+  { "Plugin %s wakes up in %ld min, continue?",
+    "Plugin %s wacht in %ld Min auf, weiter?",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "Laajennos %s herää %ld minuutin kuluttua - sammutetaanko?",
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+    "",//TODO
+  },
   // Channel parameters:
   { "Name",
     "Name",
@@ -2149,7 +2281,7 @@
     "Ðñþôç ìÝñá",
     "Första dag",
     "Prima zi",
-    "Elsö nap",
+    "Elsõ nap",
     "Primer dia",
     "¿ÕàÒëÙ ÔÕÝì",
     "Prvi dan",
@@ -2172,7 +2304,7 @@
     "Ôï êáíÜëç ÷ñéóéìïðïéåßôáé áðü ÷ñïíïðñïãñáììáôéóìü!",
     "Kanalen används av en timer!",
     "Canalul este utilizat de un timer!",
-    "Az adót az idözítö használja!",
+    "Az adót az idõzítõ használja!",
     "Canal en ús per un temporitzador!",
     "ºÐÝÐÛ ×ÐÝïâ âÐÙÜÕàÞÜ!",
     "Program je trenutno zauzet terminom za snimanje",
@@ -2304,7 +2436,7 @@
     "",//TODO
     "strax VPS inspelning...",
     "Urmeazã o înregistrare VPS!",
-    "VPS-felvétel rögtön kezdödik!",
+    "VPS-felvétel rögtön kezdõdik!",
     "",//TODO
     "VPS-·ÐßØáì áÚÞàÞ ÝÐçÝÕâáï",
     "",//TODO
@@ -2348,7 +2480,7 @@
     "Ôï êáíÜëç äÝí åßíáé äéáèÝóéìï!",
     "Kanalen är inte tillgänglig!",
     "Canal indisponibil",
-    "Az adó nem elérhetö",
+    "Az adó nem elérhetõ",
     "Canal no disponible!",
     "ºÐÝÐÛ ÝÕÔÞáâãßÕÝ!",
     "Program nije dostupan!",
@@ -2370,7 +2502,7 @@
     "Ïé ñéèìýóåéò ôïí êáíáëéþí áëëõëïóõìðßðôïõí!",
     "Kanalinställningarna är ej unika!",
     "Parametrii canalului nu sunt univoci!",
-    "Az adóbeállítások nem egyértelmüek",
+    "Az adóbeállítások nem egyértelmûek",
     "Propietats del canal duplicades!",
     "½ÐáâàÞÙÚØ ÚÐÝÐÛÐ ÝÕ ãÝØÚÐÛìÝë!",
     "Parametri programa nisu jednoznaèni!",
@@ -2524,7 +2656,7 @@
     "",//TODO
     "Otillräcklingt diskutrymme för inspelning!",
     "Insuficient spaþiul pe disc pentru înregistrare!",
-    "Nincs elegendö hely a felvételre",
+    "Nincs elegendõ hely a felvételre",
     "",//TODO
     "½ÕÔÞáâÐâÞçÝÞ ÜÕáâÐ ÝÐ ÔØáÚÕ ÔÛï ÝÐçÐÛÐ ×ÐßØáØ",
     "",//TODO
@@ -3186,7 +3318,7 @@
     "×ñüíïò Ýíäåéîçò ìõíçìÜôùí (ä)",
     "Tid för meddelanden (sek)",
     "Timp afiºare mesaje (sec)",
-    "Információ feltüntetésének idötartama",
+    "Információ feltûntetésének idõtartama",
     "Durada dels missatges (s)",
     "´ÛØâÕÛìÝÞáâì ßÞÚÐ×Ð áÞÞÑéÕÝØÙ (áÕÚ)",
     "Vrijeme prikaza poruka (s)",
@@ -3208,7 +3340,7 @@
     "×ñéóçìïðïßçóç ìéêñüí ãñáììáôïóåéñþí",
     "Använd liten font",
     "Utilizare fonturi mici",
-    "Kisbetüt használni",
+    "Kisbetût használni",
     "",// TODO
     "¸áßÞÛì×ÞÒÐâì ÜÕÛÚØÙ èàØäâ",
     "Koristi mala slova",
@@ -3252,7 +3384,7 @@
     "ÅîáñôÜôå áðü ôÞí åðéöÜíåéá",
     "skin beroende",
     "dep. de skin",
-    "Menü nézetétöl függöen",
+    "Menü nézetétõl függõen",
     "",// TODO
     "áÞÓÛÐáÝÞ âÕÜÕ",
     "ovisno o povr¹ini",
@@ -3318,7 +3450,7 @@
     "÷ñüíïò Ýíäåéêóçò ðëçñïöïñßùí êáíáëéïý óå (ä)",
     "Kanal information (s)",
     "Durata afiºãrii info-canal (s)",
-    "Adásinformáció feltüntetésének idötartama (s)",
+    "Adásinformáció feltûntetésének idõtartama (s)",
     "",// TODO
     "¿ÞÚÐ× ØÝäÞàÜÐæØØ Þ ÚÐÝÐÛÕ (áÕÚ)",
     "Vrijeme prikaza informacije o programu (s)",
@@ -3414,7 +3546,7 @@
     "Scroll rundt",
     "Z konce na zaèátek",
   },
-  { "Setup.OSD$Menu button closes",
+  { "Setup.OSD$Menu key closes",
     "Menu-Taste schließt",
     "Meni gumb zapre meni",
     "Usare il bottone Menu per chiudere",
@@ -3472,7 +3604,7 @@
     "×ñüíïò äéÜñêåéáò åîÝôáóçò EPG óå þñåò",
     "EPG sökning timeout",
     "Interval achiziþie EPG (h)",
-    "Fennmaradt idö az EPG-újításig (h)",
+    "Fennmaradt idõ az EPG-újításig (h)",
     "Màxim d'Hores a cercar per la Guia",
     "·ÐÔÕàÖÚÐ áÚÐÝØàÞÒÐÝØï âÕÛÕÓØÔÐ (ç)",
     "Vrijeme do EPG pregleda (h)",
@@ -3538,7 +3670,7 @@
     "Óõíôïíéóìüò þñáò õðïëïãéóôÞ",
     "Ställ in systemtid",
     "Potriveºte ceasul sistem",
-    "Az idö beállítása",
+    "Az idõ beállítása",
     "Ajustar l'hora del sistema",
     "ÃáâÐÝÞÒØâì áØáâÕÜÝÞÕ ÒàÕÜï",
     "Podesi vrijeme sistema",
@@ -3560,7 +3692,7 @@
     "Áíáìåôáäüôçò óõíôïíéóìïý þñáò",
     "Använd klockan från transponder",
     "Preia ora din transponder",
-    "Idöhöz tartozó Transponder",
+    "Idõhöz tartozó Transponder",
     "Usar el temps del múltiplex",
     "¸áßÞÛì×ÞÒÐâì ÒàÕÜï âàÐÝáßÞÝÔÕàÐ",
     "Transponder za pode¹avanje sata",
@@ -3626,7 +3758,7 @@
     "Êýñéá DVB êÜñôá",
     "Primär DVB enhet",
     "Dispozitiv DVB primar",
-    "Elsö DVB interface",
+    "Elsõ DVB interface",
     "Tarja DVB primària",
     "¾áÝÞÒÝÞÕ DVB-ãáâàÞÙáâÒÞ",
     "Primarni DVB ureðaj",
@@ -4000,7 +4132,7 @@
     "¢íù LNB-Óõ÷íüôçôá (MHz)",
     "Övre LNB frekvens (MHz)",
     "Frecvnþã LNB superioarã (MHz)",
-    "Felsö LNB-frekvencia (MHZ)",
+    "Felsõ LNB-frekvencia (MHZ)",
     "Freqüència LNB alta (MHz)",
     "²ÕàåÝïï çÐáâÞâÐ ÚÞÝÒÕàâÕàÐ (¼³æ)",
     "Gornja LNB frekv. (MHz)",
@@ -4044,7 +4176,7 @@
     "Ðñüóèåôïò ÷ñüíïò óôçí áñ÷Þ (ëåðôÜ)",
     "Marginal för start (min)",
     "Marjã la pornire (min)",
-    "Idöeltolódás a kezdésnél (perc)",
+    "Idõeltolódás a kezdésnél (perc)",
     "Marge d'inici de gravació (min)",
     "¾ßÕàÕÖÕÝØÕ ÝÐçÐÛÐ ×ÐßØáØ (ÜØÝ)",
     "Rezerva na poèetku snimanja (min)",
@@ -4066,7 +4198,7 @@
     "Ðñüóèåôïò ÷ñüíïò óôü ôÝëïò (ëåðôÜ)",
     "Marginal för stopp (min)",
     "Marjã la oprire (min)",
-    "Idöeltolódás a befejezésnél (perc)",
+    "Idõeltolódás a befejezésnél (perc)",
     "Marge de fi de gravació (min)",
     "·ÐßÐ×ÔëÒÐÝØÕ ÞáâÐÝÞÒÚØ ×ÐßØáØ (ÜØÝ)",
     "Rezerva na kraju (min)",
@@ -4242,7 +4374,7 @@
     "Ðåñéèþñéï VPS (ä)",
     "VPS marginal (s)",
     "Marjã de timp la utilizare VPS (s)",
-    "Idöeltolódás VPS-nél (s)",
+    "Idõeltolódás VPS-nél (s)",
     "",// TODO
     "±ãäÕàÝÞÕ ÒàÕÜï VPS (áÕÚ)",
     "Vremenska rezerva kod VPS (s)",
@@ -4308,7 +4440,7 @@
     "ÄéÜñêåéá óôãìéáßáò åããñáöÞò (ëåðôÜ)",
     "Direktinspelning längd (min)",
     "Timpul de înregistare imediatã (min)",
-    "Felvétel idötartama (perc)",
+    "Felvétel idõtartama (perc)",
     "Temps de gravació instantània (min)",
     "´ÛØâÕÛìÝÞáâì àãçÝÞÙ ×ÐßØáØ (ÜØÝ)",
     "Trajanje direktnog snimanja (min)",
@@ -4440,7 +4572,7 @@
     "ÅëÜ÷éóôïò ÷ñÜíïò ðáñåìâïëÞò (ëåðôÜ)",
     "Minsta händelse-pause (min)",
     "Duratã minimã emisiuni (min)",
-    "Idözitések közötti idötartam (perc)",
+    "Idõzitések közötti idõtartam (perc)",
     "Temps mínim en pausa (min)",
     "¼ØÝ. ÒàÕÜï ÞÖØÔÐÝØï áÞÑëâØï (ÜØÝ)",
     "Minimalno vrijeme pauze",
@@ -4514,6 +4646,28 @@
     "Zap timeout (s)",
     "Èasový limit Zap (s)",
   },
+  { "Setup.Miscellaneous$Channel entry timeout (ms)",
+    "Zeitlimit für Kanaleingabe (ms)",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+  },
   { "Setup.Miscellaneous$Initial channel",
     "Kanal beim Einschalten",
     "Privzeti kanal",
@@ -4550,7 +4704,7 @@
     "",// TODO
     "Ljudstyrka vid uppstart",
     "Volumul la pornire",
-    "Hangerö a bekapcsolásnál",
+    "Hangerõ a bekapcsolásnál",
     "",// TODO
     "³àÞÜÚÞáâì ßàØ ÒÚÛîçÕÝØØ",
     "",// TODO
@@ -4572,7 +4726,7 @@
     "",// TODO
     "som förut",
     "ca mai înainte",
-    "ahogy az elöbb",
+    "ahogy az elõbb",
     "",// TODO
     "ÚÐÚ àÐÝìèÕ",
     "",// TODO
@@ -4640,7 +4794,7 @@
     " áÜâãäåÝæçÞèéßêëìíîïüðñóòôõýö÷øùþ0123456789-.#~,/_@abcdefghijklmnopqrstuvwxyz",
     " abcdefghijklmnopqrstuvwxyzåäö0123456789-.#~,/_@",
     " aãâbcdefghiîjklmnopqrsºtþuvwxyz0123456789-.#~,/_@",
-    " aábcdeéfghiíjklmnoóö¿pqrstuúü¿vwxyz0123456789-.,#~,/_@",
+    " aábcdeéfghiíjklmnoóöõpqrstuúüûvwxyz0123456789-.,#~,/_@",
     " aàbcçdeéèfghiíjklmnoòpqrstuúvwxyz0123456789-.,#~,/_@·",
     " abcdefghijklmnopqrstuvwxyzÐÑÒÓÔÕñÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìîï0123456789-.#~,/_@",
     " abcèædðefghijklmnopqrs¹tuvwxyz¾0123456789-.#~,/_@", // hrv
@@ -4663,7 +4817,7 @@
     "",//TODO
     " 0\t-.#~,/_@1\tabcåä2\tdef3\tghi4\tjkl5\tmnoö6\tpqrs7\ttuv8\twxyz",
     " 0\t-.#~,/_@1\taãâbc2\tdef3\tghiî4\tjkl5\tmno6\tpqrsº7\ttþuv8\twxyz9",
-    " 0\t-.#~,/_@1\taábc2\tdeé3\tghií4\tjkl5\tmnoóö¿6\tpqrs7\ttuúü¿v8\twxyz9",
+    " 0\t-.#~,/_@1\taábc2\tdeéf3\tghií4\tjkl5\tmnoóöõ6\tpqrs7\ttuúüûv8\twxyz9",
     "",//TODO
     "",//TODO
     "",//TODO
@@ -4708,7 +4862,7 @@
     "ÖÜóç 1: Áíß÷íåõóç êþäéêá RC",
     "Steg1: identifiering av kod",
     "Faza 1: Detecþia tipului telecomenzii",
-    "Elsö lépés: távirányító kódjának meghatározása",
+    "Elsõ lépés: távirányító kódjának meghatározása",
     "Fase 1: Detectant el tipus de receptor",
     "ÈÐÓ 1: ¾ßàÕÔÕÛÕÝØÕ âØßÐ ÚÞÔÐ ßãÛìâÐ",
     "Faza 1: detektiranje kôda daljinskog upravljaèa.",
@@ -5347,7 +5501,7 @@
     "Ðñïþèçóç åìðñüò",
     "Snabbspolning framåt",
     "Derulare înainte",
-    "Elöre pörgetni",
+    "Elõre pörgetni",
     "Endavant ràpidament",
     "¿àÞÚàãâÚÐ ÒßÕàñÔ",
     "Naprijed",
@@ -5391,7 +5545,7 @@
     "",// TODO
     "Nästa",
     "Urmãtor",
-    "Elöre",
+    "Elõre",
     "",// TODO
     "²ßÕàÕÔ",
     "",// TODO
@@ -5429,7 +5583,7 @@
     "Ligar",
     "Arrêt",
     "Power",
-    "Virtakytkin",
+    "Virta",
     "Wy³±cz",
     "Apagar",
     "Këåßóéìï",
@@ -5501,7 +5655,7 @@
     "",// TODO
     "Förra kanalen",
     "Canal anterior",
-    "Az elözö adás",
+    "Az elõzõ adás",
     "",// TODO
     "¿àÕÔëÔãéØÙ ÚÐÝÐÛ",
     "",// TODO
@@ -5523,7 +5677,7 @@
     "¸íôáóç+",
     "Volym+",
     "Volum+",
-    "Hangerö+",
+    "Hangerõ+",
     "Volum +",
     "³àÞÜÚÞáâì +",
     "Glasnije", // hrv "Glasnocca +"
@@ -5545,7 +5699,7 @@
     "¸íôáóç-",
     "Volym-",
     "Volum-",
-    "Hangerö-",
+    "Hangerõ-",
     "Volum -",
     "³àÞÜÚÞáâì -",
     "Ti¹e", // hrv Glasnocca -"
@@ -5561,7 +5715,7 @@
     "Sem som",
     "Coupure du son",
     "Lyd av",
-    "Äänetön",
+    "Mykistys",
     "Wycisz",
     "Mudo",
     "Óéùðçëü",
@@ -5832,7 +5986,7 @@
     "¸íôáóç ",
     "Volym ",
     "Volum ",
-    "Hangerö",
+    "Hangerõ",
     "Volum ",
     "³àÞÜÚÞáâì ",
     "Glasnoæa ",
@@ -6052,7 +6206,7 @@
     "ÐÜãùìá æùíôáíïý óÞìáôïò",
     "Pausar direktinspelningen",
     "Trec în pauzã emisiunea transmisã...",
-    "Az élö adás megállítva...",
+    "Az élõ adás megállítva...",
     "Pausa d'emissió en directe...",
     "ÀÕÖØÜ ÞâÛÞÖÕÝÝÞÓÞ ßàÞáÜÞâàÐ...",
     "Zaustavljanje ¾ivog signala...",
diff -ruN vdr-1.5.0/keys.h vdr-1.5.1/keys.h
--- vdr-1.5.0/keys.h	2006-10-14 12:41:20.000000000 +0200
+++ vdr-1.5.1/keys.h	2007-02-25 11:49:35.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: keys.h 1.10 2006/10/14 10:41:20 kls Exp $
+ * $Id: keys.h 1.11 2007/02/25 10:49:35 kls Exp $
  */
 
 #ifndef __KEYS_H
@@ -74,6 +74,7 @@
 #define ISRAWKEY(k)      ((k) != kNone && ((k) & k_Flags) == 0)
 #define NORMALKEY(k)     (eKeys((k) & ~k_Repeat))
 #define ISMODELESSKEY(k) (RAWKEY(k) > k9)
+#define ISREALKEY(k)     (k != kNone && k != k_Plugin)
 
 #define BASICKEY(k)      (eKeys((k) & 0xFFFF))
 #define KBDKEY(k)        (eKeys(((k) << 16) | kKbd))
diff -ruN vdr-1.5.0/libsi/descriptor.c vdr-1.5.1/libsi/descriptor.c
--- vdr-1.5.0/libsi/descriptor.c	2006-05-28 16:25:30.000000000 +0200
+++ vdr-1.5.1/libsi/descriptor.c	2007-02-03 12:45:58.000000000 +0100
@@ -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.21 2006/05/28 14:25:30 kls Exp $
+ *   $Id: descriptor.c 1.22 2007/02/03 11:45:58 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -418,8 +418,16 @@
    return s->polarization;
 }
 
-int SatelliteDeliverySystemDescriptor::getModulation() const {
-   return s->modulation;
+int SatelliteDeliverySystemDescriptor::getModulationSystem() const {
+   return s->modulation_system;
+}
+
+int SatelliteDeliverySystemDescriptor::getModulationType() const {
+   return s->modulation_type;
+}
+
+int SatelliteDeliverySystemDescriptor::getRollOff() const {
+   return s->roll_off;
 }
 
 int SatelliteDeliverySystemDescriptor::getSymbolRate() const {
@@ -462,6 +470,18 @@
    return (HILO(s->frequency_hi) << 16) | HILO(s->frequency_lo);
 }
 
+int TerrestrialDeliverySystemDescriptor::getPriority() const {
+   return s->priority;
+}
+
+int TerrestrialDeliverySystemDescriptor::getTimeSlicingIndicator() const {
+   return s->time_slicing_indicator;
+}
+
+int TerrestrialDeliverySystemDescriptor::getMpeFecIndicator() const {
+   return s->mpe_fec_indicator;
+}
+
 int TerrestrialDeliverySystemDescriptor::getBandwidth() const {
    return s->bandwidth;
 }
@@ -794,6 +814,41 @@
    return s->ancillary_data_identifier;
 }
 
+void S2SatelliteDeliverySystemDescriptor::Parse() {
+   int offset=0;
+   input_stream_identifier=0;
+   data.setPointerAndOffset<const descr_s2_satellite_delivery_system>(s, offset);
+   if (s->scrambling_sequence_selector)
+      data.setPointerAndOffset<const descr_scrambling_sequence_selector>(sss, offset);
+   if (s->multiple_input_stream_flag)
+      input_stream_identifier = *data.getData(offset++);
+}
+
+int S2SatelliteDeliverySystemDescriptor::getScramblingSequenceSelector() const {
+   return s->scrambling_sequence_selector;
+}
+
+int S2SatelliteDeliverySystemDescriptor::getMultipleInputStreamFlag() const {
+   return s->multiple_input_stream_flag;
+}
+
+int S2SatelliteDeliverySystemDescriptor::getBackwardsCompatibilityIndicator() const {
+   return s->backwards_compatibility_indicator;
+}
+
+int S2SatelliteDeliverySystemDescriptor::getScramblingSequenceIndex() const {
+   return sss == NULL ? 0 : (sss->scrambling_sequence_index_hi_lo << 16) | HILO(sss->scrambling_sequence_index_lo);
+}
+
+void ExtensionDescriptor::Parse() {
+   int offset=0;
+   data.setPointerAndOffset<const descr_extension>(s, offset);
+}
+
+int ExtensionDescriptor::getExtensionDescriptorTag() const {
+   return s->descriptor_tag_extension;
+}
+
 int PremiereContentTransmissionDescriptor::getOriginalNetworkId() const {
    return HILO(s->original_network_id);
 }
diff -ruN vdr-1.5.0/libsi/descriptor.h vdr-1.5.1/libsi/descriptor.h
--- vdr-1.5.0/libsi/descriptor.h	2006-05-28 16:25:30.000000000 +0200
+++ vdr-1.5.1/libsi/descriptor.h	2007-02-03 12:45:58.000000000 +0100
@@ -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.15 2006/05/28 14:25:30 kls Exp $
+ *   $Id: descriptor.h 1.16 2007/02/03 11:45:58 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -210,7 +210,9 @@
    int getOrbitalPosition() const;
    int getWestEastFlag() const;
    int getPolarization() const;
-   int getModulation() const;
+   int getModulationSystem() const;
+   int getModulationType() const;
+   int getRollOff() const;
    int getSymbolRate() const;
    int getFecInner() const;
 protected:
@@ -236,6 +238,9 @@
 public:
    int getFrequency() const;
    int getBandwidth() const;
+   int getPriority() const;
+   int getTimeSlicingIndicator() const;
+   int getMpeFecIndicator() const;
    int getConstellation() const;
    int getHierarchy() const;
    int getCodeRateHP() const;
@@ -484,6 +489,30 @@
    const descr_ancillary_data *s;
 };
 
+class S2SatelliteDeliverySystemDescriptor : public Descriptor {
+public:
+   int getScramblingSequenceSelector() const;
+   int getMultipleInputStreamFlag() const;
+   int getBackwardsCompatibilityIndicator() const;
+   int getScramblingSequenceIndex() const;
+   int getInputStreamIdentifier() const { return input_stream_identifier; }
+protected:
+   virtual void Parse();
+private:
+   const descr_s2_satellite_delivery_system *s;
+   const descr_scrambling_sequence_selector *sss;
+   int input_stream_identifier;
+};
+
+class ExtensionDescriptor : public Descriptor {
+public:
+   int getExtensionDescriptorTag() const;
+protected:
+   virtual void Parse();
+private:
+   const descr_extension *s;
+};
+
 // Private DVB Descriptor  Premiere.de
 // 0xF2  Content Transmission Descriptor
 // http://dvbsnoop.sourceforge.net/examples/example-private-section.html
diff -ruN vdr-1.5.0/libsi/headers.h vdr-1.5.1/libsi/headers.h
--- vdr-1.5.0/libsi/headers.h	2006-09-02 22:25:16.000000000 +0200
+++ vdr-1.5.1/libsi/headers.h	2007-02-03 12:45:58.000000000 +0100
@@ -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.8 2006/09/02 20:25:16 kls Exp $
+ *   $Id: headers.h 1.9 2007/02/03 11:45:58 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -942,9 +942,13 @@
 #if BYTE_ORDER == BIG_ENDIAN
    u_char west_east_flag                         :1;
    u_char polarization                           :2;
-   u_char modulation                             :5;
-#else
-   u_char modulation                             :5;
+   u_char roll_off                               :2;
+   u_char modulation_system                      :1;
+   u_char modulation_type                        :2;
+#else
+   u_char modulation_type                        :2;
+   u_char modulation_system                      :1;
+   u_char roll_off                               :2;
    u_char polarization                           :2;
    u_char west_east_flag                         :1;
 #endif
@@ -1349,9 +1353,15 @@
    u_char frequency_lo_lo                        :8;
 #if BYTE_ORDER == BIG_ENDIAN
    u_char bandwidth                              :3;
-   u_char reserved1                              :5;
-#else
-   u_char reserved1                              :5;
+   u_char priority                               :1;
+   u_char time_slicing_indicator                 :1;
+   u_char mpe_fec_indicator                      :1;
+   u_char reserved1                              :2;
+#else
+   u_char reserved1                              :2;
+   u_char mpe_fec_indicator                      :1;
+   u_char time_slicing_indicator                 :1;
+   u_char priority                               :1;
    u_char bandwidth                              :3;
 #endif
 #if BYTE_ORDER == BIG_ENDIAN
@@ -1492,10 +1502,10 @@
    /* TBD */
 };
 
-/* 0x65 ca_system_descriptor */
+/* 0x65 scrambling_descriptor */
 
-#define DESCR_CA_SYSTEM_LEN XX
-struct descr_ca_system {
+#define DESCR_SCRAMBLING_LEN XX
+struct descr_scrambling {
    u_char descriptor_tag                         :8;
    u_char descriptor_length                      :8;
    /* TBD */
@@ -1628,6 +1638,189 @@
    u_char descriptor_length                      :8;
 };
 
+/* 0x72 service_availbility_descriptor */
+
+struct descr_service_availbility {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char availability_flag                      :1;
+   u_char reserved                               :7;
+#else
+   u_char reserved                               :7;
+   u_char availability_flag                      :1;
+#endif
+};
+
+/* 0x73 default_authority_descriptor (ETSI TS 102 323) */
+
+struct descr_default_authority {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+};
+
+/* 0x74 related_content_descriptor (ETSI TS 102 323) */
+
+struct descr_related_content {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+};
+
+/* 0x75 tva_id_descriptor (ETSI TS 102 323) */
+
+struct descr_tva_id {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+};
+
+/* 0x76 content_identifier_descriptor (ETSI TS 102 323) */
+
+struct descr_content_identifier {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+};
+
+/* 0x77 time_slice_fec_identifier_descriptor (ETSI EN 301 192) */
+
+struct descr_time_slice_fec_identifier {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char time_slicing                           :1;
+   u_char mpe_fec                                :2;
+   u_char reserved                               :2;
+   u_char frame_size                             :3;
+#else
+   u_char frame_size                             :3;
+   u_char reserved                               :2;
+   u_char mpe_fec                                :2;
+   u_char time_slicing                           :1;
+#endif
+   u_char max_burst_duration                     :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char max_average_rate                       :4;
+   u_char time_slice_fec_id                      :4;
+#else
+   u_char time_slice_fec_id                      :4;
+   u_char max_average_rate                       :4;
+#endif
+};
+
+/* 0x78 ecm_repetition_rate_descriptor (ETSI EN 301 192) */
+
+struct descr_ecm_repetition_rate {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char ca_system_id_hi                        :8;
+   u_char ca_system_id_lo                        :8;
+   u_char ecm_repetition_rate_hi                 :8;
+   u_char ecm_repetition_rate_lo                 :8;
+};
+
+/* 0x79 s2_satellite_delivery_system_descriptor */
+
+struct descr_s2_satellite_delivery_system {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char scrambling_sequence_selector           :1;
+   u_char multiple_input_stream_flag             :1;
+   u_char backwards_compatibility_indicator      :1;
+   u_char reserved                               :5;
+#else
+   u_char reserved                               :5;
+   u_char backwards_compatibility_indicator      :1;
+   u_char multiple_input_stream_flag             :1;
+   u_char scrambling_sequence_selector           :1;
+#endif
+};
+
+struct descr_scrambling_sequence_selector {
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char reserved                               :6;
+   u_char scrambling_sequence_index_hi_lo        :2;
+#else
+   u_char scrambling_sequence_index_hi_lo        :2;
+   u_char reserved                               :6;
+#endif
+   u_char scrambling_sequence_index_lo_hi        :8;
+   u_char scrambling_sequence_index_lo_lo        :8;
+};
+
+/* 0x7A enhanced_ac3_descriptor */
+
+struct descr_enhanced_ac3 {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char component_type_flag                    :1;
+   u_char bsid_flag                              :1;
+   u_char mainid_flag                            :1;
+   u_char asvc_flag                              :1;
+   u_char mixinfoexists                          :1;
+   u_char substream1_flag                        :1;
+   u_char substream2_flag                        :1;
+   u_char substream3_flag                        :1;
+#else
+   u_char substream3_flag                        :1;
+   u_char substream2_flag                        :1;
+   u_char substream1_flag                        :1;
+   u_char mixinfoexists                          :1;
+   u_char asvc_flag                              :1;
+   u_char mainid_flag                            :1;
+   u_char bsid_flag                              :1;
+   u_char component_type_flag                    :1;
+#endif
+};
+
+/* 0x7B dts_descriptor */
+
+struct descr_dts {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char sample_rate_code                       :4;
+   u_char bit_rate_code                          :6;
+   u_char nblks                                  :7;
+   u_char fsize_hi                               :6;
+   u_char fsize_lo                               :8;
+   u_char surround_mode                          :6;
+   u_char lfe_flag                               :1;
+   u_char extended_surround_flag                 :2;
+#else
+   u_char extended_surround_flag                 :2;
+   u_char lfe_flag                               :1;
+   u_char surround_mode                          :6;
+   u_char fsize_lo                               :8;
+   u_char fsize_hi                               :6;
+   u_char nblks                                  :7;
+   u_char bit_rate_code                          :6;
+   u_char sample_rate_code                       :4;
+#endif
+};
+
+/* 0x7C aac_descriptor */
+
+struct descr_aac {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char profile_and_level                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char aac_type_flag                          :1;
+   u_char reserved                               :7;
+#else
+   u_char reserved                               :7;
+   u_char aac_type_flag                          :1;
+#endif
+};
+/* 0x7F extension_descriptor */
+
+struct descr_extension {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char descriptor_tag_extension               :8;
+};
+
 /* MHP 0x00 application_descriptor */
 
 #define DESCR_APPLICATION_LEN 3
diff -ruN vdr-1.5.0/libsi/si.c vdr-1.5.1/libsi/si.c
--- vdr-1.5.0/libsi/si.c	2006-04-14 12:53:44.000000000 +0200
+++ vdr-1.5.1/libsi/si.c	2007-02-03 12:45:58.000000000 +0100
@@ -6,7 +6,7 @@
  *   the Free Software Foundation; either version 2 of the License, or     *
  *   (at your option) any later version.                                   *
  *                                                                         *
- *   $Id: si.c 1.16 2006/04/14 10:53:44 kls Exp $
+ *   $Id: si.c 1.17 2007/02/03 11:45:58 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -425,6 +425,12 @@
          case AncillaryDataDescriptorTag:
             d=new AncillaryDataDescriptor();
             break;
+         case S2SatelliteDeliverySystemDescriptorTag:
+            d=new S2SatelliteDeliverySystemDescriptor();
+            break;
+         case ExtensionDescriptorTag:
+            d=new ExtensionDescriptor();
+            break;
 
          //note that it is no problem to implement one
          //of the unimplemented descriptors.
@@ -459,12 +465,23 @@
          case PartialTransportStreamDescriptorTag:
          case DataBroadcastDescriptorTag:
          case DataBroadcastIdDescriptorTag:
-         case CaSystemDescriptorTag:
+         case ScramblingDescriptorTag:
          case AC3DescriptorTag:
          case DSNGDescriptorTag:
          case AnnouncementSupportDescriptorTag:
          case AdaptationFieldDataDescriptorTag:
          case TransportStreamDescriptorTag:
+
+         //defined in ETSI EN 300 468 v 1.7.1
+         case DefaultAuthorityDescriptorTag:
+         case RelatedContentDescriptorTag:
+         case TVAIdDescriptorTag:
+         case ContentIdentifierDescriptorTag:
+         case TimeSliceFecIdentifierDescriptorTag:
+         case ECMRepetitionRateDescriptorTag:
+         case EnhancedAC3DescriptorTag:
+         case DTSDescriptorTag:
+         case AACDescriptorTag:
          default:
             if (!returnUnimplemetedDescriptor)
                return 0;
diff -ruN vdr-1.5.0/libsi/si.h vdr-1.5.1/libsi/si.h
--- vdr-1.5.0/libsi/si.h	2006-05-27 15:07:20.000000000 +0200
+++ vdr-1.5.1/libsi/si.h	2007-02-03 12:47:25.000000000 +0100
@@ -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.15 2006/05/27 13:07:20 kls Exp $
+ *   $Id: si.h 1.16 2007/02/03 11:47:25 kls Exp $
  *                                                                         *
  ***************************************************************************/
 
@@ -108,7 +108,7 @@
                FrequencyListDescriptorTag = 0x62,
                PartialTransportStreamDescriptorTag = 0x63,
                DataBroadcastDescriptorTag = 0x64,
-               CaSystemDescriptorTag = 0x65,
+               ScramblingDescriptorTag = 0x65,
                DataBroadcastIdDescriptorTag = 0x66,
                TransportStreamDescriptorTag = 0x67,
                DSNGDescriptorTag = 0x68,
@@ -122,6 +122,19 @@
                AdaptationFieldDataDescriptorTag = 0x70,
                ServiceIdentifierDescriptorTag = 0x71,
                ServiceAvailabilityDescriptorTag = 0x72,
+  // defined by ETSI (EN 300 468) v 1.7.1
+               DefaultAuthorityDescriptorTag = 0x73,
+               RelatedContentDescriptorTag = 0x74,
+               TVAIdDescriptorTag = 0x75,
+               ContentIdentifierDescriptorTag = 0x76,
+               TimeSliceFecIdentifierDescriptorTag = 0x77,
+               ECMRepetitionRateDescriptorTag = 0x78,
+               S2SatelliteDeliverySystemDescriptorTag = 0x79,
+               EnhancedAC3DescriptorTag = 0x7A,
+               DTSDescriptorTag = 0x7B,
+               AACDescriptorTag = 0x7C,
+               ExtensionDescriptorTag = 0x7F,
+
  // Defined by ETSI TS 102 812 (MHP)
                // They once again start with 0x00 (see page 234, MHP specification)
                MHP_ApplicationDescriptorTag = 0x00,
diff -ruN vdr-1.5.0/menu.c vdr-1.5.1/menu.c
--- vdr-1.5.0/menu.c	2007-01-07 13:19:48.000000000 +0100
+++ vdr-1.5.1/menu.c	2007-02-25 15:04:33.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menu.c 1.447 2007/01/07 12:19:48 kls Exp $
+ * $Id: menu.c 1.450 2007/02/25 14:04:33 kls Exp $
  */
 
 #include "menu.h"
@@ -22,6 +22,7 @@
 #include "plugin.h"
 #include "recording.h"
 #include "remote.h"
+#include "shutdown.h"
 #include "sources.h"
 #include "status.h"
 #include "themes.h"
@@ -2206,7 +2207,7 @@
   Add(new cMenuEditBoolItem(tr("Setup.OSD$Timeout requested channel info"), &data.TimeoutRequChInfo));
   Add(new cMenuEditBoolItem(tr("Setup.OSD$Scroll pages"),           &data.MenuScrollPage));
   Add(new cMenuEditBoolItem(tr("Setup.OSD$Scroll wraps"),           &data.MenuScrollWrap));
-  Add(new cMenuEditBoolItem(tr("Setup.OSD$Menu button closes"),     &data.MenuButtonCloses));
+  Add(new cMenuEditBoolItem(tr("Setup.OSD$Menu key closes"),        &data.MenuKeyCloses));
   Add(new cMenuEditBoolItem(tr("Setup.OSD$Recording directories"),  &data.RecordingDirs));
   SetCurrent(Get(current));
   Display();
@@ -2661,6 +2662,7 @@
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Min. user inactivity (min)"), &data.MinUserInactivity));
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"),          &data.SVDRPTimeout));
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Zap timeout (s)"),            &data.ZapTimeout));
+  Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Channel entry timeout (ms)"), &data.ChannelEntryTimeout, 0));
   Add(new cMenuEditChanItem(tr("Setup.Miscellaneous$Initial channel"),            &data.InitialChannel, tr("Setup.Miscellaneous$as before")));
   Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Initial volume"),             &data.InitialVolume, -1, 255, tr("Setup.Miscellaneous$as before")));
 }
@@ -2770,10 +2772,8 @@
 
 eOSState cMenuSetup::Restart(void)
 {
-  if (Interface->Confirm(tr("Really restart?"))
-     && (!cRecordControls::Active() || Interface->Confirm(tr("Recording - restart anyway?")))
-     && !cPluginManager::Active(tr("restart anyway?"))) {
-     cThread::EmergencyExit(true);
+  if (Interface->Confirm(tr("Really restart?")) && ShutdownHandler.ConfirmRestart(true)) {
+     ShutdownHandler.Exit(1);
      return osEnd;
      }
   return osContinue;
@@ -3090,8 +3090,6 @@
 
 // --- cDisplayChannel -------------------------------------------------------
 
-#define DIRECTCHANNELTIMEOUT 1000 //ms
-
 cDisplayChannel *cDisplayChannel::currentDisplayChannel = NULL;
 
 cDisplayChannel::cDisplayChannel(int Number, bool Switched)
@@ -3290,7 +3288,7 @@
          Refresh();
          break;
     case kNone:
-         if (number && lastTime.Elapsed() > DIRECTCHANNELTIMEOUT) {
+         if (number && Setup.ChannelEntryTimeout && int(lastTime.Elapsed()) > Setup.ChannelEntryTimeout) {
             channel = Channels.GetByNumber(number);
             if (channel)
                NewChannel = channel;
@@ -3699,7 +3697,7 @@
      if (device) {
         dsyslog("switching device %d to channel %d", device->DeviceNumber() + 1, channel->Number());
         if (!device->SwitchChannel(channel, false)) {
-           cThread::EmergencyExit(true);
+           ShutdownHandler.RequestEmergencyExit();
            return false;
            }
         if (!Timer || Timer->Matches()) {
diff -ruN vdr-1.5.0/newplugin vdr-1.5.1/newplugin
--- vdr-1.5.0/newplugin	2006-09-09 14:38:35.000000000 +0200
+++ vdr-1.5.1/newplugin	2007-02-24 14:23:08.000000000 +0100
@@ -12,7 +12,7 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: newplugin 1.30 2006/09/09 12:38:35 kls Exp $
+# $Id: newplugin 1.31 2007/02/24 13:23:08 kls Exp $
 
 $PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
 
@@ -169,6 +169,7 @@
   virtual void Housekeeping(void);
   virtual void MainThreadHook(void);
   virtual cString Active(void);
+  virtual time_t WakeupTime(void);
   virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
   virtual cOsdObject *MainMenuAction(void);
   virtual cMenuSetupPage *SetupMenu(void);
@@ -236,6 +237,12 @@
   return NULL;
 }
 
+time_t cPlugin${PLUGIN_CLASS}::WakeupTime(void)
+{
+  // Return custom wakeup time for shutdown script
+  return 0;
+}
+
 cOsdObject *cPlugin${PLUGIN_CLASS}::MainMenuAction(void)
 {
   // Perform the action when selected from the main VDR menu.
diff -ruN vdr-1.5.0/osd.c vdr-1.5.1/osd.c
--- vdr-1.5.0/osd.c	2006-02-26 15:31:31.000000000 +0100
+++ vdr-1.5.1/osd.c	2007-02-17 17:05:52.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: osd.c 1.67 2006/02/26 14:31:31 kls Exp $
+ * $Id: osd.c 1.68 2007/02/17 16:05:52 kls Exp $
  */
 
 #include "osd.h"
@@ -218,14 +218,17 @@
                  int w, h, n, c;
                  if (4 != sscanf(s, "%d %d %d %d", &w, &h, &n, &c)) {
                     esyslog("ERROR: faulty 'values' line in XPM file '%s'", FileName);
+                    isXpm = false;
                     break;
                     }
                  lines = h + n + 1;
                  Xpm = MALLOC(char *, lines);
+                 memset(Xpm, 0, lines * sizeof(char*));
                  }
               char *q = strchr(s, '"');
               if (!q) {
                  esyslog("ERROR: missing quotes in XPM file '%s'", FileName);
+                 isXpm = false;
                  break;
                  }
               *q = 0;
@@ -233,16 +236,21 @@
                  Xpm[index++] = strdup(s);
               else {
                  esyslog("ERROR: too many lines in XPM file '%s'", FileName);
+                 isXpm = false;
                  break;
                  }
               }
            }
-     if (index == lines)
-        Result = SetXpm(Xpm);
-     else
-        esyslog("ERROR: too few lines in XPM file '%s'", FileName);
-     for (int i = 0; i < index; i++)
-         free(Xpm[i]);
+     if (isXpm) {
+        if (index == lines)
+           Result = SetXpm(Xpm);
+        else
+           esyslog("ERROR: too few lines in XPM file '%s'", FileName);
+        }
+     if (Xpm) {
+        for (int i = 0; i < index; i++)
+            free(Xpm[i]);
+        }
      free(Xpm);
      fclose(f);
      }
diff -ruN vdr-1.5.0/plugin.c vdr-1.5.1/plugin.c
--- vdr-1.5.0/plugin.c	2006-10-14 11:49:16.000000000 +0200
+++ vdr-1.5.1/plugin.c	2007-02-24 14:44:23.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: plugin.c 1.24 2006/10/14 09:49:16 kls Exp $
+ * $Id: plugin.c 1.25 2007/02/24 13:44:23 kls Exp $
  */
 
 #include "plugin.h"
@@ -80,6 +80,11 @@
   return NULL;
 }
 
+time_t cPlugin::WakeupTime(void)
+{
+  return 0;
+}
+
 const char *cPlugin::MainMenuEntry(void)
 {
   return NULL;
@@ -403,6 +408,26 @@
   return false;
 }
 
+cPlugin *cPluginManager::GetNextWakeupPlugin(void)
+{
+  cPlugin *NextPlugin = NULL;
+  if (pluginManager) {
+     time_t Now = time(NULL);
+     time_t Next = 0;
+     for (cDll *dll = pluginManager->dlls.First(); dll; dll = pluginManager->dlls.Next(dll)) {
+         cPlugin *p = dll->Plugin();
+         if (p) {
+            time_t t = p->WakeupTime();
+            if (t > Now && (!Next || t < Next)) {
+               Next = t;
+               NextPlugin = p;
+               }
+            }
+         }
+     }
+  return NextPlugin;
+}
+
 bool cPluginManager::HasPlugins(void)
 {
   return pluginManager && pluginManager->dlls.Count();
diff -ruN vdr-1.5.0/plugin.h vdr-1.5.1/plugin.h
--- vdr-1.5.0/plugin.h	2006-04-17 11:18:16.000000000 +0200
+++ vdr-1.5.1/plugin.h	2007-02-24 14:45:28.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: plugin.h 1.13 2006/04/17 09:18:16 kls Exp $
+ * $Id: plugin.h 1.14 2007/02/24 13:45:28 kls Exp $
  */
 
 #ifndef __PLUGIN_H
@@ -41,6 +41,7 @@
   virtual void Housekeeping(void);
   virtual void MainThreadHook(void);
   virtual cString Active(void);
+  virtual time_t WakeupTime(void);
 
   virtual const char *MainMenuEntry(void);
   virtual cOsdObject *MainMenuAction(void);
@@ -93,6 +94,7 @@
   void Housekeeping(void);
   void MainThreadHook(void);
   static bool Active(const char *Prompt = NULL);
+  static cPlugin *GetNextWakeupPlugin(void);
   static bool HasPlugins(void);
   static cPlugin *GetPlugin(int Index);
   static cPlugin *GetPlugin(const char *Name);
diff -ruN vdr-1.5.0/recorder.c vdr-1.5.1/recorder.c
--- vdr-1.5.0/recorder.c	2007-01-05 11:43:09.000000000 +0100
+++ vdr-1.5.1/recorder.c	2007-02-24 17:36:24.000000000 +0100
@@ -4,13 +4,14 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: recorder.c 1.18 2007/01/05 10:43:09 kls Exp $
+ * $Id: recorder.c 1.19 2007/02/24 16:36:24 kls Exp $
  */
 
 #include "recorder.h"
 #include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
+#include "shutdown.h"
 
 #define RECORDERBUFSIZE  MEGABYTE(5)
 
@@ -117,7 +118,7 @@
            }
         else if (time(NULL) - t > MAXBROKENTIMEOUT) {
            esyslog("ERROR: video data stream broken");
-           cThread::EmergencyExit(true);
+           ShutdownHandler.RequestEmergencyExit();
            t = time(NULL);
            }
         }
diff -ruN vdr-1.5.0/remote.c vdr-1.5.1/remote.c
--- vdr-1.5.0/remote.c	2006-12-02 12:12:42.000000000 +0100
+++ vdr-1.5.1/remote.c	2007-02-24 14:23:12.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remote.c 1.55 2006/12/02 11:12:42 kls Exp $
+ * $Id: remote.c 1.56 2007/02/24 13:23:12 kls Exp $
  */
 
 #include "remote.h"
@@ -31,6 +31,7 @@
 cCondVar cRemote::keyPressed;
 const char *cRemote::keyMacroPlugin = NULL;
 const char *cRemote::callPlugin = NULL;
+time_t cRemote::lastActivity = 0;
 
 cRemote::cRemote(const char *Name)
 {
@@ -183,6 +184,7 @@
             out = 0;
          if ((k & k_Repeat) != 0)
             repeatTimeout.Set(REPEATTIMEOUT);
+         lastActivity = time(NULL);
          return k;
          }
       else if (!WaitMs || !keyPressed.TimedWait(mutex, WaitMs) && repeatTimeout.TimedOut())
diff -ruN vdr-1.5.0/remote.h vdr-1.5.1/remote.h
--- vdr-1.5.0/remote.h	2006-12-02 12:12:49.000000000 +0100
+++ vdr-1.5.1/remote.h	2007-02-24 16:53:00.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remote.h 1.38 2006/12/02 11:12:49 kls Exp $
+ * $Id: remote.h 1.39 2007/02/24 15:53:00 kls Exp $
  */
 
 #ifndef __REMOTE_H
@@ -28,6 +28,7 @@
   static char *unknownCode;
   static cMutex mutex;
   static cCondVar keyPressed;
+  static time_t lastActivity;
   static const char *keyMacroPlugin;
   static const char *callPlugin;
   char *name;
@@ -61,6 +62,8 @@
       ///< plugin name will be reset to NULL by this call.
   static bool HasKeys(void);
   static eKeys Get(int WaitMs = 1000, char **UnknownCode = NULL);
+  static time_t LastActivity(void) { return lastActivity; }
+      ///< Absolute time when last key was delivered by Get().
   };
 
 class cRemotes : public cList<cRemote> {};
diff -ruN vdr-1.5.0/remux.c vdr-1.5.1/remux.c
--- vdr-1.5.0/remux.c	2006-12-01 15:46:25.000000000 +0100
+++ vdr-1.5.1/remux.c	2007-02-24 17:36:10.000000000 +0100
@@ -11,13 +11,13 @@
  * The cRepacker family's code was originally written by Reinhard Nissl <rnissl@gmx.de>,
  * and adapted to the VDR coding style by Klaus.Schmidinger@cadsoft.de.
  *
- * $Id: remux.c 1.57 2006/12/01 14:46:25 kls Exp $
+ * $Id: remux.c 1.58 2007/02/24 16:36:10 kls Exp $
  */
 
 #include "remux.h"
 #include <stdlib.h>
 #include "channels.h"
-#include "thread.h"
+#include "shutdown.h"
 #include "tools.h"
 
 ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader)
@@ -2011,7 +2011,7 @@
         esyslog("ERROR: no useful data seen within %d byte of video stream", skipped);
         skipped = -1;
         if (exitOnFailure)
-           cThread::EmergencyExit(true);
+           ShutdownHandler.RequestEmergencyExit();
         }
      else
         skipped += used;
@@ -2059,7 +2059,7 @@
                   if (pt < I_FRAME || B_FRAME < pt) {
                      esyslog("ERROR: unknown picture type '%d'", pt);
                      if (++numUPTerrors > MAXNUMUPTERRORS && exitOnFailure)
-                        cThread::EmergencyExit(true);
+                        ShutdownHandler.RequestEmergencyExit();
                      }
                   else if (!synced) {
                      if (pt == I_FRAME) {
diff -ruN vdr-1.5.0/shutdown.c vdr-1.5.1/shutdown.c
--- vdr-1.5.0/shutdown.c	1970-01-01 01:00:00.000000000 +0100
+++ vdr-1.5.1/shutdown.c	2007-02-24 18:24:11.000000000 +0100
@@ -0,0 +1,250 @@
+/*
+ * shutdown.c: Handling of shutdown and inactivity
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * Original version written by Udo Richter <udo_richter@gmx.de>.
+ *
+ * $Id: shutdown.c 1.1 2007/02/24 17:24:11 kls Exp $
+ */
+
+#include "shutdown.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "channels.h"
+#include "config.h"
+#include "cutter.h"
+#include "i18n.h"
+#include "interface.h"
+#include "menu.h"
+#include "plugin.h"
+#include "timers.h"
+#include "tools.h"
+
+cShutdownHandler ShutdownHandler;
+
+cCountdown::cCountdown(void)
+{
+  timeout = 0;
+  counter = 0;
+  timedOut = false;
+  message = NULL;
+}
+
+void cCountdown::Start(const char *Message, int Seconds)
+{
+  timeout = time(NULL) + Seconds;
+  counter = -1;
+  timedOut = false;
+  message = Message;
+  Update();
+}
+
+void cCountdown::Cancel(void)
+{
+  if (timeout) {
+     timeout = 0;
+     timedOut = false;
+     Skins.Message(mtStatus, NULL);
+     }
+}
+
+bool cCountdown::Done(void)
+{
+  if (timedOut) {
+     Cancel();
+     return true;
+     }
+  return false;
+}
+
+bool cCountdown::Update(void)
+{
+  if (timeout) {
+     int NewCounter = (timeout - time(NULL) + 9) / 10;
+     if (NewCounter <= 0)
+        timedOut = true;
+     if (counter != NewCounter) {
+        counter = NewCounter;
+        char time[10];
+        snprintf(time, sizeof(time), "%d:%d0", counter > 0 ? counter / 6 : 0, counter > 0 ? counter % 6 : 0);
+        cString Message = cString::sprintf(message, time);
+        Skins.Message(mtStatus, Message);
+        return true;
+        }
+     }
+  return false;
+}
+
+cShutdownHandler::cShutdownHandler(void)
+{
+  activeTimeout = 0;
+  retry = 0;
+  shutdownCommand = NULL;
+  exitCode = -1;
+  emergencyExitRequested = false;
+}
+
+cShutdownHandler::~cShutdownHandler()
+{
+  free(shutdownCommand);
+}
+
+void cShutdownHandler::RequestEmergencyExit(void)
+{
+  esyslog("initiating emergency exit");
+  emergencyExitRequested = true;
+  Exit(1);
+}
+
+void cShutdownHandler::CheckManualStart(int ManualStart)
+{
+  time_t Delta = Setup.NextWakeupTime ? Setup.NextWakeupTime - time(NULL) : 0;
+
+  if (!Setup.NextWakeupTime || abs(Delta) > ManualStart) {
+     // Apparently the user started VDR manually
+     dsyslog("assuming manual start of VDR");
+     // Set inactive after MinUserInactivity
+     SetUserInactiveTimeout();
+     }
+  else
+     // Set inactive from now on
+     SetUserInactive();
+}
+
+void cShutdownHandler::SetShutdownCommand(const char *ShutdownCommand)
+{
+  free(shutdownCommand);
+  shutdownCommand = ShutdownCommand ? strdup(ShutdownCommand) : NULL;
+}
+
+void cShutdownHandler::CallShutdownCommand(time_t WakeupTime, int Channel, const char *File, bool UserShutdown)
+{
+  time_t Delta = WakeupTime ? WakeupTime - time(NULL) : 0;
+  cString cmd = cString::sprintf("%s %ld %ld %d \"%s\" %d", shutdownCommand, WakeupTime, Delta, Channel, *strescape(File, "\"$"), UserShutdown);
+  isyslog("executing '%s'", *cmd);
+  if (SystemExec(cmd, true) == 0)
+     Setup.NextWakeupTime = WakeupTime; // Remember this wakeup time for comparison on reboot
+}
+
+void cShutdownHandler::SetUserInactiveTimeout(int Seconds, bool Force)
+{
+  if (!Setup.MinUserInactivity && !Force) {
+     activeTimeout = 0;
+     return;
+     }
+  if (Seconds < 0)
+     Seconds = Setup.MinUserInactivity * 60;
+  activeTimeout = time(NULL) + Seconds;
+}
+
+bool cShutdownHandler::ConfirmShutdown(bool Interactive)
+{
+  if (!shutdownCommand) {
+     if (Interactive)
+        Skins.Message(mtError, tr("Can't shutdown - option '-s' not given!"));
+     return false;
+     }
+  if (cCutter::Active()) {
+     if (!Interactive || !Interface->Confirm(tr("Editing - shut down anyway?")))
+        return false;
+     }
+
+  cTimer *timer = Timers.GetNextActiveTimer();
+  time_t Next = timer ? timer->StartTime() : 0;
+  time_t Delta = timer ? Next - time(NULL) : 0;
+
+  if (cRecordControls::Active() || (Next && Delta <= 0)) {
+     // VPS recordings in timer end margin may cause Delta <= 0
+     if (!Interactive || !Interface->Confirm(tr("Recording - shut down anyway?")))
+        return false;
+     }
+  else if (Next && Delta <= Setup.MinEventTimeout * 60) {
+     // Timer within Min Event Timeout
+     if (!Interactive)
+        return false;
+     cString buf = cString::sprintf(tr("Recording in %ld minutes, shut down anyway?"), Delta / 60);
+     if (!Interface->Confirm(buf))
+        return false;
+     }
+
+  if (cPluginManager::Active(Interactive ? tr("shut down anyway?") : NULL))
+     return false;
+
+  cPlugin *Plugin = cPluginManager::GetNextWakeupPlugin();
+  Next = Plugin ? Plugin->WakeupTime() : 0;
+  Delta = Next ? Next - time(NULL) : 0;
+  if (Next && Delta <= Setup.MinEventTimeout * 60) {
+     // Plugin wakeup within Min Event Timeout
+     if (!Interactive)
+        return false;
+     cString buf = cString::sprintf(tr("Plugin %s wakes up in %ld min, continue?"), Plugin->Name(), Delta / 60);
+     if (!Interface->Confirm(buf))
+        return false;
+     }
+
+  return true;
+}
+
+bool cShutdownHandler::ConfirmRestart(bool Interactive)
+{
+  if (cCutter::Active()) {
+     if (!Interactive || !Interface->Confirm(tr("Editing - restart anyway?")))
+        return false;
+     }
+
+  cTimer *timer = Timers.GetNextActiveTimer();
+  time_t Next  = timer ? timer->StartTime() : 0;
+  time_t Delta = timer ? Next - time(NULL) : 0;
+
+  if (cRecordControls::Active() || (Next && Delta <= 0)) {
+     // VPS recordings in timer end margin may cause Delta <= 0
+     if (!Interactive || !Interface->Confirm(tr("Recording - restart anyway?")))
+        return false;
+     }
+
+  if (cPluginManager::Active(Interactive ? tr("restart anyway?") : NULL))
+     return false;
+
+  return true;
+}
+
+bool cShutdownHandler::DoShutdown(bool Force)
+{
+  time_t Now = time(NULL);
+  cTimer *timer = Timers.GetNextActiveTimer();
+  cPlugin *Plugin = cPluginManager::GetNextWakeupPlugin();
+
+  time_t Next = timer ? timer->StartTime() : 0;
+  time_t NextPlugin = Plugin ? Plugin->WakeupTime() : 0;
+  if (NextPlugin && (!Next || Next > NextPlugin)) {
+     Next = NextPlugin;
+     timer = NULL;
+     }
+  time_t Delta = Next ? Next - Now : 0;
+
+  if (Next && Delta < Setup.MinEventTimeout * 60) {
+     if (!Force)
+        return false;
+     Delta = Setup.MinEventTimeout * 60;
+     Next = Now + Delta;
+     timer = NULL;
+     dsyslog("reboot at %s", *TimeToString(Next));
+     }
+
+  if (Next && timer) {
+     dsyslog("next timer event at %s", *TimeToString(Next));
+     CallShutdownCommand(Next, timer->Channel()->Number(), timer->File(), Force);
+     }
+  else if (Next && Plugin) {
+     CallShutdownCommand(Next, 0, Plugin->Name(), Force);
+     dsyslog("next plugin wakeup at %s", *TimeToString(Next));
+     }
+  else
+     CallShutdownCommand(Next, 0, "", Force); // Next should always be 0 here. Just for safety, pass it.
+
+  return true;
+}
diff -ruN vdr-1.5.0/shutdown.h vdr-1.5.1/shutdown.h
--- vdr-1.5.0/shutdown.h	1970-01-01 01:00:00.000000000 +0100
+++ vdr-1.5.1/shutdown.h	2007-02-24 18:23:59.000000000 +0100
@@ -0,0 +1,112 @@
+/*
+ * shutdown.h: Handling of shutdown and inactivity
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * Original version written by Udo Richter <udo_richter@gmx.de>.
+ *
+ * $Id: shutdown.h 1.1 2007/02/24 17:23:59 kls Exp $
+ */
+
+#ifndef __SHUTDOWN_H
+#define __SHUTDOWN_H
+
+#include <time.h>
+
+class cCountdown {
+private:
+  time_t timeout;      ///< 5-minute countdown timer
+  int counter;         ///< last shown time in 10s units
+  bool timedOut;       ///< countdown did run down to 0 and was not canceled
+  const char *message; ///< message to display, %s is placeholder for time
+public:
+  cCountdown(void);
+  void Start(const char *Message, int Seconds);
+       ///< Start the 5 minute shutdown warning countdown.
+  void Cancel(void);
+       ///< Cancel the 5 minute shutdown warning countdown.
+  bool Done(void);
+       ///< Check if countdown timer has run out without canceling.
+  operator bool(void) const { return timeout != 0; }
+       ///< Check if countdown is running.
+  bool Update(void);
+       ///< Update status display of the countdown.
+       ///< Returns true on actual update.
+  };
+
+class cShutdownHandler {
+private:
+  time_t activeTimeout;
+       ///< Time when VDR will become non-interactive. 0 means never.
+  time_t retry;
+       ///< Time for retrying the shutdown.
+  char *shutdownCommand;
+       ///< Command for shutting down VDR.
+  int exitCode;
+       ///< Exit code, if VDR exit was requested, or -1 if not requested.
+  bool emergencyExitRequested;
+       ///< The requested exit is an emergency exit.
+public:
+  cCountdown countdown;
+  cShutdownHandler(void);
+  ~cShutdownHandler();
+  void Exit(int ExitCode) { exitCode = ExitCode; }
+       ///< Set VDR exit code and initiate end of VDR main loop.
+       ///< This will exit VDR without any confirmation.
+  bool DoExit(void) { return exitCode >= 0; }
+       ///< Check if an exit code was set, and VDR should exit.
+  int GetExitCode(void) { return exitCode >= 0 ? exitCode : 0; }
+       ///< Get the currently set exit code of VDR.
+  bool EmergencyExitRequested(void) { return emergencyExitRequested; }
+       ///< Returns true if an emergency exit was requested.
+  void RequestEmergencyExit(void);
+       ///< Requests an emergency exit of the VDR main loop.
+  void CheckManualStart(int ManualStart);
+       ///< Check whether the next timer is in ManualStart time window.
+       ///< If yes, assume non-interactive use.
+  void SetShutdownCommand(const char *ShutdownCommand);
+       ///< Set the command string for shutdown command.
+  void CallShutdownCommand(time_t WakeupTime, int Channel, const char *File, bool UserShutdown);
+       ///< Call the shutdown command with the given parameters.
+  bool IsUserInactive(time_t AtTime = 0) { return activeTimeout && activeTimeout <= (AtTime ? AtTime : time(NULL)); }
+       ///< Check whether VDR is in interactive mode or non-interactive mode (waiting for shutdown).
+       ///< AtTime checks whether VDR will probably be inactive at that time.
+  time_t GetUserInactiveTime(void) { return activeTimeout; }
+       ///< Time when user will become non-inactive, or 0 if never.
+  void SetUserInactiveTimeout(int Seconds = -1, bool Force = false);
+       ///< Set the time when VDR will switch into non-interactive mode or power down.
+       ///< -1 means Setup.MinUserInactivity in the future.
+       ///< Otherwise, seconds in the future.
+       ///< If MinUserInactivity = 0 and Force = false, Seconds is ignored and VDR will
+       ///< stay interactive forever.
+  void SetUserInactive(void) { SetUserInactiveTimeout(0, true); }
+       ///< Set VDR manually into non-interactive mode.
+  bool Retry(time_t AtTime = 0) { return retry <= (AtTime ? AtTime : time(NULL)); }
+       ///< Check whether its time to re-try the shutdown.
+       ///< AtTime checks whether VDR will probably be inactive at that time.
+  time_t GetRetry(void) { return retry; }
+       ///< Time when shutdown retry block ends.
+  void SetRetry(int Seconds) { retry = time(NULL) + Seconds; }
+       ///< Set shutdown retry so that VDR will not try to automatically shut down
+       ///< within Seconds.
+  bool ConfirmShutdown(bool Ask);
+       ///< Check for background activity that blocks shutdown.
+       ///< Returns immediately and without user interaction if Ask = false.
+       ///< Asks for confirmation if Ask = true.
+       ///< Returns true if ready for shutdown.
+  bool ConfirmRestart(bool Ask);
+       ///< Check for background activity that blocks restart.
+       ///< Returns immediately and without user interaction if Ask = false.
+       ///< Asks for confirmation if Ask = true.
+       ///< Returns true if ready for restart.
+  bool DoShutdown(bool Force);
+       ///< Call the shutdown script with data of the next pending timer.
+       ///< Fails if Force = false and a timer is running or within MinEventTimeout.
+       ///< Always calls shutdown on Force = true.
+       ///< Returns true on success.
+  };
+
+extern cShutdownHandler ShutdownHandler;
+
+#endif
diff -ruN vdr-1.5.0/sources.conf vdr-1.5.1/sources.conf
--- vdr-1.5.0/sources.conf	2006-06-15 12:02:28.000000000 +0200
+++ vdr-1.5.1/sources.conf	2007-02-17 17:15:13.000000000 +0100
@@ -38,7 +38,7 @@
 S39E    Hellas Sat 2
 S40E    Express AM1
 S42E    Turksat 1C/2A
-S45E    PAS 12
+S45E    Intelsat 12
 S49E    Yamal 202
 S53E    Express AM 22
 S55E    Insat 3E & Intelsat 702
@@ -48,9 +48,9 @@
 S62E    Intelsat 902
 S64E    Intelsat 906
 S66E    Intelsat 704
-S68.5E  PAS 7/10
+S68.5E  Intelsat 7/10
 S70.5E  Eutelsat W5
-S72E    PAS 4
+S72E    Intelsat 4
 
 # Asia
 
@@ -98,8 +98,8 @@
 S160E   Optus B1
 S162E   Superbird B2
 S164E   Optus A3
-S166E   PAS 8
-S169E   PAS 2
+S166E   Intelsat 8
+S169E   Intelsat 2
 S172E   AMC 23
 S180E   Intelsat 701
 S177W   NSS 5
@@ -125,12 +125,12 @@
 S34.5W  Intelsat 903
 S37.5W  Telstar 11 & AMC 12
 S40.5W  NSS 806
-S43W    PAS 3R/6B
-S45W    PAS 1R
+S43W    Intelsat 3R/6B
+S45W    Intelsat 1R
 S50W    Intelsat 705
 S53W    Intelsat 707
 S55.5W  Intelsat 805
-S58W    PAS 9
+S58W    Intelsat 9
 S61W    Amazonas
 
 # America
@@ -151,13 +151,13 @@
 S85W    AMC 2
 S85.1W  XM 3
 S87W    AMC3
-S89W    Intelsat Americas 8
+S89W    Galaxy 28
 S91W    Galaxy 11 & Nimiq 1
 S91.5W  DirecTV 2
 S92W    Brasilsat B4
-S93W    Intelsat Americas 6
+S93W    Galaxy 26
 S95W    Galaxy 3C
-S97W    Intelsat Americas 5
+S97W    Galaxy 25
 S99W    Galaxy 4R
 S99.2W  Spaceway 2
 S101W   DirecTV 1R/4S/8 & AMC4
@@ -168,11 +168,11 @@
 S111.1W Anik F2
 S113W   Solidaridad 2
 S119W   Echostar 7 & DirecTV 7S
-S121W   Echostar 9 & Intelsat Americas 13
+S121W   Echostar 9 & Galaxy 23
 S123W   Galaxy 10R
 S125W   Galaxy 14
 S127W   Galaxy 13/Horizons 1
-S129W   Echostar 5 & Intelsat Americas 7
+S129W   Echostar 5 & Galaxy 27
 S131W   AMC 11
 S133W   Galaxy15/1R
 S135W   AMC 10
diff -ruN vdr-1.5.0/thread.c vdr-1.5.1/thread.c
--- vdr-1.5.0/thread.c	2007-01-05 11:44:22.000000000 +0100
+++ vdr-1.5.1/thread.c	2007-02-24 17:13:33.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: thread.c 1.59 2007/01/05 10:44:22 kls Exp $
+ * $Id: thread.c 1.60 2007/02/24 16:13:33 kls Exp $
  */
 
 #include "thread.h"
@@ -200,7 +200,6 @@
 // --- cThread ---------------------------------------------------------------
 
 tThreadId cThread::mainThreadId = 0;
-bool cThread::emergencyExitRequested = false;
 
 cThread::cThread(const char *Description)
 {
@@ -320,14 +319,6 @@
      }
 }
 
-bool cThread::EmergencyExit(bool Request)
-{
-  if (!Request)
-     return emergencyExitRequested;
-  esyslog("initiating emergency exit");
-  return emergencyExitRequested = true; // yes, it's an assignment, not a comparison!
-}
-
 tThreadId cThread::ThreadId(void)
 {
   return syscall(__NR_gettid);
@@ -505,7 +496,7 @@
 
 // --- SystemExec ------------------------------------------------------------
 
-int SystemExec(const char *Command)
+int SystemExec(const char *Command, bool Detached)
 {
   pid_t pid;
 
@@ -515,14 +506,24 @@
      }
 
   if (pid > 0) { // parent process
-     int status;
-     if (waitpid(pid, &status, 0) < 0) {
+     int status = 0;
+     if (!Detached && waitpid(pid, &status, 0) < 0) {
         LOG_ERROR;
         return -1;
         }
      return status;
      }
   else { // child process
+     if (Detached) {
+        // Start a new session
+        pid_t sid = setsid();
+        if (sid < 0)
+           LOG_ERROR;
+        // close STDIN and re-open as /dev/null
+        int devnull = open("/dev/null", O_RDONLY);
+        if (devnull < 0 || dup2(devnull, 0) < 0)
+           LOG_ERROR;
+        }
      int MaxPossibleFileDescriptors = getdtablesize();
      for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
          close(i); //close all dup'ed filedescriptors
diff -ruN vdr-1.5.0/thread.h vdr-1.5.1/thread.h
--- vdr-1.5.0/thread.h	2007-01-05 11:44:38.000000000 +0100
+++ vdr-1.5.1/thread.h	2007-02-24 17:13:28.000000000 +0100
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: thread.h 1.38 2007/01/05 10:44:38 kls Exp $
+ * $Id: thread.h 1.39 2007/02/24 16:13:28 kls Exp $
  */
 
 #ifndef __THREAD_H
@@ -84,7 +84,6 @@
   cMutex mutex;
   char *description;
   static tThreadId mainThreadId;
-  static bool emergencyExitRequested;
   static void *StartThread(cThread *Thread);
 protected:
   void SetPriority(int Priority);
@@ -118,7 +117,6 @@
        ///< If the thread is already running, nothing happens.
   bool Active(void);
        ///< Checks whether the thread is still alive.
-  static bool EmergencyExit(bool Request = false);
   static tThreadId ThreadId(void);
   static tThreadId IsMainThread(void) { return ThreadId() == mainThreadId; }
   static void SetMainThreadId(void);
@@ -175,7 +173,9 @@
 
 // SystemExec() implements a 'system()' call that closes all unnecessary file
 // descriptors in the child process.
+// With Detached=true, calls command in background and in a separate session,
+// with stdin connected to /dev/null.
 
-int SystemExec(const char *Command);
+int SystemExec(const char *Command, bool Detached = false);
 
 #endif //__THREAD_H
diff -ruN vdr-1.5.0/vdr.1 vdr-1.5.1/vdr.1
--- vdr-1.5.0/vdr.1	2007-01-07 15:03:56.000000000 +0100
+++ vdr-1.5.1/vdr.1	2007-02-24 18:40:20.000000000 +0100
@@ -8,7 +8,7 @@
 .\" License as specified in the file COPYING that comes with the
 .\" vdr distribution.
 .\"
-.\" $Id: vdr.1 1.28 2007/01/07 14:03:56 kls Exp $
+.\" $Id: vdr.1 1.29 2007/02/24 17:40:20 kls Exp $
 .\"
 .TH vdr 1 "07 Jan 2007" "1.4.5" "Video Disk Recorder"
 .SH NAME
@@ -153,6 +153,14 @@
 .BI \-w\  sec ,\ \-\-watchdog= sec
 Activate the watchdog timer with a timeout of \fIsec\fR seconds.
 A value of \fB0\fR (default) disables the watchdog.
+.SH SIGNALS
+.TP
+.B SIGINT, SIGTERM
+Program exits with status 0.
+.TP
+.B SIGHUP
+Program exits with status 1. This can be used to force a reload, for example
+if an update has been installed.
 .SH EXIT STATUS
 .TP
 .B 0
diff -ruN vdr-1.5.0/vdr.c vdr-1.5.1/vdr.c
--- vdr-1.5.0/vdr.c	2007-01-05 11:46:14.000000000 +0100
+++ vdr-1.5.1/vdr.c	2007-02-25 12:27:36.000000000 +0100
@@ -22,7 +22,7 @@
  *
  * The project's page is at http://www.cadsoft.de/vdr
  *
- * $Id: vdr.c 1.283 2007/01/05 10:46:14 kls Exp $
+ * $Id: vdr.c 1.285 2007/02/25 11:27:36 kls Exp $
  */
 
 #include <getopt.h>
@@ -54,6 +54,7 @@
 #include "plugin.h"
 #include "rcu.h"
 #include "recording.h"
+#include "shutdown.h"
 #include "skinclassic.h"
 #include "skinsttng.h"
 #include "sources.h"
@@ -66,20 +67,23 @@
 #define MINCHANNELWAIT     10 // seconds to wait between failed channel switchings
 #define ACTIVITYTIMEOUT    60 // seconds before starting housekeeping
 #define SHUTDOWNWAIT      300 // seconds to wait in user prompt before automatic shutdown
+#define SHUTDOWNRETRY     360 // seconds before trying again to shut down
+#define SHUTDOWNFORCEPROMPT 5 // seconds to wait in user prompt to allow forcing shutdown
+#define SHUTDOWNCANCELROMPT 5 // seconds to wait in user prompt to allow canceling shutdown
+#define RESTARTCANCELPROMPT 5 // seconds to wait in user prompt before restarting on SIGHUP
 #define MANUALSTART       600 // seconds the next timer must be in the future to assume manual start
 #define CHANNELSAVEDELTA  600 // seconds before saving channels.conf after automatic modifications
 #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 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; }
+#define EXIT(v) { ShutdownHandler.Exit(v); goto Exit; }
 
-static int Interrupted = 0;
+static int LastSignal = 0;
 
 static bool SetUser(const char *UserName)
 {
@@ -138,10 +142,18 @@
 
 static void SignalHandler(int signum)
 {
-  if (signum != SIGPIPE) {
-     Interrupted = signum;
-     Interface->Interrupt();
-     }
+  isyslog("caught signal %d", signum);
+  switch (signum) {
+    case SIGPIPE:
+         break;
+    case SIGHUP:
+         LastSignal = signum;
+         break;
+    default:
+         LastSignal = signum;
+         Interface->Interrupt();
+         ShutdownHandler.Exit(0);
+    }
   signal(signum, SignalHandler);
 }
 
@@ -184,7 +196,6 @@
   bool MuteAudio = false;
   int WatchdogTimeout = DEFAULTWATCHDOG;
   const char *Terminal = NULL;
-  const char *Shutdown = NULL;
 
   bool UseKbd = true;
   const char *LircDevice = NULL;
@@ -205,7 +216,6 @@
 #endif
 
   cPluginManager PluginManager(DEFAULTPLUGINDIR);
-  int ExitCode = 0;
 
   static struct option long_options[] = {
       { "audio",    required_argument, NULL, 'a' },
@@ -313,7 +323,7 @@
                     break;
           case 'r': cRecordingUserCommand::SetCommand(optarg);
                     break;
-          case 's': Shutdown = optarg;
+          case 's': ShutdownHandler.SetShutdownCommand(optarg);
                     break;
           case 't': Terminal = optarg;
                     if (access(Terminal, R_OK | W_OK) < 0) {
@@ -498,10 +508,7 @@
   int PreviousChannel[2] = { 1, 1 };
   int PreviousChannelIndex = 0;
   time_t LastChannelChanged = time(NULL);
-  time_t LastActivity = 0;
   int MaxLatencyTime = 0;
-  bool ForceShutdown = false;
-  bool UserShutdown = false;
   bool InhibitEpgScan = false;
   bool IsInfoMenu = false;
   cSkin *CurrentSkin = NULL;
@@ -596,6 +603,10 @@
         }
      }
 
+  // Check for timers in automatic start time window:
+
+  ShutdownHandler.CheckManualStart(MANUALSTART);
+
   // User interface:
 
   Interface = new cInterface(SVDRPport);
@@ -668,12 +679,7 @@
 
 #define DELETE_MENU ((IsInfoMenu &= (Menu == NULL)), delete Menu, Menu = NULL)
 
-  while (!Interrupted) {
-        // Handle emergency exits:
-        if (cThread::EmergencyExit()) {
-           esyslog("emergency exit requested - shutting down");
-           break;
-           }
+  while (!ShutdownHandler.DoExit()) {
 #ifdef DEBUGRINGBUFFERS
         cRingBufferLinear::PrintDebugRBL();
 #endif
@@ -856,9 +862,13 @@
         // User Input:
         cOsdObject *Interact = Menu ? Menu : cControl::Control();
         eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse());
-        if (NORMALKEY(key) != kNone) {
+        if (ISREALKEY(key)) {
            EITScanner.Activity();
-           LastActivity = time(NULL);
+           // Cancel shutdown countdown:
+           if (ShutdownHandler.countdown)
+              ShutdownHandler.countdown.Cancel();
+           // Set user active for MinUserInactivity time in the future:
+           ShutdownHandler.SetUserInactiveTimeout();
            }
         // Keys that must work independent of any interactive mode:
         switch (key) {
@@ -875,7 +885,7 @@
                   else
                      WasOpen = false;
                   }
-               if (!WasOpen || !WasMenu && !Setup.MenuButtonCloses)
+               if (!WasOpen || !WasMenu && !Setup.MenuKeyCloses)
                   Menu = new cMenuMain;
                }
                break;
@@ -996,37 +1006,32 @@
                   }
                break;
           // Power off:
-          case kPower: {
+          case kPower:
                isyslog("Power button pressed");
                DELETE_MENU;
-               if (!Shutdown) {
-                  Skins.Message(mtError, tr("Can't shutdown - option '-s' not given!"));
+               // Check for activity, request power button again if active:
+               if (!ShutdownHandler.ConfirmShutdown(false) && Skins.Message(mtWarning, tr("VDR will shut down later - press Power to force"), SHUTDOWNFORCEPROMPT) != kPower) {
+                  // Not pressed power - set VDR to be non-interactive and power down later:
+                  ShutdownHandler.SetUserInactive();
                   break;
                   }
-               LastActivity = 1; // not 0, see below!
-               UserShutdown = true;
-               if (cRecordControls::Active()) {
-                  if (!Interface->Confirm(tr("Recording - shut down anyway?")))
-                     break;
-                  }
-               if (cPluginManager::Active(tr("shut down anyway?")))
+               // No activity or power button pressed twice - ask for confirmation:
+               if (!ShutdownHandler.ConfirmShutdown(true)) {
+                  // Non-confirmed background activity - set VDR to be non-interactive and power down later:
+                  ShutdownHandler.SetUserInactive();
                   break;
-               if (!cRecordControls::Active()) {
-                  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;
+               // Ask the final question:
+               if (!Interface->Confirm(tr("Press any key to cancel shutdown"), SHUTDOWNCANCELROMPT, true))
+                  // If final question was canceled, continue to be active:
+                  break;
+               // Ok, now call the shutdown script:
+               ShutdownHandler.DoShutdown(true);
+               // Set VDR to be non-interactive and power down again later:
+               ShutdownHandler.SetUserInactive();
+               // Do not attempt to automatically shut down for a while:
+               ShutdownHandler.SetRetry(SHUTDOWNRETRY);
                break;
-               }
           default: break;
           }
         Interact = Menu ? Menu : cControl::Control(); // might have been closed in the mean time
@@ -1041,7 +1046,7 @@
                     continue;
                     }
                  }
-              else if (time(NULL) - LastActivity > MENUTIMEOUT)
+              else if (time(NULL) - cRemote::LastActivity() > MENUTIMEOUT)
                  state = osEnd;
               }
            switch (state) {
@@ -1143,77 +1148,55 @@
                  Skins.Message(mtInfo, tr("Editing process finished"));
               }
            }
-        if (!Interact && ((!cRecordControls::Active() && !cCutter::Active() && (!Interface->HasSVDRPConnection() || UserShutdown)) || ForceShutdown)) {
-           time_t Now = time(NULL);
-           if (Now - LastActivity > ACTIVITYTIMEOUT) {
-              // Shutdown:
-              if (Shutdown && (Setup.MinUserInactivity || LastActivity == 1) && Now - LastActivity > Setup.MinUserInactivity * 60) {
-                 cTimer *timer = Timers.GetNextActiveTimer();
-                 time_t Next  = timer ? timer->StartTime() : 0;
-                 time_t Delta = timer ? Next - Now : 0;
-                 if (!LastActivity) {
-                    if (!timer || Delta > MANUALSTART) {
-                       // Apparently the user started VDR manually
-                       dsyslog("assuming manual start of VDR");
-                       LastActivity = Now;
-                       continue; // don't run into the actual shutdown procedure below
-                       }
-                    else
-                       LastActivity = 1;
-                    }
-                 if (timer && Delta < Setup.MinEventTimeout * 60 && ForceShutdown) {
-                    Delta = Setup.MinEventTimeout * 60;
-                    Next = Now + Delta;
-                    timer = NULL;
-                    dsyslog("reboot at %s", *TimeToString(Next));
-                    }
-                 if (!ForceShutdown && cPluginManager::Active()) {
-                    LastActivity = Now - Setup.MinUserInactivity * 60 + SHUTDOWNRETRY; // try again later
-                    continue;
-                    }
-                 if (!Next || Delta > Setup.MinEventTimeout * 60 || ForceShutdown) {
-                    ForceShutdown = false;
-                    if (timer)
-                       dsyslog("next timer event at %s", *TimeToString(Next));
-                    if (WatchdogTimeout > 0)
-                       signal(SIGALRM, SIG_IGN);
-                    if (Interface->Confirm(tr("Press any key to cancel shutdown"), UserShutdown ? 5 : SHUTDOWNWAIT, true)) {
-                       cControl::Shutdown();
-                       int Channel = timer ? timer->Channel()->Number() : 0;
-                       const char *File = timer ? timer->File() : "";
-                       if (timer)
-                          Delta = Next - time(NULL); // compensates for Confirm() timeout
-                       char *cmd;
-                       asprintf(&cmd, "%s %ld %ld %d \"%s\" %d", Shutdown, Next, Delta, Channel, *strescape(File, "\"$"), UserShutdown);
-                       isyslog("executing '%s'", cmd);
-                       SystemExec(cmd);
-                       free(cmd);
-                       LastActivity = time(NULL) - Setup.MinUserInactivity * 60 + SHUTDOWNRETRY; // try again later
-                       }
-                    else {
-                      LastActivity = Now;
-                      if (WatchdogTimeout > 0) {
-                         alarm(WatchdogTimeout);
-                         if (signal(SIGALRM, Watchdog) == SIG_IGN)
-                            signal(SIGALRM, SIG_IGN);
-                         }
-                      }
-                    UserShutdown = false;
-                    continue; // skip the rest of the housekeeping for now
-                    }
-                 }
-              // Disk housekeeping:
-              RemoveDeletedRecordings();
-              cSchedules::Cleanup();
-              // Plugins housekeeping:
-              PluginManager.Housekeeping();
+
+        // SIGHUP shall cause a restart:
+        if (LastSignal == SIGHUP) {
+           if (ShutdownHandler.ConfirmRestart(true) && Interface->Confirm(tr("Press any key to cancel restart"), RESTARTCANCELPROMPT, true))
+              EXIT(1);
+           LastSignal = 0;
+           }
+
+        // Update the shutdown countdown:
+        if (ShutdownHandler.countdown && ShutdownHandler.countdown.Update()) {
+           if (!ShutdownHandler.ConfirmShutdown(false))
+              ShutdownHandler.countdown.Cancel();
+           }
+
+        if (!Interact && !cRecordControls::Active() && !cCutter::Active() && !Interface->HasSVDRPConnection() && cRemote::LastActivity() > ACTIVITYTIMEOUT) {
+           // Handle housekeeping tasks
+
+           // Shutdown:
+           // Check whether VDR will be ready for shutdown in SHUTDOWNWAIT seconds:
+           time_t Soon = time(NULL) + SHUTDOWNWAIT;
+           if (ShutdownHandler.IsUserInactive(Soon) && ShutdownHandler.Retry(Soon) && !ShutdownHandler.countdown) {
+              if (ShutdownHandler.ConfirmShutdown(false))
+                 // Time to shut down - start final countdown:
+                 ShutdownHandler.countdown.Start(tr("VDR will shut down in %s minutes"), SHUTDOWNWAIT); // the placeholder is really %s!
+              // Dont try to shut down again for a while:
+              ShutdownHandler.SetRetry(SHUTDOWNRETRY);
+              }
+           // Countdown run down to 0?
+           if (ShutdownHandler.countdown.Done()) {
+              // Timed out, now do a final check:
+              if (ShutdownHandler.IsUserInactive() && ShutdownHandler.ConfirmShutdown(false))
+                 ShutdownHandler.DoShutdown(false);
+              // Do this again a bit later:
+              ShutdownHandler.SetRetry(SHUTDOWNRETRY);
               }
+
+           // Disk housekeeping:
+           RemoveDeletedRecordings();
+           cSchedules::Cleanup();
+           // Plugins housekeeping:
+           PluginManager.Housekeeping();
            }
+
         // Main thread hooks of plugins:
         PluginManager.MainThreadHook();
         }
-  if (Interrupted)
-     isyslog("caught signal %d", Interrupted);
+
+  if (ShutdownHandler.EmergencyExitRequested())
+     esyslog("emergency exit requested - shutting down");
 
 Exit:
 
@@ -1227,7 +1210,7 @@
   Remotes.Clear();
   Audios.Clear();
   Skins.Clear();
-  if (ExitCode != 2) {
+  if (ShutdownHandler.GetExitCode() != 2) {
      Setup.CurrentChannel = cDevice::CurrentChannel();
      Setup.CurrentVolume  = cDevice::CurrentVolume();
      Setup.Save();
@@ -1238,14 +1221,12 @@
   ReportEpgBugFixStats();
   if (WatchdogTimeout > 0)
      dsyslog("max. latency time %d seconds", MaxLatencyTime);
-  isyslog("exiting");
+  isyslog("exiting, exit code %d", ShutdownHandler.GetExitCode());
+  if (ShutdownHandler.EmergencyExitRequested())
+     esyslog("emergency exit!");
   if (SysLogLevel > 0)
      closelog();
   if (HasStdin)
      tcsetattr(STDIN_FILENO, TCSANOW, &savedTm);
-  if (cThread::EmergencyExit()) {
-     esyslog("emergency exit!");
-     return 1;
-     }
-  return ExitCode;
+  return ShutdownHandler.GetExitCode();
 }
