diff -ruN vdr-1.7.8/CONTRIBUTORS vdr-1.7.9/CONTRIBUTORS
--- vdr-1.7.8/CONTRIBUTORS	2009-06-13 15:35:49.000000000 +0200
+++ vdr-1.7.9/CONTRIBUTORS	2009-08-16 17:32:39.000000000 +0200
@@ -1079,6 +1079,8 @@
  for adding cThread::SetIOPriority() and using it in cRemoveDeletedRecordingsThread
  for suggesting to introduce cDevice::GetOsdSize()
  for adding a note about the meaning of PERCENTAGEDELTA in cRingBuffer::UpdatePercentage()
+ for fixing handling file name length on VFAT systems in case they
+ contain UTF-8 characters
 
 Ralf Klueber <ralf.klueber@vodafone.com>
  for reporting a bug in cutting a recording if there is only a single editing mark
@@ -1229,6 +1231,9 @@
  and GetOsdSize()
  for reporting a problem with calculating menu colum widths in case the font has a
  size other than the default size
+ for reporting a bug in storing the current OSD size in case the
+ device has changed it in its setup menu
+ for increasing the value of MAXFRAMESIZE to better suit HD recordings
 
 Richard Robson <richard_robson@beeb.net>
  for reporting freezing replay if a timer starts while in Transfer Mode from the
@@ -1641,6 +1646,8 @@
  for suggesting to add a note to the INSTALL file about using subdirectories to
  split a large disk into separate areas for VDR's video data and other stuff
  for reporting wrong variable types in cIndexFile
+ for reporting a problem with cDevice::PlayTsVideo() and cDevice::PlayTsAudio() in
+ case only part of the buffer has been accepted by the device
 
 Sven Kreiensen <svenk@kammer.uni-hannover.de>
  for his help in keeping 'channels.conf.terr' up to date
@@ -2281,6 +2288,7 @@
  for adding DESTDIR and PREFIX handling to the Makefile
  for fixing some compiler warnings with gcc-4.2.0
  for fixing setting the locale file name in i18n-to-gettext.pl
+ for fixing cRecordings::DelByName() to avoid compilation errors with gcc 4.4
 
 Martin Ostermann <martin@familie-ostermann.de>
  for fixing processing the PDCDescriptor in 'libsi' on big endian systems
@@ -2478,3 +2486,6 @@
 Martin Neuditschko <yosuke.tomoe@gmx.net>
  for reporting a problem with error messages from cDvbDevice::GetVideoSize()
  on systems with no real primary replay device
+
+Mikko Tuumanen <mikko.tuumanen@utu.fi>
+ for implementing full handling of subtitling descriptors
diff -ruN vdr-1.7.8/HISTORY vdr-1.7.9/HISTORY
--- vdr-1.7.8/HISTORY	2009-06-13 15:35:31.000000000 +0200
+++ vdr-1.7.9/HISTORY	2009-08-23 15:21:39.000000000 +0200
@@ -6133,5 +6133,26 @@
   default size (reported by Reinhard Nissl).
 - Added a plausibility check for the OSD percentage parameters
   to avoid problems in case the values are stored in the setup.conf
-  file in a  wrong way.
+  file in a wrong way.
 - Fixed variable types in cIndexFile (reported by Udo Richter).
+
+2009-08-23: Version 1.7.9
+
+- Fixed storing the current OSD size in case the device has
+  changed it in its setup menu (reported by Reinhard Nissl).
+- Fixed cDevice::PlayTsVideo() and cDevice::PlayTsAudio() in case only part of the
+  buffer has been accepted by the device (reported by Udo Richter).
+- Changed the EIT filter setup to save a few handles on devices that do hardware
+  filtering.
+- Fixed deleting expired timers if they have the VPS flag set, but the event they
+  are assigned to doesn't have a VPS tag.
+- Fixed handling file name length on VFAT systems in case they
+  contain UTF-8 characters (thanks to Rolf Ahrenberg).
+- Fixed generating CaPmts in case audio and video are encrypted using different
+  ECM pids.
+- Updated vdr.1 to use the new file names in recording directories.
+- Fixed cRecordings::DelByName() to avoid compilation errors with gcc 4.4
+  (thanks to Matthias Schwarzott).
+- Increased the value of MAXFRAMESIZE to better suit HD recordings (thanks to
+  Reinhard Nissl).
+- Implemented full handling of subtitling descriptors (thanks to Mikko Tuumanen).
diff -ruN vdr-1.7.8/channels.c vdr-1.7.9/channels.c
--- vdr-1.7.8/channels.c	2009-04-25 15:57:32.000000000 +0200
+++ vdr-1.7.9/channels.c	2009-08-16 17:08:49.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: channels.c 2.6 2009/04/25 13:57:32 kls Exp $
+ * $Id: channels.c 2.7 2009/08/16 15:08:49 kls Exp $
  */
 
 #include "channels.h"
