diff -ruN vdr-1.4.1/CONTRIBUTORS vdr-1.4.2/CONTRIBUTORS
--- vdr-1.4.1/CONTRIBUTORS	2006-06-11 11:13:20.000000000 +0200
+++ vdr-1.4.2/CONTRIBUTORS	2006-08-20 12:46:02.000000000 +0200
@@ -219,6 +219,9 @@
  again
  for reporting a problem with channel up/down switching on single card systems
  for fixing the PremiereContentTransmissionDescriptor in 'libsi'
+ for reporting a double fdopen() in cPipe::Open()
+ for suggesting to increase the APIVERSION to allow plugins that relied on the
+ cStatus::MsgSetVolume() bug to react properly
 
 Ulrich Röder <roeder@efr-net.de>
  for pointing out that there are channels that have a symbol rate higher than 27500
@@ -276,6 +279,8 @@
  for a patch that contained a fix for checking toFile in cCuttingThread::Action()
  for improving cUnbufferedFile
  for fixing calculating the cache size in cUnbufferedFile::Read()
+ for making the /video/.update file be touched _after_ an editing process is finished
+ in order to avoid excessive disk access
 
 Werner Fink <werner@suse.de>
  for making I/O more robust by handling EINTR
@@ -340,6 +345,8 @@
  for reporting a bug in handling min/max borders when entering integer values
  for reporting a problem with replaying in fast forward mode if the video directory
  is mounted via a Samba share
+ for suggesting to make menu items that are derived from cMenuEditIntItem loop
+ though their values if they have a dedicated minimum or maximum limit
 
 Thomas Heiligenmann <thomas@heiligenmann.de>
  for implementing the SVDRP commands LSTR and DELR
@@ -574,6 +581,8 @@
  for reporting a problem with the "Press any key on the RC unit" step when learning
  LIRC remote control codes
  for suggesting to reduce the logging for the SVDRP GRAB command
+ 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
 
 Jeremy Hall <jhall@UU.NET>
  for fixing an incomplete initialization of the filter parameters in eit.c
@@ -630,6 +639,7 @@
  against invalid data
  for reporting a problem in extracting APIVERSION with older versions of 'sed'
  for fixing broken APIVERSION extraction line in 'newplugin'
+ for making VDR no longer stop removing empty directories if an error occurs
 
 Reinhard Walter Buchner <rw.buchner@freenet.de>
  for adding some satellites to 'sources.conf'
@@ -1221,6 +1231,8 @@
  for reporting a problem in handling Transfer Mode for radio channels
  for reporting a problem with messages when a cOsdObject uses the raw OSD
  for implementing palette replace mode in the OSD bitmaps
+ for fixing handling numeric keys in the channel display after switching channel
+ groups
 
 Thomas Bergwinkl <Thomas.Bergwinkl@vr-web.de>
  for fixing the validity check for channel IDs, because some providers use TIDs
@@ -1364,6 +1376,8 @@
  and PremiereContentTransmissionDescriptor to 'libsi'
  for pointing out that plugins might be compiled with different DVB driver header
  files than VDR itself
+ for adding a missing initialization of 'mutex' in cCiMenu::cCiMenu() and removing
+ some superfluous semicolons in ci.c
 
 Jürgen Schmitz <j.schmitz@web.de>
  for reporting a bug in displaying the current channel when switching via the SVDRP
@@ -1440,6 +1454,15 @@
  for fixing handling the "Power" key in case a timer is about to start recording
  for fixing calculating the start time of repeated timers with "first day"
  for setting a timer's cached start time to 0 after a call to Skip()
+ for adding "-fPIC" to the compiler options in Make.config.template when compiling
+ plugins
+ for reporting a missing '--vfat' in the vdr.1 man page
+ for fixing deleting the last character of a string menu item in insert mode
+ for reporting that the shutdown message "Recording in ... minutes, shut down anyway?"
+ may have been given with a negative number of minutes
+ for fixing getting the next active timer when shutting down
+ for reporting a problem with cPlugin::ConfigDirectory() in case a plugin calls it
+ from a separate thread
 
 Sven Kreiensen <svenk@kammer.uni-hannover.de>
  for his help in keeping 'channels.conf.terr' up to date
@@ -1601,6 +1624,9 @@
  for fixing several spelling errors
  for reporting that the call to pthread_setschedparam(childTid, SCHED_RR, 0) in
  thread.c caused a compiler warning with g++ 4.1.1
+ for fixing converting the port number in the "connect from..." log message of SVDRP
+ for reporting that there are places where ntohs() is assigned to different types
+ for adapting cThread::ThreadId() to recent kernels
 
 Steffen Beyer <cpunk@reactor.de>
  for fixing setting the colored button help after deleting a recording in case the next
@@ -1783,6 +1809,8 @@
 Petri Hintukainen <Petri.Hintukainen@hut.fi>
  for suggesting to disable the use of "fadvise" in cUnbufferedFile because there
  have been several reports that it causes more problems than it solves
+ for suggesting to add --remove-destination to the 'cp' command for binaries in
+ the Makefile to avoid a crash in case a new version is installed on a running system
 
 Marcel Schaeben <mts280@gmx.de>
  for his "Easy Input" patch
@@ -1792,6 +1820,7 @@
 
 Patrick Cernko <errror@errror.org>
  for suggesting to add a note about "modprobe capability" to INSTALL
+ for reporting a problem with relative link targets in the ReadLink() function
 
 Philippe Gramoullé <philippe@gramoulle.com>
  for reporting a a missing '-' in the example for viewing a grabbed image on a remote
@@ -1860,6 +1889,7 @@
  the jump instead of closing the display
  for reporting that the log message "deleting plugin: ..." is irritating when
  calling "vdr --help"
+ for fixing cDevice::ToggleMute()
 
 Pekka Mauno <pekka.mauno@iki.fi>
  for fixing cSchedule::GetFollowingEvent() in case there is currently no present
@@ -1925,6 +1955,35 @@
 
 Prakash Punnoor <prakash@punnoor.de>
  for suggesting to remove -fPIC from VDR's and libsi's Makefile
+ for adding a missing variable initialization in cRingBufferLinear::cRingBufferLinear()
 
 Anssi Hannula <anssi.hannula@gmail.com>
  for a patch that was used to implement processing the "frequency list descriptor"
+ for suggesting that cDevice::GetDevice() should prefer any device that's already
+ receiving and doesn't require detatching receivers
+ for improving handling Transfer Mode devices when selecting a device to receive
+
+Antti Hartikainen <ami+vdr@ah.fi>
+ for updating 'S13E' in 'sources.conf'
+
+Bernd Melcher <bernd@bernd-melcher.de>
+ for reporting a problem with the 'servicedemo' plugin having no PLUGIN macro
+
+Patrick Maier <maierp@informatik.tu-muenchen.de>
+ for fixing handling network masks in the svdrphosts.conf file
+
+Norbert Wentz <norbert.wentz@online.de>
+ for reporting a bug in handling relative volume settings in the call to
+ cStatus::MsgSetVolume()
+
+Frank Schmirler <vdr@schmirler.de>
+ for fixing handling client side termination of SVDRP connections
+ for fixing assigning schedules to channels in case there is no initial EPG information
+
+Jörn Reder <joern@zyn.de>
+ for reporting that a recording may unnecessarily block a device with a CAM, while
+ it could record on the primary device as well
+
+Tomas Berglund <tomber@telia.com>
+ for reporting a problem with sticky PIDs in CAMs when switching between encrypted
+ channels on the same transponder
diff -ruN vdr-1.4.1/HISTORY vdr-1.4.2/HISTORY
--- vdr-1.4.1/HISTORY	2006-06-11 11:14:22.000000000 +0200
+++ vdr-1.4.2/HISTORY	2006-08-27 10:42:31.000000000 +0200
@@ -4782,3 +4782,116 @@
 - Changed the log messages when grabbing an image from 'isyslog()' to 'dsyslog()'
   so that they can be suppressed in normal operation mode to avoid clogging the
   log file in case this function is used frequently (suggested by Helmut Auer).
