diff -ruN vdr-1.3.25/CONTRIBUTORS vdr-1.3.26/CONTRIBUTORS
--- vdr-1.3.25/CONTRIBUTORS	2005-05-29 13:44:52.000000000 +0200
+++ vdr-1.3.26/CONTRIBUTORS	2005-06-12 12:02:59.000000000 +0200
@@ -283,6 +283,7 @@
  for pointing out that MAXDPIDS needs to be to 16 (8xAC3 + 8xDTS)
  for reporting a problem with ensuring there is a current audio track in case there
  is only one track
+ for enabling a device to detach all receivers for a given PID
 
 Rolf Hakenes <hakenes@hippomi.de>
  for providing 'libdtv' and adapting the EIT mechanisms to it
@@ -713,6 +714,7 @@
  for reporting a compiler warning in g++ 3.2.3 regarding cReplayControl::Show()
  for reporting and helping to debug a problem in frequency handling when setting
  the CA descriptors in cDvbTuner::Action()
+ for suggesting to add the year to recording dates in LSTR
 
 Marcel Wiesweg <marcel.wiesweg@gmx.de>
  for pointing out a problem with high CPU load during replay
@@ -828,6 +830,7 @@
  for reporting a problem in handling the '-E' options in version 1.3.18
  for reporting a problem in case a station defines all 32 audio PIDs
  for suggestions and experiments regarding the buffer reserve in cTransfer
+ for reporting a problem with 'summary.vdr' files with more than two empty lines
 
 Andreas Mair <Andreas.Mair@linogate.com>
  for reporting a short display of the main menu if a plugin displays its own OSD and
@@ -880,6 +883,7 @@
  for translating OSD texts to the Finnish language
  for fixing internationalization of the text for "Setup/DVB/Audio language(s)"
  for making pressing the Power button not stop Transfer Mode or replay immediately
+ for making EPG events without a title display "No title" instead of "(null)"
 
 Ralf Klueber <ralf.klueber@vodafone.com>
  for reporting a bug in cutting a recording if there is only a single editing mark
@@ -954,6 +958,9 @@
  for fixing a typo in detecting UTF-8
  for fixing handling fragments of less than 4 byte in cPesAssembler
  for some rearrangements in cDvbPlayer::Action() to avoid lockups on NPTL systems
+ for implementing cVideoRepacker in remux.c to make sure every PES packet contains
+ only data from one frame
+ for fixing the call to Channels.Unlock() in cEITScanner::Process()
 
 Richard Robson <richard_robson@beeb.net>
  for reporting freezing replay if a timer starts while in Transfer Mode from the
@@ -1186,6 +1193,7 @@
  level from being set to a wrong value
  for fixing a possible hangup when ending a replay session while cIndexFile::CatchUp()
  is waiting
+ for improving resetting CAM connections
 
 Jürgen Schmitz <j.schmitz@web.de>
  for reporting a bug in displaying the current channel when switching via the SVDRP
@@ -1231,6 +1239,8 @@
 Udo Richter <udo_richter@gmx.de>
  for refining the formula for making volume control more linear
  for fixing handling lifetime when deciding whether to delete a recording
+ for reporting a problem in handling page up/down in menu lists in case there are
+ several non selectable items in a row
 
 Sven Kreiensen <svenk@kammer.uni-hannover.de>
  for his help in keeping 'channels.conf.terr' up to date
@@ -1311,6 +1321,7 @@
  for removing some unneeded code and fixing access to unallocated memory in
  cEvent::FixEpgBugs()
  for adding a missing cMutexLock to cRemote::HasKeys()
+ for removing an unnecessary #include from osd.c
 
 Chad Flynt <hoochster@sofnet.com>
  for suggestions and experiments regarding the buffer reserve in cTransfer
@@ -1318,6 +1329,8 @@
 Chris Warren <dvb@ixalon.net>
  for pointing out that the call to system("sync") in SpinUpDisk() should be
  replaced with fsync(f) to avoid problems on NPTL systems
+ for fixing dropping EPG events that have a zero start time or duration, in case it's
+ an NVOD event
 
 Luca Olivetti <luca@ventoso.org>
  for making cDevice::AttachPlayer() keep the track language codes and descriptions
@@ -1367,3 +1380,7 @@
  for avoiding unnecessary calls to getLength() in libsi/si.c, and avoiding the
  '& 0xff' in CRC32::crc32() of libsi/util.c
  for suggesting to reduce the priority of the section handler threads
+
+Henrik Niehaus <henrik.niehaus@gmx.de>
+ for reporting a problem with timers with a day given as MTWTF--@6, i.e. a repeating
+ timer with first day not as full date, but just day of month
diff -ruN vdr-1.3.25/HISTORY vdr-1.3.26/HISTORY
--- vdr-1.3.25/HISTORY	2005-05-29 13:44:26.000000000 +0200
+++ vdr-1.3.26/HISTORY	2005-06-12 16:16:12.000000000 +0200
@@ -3577,3 +3577,38 @@
   to Stefan Huelswitt for pointing this out).
 - Added cThread::SetPriority() and using it in cSectionHandler::Action() to
   reduce the priority of the section handler threads (as suggested by Georg Acher).
+
+2005-06-12: Version 1.3.26
+
+- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
+- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
+- Fixed handling 'summary.vdr' files with more than two empty lines (thanks to
+  Christian Jacobsen for reporting this one).
+- Improved resetting CAM connections (thanks to Marco Schlüßler).
+- Implemented cVideoRepacker in remux.c to make sure every PES packet contains
+  only data from one frame (thanks to Reinhard Nissl).
+  NOTE: currently this doesn't work with MPEG1, so if you use MPEG1 you may want
+  to change line 1158 in remux.c to
+
+  ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS);
+
+  as it was before.
+- EPG events without a title now display "No title" instead of "(null)" (thanks
+  to Rolf Ahrenberg).
+- A device can now detach all receivers for a given PID, as is necessary, e.g.,
+  for the bitstreamout plugin (thanks to Werner Fink).
+- Added the year (two digits) to recording dates in LSTR, and thus also in menus
+  (suggested by Jan Ekholm).
+- Fixed the call to Channels.Unlock() in cEITScanner::Process() (thanks to
+  Reinhard Nissl).
+- Fixed handling timers with a day given as MTWTF--@6, i.e. a repeating timer with
+  first day not as full date, but just day of month (thanks to Henrik Niehaus for
+  reporting this one).
+- Removed an unnecessary #include from osd.c (thanks to Wolfgang Rohdewald).
+- Fixed dropping EPG events that have a zero start time or duration, in case it's
+  an NVOD event (thanks to Chris Warren).
+- Fixed handling page up/down in menu lists in case there are several non selectable
+  items in a row (thanks to Udo Richter for reporting this one).
+- Added cOsdMenu::SetCols() to allow adjusting the menu columns.
+- Modified cEITScanner::Process() so that it works on systems with only budget cards
+  or a mix of DVB-S, DVB-C or DVB-T cards.
diff -ruN vdr-1.3.25/channels.conf vdr-1.3.26/channels.conf
--- vdr-1.3.25/channels.conf	2005-05-29 16:22:12.000000000 +0200
+++ vdr-1.3.26/channels.conf	2005-06-12 16:20:01.000000000 +0200
@@ -26,7 +26,7 @@
 DSF;BetaDigital:12480:vC34:S19.2E:27500:1023:1024=deu:0: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;BSkyB:11597:vC56:S19.2E:22000:305+131:306=eng:0:0:28707:1:1026:0
 Veronica/JETIX;CANAL+:12574:hC56:S19.2E:22000:518+8190:92=dut:38:622,100:5020:53:1109:0