@@ -533,6 +533,22 @@
      }
 }
 
+void cChannel::SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds)
+{
+  if (SubtitlingTypes) {
+     for (int i = 0; i < MAXSPIDS; i++)
+         subtitlingTypes[i] = SubtitlingTypes[i];
+     }
+  if (CompositionPageIds) {
+     for (int i = 0; i < MAXSPIDS; i++)
+         compositionPageIds[i] = CompositionPageIds[i];
+     }
+  if (AncillaryPageIds) {
+     for (int i = 0; i < MAXSPIDS; i++)
+         ancillaryPageIds[i] = AncillaryPageIds[i];
+     }
+}
+
 void cChannel::SetCaIds(const int *CaIds)
 {
   if (caids[0] && caids[0] <= CA_USER_MAX)
diff -ruN vdr-1.7.8/channels.h vdr-1.7.9/channels.h
--- vdr-1.7.8/channels.h	2008-11-22 14:35:52.000000000 +0100
+++ vdr-1.7.9/channels.h	2009-08-16 16:58:26.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: channels.h 2.4 2008/11/22 13:35:52 kls Exp $
+ * $Id: channels.h 2.5 2009/08/16 14:58:26 kls Exp $
  */
 
 #ifndef __CHANNELS_H
@@ -129,6 +129,9 @@
   char dlangs[MAXDPIDS][MAXLANGCODE2];
   int spids[MAXSPIDS + 1]; // list is zero-terminated
   char slangs[MAXSPIDS][MAXLANGCODE2];
+  uchar subtitlingTypes[MAXSPIDS];
+  uint16_t compositionPageIds[MAXSPIDS];
+  uint16_t ancillaryPageIds[MAXSPIDS];
   int tpid;
   int caids[MAXCAIDS + 1]; // list is zero-terminated
   int nid;
@@ -185,6 +188,9 @@
   const char *Alang(int i) const { return (0 <= i && i < MAXAPIDS) ? alangs[i] : ""; }
   const char *Dlang(int i) const { return (0 <= i && i < MAXDPIDS) ? dlangs[i] : ""; }
   const char *Slang(int i) const { return (0 <= i && i < MAXSPIDS) ? slangs[i] : ""; }
+  uchar SubtitlingType(int i) const { return (0 <= i && i < MAXSPIDS ? subtitlingTypes[i] : 0); }
+  uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS ? compositionPageIds[i] : 0); }
+  uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS ? ancillaryPageIds[i] : 0); }
   int Tpid(void) const { return tpid; }
   const int *Caids(void) const { return caids; }
   int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; }
@@ -226,6 +232,7 @@
   void SetCaDescriptors(int Level);
   void SetLinkChannels(cLinkChannels *LinkChannels);
   void SetRefChannel(cChannel *RefChannel);
+  void SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds);
   };
 
 class cChannels : public cRwLock, public cConfig<cChannel> {
diff -ruN vdr-1.7.8/ci.c vdr-1.7.9/ci.c
--- vdr-1.7.8/ci.c	2008-04-13 15:28:52.000000000 +0200
+++ vdr-1.7.9/ci.c	2009-08-16 15:21:07.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 2.1 2008/04/13 13:28:52 kls Exp $
+ * $Id: ci.c 2.3 2009/08/16 13:21:07 kls Exp $
  */
 
 #include "ci.h"
@@ -551,6 +551,8 @@
 
 // --- cCiCaPmt --------------------------------------------------------------
 
+#define MAXCASYSTEMIDS 64
+
 // Ca Pmt List Management:
 
 #define CPLM_MORE    0x00
@@ -574,9 +576,10 @@
   int length;
   int esInfoLengthPos;
   uint8_t capmt[2048]; ///< XXX is there a specified maximum?
-  int caDescriptorsLength;
-  uint8_t caDescriptors[2048];
-  bool streamFlag;
+  int source;
+  int transponder;
+  int programNumber;
+  int caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
   void AddCaDescriptors(int Length, const uint8_t *Data);
 public:
   cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds);
@@ -589,7 +592,17 @@
 cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
 {
   cmdId = CmdId;
-  caDescriptorsLength = GetCaDescriptors(Source, Transponder, ProgramNumber, CaSystemIds, sizeof(caDescriptors), caDescriptors, streamFlag);
+  source = Source;
+  transponder = Transponder;
+  programNumber = ProgramNumber;
+  int i = 0;
+  if (CaSystemIds) {
+     for (; CaSystemIds[i]; i++)
+         caSystemIds[i] = CaSystemIds[i];
+     }
+  caSystemIds[i] = 0;
+  uint8_t caDescriptors[512];
+  int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, 0);
   length = 0;
   capmt[length++] = CPLM_ONLY;
   capmt[length++] = (ProgramNumber >> 8) & 0xFF;