+
+2006-06-18: Version 1.4.1-1
+
+- Added "-fPIC" to the compiler options in Make.config.template when compiling
+  plugins (thanks to Udo Richter). If you use your own Make.config file, you may
+  want to add these lines there, too.
+- Added some comment to cDevice::GetDevice() to explain how the individual
+  conditions are put together to make a decision on which device to use.
+- Updated 'S13E' in 'sources.conf' (thanks to Antti Hartikainen).
+- Now making sure VPS timers don't get stuck with outdated events, and that the
+  actual device isn't used for updating a VPS timer's event as long as other
+  free devices are available.
+- Modified rcu.c to better handle RC5 codes.
+- Added a missing variable initialization in cRingBufferLinear::cRingBufferLinear()
+  (thanks to Prakash Punnoor).
+- Fixed handling relative link targets in the ReadLink() function (reported by
+  Patrick Cernko).
+- Now making sure a VPS timer has a schedule in case the epg.data file didn't
+  contain one when VDR was started.
+
+2006-07-23: Version 1.4.1-2
+
+- Fixed the Makefile of the 'servicedemo' plugin, so that it defines the
+  PLUGIN macro, which allows the Make.config file to react properly when
+  compiling the plugin (reported by Bernd Melcher).
+  Note to all plugin developers: a plugin's Makefile *must* define the PLUGIN
+  macro, even if it doesn't use it itself!
+- Added a comment regarding the PLUGIN macro to the 'newplugin' script.
+- Added '--vfat' to the vdr.1 man page (reported by Udo Richter).
+- Removed a double fdopen() in cPipe::Open() (reported by Stefan Huelswitt).
+- Fixed handling the running status of EPG events before the currently running one,
+  in case they are added after the current event.
+- cEIT::cEIT() now calls pSchedule->SetPresentSeen() even if OnlyRunningStatus is
+  true.
+- Newlines in title and short text of an EPG event are now changed into blanks only
+  after all other fixes, because a short text might become a description.
+- Fixed handling network masks in the svdrphosts.conf file (thanks to Patrick
+  Maier).
+- Fixed handling relative volume settings in the call to cStatus::MsgSetVolume()
+  (reported by Norbert Wentz).
+- Added a missing initialization of 'mutex' in cCiMenu::cCiMenu() and removed
+  some superfluous semicolons in ci.c (thanks to Marco Schlüßler).
+- Fixed handling client side termination of SVDRP connections (thanks to Frank
+  Schmirler).
+- cDevice::GetDevice() now prefers any device that's already receiving and doesn't
+  require detatching receivers (suggested by Anssi Hannula).
+- Fixed handling numeric keys in the channel display after switching channel groups
+  (thanks to Andreas Regel).
+- Menu items derived from cMenuEditIntItem now loop though their values if they
+  have a dedicated minimum or maximum limit (suggested by Andy Grobb). Looping is
+  only done for normal keypresses, not for repeated ones. This allows the user to
+  scroll the value all the way to the limit by keeping the key pressed.
+
+2006-08-06: Version 1.4.1-3
+
+- Fixed assigning schedules to channels in case there is no initial EPG information
+  (thanks to Frank Schmirler).
+- Increased the APIVERSION to allow plugins that relied on the cStatus::MsgSetVolume()
+  bug to react properly (suggested by Stefan Huelswitt).
+- Fixed cDevice::ToggleMute() (thanks to Christoph Haubrich).
+- Fixed deleting the last character of a string menu item in insert mode (thanks
+  to Udo Richter).
+- The /video/.update file is now touched _after_ an editing process is finished
+  in order to avoid excessive disk access (thanks to Artur Skawina).
+- Fixed handling the running status of EPG events before the currently running one,
+  in case they are added after the current event (cont'd from version 1.4.1-2).
+- Modified the shutdown mechanism, so that the shutdown script is never given a
+  time in the past (reported by Helmut Auer). If a timer is currently recording,
+  or a recording would start within the next 30 minutes (default for the "Min.
+  event timeout" setup parameter), and the user insists in shutting down now, the
+  reboot time given to the shutdown script will correspond to a time that is
+  "Min. event timeout" minutes (default is 30) in the future.
+- Avoiding shutdown message "Recording in ... minutes, shut down anyway?" with
+  a negative number of minutes (reported by Udo Richter).
+- Fixed getting the next active timer when shutting down (thanks to Udo Richter).
+- Modified the cSVDRP::Close() function to avoid code duplication.
+
+2006-08-13: Version 1.4.1-4
+
+- Fixed converting the port number in the "connect from..." log message of SVDRP
+  (thanks to Ville Skyttä).
+- Made the cCiSession members sessionId and resourceId uint16_t and uint32_t,
+  respectively, to match their types in the CI session data (thanks to Ville Skyttä
+  for reporting that there are places where ntohs() is assigned to different types).
+- Changed the way a device is selected for receiving in order to keep devices with
+  CAMs better available, even if this means recording on the primary device (reported
+  by Jörn Reder; thanks to Anssi Hannula for improving handling Transfer Mode devices
+  in this).
+- No longer stopping removing empty directories if an error occurs (thanks to
+  Oliver Endriss).
+- Added a log error message to cPlugin::ConfigDirectory() in case a plugin calls it
+  from a separate thread (reported by Udo Richter).
+
+2006-08-20: Version 1.4.1-5
+
+- Replaced the "quick workaround for additional live audio PIDs" in
+  cDvbDevice::SetChannelDevice() with an actual solution in
+  cDvbDevice::SetAudioTrackDevice() in order to prevent sticky PIDs in CAMs,
+  which caused long switching times or completely blank screens when switching
+  between encrypted channels on the same transponder (reported by Tomas Berglund).
+- Adapted cThread::ThreadId() to recent kernels (thanks to Ville Skyttä).
+- Added --remove-destination to the 'cp' command for binaries in the Makefile to
+  avoid a crash in case a new version is installed on a running system (suggested
+  by Petri Hintukainen).
+- Fixed handling "Ca Info" in case the CAM sends this again if the smart card is
+  replaced with a different one.
+
+2006-08-27: Version 1.4.2
+
+- Revoked the change to cDevice::GetDevice() that was introduced in version 1.4.1-2,
+  which made it prefer any device that's already receiving and doesn't require
+  detatching receivers. This change has caused some unwanted behavior, so further
+  testing is necessary.
diff -ruN vdr-1.4.1/INSTALL vdr-1.4.2/INSTALL
--- vdr-1.4.1/INSTALL	2006-05-01 15:35:40.000000000 +0200
+++ vdr-1.4.2/INSTALL	2006-07-30 12:57:25.000000000 +0200
@@ -171,7 +171,7 @@
 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 MinUserInactivity minutes.
+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
@@ -191,11 +191,10 @@
 key). The shutdown program may use this information to decide whether or
 not to actually perform the system shutdown.
 
-If a timer is currently recording, the parameters will reflect the start
-time of that timer. This means that the first parameter will be a time in
-the past, and the second parameter will be a negative number. This only
-happens if the user presses the "Power" key while a timer is currently
-recording.
+If a timer is currently recording, or a recording would start within the
+next 30 minutes (default for the "Min. event timeout" setup parameter), and
+the user insists in shutting down now, the first and second parameter will
+correspond to a time that is "Min. event timeout" minutes in the future.
 
 Before the shutdown program is called, the user will be prompted to inform
 him that the system is about to shut down. If any remote control key is
diff -ruN vdr-1.4.1/Make.config.template vdr-1.4.2/Make.config.template
--- vdr-1.4.1/Make.config.template	2006-05-26 12:41:46.000000000 +0200
+++ vdr-1.4.2/Make.config.template	2006-06-15 11:15:25.000000000 +0200
@@ -6,7 +6,7 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: Make.config.template 1.9 2006/05/26 10:41:46 kls Exp $
+# $Id: Make.config.template 1.10 2006/06/15 09:15:25 kls Exp $
 
 ### The C compiler and options:
 
@@ -16,6 +16,11 @@
 CXX      = g++
 CXXFLAGS = -g -O2 -Wall -Woverloaded-virtual
 
+ifdef PLUGIN
+CFLAGS   += -fPIC
+CXXFLAGS += -fPIC
+endif 
+
 ### The directory environment:
 
 #DVBDIR   = /usr/src/v4l-dvb/linux
diff -ruN vdr-1.4.1/Makefile vdr-1.4.2/Makefile
--- vdr-1.4.1/Makefile	2006-06-02 16:45:33.000000000 +0200
+++ vdr-1.4.2/Makefile	2006-08-20 12:44:22.000000000 +0200
@@ -4,7 +4,7 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: Makefile 1.94 2006/06/02 14:45:33 kls Exp $
+# $Id: Makefile 1.95 2006/08/20 10:44:22 kls Exp $
 
 .DELETE_ON_ERROR:
 
@@ -201,7 +201,7 @@
 
 install-bin: vdr
 	@mkdir -p $(BINDIR)
-	@cp vdr runvdr $(BINDIR)
+	@cp --remove-destination vdr runvdr $(BINDIR)
 
 # Configuration files:
 
@@ -223,7 +223,7 @@
 
 install-plugins: plugins
 	@mkdir -p $(PLUGINLIBDIR)
-	@cp $(PLUGINDIR)/lib/lib*-*.so.$(APIVERSION) $(PLUGINLIBDIR)
+	@cp --remove-destination $(PLUGINDIR)/lib/lib*-*.so.$(APIVERSION) $(PLUGINLIBDIR)
 
 # Source documentation:
 
diff -ruN vdr-1.4.1/PLUGINS/src/servicedemo/Makefile vdr-1.4.2/PLUGINS/src/servicedemo/Makefile
--- vdr-1.4.1/PLUGINS/src/servicedemo/Makefile	2006-04-24 19:21:01.000000000 +0200
+++ vdr-1.4.2/PLUGINS/src/servicedemo/Makefile	2006-06-24 11:09:54.000000000 +0200
@@ -1,12 +1,13 @@
 #
 # Makefile for a Video Disk Recorder plugin
 #
-# $Id: Makefile 1.6 2006/04/24 17:21:01 kls Exp $
+# $Id: Makefile 1.7 2006/06/24 09:09:54 kls Exp $
 
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
 # By default the main source file also carries this name.
 #
+PLUGIN  = servicedemo # dummy name for Make.config
 PLUGIN1 = svccli
 PLUGIN2 = svcsvr
 
diff -ruN vdr-1.4.1/channels.conf vdr-1.4.2/channels.conf
--- vdr-1.4.1/channels.conf	2006-04-23 16:02:30.000000000 +0200
+++ vdr-1.4.2/channels.conf	2006-08-27 10:48:58.000000000 +0200
@@ -17,7 +17,7 @@
 arte;ARD:11836:hC34:S19.2E:27500:401:402=deu,403=fra:404:0:28109:1:1101:0
 ORF1;ORF:12692:hC56:S19.2E:22000:160:161=deu;163=deu:165:1762,D05,1801,1702:13001:1:1117:0
 ORF2;ORF:12692:hC56:S19.2E:22000:500:501=deu;503=deu:505:1762,D05,1801,1702:13002:1:1117:0
-ZDFinfokanal;ZDFvision:11953:hC34:S19.2E:27500:610:620=deu:130:0:28011:1:1079:0
+ZDFinfokanal;ZDFvision:11953:hC34:S19.2E:27500:610:620=deu:630:0:28011:1:1079:0
 CNN Int.;CNN:11778:vC34:S19.2E:27500:165:100=eng:47:0:28522:1:1068:0
 Super RTL,S RTL;RTL World:12187:hC34:S19.2E:27500:165:120=deu:65:0:12040:1:1089:0
 VOX;RTL World:12187:hC34:S19.2E:27500:167:136=deu:71:0:12060:1:1089:0
@@ -27,9 +27,9 @@
 DSF;BetaDigital:12480:vC34:S19.2E:27500:1023:1024=deu:39:0:900:133:33:0
 HSE24,HSE24;BetaDigital:12480:vC34:S19.2E:27500:1279:1280=deu:37:0:40:133:33:0
 Bloomberg TV Germany;Bloomberg:12551:vC56:S19.2E:22000:162:99=deu:0:0:12160:1:1108:0
-EURONEWS;CSAT:11817:vC34:S19.2E:27500:163:92=fra,91=rus,93=eng,94=ita,95=esl,98=por,99=deu:0:0:8004:1:1070:0
+EURONEWS;CSAT:11817:vC34:S19.2E:27500:163:92=fra,93=eng,94=ita,95=esl,91=rus,98=por,99=deu:0:0:8004:1:1070:0
 rbb Brandenburg;ARD:12109:hC34:S19.2E:27500:601:602=deu:604:0:28205:1:1073:0
-Sky News;BT:11597:vC56:S19.2E:22000:305+131:306=eng:0:0:28707:1:1026:0
+Sky News;BT:11597:vC56:S19.2E:22000:305+131:306=eng:579:0:28707:1:1026:0
 Veronica/JETIX;CANALDIGITAAL:12574:hC56:S19.2E:22000:518+8190:92=dut:38:622,100:5020:53:1109:0
 BVN;CANALDIGITAAL:12574:hC56:S19.2E:22000:515+8190:96=dut:36:0:5025:53:1109:0
 n-tv;RTL World:12187:hC34:S19.2E:27500:169:73=deu:80:0:12090:1:1089:0
@@ -39,33 +39,35 @@
 EinsExtra;ARD:12109:hC34:S19.2E:27500:101:102=deu:0:0:28201:1:1073:0
 EinsFestival;ARD:12109:hC34:S19.2E:27500:201:202=deu:204:0:28202:1:1073:0
 EinsPlus;ARD:12109:hC34:S19.2E:27500:301:302=deu:0:0:28203:1:1073:0
-ZDFtheaterkanal;ZDFvision:11953:hC34:S19.2E:27500:1110:1120=deu:130:0:28016:1:1079:0
-ZDFdokukanal;ZDFvision:11953:hC34:S19.2E:27500:660:670=deu:130:0:28014:1:1079:0
+ZDFtheaterkanal;ZDFvision:11953:hC34:S19.2E:27500:1110:1120=deu:630:0:28016:1:1079:0
+ZDFdokukanal;ZDFvision:11953:hC34:S19.2E:27500:660:670=deu:630:0:28014:1:1079:0
 MDR FERNSEHEN;ARD:12109:hC34:S19.2E:27500:401:402=deu:404:0:28204:1:1073:0
 rbb Berlin;ARD:12109:hC34:S19.2E:27500:601:602=deu:604:0:28206:1:1073:0
 :Premiere World
-PREMIERE START,START;PREMIERE:11797:hC34:S19.2E:27500:255:256=deu:32:1722,1801,1702:8:133:2:0
-PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:32:1722,1801,1702:10:133:2:0
-PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu,1793=deu;1795=deu:32:1722,1801,1702:11:133:2:0
-PREMIERE 3,PREM 3;PREMIERE:11797:hC34:S19.2E:27500:2303:2304=deu,2305=deu:32:1722,1801,1702:43:133:2:0
-PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu,769=deu:32:1722,1801,1702:9:133:2:0
-PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu,1281=deu:32:1722,1801,1702:29:133:2:0
-PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1722,1801,1702:41:133:2:0
-PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1702,1801,1722:20:133:2:0
-DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:32:1722,1801,1702:34:133:17:0
+PREMIERE START,START;PREMIERE:12070:hC34:S19.2E:27500:3071:3072=deu:32:1801,1702,1722:8:133:1:0
+PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:32:1:10:133:2:0
+PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu;1795=deu:32:1:11:133:2:0
+PREMIERE 3,PREM 3;PREMIERE:11797:hC34:S19.2E:27500:2303:2304=deu,2305=deu;2307=deu:32:1:43:133:2:0
+PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu,769=deu;771=deu:32:1801,1722,1702:9:133:2:0
+PREMIERE SERIE,SERIE;PREMIERE:11797:hC34:S19.2E:27500:2559:2560=deu;2563=deu:32:1801,1702,1722:16:133:2:0
+PREMIERE KRIMI,KRIMI;PREMIERE:11797:hC34:S19.2E:27500:2815:2816=deu:32:1702,1801,1722:23:133:2:0
+PREMIERE NOSTALGIE,NOSTALGIE;PREMIERE:11719:hC34:S19.2E:27500:1535:1536=deu:32:1702,1801,1722:516:133:3:0
+PREMIERE FILMCLASSICS,FILMCLASSICS;PREMIERE:11719:hC34:S19.2E:27500:1023:1024=deu:32:1801,1702,1722:41:133:3:0
+PREMIERE FILMFEST,FILMFEST;PREMIERE:11719:hC34:S19.2E:27500:1279:1280=deu:32:1801,1702,1722:20:133:3:0
+DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:32:1:34:133:17:0
 :Premiere Direkt
 PREMIERE DIREKT,DIREKT;PREMIERE:12031:hC34:S19.2E:27500:2815:2816=deu,2817=deu;2819=deu:0:0:18:133:4:0
 :PW Erotic
-BEATE-UHSE.TV,B-UHSE;PREMIERE:11758:hC34:S19.2E:27500:1791:1792=deu:32:1722,1702,1801:21:133:17:0
-EROTIK - AB 18!,AB 18!;PREMIERE:12031:hC34:S19.2E:27500:1279:1280=deu:0:1722,1801,1702,1810:513:133:4:0
+BEATE-UHSE.TV,B-UHSE;PREMIERE:11758:hC34:S19.2E:27500:1791:1792=deu:32:1702,1722,1801:21:133:17:0
+EROTIK - AB 18!,AB 18!;PREMIERE:12031:hC34:S19.2E:27500:1279:1280=deu:0:1801,1702,1722,1810:513:133:4:0
 :Sportsworld
-PREMIERE SPORT PORTAL,SPORT PORTAL;PREMIERE:11719:hC34:S19.2E:27500:255:256=deu,257=deu:32:1722,1801,1702:17:133:3:0
-PREMIERE WIN,WIN;PREMIERE:12031:hC34:S19.2E:27500:3839:3840=deu:33:0:27:133:4:0
+PREMIERE SPORT PORTAL,SPORT PORTAL;PREMIERE:11719:hC34:S19.2E:27500:255:256=deu,257=deu;259=deu:32:1722,1801,1702:17:133:3:0
+Live Wetten:12031:hC34:S19.2E:27500:3839:3840=deu:33:0:27:133:4:0
 :Beta Digital
 N24;ProSiebenSat.1:12480:vC34:S19.2E:27500:2047:2048=deu:36:0:47:133:33:0
 LibertyTV FR;LibertyTV.com:12610:vC56:S19.2E:22000:941:943=deu:0:0:12199:1:1112:0
 :-
-münchen.TV/RFO,müTV/RFO;BetaDigital:12148:hC34:S19.2E:27500:495:496:0:0:658:133:7:0
+münchen.TV/RFO,müTV/RFO;BetaDigital:12148:hC34:S19.2E:27500:495:496=deu:0:0:658:133:7:0
 ProSieben Austria;ProSiebenSat.1:12051:vC34:S19.2E:27500:161:84=deu;85=deu:36:0:20002:1:1082:0
 Kabel 1 Schweiz;ProSiebenSat.1:12051:vC34:S19.2E:27500:162:163=deu:165:0:20003:1:1082:0
 Kabel 1 Austria;ProSiebenSat.1:12051:vC34:S19.2E:27500:166:167=deu:169:0:20004:1:1082:0
@@ -73,17 +75,17 @@
 FRANCE 5;CSAT:12207:vC34:S19.2E:27500:160:80=fra:32:500,100:8501:1:1090:0
 LCP;ABSAT:12285:vC34:S19.2E:27500:167:108:0:0:17027:1:1094:0
 ESCALES;ABSAT:12285:vC34:S19.2E:27500:165:100:41:500,100:17025:1:1094:0
-Best of Shopping;CSAT:12324:vC34:S19.2E:27500:160:80=fra:0:0:8612:1:1096:0
+BEST OF SHOPPING;CSAT:12324:vC34:S19.2E:27500:160:80=fra:0:0:8612:1:1096:0
 ASTRA-Mosaic;SES ASTRA:12551:vC56:S19.2E:22000:175:176=fra:0:0:3988:1:1108:0
 ASTRA-Mosaic 2;SES ASTRA:12551:vC56:S19.2E:22000:179:120=fra:0:0:3987:1:1108:0
 ASTRA-Mosaic 3;SES ASTRA:12551:vC56:S19.2E:22000:182:169=fra:0:0:3986:1:1108:0
 ASTRA-Mosaic 4;SES ASTRA:12551:vC56:S19.2E:22000:185:170=fra:0:0:3985:1:1108:0
 ASTRA-Mosaic 5;SES ASTRA:12551:vC56:S19.2E:22000:163:164:0:0:3984:1:1108:0
 Chamber TV;Chambre des Députées:12551:vC56:S19.2E:22000:55:56=ltz:0:0:12180:1:1108:0
-RTL TELE Letzebuerg:12551:vC56:S19.2E:22000:168:144=eng,146=fra,151=ltz:0:0:3994:1:1108:0
+RTL TELE Letzebuerg:12551:vC56:S19.2E:22000:168:144=ltz,146=fra:74:0:3994:1:1108:0
 Nick/Talpa;CANALDIGITAAL:12574:hC56:S19.2E:22000:512+8190:84=dut:33:622,100:5010:53:1109:0
 NICK;MTV Networks:12226:hC34:S19.2E:27500:513+8190:661=deu:577:0:28640:1:1091:0
-MTV Central;MTV Networks:11739:vC34:S19.2E:27500:3031:3032:3034:0:28653:1:1066:0
+Service 3;MTV Networks:11739:vC34:S19.2E:27500:3031:3032:3034:0:28653:1:1066:0
 VIVA;MTV Networks:11973:vC34:S19.2E:27500:4061+8190:4062:4064:0:28676:1:1078:0
 VIVA PLUS;MTV Networks:11973:vC34:S19.2E:27500:4071+8190:4072:4074:0:28677:1:1078:0
 QVC Deutschland;QVC:12551:vC56:S19.2E:22000:165:166:167:0:12100:1:1108:0
@@ -92,8 +94,8 @@
 Venevision;T-Systems/MTI:11200:vC56:S13.0E:27500:922:923=und:0:0:4750:0:13400:0
 EBC.1;T-Systems/MTI:11200:vC56:S13.0E:27500:373:374=eng:0:0:4747:0:13400:0
 :HDTV
-HDFORUM;TF1:11242:vC34:S13.0E:27500:33:36=fra:0:0:13809:100:200:0
-HDFORUM;TF1:11242:vC34:S13.0E:27500:33:36=fra:0:0:13809:318:200:0
+HDFORUM;TF1:11242:vC34:S13.0E:27500:0:36=fra:0:0:13809:100:200:0
+HD FORUM;EUTELSAT:11240:vC34:S13.0E:27500:33:36=fra:0:0:13809:318:200:0
 Euro1080 HD-5;Euro1080:10758:vC78:S23.5E:22000:34:160=eng:0:0:1085:9999:3104:0
 Euro1080;EURO1080:12168:vC56:S19.2E:27500:308:256:0:0:21100:1:1088:0
 SMD HD;SES ASTRA:12699:vC56:S19.2E:22000:133+80:234=eng:0:0:29700:0:0:0
@@ -105,12 +107,12 @@
 HELLAS-HDTV;Scopus Network Technologies:11642:hC34:S13.0E:27500:2201:2211=ell,2212=eng:0:0:2200:318:15700:0
 TPS Star:10757:vC34:S13.0E:27500:420:430=fra,431=eng:440:500,100:1204:176:11200:0
 :@201 Sky
-Sky One;BSkyB:12226:hC23:S28.2E:27500:515+8190:643=eng:579:960,961:4705:2:2027:0
+Sky One;BSkyB:12285:vC23:S28.2E:27500:513+8190:641=eng,661=NAR:577:960,961:4703:2:2030:0
 Sky Two;BSkyB:12226:hC23:S28.2E:27500:514+8190:642=eng,662=NAR:578:960,961:5104:2:2027:0
-ITV2;BSkyB:10758:vC56:S28.2E:22000:2314:2315=eng,2363=NAR:2317:0:10070:2:2044:0
+ITV2;BSkyB:10758:vC56:S28.2E:22000:2348:2350=eng,2352=NAR:2354:0:10070:2:2044:0
 SCI FI;BSkyB:12148:hC23:S28.2E:27500:512+8190:640=eng,660=NAR:576:960,961:4905:2:2023:0
 ParaComedy 1;BSkyB:12187:hC23:S28.2E:27500:518+8190:666=eng,686=NAR:582:960,961:5904:2:2025:0
-Paramount;BSkyB:11526:vC23:S28.2E:27500:2317+2306:2318=eng:2319:960,961:50305:2:2404:0
+ParaComedy 1;BSkyB:11526:vC23:S28.2E:27500:2317+2306:2318=eng:2319:960,961:50305:2:2404:0
 ParaComedy 2;BSkyB:11914:hC23:S28.2E:27500:514+8190:642=eng,662=NAR:578:960,961:4504:2:2011:0
 Discovery;BSkyB:11875:hC23:S28.2E:27500:2308:2310=eng,2311=NAR:2309:960,961:6201:2:2009:0
 Sky Movies 1;BSkyB:11836:hC23:S28.2E:27500:518+8190:646=eng,653=NAR;666=eng:582:960,961:4303:2:2007:0
@@ -127,12 +129,14 @@
 :@900 Some 'seed' channels
 Chelsea TV;BskyB:11778:vC23:S28.2E:27500:2308+2304:2309=eng:0:960,961:9307:2:2004:0
 WDR Münster;ARD:12421:hC34:S19.2E:27500:101:102=deu:104:0:28310:1:1201:0
-Animal Plnt+;BSkyB:12070:hC23:S28.2E:27500:2315+2307:2316=eng:0:960,961:50002:2:2019:0
+Animal Plnt+1;BSkyB:12070:hC23:S28.2E:27500:514+8190:662=eng:0:960,961:50002:2:2019:0
 S1T;BSkyB:12285:vC23:S28.2E:27500:513+8190:641=eng,661=NAR:577:960,961:4409:2:2030:0
 CNN;BSkyB:12051:vC23:S28.2E:27500:2313:2315=eng:2314:0:7140:2:2018:0
 BBC PARL'MNT;BSkyB:10847:vC56:S28.2E:22000:2327:2328=eng:2331:0:6902:2:2050:0
-IGLESIA MME;T-Systems/MTI:11200:vC56:S13.0E:27500:4097:4098:0:0:4733:318:13400:0
-eng-WRN-multi;WRN:12597:vC34:S13.0E:27500:0:2132:0:0:8230:318:9400:0
+MTI;T-Systems/MTI:11200:vC56:S13.0E:27500:4097:4098:0:0:4733:318:13400:0
+WRN Eng AAP;WRN:12597:vC34:S13.0E:27500:0:2132:0:0:8230:318:9400:0
+Dr Dish TV;Overon:12359:hC34:S13.0E:27500:4231:4232=eng:0:0:14023:318:8300:0
+! LifeStyle-TV !;T-Systems:12633:hC56:S19.2E:22000:204:304=deu:0:0:12603:1:1113:0
 Challenger Tv;Telespazio:11295:hC34:S13.0E:27500:490:491:0:0:8409:318:500:0
-TVS Teleport Bonn;DMV:11535:vC34:S1.0W:5632:308+8190:256=eng,257=eng:0:3:1:65535:1:0
+TVS Teleport Bonn;DMV:11535:vC34:S1.0W:5632:308+8190:256=eng,257=eng:0:0:1:65535:1:0
 :@1000 New channels
diff -ruN vdr-1.4.1/ci.c vdr-1.4.2/ci.c
--- vdr-1.4.1/ci.c	2006-01-07 16:07:16.000000000 +0100
+++ vdr-1.4.2/ci.c	2006-08-20 13:38:33.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: ci.c 1.42 2006/01/07 15:07:16 kls Exp $
+ * $Id: ci.c 1.45 2006/08/20 11:38:33 kls Exp $
  */
 
 #include "ci.h"
@@ -630,24 +630,24 @@
 
 class cCiSession {
 private:
-  int sessionId;
-  int resourceId;
+  uint16_t sessionId;
+  uint32_t resourceId;
   cCiTransportConnection *tc;
 protected:
   int GetTag(int &Length, const uint8_t **Data);
   const uint8_t *GetData(const uint8_t *Data, int &Length);
   int SendData(int Tag, int Length = 0, const uint8_t *Data = NULL);
 public:
-  cCiSession(int SessionId, int ResourceId, cCiTransportConnection *Tc);
+  cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc);
   virtual ~cCiSession();
   const cCiTransportConnection *Tc(void) { return tc; }
-  int SessionId(void) { return sessionId; }
-  int ResourceId(void) { return resourceId; }
+  uint16_t SessionId(void) { return sessionId; }
+  uint32_t ResourceId(void) { return resourceId; }
   virtual bool HasUserIO(void) { return false; }
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   };
 