@@ -45,9 +45,9 @@
 :Premiere World
 PREMIERE START,START;PREMIERE:11797:hC34:S19.2E:27500:255:256=deu:32:1702,1801,1722: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;1795=deu:32:1722,1801,1702:11: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:32:1801,1722,1702:9:133:2:0
+PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu,769=deu:32:1801,1722,1702:9:133:2:0
 PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu:32:1801,1722,1702:29:133:2:0
 PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1702,1722,1801:41:133:2:0
 PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1722,1702,1801:20:133:2:0
@@ -55,11 +55,11 @@
 :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:12070:hC34:S19.2E:27500:1023:1024=deu:32:1702,1801,1722:21:133:1:0
+BEATE-UHSE.TV,B-UHSE;PREMIERE:11758:hC34:S19.2E:27500:1791:1792=deu:32:1801,1722,1702:21:133:17:0
 DIREKT EROTIK,EROTIK;PREMIERE:12031:hC34:S19.2E:27500:1279:0:0:1722,1801,1702:513:133:4:0
 :Sportsworld
-F1-Portal:11719:hC34:S19.2E:27500:255:256=deu,257=deu:32:1702,1801,1722:17:133:3:0
-PREMIERE SPORT 2,SPORT 2;PREMIERE:12031:hC34:S19.2E:27500:3839:3840=deu,3841=deu:32:1722,1702,1801:27:133:4:0
+PREMIERE SPORT PORTAL,SPORT PORTAL;PREMIERE:11719:hC34:S19.2E:27500:255:256=deu,257=deu:32:1702,1801,1722:17:133:3:0
+.,.;PREMIERE:12031:hC34:S19.2E:27500:3839:3840=deu:32:1722,1702,1801: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
@@ -69,7 +69,7 @@
 Kabel 1 Austria;ProSiebenSat.1:12051:vC34:S19.2E:27500:166:167=deu:169:0:20004:1:1082:0
 ProSieben Schweiz;ProSiebenSat.1:12051:vC34:S19.2E:27500:289:290=deu:33:0:20001:1:1082:0
 FRANCE 5;CSAT:12207:vC34:S19.2E:27500:160:80=fra:32:500,100:8501:1:1090:0
-LCP;CSAT:12207:vC34:S19.2E:27500:2047+8191:0:0:0:8506: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
 ASTRA-Mosaic;SES ASTRA:12551:vC56:S19.2E:22000:175:176=fra:0:0:3988:1:1108:0
@@ -82,7 +82,6 @@
 Yorin;CANAL+:12574:hC56:S19.2E:22000:512+8190:84=dut:33:622,100:5010:53:1109:0
 MTV2 Pop Channel;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
-Via 1 - Schöner Reisen:12148:h:S19.2E:27500:511:512:0:0:44:0:0:0
 VIVA;VIVA Fernsehen GmbH & Co. KG:12669:vC56:S19.2E:22000:309:310=deu:311:0:12732:1:1116:0
 VIVA PLUS;VIVA Fernsehen GmbH & Co. KG:12551:vC56:S19.2E:22000:171:172=deu:173:0:12120:1:1108:0
 QVC Deutschland;QVC:12551:vC56:S19.2E:22000:165:166:167:0:12100:1:1108:0
diff -ruN vdr-1.3.25/ci.c vdr-1.3.26/ci.c
--- vdr-1.3.25/ci.c	2004-07-17 16:30:17.000000000 +0200
+++ vdr-1.3.26/ci.c	2005-06-04 13:57:05.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.23 2004/07/17 14:30:17 kls Exp $
+ * $Id: ci.c 1.24 2005/06/04 11:57:05 kls Exp $
  */
 
 #include "ci.h"
@@ -287,6 +287,7 @@
   int RecvData(void);
   const uint8_t *Data(int &Length);
   //XXX Close()
+  void Reset(void);
   };
 
 cCiTransportConnection::cCiTransportConnection(void)
@@ -428,6 +429,11 @@
   return ERROR;
 }
 
+void cCiTransportConnection::Reset(void)
+{
+  Init(-1, 0, 0);
+}
+
 // --- cCiTransportLayer -----------------------------------------------------
 
 #define MAX_CI_CONNECT  16 // maximum possible value is 254
@@ -440,7 +446,7 @@
 public:
   cCiTransportLayer(int Fd, int NumSlots);
   cCiTransportConnection *NewConnection(int Slot);
-  bool ResetSlot(int Slot);
+  bool ResetSlot(int Slot, bool Wait = false);
   bool ModuleReady(int Slot);
   cCiTransportConnection *Process(int Slot);
   };
@@ -451,6 +457,7 @@
   numSlots = NumSlots;
   for (int s = 0; s < numSlots; s++)
       ResetSlot(s);
+  cCondWait::SleepMs(2000);
 }
 
 cCiTransportConnection *cCiTransportLayer::NewConnection(int Slot)
@@ -467,10 +474,16 @@
   return NULL;
 }
 