@@ -597,8 +610,9 @@
   capmt[length++] = 0x01; // version_number, current_next_indicator - apparently vn doesn't matter, but cni must be 1
   esInfoLengthPos = length;
   capmt[length++] = 0x00; // program_info_length H (at program level)
-  capmt[length++] = 0x00; // program_info_length L
-  if (!streamFlag)
+  capmt[length++] = 0x01; // program_info_length L
+  capmt[length++] = cmdId;
+  if (caDescriptorsLength > 0)
      AddCaDescriptors(caDescriptorsLength, caDescriptors);
 }
 
@@ -610,14 +624,17 @@
 void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
 {
   if (Pid) {
+     uint8_t caDescriptors[512];
+     int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, Pid);
      //XXX buffer overflow check???
      capmt[length++] = StreamType;
      capmt[length++] = (Pid >> 8) & 0xFF;
      capmt[length++] =  Pid       & 0xFF;
      esInfoLengthPos = length;
      capmt[length++] = 0x00; // ES_info_length H (at ES level)
-     capmt[length++] = 0x00; // ES_info_length L
-     if (streamFlag)
+     capmt[length++] = 0x01; // ES_info_length L
+     capmt[length++] = cmdId;
+     if (caDescriptorsLength > 0)
         AddCaDescriptors(caDescriptorsLength, caDescriptors);
      }
 }