-cCiSession::cCiSession(int SessionId, int ResourceId, cCiTransportConnection *Tc)
+cCiSession::cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc)
 {
   sessionId = SessionId;
   resourceId = ResourceId;
@@ -711,11 +711,11 @@
 private:
   int state;
 public:
-  cCiResourceManager(int SessionId, cCiTransportConnection *Tc);
+  cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   };
 
-cCiResourceManager::cCiResourceManager(int SessionId, cCiTransportConnection *Tc)
+cCiResourceManager::cCiResourceManager(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_RESOURCE_MANAGER, Tc)
 {
   dbgprotocol("New Resource Manager (session id %d)\n", SessionId);
@@ -729,12 +729,12 @@
      switch (Tag) {
        case AOT_PROFILE_ENQ: {
             dbgprotocol("%d: <== Profile Enquiry\n", SessionId());
-            int resources[] = { htonl(RI_RESOURCE_MANAGER),
-                                htonl(RI_APPLICATION_INFORMATION),
-                                htonl(RI_CONDITIONAL_ACCESS_SUPPORT),
-                                htonl(RI_DATE_TIME),
-                                htonl(RI_MMI)
-                              };
+            uint32_t resources[] = { htonl(RI_RESOURCE_MANAGER),
+                                     htonl(RI_APPLICATION_INFORMATION),
+                                     htonl(RI_CONDITIONAL_ACCESS_SUPPORT),
+                                     htonl(RI_DATE_TIME),
+                                     htonl(RI_MMI)
+                                   };
             dbgprotocol("%d: ==> Profile\n", SessionId());
             SendData(AOT_PROFILE, sizeof(resources), (uint8_t*)resources);
             state = 3;
@@ -779,14 +779,14 @@
   uint16_t manufacturerCode;
   char *menuString;
 public:
-  cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc);
+  cCiApplicationInformation(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual ~cCiApplicationInformation();
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   bool EnterMenu(void);
   const char *GetMenuString(void) { return menuString; }
   };
 
-cCiApplicationInformation::cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc)
+cCiApplicationInformation::cCiApplicationInformation(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_APPLICATION_INFORMATION, Tc)
 {
   dbgprotocol("New Application Information (session id %d)\n", SessionId);
@@ -963,14 +963,14 @@
   int numCaSystemIds;
   unsigned short caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
 public:
-  cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc);
+  cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   const unsigned short *GetCaSystemIds(void) { return caSystemIds; }
   bool SendPMT(cCiCaPmt *CaPmt);
   bool ReceivedReply(bool CanDescramble = false);
   };
 