-bool cCiTransportLayer::ResetSlot(int Slot)
+bool cCiTransportLayer::ResetSlot(int Slot, bool Wait)
 {
+  for (int i = 0; i < MAX_CI_CONNECT; i++) {
+      if (tc[i].State() != stIDLE && tc[i].Slot() == Slot)
+         tc[i].Reset();
+      }
   dbgprotocol("Resetting slot %d...", Slot);
   if (ioctl(fd, CA_RESET, 1 << Slot) != -1) {
+     if (Wait)
+        cCondWait::SleepMs(2000);
      dbgprotocol("ok.\n");
      return true;
      }
@@ -1602,5 +1615,5 @@
 {
   cMutexLock MutexLock(&mutex);
   CloseAllSessions(Slot);
-  return tpl->ResetSlot(Slot);
+  return tpl->ResetSlot(Slot, true);
 }
diff -ruN vdr-1.3.25/config.h vdr-1.3.26/config.h
--- vdr-1.3.25/config.h	2005-05-14 11:18:08.000000000 +0200
+++ vdr-1.3.26/config.h	2005-06-03 14:39:16.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.218 2005/05/14 09:18:08 kls Exp $
+ * $Id: config.h 1.219 2005/06/03 12:39:16 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -20,8 +20,8 @@
 #include "i18n.h"
 #include "tools.h"
 
-#define VDRVERSION  "1.3.25"
-#define VDRVERSNUM   10325  // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION  "1.3.26"
+#define VDRVERSNUM   10326  // Version * 10000 + Major * 100 + Minor
 
 #define MAXPRIORITY 99
 #define MAXLIFETIME 99
diff -ruN vdr-1.3.25/device.c vdr-1.3.26/device.c
--- vdr-1.3.25/device.c	2005-05-07 17:04:17.000000000 +0200
+++ vdr-1.3.26/device.c	2005-06-12 15:39:11.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: device.c 1.101 2005/05/07 15:04:17 kls Exp $
+ * $Id: device.c 1.103 2005/06/12 13:39:11 kls Exp $
  */
 
 #include "device.h"
@@ -397,6 +397,8 @@
            PRINTPIDS("A");
            if (!SetPid(&pidHandles[n], n, true)) {
               esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1);
+              if (PidType <= ptTeletext)
+                 DetachAll(Pid);
               DelPid(Pid, PidType);
               return false;
               }
@@ -422,6 +424,8 @@
         PRINTPIDS("C");
         if (!SetPid(&pidHandles[n], n, true)) {
            esyslog("ERROR: can't set PID %d on device %d", Pid, CardIndex() + 1);
+           if (PidType <= ptTeletext)
+              DetachAll(Pid);
            DelPid(Pid, PidType);
            return false;
            }
@@ -501,6 +505,15 @@
   return false;
 }
 
+bool cDevice::ProvidesTransponderExclusively(const cChannel *Channel) const
+{
+  for (int i = 0; i < numDevices; i++) {
+      if (device[i] && device[i] != this && device[i]->ProvidesTransponder(Channel))
+         return false;
+      }
+  return true;
+}
+
 bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
 {
   return false;
@@ -1211,6 +1224,18 @@
      }
 }
 
+void cDevice::DetachAll(int Pid)
+{
+  if (Pid) {
+     cMutexLock MutexLock(&mutexReceiver);
+     for (int i = 0; i < MAXRECEIVERS; i++) {
+         cReceiver *Receiver = receiver[i];
+         if (Receiver && Receiver->WantsPid(Pid))
+            Detach(Receiver);
+         }
+     }
+}
+
 // --- cTSBuffer -------------------------------------------------------------
 
 cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
diff -ruN vdr-1.3.25/device.h vdr-1.3.26/device.h
--- vdr-1.3.25/device.h	2005-02-20 15:06:28.000000000 +0100
+++ vdr-1.3.26/device.h	2005-06-12 15:35:47.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.57 2005/02/20 14:06:28 kls Exp $
+ * $Id: device.h 1.59 2005/06/12 13:35:47 kls Exp $
  */
 
 #ifndef __DEVICE_H
@@ -186,6 +186,9 @@
          ///< Returns true if this device can provide the given source.
   virtual bool ProvidesTransponder(const cChannel *Channel) const;
          ///< XXX -> PLUGINS.html!
+  virtual bool ProvidesTransponderExclusively(const cChannel *Channel) const;
+         ///< Returns true if this is the only device that is able to provide
+         ///< the given channel's transponder.
   virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
          ///< Returns true if this device can provide the given channel.
          ///< In case the device has cReceivers attached to it or it is the primary
@@ -500,6 +503,8 @@
        ///< Attaches the given receiver to this device.
   void Detach(cReceiver *Receiver);
        ///< Detaches the given receiver from this device.
+  void DetachAll(int Pid);
+       ///< Detaches all receivers from this device for this pid.
   };
 
 /// Derived cDevice classes that can receive channels will have to provide
diff -ruN vdr-1.3.25/dvbdevice.c vdr-1.3.26/dvbdevice.c
--- vdr-1.3.25/dvbdevice.c	2005-05-16 17:23:43.000000000 +0200
+++ vdr-1.3.26/dvbdevice.c	2005-06-05 15:05:55.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: dvbdevice.c 1.129 2005/05/16 15:23:43 kls Exp $
+ * $Id: dvbdevice.c 1.130 2005/06/05 13:05:55 kls Exp $
  */
 
 #include "dvbdevice.h"
@@ -654,8 +654,10 @@
      if (On) {
         if (Handle->handle < 0) {
            Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), O_RDWR | O_NONBLOCK, true);
-           if (Handle->handle < 0)
+           if (Handle->handle < 0) {
+              LOG_ERROR;
               return false;
+              }
            }
         pesFilterParams.pid     = Handle->pid;
         pesFilterParams.input   = DMX_IN_FRONTEND;
@@ -722,6 +724,10 @@
 
   // Turn off live PIDs:
 
+  DetachAll(pidHandles[ptAudio].pid);
+  DetachAll(pidHandles[ptVideo].pid);
+  DetachAll(pidHandles[ptPcr].pid);
+  DetachAll(pidHandles[ptTeletext].pid);
   DelPid(pidHandles[ptAudio].pid);
   DelPid(pidHandles[ptVideo].pid);
   DelPid(pidHandles[ptPcr].pid, ptPcr);
@@ -891,6 +897,7 @@
   if (TrackId && TrackId->id) {
      if (IS_AUDIO_TRACK(Type)) {
         if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) {
+           DetachAll(pidHandles[ptAudio].pid);
            pidHandles[ptAudio].pid = TrackId->id;
            SetPid(&pidHandles[ptAudio], ptAudio, true);
            }
diff -ruN vdr-1.3.25/eit.c vdr-1.3.26/eit.c
--- vdr-1.3.25/eit.c	2005-05-28 13:35:55.000000000 +0200
+++ vdr-1.3.26/eit.c	2005-06-11 17:31: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.107 2005/05/28 11:35:55 kls Exp $
+ * $Id: eit.c 1.108 2005/06/11 15:31:21 kls Exp $
  */
 
 #include "eit.h"
@@ -48,8 +48,8 @@
 
   SI::EIT::Event SiEitEvent;
   for (SI::Loop::Iterator it; eventLoop.getNext(SiEitEvent, it); ) {
-      // Drop bogus events.
-      if (SiEitEvent.getStartTime() == 0 || SiEitEvent.getDuration() == 0)
+      // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number.
+      if (SiEitEvent.getStartTime() == 0 || SiEitEvent.getStartTime() > 0 && SiEitEvent.getDuration() == 0)
          continue;
       Empty = false;
       cEvent *newEvent = NULL;
diff -ruN vdr-1.3.25/eitscan.c vdr-1.3.26/eitscan.c
--- vdr-1.3.25/eitscan.c	2005-05-05 15:05:00.000000000 +0200
+++ vdr-1.3.26/eitscan.c	2005-06-12 16:09:45.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: eitscan.c 1.24 2005/05/05 13:05:00 kls Exp $
+ * $Id: eitscan.c 1.26 2005/06/12 14:09:45 kls Exp $
  */
 
 #include "eitscan.h"
@@ -12,6 +12,7 @@
 #include "channels.h"
 #include "dvbdevice.h"
 #include "skins.h"
+#include "transfer.h"
 
 // --- cScanData -------------------------------------------------------------
 
@@ -139,51 +140,47 @@
                  transponderList = NULL;
                  }
               }