@@ -625,8 +642,7 @@
 void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data)
 {
   if (esInfoLengthPos) {
-     if (length + Length < int(sizeof(capmt))) {
-        capmt[length++] = cmdId;
+     if (length + Length <= int(sizeof(capmt))) {
         memcpy(capmt + length, Data, Length);
         length += Length;
         int l = length - esInfoLengthPos - 2;
@@ -643,8 +659,6 @@
 
 // --- cCiConditionalAccessSupport -------------------------------------------
 
-#define MAXCASYSTEMIDS 64
-
 // CA Enable Ids:
 
 #define CAEI_POSSIBLE                  0x01
diff -ruN vdr-1.7.8/config.h vdr-1.7.9/config.h
--- vdr-1.7.8/config.h	2009-05-21 13:11:32.000000000 +0200
+++ vdr-1.7.9/config.h	2009-06-21 12:02:49.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 2.13 2009/05/21 11:11:32 kls Exp $
+ * $Id: config.h 2.14 2009/06/21 10:02:49 kls Exp $
  */
 
 #ifndef __CONFIG_H
@@ -22,13 +22,13 @@
 
 // VDR's own version number:
 
-#define VDRVERSION  "1.7.8"
-#define VDRVERSNUM   10708  // Version * 10000 + Major * 100 + Minor
+#define VDRVERSION  "1.7.9"
+#define VDRVERSNUM   10709  // Version * 10000 + Major * 100 + Minor
 
 // The plugin API's version number:
 
-#define APIVERSION  "1.7.8"
-#define APIVERSNUM   10708  // Version * 10000 + Major * 100 + Minor
+#define APIVERSION  "1.7.9"
+#define APIVERSNUM   10709  // 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.7.8/device.c vdr-1.7.9/device.c
--- vdr-1.7.8/device.c	2009-06-06 15:25:58.000000000 +0200
+++ vdr-1.7.9/device.c	2009-08-16 12:54:36.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 2.23 2009/06/06 13:25:58 kls Exp $
+ * $Id: device.c 2.25 2009/08/16 10:54:36 kls Exp $
  */
 
 #include "device.h"
@@ -1293,8 +1293,10 @@
      int l;
      while (const uchar *p = tsToPesVideo.GetPes(l)) {
            int w = PlayVideo(p, l);
-           if (w <= 0)
+           if (w <= 0) {
+              tsToPesVideo.SetRepeatLast();
               return w;
+              }
            }
      tsToPesVideo.Reset();
      }
@@ -1308,8 +1310,10 @@
   int l;
   if (const uchar *p = tsToPesAudio.GetPes(l)) {
      int w = PlayAudio(p, l, 0);
-     if (w <= 0)
+     if (w <= 0) {
+        tsToPesAudio.SetRepeatLast();
         return w;
+        }
      tsToPesAudio.Reset();
      }
   tsToPesAudio.PutTs(Data, Length);
diff -ruN vdr-1.7.8/eit.c vdr-1.7.9/eit.c
--- vdr-1.7.8/eit.c	2009-05-15 14:34:43.000000000 +0200
+++ vdr-1.7.9/eit.c	2009-06-21 15:46:20.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 2.5 2009/05/15 12:34:43 kls Exp $
+ * $Id: eit.c 2.6 2009/06/21 13:46:20 kls Exp $
  */
 
 #include "eit.h"
@@ -322,29 +322,30 @@
 
 cEitFilter::cEitFilter(void)
 {
-  Set(0x12, 0x4E, 0xFE);  // event info, actual(0x4E)/other(0x4F) TS, present/following
-  Set(0x12, 0x50, 0xF0);  // event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
-  Set(0x12, 0x60, 0xF0);  // event info, other  TS, schedule(0x60)/schedule for future days(0x6X)
-  Set(0x14, 0x70);        // TDT
+  Set(0x12, 0x40, 0xC0);  // event info now&next actual/other TS (0x4E/0x4F), future actual/other TS (0x5X/0x6X)
+  if (Setup.SetSystemTime && Setup.TimeTransponder)
+     Set(0x14, 0x70);     // TDT
 }
 
 void cEitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
 {
   switch (Pid) {
     case 0x12: {
-         cSchedulesLock SchedulesLock(true, 10);
-         cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
-         if (Schedules)
-            cEIT EIT(Schedules, Source(), Tid, Data);
-         else {
-            // If we don't get a write lock, let's at least get a read lock, so
-            // that we can set the running status and 'seen' timestamp (well, actually
-            // with a read lock we shouldn't be doing that, but it's only integers that
-            // get changed, so it should be ok)
-            cSchedulesLock SchedulesLock;
+         if (Tid >= 0x4E && Tid <= 0x6F) {
+            cSchedulesLock SchedulesLock(true, 10);
             cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
             if (Schedules)
-               cEIT EIT(Schedules, Source(), Tid, Data, true);
+               cEIT EIT(Schedules, Source(), Tid, Data);
+            else {
+               // If we don't get a write lock, let's at least get a read lock, so
+               // that we can set the running status and 'seen' timestamp (well, actually
+               // with a read lock we shouldn't be doing that, but it's only integers that
+               // get changed, so it should be ok)
+               cSchedulesLock SchedulesLock;
+               cSchedules *Schedules = (cSchedules *)cSchedules::Schedules(SchedulesLock);
+               if (Schedules)
+                  cEIT EIT(Schedules, Source(), Tid, Data, true);
+               }
             }
          }
          break;
diff -ruN vdr-1.7.8/menu.c vdr-1.7.9/menu.c
--- vdr-1.7.8/menu.c	2009-05-21 13:10:38.000000000 +0200
+++ vdr-1.7.9/menu.c	2009-06-21 11:56:06.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 2.8 2009/05/21 11:10:38 kls Exp $
+ * $Id: menu.c 2.9 2009/06/21 09:56:06 kls Exp $
  */
 
 #include "menu.h"
@@ -2133,6 +2133,7 @@
 void cMenuSetupBase::Store(void)
 {
   Setup = data;
+  cOsdProvider::UpdateOsdSize(true);
   Setup.Save();
 }
 
diff -ruN vdr-1.7.8/pat.c vdr-1.7.9/pat.c
--- vdr-1.7.8/pat.c	2008-07-06 16:01:32.000000000 +0200
+++ vdr-1.7.9/pat.c	2009-08-16 17:01:03.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: pat.c 2.2 2008/07/06 14:01:32 kls Exp $
+ * $Id: pat.c 2.4 2009/08/16 15:01:03 kls Exp $
  */
 
 #include "pat.h"
@@ -21,23 +21,23 @@
 class cCaDescriptor : public cListObject {
 private:
   int caSystem;
-  bool stream;
+  int esPid;
   int length;
   uchar *data;
 public:
-  cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data);
+  cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data);
   virtual ~cCaDescriptor();
   bool operator== (const cCaDescriptor &arg) const;
   int CaSystem(void) { return caSystem; }
-  int Stream(void) { return stream; }
+  int EsPid(void) { return esPid; }
   int Length(void) const { return length; }
   const uchar *Data(void) const { return data; }
   };
 
-cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data)
+cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
 {
   caSystem = CaSystem;
-  stream = Stream;
+  esPid = EsPid;
   length = Length + 6;
   data = MALLOC(uchar, length);
   data[0] = SI::CaDescriptorTag;
@@ -57,7 +57,7 @@
 
 bool cCaDescriptor::operator== (const cCaDescriptor &arg) const
 {
-  return length == arg.length && memcmp(data, arg.data, length) == 0;
+  return esPid == arg.esPid && length == arg.length && memcmp(data, arg.data, length) == 0;
 }
 
 // --- cCaDescriptors --------------------------------------------------------
@@ -77,8 +77,8 @@
   bool Is(int Source, int Transponder, int ServiceId);
   bool Is(cCaDescriptors * CaDescriptors);
   bool Empty(void) { return caDescriptors.Count() == 0; }
-  void AddCaDescriptor(SI::CaDescriptor *d, bool Stream);
-  int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
+  void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
+  int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
   const int *CaIds(void) { return caIds; }
   };
 
@@ -126,9 +126,9 @@
      }
 }
 
-void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, bool Stream)
+void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, int EsPid)
 {
-  cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), Stream, d->privateData.getLength(), d->privateData.getData());
+  cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), EsPid, d->privateData.getLength(), d->privateData.getData());
   for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
       if (*ca == *nca) {
          delete nca;
@@ -141,37 +141,39 @@
 #ifdef DEBUG_CA_DESCRIPTORS
   char buffer[1024];
   char *q = buffer;
-  q += sprintf(q, "CAM: %04X %5d %5d %04X %d -", source, transponder, serviceId, d->getCaType(), Stream);
+  q += sprintf(q, "CAM: %04X %5d %5d %04X %04X -", source, transponder, serviceId, d->getCaType(), EsPid);
   for (int i = 0; i < nca->Length(); i++)
       q += sprintf(q, " %02X", nca->Data()[i]);
   dsyslog(buffer);
 #endif
 }
 
