diff -ruN vdr-1.6.0-sl/Makefile vdr-1.6.0-sl-ttxtsubs/Makefile
--- vdr-1.6.0-sl/Makefile	2010-04-19 20:36:26.000000000 +0300
+++ vdr-1.6.0-sl-ttxtsubs/Makefile	2010-04-19 21:37:52.000000000 +0300
@@ -64,6 +64,8 @@
        timers.o tools.o transfer.o vdr.o videodir.o
 endif
 
+OBJS += vdrttxtsubshooks.o
+
 ifndef NO_KBD
 DEFINES += -DREMOTE_KBD
 endif
diff -ruN vdr-1.6.0-sl/dvbplayer.c vdr-1.6.0-sl-ttxtsubs/dvbplayer.c
--- vdr-1.6.0-sl/dvbplayer.c	2010-04-17 20:19:02.000000000 +0300
+++ vdr-1.6.0-sl-ttxtsubs/dvbplayer.c	2010-04-19 21:37:52.000000000 +0300
@@ -14,6 +14,7 @@
 #include "ringbuffer.h"
 #include "thread.h"
 #include "tools.h"
+#include "vdrttxtsubshooks.h"
 
 // --- cBackTrace ------------------------------------------------------------
 
@@ -312,6 +313,32 @@
   firstPacket = true;
 }
 