-cCiConditionalAccessSupport::cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc)
+cCiConditionalAccessSupport::cCiConditionalAccessSupport(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_CONDITIONAL_ACCESS_SUPPORT, Tc)
 {
   dbgprotocol("New Conditional Access Support (session id %d)\n", SessionId);
@@ -985,6 +985,7 @@
      switch (Tag) {
        case AOT_CA_INFO: {
             dbgprotocol("%d: <== Ca Info", SessionId());
+            numCaSystemIds = 0;
             int l = 0;
             const uint8_t *d = GetData(Data, l);
             while (l > 1) {
@@ -992,13 +993,14 @@
                   dbgprotocol(" %04X", id);
                   d += 2;
                   l -= 2;
-                  if (numCaSystemIds < MAXCASYSTEMIDS) {
+                  if (numCaSystemIds < MAXCASYSTEMIDS)
                      caSystemIds[numCaSystemIds++] = id;
-                     caSystemIds[numCaSystemIds] = 0;
-                     }
-                  else
+                  else {
                      esyslog("ERROR: too many CA system IDs!");
+                     break;
+                     }
                   }
+            caSystemIds[numCaSystemIds] = 0;
             dbgprotocol("\n");
             }
             state = 2; // got ca info
@@ -1090,11 +1092,11 @@
   time_t lastTime;
   bool SendDateTime(void);
 public:
-  cCiDateTime(int SessionId, cCiTransportConnection *Tc);
+  cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   };
 
-cCiDateTime::cCiDateTime(int SessionId, cCiTransportConnection *Tc)
+cCiDateTime::cCiDateTime(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_DATE_TIME, Tc)
 {
   interval = 0;
@@ -1193,7 +1195,7 @@
   cCiMenu *menu, *fetchedMenu;
   cCiEnquiry *enquiry, *fetchedEnquiry;
 public:
-  cCiMMI(int SessionId, cCiTransportConnection *Tc);
+  cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc);
   virtual ~cCiMMI();
   virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
   virtual bool HasUserIO(void) { return menu || enquiry; }
@@ -1204,7 +1206,7 @@
   bool SendCloseMMI(void);
   };
 