-int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
+// EsPid is to select the "type" of CaDescriptor to be returned
+// >0 - CaDescriptor for the particular esPid
+// =0 - common CaDescriptor
+// <0 - all CaDescriptors regardless of type (old default)
+
+int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
 {
   if (!CaSystemIds || !*CaSystemIds)
      return 0;
   if (BufSize > 0 && Data) {
      int length = 0;
-     int IsStream = -1;
      for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
-         const int *caids = CaSystemIds;
-         do {
-            if (d->CaSystem() == *caids) {
-               if (length + d->Length() <= BufSize) {
-                  if (IsStream >= 0 && IsStream != d->Stream())
-                     dsyslog("CAM: different stream flag in CA descriptors");
-                  IsStream = d->Stream();
-                  memcpy(Data + length, d->Data(), d->Length());
-                  length += d->Length();
+         if (EsPid < 0 || d->EsPid() == EsPid) {
+            const int *caids = CaSystemIds;
+            do {
+               if (d->CaSystem() == *caids) {
+                  if (length + d->Length() <= BufSize) {
+                     memcpy(Data + length, d->Data(), d->Length());
+                     length += d->Length();
+                     }
+                  else
+                     return -1;
                   }
-               else
-                  return -1;
-               }
-            } while (*++caids);
+               } while (*++caids);
+            }
          }
-     StreamFlag = IsStream == 1;
      return length;
      }
   return -1;
@@ -187,7 +189,7 @@
       // Returns 0 if this is an already known descriptor,
       // 1 if it is an all new descriptor with actual contents,
       // and 2 if an existing descriptor was changed.
-  int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
+  int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
   };
 
 int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
@@ -208,22 +210,21 @@
   return CaDescriptors->Empty() ? 0 : 1;
 }
 
-int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
+int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
 {
   cMutexLock MutexLock(&mutex);
-  StreamFlag = false;
   for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
       if (ca->Is(Source, Transponder, ServiceId))
-         return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, StreamFlag);
+         return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, EsPid);
       }
   return 0;
 }
 
 cCaDescriptorHandler CaDescriptorHandler;
 
-int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
+int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
 {
-  return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, StreamFlag);
+  return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);
 }
 
 // --- cPatFilter ------------------------------------------------------------
@@ -322,7 +323,7 @@
         cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid());
         // Scan the common loop:
         for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
-            CaDescriptors->AddCaDescriptor(d, false);
+            CaDescriptors->AddCaDescriptor(d, 0);
             delete d;
             }
         // Scan the stream-specific loop:
@@ -333,6 +334,9 @@
         int Apids[MAXAPIDS + 1] = { 0 }; // these lists are zero-terminated
         int Dpids[MAXDPIDS + 1] = { 0 };
         int Spids[MAXSPIDS + 1] = { 0 };
+        uchar SubtitlingTypes[MAXSPIDS + 1] = { 0 };
+        uint16_t CompositionPageIds[MAXSPIDS + 1] = { 0 };
+        uint16_t AncillaryPageIds[MAXSPIDS + 1] = { 0 };
         char ALangs[MAXAPIDS][MAXLANGCODE2] = { "" };
         char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" };
         char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" };
@@ -341,11 +345,12 @@
         int NumDpids = 0;
         int NumSpids = 0;
         for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