+static void StripExtendedPackets(uchar *b, int Length)
+{
+  for (int i = 0; i < Length - 6; i++) {
+      if (b[i] == 0x00 && b[i + 1] == 0x00 && b[i + 2] == 0x01) {
+         uchar c = b[i + 3];
+         int l = b[i + 4] * 256 + b[i + 5] + 6;
+         switch (c) {
+           case 0xBD: // dolby
+                // EBU Teletext data, ETSI EN 300 472
+                if (b[i + 8] == 0x24 && b[i + 45] >= 0x10 && b[i + 45] < 0x20) {
+                   cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData(&b[i], l);
+                   // continue with deleting the data - otherwise it disturbs DVB replay
+                   int n = l;
+                   for (int j = i; j < Length && n--; j++)
+                       b[j] = 0x00;
+                   }
+                break;
+           default:
+                break;
+           }
+         if (l)
+            i += l - 1; // the loop increments, too!
+         }
+      }
+}
+
 bool cDvbPlayer::NextFile(uchar FileNumber, int FileOffset)
 {
   if (FileNumber > 0)
@@ -503,6 +530,7 @@
                     }
                  }
               if (p) {
+                 StripExtendedPackets(p, pc);
                  int w = PlayPes(p, pc, playMode != pmPlay);
                  if (w > 0) {
                     p += w;
diff -ruN vdr-1.6.0-sl/menu.c vdr-1.6.0-sl-ttxtsubs/menu.c
--- vdr-1.6.0-sl/menu.c	2010-04-17 20:51:39.000000000 +0300
+++ vdr-1.6.0-sl-ttxtsubs/menu.c	2010-04-19 21:37:52.000000000 +0300
@@ -28,6 +28,7 @@
 #include "themes.h"
 #include "timers.h"
 #include "transfer.h"
+#include "vdrttxtsubshooks.h"
 #include "videodir.h"
 #ifdef __APPLE__
 #include "darwinutils.h"
@@ -3818,8 +3819,10 @@
   isyslog("record %s", fileName);
   if (MakeDirs(fileName, true)) {
      const cChannel *ch = timer->Channel();
-     recorder = new cRecorder(fileName, ch->GetChannelID(), timer->Priority(), ch->Vpid(), ch->Apids(), ch->Dpids(), ch->Spids());
+     cTtxtSubsRecorderBase *subsRecorder = cVDRTtxtsubsHookListener::Hook()->NewTtxtSubsRecorder(device, ch);
+     recorder = new cRecorder(fileName, ch->GetChannelID(), timer->Priority(), ch->Vpid(), ch->Apids(), ch->Dpids(), ch->Spids(), subsRecorder);
      if (device->AttachReceiver(recorder)) {
+        if (subsRecorder) subsRecorder->DeviceAttach();
         Recording.WriteInfo();
         cStatus::MsgRecording(device, Recording.Name(), Recording.FileName(), true);
         if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
diff -ruN vdr-1.6.0-sl/osd.c vdr-1.6.0-sl-ttxtsubs/osd.c
--- vdr-1.6.0-sl/osd.c	2010-04-17 20:19:02.000000000 +0300
+++ vdr-1.6.0-sl-ttxtsubs/osd.c	2010-04-19 21:37:52.000000000 +0300
@@ -15,6 +15,7 @@
 #include <sys/stat.h>
 #include <sys/unistd.h>
 #include "tools.h"
+#include "vdrttxtsubshooks.h"
 
 // --- cPalette --------------------------------------------------------------
 
diff -ruN vdr-1.6.0-sl/recorder.c vdr-1.6.0-sl-ttxtsubs/recorder.c
--- vdr-1.6.0-sl/recorder.c	2010-04-17 20:19:02.000000000 +0300
+++ vdr-1.6.0-sl-ttxtsubs/recorder.c	2010-04-19 21:37:52.000000000 +0300
@@ -11,6 +11,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <stdint.h>
 #include "shutdown.h"
 
 #define RECORDERBUFSIZE  MEGABYTE(5)
@@ -26,6 +27,7 @@
 
 class cFileWriter : public cThread {
 private:
+  cTtxtSubsRecorderBase *ttxtSubsRecorder;
   cRemux *remux;
   cFileName *fileName;
   cIndexFile *index;
@@ -38,13 +40,14 @@
 protected:
   virtual void Action(void);
 public:
-  cFileWriter(const char *FileName, cRemux *Remux);
+  cFileWriter(const char *FileName, cRemux *Remux, cTtxtSubsRecorderBase *tsr);
   virtual ~cFileWriter();
   };
 
-cFileWriter::cFileWriter(const char *FileName, cRemux *Remux)
+cFileWriter::cFileWriter(const char *FileName, cRemux *Remux, cTtxtSubsRecorderBase *tsr)
 :cThread("file writer")
 {
+  ttxtSubsRecorder = tsr;
   fileName = NULL;
   remux = Remux;
   index = NULL;
@@ -67,6 +70,8 @@
   Cancel(3);
   delete index;
   delete fileName;
+  if (ttxtSubsRecorder)
+     delete ttxtSubsRecorder;
 }
 
 bool cFileWriter::RunningLowOnDiskSpace(void)
@@ -111,6 +116,16 @@
                  }
               fileSize += Count;
               remux->Del(Count);
+              // not sure if the pictureType test is needed, but it seems we can get
+              // incomplete pes packets from remux if we are not getting pictures?
+              if (ttxtSubsRecorder && pictureType != NO_PICTURE) {
+                 uint8_t *subsp;
+                 size_t len;
+                 if (ttxtSubsRecorder->GetPacket(&subsp, &len)) {
+                    recordFile->Write(subsp, len);
+                    fileSize += len;
+                    }
+                 }
               }
            else
               break;
@@ -126,7 +141,7 @@
 
 // --- cRecorder -------------------------------------------------------------
 
-cRecorder::cRecorder(const char *FileName, tChannelID ChannelID, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids)
+cRecorder::cRecorder(const char *FileName, tChannelID ChannelID, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids, cTtxtSubsRecorderBase *tsr)
 :cReceiver(ChannelID, Priority, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids)
 ,cThread("recording")
 {
@@ -137,7 +152,7 @@
   ringBuffer = new cRingBufferLinear(RECORDERBUFSIZE, TS_SIZE * 2, true, "Recorder");
   ringBuffer->SetTimeouts(0, 100);
   remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids, true);
-  writer = new cFileWriter(FileName, remux);
+  writer = new cFileWriter(FileName, remux, tsr);
 }
 
 cRecorder::~cRecorder()
diff -ruN vdr-1.6.0-sl/recorder.h vdr-1.6.0-sl-ttxtsubs/recorder.h
--- vdr-1.6.0-sl/recorder.h	2010-04-17 20:19:02.000000000 +0300
+++ vdr-1.6.0-sl-ttxtsubs/recorder.h	2010-04-19 21:37:52.000000000 +0300
@@ -15,6 +15,7 @@
 #include "remux.h"
 #include "ringbuffer.h"
 #include "thread.h"
+#include "vdrttxtsubshooks.h"
 
 class cFileWriter;
 
@@ -28,7 +29,7 @@
   virtual void Receive(uchar *Data, int Length);
   virtual void Action(void);
 public:
-  cRecorder(const char *FileName, tChannelID ChannelID, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids);
+  cRecorder(const char *FileName, tChannelID ChannelID, int Priority, int VPid, const int *APids, const int *DPids, const int *SPids, cTtxtSubsRecorderBase *tsr);
                // Creates a new recorder for the channel with the given ChannelID and
                // the given Priority that will record the given PIDs into the file FileName.
   virtual ~cRecorder();
diff -ruN vdr-1.6.0-sl/vdrttxtsubshooks.c vdr-1.6.0-sl-ttxtsubs/vdrttxtsubshooks.c
--- vdr-1.6.0-sl/vdrttxtsubshooks.c	1970-01-01 02:00:00.000000000 +0200
+++ vdr-1.6.0-sl-ttxtsubs/vdrttxtsubshooks.c	2010-04-19 21:37:52.000000000 +0300
@@ -0,0 +1,44 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "vdrttxtsubshooks.h"
+
+// XXX Really should be a list...
+static cVDRTtxtsubsHookListener *gListener;
+
+// ------ class cVDRTtxtsubsHookProxy ------
+
+class cVDRTtxtsubsHookProxy : public cVDRTtxtsubsHookListener
+{
+ public:
+  virtual void HideOSD(void) { if(gListener) gListener->HideOSD(); };
+  virtual void ShowOSD(void) { if(gListener) gListener->ShowOSD(); };
+  virtual void PlayerTeletextData(uint8_t *p, int length)
+    { if(gListener) gListener->PlayerTeletextData(p, length); };
+  virtual cTtxtSubsRecorderBase *NewTtxtSubsRecorder(cDevice *dev, const cChannel *ch)
+    { if(gListener) return gListener->NewTtxtSubsRecorder(dev, ch); else return NULL; };
+};
+
+
+// ------ class cVDRTtxtsubsHookListener ------
+
+cVDRTtxtsubsHookListener::~cVDRTtxtsubsHookListener()
+{
+  gListener = 0;
+}
+
+void cVDRTtxtsubsHookListener::HookAttach(void)
+{
+  gListener = this;
+  //printf("cVDRTtxtsubsHookListener::HookAttach\n");
+}
+
+static cVDRTtxtsubsHookProxy gProxy;
+
+cVDRTtxtsubsHookListener *cVDRTtxtsubsHookListener::Hook(void)
+{
+  return &gProxy;
+}
+
diff -ruN vdr-1.6.0-sl/vdrttxtsubshooks.h vdr-1.6.0-sl-ttxtsubs/vdrttxtsubshooks.h
--- vdr-1.6.0-sl/vdrttxtsubshooks.h	1970-01-01 02:00:00.000000000 +0200
+++ vdr-1.6.0-sl-ttxtsubs/vdrttxtsubshooks.h	2010-04-19 21:37:52.000000000 +0300
@@ -0,0 +1,36 @@
+
+#ifndef __VDRTTXTSUBSHOOKS_H
+#define __VDRTTXTSUBSHOOKS_H
+
+class cDevice;
+class cChannel;
+
+#define VDRTTXTSUBSHOOKS
+
+class cTtxtSubsRecorderBase {
+ public:
+  virtual ~cTtxtSubsRecorderBase() {};
+
+  // returns a PES packet if there is data to add to the recording
+  virtual uint8_t *GetPacket(uint8_t **buf, size_t *len) { return NULL; };
+  virtual void DeviceAttach(void) {};
+};
+
+class cVDRTtxtsubsHookListener {
+ public:
+  cVDRTtxtsubsHookListener(void) {};
+  virtual ~cVDRTtxtsubsHookListener();
+
+  void HookAttach(void);
+  
+  virtual void HideOSD(void) {};
+  virtual void ShowOSD(void) {};
+  virtual void PlayerTeletextData(uint8_t *p, int length) {};
+  virtual cTtxtSubsRecorderBase *NewTtxtSubsRecorder(cDevice *dev, const cChannel *ch)
+    { return NULL; };
+
+  // used by VDR to call hook listeners
+  static cVDRTtxtsubsHookListener *Hook(void);
+};
+
+#endif