-cCiMMI::cCiMMI(int SessionId, cCiTransportConnection *Tc)
+cCiMMI::cCiMMI(uint16_t SessionId, cCiTransportConnection *Tc)
 :cCiSession(SessionId, RI_MMI, Tc)
 {
   dbgprotocol("New MMI (session id %d)\n", SessionId);
@@ -1387,6 +1389,7 @@
 cCiMenu::cCiMenu(cCiMMI *MMI, bool Selectable)
 {
   mmi = MMI;
+  mutex = NULL;
   selectable = Selectable;
   titleText = subTitleText = bottomText = NULL;
   numEntries = 0;
@@ -1445,8 +1448,8 @@
 {
   mmi = MMI;
   text = NULL;
-  blind = false;;
-  expectedLength = 0;;
+  blind = false;
+  expectedLength = 0;
 }
 
 cCiEnquiry::~cCiEnquiry()
@@ -1523,12 +1526,12 @@
   return NULL;
 }
 
-int cCiHandler::ResourceIdToInt(const uint8_t *Data)
+uint32_t cCiHandler::ResourceIdToInt(const uint8_t *Data)
 {
-  return (ntohl(get_unaligned((int32_t *)Data)));
+  return (ntohl(get_unaligned((uint32_t *)Data)));
 }
 
-bool cCiHandler::Send(uint8_t Tag, int SessionId, int ResourceId, int Status)
+bool cCiHandler::Send(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId, int Status)
 {
   uint8_t buffer[16];
   uint8_t *p = buffer;
@@ -1537,7 +1540,7 @@
   if (Status >= 0)
      *p++ = Status;
   if (ResourceId) {
-     put_unaligned(htonl(ResourceId), (int32_t *)p);
+     put_unaligned(htonl(ResourceId), (uint32_t *)p);
      p += 4;
      }
   put_unaligned(htons(SessionId), (uint16_t *)p);
@@ -1546,7 +1549,7 @@
   return tc && tc->SendData(p - buffer, buffer) == OK;
 }
 
-cCiSession *cCiHandler::GetSessionBySessionId(int SessionId)
+cCiSession *cCiHandler::GetSessionBySessionId(uint16_t SessionId)
 {
   for (int i = 0; i < MAX_CI_SESSION; i++) {
       if (sessions[i] && sessions[i]->SessionId() == SessionId)
@@ -1555,7 +1558,7 @@
   return NULL;
 }
 
-cCiSession *cCiHandler::GetSessionByResourceId(int ResourceId, int Slot)
+cCiSession *cCiHandler::GetSessionByResourceId(uint32_t ResourceId, int Slot)
 {
   for (int i = 0; i < MAX_CI_SESSION; i++) {
       if (sessions[i] && sessions[i]->Tc()->Slot() == Slot && sessions[i]->ResourceId() == ResourceId)
@@ -1564,7 +1567,7 @@
   return NULL;
 }
 
-cCiSession *cCiHandler::CreateSession(int ResourceId)
+cCiSession *cCiHandler::CreateSession(uint32_t ResourceId)
 {
   if (!GetSessionByResourceId(ResourceId, tc->Slot())) {
      for (int i = 0; i < MAX_CI_SESSION; i++) {
@@ -1587,7 +1590,7 @@
 bool cCiHandler::OpenSession(int Length, const uint8_t *Data)
 {
   if (Length == 6 && *(Data + 1) == 0x04) {
-     int ResourceId = ResourceIdToInt(Data + 2);
+     uint32_t ResourceId = ResourceIdToInt(Data + 2);
      dbgprotocol("OpenSession %08X\n", ResourceId);
      switch (ResourceId) {
        case RI_RESOURCE_MANAGER:
@@ -1610,9 +1613,9 @@
   return false;
 }
 
-bool cCiHandler::CloseSession(int SessionId)
+bool cCiHandler::CloseSession(uint16_t SessionId)
 {
-  dbgprotocol("CloseSession %08X\n", SessionId);
+  dbgprotocol("CloseSession %d\n", SessionId);
   cCiSession *Session = GetSessionBySessionId(SessionId);
   if (Session && sessions[SessionId - 1] == Session) {
      delete Session;
@@ -1674,7 +1677,7 @@
             if (Data && Length > 1) {
                switch (*Data) {
                  case ST_SESSION_NUMBER:          if (Length > 4) {
-                                                     int SessionId = ntohs(get_unaligned((uint16_t *)&Data[2]));
+                                                     uint16_t SessionId = ntohs(get_unaligned((uint16_t *)&Data[2]));
                                                      cCiSession *Session = GetSessionBySessionId(SessionId);
                                                      if (Session)
                                                         Session->Process(Length - 4, Data + 4);
diff -ruN vdr-1.4.1/ci.h vdr-1.4.2/ci.h
--- vdr-1.4.1/ci.h	2006-01-07 16:03:05.000000000 +0100
+++ vdr-1.4.2/ci.h	2006-08-12 11:43:31.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: ci.h 1.21 2006/01/07 15:03:05 kls Exp $
+ * $Id: ci.h 1.22 2006/08/12 09:43:31 kls Exp $
  */
 
 #ifndef __CI_H
@@ -110,14 +110,14 @@
   int source;
   int transponder;
   cList<cCiCaProgramData> caProgramList;
-  int ResourceIdToInt(const uint8_t *Data);
-  bool Send(uint8_t Tag, int SessionId, int ResourceId = 0, int Status = -1);
+  uint32_t ResourceIdToInt(const uint8_t *Data);
+  bool Send(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0, int Status = -1);
   const unsigned short *GetCaSystemIds(int Slot);
-  cCiSession *GetSessionBySessionId(int SessionId);
-  cCiSession *GetSessionByResourceId(int ResourceId, int Slot);
-  cCiSession *CreateSession(int ResourceId);
+  cCiSession *GetSessionBySessionId(uint16_t SessionId);
+  cCiSession *GetSessionByResourceId(uint32_t ResourceId, int Slot);
+  cCiSession *CreateSession(uint32_t ResourceId);
   bool OpenSession(int Length, const uint8_t *Data);
-  bool CloseSession(int SessionId);
+  bool CloseSession(uint16_t SessionId);
   int CloseAllSessions(int Slot);
   cCiHandler(int Fd, int NumSlots);
   void SendCaPmt(void);
diff -ruN vdr-1.4.1/config.c vdr-1.4.2/config.c
--- vdr-1.4.1/config.c	2006-04-17 14:43:57.000000000 +0200
+++ vdr-1.4.2/config.c	2006-07-22 13:57:51.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.c 1.145 2006/04/17 12:43:57 kls Exp $
+ * $Id: config.c 1.146 2006/07/22 11:57:51 kls Exp $
  */
 
 #include "config.h"
@@ -106,8 +106,10 @@
      *(char *)p = 0; // yes, we know it's 'const' - will be restored!
      if (m == 0)
         mask = 0;
-     else
-        mask >>= (32 - m);
+     else {
+        mask <<= (32 - m);
+        mask = htonl(mask);
+        }
      }
   int result = inet_aton(s, &addr);
   if (p)
diff -ruN vdr-1.4.1/config.h vdr-1.4.2/config.h
--- vdr-1.4.1/config.h	2006-06-11 10:57:35.000000000 +0200
+++ vdr-1.4.2/config.h	2006-08-26 16:16:34.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: config.h 1.260 2006/06/11 08:57:35 kls Exp $
+ * $Id: config.h 1.267 2006/08/26 14:16:34 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -21,13 +21,13 @@
 
 // VDR's own version number:
 
-#define VDRVERSION  "1.4.1"
-#define VDRVERSNUM   10401  // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION  "1.4.2"
+#define VDRVERSNUM   10402  // Version * 10000 + Major * 100 + Minor
 
 // The plugin API's version number:
 
-#define APIVERSION  "1.4.1"
-#define APIVERSNUM   10401  // Version * 10000 + Major * 100 + Minor
+#define APIVERSION  "1.4.2"
+#define APIVERSNUM   10402  // Version * 10000 + Major * 100 + Minor
 
 // When loading plugins, VDR searches them by their APIVERSION, which
 // may be smaller than VDRVERSION in case there have been no changes to
diff -ruN vdr-1.4.1/cutter.c vdr-1.4.2/cutter.c
--- vdr-1.4.1/cutter.c	2006-02-12 11:07:23.000000000 +0100
+++ vdr-1.4.2/cutter.c	2006-07-30 12:22:08.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: cutter.c 1.15 2006/02/12 10:07:23 kls Exp $
+ * $Id: cutter.c 1.16 2006/07/30 10:22:08 kls Exp $
  */
 
 #include "cutter.h"
@@ -171,6 +171,7 @@
                  LastMark = true;
               }
            }
+     Recordings.TouchUpdate();
      }
   else
      esyslog("no editing marks found!");
@@ -205,7 +206,7 @@
         // XXX
         editedVersionName = strdup(evn);
         Recording.WriteInfo();
-        Recordings.AddByName(editedVersionName);
+        Recordings.AddByName(editedVersionName, false);
         cuttingThread = new cCuttingThread(FileName, editedVersionName);
         return true;
         }
diff -ruN vdr-1.4.1/device.c vdr-1.4.2/device.c
--- vdr-1.4.1/device.c	2006-05-27 13:14:42.000000000 +0200
+++ vdr-1.4.2/device.c	2006-08-26 16:11:03.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.c 1.130 2006/05/27 11:14:42 kls Exp $
+ * $Id: device.c 1.136 2006/08/26 14:11:03 kls Exp $
  */
 
 #include "device.h"
@@ -281,19 +281,26 @@
 cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
 {
   cDevice *d = NULL;
-  uint Impact = 0xFFFFFFFF;
+  uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
   for (int i = 0; i < numDevices; i++) {
       bool ndr;
       if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
+         // Put together an integer number that reflects the "impact" using
+         // this device would have on the overall system. Each condition is represented
+         // by one bit in the number (or several bits, if the condition is actually
+         // a numeric value). The sequence in which the conditions are listed corresponds
+         // to their individual severity, where the one listed first will make the most
+         // difference, because it results in the most significant bit of the result.
          uint imp = 0;
-         imp <<= 1; imp |= !device[i]->Receiving() || ndr;
-         imp <<= 1; imp |= device[i]->Receiving();
-         imp <<= 1; imp |= device[i] == ActualDevice();
-         imp <<= 1; imp |= device[i]->IsPrimaryDevice();
-         imp <<= 1; imp |= device[i]->HasDecoder();
-         imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF);
-         imp <<= 8; imp |= min(max(device[i]->ProvidesCa(Channel), 0), 0xFF);
+         imp <<= 1; imp |= !device[i]->Receiving() || ndr;                         // use receiving devices if we don't need to detach existing receivers
+         imp <<= 1; imp |= device[i]->Receiving();                                 // avoid devices that are receiving
+         imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice();        // avoid the Transfer Mode receiver device
+         imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF); // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
+         imp <<= 8; imp |= min(max(device[i]->ProvidesCa(Channel), 0), 0xFF);      // use the device that provides the lowest number of conditional access methods
+         imp <<= 1; imp |= device[i]->IsPrimaryDevice();                           // avoid the primary device
+         imp <<= 1; imp |= device[i]->HasDecoder();                                // avoid full featured cards
          if (imp < Impact) {
+            // This device has less impact than any previous one, so we take it.
             Impact = imp;
             d = device[i];
             if (NeedsDetachReceivers)
@@ -744,12 +751,12 @@
   mute = !mute;
   //XXX why is it necessary to use different sequences???
   if (mute) {
-     SetVolume(0, mute);
+     SetVolume(0, true);
      Audios.MuteAudio(mute); // Mute external audio after analog audio
      }
   else {
      Audios.MuteAudio(mute); // Enable external audio before analog audio
-     SetVolume(0, mute);
+     SetVolume(OldVolume, true);
      }
   volume = OldVolume;
   return mute;
@@ -769,9 +776,10 @@
 
 void cDevice::SetVolume(int Volume, bool Absolute)
 {
+  int OldVolume = volume;
   volume = min(max(Absolute ? Volume : volume + Volume, 0), MAXVOLUME);
   SetVolumeDevice(volume);
-  cStatus::MsgSetVolume(volume, Absolute);
+  cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute);
   if (volume > 0) {
      mute = false;
      Audios.MuteAudio(mute);
diff -ruN vdr-1.4.1/device.h vdr-1.4.2/device.h
--- vdr-1.4.1/device.h	2006-05-28 17:04:24.000000000 +0200
+++ vdr-1.4.2/device.h	2006-06-15 11:32:48.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.h 1.78 2006/05/28 15:04:24 kls Exp $
+ * $Id: device.h 1.79 2006/06/15 09:32:48 kls Exp $
  */
 
 #ifndef __DEVICE_H
@@ -130,7 +130,8 @@
          ///< \return A pointer to the device, or NULL if the Index was invalid.
   static cDevice *GetDevice(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
          ///< Returns a device that is able to receive the given Channel at the
-         ///< given Priority.
+         ///< given Priority, with the least impact on active recordings and
+         ///< live viewing.
          ///< See ProvidesChannel() for more information on how
          ///< priorities are handled, and the meaning of NeedsDetachReceivers.
   static void Shutdown(void);
diff -ruN vdr-1.4.1/dvbdevice.c vdr-1.4.2/dvbdevice.c
--- vdr-1.4.1/dvbdevice.c	2006-06-11 11:03:55.000000000 +0200
+++ vdr-1.4.2/dvbdevice.c	2006-08-14 11:38:32.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: dvbdevice.c 1.159 2006/06/11 09:03:55 kls Exp $
+ * $Id: dvbdevice.c 1.160 2006/08/14 09:38:32 kls Exp $
  */
 
 #include "dvbdevice.h"
@@ -853,11 +853,6 @@
         esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1);
         return false;
         }
-     //XXX quick workaround for additional live audio PIDs:
-     if (ciHandler) {
-        ciHandler->SetPid(Channel->Apid(1), true);
-        ciHandler->SetPid(Channel->Dpid(0), true);
-        }
      if (IsPrimaryDevice())
         AddPid(Channel->Tpid(), ptTeletext);
      CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true)); // actually one would expect 'false' here, but according to Marco Schlüßler <marco@lordzodiac.de> this works
@@ -927,8 +922,14 @@
      if (IS_AUDIO_TRACK(Type) || (IS_DOLBY_TRACK(Type) && SetAudioBypass(true))) {
         if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) {
            DetachAll(pidHandles[ptAudio].pid);
+           if (ciHandler)
+              ciHandler->SetPid(pidHandles[ptAudio].pid, false);
            pidHandles[ptAudio].pid = TrackId->id;
            SetPid(&pidHandles[ptAudio], ptAudio, true);
+           if (ciHandler) {
+              ciHandler->SetPid(pidHandles[ptAudio].pid, true);
+              ciHandler->StartDecrypting();
+              }
            }
         }
      else if (IS_DOLBY_TRACK(Type)) {
diff -ruN vdr-1.4.1/eit.c vdr-1.4.2/eit.c
--- vdr-1.4.1/eit.c	2006-05-25 16:35:19.000000000 +0200
+++ vdr-1.4.2/eit.c	2006-08-05 12:01:21.000000000 +0200
@@ -8,7 +8,7 @@
  * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
  * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
  *
- * $Id: eit.c 1.118 2006/05/25 14:35:19 kls Exp $
+ * $Id: eit.c 1.120 2006/08/05 10:01:21 kls Exp $
  */
 
 #include "eit.h"
@@ -94,6 +94,8 @@
          pEvent->SetStartTime(SiEitEvent.getStartTime());
          pEvent->SetDuration(SiEitEvent.getDuration());
          }
+      if (newEvent)
+         pSchedule->AddEvent(newEvent);
       if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
          if (SiEitEvent.getRunningStatus() >= SI::RunningStatusNotRunning)
             pSchedule->SetRunningStatus(pEvent, SiEitEvent.getRunningStatus(), channel);
@@ -240,9 +242,6 @@
       delete ExtendedEventDescriptors;
       delete ShortEventDescriptor;
 
-      if (newEvent)
-         pSchedule->AddEvent(newEvent);
-
       pEvent->SetComponents(Components);
 
       pEvent->FixEpgBugs();
@@ -253,10 +252,10 @@
   if (Empty && Tid == 0x4E && getSectionNumber() == 0)
      // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
      pSchedule->ClrRunningStatus(channel);
-  if (OnlyRunningStatus)
-     return;
   if (Tid == 0x4E)
      pSchedule->SetPresentSeen();
+  if (OnlyRunningStatus)
+     return;
   if (Modified) {
      pSchedule->Sort();
      if (!HasExternalData)
diff -ruN vdr-1.4.1/epg.c vdr-1.4.2/epg.c
--- vdr-1.4.1/epg.c	2006-05-25 16:55:36.000000000 +0200
+++ vdr-1.4.2/epg.c	2006-08-05 12:04:17.000000000 +0200
@@ -7,7 +7,7 @@
  * Original version (as used in VDR before 1.3.0) written by
  * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
  *
- * $Id: epg.c 1.75 2006/05/25 14:55:36 kls Exp $
+ * $Id: epg.c 1.79 2006/08/05 10:04:17 kls Exp $
  */
 
 #include "epg.h"
@@ -435,18 +435,6 @@
 
 void cEvent::FixEpgBugs(void)
 {
-  // VDR can't usefully handle newline characters in the title and shortText of EPG
-  // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel):
-  strreplace(title, '\n', ' ');
-  strreplace(shortText, '\n', ' ');
-  // Same for control characters:
-  strreplace(title, '\x86', ' ');
-  strreplace(title, '\x87', ' ');
-  strreplace(shortText, '\x86', ' ');
-  strreplace(shortText, '\x87', ' ');
-  strreplace(description, '\x86', ' ');
-  strreplace(description, '\x87', ' ');
-
   if (isempty(title)) {
      // we don't want any "(null)" titles
      title = strcpyrealloc(title, tr("No title"));
@@ -454,7 +442,7 @@
      }
 
   if (Setup.EPGBugfixLevel == 0)
-     return;
+     goto Final;
 
   // Some TV stations apparently have their own idea about how to fill in the
   // EPG data. Let's fix their bugs as good as we can:
@@ -528,7 +516,7 @@
      }
 
   if (Setup.EPGBugfixLevel <= 1)
-     return;
+     goto Final;
 
   // Some channels apparently try to do some formatting in the texts,
   // which is a bad idea because they have no way of knowing the width
@@ -574,7 +562,7 @@
   strreplace(description, '`', '\'');
 
   if (Setup.EPGBugfixLevel <= 2)
-     return;
+     goto Final;
 
   // The stream components have a "description" field which some channels
   // apparently have no idea of how to set correctly:
@@ -638,6 +626,20 @@
            }
          }
      }
+
+Final:
+
+  // VDR can't usefully handle newline characters in the title and shortText of EPG
+  // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel):
+  strreplace(title, '\n', ' ');
+  strreplace(shortText, '\n', ' ');
+  // Same for control characters:
+  strreplace(title, '\x86', ' ');
+  strreplace(title, '\x87', ' ');
+  strreplace(shortText, '\x86', ' ');
+  strreplace(shortText, '\x87', ' ');
+  strreplace(description, '\x86', ' ');
+  strreplace(description, '\x87', ' ');
 }
 
 // --- cSchedule -------------------------------------------------------------
@@ -645,7 +647,7 @@
 cSchedule::cSchedule(tChannelID ChannelID)
 {
   channelID = ChannelID;
-  hasRunning = false;;
+  hasRunning = false;
   modified = 0;
   presentSeen = 0;
 }
@@ -736,6 +738,7 @@
 
 void cSchedule::SetRunningStatus(cEvent *Event, int RunningStatus, cChannel *Channel)
 {
+  hasRunning = false;
   for (cEvent *p = events.First(); p; p = events.Next(p)) {
       if (p == Event) {
          if (p->RunningStatus() > SI::RunningStatusNotRunning || RunningStatus > SI::RunningStatusNotRunning)
@@ -743,9 +746,9 @@
          }
       else if (RunningStatus >= SI::RunningStatusPausing && p->StartTime() < Event->StartTime())
          p->SetRunningStatus(SI::RunningStatusNotRunning);
+      if (p->RunningStatus() >= SI::RunningStatusPausing)
+         hasRunning = true;
       }
-  if (RunningStatus >= SI::RunningStatusPausing)
-     hasRunning = true;
 }
 
 void cSchedule::ClrRunningStatus(cChannel *Channel)
@@ -770,6 +773,14 @@
 void cSchedule::Sort(void)
 {
   events.Sort();
+  // Make sure there are no RunningStatusUndefined before the currently running event:
+  if (hasRunning) {
+     for (cEvent *p = events.First(); p; p = events.Next(p)) {
+         if (p->RunningStatus() >= SI::RunningStatusPausing)
+            break;
+         p->SetRunningStatus(SI::RunningStatusNotRunning);
+         }
+     }
 }
 
 void cSchedule::DropOutdated(time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version)
@@ -1025,6 +1036,9 @@
   if (!p) {
      p = new cSchedule(ChannelID);
      Add(p);
+     cChannel *channel = Channels.GetByChannelID(ChannelID);
+     if (channel)
+        channel->schedule = p;
      }
   return p;
 }
diff -ruN vdr-1.4.1/menu.c vdr-1.4.2/menu.c
--- vdr-1.4.1/menu.c	2006-06-03 15:32:42.000000000 +0200
+++ vdr-1.4.2/menu.c	2006-07-23 11:23:11.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menu.c 1.441 2006/06/03 13:32:42 kls Exp $
+ * $Id: menu.c 1.443 2006/07/23 09:23:11 kls Exp $
  */
 
 #include "menu.h"
@@ -39,7 +39,7 @@
 #define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS)
 #define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
 #define MAXWAITFORCAMMENU 4 // seconds to wait for the CAM menu to open
-#define MINFREEDISK       300 // minimum free disk space required to start recording
+#define MINFREEDISK       300 // minimum free disk space (in MB) required to start recording
 #define NODISKSPACEDELTA  300 // seconds between "Not enough disk space to start recording!" messages
 
 #define CHNUMWIDTH  (numdigits(Channels.MaxNumber()) + 1)
@@ -3146,6 +3146,7 @@
             return osEnd;
             }
     case k1 ... k9:
+         group = -1;
          if (number >= 0) {
             if (number > Channels.MaxNumber())
                number = Key - k0;
diff -ruN vdr-1.4.1/menuitems.c vdr-1.4.2/menuitems.c
--- vdr-1.4.1/menuitems.c	2006-06-03 15:20:01.000000000 +0200
+++ vdr-1.4.2/menuitems.c	2006-07-30 11:09:30.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: menuitems.c 1.45 2006/06/03 13:20:01 kls Exp $
+ * $Id: menuitems.c 1.47 2006/07/30 09:09:30 kls Exp $
  */
 
 #include "menuitems.h"
@@ -75,6 +75,7 @@
 
   if (state == osUnknown) {
      int newValue = *value;
+     bool IsRepeat = Key & k_Repeat;
      Key = NORMALKEY(Key);
      switch (Key) {
        case kNone: break;
@@ -88,10 +89,14 @@
        case kLeft: // TODO might want to increase the delta if repeated quickly?
             newValue = *value - 1;
             fresh = true;
+            if (!IsRepeat && newValue < min && max != INT_MAX)
+               newValue = max;
             break;
        case kRight:
             newValue = *value + 1;
             fresh = true;
+            if (!IsRepeat && newValue > max && min != INT_MIN)
+               newValue = min;
             break;
        default:
             if (*value < min) { *value = min; Set(); }
@@ -308,7 +313,7 @@
         SetValue(buf);
         return;
         }
-     width -= font->Width('>'); // assuming '<' and '>' have the same with
+     width -= font->Width('>'); // assuming '<' and '>' have the same width
      int w = 0;
      int i = 0;
      int l = strlen(buf);
@@ -390,6 +395,8 @@
                     if (strlen(value) > 1) {
                        if (!insert || pos < int(strlen(value)) - 1)
                           memmove(value + pos, value + pos + 1, strlen(value) - pos);
+                       else if (insert && pos == int(strlen(value)) - 1)
+                          value[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position
                        // reduce position, if we removed the last character
                        if (pos == int(strlen(value)))
                           pos--;
diff -ruN vdr-1.4.1/newplugin vdr-1.4.2/newplugin
--- vdr-1.4.1/newplugin	2006-04-24 19:18:41.000000000 +0200
+++ vdr-1.4.2/newplugin	2006-06-24 11:15:17.000000000 +0200
@@ -12,7 +12,7 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: newplugin 1.28 2006/04/24 17:18:41 kls Exp $
+# $Id: newplugin 1.29 2006/06/24 09:15:17 kls Exp $
 
 $PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
 
@@ -61,6 +61,8 @@
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
 # By default the main source file also carries this name.
+# IPORTANT: the presence of this macro is important for the Make.config
+# file. So it must be defined, even if it is not used here!
 #
 PLUGIN = $PLUGIN_NAME
 
diff -ruN vdr-1.4.1/plugin.c vdr-1.4.2/plugin.c
--- vdr-1.4.1/plugin.c	2006-04-17 11:20:05.000000000 +0200
+++ vdr-1.4.2/plugin.c	2006-08-13 10:51:44.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: plugin.c 1.22 2006/04/17 09:20:05 kls Exp $
+ * $Id: plugin.c 1.23 2006/08/13 08:51:44 kls Exp $
  */
 
 #include "plugin.h"
@@ -15,6 +15,7 @@
 #include <time.h>
 #include "config.h"
 #include "interface.h"
+#include "thread.h"
 
 #define LIBVDR_PREFIX  "libvdr-"
 #define SO_INDICATOR   ".so."
@@ -137,6 +138,8 @@
 const char *cPlugin::ConfigDirectory(const char *PluginName)
 {
   static char *buffer = NULL;
+  if (!cThread::IsMainThread())
+     esyslog("ERROR: plugin '%s' called cPlugin::ConfigDirectory(), which is not thread safe!", PluginName ? PluginName : "<no name given>");
   free(buffer);
   asprintf(&buffer, "%s/plugins%s%s", configDirectory, PluginName ? "/" : "", PluginName ? PluginName : "");
   return MakeDirs(buffer, true) ? buffer : NULL;
diff -ruN vdr-1.4.1/rcu.c vdr-1.4.2/rcu.c
--- vdr-1.4.1/rcu.c	2006-06-11 11:08:52.000000000 +0200
+++ vdr-1.4.2/rcu.c	2006-06-16 11:29:24.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: rcu.c 1.13 2006/01/08 11:40:09 kls Exp $
+ * $Id: rcu.c 1.14 2006/06/16 09:29:24 kls Exp $
  */
 
 #include "rcu.h"
@@ -13,8 +13,9 @@
 #include <unistd.h>
 #include "tools.h"
 
-#define REPEATLIMIT  20 // ms
-#define REPEATDELAY 350 // ms
+#define REPEATLIMIT      150 // ms
+#define REPEATDELAY      350 // ms
+#define HANDSHAKETIMEOUT  20 // ms
 
 cRcuRemote::cRcuRemote(const char *DeviceName)
 :cRemote("RCU")
@@ -96,7 +97,7 @@
   time_t LastCodeRefresh = 0;
   cTimeMs FirstTime;
   unsigned char LastCode = 0, LastMode = 0;
-  uint64 LastCommand = 0;
+  uint64 LastCommand = ~0; // 0x00 might be a valid command
   unsigned int LastData = 0;
   bool repeat = false;
 
@@ -136,7 +137,7 @@
         else if (repeat) { // the last one was a repeat, so let's generate a release
            Put(LastCommand, false, true);
            repeat = false;
-           LastCommand = 0;
+           LastCommand = ~0;
            }
         else {
            unsigned int d = data;
@@ -154,9 +155,9 @@
               SendCommand(m);
               LastMode = m;
               }
-           LastCommand = 0;
+           LastCommand = ~0;
            }
-        if (code && time(NULL) - LastCodeRefresh > 60) {
+        if (!repeat && code && time(NULL) - LastCodeRefresh > 60) {
            SendCommand(code); // in case the PIC listens to the wrong code
            LastCodeRefresh = time(NULL);
            }
@@ -181,7 +182,7 @@
   if (f >= 0) {
      int w = write(f, &c, 1);
      if (w == 1) {
-        for (int reply = ReceiveByte(REPEATLIMIT); reply >= 0;) {
+        for (int reply = ReceiveByte(HANDSHAKETIMEOUT); reply >= 0;) {
             if (reply == c)
                return true;
             else if (reply == 'X') {
diff -ruN vdr-1.4.1/recording.c vdr-1.4.2/recording.c
--- vdr-1.4.1/recording.c	2006-04-29 15:22:20.000000000 +0200
+++ vdr-1.4.2/recording.c	2006-07-30 12:23:46.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: recording.c 1.148 2006/04/29 13:22:20 kls Exp $
+ * $Id: recording.c 1.149 2006/07/30 10:23:46 kls Exp $
  */
 
 #include "recording.h"
@@ -970,7 +970,7 @@
   return NULL;
 }
 
-void cRecordings::AddByName(const char *FileName)
+void cRecordings::AddByName(const char *FileName, bool TriggerUpdate)
 {
   LOCK_THREAD;
   cRecording *recording = GetByName(FileName);
@@ -978,7 +978,8 @@
      recording = new cRecording(FileName);
      Add(recording);
      ChangeState();
-     TouchUpdate();
+     if (TriggerUpdate)
+        TouchUpdate();
      }
 }
 
diff -ruN vdr-1.4.1/recording.h vdr-1.4.2/recording.h
--- vdr-1.4.1/recording.h	2006-04-09 15:47:11.000000000 +0200
+++ vdr-1.4.2/recording.h	2006-07-30 12:24:07.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: recording.h 1.54 2006/04/09 13:47:11 kls Exp $
+ * $Id: recording.h 1.55 2006/07/30 10:24:07 kls Exp $
  */
 
 #ifndef __RECORDING_H
@@ -133,7 +133,7 @@
   bool StateChanged(int &State);
   void ResetResume(const char *ResumeFileName = NULL);
   cRecording *GetByName(const char *FileName);
-  void AddByName(const char *FileName);
+  void AddByName(const char *FileName, bool TriggerUpdate = true);
   void DelByName(const char *FileName);
   int TotalFileSizeMB(void); ///< Only for deleted recordings!
   };
diff -ruN vdr-1.4.1/ringbuffer.c vdr-1.4.2/ringbuffer.c
--- vdr-1.4.1/ringbuffer.c	2005-12-30 16:42:08.000000000 +0100
+++ vdr-1.4.2/ringbuffer.c	2006-06-16 11:32:13.000000000 +0200
@@ -7,7 +7,7 @@
  * Parts of this file were inspired by the 'ringbuffy.c' from the
  * LinuxDVB driver (see linuxtv.org).
  *
- * $Id: ringbuffer.c 1.23 2005/12/30 15:42:08 kls Exp $
+ * $Id: ringbuffer.c 1.24 2006/06/16 09:32:13 kls Exp $
  */
 
 #include "ringbuffer.h"
@@ -156,6 +156,7 @@
 {
   description = Description ? strdup(Description) : NULL;
   tail = head = margin = Margin;
+  gotten = 0;
   buffer = NULL;
   if (Size > 1) { // 'Size - 1' must not be 0!
      if (Margin <= Size / 2) {
diff -ruN vdr-1.4.1/sources.conf vdr-1.4.2/sources.conf
--- vdr-1.4.1/sources.conf	2006-05-01 11:34:18.000000000 +0200
+++ vdr-1.4.2/sources.conf	2006-06-15 12:02:28.000000000 +0200
@@ -22,7 +22,7 @@
 S5E     Sirius 2/3
 S7E     Eutelsat W3A
 S10E    Eutelsat W1
-S13E    Hotbird 1-(5)-6
+S13E    Hotbird 1-3/6/7A
 S16E    Eutelsat W2
 S19.2E  Astra 1B/C/E/F/G/H/2C
 S21.0E  Afristar 1
diff -ruN vdr-1.4.1/svdrp.c vdr-1.4.2/svdrp.c
--- vdr-1.4.1/svdrp.c	2006-06-11 11:04:36.000000000 +0200
+++ vdr-1.4.2/svdrp.c	2006-08-12 11:09:55.000000000 +0200
@@ -10,7 +10,7 @@
  * and interact with the Video Disk Recorder - or write a full featured
  * graphical interface that sits on top of an SVDRP connection.
  *
- * $Id: svdrp.c 1.97 2006/06/11 09:04:36 kls Exp $
+ * $Id: svdrp.c 1.100 2006/08/12 09:09:55 kls Exp $
  */
 
 #include "svdrp.h"
@@ -120,7 +120,7 @@
            close(newsock);
            newsock = -1;
            }
-        isyslog("connect from %s, port %hd - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
+        isyslog("connect from %s, port %hu - %s", inet_ntoa(clientname.sin_addr), ntohs(clientname.sin_port), accepted ? "accepted" : "DENIED");
         }
      else if (errno != EINTR && errno != EAGAIN)
         LOG_ERROR;
@@ -378,17 +378,19 @@
 
 cSVDRP::~cSVDRP()
 {
-  Close();
+  Close(true);
   free(cmdLine);
 }
 
-void cSVDRP::Close(bool Timeout)
+void cSVDRP::Close(bool SendReply, bool Timeout)
 {
   if (file.IsOpen()) {
-     //TODO how can we get the *full* hostname?
-     char buffer[BUFSIZ];
-     gethostname(buffer, sizeof(buffer));
-     Reply(221, "%s closing connection%s", buffer, Timeout ? " (timeout)" : "");
+     if (SendReply) {
+        //TODO how can we get the *full* hostname?
+        char buffer[BUFSIZ];
+        gethostname(buffer, sizeof(buffer));
+        Reply(221, "%s closing connection%s", buffer, Timeout ? " (timeout)" : "");
+        }
      isyslog("closing SVDRP connection"); //TODO store IP#???
      file.Close();
      DELETENULL(PUTEhandler);
@@ -401,7 +403,7 @@
      length = strlen(s);
   if (safe_write(file, s, length) < 0) {
      LOG_ERROR;
-     file.Close();
+     Close();
      return false;
      }
   return true;
@@ -423,10 +425,8 @@
                  cont = '-';
               char number[16];
               sprintf(number, "%03d%c", abs(Code), cont);
-              if (!(Send(number) && Send(s, n ? n - s : -1) && Send("\r\n"))) {
-                 Close();
+              if (!(Send(number) && Send(s, n ? n - s : -1) && Send("\r\n")))
                  break;
-                 }
               s = n ? n + 1 : NULL;
               }
         free(buffer);
@@ -1530,7 +1530,7 @@
   else if (CMD("STAT"))  CmdSTAT(s);
   else if (CMD("UPDT"))  CmdUPDT(s);
   else if (CMD("VOLU"))  CmdVOLU(s);
-  else if (CMD("QUIT"))  Close();
+  else if (CMD("QUIT"))  Close(true);
   else                   Reply(500, "Command unrecognized: \"%s\"", Cmd);
 }
 
@@ -1570,7 +1570,7 @@
                  }
               else if (c == 0x04 && numChars == 0) {
                  // end of file (only at beginning of line)
-                 Close();
+                 Close(true);
                  }
               else if (c == 0x08 || c == 0x7F) {
                  // backspace or delete (last character)
@@ -1590,16 +1590,14 @@
                  }
               lastActivity = time(NULL);
               }
-           else if (r < 0) {
+           else if (r <= 0) {
               isyslog("lost connection to SVDRP client");
               Close();
               }
-           else
-              break;
            }
      if (Setup.SVDRPTimeout && time(NULL) - lastActivity > Setup.SVDRPTimeout) {
         isyslog("timeout on SVDRP connection");
-        Close(true);
+        Close(true, true);
         }
      return true;
      }
diff -ruN vdr-1.4.1/svdrp.h vdr-1.4.2/svdrp.h
--- vdr-1.4.1/svdrp.h	2005-12-30 15:46:38.000000000 +0100
+++ vdr-1.4.2/svdrp.h	2006-08-06 10:51:09.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: svdrp.h 1.27 2005/12/30 14:46:38 kls Exp $
+ * $Id: svdrp.h 1.28 2006/08/06 08:51:09 kls Exp $
  */
 
 #ifndef __SVDRP_H
@@ -50,7 +50,7 @@
   char *cmdLine;
   time_t lastActivity;
   static char *grabImageDir;
-  void Close(bool Timeout = false);
+  void Close(bool SendReply = false, bool Timeout = false);
   bool Send(const char *s, int length = -1);
   void Reply(int Code, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
   void PrintHelpTopics(const char **hp);
diff -ruN vdr-1.4.1/thread.c vdr-1.4.2/thread.c
--- vdr-1.4.1/thread.c	2006-06-02 15:51:39.000000000 +0200
+++ vdr-1.4.2/thread.c	2006-08-20 12:20:44.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: thread.c 1.55 2006/06/02 13:51:39 kls Exp $
+ * $Id: thread.c 1.57 2006/08/20 10:20:44 kls Exp $
  */
 
 #include "thread.h"
@@ -316,11 +316,9 @@
   return emergencyExitRequested = true; // yes, it's an assignment, not a comparison!
 }
 
-_syscall0(pid_t, gettid)
-
 tThreadId cThread::ThreadId(void)
 {
-  return gettid();
+  return syscall(__NR_gettid);
 }
 
 void cThread::SetMainThreadId(void)
@@ -423,7 +421,6 @@
         iopipe = 1;
         }
      close(fd[iopipe]);
-     f = fdopen(fd[1 - iopipe], mode);
      if ((f = fdopen(fd[1 - iopipe], mode)) == NULL) {
         LOG_ERROR;
         close(fd[1 - iopipe]);
diff -ruN vdr-1.4.1/timers.c vdr-1.4.2/timers.c
--- vdr-1.4.1/timers.c	2006-05-25 16:36:37.000000000 +0200
+++ vdr-1.4.2/timers.c	2006-08-05 14:03:36.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: timers.c 1.61 2006/05/25 14:36:37 kls Exp $
+ * $Id: timers.c 1.62 2006/08/05 12:03:36 kls Exp $
  */
 
 #include "timers.h"
@@ -351,7 +351,7 @@
          if (DayMatches(t0)) {
             time_t a = SetTime(t0, begin);
             time_t b = a + length;
-            if ((!day || a >= day) && t <= b) {
+            if ((!day || a >= day) && t < b) {
                startTime = a;
                stopTime = b;
                break;
@@ -647,6 +647,7 @@
 {
   cTimer *t0 = NULL;
   for (cTimer *ti = First(); ti; ti = Next(ti)) {
+      ti->Matches();
       if ((ti->HasFlags(tfActive)) && (!t0 || ti->StopTime() > time(NULL) && ti->Compare(*t0) < 0))
          t0 = ti;
       }
diff -ruN vdr-1.4.1/tools.c vdr-1.4.2/tools.c
--- vdr-1.4.1/tools.c	2006-05-26 12:10:31.000000000 +0200
+++ vdr-1.4.2/tools.c	2006-08-12 15:30:07.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: tools.c 1.118 2006/05/26 10:10:31 kls Exp $
+ * $Id: tools.c 1.120 2006/08/12 13:30:07 kls Exp $
  */
 
 #include "tools.h"
@@ -422,8 +422,7 @@
                  }
               else {
                  LOG_ERROR_STR(buffer);
-                 free(buffer);
-                 return false;
+                 empty = false;
                  }
               free(buffer);
               }
@@ -480,22 +479,16 @@
 
 char *ReadLink(const char *FileName)
 {
-  char RealName[PATH_MAX];
-  const char *TargetName = NULL;
-  int n = readlink(FileName, RealName, sizeof(RealName) - 1);
-  if (n < 0) {
-     if (errno == ENOENT || errno == EINVAL) // file doesn't exist or is not a symlink
-        TargetName = FileName;
+  if (!FileName)
+     return NULL;
+  char *TargetName = canonicalize_file_name(FileName);
+  if (!TargetName) {
+     if (errno == ENOENT) // file doesn't exist
+        TargetName = strdup(FileName);
      else // some other error occurred
         LOG_ERROR_STR(FileName);
      }
-  else if (n < int(sizeof(RealName))) { // got it!
-     RealName[n] = 0;
-     TargetName = RealName;
-     }
-  else
-     esyslog("ERROR: symlink's target name too long: %s", FileName);
-  return TargetName ? strdup(TargetName) : NULL;
+  return TargetName;
 }
 
 bool SpinUpDisk(const char *FileName)
diff -ruN vdr-1.4.1/vdr.1 vdr-1.4.2/vdr.1
--- vdr-1.4.1/vdr.1	2006-04-30 10:55:12.000000000 +0200
+++ vdr-1.4.2/vdr.1	2006-06-24 12:07:16.000000000 +0200
@@ -8,7 +8,7 @@
 .\" License as specified in the file COPYING that comes with the
 .\" vdr distribution.
 .\"
-.\" $Id: vdr.1 1.25 2006/04/30 08:55:12 kls Exp $
+.\" $Id: vdr.1 1.26 2006/06/24 10:07:16 kls Exp $
 .\"
 .TH vdr 1 "30 Apr 2006" "1.4.0" "Video Disk Recorder"
 .SH NAME
@@ -137,6 +137,10 @@
 vdr can switch to a lesser privileged user id during normal
 operation.
 .TP
+.BI \-\-vfat
+Encode special characters in recording names to avoid problems
+with VFAT file systems.
+.TP
 .BI \-v\  dir ,\ \-\-video= dir
 Use \fIdir\fR as video directory.
 The default is \fI/video\fR.
diff -ruN vdr-1.4.1/vdr.c vdr-1.4.2/vdr.c
--- vdr-1.4.1/vdr.c	2006-06-04 11:04:47.000000000 +0200
+++ vdr-1.4.2/vdr.c	2006-08-05 12:46:38.000000000 +0200
@@ -22,7 +22,7 @@
  *
  * The project's page is at http://www.cadsoft.de/vdr
  *
- * $Id: vdr.c 1.274 2006/06/04 09:04:47 kls Exp $
+ * $Id: vdr.c 1.278 2006/08/05 10:46:38 kls Exp $
  */
 
 #include <getopt.h>
@@ -47,6 +47,7 @@
 #include "i18n.h"
 #include "interface.h"
 #include "keys.h"
+#include "libsi/si.h"
 #include "lirc.h"
 #include "menu.h"
 #include "osdbase.h"
@@ -773,15 +774,20 @@
                   bool NeedsTransponder = false;
                   if (Timer->HasFlags(tfActive) && !Timer->Recording()) {
                      if (Timer->HasFlags(tfVps)) {
-                        if (Timer->Matches(Now, true, Setup.VpsMargin))
+                        if (Timer->Matches(Now, true, Setup.VpsMargin)) {
                            InVpsMargin = true;
-                        else if (Timer->Event())
+                           Timer->SetInVpsMargin(InVpsMargin);
+                           }
+                        else if (Timer->Event()) {
+                           InVpsMargin = Timer->Event()->StartTime() <= Now && Timer->Event()->RunningStatus() == SI::RunningStatusUndefined;
                            NeedsTransponder = Timer->Event()->StartTime() - Now < VPSLOOKAHEADTIME * 3600 && !Timer->Event()->SeenWithin(VPSUPTODATETIME);
+                           }
                         else {
                            cSchedulesLock SchedulesLock;
                            const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
                            if (Schedules) {
                               const cSchedule *Schedule = Schedules->GetSchedule(Timer->Channel());
+                              InVpsMargin = !Schedule; // we must make sure we have the schedule
                               NeedsTransponder = Schedule && !Schedule->PresentSeenWithin(VPSUPTODATETIME);
                               }
                            }
@@ -790,10 +796,10 @@
                      else
                         NeedsTransponder = Timer->Matches(Now, true, TIMERLOOKAHEADTIME);
                      }
-                  Timer->SetInVpsMargin(InVpsMargin);
                   if (NeedsTransponder || InVpsMargin) {
                      // Find a device that provides the required transponder:
                      cDevice *Device = NULL;
+                     bool DeviceAvailable = false;
                      for (int i = 0; i < cDevice::NumDevices(); i++) {
                          cDevice *d = cDevice::GetDevice(i);
                          if (d && d->ProvidesTransponder(Timer->Channel())) {
@@ -802,18 +808,17 @@
                                Device = d;
                                break;
                                }
-                            else if (Now - DeviceUsed[d->DeviceNumber()] > TIMERDEVICETIMEOUT) {
-                               // only check other devices if they have been left alone for a while
-                               if (d->MaySwitchTransponder())
-                                  // this one can be switched without disturbing anything else
-                                  Device = d;
-                               else if (!Device && InVpsMargin && !d->Receiving() && d->ProvidesTransponderExclusively(Timer->Channel()))
-                                  // use this one only if no other with less impact can be found
-                                  Device = d;
+                            bool timeout = Now - DeviceUsed[d->DeviceNumber()] > TIMERDEVICETIMEOUT; // only check other devices if they have been left alone for a while
+                            if (d->MaySwitchTransponder()) {
+                               DeviceAvailable = true; // avoids using the actual device below
+                               if (timeout)
+                                  Device = d; // only check other devices if they have been left alone for a while
                                }
+                            else if (timeout && !Device && InVpsMargin && !d->Receiving() && d->ProvidesTransponderExclusively(Timer->Channel()))
+                               Device = d; // use this one only if no other with less impact can be found
                             }
                          }
-                     if (!Device && InVpsMargin) {
+                     if (!Device && InVpsMargin && !DeviceAvailable) {
                         cDevice *d = cDevice::ActualDevice();
                         if (!d->Receiving() && d->ProvidesTransponder(Timer->Channel()) && Now - DeviceUsed[d->DeviceNumber()] > TIMERDEVICETIMEOUT)
                            Device = d; // use the actual device as a last resort
@@ -1010,16 +1015,18 @@
                   }
                if (cPluginManager::Active(tr("shut down anyway?")))
                   break;
-               cTimer *timer = Timers.GetNextActiveTimer();
-               time_t Next  = timer ? timer->StartTime() : 0;
-               time_t Delta = timer ? Next - time(NULL) : 0;
-               if (Next && Delta <= Setup.MinEventTimeout * 60) {
-                  char *buf;
-                  asprintf(&buf, tr("Recording in %ld minutes, shut down anyway?"), Delta / 60);
-                  bool confirm = Interface->Confirm(buf);
-                  free(buf);
-                  if (!confirm)
-                     break;
+               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;
                break;
@@ -1161,6 +1168,12 @@
                     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 (!Next || Delta > Setup.MinEventTimeout * 60 || ForceShutdown) {
                     ForceShutdown = false;
                     if (timer)