-           for (bool AnyDeviceSwitched = false; !AnyDeviceSwitched; ) {
-               cScanData *ScanData = NULL;
-               for (int i = 0; i < cDevice::NumDevices(); i++) {
-                   if (ScanData || (ScanData = scanList->First()) != NULL) {
-                      cDevice *Device = cDevice::GetDevice(i);
-                      if (Device) {
-                         if (Device != cDevice::PrimaryDevice() || (cDevice::NumDevices() == 1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) {
-                            if (!(Device->Receiving(true) || Device->Replaying())) {
-                               const cChannel *Channel = ScanData->GetChannel();
-                               if (Channel) {
-                                  if ((!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= 0x0100) && Device->ProvidesTransponder(Channel)) {
-                                     if (Device == cDevice::PrimaryDevice() && !currentChannel) {
+           bool AnyDeviceSwitched = false;
+           for (int i = 0; i < cDevice::NumDevices(); i++) {
+               cDevice *Device = cDevice::GetDevice(i);
+               if (Device) {
+                  for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) {
+                      const cChannel *Channel = ScanData->GetChannel();
+                      if (Channel) {
+                         if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= 0x0100) {
+                            if (Device->ProvidesTransponder(Channel)) {
+                               if (!Device->Receiving()) {
+                                  if (Device != cDevice::ActualDevice() || (Device->ProvidesTransponderExclusively(Channel) && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) {
+                                     if (Device == cDevice::ActualDevice() && !currentChannel) {
+                                        if (cTransferControl::ReceiverDevice())
+                                           cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
                                         currentChannel = Device->CurrentChannel();
                                         Skins.Message(mtInfo, tr("Starting EPG scan"));
                                         }
                                      currentDevice = Device;//XXX see also dvbdevice.c!!!
+                                     //dsyslog("EIT scan: device %d  source  %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
                                      Device->SwitchChannel(Channel, false);
                                      currentDevice = NULL;
                                      scanList->Del(ScanData);
-                                     ScanData = NULL;
                                      AnyDeviceSwitched = true;
+                                     break;
                                      }
                                   }
                                }
                             }
                          }
                       }
-                   else
-                      break;
-                   }
-               if (ScanData && !AnyDeviceSwitched) {
-                  scanList->Del(ScanData);
-                  ScanData = NULL;
-                  }
-               if (!scanList->Count()) {
-                  delete scanList;
-                  scanList = NULL;
-                  if (lastActivity == 0) // this was a triggered scan
-                     Activity();
-                  break;
                   }
                }
+           if (!scanList->Count() || !AnyDeviceSwitched) {
+              delete scanList;
+              scanList = NULL;
+              if (lastActivity == 0) // this was a triggered scan
+                 Activity();
+              }
+           Channels.Unlock();
            }
         lastScan = time(NULL);
-        Channels.Unlock();
         }
      }
 }
diff -ruN vdr-1.3.25/epg.c vdr-1.3.26/epg.c
--- vdr-1.3.25/epg.c	2005-05-29 12:19:48.000000000 +0200
+++ vdr-1.3.26/epg.c	2005-06-05 14:17:15.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.34 2005/05/29 10:19:48 kls Exp $
+ * $Id: epg.c 1.35 2005/06/05 12:17:15 kls Exp $
  */
 
 #include "epg.h"
@@ -323,7 +323,7 @@
   return false;
 }
 
-#define MAXEPGBUGFIXSTATS 12
+#define MAXEPGBUGFIXSTATS 13
 #define MAXEPGBUGFIXCHANS 100
 struct tEpgBugFixStats {
   int hits;
@@ -638,6 +638,11 @@
             }
         }
      }
+  else {
+     // we don't want any "(null)" titles
+     title = strcpyrealloc(title, tr("No title"));
+     EpgBugFixStat(12, ChannelID());
+     }
 }
 
 // --- cSchedule -------------------------------------------------------------
diff -ruN vdr-1.3.25/i18n.c vdr-1.3.26/i18n.c
--- vdr-1.3.25/i18n.c	2005-05-15 16:37:59.000000000 +0200
+++ vdr-1.3.26/i18n.c	2005-06-05 13:59:09.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: i18n.c 1.191 2005/05/15 14:37:59 kls Exp $
+ * $Id: i18n.c 1.194 2005/06/05 11:59:09 kls Exp $
  *
  * Translations provided by:
  *
@@ -386,7 +386,7 @@
     "Resumo",
     "Résumé",
     "Sammendrag",
-    "Tiedot",
+    "Yhteenveto",
     "Zawartosc",
     "Resúmen",
     "Ðåñéå÷üìåíï",
@@ -407,6 +407,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
+    "Tiedot",
     "",//TODO
     "",//TODO
     "",//TODO
@@ -416,8 +417,7 @@
     "",//TODO
     "",//TODO
     "",//TODO
-    "",//TODO
-    "",//TODO
+    "Info",
     "",//TODO
   },
   { "Schedule - %s",
@@ -964,7 +964,7 @@
     "Reiniciar",
     "ÁÑàÞá",
     "Reset",
-    "Reset",
+    "Nullimine",
     "Nulstille",
   },
   { "Scan",
@@ -2734,7 +2734,7 @@
     "Durada dels missatges (s)",
     "´ÛØâÕÛìÝÞáâì ßÞÚÐ×Ð áÞÞÑéÕÝØÙ (áÕÚ)",
     "Vrijeme prikaza poruka (s)",
-    "Kanaliteate esitusaeg (s)",
+    "Teate esitusaeg (s)",
     "Tid beskeder skal vises (s)",
   },
   { "Setup.OSD$Use small font",
@@ -2860,7 +2860,7 @@
     "",// TODO
     "¿ÞÚÐ× ØÝäÞàÜÐæØØ Þ ÚÐÝÐÛÕ (áÕÚ)",
     "",// TODO
-    "",// TODO
+    "Kanaliteate esitusaeg (s)",
     "Tid kanalinfo skal vises (s)",
   },
   { "Setup.OSD$Info on channel switch",
@@ -2881,7 +2881,7 @@
     "Informació del canvi de canal",
     "¿ÞÚÐ×ëÒÐâì ØÝäÞàÜÐæØî Þ ÚÐÝÐÛÕ",
     "Informacije kod promjene kanala",
-    "Näita kanaliteadet",
+    "Kanaliteate näitamine",
     "Info ved kanalskift",
   },
   { "Setup.OSD$Scroll pages",
@@ -2944,7 +2944,7 @@
     "Gravacions en subcarpetes",
     "ºÐâÐÛÞÓØ åàÐÝÕÝØï ×ÐßØáÕÙ",
     "Imenik za snimke",
-    "Salvesta kausta nime",
+    "Kausta nime salvestamine",
     "Optagelser i foldere",
   },
   { "Setup.EPG$EPG scan timeout (h)",
@@ -3658,7 +3658,7 @@
     "Utilitzar el nom de l'episodi",
     "³àãßßØàÞÒÐâì äÐÙÛë ßÞ íßØ×ÞÔÐÜ",
     "Koristi ime epizode",
-    "Kasuta episoodi nime",
+    "Episoodi nime kasutamine",
     "Anvend udsendelsesnavn",
   },
   { "Setup.Recording$Use VPS",
@@ -3679,7 +3679,7 @@
     "",// TODO
     "¸áßÞÛì×ÞÒÐâì áØÓÝÐÛë VPS",
     "Koristi VPS",
-    "Kasuta VPS-i",
+    "VPS-i kasutamine",
     "Anvend VPS",
   },
   { "Setup.Recording$VPS margin (s)",
@@ -3721,7 +3721,7 @@
     "Marcar gravació instantània",
     "¾âÜÕçÐâì áÔÕÛÐÝÝëÕ ÒàãçÝãî ×ÐßØáØ",
     "Oznaèi direktno snimanje",
-    "Märgista otsesalvestusi",
+    "Otsesalvestuse märgistamine",
     "Markér direkte optagelse",
   },
   { "Setup.Recording$Name instant recording",
@@ -3805,7 +3805,7 @@
     "Separar arxius",
     "´ÕÛØâì ÞâàÕÔÐÚâØàÞÒÐÝÝëÕ äÐÙÛë",
     "Podijeli ureðene datoteke",
-    "Tükelda redigeeritud faile",
+    "Redigeeritud failide tükeldamine",
     "Opdel redigerede filer",
   },
   { "Setup.Replay$Multi speed mode",
@@ -5346,6 +5346,27 @@
     "ST:TNG konsool",
     "ST:TNG konsol",
   },