+            int esPid = stream.getPid();
             switch (stream.getStreamType()) {
               case 1: // STREAMTYPE_11172_VIDEO
               case 2: // STREAMTYPE_13818_VIDEO
               case 0x1B: // MPEG4
-                      Vpid = stream.getPid();
+                      Vpid = esPid;
                       Ppid = pmt.getPCRPid();
                       Vtype = stream.getStreamType();
                       break;
@@ -353,7 +358,7 @@
               case 4: // STREAMTYPE_13818_AUDIO
                       {
                       if (NumApids < MAXAPIDS) {
-                         Apids[NumApids] = stream.getPid();
+                         Apids[NumApids] = esPid;
                          SI::Descriptor *d;
                          for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
                              switch (d->getDescriptorTag()) {
@@ -392,17 +397,20 @@
                       for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
                           switch (d->getDescriptorTag()) {
                             case SI::AC3DescriptorTag:
-                                 dpid = stream.getPid();
+                                 dpid = esPid;
                                  break;
                             case SI::SubtitlingDescriptorTag:
                                  if (NumSpids < MAXSPIDS) {
-                                    Spids[NumSpids] = stream.getPid();
+                                    Spids[NumSpids] = esPid;
                                     SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d;
                                     SI::SubtitlingDescriptor::Subtitling sub;
                                     char *s = SLangs[NumSpids];
                                     int n = 0;
                                     for (SI::Loop::Iterator it; sd->subtitlingLoop.getNext(sub, it); ) {
                                         if (sub.languageCode[0]) {
+                                           SubtitlingTypes[NumSpids] = sub.getSubtitlingType();
+                                           CompositionPageIds[NumSpids] = sub.getCompositionPageId();
+                                           AncillaryPageIds[NumSpids] = sub.getAncillaryPageId();
                                            if (n > 0)
                                               *s++ = '+';
                                            strn0cpy(s, I18nNormalizeLanguageCode(sub.languageCode), MAXLANGCODE1);
@@ -415,7 +423,7 @@
                                     }
                                  break;
                             case SI::TeletextDescriptorTag:
-                                 Tpid = stream.getPid();
+                                 Tpid = esPid;
                                  break;
                             case SI::ISO639LanguageDescriptorTag: {
                                  SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
@@ -438,13 +446,14 @@
               //default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX
               }
             for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
-                CaDescriptors->AddCaDescriptor(d, true);
+                CaDescriptors->AddCaDescriptor(d, esPid);
                 delete d;
                 }
             }
         if (Setup.UpdateChannels >= 2) {
            Channel->SetPids(Vpid, Ppid, Vtype, Apids, ALangs, Dpids, DLangs, Spids, SLangs, Tpid);
            Channel->SetCaIds(CaDescriptors->CaIds());
+           Channel->SetSubtitlingDescriptors(SubtitlingTypes, CompositionPageIds, AncillaryPageIds);
            }
         Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));
         }
diff -ruN vdr-1.7.8/pat.h vdr-1.7.9/pat.h
--- vdr-1.7.8/pat.h	2007-01-05 11:42:11.000000000 +0100
+++ vdr-1.7.9/pat.h	2009-06-14 13:14:00.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: pat.h 2.0 2007/01/05 10:42:11 kls Exp $
+ * $Id: pat.h 2.1 2009/06/14 11:14:00 kls Exp $
  */
 
 #ifndef __PAT_H
@@ -32,7 +32,7 @@
   void Trigger(void);
   };
 
-int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
+int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
          ///< Gets all CA descriptors for a given channel.
          ///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
          ///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors
diff -ruN vdr-1.7.8/recording.c vdr-1.7.9/recording.c
--- vdr-1.7.8/recording.c	2009-06-13 15:34:08.000000000 +0200
+++ vdr-1.7.9/recording.c	2009-08-16 12:39:43.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 2.16 2009/06/13 13:34:08 kls Exp $
+ * $Id: recording.c 2.17 2009/08/16 10:39:43 kls Exp $
  */
 
 #include "recording.h"
@@ -1156,7 +1156,7 @@
   if (recording) {
      cThreadLock DeletedRecordingsLock(&DeletedRecordings);
      Del(recording, false);
-     char *ext = strrchr(recording->FileName(), '.');
+     char *ext = strrchr(recording->fileName, '.');
      if (ext) {
         strncpy(ext, DELEXT, strlen(ext));
         recording->fileSizeMB = DirSizeMB(recording->FileName());
diff -ruN vdr-1.7.8/recording.h vdr-1.7.9/recording.h
--- vdr-1.7.8/recording.h	2009-05-23 14:14:42.000000000 +0200
+++ vdr-1.7.9/recording.h	2009-08-16 17:35:30.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 2.8 2009/05/23 12:14:42 kls Exp $
+ * $Id: recording.h 2.9 2009/08/16 15:35:30 kls Exp $
  */
 
 #ifndef __RECORDING_H
@@ -207,7 +207,7 @@
   };
 
 // The maximum size of a single frame (up to HDTV 1920x1080):
-#define MAXFRAMESIZE  (KILOBYTE(512) / TS_SIZE * TS_SIZE) // multiple of TS_SIZE to avoid breaking up TS packets
+#define MAXFRAMESIZE  (KILOBYTE(1024) / TS_SIZE * TS_SIZE) // multiple of TS_SIZE to avoid breaking up TS packets
 
 // The maximum file size is limited by the range that can be covered
 // with a 40 bit 'unsigned int', which is 1TB. The actual maximum value
diff -ruN vdr-1.7.8/remux.c vdr-1.7.9/remux.c
--- vdr-1.7.8/remux.c	2009-06-06 15:24:57.000000000 +0200
+++ vdr-1.7.9/remux.c	2009-08-16 17:13:42.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remux.c 2.24 2009/06/06 13:24:57 kls Exp $
+ * $Id: remux.c 2.26 2009/08/16 15:13:42 kls Exp $
  */
 
 #include "remux.h"
@@ -198,7 +198,7 @@
   return i;
 }
 
-int cPatPmtGenerator::MakeSubtitlingDescriptor(uchar *Target, const char *Language)
+int cPatPmtGenerator::MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId)
 {
   int i = 0;
   Target[i++] = SI::SubtitlingDescriptorTag;
@@ -206,11 +206,11 @@
   Target[i++] = *Language++;
   Target[i++] = *Language++;
   Target[i++] = *Language++;
-  Target[i++] = 0x00; // subtitling type
-  Target[i++] = 0x00; // composition page id hi
-  Target[i++] = 0x01; // composition page id lo
-  Target[i++] = 0x00; // ancillary page id hi
-  Target[i++] = 0x01; // ancillary page id lo
+  Target[i++] = SubtitlingType;
+  Target[i++] = CompositionPageId >> 8;
+  Target[i++] = CompositionPageId & 0xFF;
+  Target[i++] = AncillaryPageId >> 8;
+  Target[i++] = AncillaryPageId & 0xFF;
   IncEsInfoLength(i);
   return i;
 }
