summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Grimm <tobias@e-tobi.loc>2008-12-13 11:01:34 +0100
committerTobias Grimm <tobias@e-tobi.loc>2008-12-13 11:01:34 +0100
commite5d1aacca2020e63dbaf320ba8b1de61746ad410 (patch)
tree0e267f716f34700a439971926fdc79b0172a0f38
parent88012c106b8310507e872c72544f423433bac5d2 (diff)
downloadvdr-plugin-ttxtsubs-0.0.5pre1.tar.gz
vdr-plugin-ttxtsubs-0.0.5pre1.tar.bz2
- New features:v0.0.5pre1
- More than one language can be chosen, they are used in order of preference - Handles languages with two ISO 639-2 identifiers (as ger/deu, fre/fra) - Subtitles can now be turned on or off - Optional main menu alternative for easy access - Selectable vertical position of text for 4:3/Anamorphic or Letterbox - Left, Center or Right horizontal position of text - Remapping option for those French channels that incorrectly sends teletext page numbers in decimal instead of hexadecimal. Very moderate remapping done at the moment, I hope it is enough. - Subtitles are now recorded with their PTS (timestamps). Not that the timestamps are completely wrong on some channels, this may confuse uncareful subtitle extracting software. - Included patch for VDR 1.3.5 - untested! - Bugs fixed: - Fixed a net-to-host-order bug in the si parser that could make it incorrectly think that there are no subtitles on a channel. Thanks to Nicolas "tarass"! - Fixed a bit swapping bug causing incorrect character encoding for some languages. Thanks to Nicolas "tarass"!
-rw-r--r--HISTORY23
-rw-r--r--Makefile4
-rw-r--r--README2
-rw-r--r--VDR-1.3.5.patch251
-rw-r--r--siinfo.c73
-rw-r--r--siinfo.h4
-rw-r--r--teletext-chars.h4
-rw-r--r--teletext.c2
-rw-r--r--ttxtsubs.c477
-rw-r--r--ttxtsubsdisplay.c91
-rw-r--r--ttxtsubsdisplayer.c48
-rw-r--r--ttxtsubsdisplayer.h5
-rw-r--r--ttxtsubsfilter.c5
-rw-r--r--ttxtsubsglobals.h50
-rw-r--r--ttxtsubsreceiver.c44
-rw-r--r--ttxtsubsreceiver.h8
-rw-r--r--ttxtsubsrecorder.c21
-rw-r--r--ttxtsubsrecorder.h2
18 files changed, 909 insertions, 205 deletions
diff --git a/HISTORY b/HISTORY
index fab4efd..81e373d 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,29 @@
VDR Plugin 'ttxtsubs' Revision History
--------------------------------------
+2004-03-01: Version 0.0.5pre1
+
+- New features:
+ - More than one language can be chosen, they are used in order of preference
+ - Handles languages with two ISO 639-2 identifiers (as ger/deu, fre/fra)
+ - Subtitles can now be turned on or off
+ - Optional main menu alternative for easy access
+ - Selectable vertical position of text for 4:3/Anamorphic or Letterbox
+ - Left, Center or Right horizontal position of text
+ - Remapping option for those French channels that incorrectly
+ sends teletext page numbers in decimal instead of hexadecimal.
+ Very moderate remapping done at the moment, I hope it is enough.
+ - Subtitles are now recorded with their PTS (timestamps). Not that
+ the timestamps are completely wrong on some channels, this
+ may confuse uncareful subtitle extracting software.
+ - Included patch for VDR 1.3.5 - untested!
+- Bugs fixed:
+ - Fixed a net-to-host-order bug in the si parser that could make it
+ incorrectly think that there are no subtitles on a channel.
+ Thanks to Nicolas "tarass"!
+ - Fixed a bit swapping bug causing incorrect character encoding for
+ some languages. Thanks to Nicolas "tarass"!
+
2003-09-26: Version 0.0.4b
- Fix patch for VDR 1.2.5
- Minor bug fix for dxr3 display
diff --git a/Makefile b/Makefile
index 92e053c..3d2da80 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for a Video Disk Recorder plugin
#
-# $Id: Makefile,v 1.18 2003/07/16 04:01:44 ragge Exp $
+# $Id: Makefile,v 1.19 2004/03/01 04:41:13 ragge Exp ragge $
# The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin.
@@ -83,7 +83,7 @@ dist: clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@echo Distribution package created as $(PACKAGE).tgz
-bup: clean patch
+bup: clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@cp -a $(SOURCEFILES) RCS $(TMPDIR)/$(ARCHIVE)
diff --git a/README b/README
index 5b58dee..2479f06 100644
--- a/README
+++ b/README
@@ -2,7 +2,7 @@ This is a "plugin" for the Video Disk Recorder (VDR).
Written by: Ragnar Sundblad <ragge@nada.kth.se>
-Project's homepage: -
+Project's homepage: http://www.nada.kth.se/~ragge/vdr/ttxtsubs/
Latest version available at: ftp://ftp.nada.kth.se/pub/home/ragge/vdr/
diff --git a/VDR-1.3.5.patch b/VDR-1.3.5.patch
new file mode 100644
index 0000000..8a1a32c
--- /dev/null
+++ b/VDR-1.3.5.patch
@@ -0,0 +1,251 @@
+diff -upr ./DIST/Makefile ./Makefile
+--- ./DIST/Makefile 2004-01-18 15:16:53.000000000 +0100
++++ ./Makefile 2004-03-01 05:19:59.000000000 +0100
+@@ -37,7 +37,8 @@ OBJS = audio.o channels.o ci.o config.o
+ dvbplayer.o dvbspu.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\
+ lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o rcu.o\
+ receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o sources.o\
+- spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o
++ spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o\
++ vdrttxtsubshooks.o
+
+ FIXFONT_ISO8859_1 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
+ OSDFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
+diff -upr ./DIST/dvbplayer.c ./dvbplayer.c
+--- ./DIST/dvbplayer.c 2003-10-18 13:31:54.000000000 +0200
++++ ./dvbplayer.c 2004-03-01 05:18:15.000000000 +0100
+@@ -14,6 +14,7 @@
+ #include "ringbuffer.h"
+ #include "thread.h"
+ #include "tools.h"
++#include "vdrttxtsubshooks.h"
+
+ // --- cBackTrace ----------------------------------------------------------
+
+@@ -323,6 +324,12 @@ void cDvbPlayer::StripAudioPackets(uchar
+ int l = b[i + 4] * 256 + b[i + 5] + 6;
+ switch (c) {
+ case 0xBD: // dolby
++#ifdef VDRTTXTSUBSHOOKS
++ if (b[i + 8] == 0x24 && b[i + 45] >= 0x10 && b[i + 45] < 0x20) {
++ break; // run these through the ring buffer to get somewhat correct
++ // timing for the subtitles
++ } else
++#endif
+ if (Except)
+ PlayAudio(&b[i], l);
+ // continue with deleting the data - otherwise it disturbs DVB replay
+@@ -349,6 +356,40 @@ void cDvbPlayer::StripAudioPackets(uchar
+ }
+ }
+
++#ifdef VDRTTXTSUBSHOOKS
++static void StripTtxtPackets(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
++ {
++ if (b[i + 8] == 0x24 && b[i + 45] >= 0x10 && b[i + 45] < 0x20) {
++ // EBU Teletext data, ETSI EN 300 472
++ 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!
++ }
++ /*XXX
++ else
++ esyslog("ERROR: broken packet header");
++ XXX*/
++ }
++}
++#endif
++
+ bool cDvbPlayer::NextFile(uchar FileNumber, int FileOffset)
+ {
+ if (FileNumber > 0)
+@@ -522,6 +563,11 @@ void cDvbPlayer::Action(void)
+ StripAudioPackets(p, pc, AudioTrack);
+ }
+ }
++#ifdef VDRTTXTSUBSHOOKS
++ // pick out the teletext packets here
++ if(p)
++ StripTtxtPackets((uchar *) p, pc);
++#endif
+ if (p) {
+ int w = PlayVideo(p, pc);
+ if (w > 0) {
+diff -upr ./DIST/menu.c ./menu.c
+--- ./DIST/menu.c 2004-02-29 15:11:16.000000000 +0100
++++ ./menu.c 2004-03-01 05:18:15.000000000 +0100
+@@ -3104,8 +3104,18 @@ cRecordControl::cRecordControl(cDevice *
+ isyslog("record %s", fileName);
+ if (MakeDirs(fileName, true)) {
+ const cChannel *ch = timer->Channel();
++#ifdef VDRTTXTSUBSHOOKS
++ cTtxtSubsRecorderBase *subsRecorder = cVDRTtxtsubsHookListener::Hook()
++ ->NewTtxtSubsRecorder(device, ch);
++ recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apid1(), ch->Apid2(), ch->Dpid1(), ch->Dpid2(), subsRecorder);
++#else
+ recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apid1(), ch->Apid2(), ch->Dpid1(), ch->Dpid2());
++#endif
+ if (device->AttachReceiver(recorder)) {
++#ifdef VDRTTXTSUBSHOOKS
++ if(subsRecorder)
++ subsRecorder->DeviceAttach();
++#endif
+ Recording.WriteSummary();
+ cStatus::MsgRecording(device, Recording.Name());
+ if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
+diff -upr ./DIST/menu.h ./menu.h
+--- ./DIST/menu.h 2004-02-15 15:11:28.000000000 +0100
++++ ./menu.h 2004-03-01 05:18:15.000000000 +0100
+@@ -15,6 +15,7 @@
+ #include "epg.h"
+ #include "osd.h"
+ #include "dvbplayer.h"
++#include "vdrttxtsubshooks.h"
+ #include "recorder.h"
+ #include "recording.h"
+
+diff -upr ./DIST/osd.c ./osd.c
+--- ./DIST/osd.c 2003-06-04 18:13:00.000000000 +0200
++++ ./osd.c 2004-03-01 05:18:15.000000000 +0100
+@@ -12,6 +12,7 @@
+ #include "device.h"
+ #include "i18n.h"
+ #include "status.h"
++#include "vdrttxtsubshooks.h"
+
+ // --- cOsd ------------------------------------------------------------------
+
+@@ -62,6 +63,10 @@ void cOsd::SetColor(eDvbColor colorFg, e
+
+ cOsdBase *cOsd::OpenRaw(int x, int y)
+ {
++#ifdef VDRTTXTSUBSHOOKS
++ // OSD_HOOK_2 - Information to Checkpatch.sh
++ cVDRTtxtsubsHookListener::Hook()->HideOSD();
++#endif
+ #ifdef DEBUG_OSD
+ return NULL;
+ #else
+@@ -138,6 +143,9 @@ void cOsd::Close(void)
+ delete osd;
+ osd = NULL;
+ #endif
++#ifdef VDRTTXTSUBSHOOKS
++ cVDRTtxtsubsHookListener::Hook()->ShowOSD();
++#endif
+ }
+
+ void cOsd::Clear(void)
+diff -upr ./DIST/recorder.c ./recorder.c
+--- ./DIST/recorder.c 2003-10-18 13:35:02.000000000 +0200
++++ ./recorder.c 2004-03-01 05:18:15.000000000 +0100
+@@ -10,6 +10,8 @@
+ #include <stdarg.h>
+ #include <stdio.h>
+ #include <unistd.h>
++#include <stdint.h>
++#include "vdrttxtsubshooks.h"
+ #include "recorder.h"
+
+ // The size of the array used to buffer video data:
+@@ -23,7 +25,11 @@
+ #define MINFREEDISKSPACE (512) // MB
+ #define DISKCHECKINTERVAL 100 // seconds
+
++#ifdef VDRTTXTSUBSHOOKS
++cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2, cTtxtSubsRecorderBase *tsr)
++#else
+ cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2)
++#endif
+ :cReceiver(Ca, Priority, 5, VPid, APid1, APid2, DPid1, DPid2)
+ ,cThread("recording")
+ {
+@@ -35,6 +41,9 @@ cRecorder::cRecorder(const char *FileNam
+ fileSize = 0;
+ active = false;
+ lastDiskSpaceCheck = time(NULL);
++#ifdef VDRTTXTSUBSHOOKS
++ ttxtSubsRecorder = tsr;
++#endif
+
+ // Make sure the disk is up and running:
+
+@@ -56,6 +65,10 @@ cRecorder::cRecorder(const char *FileNam
+ cRecorder::~cRecorder()
+ {
+ Detach();
++#ifdef VDRTTXTSUBSHOOKS
++ if(ttxtSubsRecorder)
++ delete ttxtSubsRecorder;
++#endif
+ delete index;
+ delete fileName;
+ delete remux;
+@@ -128,6 +141,19 @@ void cRecorder::Action(void)
+ break;
+ }
+ fileSize += Result;
++#ifdef VDRTTXTSUBSHOOKS
++ // 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)) {
++ safe_write(recordFile, subsp, len);
++ fileSize += len;
++ // fprintf(stderr, "cRecorder::Action: Wrote ttxtsubs data len %d\n", len); // XXX
++ }
++ }
++#endif
+ }
+ else
+ break;
+diff -upr ./DIST/recorder.h ./recorder.h
+--- ./DIST/recorder.h 2002-06-08 11:35:03.000000000 +0200
++++ ./recorder.h 2004-03-01 05:18:15.000000000 +0100
+@@ -15,6 +15,7 @@
+ #include "remux.h"
+ #include "ringbuffer.h"
+ #include "thread.h"
++#include "vdrttxtsubshooks.h"
+
+ class cRecorder : public cReceiver, cThread {
+ private:
+@@ -29,12 +30,19 @@ private:
+ time_t lastDiskSpaceCheck;
+ bool RunningLowOnDiskSpace(void);
+ bool NextFile(void);
++#ifdef VDRTTXTSUBSHOOKS
++ cTtxtSubsRecorderBase *ttxtSubsRecorder;
++#endif
+ protected:
+ virtual void Activate(bool On);
+ virtual void Receive(uchar *Data, int Length);
+ virtual void Action(void);
+ public:
++#ifdef VDRTTXTSUBSHOOKS
++ cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2, cTtxtSubsRecorderBase *tsr);
++#else
+ cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2);
++#endif
+ // Creates a new recorder that requires conditional access Ca, has
+ // the given Priority and will record the given PIDs into the file FileName.
+ virtual ~cRecorder();
diff --git a/siinfo.c b/siinfo.c
index cd14c8b..5ef3eb0 100644
--- a/siinfo.c
+++ b/siinfo.c
@@ -22,6 +22,8 @@
#include "linux/dvb/dmx.h"
#include "siinfo.h"
+#include "ttxtsubsglobals.h"
+
#define DESCR_TELETEXT 0x56
#define DESCR_DVBSUBTITLES 0x59
@@ -329,6 +331,23 @@ static void addpageinfo(struct ttxtinfo *info, uint16_t pid, struct ttxt_descr *
pa->type = descr->d[descr_index].type_mag >> 3;
pa->mag = descr->d[descr_index].type_mag & 0x7;
pa->page = descr->d[descr_index].page_no;
+
+ if(globals.frenchSpecial()) {
+ /* By some silly reason some French channels (Canal+ and CanalSatellite)
+ announce subtitles with the page number in decimal, for example
+ page 859 when they really are on page 889. */
+ uint8_t newpage = pa->page;
+ if(pa->page >= 0x50 && pa->page <= 0x59)
+ newpage += 0x30;
+ if(pa->page != newpage) {
+ uint8_t mag = pa->mag;
+ if(mag == 0)
+ mag = 8;
+ fprintf(stderr, "Warning: Remapped page number %01x%02x to %01x%02x!\n",
+ mag, pa->page, mag, newpage);
+ pa->page = newpage;
+ }
+ }
}
@@ -343,7 +362,7 @@ static int HasVPID(int vpid, char **pmtsects, int numsects)
char *end;
psect = (struct PMT_sect *) pmtsects[i];
- end = pmtsects[i] + (psect->syntax_len & 0x3ff) - 7;
+ end = pmtsects[i] + (ntohs(psect->syntax_len) & 0x3ff) - 7;
// skip extra program info
sp = ((char *) &(psect->s)) + (ntohs(psect->res_program_info_length) & 0xfff);
@@ -374,7 +393,7 @@ static void ExtractTtxtInfo(char **pmtsects, int numsects, struct ttxtinfo *info
char *end;
psect = (struct PMT_sect *) pmtsects[i];
- end = pmtsects[i] + (psect->syntax_len & 0x3ff) - 7;
+ end = pmtsects[i] + (ntohs(psect->syntax_len) & 0x3ff) - 7;
// skip extra program info
sp = ((char *) &(psect->s)) + (ntohs(psect->res_program_info_length) & 0xfff);
@@ -572,52 +591,47 @@ void DupTtxtInfo(struct ttxtinfo *in, struct ttxtinfo *out)
}
-struct ttxtpidinfo *FindSubs(struct ttxtinfo *info, char *lang, int HI, int *pid, int *pageno)
+struct ttxtpidinfo *FindSubs(struct ttxtinfo *info, int *pid, int *pageno)
{
- struct ttxtpidinfo *foundNonHIInfo = NULL;
- int foundNonHIPid = 0;
- int foundNonHIPage = -1;
+ struct ttxtpidinfo *foundPI = NULL;
+ int foundChoise = 1000;
+ // walk through all available languages and remember most preferred one
for(int i = 0; i < info->pidcount; i++) {
for(int j = 0; j < info->p[i].pagecount; j++) {
- if(info->p[i].i[j].lang[0] == lang[0] &&
- info->p[i].i[j].lang[1] == lang[1] &&
- info->p[i].i[j].lang[2] == lang[2]) {
- if((!HI && info->p[i].i[j].type == TTXT_SUBTITLE_PAGE) ||
- (HI && info->p[i].i[j].type == TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE)) {
+ if((info->p[i].i[j].type != TTXT_SUBTITLE_PAGE) &&
+ (info->p[i].i[j].type != TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE))
+ continue;
+
+ int ch = globals.langChoise(info->p[i].i[j].lang,
+ info->p[i].i[j].type == TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE);
+ if(ch != -1) {
+ if(ch < foundChoise) {
+ foundChoise = ch;
*pid = info->p[i].pid;
*pageno = info->p[i].i[j].mag * 0x100 + info->p[i].i[j].page;
- fprintf(stderr, "ttxtsubs: Found selected subtitles on PID %d, page %03x\n", *pid,
- *pageno < 0x100 ? *pageno + 0x800 : *pageno);
- return &(info->p[i]);
- } else if(HI && info->p[i].i[j].type == TTXT_SUBTITLE_PAGE) {
- foundNonHIPid = info->p[i].pid;
- foundNonHIPage = info->p[i].i[j].mag * 0x100 + info->p[i].i[j].page;
- foundNonHIInfo = &(info->p[i]);
+ foundPI = &(info->p[i]);
}
}
}
}
- if(foundNonHIInfo) {
- *pid = foundNonHIPid;
- *pageno = foundNonHIPage;
- fprintf(stderr, "ttxtsubs: Found non HI subtitles on PID %d, page %03x\n", *pid,
- *pageno < 0x100 ? *pageno + 0x800 : *pageno);
- return foundNonHIInfo;
+ if(foundPI) {
+ return foundPI;
}
if(info->pidcount == 0)
fprintf(stderr, "ttxtsubs: No teletext subtitles on channel.\n");
else {
- fprintf(stderr, "ttxtsubs: Subtitles for language \"%c%c%c\" not found on channel, available languages:\n", lang[0], lang[1], lang[2]);
+ fprintf(stderr, "ttxtsubs: Wanted subtitle language(s) not found on channel, available languages:\n");
for(int i = 0; i < info->pidcount; i++) {
for(int j = 0; j < info->p[i].pagecount; j++) {
int page = info->p[i].i[j].mag * 0x100 + info->p[i].i[j].page;
int type = info->p[i].i[j].type;
if(page < 0x100)
page += 0x800;
- fprintf(stderr, " %03x: %c%c%c %s\n", page, info->p[i].i[j].lang[0], info->p[i].i[j].lang[1], info->p[i].i[j].lang[2],
+ fprintf(stderr, " %03x: %c%c%c %s\n", page, info->p[i].i[j].lang[0],
+ info->p[i].i[j].lang[1], info->p[i].i[j].lang[2],
type == TTXT_INITIAL_PAGE ? "(Initial Page (The teletext start page, not a subtitles page!))" :
type == TTXT_SUBTITLE_PAGE ? "(Subtitles)" :
type == TTXT_ADDITIONAL_INFO_PAGE ? "(Additional Info Page)" :
@@ -633,6 +647,13 @@ struct ttxtpidinfo *FindSubs(struct ttxtinfo *info, char *lang, int HI, int *pid
}
+void
+ClearSICache(void)
+{
+ gCache.clear();
+}
+
+
#if 0
int XX_GetTtxtSubtitleInfo(uint16_t pid, int card_no, struct ttxtinfo *info)
{
diff --git a/siinfo.h b/siinfo.h
index 5b580f2..a3422f6 100644
--- a/siinfo.h
+++ b/siinfo.h
@@ -35,4 +35,6 @@ int GetTtxtInfo(int card_no, int channel, uint16_t sid, uint16_t vpid, struct tt
void FreeTtxtInfoData(struct ttxtinfo *info);
void DupTtxtInfo(struct ttxtinfo *in, struct ttxtinfo *out);
-struct ttxtpidinfo *FindSubs(struct ttxtinfo *info, char *lang, int HI, int *pid, int *pageno);
+struct ttxtpidinfo *FindSubs(struct ttxtinfo *info, int *pid, int *pageno);
+
+void ClearSICache(void);
diff --git a/teletext-chars.h b/teletext-chars.h
index 1ebc10b..995a43f 100644
--- a/teletext-chars.h
+++ b/teletext-chars.h
@@ -53,7 +53,7 @@ uint8_t laG0_nat_opts[13][14] = {
{0, '£', '$', '@', '-', '½', '-', '|', '#', '-', '¼', '#', '¾', '÷'}, // 1 - English
{0, '#', 'õ', 'S', 'Ä', 'Ö', 'Z', 'Ü', 'Õ', 's', 'ä', 'ö', 'z', 'ü'}, // 2 - Estonian
{0, 'é', 'ï', 'à', 'ë', 'ê', 'ù', 'î', '#', 'è', 'â', 'ô', 'û', 'ç'}, // 3 - French
-{0, '#', '$', '§', 'Ä', 'Ö', 'Ü', '^', '_', 'º', 'ä', 'ö', 'û', 'ß'}, // 4 - German
+{0, '#', '$', '§', 'Ä', 'Ö', 'Ü', '^', '_', 'º', 'ä', 'ö', 'ü', 'ß'}, // 4 - German
{0, '£', '$', 'é', 'º', 'ç', '-', '|', '#', 'ù', 'à', 'ò', 'è', 'ì'}, // 5 - Italian
{0, '#', '$', 'S', 'e', 'e', 'Z', 'c', 'u', 's', 'a', 'u', 'z', 'i'}, // 6 - Lettish/Lithuanian
{0, '#', 'n', 'a', 'Z', 'S', 'L', 'c', 'ó', 'e', 'z', 's', 'l', 'z'}, // 7 - Polish
@@ -61,7 +61,7 @@ uint8_t laG0_nat_opts[13][14] = {
{0, '#', '¤', 'T', 'Â', 'S', 'A', 'Î', 'i', 't', 'â', 's', 'a', 'î'}, // 9 - Rumanian
{0, '#', 'Ë', 'C', 'C', 'Z', 'D', 'S', 'ë', 'c', 'c', 'z', 'd', 's'}, // 10 - Serbian/Croation/Slovenian
{0, '#', '¤', 'É', 'Ä', 'Ö', 'Å', 'Ü', '_', 'é', 'ä', 'ö', 'å', 'ü'}, // 11 - Swedish/Finnish/Hungarian
-{0, 'T', 'g', 'I', 'S', 'Ö', 'Ç', 'Ü', 'G', 'i', 'S', 'ö', 'ç', 'ü'} // 12 - Turkish
+{0, 'T', 'g', 'I', 'S', 'Ö', 'Ç', 'Ü', 'G', 'i', 's', 'ö', 'ç', 'ü'} // 12 - Turkish
};
/*
diff --git a/teletext.c b/teletext.c
index 13ea178..a99b7ec 100644
--- a/teletext.c
+++ b/teletext.c
@@ -484,7 +484,7 @@ ttxt_packet_in(int data_unit_id, int mag, int pack, uint8_t *data)
//if(data[7] & 0x02) // Magazine Serial
p.national_charset =
- ((data[7] & 0x80) >> 5) + ((data[7] & 0x20) >> 4) + ((data[7] & 0x08) >> 3);
+ ((data[7] & 0x80) >> 7) + ((data[7] & 0x20) >> 4) + ((data[7] & 0x08) >> 1);
valid = 1;
diff --git a/ttxtsubs.c b/ttxtsubs.c
index ae1ca63..02f09a9 100644
--- a/ttxtsubs.c
+++ b/ttxtsubs.c
@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: ttxtsubs.c,v 1.20 2003/07/19 02:03:15 ragge Exp ragge $
+ * $Id: ttxtsubs.c,v 1.22 2004/03/01 04:36:32 ragge Exp $
*/
#include <vdr/plugin.h>
@@ -12,39 +12,63 @@
#include <vdr/menuitems.h>
#include <vdr/config.h>
+#include "ttxtsubsglobals.h"
#include "ttxtsubsdisplayer.h"
#include "ttxtsubsrecorder.h"
#include "utils.h"
#include "siinfo.h"
#include "ttxtsubs.h"
-static const char *VERSION = "0.0.4b";
+static const char *VERSION = "0.0.5pre1";
static const char *DESCRIPTION = "Teletext subtitles";
-//static const char *MAINMENUENTRY = "Ttxtsubs";
+
+cTtxtsubsConf globals;
// ISO 639-2 language codes in VDR order
-// XXX should be replaced by something that allows for other languages and for real language names!
+// XXX should be replaced with something that allows for other languages and for real language names!
+// <http://www.avio-systems.com/dtvcc/iso639-2.txt>
// <http://www.loc.gov/standards/iso639-2/englangn_ascii.html>
-char *gLanguages[] =
-{ "eng", //English
- "deu", //Deutsch
- "slv", //Slovenian
- "ita", //Italian
- "dut", //"nld"? Dutch
- "por", //Portuguese
- "fre", //"fra"? French
- "nor", //Norwegian
- "fin", //Finnish
- "pol", //Polish
- "spa", //Spanish
- "gre", //Greek
- "swe", //"sve? Swedish
- "rom", //Romanian
- "hun", //Hungarian
- "cat", //Catalanian
+char *gLanguages[][2] = {
+ "","", //None
+ "eng","", //English
+ "deu","ger", //Deutsch
+ "slv","", //Slovenian
+ "ita","", //Italian
+ "dut","nld", //Dutch
+ "por","", //Portuguese
+ "fre","fra", //French
+ "nor","", //Norwegian
+ "fin","", //Finnish
+ "pol","", //Polish
+ "spa","esl", //Spanish
+ "gre","ell", //Greek
+ "swe","sve", //Swedish
+ "ron","rum", //Romanian
+ "hun","", //Hungarian
+ "cat","", //Catalanian
// Not in translations!
- "dan" //Danish
- };
+ "dan","" //Danish
+};
+const char *gLanguageNames[] = {
+ "-",
+ "English",
+ "Deutsch",
+ "Slovenski",
+ "Italiano",
+ "Nederlands",
+ "Português",
+ "Français",
+ "Norsk",
+ "suomi", // this is not a typo - it's really lowercase!
+ "Polski",
+ "Español",
+ "Ellinika",
+ "Svenska",
+ "Romaneste",
+ "Magyar",
+ "Català",
+ "Dansk"
+};
int gNumLanguages = sizeof(gLanguages) / sizeof(gLanguages[0]);
class cPluginTtxtsubs : public cPlugin, public cStatus, public cVDRTtxtsubsHookListener {
@@ -59,20 +83,11 @@ public:
virtual bool ProcessArgs(int argc, char *argv[]);
virtual bool Start(void);
virtual void Housekeeping(void);
- //virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
+ virtual const char *MainMenuEntry(void);
virtual cOsdObject *MainMenuAction(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value);
- // -- Setup stuff
- virtual char *Language(void) { return mLanguage; };
- virtual int HearingImpaired(void) { return mHearingImpaired; };
- virtual int Record(void) { return mRecord; };
-
- virtual void SetLanguage(char *lang) { strncpy(mLanguage, lang, 4); mLanguage[3] = '\0'; };
- virtual void SetHearingImpaired(int hi) { mHearingImpaired = hi; };
- virtual void SetRecord(int record) { mRecord = record; };
-
// -- cStatus
protected:
virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber);
@@ -103,15 +118,14 @@ public:
void StopTtxt(void);
void ShowTtxt(void);
void HideTtxt(void);
+ void parseLanguages(const char *val);
+ void parseHIs(const char *val);
private:
- // Add any member variables or functions you may need here.
- cTtxtSubsDisplayer *mRec;
+ cTtxtSubsDisplayer *mDispl;
- // Setup items
- char mLanguage[4];
- int mHearingImpaired;
- int mRecord;
+ char mOldLanguage[4]; // language chosen from previous version
+ int mOldHearingImpaired; // HI setting chosen from previous version
// ugly hack for now
int mPage;
@@ -119,30 +133,31 @@ private:
class cMenuSetupTtxtsubs : public cMenuSetupPage {
public:
- cMenuSetupTtxtsubs(cPluginTtxtsubs *ttxtsubs);
+ cMenuSetupTtxtsubs(cPluginTtxtsubs *ttxtsubs, int doStore = 0);
+ ~cMenuSetupTtxtsubs(void);
protected:
virtual void Store(void);
private:
cPluginTtxtsubs *mTtxtsubs;
- char mLanguage[4];
- int mLanguageNo;
- int mHearingImpaired;
- int mRecord;
+ int mLanguageNo[MAXLANGUAGES];
+ int mLangHI[MAXLANGUAGES];
+ int mSavedFrenchSpecial;
+ int mDoStore;
+ cTtxtsubsConf mConf;
};
cPluginTtxtsubs::cPluginTtxtsubs(void)
:
- mRec(NULL),
- mHearingImpaired(0),
- mRecord(1),
- mPage(0x199)
+ mDispl(NULL),
+ mOldHearingImpaired(0)
{
// Initialize any member variables here.
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
-
- strncpy(mLanguage, "unk", 4);
+
+ memset(mOldLanguage, 0, 4);
+ strncpy(globals.mLanguages[0][0], "unk", 4);
}
cPluginTtxtsubs::~cPluginTtxtsubs()
@@ -166,13 +181,37 @@ bool cPluginTtxtsubs::Start(void)
{
// Start any background activities the plugin shall perform.
- if(!memcmp(mLanguage, "unk", 3)) {
- int n = Setup.OSDLanguage;
- if(n > gNumLanguages) {
- strncpy(mLanguage, "eng", 4);
+ if(!memcmp(globals.mLanguages[0][0], "unk", 3)) {
+ // no language found in setup
+ if(strlen(mOldLanguage)) {
+ // use old setup lang, first try to find it amongst known languages
+ for(int i = 0; i < gNumLanguages; i++) {
+ if(!memcmp(mOldLanguage, gLanguages[i][0], 3) ||
+ !memcmp(mOldLanguage, gLanguages[i][1], 3)) {
+ strncpy(globals.mLanguages[0][0], gLanguages[i][0], 4);
+ globals.mLanguages[0][0][3] = '\0';
+ strncpy(globals.mLanguages[0][1], gLanguages[i][1], 4);
+ globals.mLanguages[0][1][3] = '\0';
+ }
+ }
+ if(!memcmp(globals.mLanguages[0][0], "unk", 3)) {
+ // not found there, just copy it
+ memcpy(globals.mLanguages[0][0], mOldLanguage, 3);
+ globals.mLanguages[0][0][3] = '\0';
+ }
+ globals.mHearingImpaireds[0][0] = mOldHearingImpaired;
+ globals.mHearingImpaireds[0][1] = mOldHearingImpaired;
} else {
- strncpy(mLanguage, gLanguages[n], 4);
- mLanguage[3] = '\0';
+ // get lang from OSD lang
+ int n = Setup.OSDLanguage + 1;
+ if(n > gNumLanguages) {
+ strncpy(globals.mLanguages[0][0], "eng", 4);
+ } else {
+ strncpy(globals.mLanguages[0][0], gLanguages[n][0], 4);
+ globals.mLanguages[0][0][3] = '\0';
+ strncpy(globals.mLanguages[0][1], gLanguages[n][1], 4);
+ globals.mLanguages[0][1][3] = '\0';
+ }
}
}
@@ -188,9 +227,45 @@ void cPluginTtxtsubs::Housekeeping(void)
// Perform any cleanup or other regular tasks.
}
+const char *cPluginTtxtsubs::MainMenuEntry(void)
+{
+ switch(globals.mMainMenuEntry) {
+ case 1:
+ if(globals.mDoDisplay)
+ return tr("Hide teletext subtitles");
+ else
+ return tr("Display teletext subtitles");
+ case 2:
+ if(globals.mBottomLB)
+ return tr("Position Teletext Subtitles for 4:3/Anamorph");
+ else
+ return tr("Position Teletext Subtitles for Letterbox");
+ case 3:
+ return tr("Teletext Subtitles");
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
cOsdObject *cPluginTtxtsubs::MainMenuAction(void)
{
// Perform the action when selected from the main VDR menu.
+
+ switch(globals.mMainMenuEntry) {
+ case 1:
+ globals.mDoDisplay = globals.mDoDisplay ? 0 : 1;
+ return NULL;
+ case 2:
+ globals.mBottomLB = globals.mBottomLB ? 0 : 1;
+ return NULL;
+ case 3:
+ return new cMenuSetupTtxtsubs(this, 1);
+ default:
+ return NULL;
+ }
+
return NULL;
}
@@ -201,9 +276,19 @@ cMenuSetupPage *cPluginTtxtsubs::SetupMenu(void)
bool cPluginTtxtsubs::SetupParse(const char *Name, const char *Value)
{
- if(!strcasecmp(Name, "Language")) { strncpy(mLanguage, Value, 4); mLanguage[3] = '\0'; }
- else if(!strcasecmp(Name, "HearingImpaired")) mHearingImpaired = atoi(Value);
- else if(!strcasecmp(Name, "Record")) mRecord = atoi(Value);
+ if(!strcasecmp(Name, "Display")) globals.mDoDisplay = atoi(Value);
+ else if(!strcasecmp(Name, "Record")) globals.mDoRecord = atoi(Value);
+ else if(!strcasecmp(Name, "MainMenuEntry")) globals.mMainMenuEntry = atoi(Value);
+ else if(!strcasecmp(Name, "TextPos")) globals.mTextPos = atoi(Value);
+ else if(!strcasecmp(Name, "BottomLB")) globals.mBottomLB = atoi(Value);
+ else if(!strcasecmp(Name, "BottomAdj")) globals.mBottomAdj = atoi(Value);
+ else if(!strcasecmp(Name, "FrenchSpecial")) globals.mFrenchSpecial = atoi(Value);
+ else if(!strcasecmp(Name, "Languages")) parseLanguages(Value);
+ else if(!strcasecmp(Name, "HearingImpaireds")) parseHIs(Value);
+ // Handle old settings
+ else if(!strcasecmp(Name, "Language")) {
+ strncpy(mOldLanguage, Value, 4); mOldLanguage[3] = '\0'; }
+ else if(!strcasecmp(Name, "HearingImpaired")) mOldHearingImpaired = atoi(Value);
else
return false;
return true;
@@ -211,6 +296,9 @@ bool cPluginTtxtsubs::SetupParse(const char *Name, const char *Value)
void cPluginTtxtsubs::ChannelSwitch(const cDevice *Device, int ChannelNumber)
{
+ dprint("cPluginTtxtsubs::ChannelSwitch(devicenr: %d, channelnr: %d) - mDispl: %x\n",
+ Device->DeviceNumber(), ChannelNumber, mDispl); // XXX
+
if(Device->IsPrimaryDevice()) {
if(ChannelNumber) {
cChannel *c = Channels.GetByNumber(ChannelNumber);
@@ -221,7 +309,7 @@ void cPluginTtxtsubs::ChannelSwitch(const cDevice *Device, int ChannelNumber)
if(GetTtxtInfo(Device->ActualDevice()->CardIndex(), ChannelNumber, c->Sid(), c->Vpid(), &info)) {
fprintf(stderr, "ttxtsubs: Error: GetTtxtInfo failed!\n");
} else {
- if(FindSubs(&info, mLanguage, mHearingImpaired, &pid, &page)) {
+ if(FindSubs(&info, &pid, &page)) {
//fprintf(stderr, "CHANNELSWITCH, pid: %d page: %x\n", pid, page);
mPage = page; // XXX remember this for playback (temporary hack)!
StartTtxtLive(Device, pid, page);
@@ -236,6 +324,8 @@ void cPluginTtxtsubs::ChannelSwitch(const cDevice *Device, int ChannelNumber)
void cPluginTtxtsubs::Replaying(const cControl *Control, const char *Name)
{
+ dprint("cPluginTtxtsubs::Replaying\n"); // XXX
+
StopTtxt();
StartTtxtPlay(mPage);
// XXX this page number is just a fallback for old recordings which
@@ -244,7 +334,7 @@ void cPluginTtxtsubs::Replaying(const cControl *Control, const char *Name)
void cPluginTtxtsubs::PlayerTeletextData(uint8_t *p, int length)
{
- cTtxtSubsPlayer *r = dynamic_cast<cTtxtSubsPlayer *>(mRec);
+ cTtxtSubsPlayer *r = dynamic_cast<cTtxtSubsPlayer *>(mDispl);
if(!r) {
fprintf(stderr, "ttxtsubs: ERROR: not a cTtxtSubsPlayer!\n");
@@ -256,8 +346,8 @@ void cPluginTtxtsubs::PlayerTeletextData(uint8_t *p, int length)
cTtxtSubsRecorderBase *cPluginTtxtsubs::NewTtxtSubsRecorder(cDevice *dev, const cChannel *ch)
{
- if(mRecord)
- return new cTtxtSubsRecorder(dev, ch, mLanguage, mHearingImpaired);
+ if(globals.mDoRecord)
+ return new cTtxtSubsRecorder(dev, ch);
else
return NULL;
}
@@ -267,18 +357,16 @@ cTtxtSubsRecorderBase *cPluginTtxtsubs::NewTtxtSubsRecorder(cDevice *dev, const
void cPluginTtxtsubs::StartTtxtLive(const cDevice *Device, int pid, int page)
{
- //dprint("cPluginTtxtsubs::StartTtxtLive\n");
+ dprint("cPluginTtxtsubs::StartTtxtLive(devicenr: %d, pid: %d, page: %03x)\n",
+ Device->DeviceNumber(), pid, page); // XXX
-#if 0
- return; // XXX TEST - No live subs
-#endif
-
- if(!mRec) {
+ if(!mDispl) {
cTtxtSubsLiveReceiver *r;
//dprint("teletext subtitles started on pid %d\n", pid);
- mRec = r = new cTtxtSubsLiveReceiver(pid, page);
+ mDispl = r = new cTtxtSubsLiveReceiver(pid, page);
if(!cDevice::PrimaryDevice()->ActualDevice()->AttachReceiver(r))
fprintf(stderr, "ttxtsubs: Error: AttachReceiver failed!\n"); //
+ ShowTtxt();
} else
fprintf(stderr, "ttxtsubs: Error: StartTtxtLive called when already started!\n");
}
@@ -287,9 +375,10 @@ void cPluginTtxtsubs::StartTtxtPlay(int backup_page)
{
dprint("cPluginTtxtsubs::StartTtxtPlay\n");
- if(!mRec) {
+ if(!mDispl) {
dprint("ttxtsubs: teletext subtitles replayer started with initial page %03x\n", backup_page);
- mRec = new cTtxtSubsPlayer(mLanguage, mHearingImpaired, backup_page);
+ mDispl = new cTtxtSubsPlayer(backup_page);
+ ShowTtxt();
} else
fprintf(stderr, "ttxtsubs: Error: StartTtxtPlay called when already started!\n");
}
@@ -298,68 +387,244 @@ void cPluginTtxtsubs::StopTtxt(void)
{
dprint("cPluginTtxtsubs::StopTtxt\n");
- if(mRec) {
+ if(mDispl) {
+ cTtxtSubsDisplayer *d = mDispl;
HideTtxt();
- delete mRec;
- mRec = NULL;
+ mDispl = NULL;
+ delete d;
}
}
void cPluginTtxtsubs::ShowTtxt(void)
{
- if(mRec)
- mRec->ShowDisplay();
+ if(globals.mDoDisplay)
+ if(mDispl)
+ mDispl->ShowDisplay();
}
void cPluginTtxtsubs::HideTtxt(void)
{
- if(mRec)
- mRec->HideDisplay();
+ if(mDispl)
+ mDispl->HideDisplay();
+}
+
+void cPluginTtxtsubs::parseLanguages(const char *val) {
+ size_t i;
+ const char *p = val;
+ const char *p2;
+ size_t len;
+
+ for(i = 0; i < (MAXLANGUAGES*2); i++) {
+ if(*p == '\0')
+ break; // end of string
+
+ p2 = strchr(p, ','); // find end of entry
+ if(p2) {
+ len = p2 - p;
+ } else { // no more , found
+ len = strlen(p);
+ }
+
+ if(len) {
+ size_t trlen = len;
+ if(trlen > 3)
+ trlen = 3;
+ memcpy(globals.mLanguages[i/2][i%2], p, trlen);
+ globals.mLanguages[i/2][i%2][trlen] = '\0';
+ }
+
+ p += len + 1;
+ }
+}
+
+void cPluginTtxtsubs::parseHIs(const char *val)
+{
+ size_t i;
+
+ for(i = 0; i < (MAXLANGUAGES*2); i++) {
+ if(val[i] == '\0')
+ break;
+ globals.mHearingImpaireds[i/2][i%2] = val[i] != '0';
+ }
}
// ----- cMenuSetupTtxtsubs -----
-cMenuSetupTtxtsubs::cMenuSetupTtxtsubs(cPluginTtxtsubs *ttxtsubs)
+//#define TEST
+class cMenuSetupTtxtsubsLanguages : public cMenuSetupPage {
+ public:
+ cMenuSetupTtxtsubsLanguages(cPluginTtxtsubs *ttxtsubs);
+ protected:
+ virtual void Store(void);
+ private:
+ cPluginTtxtsubs *mTtxtsubs;
+};
+
+cMenuSetupTtxtsubsLanguages::cMenuSetupTtxtsubsLanguages(cPluginTtxtsubs *ttxtsubs)
+ :
+ mTtxtsubs(ttxtsubs)
+{}
+
+void cMenuSetupTtxtsubsLanguages::Store(void)
+{
+ fprintf(stderr, "cMenuSetupTtxtsubsLanguages::Store\n");
+}
+
+cMenuSetupTtxtsubs::cMenuSetupTtxtsubs(cPluginTtxtsubs *ttxtsubs, int doStore)
:
mTtxtsubs(ttxtsubs),
- mLanguageNo(-1),
- mHearingImpaired(mTtxtsubs->HearingImpaired()),
- mRecord(mTtxtsubs->Record())
+ mDoStore(doStore),
+ mConf(globals)
{
- memcpy(mLanguage, ttxtsubs->Language(), 3);
- mLanguage[3] = '\0';
+ //static char *mainMenuAlts[] = {"off", "Display on/off", "4:3/Letterbox", "This menu"};
+ // can't get it to store changes in file
+ static char *mainMenuAlts[] = {"off", "Display on/off", "4:3/Letterbox"};
+ static int numMainMenuAlts = sizeof(mainMenuAlts) / sizeof(mainMenuAlts[0]);
+ static char *textPosAlts[] = {"Left", "Center", "Right"};
+ static int numTextPosAlts = sizeof(textPosAlts) / sizeof(textPosAlts[0]);
+
+ mSavedFrenchSpecial = mConf.mFrenchSpecial;
+
+ for(int n = 0; n < MAXLANGUAGES; n++) {
+ mLanguageNo[n] = -1;
+ mLangHI[n] = mConf.mHearingImpaireds[n][0];
+
+ for(int i = 0; i < gNumLanguages; i++) {
+ if(!strncmp(mConf.mLanguages[n][0], gLanguages[i][0], 4) &&
+ !strncmp(mConf.mLanguages[n][1], gLanguages[i][1], 4)) {
+ mLanguageNo[n] = i;
+ break;
+ }
+ }
+ }
- for(int i = 0; i < gNumLanguages; i++) {
- if(!memcmp(mLanguage, gLanguages[i], 3)) {
- mLanguageNo = i;
- break;
+ Add(new cMenuEditBoolItem(tr("Display Subtitles"), &mConf.mDoDisplay, tr("no"), tr("yes")));
+ Add(new cMenuEditBoolItem(tr("Record Subtitles"), &mConf.mDoRecord, tr("no"), tr("yes")));
+ if(mConf.mMainMenuEntry < 0 || mConf.mMainMenuEntry >= numMainMenuAlts)
+ mConf.mMainMenuEntry = 0; // menu item segfaults if out of range
+ Add(new cMenuEditStraItem(tr("Main Menu Alternative"), &mConf.mMainMenuEntry,
+ numMainMenuAlts, mainMenuAlts));
+ if(mConf.mTextPos < 0 || mConf.mTextPos >= numTextPosAlts)
+ mConf.mTextPos = 0; // menu item segfaults if out of range
+ Add(new cMenuEditStraItem(tr("Text Horizontal Position"), &mConf.mTextPos,
+ numTextPosAlts, textPosAlts));
+ Add(new cMenuEditBoolItem(tr("Text Vertical Position"),
+ &mConf.mBottomLB, tr("4:3/Anamorph"), tr("Letterbox")));
+ Add(new cMenuEditIntItem(tr("Text Vertical Adjust"),
+ &mConf.mBottomAdj, -100, 45));
+ Add(new cMenuEditBoolItem(tr("Workaround for some French chns"),
+ &mConf.mFrenchSpecial, tr("no"), tr("yes")));
+
+ for(int n = 0; n < MAXLANGUAGES; n++) {
+ char str[100];
+ char *allowedc = "abcdefghijklmnopqrstuvwxyz";
+
+ cOsdItem *item = new cOsdItem("----------------------------");
+ item->SetColor(clrCyan);
+ Add(item);
+
+ sprintf(str, "Language %d", n + 1);
+ if(mLanguageNo[n] >= 0) {
+ Add(new cMenuEditStraItem(tr(str), &mLanguageNo[n], gNumLanguages, gLanguageNames));
+ } else {
+ Add(new cMenuEditStrItem(tr(str), mConf.mLanguages[n][0], 4, allowedc));
+ Add(new cMenuEditStrItem(tr(str), mConf.mLanguages[n][1], 4, allowedc));
}
+
+ sprintf(str, "Language %d Hearing Impaired", n + 1);
+ Add(new cMenuEditBoolItem(tr(str), &(mConf.mHearingImpaireds[n][0]),
+ tr("no"), tr("yes")));
}
- if(mLanguageNo >= 0)
- Add(new cMenuEditStraItem(tr("Language"), &mLanguageNo, gNumLanguages, gLanguages));
- else
- Add(new cMenuEditStrItem(tr("Language"), mLanguage, 4, "abcdefghijklmnopqrstuvwxyz"));
-
- Add(new cMenuEditBoolItem(tr("Hearing Impaired"), &mHearingImpaired, tr("no"), tr("yes")));
- Add(new cMenuEditBoolItem(tr("Record Subtitles"), &mRecord, tr("no"), tr("yes")));
+#ifdef TEST
+ //AddSubMenu(new cMenuSetupTtxtsubsLanguages(mTtxtsubs));
+#endif
+}
+
+cMenuSetupTtxtsubs::~cMenuSetupTtxtsubs(void)
+{
+ if(mSavedFrenchSpecial != mConf.mFrenchSpecial)
+ ClearSICache();
+
+ if(mDoStore) {
+ Store();
+ // Setup.Save(); // Can't get it to write to conf file, menu item disabled.
+ }
}
void cMenuSetupTtxtsubs::Store(void)
{
- if(mLanguageNo >= 0) {
- SetupStore("Language", gLanguages[mLanguageNo]);
- mTtxtsubs->SetLanguage(gLanguages[mLanguageNo]);
- } else {
- SetupStore("Language", mLanguage);
- mTtxtsubs->SetLanguage(mLanguage);
+ for(int n=0; n < MAXLANGUAGES; n++) {
+ if(mLanguageNo[n] >= 0) {
+ strncpy(mConf.mLanguages[n][0], gLanguages[mLanguageNo[n]][0], 4);
+ mConf.mLanguages[n][0][3] = '\0';
+ strncpy(mConf.mLanguages[n][1], gLanguages[mLanguageNo[n]][1], 4);
+ mConf.mLanguages[n][1][3] = '\0';
+ }
+
+ mConf.mHearingImpaireds[n][1] = mConf.mHearingImpaireds[n][0];
}
+
+ SetupStore("Display", mConf.mDoDisplay);
+ SetupStore("Record", mConf.mDoRecord);
+ SetupStore("TextPos", mConf.mTextPos);
+ SetupStore("BottomLB", mConf.mBottomLB);
+ SetupStore("BottomAdj", mConf.mBottomAdj);
+ SetupStore("FrenchSpecial", mConf.mFrenchSpecial);
+ SetupStore("MainMenuEntry", mConf.mMainMenuEntry);
+
+ char lstr[MAXLANGUAGES*2*4 + 1];
+ char histr[MAXLANGUAGES*2 + 1];
+ lstr[0] = '\0';
+ histr[0] = '\0';
+ for(int n=0; n < MAXLANGUAGES; n++) {
+ strncat(lstr, mConf.mLanguages[n][0], 3);
+ strcat(lstr, ",");
+ strncat(lstr, mConf.mLanguages[n][1], 3);
+ if(n != (MAXLANGUAGES - 1))
+ strcat(lstr, ",");
+
+ strcat(histr, mConf.mHearingImpaireds[n][0] ? "1" : "0");
+ strcat(histr, mConf.mHearingImpaireds[n][1] ? "1" : "0");
+ }
+ SetupStore("Languages", lstr);
+ SetupStore("HearingImpaireds", histr);
+
+ globals = mConf;
+}
+
+
+// returns the index to choise number for the given language,
+// lower is more preferred. The result is times two, plus one
+// if the HI wanted but not found, or -1 if no match.
+// Non HI wanted but found is no match.
+
+int cTtxtsubsConf::langChoise(const char *lang, const int HI)
+{
+ size_t i, j;
+ int result = -1;
- SetupStore("HearingImpaired", mHearingImpaired);
- mTtxtsubs->SetHearingImpaired(mHearingImpaired);
+ for(i = 0; i < MAXLANGUAGES; i++) {
+ for(j = 0; j < 2; j++) {
+ if(!mLanguages[i][j][0])
+ continue;
+
+ if(!memcmp(lang, mLanguages[i][j], 3)) {
+ if( ( HI && mHearingImpaireds[i][j] ) ||
+ ( !HI && !mHearingImpaireds[i][j] ) ) {
+ result = i*2;
+ goto x;
+ }
+ if( !HI && mHearingImpaireds[i][j] ) {
+ result = 1 + i*2;
+ goto x;
+ }
+ }
+ }
+ }
- SetupStore("Record", mRecord);
- mTtxtsubs->SetRecord(mRecord);
+ x:
+ return result;
}
diff --git a/ttxtsubsdisplay.c b/ttxtsubsdisplay.c
index a108919..cfb7e88 100644
--- a/ttxtsubsdisplay.c
+++ b/ttxtsubsdisplay.c
@@ -10,6 +10,7 @@
#include <vdr/osdbase.h>
#include <vdr/thread.h>
+#include "ttxtsubsglobals.h"
#include "ttxtsubsdisplay.h"
#include "utils.h"
@@ -213,7 +214,7 @@ void cTtxtSubsDisplay::TtxtData(const uint8_t *Data)
// if(fi[7] & 0x02) // Magazine Serial
page.national_charset = ((fi[7] & 0x80) >> 5) +
- ((fi[7] & 0x20) >> 4) + ((fi[7] & 0x08) >> 3);
+ ((fi[7] & 0x20) >> 4) + ((fi[7] & 0x08) >> 1);
mPageState = collecting;
gettimeofday(mLastDataTime, NULL);
@@ -287,8 +288,23 @@ ttxt2la1(uint8_t *p, char *buf, int natopts)
return NULL;
}
+#if 0
+
+#define TEST_CENTER 0
+#if TEST_CENTER
+#define SCREENLEFT 0
+#define SCREENWIDTH 720
+#else
#define SCREENLEFT 125
+#endif
+
+#define TEST_169 0
+#if TEST_169
+#define SCREENBOT 480
+#else
#define SCREENBOT 540
+#endif
+
#if 0
#define ROWINCR 45
#define ROWH 36
@@ -299,7 +315,26 @@ ttxt2la1(uint8_t *p, char *buf, int natopts)
#define TEXTY 3
#endif
#define TEXTX 15
-#define SCREENTOP (SCREENBOT - MAXTTXTROWS * ROWINCR)
+//#define SCREENTOP (SCREENBOT - MAXTTXTROWS * ROWINCR)
+#define SCREENTOP 100
+
+#endif
+
+enum {
+ SCREENLEFT = 0,
+ SCREENRIGHT = 719,
+ SCREENTOP = 150,
+ SCREENBOTTOM = 575,
+
+ SIDEMARGIN = 125,
+ BOTNORM = 540,
+ BOTLETTERBOX = 482,
+
+ ROWINCR = 43,
+ ROWH = 34,
+ TEXTY = 3,
+ TEXTX = 15
+};
void cTtxtSubsDisplay::ShowOSD(void)
{
@@ -307,6 +342,7 @@ void cTtxtSubsDisplay::ShowOSD(void)
int rowcount = 0;
char buf[TTXT_DISPLAYABLE_ROWS][41];
int doneWidthWorkaround = 0;
+ int bottom = globals.bottomAdj() + (globals.bottomLB() ? BOTLETTERBOX : BOTNORM);
cOSDSelfMemoryLock selfmem(&gSelfMem);
cMutexLock lock(&mOsdLock);
@@ -332,11 +368,8 @@ void cTtxtSubsDisplay::ShowOSD(void)
rowcount++;
}
-#if 1
mOsd = cOsd::OpenRaw(SCREENLEFT, SCREENTOP);
-#else
- mOsd = cDevice::PrimaryDevice()->NewOsd(SCREENLEFT, SCREENTOP);
-#endif
+
if(mOsd == NULL) {
//dprint("Error: cOsd::OpenRaw returned NULL!\n");
return;
@@ -347,29 +380,48 @@ void cTtxtSubsDisplay::ShowOSD(void)
if(rowcount > MAXTTXTROWS)
rowcount = MAXTTXTROWS;
- y = SCREENBOT - SCREENTOP - ROWH - (ROWINCR * (rowcount-1));
+#if 0 // XXXX
+ rowcount = 4;
+ strcpy(buf[0], "1234567890123456789012345678901234567890");
+ strcpy(buf[1], "1234567890123456789012345678901234567890");
+ strcpy(buf[2], "1234567890123456789012345678901234567890");
+ strcpy(buf[3], "1234567890123456789012345678901234567890");
+#endif
+
+ y = bottom - SCREENTOP - ROWH - (ROWINCR * (rowcount-1));
for(i = 0; i < rowcount; i++) {
tWindowHandle wind;
- int w = 0; // XXX should be text width - not %4!
+ int w = 0;
+ int left = SIDEMARGIN;
// XXX Width calculations doesn't work before we have created a window...
if(!doneWidthWorkaround) {
- wind = mOsd->Create(0, y, 4, ROWH, 2);
- mOsd->Fill(0, y, 4, y + ROWH, clrWhite, wind);
- mOsd->Fill(0, y, 4, y + ROWH, clrBackground, wind);
+ //wind = mOsd->Create(0, y, 4, ROWH, 2);
+ //mOsd->Fill(0, y, 4, y + ROWH, clrWhite, wind);
+ //mOsd->Fill(0, y, 4, y + ROWH, clrBackground, wind);
+ wind = mOsd->Create(0, 575, 4, 1, 2);
+ mOsd->Fill(0, 574, 4, 575, clrWhite, wind);
+ mOsd->Fill(0, 574, 4, 575, clrTransparent, wind);
doneWidthWorkaround = 1;
}
-
- w = mOsd->Width(buf[i]) + 2 * TEXTX;
+ w = mOsd->Width(buf[i]) + 2 * TEXTX;
if(w % 4)
w += 4 - (w % 4);
- wind = mOsd->Create(0, y, w, ROWH, 2);
- //dprint("W: %d\n", w);
- mOsd->Fill(0, y, w, y + ROWH, clrWhite, wind); // needed for dxr3s...
- mOsd->Fill(0, y, w, y + ROWH, clrBackground, wind);
- mOsd->Text(TEXTX, y + TEXTY, buf[i], clrWhite, clrBackground, wind);
+ switch(globals.textPos()) {
+ case 1:
+ left = (SCREENRIGHT - w) / 2;
+ break;
+ case 2:
+ left = SCREENRIGHT - SIDEMARGIN - w;
+ break;
+ }
+
+ wind = mOsd->Create(left, y, w, ROWH, 2);
+ mOsd->Fill(left, y, left + w, y + ROWH, clrWhite, wind); // needed for dxr3s...
+ mOsd->Fill(left, y, left + w, y + ROWH, clrBackground, wind);
+ mOsd->Text(left + TEXTX, y + TEXTY, buf[i], clrWhite, clrBackground, wind);
y += ROWINCR;
}
@@ -392,8 +444,11 @@ void cTtxtSubsDisplay::ClearOSD(void)
if(mOsd) {
//mOsd->Clear(ALL_WINDOWS);
+#if 0
+ // not needed, windows are removed in mOsd destructor
mOsd->Hide(ALL_WINDOWS);
mOsd->Flush();
+#endif
delete mOsd;
mOsd = NULL;
}
diff --git a/ttxtsubsdisplayer.c b/ttxtsubsdisplayer.c
index 5f2f0a6..fe69aa7 100644
--- a/ttxtsubsdisplayer.c
+++ b/ttxtsubsdisplayer.c
@@ -4,6 +4,7 @@
#include "utils.h"
#include "ttxtsubs.h"
#include "siinfo.h"
+#include "ttxtsubsglobals.h"
// ----- class cTtxtSubsDisplayer -----
@@ -17,7 +18,6 @@ cTtxtSubsDisplayer::cTtxtSubsDisplayer(int textpage)
{
mDisp = new cTtxtSubsDisplay();
mDisp->SetPage(textpage);
- ShowDisplay();
mRun = 1;
this->Start(); // start thread
@@ -108,16 +108,14 @@ void cTtxtSubsLiveReceiver::Receive(uchar *Data, int Length)
// ----- class cTtxtSubsPlayer -----
-cTtxtSubsPlayer::cTtxtSubsPlayer(char *lang, int HI, int backup_textpage)
+cTtxtSubsPlayer::cTtxtSubsPlayer(int backup_textpage)
:
cTtxtSubsDisplayer(backup_textpage),
- mHearingImpaired(HI),
mHasFilteredStream(0),
mFoundLangPage(0),
+ mLangChoise(1000),
mLangInfoState(0)
{
- memcpy(mLanguage, lang, 3);
- mLanguage[3] = '\0';
}
// Take PES packets and break out the teletext data
@@ -169,8 +167,6 @@ void cTtxtSubsPlayer::SearchLanguagePage(uint8_t *p, int len)
{
char *infoline = "Subtitles Index Page";
int foundlines = 0;
- unsigned int foundNonHIPage = 0;
- int foundNonHI = 0; // 1 = found non hearing impaired
if(len < (3*46))
return;
@@ -201,25 +197,26 @@ void cTtxtSubsPlayer::SearchLanguagePage(uint8_t *p, int len)
break;
case 2:
mLangInfoState++;
- if(mLangInfoState == 3)
- fprintf(stderr, "ttxtsubs: Language \"%c%c%c\" not found in recording, available languages:\n",
- mLanguage[0], mLanguage[1], mLanguage[2]);
-
if(packet < 2) // need a Y2 or more
return;
+ if(mLangInfoState == 3)
+ fprintf(stderr, "ttxtsubs: Chosen Language not found in recording, available languages:\n");
copy_inv_strip_par(buf, d->data, sizeof(buf));
for(size_t i = 0; i < 40; i += 8) {
if(mLangInfoState == 3 && buf[i] >= 'a' && buf[i] <= 'z')
- fprintf(stderr, " %c%c%c: %c%c%c %s\n", buf[i+4], buf[i+5], buf[i+6], buf[i], buf[i+1], buf[i+2],
- buf[i+3] == ' ' ? "" : buf[i+3] == 'h' ? "(Hearing Impaired)" : "(Unknown type)");
- if(buf[i] == mLanguage[0] &&
- buf[i+1] == mLanguage[1] &&
- buf[i+2] == mLanguage[2] &&
+ fprintf(stderr, " %c%c%c: %c%c%c %s\n", buf[i+4], buf[i+5], buf[i+6],
+ buf[i], buf[i+1], buf[i+2], buf[i+3] == ' ' ? "" :
+ buf[i+3] == 'h' ? "(Hearing Impaired)" : "(Unknown type)");
+
+ if(buf[i] >= 'a' && buf[i] <= 'z' &&
+ buf[i+1] >= 'a' && buf[i+1] <= 'z' &&
+ buf[i+2] >= 'a' && buf[i+2] <= 'z' &&
((buf[i+3] == ' ') || (buf[i+3] == 'h')) &&
buf[i+4] >= '1' && buf[i+4] <= '8' &&
buf[i+5] >= '0' && buf[i+5] <= '9' &&
buf[i+6] >= '0' && buf[i+6] <= '9' &&
buf[i+7] == ' ') {
+ int ch = globals.langChoise((char *)buf+i, buf[i+3] == 'h');
unsigned int page =
((buf[i+4] - '0') << 8) +
((buf[i+5] - '0') << 4) +
@@ -228,17 +225,11 @@ void cTtxtSubsPlayer::SearchLanguagePage(uint8_t *p, int len)
if(page >= 0x800)
page -= 0x800;
- if(((!mHearingImpaired) && (buf[3+i] == ' ')) ||
- (mHearingImpaired && (buf[3+i] == 'h'))) {
+ if(ch >= 0 && ch < mLangChoise) {
+ mLangChoise = ch;
mDisp->SetPage(page);
mFoundLangPage = 1;
- fprintf(stderr, "FOUND subtitle page: %03x\n", page); // XXX
- return;
- }
- if(mHearingImpaired && (buf[3+i] == ' ')) {
- foundNonHIPage = page;
- foundNonHI = 1;
- fprintf(stderr, "FOUND non hi subtitle page, remembering: %03x\n", page); // XXX
+ fprintf(stderr, "Found subtitle page: %03x\n", page); // XXX
}
}
}
@@ -246,11 +237,4 @@ void cTtxtSubsPlayer::SearchLanguagePage(uint8_t *p, int len)
break;
}
}
-
- if(foundNonHI) {
- mDisp->SetPage(foundNonHIPage);
- mFoundLangPage = 1;
- fprintf(stderr, "Didn't find HI page, but found right language: %03x\n", foundNonHIPage); // XXX
- return;
- }
}
diff --git a/ttxtsubsdisplayer.h b/ttxtsubsdisplayer.h
index 00127ff..cd63595 100644
--- a/ttxtsubsdisplayer.h
+++ b/ttxtsubsdisplayer.h
@@ -33,15 +33,14 @@ class cTtxtSubsLiveReceiver : public cReceiver, public cTtxtSubsDisplayer {
class cTtxtSubsPlayer : public cTtxtSubsDisplayer {
public:
- cTtxtSubsPlayer(char *lang, int HI, int backup_textpage);
+ cTtxtSubsPlayer(int backup_textpage);
virtual void PES_data(uchar *Data, int Length);
private:
void SearchLanguagePage(uint8_t *p, int len);
- char mLanguage[4];
- int mHearingImpaired;
int mHasFilteredStream;
int mFoundLangPage;
+ int mLangChoise;
int mLangInfoState;
};
diff --git a/ttxtsubsfilter.c b/ttxtsubsfilter.c
index 9271215..ae13cc0 100644
--- a/ttxtsubsfilter.c
+++ b/ttxtsubsfilter.c
@@ -126,6 +126,11 @@ void cTtxtSubsFilter::MakeY0(char *outdata, char *indata, uint16_t newpageno)
struct ttxt_data_field *o = (struct ttxt_data_field *) outdata;
uint8_t hambuf[2];
+ o->data_unit_id = 3; // EBU Teletxt subtitle data
+ o->data_unit_length = 44;
+ o->par_loff = 0xc0; // reserved bits + unknown line
+ o->framing_code = 0xe4;
+
// new magazine number (Y = 0)
ham8_4byte((newpageno >> 8) & 0x7, hambuf);
o->mag_addr_ham[0] = invtab[hambuf[0]];
diff --git a/ttxtsubsglobals.h b/ttxtsubsglobals.h
new file mode 100644
index 0000000..09bae9d
--- /dev/null
+++ b/ttxtsubsglobals.h
@@ -0,0 +1,50 @@
+
+class cPluginTtxtsubs;
+class cMenuSetupTtxtsubs;
+
+#define MAXLANGUAGES 5
+
+class cTtxtsubsConf {
+ friend class cPluginTtxtsubs;
+ friend class cMenuSetupTtxtsubs;
+
+ public:
+ cTtxtsubsConf(void)
+ {
+ mDoDisplay = 1;
+ mDoRecord = 1;
+ mMainMenuEntry = 0;
+ mTextPos = 0;
+ mBottomLB = 0;
+ mBottomAdj = 0;
+ mFrenchSpecial = 0;
+ memset(mLanguages, 0, sizeof(mLanguages));
+ memset(mHearingImpaireds, 0, sizeof(mHearingImpaireds));
+ }
+
+ public:
+ int doDisplay(void) {return mDoDisplay;}
+ int doRecord(void) {return mDoRecord;}
+ int mainMenuEntry(void) {return mMainMenuEntry;}
+ int textPos(void) {return mTextPos;}
+ int bottomLB(void) {return mBottomLB;}
+ int bottomAdj(void) {return mBottomAdj;}
+ int frenchSpecial(void) {return mFrenchSpecial;}
+ char (*languages(void))[MAXLANGUAGES][2][4] {return &mLanguages;}
+ int (*hearingImpaireds(void))[MAXLANGUAGES][2] {return &mHearingImpaireds;}
+
+ int langChoise(const char *lang, const int HI);
+
+ protected:
+ int mDoDisplay;
+ int mDoRecord;
+ int mMainMenuEntry;
+ int mTextPos;
+ int mBottomLB;
+ int mBottomAdj;
+ int mFrenchSpecial;
+ char mLanguages[MAXLANGUAGES][2][4];
+ int mHearingImpaireds[MAXLANGUAGES][2];
+};
+
+extern cTtxtsubsConf globals;
diff --git a/ttxtsubsreceiver.c b/ttxtsubsreceiver.c
index b8473e6..b254c88 100644
--- a/ttxtsubsreceiver.c
+++ b/ttxtsubsreceiver.c
@@ -10,6 +10,11 @@
#define MAXINDEXPAGELINES 24
+struct ringBufItem {
+ encodedPTS pts;
+ uint8_t data[46];
+};
+
// ----- cTtxtSubsReceiver -----
cTtxtSubsReceiver::cTtxtSubsReceiver(int Ca, struct ttxtpidinfo *PI)
@@ -17,7 +22,7 @@ cTtxtSubsReceiver::cTtxtSubsReceiver(int Ca, struct ttxtpidinfo *PI)
cReceiver(Ca, -1, 1, PI->pid),
mGetMutex(),
mGetCond(),
- mRingBuf(46 * 500, true),
+ mRingBuf(sizeof(ringBufItem) * 500, true),
mPI(*PI),
mIndexPageLines(0),
mIndexPageCol(0),
@@ -26,6 +31,8 @@ cTtxtSubsReceiver::cTtxtSubsReceiver(int Ca, struct ttxtpidinfo *PI)
int count = 0;
uint16_t *pages = (uint16_t *) malloc(sizeof(uint16_t) * mPI.pagecount);
+ mPTS.valid = 0;
+
// find a free page to put the index page on
mIndexPageNo = 0x100;
int again;
@@ -70,13 +77,18 @@ cTtxtSubsReceiver::~cTtxtSubsReceiver()
// returns pointer buf if there is new data
-uint8_t *cTtxtSubsReceiver::Get(uint8_t *buf)
+uint8_t *cTtxtSubsReceiver::Get(uint8_t *buf, encodedPTS *pts)
{
cFrame *f;
f = mRingBuf.Get();
if(f) {
- memcpy(buf, f->Data(), 46);
+ ringBufItem *i = (ringBufItem*) f->Data();
+ if(pts) {
+ *pts = i->pts;
+ }
+
+ memcpy(buf, i->data, 46);
mRingBuf.Drop(f);
// fprintf(stderr, "cTtxtSubsReceiver::Get: returned data!\n");
return buf;
@@ -117,7 +129,7 @@ void cTtxtSubsReceiver::Activate(bool On)
// XXX We should do some filtering here to avoid unneccessary load!
void cTtxtSubsReceiver::Receive(uchar *Data, int Length)
{
- int i;
+ int i = 0;
if(Length != 188) // should never happen
return;
@@ -125,19 +137,37 @@ void cTtxtSubsReceiver::Receive(uchar *Data, int Length)
if(Data[1] & 0x80) // transport_error_indicator
return;
+ if((Data[3] & 0x30) != 0x10) // only accept TS packets with data and no adaption field
+ return; // (ETSI EN 300 472 $4.1)
+
+ if(Data[1] & 0x40) { // payload_unit_start_indicator
+ if(((Data[11] >> 6) & 0x02) == 0x02) { // PTS_DTS_flags
+ mPTS.data[0] = Data[13];
+ mPTS.data[1] = Data[14];
+ mPTS.data[2] = Data[15];
+ mPTS.data[3] = Data[16];
+ mPTS.data[4] = Data[17];
+ mPTS.valid = 1;
+ } else {
+ mPTS.valid = 0;
+ }
+ }
+
+ ringBufItem it;
+ it.pts = mPTS;
+
// payload_unit_start_indicator
for(i = (Data[1] & 0x40) ? 1 : 0; i < 4; i++) {
- char buf[46];
if(0xff == Data[4 + i*46]) // stuffing data
continue;
- if(mFilter.Filter((char *) Data + 4 + i*46, buf)) {
+ if(mFilter.Filter((char *) Data + 4 + i*46, (char *) it.data)) {
// fprintf(stderr, "Forward Packet:\n");
// print_line((char *) Data + 4 + i*46);
// print_line(buf);
- cFrame *f = new cFrame((uchar *) buf, 46);
+ cFrame *f = new cFrame((uchar *) &it, sizeof(ringBufItem));
mRingBuf.Put(f);
mGetCond.Broadcast();
}
diff --git a/ttxtsubsreceiver.h b/ttxtsubsreceiver.h
index a88aa65..3e11695 100644
--- a/ttxtsubsreceiver.h
+++ b/ttxtsubsreceiver.h
@@ -1,6 +1,11 @@
class cRingBufferFrame;
+struct encodedPTS {
+ uint8_t valid;
+ uint8_t data[5];
+};
+
class cTtxtSubsReceiver : public cReceiver
{
public:
@@ -8,7 +13,7 @@ class cTtxtSubsReceiver : public cReceiver
virtual ~cTtxtSubsReceiver();
// returns pointer buf if there is new data
- uint8_t *Get(uint8_t *buf);
+ uint8_t *Get(uint8_t *buf, encodedPTS *pts = NULL);
// wait for more data
void Wait(void);
@@ -31,4 +36,5 @@ class cTtxtSubsReceiver : public cReceiver
uint8_t mIndexPageLines;
uint8_t mIndexPageCol;
uint16_t mIndexPageNo;
+ encodedPTS mPTS;
};
diff --git a/ttxtsubsrecorder.c b/ttxtsubsrecorder.c
index 7cfb5c0..e31ec67 100644
--- a/ttxtsubsrecorder.c
+++ b/ttxtsubsrecorder.c
@@ -19,7 +19,7 @@
// ----- cTtxtSubsRecorder -----
-cTtxtSubsRecorder::cTtxtSubsRecorder(cDevice *dev, const cChannel *ch, char *lang, int HI)
+cTtxtSubsRecorder::cTtxtSubsRecorder(cDevice *dev, const cChannel *ch)
:
mDev(dev),
mSid(ch->Sid()),
@@ -35,7 +35,7 @@ cTtxtSubsRecorder::cTtxtSubsRecorder(cDevice *dev, const cChannel *ch, char *lan
if(GetTtxtInfo(dev->CardIndex(), ch->Number(), ch->Sid(), ch->Vpid(), mTtxtinfo)) {
fprintf(stderr, "cTtxtSubsRecorder::cTtxtSubsRecorder: GetTtxtSubtitleInfo error!\n");
} else {
- pi = FindSubs(mTtxtinfo, lang, HI, &pid, &page);
+ pi = FindSubs(mTtxtinfo, &pid, &page);
if(!pi && mTtxtinfo->pidcount > 0) {
pi = &(mTtxtinfo->p[0]);
@@ -73,6 +73,7 @@ uint8_t *cTtxtSubsRecorder::GetPacket(uint8_t **outbuf, size_t *lenp)
size_t len;
uint8_t *b = (uint8_t *) mPacketBuffer;
uint8_t line[46];
+ encodedPTS pts;
*outbuf = NULL;
@@ -81,7 +82,7 @@ uint8_t *cTtxtSubsRecorder::GetPacket(uint8_t **outbuf, size_t *lenp)
len = 46; // skip PES header area
- if(mReceiver->Get(line)) {
+ if(mReceiver->Get(line, &pts)) {
// if first line is a Y0, insert an index page
// XXX This isn't really correct, we don't know if there is parallel magazine
// transmission and a page in the index pages' mag is in progress...
@@ -133,11 +134,23 @@ uint8_t *cTtxtSubsRecorder::GetPacket(uint8_t **outbuf, size_t *lenp)
0x00, 0x00, // len
0x80, // 10 and flags
0x00, // PTS_DTS_flags and other flags
- 0x24}; // PES_header_data_length
+ 0x24, // PES_header_data_length
+ 0xff, 0xff, 0xff, 0xff, 0xff}; // PTS
memcpy((char *) b, (char *) header, sizeof(header));
b[4] = (len-6) >> 8;
b[5] = (len-6) & 0xff;
+#define TEST_RECORD_PTS 1
+#if TEST_RECORD_PTS
+ if(pts.valid) {
+ b[7] |= 0x80;
+ b[9] = pts.data[0];
+ b[10] = pts.data[1];
+ b[11] = pts.data[2];
+ b[12] = pts.data[3];
+ b[13] = pts.data[4];
+ }
+#endif
memset((char *) b + sizeof(header), 0xff, 45 - sizeof(header)); // add stuffing bytes
b[45] = 0x1f; // EBU data, our payload type to indicate we have filtered data
diff --git a/ttxtsubsrecorder.h b/ttxtsubsrecorder.h
index bb9182a..d3ef7ac 100644
--- a/ttxtsubsrecorder.h
+++ b/ttxtsubsrecorder.h
@@ -6,7 +6,7 @@ struct ttxtinfo;
class cTtxtSubsRecorder : public cTtxtSubsRecorderBase {
public:
- cTtxtSubsRecorder(cDevice *dev, const cChannel *ch, char *lang, int HI);
+ cTtxtSubsRecorder(cDevice *dev, const cChannel *ch);
virtual ~cTtxtSubsRecorder();
// returns a PES packet if there is data to add to the recording