+  { "No title",
+    "Kein Titel",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "Ei esitystä",
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+    "",// TODO
+  },
   { NULL }
   };
 
diff -ruN vdr-1.3.25/menu.c vdr-1.3.26/menu.c
--- vdr-1.3.25/menu.c	2005-05-16 15:59:03.000000000 +0200
+++ vdr-1.3.26/menu.c	2005-06-05 16:11:54.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.349 2005/05/16 13:59:03 kls Exp $
+ * $Id: menu.c 1.350 2005/06/05 14:11:54 kls Exp $
  */
 
 #include "menu.h"
@@ -1537,7 +1537,7 @@
 int cMenuRecordings::helpKeys = -1;
 
 cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
-:cOsdMenu(Base ? Base : tr("Recordings"), 6, 6)
+:cOsdMenu(Base ? Base : tr("Recordings"), 8, 6)
 {
   base = Base ? strdup(Base) : NULL;
   level = Setup.RecordingDirs ? Level : -1;
diff -ruN vdr-1.3.25/osd.c vdr-1.3.26/osd.c
--- vdr-1.3.25/osd.c	2005-05-14 13:16:30.000000000 +0200
+++ vdr-1.3.26/osd.c	2005-06-11 16:31:36.000000000 +0200
@@ -4,12 +4,11 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: osd.c 1.60 2005/05/14 11:16:30 kls Exp $
+ * $Id: osd.c 1.61 2005/06/11 14:31:36 kls Exp $
  */
 
 #include "osd.h"
 #include <math.h>
-#include <signal.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
diff -ruN vdr-1.3.25/osdbase.c vdr-1.3.26/osdbase.c
--- vdr-1.3.25/osdbase.c	2005-01-07 17:16:41.000000000 +0100
+++ vdr-1.3.26/osdbase.c	2005-06-12 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: osdbase.c 1.15 2005/01/07 16:16:41 kls Exp $
+ * $Id: osdbase.c 1.17 2005/06/12 10:44:22 kls Exp $
  */
 
 #include "osdbase.h"
@@ -74,11 +74,7 @@
   hasHotkeys = false;
   title = NULL;
   SetTitle(Title);
-  cols[0] = c0;
-  cols[1] = c1;
-  cols[2] = c2;
-  cols[3] = c3;
-  cols[4] = c4;
+  SetCols(c0, c1, c2, c3, c4);
   first = 0;
   current = marked = -1;
   subMenu = NULL;
@@ -116,6 +112,15 @@
   return s;
 }
 