@@ -327,7 +327,7 @@
          }
      for (int n = 0; Channel->Spid(n); n++) {
          i += MakeStream(buf + i, 0x06, Channel->Spid(n));
-         i += MakeSubtitlingDescriptor(buf + i, Channel->Slang(n));
+         i += MakeSubtitlingDescriptor(buf + i, Channel->Slang(n), Channel->SubtitlingType(n), Channel->CompositionPageId(n), Channel->AncillaryPageId(n));
          }
 
      int sl = i - SectionLength - 2 + 4; // -2 = SectionLength storage, +4 = length of CRC
@@ -610,7 +610,8 @@
 cTsToPes::cTsToPes(void)
 {
   data = NULL;
-  size = length = offset = 0;
+  size = 0;
+  Reset();
 }
 
 cTsToPes::~cTsToPes()
@@ -641,6 +642,11 @@
 
 const uchar *cTsToPes::GetPes(int &Length)
 {
+  if (repeatLast) {
+     repeatLast = false;
+     Length = lastLength;
+     return lastData;
+     }
   if (offset < length && PesLongEnough(length)) {
      if (!PesHasLength(data)) // this is a video PES packet with undefined length
         offset = 6; // trigger setting PES length for initial slice
@@ -661,12 +667,16 @@
         p[4] = l / 256;
         p[5] = l & 0xFF;
         Length = l + 6;
+        lastLength = Length;
+        lastData = p;
         return p;
         }
      else {
         Length = PesLength(data);
         if (Length <= length) {
            offset = Length; // to make sure we break out in case of garbage data
+           lastLength = Length;
+           lastData = data;
            return data;
            }
         }
@@ -674,9 +684,17 @@
   return NULL;
 }
 
+void cTsToPes::SetRepeatLast(void)
+{
+  repeatLast = true;
+}
+
 void cTsToPes::Reset(void)
 {
   length = offset = 0;
+  lastData = NULL;
+  lastLength = 0;
+  repeatLast = false;
 }
 
 // --- Some helper functions for debugging -----------------------------------
diff -ruN vdr-1.7.8/remux.h vdr-1.7.9/remux.h
--- vdr-1.7.8/remux.h	2009-06-06 15:26:23.000000000 +0200
+++ vdr-1.7.9/remux.h	2009-08-16 17:15:33.000000000 +0200
@@ -4,7 +4,7 @@
  * See the main source file 'vdr.c' for copyright information and
  * how to reach the author.
  *
- * $Id: remux.h 2.17 2009/06/06 13:26:23 kls Exp $
+ * $Id: remux.h 2.19 2009/08/16 15:15:33 kls Exp $
  */
 
 #ifndef __REMUX_H
@@ -168,7 +168,7 @@
 protected:
   int MakeStream(uchar *Target, uchar Type, int Pid);
   int MakeAC3Descriptor(uchar *Target);
-  int MakeSubtitlingDescriptor(uchar *Target, const char *Language);
+  int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId);
   int MakeLanguageDescriptor(uchar *Target, const char *Language);
   int MakeCRC(uchar *Target, const uchar *Data, int Length);
   void GeneratePmtPid(cChannel *Channel);
@@ -252,6 +252,9 @@
   int size;
   int length;
   int offset;
+  uchar *lastData;
+  int lastLength;
+  bool repeatLast;
 public:
   cTsToPes(void);
   ~cTsToPes();
@@ -279,6 +282,9 @@
        ///< TS packet that will be given to PutTs() has the "payload start" flag
        ///< set, because this is the only way to determine the end of a video PES
        ///< packet.
+  void SetRepeatLast(void);
+       ///< Makes the next call to GetPes() return exactly the same data as the
+       ///< last one (provided there was no call to Reset() in the meantime).
   void Reset(void);
        ///< Resets the converter. This needs to be called after a PES packet has
        ///< been fetched by a call to GetPes(), and before the next call to
diff -ruN vdr-1.7.8/timers.c vdr-1.7.9/timers.c
--- vdr-1.7.8/timers.c	2008-04-13 14:41:41.000000000 +0200
+++ vdr-1.7.9/timers.c	2009-08-09 14:43:20.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 2.1 2008/04/13 12:41:41 kls Exp $
+ * $Id: timers.c 2.3 2009/08/09 12:43:20 kls Exp $
  */
 
 #include "timers.h"
@@ -51,6 +51,11 @@
   event = NULL;
   if (Instant && channel)
      snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name());
+  if (VfatFileSystem && (Utf8StrLen(file) > VFAT_MAX_FILENAME)) {
+     dsyslog("timer file name too long for VFAT file system: '%s'", file);
+     file[Utf8SymChars(file, VFAT_MAX_FILENAME)] = 0;
+     dsyslog("timer file name truncated to '%s'", file);
+     }
 }
 
 cTimer::cTimer(const cEvent *Event)
@@ -83,6 +88,11 @@
   const char *Title = Event->Title();
   if (!isempty(Title))
      Utf8Strn0Cpy(file, Event->Title(), sizeof(file));
+  if (VfatFileSystem && (Utf8StrLen(file) > VFAT_MAX_FILENAME)) {
+     dsyslog("timer file name too long for VFAT file system: '%s'", file);
+     file[Utf8SymChars(file, VFAT_MAX_FILENAME)] = 0;
+     dsyslog("timer file name truncated to '%s'", file);
+     }
   aux = NULL;
   event = NULL; // let SetEvent() be called to get a log message
 }
@@ -296,13 +306,13 @@
            p++;
         else
            p = filebuffer;
-        if (strlen(p) > VFAT_MAX_FILENAME) {
+        if (Utf8StrLen(p) > VFAT_MAX_FILENAME) {
            dsyslog("timer file name too long for VFAT file system: '%s'", p);
-           p[VFAT_MAX_FILENAME] = 0;
+           p[Utf8SymChars(p, VFAT_MAX_FILENAME)] = 0;
            dsyslog("timer file name truncated to '%s'", p);
            }
         }
-     Utf8Strn0Cpy(file, filebuffer, MaxFileName);
+     Utf8Strn0Cpy(file, filebuffer, sizeof(file));
      strreplace(file, '|', ':');
      if (isnumber(channelbuffer))
         channel = Channels.GetByNumber(atoi(channelbuffer));
@@ -463,7 +473,7 @@
 
 bool cTimer::Expired(void) const
 {
-  return IsSingleEvent() && !Recording() && StopTime() + EXPIRELATENCY <= time(NULL) && (!HasFlags(tfVps) || !event);
+  return IsSingleEvent() && !Recording() && StopTime() + EXPIRELATENCY <= time(NULL) && (!HasFlags(tfVps) || !event || !event->Vps());
 }
 
 time_t cTimer::StartTime(void) const
diff -ruN vdr-1.7.8/vdr.1 vdr-1.7.9/vdr.1
--- vdr-1.7.8/vdr.1	2009-01-18 12:05:56.000000000 +0100
+++ vdr-1.7.9/vdr.1	2009-08-16 12:28:39.000000000 +0200
@@ -8,7 +8,7 @@
 .\" License as specified in the file COPYING that comes with the
 .\" vdr distribution.
 .\"
-.\" $Id: vdr.1 2.1 2009/01/18 11:05:56 kls Exp $
+.\" $Id: vdr.1 2.2 2009/08/16 10:28:39 kls Exp $
 .\"
 .TH vdr 1 "10 Feb 2008" "1.6" "Video Disk Recorder"
 .SH NAME
@@ -205,16 +205,16 @@
 SVDRP host configuration, defining which hosts or networks are given
 access to the SVDRP port.
 .TP
-.I marks.vdr
+.I marks
 Contains the editing marks defined for a recording.
 .TP
-.I info.vdr
+.I info
 Contains a description of the recording.
 .TP
-.I resume.vdr
+.I resume
 Contains the index into the recording where the last replay session left off.
 .TP
-.I index.vdr
+.I index
 Contains the file number, offset and type of each frame of the recording.
 .TP
 .I remote.conf
@@ -223,7 +223,7 @@
 .I keymacros.conf
 Contains user defined remote control key macros.
 .TP
-.IR 001.vdr\  ...\  255.vdr
+.IR 00001.ts\  ...\  65535.ts
 The actual data files of a recording.
 .TP
 .I epg.data