+void cOsdMenu::SetCols(int c0, int c1, int c2, int c3, int c4)
+{
+  cols[0] = c0;
+  cols[1] = c1;
+  cols[2] = c2;
+  cols[3] = c3;
+  cols[4] = c4;
+}
+
 void cOsdMenu::SetHasHotkeys(void)
 {
   hasHotkeys = true;
@@ -258,7 +263,8 @@
 {
   if (current > 0) {
      int tmpCurrent = current;
-     while (--tmpCurrent >= 0 && !SelectableItem(tmpCurrent));
+     while (--tmpCurrent >= 0 && !SelectableItem(tmpCurrent))
+           ;
      if (tmpCurrent < 0)
         return;
      if (tmpCurrent >= first)
@@ -282,7 +288,8 @@
 
   if (current < last) {
      int tmpCurrent = current;
-     while (++tmpCurrent <= last && !SelectableItem(tmpCurrent));
+     while (++tmpCurrent <= last && !SelectableItem(tmpCurrent))
+           ;
      if (tmpCurrent > last)
         return;
      if (tmpCurrent <= lastOnScreen)
@@ -306,33 +313,62 @@
 
 void cOsdMenu::PageUp(void)
 {
+  int oldCurrent = current;
+  int oldFirst = first;
   current -= displayMenuItems;
   first -= displayMenuItems;
+  int last = Count() - 1;
+  if (current < 0)
+     current = 0;
   if (first < 0)
-     first = current = 0;
-  if (!SelectableItem(current)) {
-     current -= (current > 0) ? 1 : -1;
-     first = min(first, current - 1);
+     first = 0;
+  int tmpCurrent = current;
+  while (!SelectableItem(tmpCurrent) && --tmpCurrent >= 0)
+        ;
+  if (tmpCurrent < 0) {
+     tmpCurrent = current;
+     while (++tmpCurrent <= last && !SelectableItem(tmpCurrent))
+           ;
+     }
+  current = tmpCurrent <= last ? tmpCurrent : -1;
+  if (current >= 0) {
+     if (current < first)
+        first = current;
+     else if (current - first >= displayMenuItems)
+        first = current - displayMenuItems + 1;
+     }
+  if (current != oldCurrent || first != oldFirst) {
+     Display();
+     DisplayCurrent(true);
      }
-  Display();
-  DisplayCurrent(true);
 }
 
 void cOsdMenu::PageDown(void) 
 {
+  int oldCurrent = current;
+  int oldFirst = first;
   current += displayMenuItems;
   first += displayMenuItems;
-  int count = Count();
-  if (current > count - 1) {
-     current = count - 1;
-     first = max(0, count - displayMenuItems);
-     }
-  if (!SelectableItem(current)) {
-     current += (current < count - 1) ? 1 : -1;
-     first = max(first, current - displayMenuItems);
+  int last = Count() - 1;
+  int tmpCurrent = current;
+  while (!SelectableItem(tmpCurrent) && ++tmpCurrent <= last)
+        ;
+  if (tmpCurrent > last) {
+     tmpCurrent = current;
+     while (--tmpCurrent >= 0 && !SelectableItem(tmpCurrent))
+           ;
+     }
+  current = tmpCurrent > 0 ? tmpCurrent : -1;
+  if (current >= 0) {
+     if (current < first)
+        first = current;
+     else if (current - first >= displayMenuItems)
+        first = current - displayMenuItems + 1;
+     }
+  if (current != oldCurrent || first != oldFirst) {
+     Display();
+     DisplayCurrent(true);
      }
-  Display();
-  DisplayCurrent(true);
 }
 
 void cOsdMenu::Mark(void)
diff -ruN vdr-1.3.25/osdbase.h vdr-1.3.26/osdbase.h
--- vdr-1.3.25/osdbase.h	2004-04-30 15:40:11.000000000 +0200
+++ vdr-1.3.26/osdbase.h	2005-06-12 12:46:34.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: osdbase.h 1.10 2004/04/30 13:40:11 kls Exp $
+ * $Id: osdbase.h 1.11 2005/06/12 10:46:34 kls Exp $
  */
 
 #ifndef __OSDBASE_H
@@ -98,6 +98,7 @@
 protected:
   cSkinDisplayMenu *DisplayMenu(void) { return displayMenu; }
   const char *hk(const char *s);
+  void SetCols(int c0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0);
   void SetHasHotkeys(void);
   virtual void Clear(void);
   bool SelectableItem(int idx);
diff -ruN vdr-1.3.25/recording.c vdr-1.3.26/recording.c
--- vdr-1.3.25/recording.c	2005-05-29 13:16:57.000000000 +0200
+++ vdr-1.3.26/recording.c	2005-06-05 16:11:45.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.107 2005/05/29 11:16:57 kls Exp $
+ * $Id: recording.c 1.109 2005/06/05 14:11:45 kls Exp $
  */
 
 #include "recording.h"
@@ -480,8 +480,8 @@
            char *data[3] = { NULL };
            cReadLine ReadLine;
            char *s;
-           while ((s = ReadLine.Read(f)) != NULL && line < 3) {
-                 if (*s) {
+           while ((s = ReadLine.Read(f)) != NULL) {
+                 if (*s || line > 1) {
                     if (data[line]) {
                        int len = strlen(s);
                        len += strlen(data[line]) + 1;
@@ -593,9 +593,10 @@
         s++;
      else
         s = name;
-     asprintf(&titleBuffer, "%02d.%02d%c%02d:%02d%c%c%s",
+     asprintf(&titleBuffer, "%02d.%02d.%02d%c%02d:%02d%c%c%s",
                             t->tm_mday,
                             t->tm_mon + 1,
+                            t->tm_year % 100,
                             Delimiter,
                             t->tm_hour,
                             t->tm_min,
diff -ruN vdr-1.3.25/remux.c vdr-1.3.26/remux.c
--- vdr-1.3.25/remux.c	2005-03-20 14:18:15.000000000 +0100
+++ vdr-1.3.26/remux.c	2005-06-04 16:49:25.000000000 +0200
@@ -11,7 +11,7 @@
  * The cDolbyRepacker 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.33 2005/03/20 13:18:15 kls Exp $
+ * $Id: remux.c 1.34 2005/06/04 14:49:25 kls Exp $
  */
 
 #include "remux.h"
@@ -32,10 +32,363 @@
   virtual void Reset(void) {}
   virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count) = 0;
   virtual int BreakAt(const uchar *Data, int Count) = 0;
+  virtual int QuerySnoopSize(void) { return 0; }
   void SetMaxPacketSize(int MaxPacketSize) { maxPacketSize = MaxPacketSize; }
   void SetSubStreamId(uint8_t SubStreamId) { subStreamId = SubStreamId; }
   };
 
+// --- cVideoRepacker --------------------------------------------------------
+
+class cVideoRepacker : public cRepacker {
+private:
+  int skippedBytes;
+  int packetTodo;
+  uchar fragmentData[6 + 65535 + 3];
+  int fragmentLen;
+  uchar pesHeader[6 + 3 + 255 + 3];
+  int pesHeaderLen;
+  uchar pesHeaderBackup[6 + 3 + 255];
+  int pesHeaderBackupLen;
+  uint32_t scanner;
+  enum eState {
+    syncing,
+    findPicture,
+    scanPicture
+    } state;
+  uint32_t localScanner;
+  int localStart;
+  bool PushOutPacket(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count);
+public:
+  cVideoRepacker(void);
+  virtual void Reset(void);
+  virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count);
+  virtual int BreakAt(const uchar *Data, int Count);
+  virtual int QuerySnoopSize() { return 4; }
+  };
+
+cVideoRepacker::cVideoRepacker(void)
+{
+  Reset();
+}
+
+void cVideoRepacker::Reset(void)
+{
+  skippedBytes = 0;
+  packetTodo = maxPacketSize - 6 - 3;
+  fragmentLen = 0;
+  pesHeaderLen = 0;
+  pesHeaderBackupLen = 0;
+  scanner = 0xFFFFFFFF;
+  state = syncing;
+  localStart = -1;
+}
+
+bool cVideoRepacker::PushOutPacket(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count)
+{
+  // enter packet length into PES header ...
+  if (fragmentLen > 0) { // ... which is contained in the fragment buffer
+     // determine PES packet payload
+     int PacketLen = fragmentLen + Count - 6;
+     fragmentData[ 4 ] = PacketLen >> 8;
+     fragmentData[ 5 ] = PacketLen & 0xFF;
+     // amount of data to put into result buffer: a negative Count value means
+     // to strip off any partially contained start code.
+     int Bite = fragmentLen + (Count >= 0 ? 0 : Count);
+     // put data into result buffer
+     int n = ResultBuffer->Put(fragmentData, Bite);
+     if (n != Bite) {
+        Reset();
+        return false;
+        }
+     fragmentLen = 0;
+     }
+  else if (pesHeaderLen > 0) { // ... which is contained in the PES header buffer
+     int PacketLen = pesHeaderLen + Count - 6;
+     pesHeader[ 4 ] = PacketLen >> 8;
+     pesHeader[ 5 ] = PacketLen & 0xFF;
+     // amount of data to put into result buffer: a negative Count value means
+     // to strip off any partially contained start code.
+     int Bite = pesHeaderLen + (Count >= 0 ? 0 : Count);
+     // put data into result buffer
+     int n = ResultBuffer->Put(pesHeader, Bite);
+     if (n != Bite) {
+        Reset();
+        return false;
+        }
+     pesHeaderLen = 0;
+     }
+  // append further payload
+  if (Count > 0) {
+     // amount of data to put into result buffer
+     int Bite = Count;
+     // put data into result buffer
+     int n = ResultBuffer->Put(Data, Bite);
+     if (n != Bite) {
+        Reset();
+        return false;
+        }
+     }
+  // we did it ;-)
+  return true;
+}
+
+int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int Count)
+{
+  // reset local scanner
+  localStart = -1;
+ 
+  // check for MPEG 2
+  if ((Data[6] & 0xC0) != 0x80)
+     return 0;
+
+  // backup PES header
+  if (Data[6] != 0x80 || Data[7] != 0x00 || Data[8] != 0x00) {
+     pesHeaderBackupLen = 6 + 3 + Data[8];
+     memcpy(pesHeaderBackup, Data, pesHeaderBackupLen);
+     }
+
+  // skip PES header
+  int done = 6 + 3 + Data[8];
+  int todo = Count - done;
+  const uchar *data = Data + done;
+  // remember start of the data
+  const uchar *payload = data;
+
+  while (todo > 0) {
+        // collect number of skipped bytes while syncing
+        if (state <= syncing)
+           skippedBytes++;
+        // did we reach a start code?
+        scanner <<= 8;
+        if (scanner != 0x00000100)
+           scanner |= *data;
+        else {
+           scanner |= *data;
+
+           // which kind of start code have we got?
+           switch (*data) {
+             case 0xB9 ... 0xFF: // system start codes
+                  esyslog("cVideoRepacker: found system start code: stream seems to be scrambled or not demultiplexed");
+                  Reset();
+                  break;
+             case 0xB0 ... 0xB1: // reserved start codes
+             case 0xB6:
+                  esyslog("cVideoRepacker: found reserved start code: stream seems to be scrambled");
+                  Reset();
+                  break;
+             case 0xB4: // sequence error code
+                  isyslog("cVideoRepacker: found sequence error code: stream seems to be damaged");
+             case 0xB2: // user data start code
+             case 0xB5: // extension start code
+                  break;
+             case 0xB7: // sequence end code
+             case 0xB3: // sequence header code
+             case 0xB8: // group start code
+             case 0x00: // picture start code
+                  if (state == scanPicture) {
+                     // the above start codes indicate that the current picture is done. So
+                     // push out the packet to start a new packet for the next picuture. If
+                     // the byte count get's negative then the current buffer ends in a
+                     // partitial start code that must be stripped off, as it shall be put
+                     // in the next packet.
+                     if (!PushOutPacket(ResultBuffer, payload, data - 3 - payload))
+                        return done - 3;
+                     // go on with syncing to the next picture
+                     state = syncing;
+                     }
+                  if (state == syncing) {
+                     // report that syncing dropped some bytes
+                     if (skippedBytes > 4)
+                        esyslog("cVideoRepacker: skipped %d bytes to sync on next picture", skippedBytes - 4);
+                     skippedBytes = 0;
+                     // if there is a PES header available, then use it ...
+                     if (pesHeaderBackupLen > 0) {
+                        // ISO 13818-1 says:
+                        // In the case of video, if a PTS is present in a PES packet header
+                        // it shall refer to the access unit containing the first picture start
+                        // code that commences in this PES packet. A picture start code commences
+                        // in PES packet if the first byte of the picture start code is present
+                        // in the PES packet.
+                        memcpy(pesHeader, pesHeaderBackup, pesHeaderBackupLen);
+                        pesHeaderLen = pesHeaderBackupLen;
+                        pesHeaderBackupLen = 0;
+                        }
+                     else {
+                        // ... otherwise create a continuation PES header
+                        pesHeaderLen = 0;
+                        pesHeader[pesHeaderLen++] = 0x00;
+                        pesHeader[pesHeaderLen++] = 0x00;
+                        pesHeader[pesHeaderLen++] = 0x01;
+                        pesHeader[pesHeaderLen++] = Data[3]; // video stream ID
+                        pesHeader[pesHeaderLen++] = 0x00; // length still unknown
+                        pesHeader[pesHeaderLen++] = 0x00; // length still unknown
+                        pesHeader[pesHeaderLen++] = 0x80;
+                        pesHeader[pesHeaderLen++] = 0x00;
+                        pesHeader[pesHeaderLen++] = 0x00;
+                        }
+                     // append the first three bytes of the start code
+                     pesHeader[pesHeaderLen++] = 0x00;
+                     pesHeader[pesHeaderLen++] = 0x00;
+                     pesHeader[pesHeaderLen++] = 0x01;
+                     // the next packet's payload will begin with the fourth byte of
+                     // the start code (= the actual code)
+                     payload = data;
+                     // as there is no length information available, assume the
+                     // maximum we can hold in one PES packet
+                     packetTodo = maxPacketSize - pesHeaderLen;
+                     // go on with finding the picture data
+                     ((int &)state)++;
+                     }
+                  break;
+             case 0x01 ... 0xAF: // slice start codes
+                  if (state == findPicture) {
+                     // go on with scanning the picture data
+                     ((int &)state)++;
+                     }
+                  break;
+             }
+           }
+        data++;
+        done++;
+        todo--;
+        // do we have to start a new packet as there is no more space left?
+        if (--packetTodo <= 0) {
+           // we connot start a new packet here if the current might end in a start
+           // code and this start code shall possibly be put in the next packet. So
+           // overfill the current packet until we can safely detect that we won't
+           // break a start code into pieces:
+           //
+           // A) the last four bytes were a start code.
+           // B) the current byte introduces a start code.
+           // C) the last three bytes begin a start code.
+           //
+           // Todo : Data                          : Rule : Result
+           // -----:-------------------------------:------:-------
+           //      : XX 00 00 00 01 YY|YY YY YY YY :      :
+           //    0 :                ^^|            : A    : push
+           // -----:-------------------------------:------:-------
+           //      : XX XX 00 00 00 01|YY YY YY YY :      :
+           //    0 :                ^^|            : B    : wait
+           //   -1 :                  |^^          : A    : push
+           // -----:-------------------------------:------:-------
+           //      : XX XX XX 00 00 00|01 YY YY YY :      :
+           //    0 :                ^^|            : C    : wait
+           //   -1 :                  |^^          : B    : wait
+           //   -2 :                  |   ^^       : A    : push
+           // -----:-------------------------------:------:-------
+           //      : XX XX XX XX 00 00|00 01 YY YY :      :
+           //    0 :                ^^|            : C    : wait
+           //   -1 :                  |^^          : C    : wait
+           //   -2 :                  |   ^^       : B    : wait
+           //   -3 :                  |      ^^    : A    : push
+           // -----:-------------------------------:------:-------
+           //      : XX XX XX XX XX 00|00 00 01 YY :      :
+           //    0 :                ^^|            : C    : wait
+           //   -1 :                  |^^          : C    : wait
+           //   -2 :                  |   ^^       :      : push
+           // -----:-------------------------------:------:-------
+           bool A = ((scanner & 0xFFFFFF00) == 0x00000100);
+           bool B = ((scanner &   0xFFFFFF) ==   0x000001);
+           bool C = ((scanner &       0xFF) ==       0x00) && (packetTodo >= -1);
+           if (A || (!B && !C)) {
+              // actually we cannot push out an overfull packet. So we'll have to
+              // adjust the byte count and payload start as necessary. If the byte
+              // count get's negative we'll have to append the excess from fragment's
+              // tail to the next PES header.
+              int bite = data + packetTodo - payload;
+              const uchar *excessData = fragmentData + fragmentLen + bite;
+              // a negative byte count means to drop some bytes from the current
+              // fragment's tail, to not exceed the maximum packet size.
+              if (!PushOutPacket(ResultBuffer, payload, bite))
+                 return done;
+              // create a continuation PES header
+              pesHeaderLen = 0;
+              pesHeader[pesHeaderLen++] = 0x00;
+              pesHeader[pesHeaderLen++] = 0x00;
+              pesHeader[pesHeaderLen++] = 0x01;
+              pesHeader[pesHeaderLen++] = Data[3]; // video stream ID
+              pesHeader[pesHeaderLen++] = 0x00; // length still unknown
+              pesHeader[pesHeaderLen++] = 0x00; // length still unknown
+              pesHeader[pesHeaderLen++] = 0x80;
+              pesHeader[pesHeaderLen++] = 0x00;
+              pesHeader[pesHeaderLen++] = 0x00;
+              // copy any excess data
+              while (bite++ < 0) {
+                    // append the excess data here
+                    pesHeader[pesHeaderLen++] = *excessData++;
+                    packetTodo++;
+                    }
+              // the next packet's payload will begin here
+              payload = data + packetTodo;
+              // as there is no length information available, assume the
+              // maximum we can hold in one PES packet
+              packetTodo += maxPacketSize - pesHeaderLen;
+              }
+           }
+        }
+  // the packet is done. Now store any remaining data into fragment buffer
+  // if we are no longer syncing.
+  if (state != syncing) {
+     // append the PES header ...
+     int bite = pesHeaderLen;
+     pesHeaderLen = 0;
+     if (bite > 0) {
+        memcpy(fragmentData + fragmentLen, pesHeader, bite);
+        fragmentLen += bite;
+        }
+     // append payload. It may contain part of a start code at it's end,
+     // which will be removed when the next packet gets processed.
+     bite = data - payload;
+     if (bite > 0) {
+        memcpy(fragmentData + fragmentLen, payload, bite);
+        fragmentLen += bite;
+        }
+     }
+  // we've eaten the whole packet ;-)
+  return Count;
+}
+
+int cVideoRepacker::BreakAt(const uchar *Data, int Count)
+{
+  // enough data for test?
+  if (Count < 6 + 3)
+     return -1;
+  // check for MPEG 2
+  if ((Data[6] & 0xC0) != 0x80)
+     return -1;
+  int headerLen = Data[8] + 6 + 3;
+  // enough data for test?
+  if (Count < headerLen)
+     return -1;
+  // just detect end of picture
+  if (state == scanPicture) {
+     // setup local scanner
+     if (localStart < 0) {
+        localScanner = scanner;
+        localStart = 0;
+        }
+     // start where we've stopped at the last run
+     const uchar *data = Data + headerLen + localStart;
+     const uchar *limit = Data + Count;
+     // scan data
+     while (data < limit) {
+           localStart++;
+           localScanner <<= 8;
+           localScanner |= *data++;
+           // check start codes which follow picture data
+           switch (localScanner) {
+             case 0x00000100: // picture start code
+             case 0x000001B8: // group start code
+             case 0x000001B3: // sequence header code
+             case 0x000001B7: // sequence end code
+                  return data - Data;
+             }
+           }
+     }
+  // just fill up packet and append next start code
+  return headerLen + packetTodo + 4;
+}
+
 // --- cDolbyRepacker --------------------------------------------------------
 
 class cDolbyRepacker : public cRepacker {
@@ -462,6 +815,7 @@
   if (repacker) {
      repacker->SetMaxPacketSize(size);
      repacker->SetSubStreamId(subStreamId);
+     size += repacker->QuerySnoopSize();
      }
 
   tsErrors = 0;
@@ -801,7 +1155,7 @@
   resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, "Result");
   resultBuffer->SetTimeouts(0, 100);
   if (VPid)
-     ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS);
+     ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS, 0x00, 0x00, new cVideoRepacker);
   if (APids) {
      int n = 0;
      while (*APids && numTracks < MAXTRACKS && n < MAXAPIDS)
diff -ruN vdr-1.3.25/summary2info.pl vdr-1.3.26/summary2info.pl
--- vdr-1.3.25/summary2info.pl	2005-05-22 12:37:47.000000000 +0200
+++ vdr-1.3.26/summary2info.pl	2005-06-04 13:33:09.000000000 +0200
@@ -10,7 +10,7 @@
 # See the main source file 'vdr.c' for copyright information and
 # how to reach the author.
 #
-# $Id: summary2info.pl 1.2 2005/05/22 10:37:47 kls Exp $
+# $Id: summary2info.pl 1.3 2005/06/04 11:33:09 kls Exp $
 
 $VideoDir = $ARGV[0] || die "please provide the name of the video directory\n";
 
@@ -24,7 +24,7 @@
     @data = ();
     while (<F>) {
           chomp;
-          if ($_) {
+          if ($_ || $line > 1) {
              $data[$line] .= '|' if ($data[$line]);
              $data[$line] .= $_;
              }
diff -ruN vdr-1.3.25/timers.c vdr-1.3.26/timers.c
--- vdr-1.3.25/timers.c	2005-05-07 13:10:56.000000000 +0200
+++ vdr-1.3.26/timers.c	2005-06-11 16:19:58.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.31 2005/05/07 11:10:56 kls Exp $
+ * $Id: timers.c 1.32 2005/06/11 14:19:58 kls Exp $
  */
 
 #include "timers.h"
@@ -159,7 +159,7 @@
      else {
         // handle "day of month" for compatibility with older versions:
         char *tail = NULL;
-        int day = strtol(s, &tail, 10);
+        int day = strtol(d, &tail, 10);
         if (tail && *tail || day < 1 || day > 31)
            return false;
         time_t t = time(NULL);
