diff options
21 files changed, 1089 insertions, 20 deletions
diff --git a/multimedia/vdr-plugin-control/Makefile b/multimedia/vdr-plugin-control/Makefile index 367fc138b3f8..9098bb22d478 100644 --- a/multimedia/vdr-plugin-control/Makefile +++ b/multimedia/vdr-plugin-control/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-control PORTVERSION= 0.0.2a45 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES= multimedia MASTER_SITES= http://ricomp.de/vdr/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION:S/a45/a/}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-epgsearch/Makefile b/multimedia/vdr-plugin-epgsearch/Makefile index 68f58272c124..726a882cdcce 100644 --- a/multimedia/vdr-plugin-epgsearch/Makefile +++ b/multimedia/vdr-plugin-epgsearch/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-epgsearch PORTVERSION= 0.9.25b20s20110221 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= multimedia MASTER_SITES= http://winni.vdr-developer.org/epgsearch/downloads/beta/:beta \ LOCAL/nox/:snapshot diff --git a/multimedia/vdr-plugin-femon/Makefile b/multimedia/vdr-plugin-femon/Makefile index 3f48f4945f5c..31a133284fde 100644 --- a/multimedia/vdr-plugin-femon/Makefile +++ b/multimedia/vdr-plugin-femon/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-femon PORTVERSION= 1.7.9 -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= multimedia MASTER_SITES= http://www.saunalahti.fi/~rahrenbe/vdr/femon/files/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-infosatepg/Makefile b/multimedia/vdr-plugin-infosatepg/Makefile index 39e232c11f49..ace434f3584c 100644 --- a/multimedia/vdr-plugin-infosatepg/Makefile +++ b/multimedia/vdr-plugin-infosatepg/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-infosatepg PORTVERSION= 0.0.11 -PORTREVISION= 8 +PORTREVISION= 9 CATEGORIES= multimedia MASTER_SITES= http://projects.vdr-developer.org/attachments/download/342/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-iptv/Makefile b/multimedia/vdr-plugin-iptv/Makefile index d386bdbc1ece..ede17f5da3f8 100644 --- a/multimedia/vdr-plugin-iptv/Makefile +++ b/multimedia/vdr-plugin-iptv/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-iptv PORTVERSION= 0.4.2 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES= multimedia MASTER_SITES= http://www.saunalahti.fi/~rahrenbe/vdr/iptv/files/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-markad/Makefile b/multimedia/vdr-plugin-markad/Makefile index ea9dfb0b7a1e..3d5386e1962e 100644 --- a/multimedia/vdr-plugin-markad/Makefile +++ b/multimedia/vdr-plugin-markad/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-markad PORTVERSION= 0.1.2 -PORTREVISION= 1 +PORTREVISION= 2 CATEGORIES= multimedia MASTER_SITES= http://projects.vdr-developer.org/attachments/download/578/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-osdpip/Makefile b/multimedia/vdr-plugin-osdpip/Makefile index 53185a542a62..5fdb637620c5 100644 --- a/multimedia/vdr-plugin-osdpip/Makefile +++ b/multimedia/vdr-plugin-osdpip/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-osdpip PORTVERSION= 0.1.0 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES= multimedia MASTER_SITES= http://projects.vdr-developer.org/attachments/download/267/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-osdteletext/Makefile b/multimedia/vdr-plugin-osdteletext/Makefile index ca0c7886b258..7a9bbb32a932 100644 --- a/multimedia/vdr-plugin-osdteletext/Makefile +++ b/multimedia/vdr-plugin-osdteletext/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-osdteletext PORTVERSION= 0.9.0 -PORTREVISION= 6 +PORTREVISION= 7 CATEGORIES= multimedia MASTER_SITES= http://projects.vdr-developer.org/attachments/download/416/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-reelchannelscan/Makefile b/multimedia/vdr-plugin-reelchannelscan/Makefile index 6f1ba58d5249..03f85323303c 100644 --- a/multimedia/vdr-plugin-reelchannelscan/Makefile +++ b/multimedia/vdr-plugin-reelchannelscan/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-reelchannelscan PORTVERSION= 0.6.1b1.7.15 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= multimedia MASTER_SITES= LOCAL/nox \ http://ppa.launchpad.net/yavdr/stable-vdr/ubuntu/pool/main/v/vdr-plugin-reelchannelscan/ diff --git a/multimedia/vdr-plugin-remote/Makefile b/multimedia/vdr-plugin-remote/Makefile index 7517e12d05b8..2d9054531513 100644 --- a/multimedia/vdr-plugin-remote/Makefile +++ b/multimedia/vdr-plugin-remote/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-remote PORTVERSION= 0.4.0 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES= multimedia MASTER_SITES= http://www.escape-edv.de/endriss/vdr/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-skinenigmang/Makefile b/multimedia/vdr-plugin-skinenigmang/Makefile index e9b7cd2e7678..f53851c62010 100644 --- a/multimedia/vdr-plugin-skinenigmang/Makefile +++ b/multimedia/vdr-plugin-skinenigmang/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-skinenigmang PORTVERSION= 0.1.1 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES= multimedia MASTER_SITES= http://andreas.vdr-developer.org/enigmang/download/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-softdevice/Makefile b/multimedia/vdr-plugin-softdevice/Makefile index f4f21c522389..d3cb15dc4d51 100644 --- a/multimedia/vdr-plugin-softdevice/Makefile +++ b/multimedia/vdr-plugin-softdevice/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-softdevice PORTVERSION= 0.5.0p20100414 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES= multimedia MASTER_SITES= LOCAL MASTER_SITE_SUBDIR= nox/ diff --git a/multimedia/vdr-plugin-streamdev/Makefile b/multimedia/vdr-plugin-streamdev/Makefile index c884433634a6..ae9eb04f4fd3 100644 --- a/multimedia/vdr-plugin-streamdev/Makefile +++ b/multimedia/vdr-plugin-streamdev/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-streamdev PORTVERSION= 0.5.1 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= multimedia MASTER_SITES= http://projects.vdr-developer.org/attachments/download/497/:release \ LOCAL:snapshot diff --git a/multimedia/vdr-plugin-upnp/Makefile b/multimedia/vdr-plugin-upnp/Makefile index 400e67ce756f..1352c1e839c4 100644 --- a/multimedia/vdr-plugin-upnp/Makefile +++ b/multimedia/vdr-plugin-upnp/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-upnp PORTVERSION= 0.0.2a2 -PORTREVISION= 9 +PORTREVISION= 10 CATEGORIES= multimedia MASTER_SITES= http://projects.vdr-developer.org/attachments/download/177/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION:S/a/-alpha/}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-vnsiserver/Makefile b/multimedia/vdr-plugin-vnsiserver/Makefile index 20a1ea334c94..1ab359f66952 100644 --- a/multimedia/vdr-plugin-vnsiserver/Makefile +++ b/multimedia/vdr-plugin-vnsiserver/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-vnsiserver PORTVERSION= 0.0.2s20100808.0952 -PORTREVISION= 7 +PORTREVISION= 8 CATEGORIES= multimedia MASTER_SITES= http://ppa.launchpad.net/yavdr/testing-vdr/ubuntu/pool/main/v/vdr-plugin-vnsiserver/ \ LOCAL/nox/ diff --git a/multimedia/vdr-plugin-wirbelscan/Makefile b/multimedia/vdr-plugin-wirbelscan/Makefile index 4b23843a8bb6..55c2129341fe 100644 --- a/multimedia/vdr-plugin-wirbelscan/Makefile +++ b/multimedia/vdr-plugin-wirbelscan/Makefile @@ -7,6 +7,7 @@ PORTNAME= vdr-plugin-wirbelscan PORTVERSION= 0.0.7 +PORTREVISION= 1 CATEGORIES= multimedia MASTER_SITES= http://wirbel.htpc-forum.de/wirbelscan/ DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX} diff --git a/multimedia/vdr-plugin-xineliboutput/Makefile b/multimedia/vdr-plugin-xineliboutput/Makefile index bc3cc4b17fae..6bc7a5252872 100644 --- a/multimedia/vdr-plugin-xineliboutput/Makefile +++ b/multimedia/vdr-plugin-xineliboutput/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr-plugin-xineliboutput PORTVERSION= 1.0.90s20110308.2305 -PORTREVISION= 8 +PORTREVISION= 9 CATEGORIES= multimedia MASTER_SITES= SF:release \ LOCAL:snapshot diff --git a/multimedia/vdr/Makefile b/multimedia/vdr/Makefile index 8d9733d59921..5e08686308b8 100644 --- a/multimedia/vdr/Makefile +++ b/multimedia/vdr/Makefile @@ -7,7 +7,7 @@ PORTNAME= vdr PORTVERSION= 1.7.18 -PORTREVISION= 2 +PORTREVISION= 3 CATEGORIES= multimedia MASTER_SITES= ftp://ftp.tvdr.de/vdr/Developer/ @@ -19,7 +19,8 @@ LIB_DEPENDS= jpeg.11:${PORTSDIR}/graphics/jpeg BUILD_DEPENDS+= ${LOCALBASE}/libdata/pkgconfig/fontconfig.pc:${PORTSDIR}/x11-fonts/fontconfig RUN_DEPENDS+= ${LOCALBASE}/libdata/pkgconfig/fontconfig.pc:${PORTSDIR}/x11-fonts/fontconfig -OPTIONS= IPTVPATCH "Stops EIT scans on IPTV channels" On +OPTIONS= IPTVPATCH "Stops EIT scans on IPTV channels" On \ + TTXPATCH "Support patches for teletext subtitle plugin" On DIST_SUBDIR= vdr USE_BZIP2= yes @@ -52,9 +53,15 @@ PLIST_SUB+= VDR_GROUP=${VDR_GROUP} .include <bsd.port.options.mk> +EXTRA_PATCHES+= ${FILESDIR}/vdr-1.7.15-disable_ca_updates.patch .if defined(WITH_IPTVPATCH) -EXTRA_PATCHES+= ${FILESDIR}/vdr-1.7.15-disable_ca_updates.patch \ - ${FILESDIR}/vdr-1.7.15-disable_eitscan.patch +EXTRA_PATCHES+= ${FILESDIR}/vdr-1.7.15-disable_eitscan.patch +.endif + +.if defined(WITH_TTXPATCH) +PLIST_SUB+= TTXPATCH="" +.else +PLIST_SUB+= TTXPATCH="@comment " .endif .if !defined(WITHOUT_NLS) @@ -65,6 +72,10 @@ ALL_TARGET= vdr plugins .endif post-patch: +.if defined(WITH_TTXPATCH) + @${PATCH} -d ${WRKSRC} --quiet -p1 <${FILESDIR}/vdr-1.7.15-ttxtsubs.patch-1 + @${PATCH} -d ${WRKSRC} --quiet -p1 <${FILESDIR}/vdr-1.7.15-ttxtsubs.patch-2 +.endif @${SED} 's|^\(VIDEODIR[[:space:]]*\)[?]*\(=[[:space:]]*\).*|\1\2${VIDEODIR}|' \ ${WRKSRC}/Make.config.template >${WRKSRC}/Make.config @${REINPLACE_CMD} -e 's|%%CONFDIR%%|${CONFDIR}|' ${WRKSRC}/vdr.1 diff --git a/multimedia/vdr/files/vdr-1.7.15-ttxtsubs.patch-1 b/multimedia/vdr/files/vdr-1.7.15-ttxtsubs.patch-1 new file mode 100644 index 000000000000..acd3b283d8f8 --- /dev/null +++ b/multimedia/vdr/files/vdr-1.7.15-ttxtsubs.patch-1 @@ -0,0 +1,877 @@ +diff --git a/MANUAL b/MANUAL +index 7fae53b..6b0ae57 100644 +--- a/MANUAL ++++ b/MANUAL +@@ -730,6 +730,9 @@ Version 1.6 + background transparency. By default the values as broadcast + are used. + ++ Record Teletext Subtitles = no ++ If set to 'yes', teletext subtitles will be recorded. ++ + LNB: + + SLOF = 11700 The switching frequency (in MHz) between low and +diff --git a/Makefile b/Makefile +index d788484..f854b2e 100644 +--- a/Makefile ++++ b/Makefile +@@ -44,6 +44,8 @@ OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o d + skinclassic.o skins.o skinsttng.o sourceparams.o sources.o spu.o status.o svdrp.o themes.o thread.o\ + timers.o tools.o transfer.o vdr.o videodir.o + ++OBJS += vdrttxtsubshooks.o ++ + ifndef NO_KBD + DEFINES += -DREMOTE_KBD + endif +diff --git a/channels.h b/channels.h +index b867297..63c8b9c 100644 +--- a/channels.h ++++ b/channels.h +@@ -35,6 +35,7 @@ + #define MAXDPIDS 16 // dolby (AC3 + DTS) + #define MAXSPIDS 32 // subtitles + #define MAXCAIDS 8 // conditional access ++#define MAXTXTPAGES 8 // teletext pages + + #define MAXLANGCODE1 4 // a 3 letter language code, zero terminated + #define MAXLANGCODE2 8 // up to two 3 letter language codes, separated by '+' and zero terminated +@@ -71,6 +72,16 @@ public: + static const tChannelID InvalidID; + }; + ++struct tTeletextSubtitlePage { ++ tTeletextSubtitlePage(void) { ttxtPage = ttxtMagazine = 0; ttxtType = 0x02; strcpy(ttxtLanguage, "und"); } ++ tTeletextSubtitlePage(int page) { ttxtMagazine = (page / 100) & 0x7; ttxtPage = (((page % 100) / 10) << 4) + (page % 10); ttxtType = 0x02; strcpy(ttxtLanguage, "und"); } ++ char ttxtLanguage[MAXLANGCODE1]; ++ uchar ttxtPage; ++ uchar ttxtMagazine; ++ uchar ttxtType; ++ int PageNumber(void) const { return BCDCHARTOINT(ttxtMagazine) * 100 + BCDCHARTOINT(ttxtPage); } ++ }; ++ + class cChannel; + + class cLinkChannel : public cListObject { +@@ -115,6 +126,9 @@ private: + uint16_t compositionPageIds[MAXSPIDS]; + uint16_t ancillaryPageIds[MAXSPIDS]; + int tpid; ++ int fixedTtxtSubtitlePages; ++ int totalTtxtSubtitlePages; ++ tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]; + int caids[MAXCAIDS + 1]; // list is zero-terminated + int nid; + int tid; +@@ -164,6 +178,8 @@ public: + uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? compositionPageIds[i] : uint16_t(0); } + uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); } + int Tpid(void) const { return tpid; } ++ const tTeletextSubtitlePage *TeletextSubtitlePages() const { return teletextSubtitlePages; } ++ int TotalTeletextSubtitlePages() const { return totalTtxtSubtitlePages; } + const int *Caids(void) const { return caids; } + int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; } + int Nid(void) const { return nid; } +@@ -190,6 +206,7 @@ public: + void SetName(const char *Name, const char *ShortName, const char *Provider); + void SetPortalName(const char *PortalName); + void SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid); ++ void SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages); + void SetCaIds(const int *CaIds); // list must be zero-terminated + void SetCaDescriptors(int Level); + void SetLinkChannels(cLinkChannels *LinkChannels); +diff --git a/ci.c b/ci.c +index 6c7b031..22fda9f 100644 +--- a/ci.c ++++ b/ci.c +@@ -1911,6 +1911,8 @@ void cCamSlot::AddChannel(const cChannel *Channel) + AddPid(Channel->Sid(), *Apid, STREAM_TYPE_AUDIO); + for (const int *Dpid = Channel->Dpids(); *Dpid; Dpid++) + AddPid(Channel->Sid(), *Dpid, STREAM_TYPE_DOLBY); ++ if (Channel->Tpid() && Setup.SupportTeletext) ++ AddPid(Channel->Sid(), Channel->Tpid(), STREAM_TYPE_DOLBY); + } + } + +@@ -1932,6 +1934,9 @@ bool cCamSlot::CanDecrypt(const cChannel *Channel) + CaPmt.AddPid(*Apid, STREAM_TYPE_AUDIO); + for (const int *Dpid = Channel->Dpids(); *Dpid; Dpid++) + CaPmt.AddPid(*Dpid, STREAM_TYPE_DOLBY); ++ if (Channel->Tpid() && Setup.SupportTeletext) { ++ CaPmt.AddPid(Channel->Tpid(), STREAM_TYPE_DOLBY); // FIXME: STREAM_TYPE_DOLBY should probably be renamed STREAM_TYPE_PRIVATE ++ } + cas->SendPMT(&CaPmt); + cTimeMs Timeout(QUERY_REPLY_TIMEOUT); + do { +diff --git a/config.c b/config.c +index 73b11b1..f2eebe6 100644 +--- a/config.c ++++ b/config.c +@@ -333,6 +333,7 @@ cSetup::cSetup(void) + MarginStop = 10; + AudioLanguages[0] = -1; + DisplaySubtitles = 0; ++ SupportTeletext = 0; + SubtitleLanguages[0] = -1; + SubtitleOffset = 0; + SubtitleFgTransparency = 0; +@@ -524,6 +525,7 @@ bool cSetup::Parse(const char *Name, const char *Value) + else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value); + else if (!strcasecmp(Name, "AudioLanguages")) return ParseLanguages(Value, AudioLanguages); + else if (!strcasecmp(Name, "DisplaySubtitles")) DisplaySubtitles = atoi(Value); ++ else if (!strcasecmp(Name, "SupportTeletext")) SupportTeletext = atoi(Value); + else if (!strcasecmp(Name, "SubtitleLanguages")) return ParseLanguages(Value, SubtitleLanguages); + else if (!strcasecmp(Name, "SubtitleOffset")) SubtitleOffset = atoi(Value); + else if (!strcasecmp(Name, "SubtitleFgTransparency")) SubtitleFgTransparency = atoi(Value); +@@ -620,6 +622,7 @@ bool cSetup::Save(void) + Store("MarginStop", MarginStop); + StoreLanguages("AudioLanguages", AudioLanguages); + Store("DisplaySubtitles", DisplaySubtitles); ++ Store("SupportTeletext", SupportTeletext); + StoreLanguages("SubtitleLanguages", SubtitleLanguages); + Store("SubtitleOffset", SubtitleOffset); + Store("SubtitleFgTransparency", SubtitleFgTransparency); +diff --git a/config.h b/config.h +index 7041eb7..289d4b6 100644 +--- a/config.h ++++ b/config.h +@@ -235,6 +235,7 @@ public: + int MarginStart, MarginStop; + int AudioLanguages[I18N_MAX_LANGUAGES + 1]; + int DisplaySubtitles; ++ int SupportTeletext; + int SubtitleLanguages[I18N_MAX_LANGUAGES + 1]; + int SubtitleOffset; + int SubtitleFgTransparency, SubtitleBgTransparency; +diff --git a/device.c b/device.c +index 681049b..4dbd920 100644 +--- a/device.c ++++ b/device.c +@@ -18,6 +18,7 @@ + #include "receiver.h" + #include "status.h" + #include "transfer.h" ++#include "vdrttxtsubshooks.h" + + // --- cLiveSubtitle --------------------------------------------------------- + +@@ -1223,6 +1224,13 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) + } + break; + case 0xBD: { // private stream 1 ++ // EBU Teletext data, ETSI EN 300 472 ++ // if PES data header length = 24 and data_identifier = 0x10..0x1F (EBU Data) ++ if (Data[8] == 0x24 && Data[45] >= 0x10 && Data[45] < 0x20) { ++ cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uint8_t*)Data, Length); ++ break; ++ } ++ + int PayloadOffset = Data[8] + 9; + + // Compatibility mode for old subtitles plugin: +@@ -1382,6 +1390,7 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly) + tsToPesVideo.Reset(); + tsToPesAudio.Reset(); + tsToPesSubtitle.Reset(); ++ tsToPesTeletext.Reset(); + } + else if (Length < TS_SIZE) { + esyslog("ERROR: skipped %d bytes of TS fragment", Length); +@@ -1427,6 +1436,17 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly) + if (!VideoOnly || HasIBPTrickSpeed()) + PlayTsSubtitle(Data, TS_SIZE); + } ++ else if (Pid == patPmtParser.Tpid()) { ++ if (!VideoOnly || HasIBPTrickSpeed()) { ++ int l; ++ tsToPesTeletext.PutTs(Data, Length); ++ if (const uchar *p = tsToPesTeletext.GetPes(l)) { ++ if ((l > 45) && (p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xbd) && (p[8] == 0x24) && (p[45] >= 0x10) && (p[45] < 0x20)) ++ cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uchar *)p, l, false, patPmtParser.TeletextSubtitlePages(), patPmtParser.TotalTeletextSubtitlePages()); ++ tsToPesTeletext.Reset(); ++ } ++ } ++ } + } + } + else if (Pid == patPmtParser.Ppid()) { +diff --git a/device.h b/device.h +index cb3bc2c..f531e70 100644 +--- a/device.h ++++ b/device.h +@@ -522,6 +522,7 @@ private: + cTsToPes tsToPesVideo; + cTsToPes tsToPesAudio; + cTsToPes tsToPesSubtitle; ++ cTsToPes tsToPesTeletext; + bool isPlayingVideo; + protected: + const cPatPmtParser *PatPmtParser(void) const { return &patPmtParser; } +diff --git a/menu.c b/menu.c +index 19cfabb..d2deeb3 100644 +--- a/menu.c ++++ b/menu.c +@@ -2790,6 +2790,7 @@ void cMenuSetupDVB::Setup(void) + Add(new cMenuEditIntItem( tr("Setup.DVB$Subtitle foreground transparency"), &data.SubtitleFgTransparency, 0, 9)); + Add(new cMenuEditIntItem( tr("Setup.DVB$Subtitle background transparency"), &data.SubtitleBgTransparency, 0, 10)); + } ++ Add(new cMenuEditBoolItem(tr("Setup.DVB$Enable teletext support"), &data.SupportTeletext)); + + SetCurrent(Get(current)); + Display(); +diff --git a/po/ca_ES.po b/po/ca_ES.po +index 247113b..aba1ae3 100644 +--- a/po/ca_ES.po ++++ b/po/ca_ES.po +@@ -943,6 +943,9 @@ msgstr "Transpar + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparncia fons subttols" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "Configuraci de l'LNB" + +diff --git a/po/cs_CZ.po b/po/cs_CZ.po +index f6313ba..aec6f4e 100644 +--- a/po/cs_CZ.po ++++ b/po/cs_CZ.po +@@ -942,6 +942,9 @@ msgstr "Průhlednost písma titulků" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Průhlednost pozadí titulků" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/da_DK.po b/po/da_DK.po +index 40cdebd..192173d 100644 +--- a/po/da_DK.po ++++ b/po/da_DK.po +@@ -940,6 +940,9 @@ msgstr "Undertekst forgrundsgennemsigtighed" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Undertekst baggrundsgennemsigtighed" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/de_DE.po b/po/de_DE.po +index 4d4f3df..a3227a0 100644 +--- a/po/de_DE.po ++++ b/po/de_DE.po +@@ -940,6 +940,9 @@ msgstr "Untertitel-Transparenz Vordergrund" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Untertitel-Transparenz Hintergrund" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "Videotext-Untersttzung aktivieren" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/el_GR.po b/po/el_GR.po +index 5414ebc..913f39e 100644 +--- a/po/el_GR.po ++++ b/po/el_GR.po +@@ -940,6 +940,9 @@ msgstr "" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/es_ES.po b/po/es_ES.po +index 217f775..78a9491 100644 +--- a/po/es_ES.po ++++ b/po/es_ES.po +@@ -941,6 +941,9 @@ msgstr "Transparencia primer plano subt + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparencia fondo subttulos" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/et_EE.po b/po/et_EE.po +index 5010dc4..af2e2d3 100644 +--- a/po/et_EE.po ++++ b/po/et_EE.po +@@ -940,6 +940,9 @@ msgstr "Subtiitri l + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Subtiitri tausta lbipaistvus" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "Teleteksti tugi" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/fi_FI.po b/po/fi_FI.po +index cd57e7c..e6a22bf 100644 +--- a/po/fi_FI.po ++++ b/po/fi_FI.po +@@ -943,6 +943,9 @@ msgstr "Tekstityksen läpinäkyvyys" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Tekstityksen taustan läpinäkyvyys" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "Salli teksti-TV-tuki" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/fr_FR.po b/po/fr_FR.po +index 0d4cb7c..770038e 100644 +--- a/po/fr_FR.po ++++ b/po/fr_FR.po +@@ -946,6 +946,9 @@ msgstr "Transparence de l'avant-plan" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparence du fond" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/hr_HR.po b/po/hr_HR.po +index 96ee695..51f596c 100644 +--- a/po/hr_HR.po ++++ b/po/hr_HR.po +@@ -942,6 +942,9 @@ msgstr "Transparentnost titla" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparentnost pozadine titla" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/hu_HU.po b/po/hu_HU.po +index a17b209..2f70812 100644 +--- a/po/hu_HU.po ++++ b/po/hu_HU.po +@@ -943,6 +943,9 @@ msgstr "Felirat transzparenci + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Felirat htternek transzparencija" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/it_IT.po b/po/it_IT.po +index 89d4237..5a055b2 100644 +--- a/po/it_IT.po ++++ b/po/it_IT.po +@@ -947,6 +947,9 @@ msgstr "Trasparenza sottotitoli" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Trasparenza sfondo sottotitoli" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/lt_LT.po b/po/lt_LT.po +index 02465e6..8b5d996 100644 +--- a/po/lt_LT.po ++++ b/po/lt_LT.po +@@ -940,6 +940,9 @@ msgstr "Subtitrų priekinio vaizdo permatomumas" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Subtitrų fono permatomumas" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "Konverteris (LNB)" + +diff --git a/po/nl_NL.po b/po/nl_NL.po +index f570337..73a02b3 100644 +--- a/po/nl_NL.po ++++ b/po/nl_NL.po +@@ -944,6 +944,9 @@ msgstr "Transparantie voorgrond ondertiteling" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparantie achtergrond ondertiteling" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/nn_NO.po b/po/nn_NO.po +index 2f40cfe..0934c9a 100644 +--- a/po/nn_NO.po ++++ b/po/nn_NO.po +@@ -941,6 +941,9 @@ msgstr "" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/pl_PL.po b/po/pl_PL.po +index 9620e1b..39057fd 100644 +--- a/po/pl_PL.po ++++ b/po/pl_PL.po +@@ -941,6 +941,9 @@ msgstr "Prze + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Przerocze podtytuw: To" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/pt_PT.po b/po/pt_PT.po +index 0510d9d..3bea1f1 100644 +--- a/po/pt_PT.po ++++ b/po/pt_PT.po +@@ -940,6 +940,9 @@ msgstr "Transpar + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparncia de background das legendas" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/ro_RO.po b/po/ro_RO.po +index e0a2119..1d4a412 100644 +--- a/po/ro_RO.po ++++ b/po/ro_RO.po +@@ -943,6 +943,9 @@ msgstr "Transparen + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparena fundalului subtitrrii" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/ru_RU.po b/po/ru_RU.po +index 889b98b..89029e1 100644 +--- a/po/ru_RU.po ++++ b/po/ru_RU.po +@@ -941,6 +941,9 @@ msgstr " + msgid "Setup.DVB$Subtitle background transparency" + msgstr " " + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "" + +diff --git a/po/sk_SK.po b/po/sk_SK.po +index 129fad3..eff0bd1 100644 +--- a/po/sk_SK.po ++++ b/po/sk_SK.po +@@ -941,6 +941,9 @@ msgstr "Prieh + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Priehadnos pozadia titulkov" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/sl_SI.po b/po/sl_SI.po +index 9f1e806..7f2bdd7 100644 +--- a/po/sl_SI.po ++++ b/po/sl_SI.po +@@ -941,6 +941,9 @@ msgstr "Transparentnost podnapisov" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparentnost ozadja podnapisov" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/sv_SE.po b/po/sv_SE.po +index e9d39dd..9c366d2 100644 +--- a/po/sv_SE.po ++++ b/po/sv_SE.po +@@ -943,6 +943,9 @@ msgstr "Transparent f + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Transparent bakgrund textremsa" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/tr_TR.po b/po/tr_TR.po +index 9acd1c1..50a6295 100644 +--- a/po/tr_TR.po ++++ b/po/tr_TR.po +@@ -940,6 +940,9 @@ msgstr "Altyaz + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Altyaz arka effaflk" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "LNB" + +diff --git a/po/uk_UA.po b/po/uk_UA.po +index b62fca7..25e7095 100644 +--- a/po/uk_UA.po ++++ b/po/uk_UA.po +@@ -940,6 +940,9 @@ msgstr "Прозорість переднього плану субтитрів" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "Прозорість заднього плану субтитрів" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "Конвертер" + +diff --git a/po/zh_CN.po b/po/zh_CN.po +index bffa301..141c362 100644 +--- a/po/zh_CN.po ++++ b/po/zh_CN.po +@@ -943,6 +943,9 @@ msgstr "字幕前景透明度" + msgid "Setup.DVB$Subtitle background transparency" + msgstr "字幕背景透明度" + ++msgid "Setup.DVB$Enable teletext support" ++msgstr "" ++ + msgid "LNB" + msgstr "切换器设置" + +diff --git a/receiver.c b/receiver.c +index 58dda78..ed28f1b 100644 +--- a/receiver.c ++++ b/receiver.c +@@ -82,7 +82,8 @@ bool cReceiver::SetPids(const cChannel *Channel) + (Channel->Ppid() == Channel->Vpid() || AddPid(Channel->Ppid())) && + AddPids(Channel->Apids()) && + AddPids(Channel->Dpids()) && +- AddPids(Channel->Spids()); ++ AddPids(Channel->Spids()) && ++ (!Setup.SupportTeletext || AddPid(Channel->Tpid())); + } + return true; + } +diff --git a/remux.c b/remux.c +index 5206544..eea5c07 100644 +--- a/remux.c ++++ b/remux.c +@@ -215,6 +215,29 @@ int cPatPmtGenerator::MakeSubtitlingDescriptor(uchar *Target, const char *Langua + return i; + } + ++int cPatPmtGenerator::MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount) ++{ ++ int i = 0, j = 0; ++ Target[i++] = SI::TeletextDescriptorTag; ++ int l = i; ++ Target[i++] = 0x00; // length ++ for (int n = 0; n < pageCount; n++) { ++ const char* Language = pages[n].ttxtLanguage; ++ Target[i++] = *Language++; ++ Target[i++] = *Language++; ++ Target[i++] = *Language++; ++ Target[i++] = (pages[n].ttxtType << 3) + pages[n].ttxtMagazine; ++ Target[i++] = pages[n].ttxtPage; ++ j++; ++ } ++ if (j > 0) { ++ Target[l] = j * 5; // update length ++ IncEsInfoLength(i); ++ return i; ++ } ++ return 0; ++} ++ + int cPatPmtGenerator::MakeLanguageDescriptor(uchar *Target, const char *Language) + { + int i = 0; +@@ -302,6 +325,7 @@ void cPatPmtGenerator::GeneratePmt(const cChannel *Channel) + if (Channel) { + int Vpid = Channel->Vpid(); + int Ppid = Channel->Ppid(); ++ int Tpid = Channel->Tpid(); + uchar *p = buf; + int i = 0; + p[i++] = 0x02; // table id +@@ -334,6 +358,10 @@ void cPatPmtGenerator::GeneratePmt(const cChannel *Channel) + i += MakeStream(buf + i, 0x06, Channel->Spid(n)); + i += MakeSubtitlingDescriptor(buf + i, Channel->Slang(n), Channel->SubtitlingType(n), Channel->CompositionPageId(n), Channel->AncillaryPageId(n)); + } ++ if (Tpid) { ++ i += MakeStream(buf + i, 0x06, Tpid); ++ i += MakeTeletextDescriptor(buf + i, Channel->TeletextSubtitlePages(), Channel->TotalTeletextSubtitlePages()); ++ } + + int sl = i - SectionLength - 2 + 4; // -2 = SectionLength storage, +4 = length of CRC + buf[SectionLength] |= (sl >> 8) & 0x0F; +@@ -407,6 +435,7 @@ void cPatPmtParser::Reset(void) + pmtPid = -1; + vpid = vtype = 0; + ppid = 0; ++ tpid = 0; + } + + void cPatPmtParser::ParsePat(const uchar *Data, int Length) +@@ -492,11 +521,13 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) + int NumSpids = 0; + vpid = vtype = 0; + ppid = 0; ++ tpid = 0; + apids[0] = 0; + dpids[0] = 0; + spids[0] = 0; + atypes[0] = 0; + dtypes[0] = 0; ++ totalTtxtSubtitlePages = 0; + SI::PMT::Stream stream; + for (SI::Loop::Iterator it; Pmt.streamLoop.getNext(stream, it); ) { + dbgpatpmt(" stream type = %02X, pid = %d", stream.getStreamType(), stream.getPid()); +@@ -595,6 +626,28 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) + spids[NumSpids]= 0; + } + break; ++ case SI::TeletextDescriptorTag: { ++ dbgpatpmt(" teletext"); ++ tpid = stream.getPid(); ++ SI::TeletextDescriptor *sd = (SI::TeletextDescriptor *)d; ++ SI::TeletextDescriptor::Teletext ttxt; ++ if (totalTtxtSubtitlePages < MAXTXTPAGES) { ++ for (SI::Loop::Iterator it; sd->teletextLoop.getNext(ttxt, it); ) { ++ bool isSubtitlePage = (ttxt.getTeletextType() == 0x02) || (ttxt.getTeletextType() == 0x05); ++ if (isSubtitlePage && ttxt.languageCode[0]) { ++ dbgpatpmt(" '%s:%x.%x'", ttxt.languageCode, ttxt.getTeletextMagazineNumber(), ttxt.getTeletextPageNumber()); ++ strn0cpy(teletextSubtitlePages[totalTtxtSubtitlePages].ttxtLanguage, I18nNormalizeLanguageCode(ttxt.languageCode), MAXLANGCODE1); ++ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtPage = ttxt.getTeletextPageNumber(); ++ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtMagazine = ttxt.getTeletextMagazineNumber(); ++ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType = ttxt.getTeletextType(); ++ totalTtxtSubtitlePages++; ++ if (totalTtxtSubtitlePages >= MAXTXTPAGES) ++ break; ++ } ++ } ++ } ++ } ++ break; + case SI::ISO639LanguageDescriptorTag: { + SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; + dbgpatpmt(" '%s'", ld->languageCode); +diff --git a/remux.h b/remux.h +index 7b62187..6f816dc 100644 +--- a/remux.h ++++ b/remux.h +@@ -171,6 +171,7 @@ protected: + int MakeStream(uchar *Target, uchar Type, int Pid); + int MakeAC3Descriptor(uchar *Target, uchar Type); + int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId); ++ int MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount); + int MakeLanguageDescriptor(uchar *Target, const char *Language); + int MakeCRC(uchar *Target, const uchar *Data, int Length); + void GeneratePmtPid(const cChannel *Channel); +@@ -216,6 +217,7 @@ private: + int vpid; + int ppid; + int vtype; ++ int tpid; + int apids[MAXAPIDS + 1]; // list is zero-terminated + int atypes[MAXAPIDS + 1]; // list is zero-terminated + char alangs[MAXAPIDS][MAXLANGCODE2]; +@@ -228,6 +230,8 @@ private: + uint16_t compositionPageIds[MAXSPIDS]; + uint16_t ancillaryPageIds[MAXSPIDS]; + bool updatePrimaryDevice; ++ int totalTtxtSubtitlePages; ++ tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]; + protected: + int SectionLength(const uchar *Data, int Length) { return (Length >= 3) ? ((int(Data[1]) & 0x0F) << 8)| Data[2] : 0; } + public: +@@ -260,6 +264,9 @@ public: + int Vtype(void) const { return vtype; } + ///< Returns the video stream type as defined by the current PMT, or 0 if no video + ///< stream type has been detected, yet. ++ int Tpid(void) { return tpid; } ++ ///< Returns the teletext pid as defined by the current PMT, or 0 if no teletext ++ ///< pid has been detected, yet. + const int *Apids(void) const { return apids; } + const int *Dpids(void) const { return dpids; } + const int *Spids(void) const { return spids; } +@@ -274,6 +281,8 @@ public: + uchar SubtitlingType(int i) const { return (0 <= i && i < MAXSPIDS) ? subtitlingTypes[i] : uchar(0); } + uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? compositionPageIds[i] : uint16_t(0); } + uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); } ++ const tTeletextSubtitlePage *TeletextSubtitlePages() const { return teletextSubtitlePages; } ++ int TotalTeletextSubtitlePages() const { return totalTtxtSubtitlePages; } + }; + + // TS to PES converter: +diff --git a/vdr.5 b/vdr.5 +index 68711b5..9b8ed05 100644 +--- a/vdr.5 ++++ b/vdr.5 +@@ -214,6 +214,13 @@ if there is an audio type. + .TP + .B TPID + The teletext PID. ++ ++Fixed teletext subtitling pages can be defined separated by a semicolon. ++The pages (separated by commas) can contain ISO 639 language codes, delimited ++by a '=' sign, as in ++ ++.B ...:2001;150=deu,151=fin:... ++ + .TP + .B Conditional access + A hexadecimal integer defining how this channel can be accessed: +diff --git a/vdrttxtsubshooks.c b/vdrttxtsubshooks.c +new file mode 100644 +index 0000000..2471788 +--- /dev/null ++++ b/vdrttxtsubshooks.c +@@ -0,0 +1,63 @@ ++/* ++ * vdr-ttxtsubs - A plugin for the Linux Video Disk Recorder ++ * Copyright (c) 2003 - 2008 Ragnar Sundblad <ragge@nada.kth.se> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#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, bool IsPesRecording, const struct tTeletextSubtitlePage teletextSubtitlePages[] = NULL, int pageCount = 0) ++ { if(gListener) gListener->PlayerTeletextData(p, length, IsPesRecording, teletextSubtitlePages, pageCount); }; ++ virtual int ManualPageNumber(const cChannel *channel) ++ { if(gListener) return gListener->ManualPageNumber(channel); else return 0; }; ++}; ++ ++ ++// ------ 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 --git a/vdrttxtsubshooks.h b/vdrttxtsubshooks.h +new file mode 100644 +index 0000000..2f97969 +--- /dev/null ++++ b/vdrttxtsubshooks.h +@@ -0,0 +1,46 @@ ++/* ++ * vdr-ttxtsubs - A plugin for the Linux Video Disk Recorder ++ * Copyright (c) 2003 - 2008 Ragnar Sundblad <ragge@nada.kth.se> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your option) ++ * any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more ++ * details. ++ * ++ * You should have received a copy of the GNU General Public License along with ++ * this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#ifndef __VDRTTXTSUBSHOOKS_H ++#define __VDRTTXTSUBSHOOKS_H ++ ++#define TTXTSUBSVERSNUM 2 ++ ++class cDevice; ++class cChannel; ++struct tTeletextSubtitlePage; ++ ++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, bool IsPesRecording = true, const struct tTeletextSubtitlePage teletextSubtitlePages[] = NULL, int pageCount = 0) {}; ++ virtual int ManualPageNumber(const cChannel *channel) { return 0; }; ++ ++ // used by VDR to call hook listeners ++ static cVDRTtxtsubsHookListener *Hook(void); ++}; ++ ++#endif diff --git a/multimedia/vdr/files/vdr-1.7.15-ttxtsubs.patch-2 b/multimedia/vdr/files/vdr-1.7.15-ttxtsubs.patch-2 new file mode 100644 index 000000000000..da202831c3f3 --- /dev/null +++ b/multimedia/vdr/files/vdr-1.7.15-ttxtsubs.patch-2 @@ -0,0 +1,179 @@ +--- a/channels.c ++++ b/channels.c +@@ -383,6 +383,26 @@ void cChannel::SetSubtitlingDescriptors( + } + } + ++void cChannel::SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages) ++{ ++ int mod = CHANNELMOD_NONE; ++ if (totalTtxtSubtitlePages != (fixedTtxtSubtitlePages + numberOfPages)) ++ mod |= CHANNELMOD_PIDS; ++ totalTtxtSubtitlePages = fixedTtxtSubtitlePages; ++ for (int i = 0; (i < numberOfPages) && (totalTtxtSubtitlePages < MAXTXTPAGES); i++) { ++ if (teletextSubtitlePages[totalTtxtSubtitlePages].ttxtMagazine != pages[i].ttxtMagazine || ++ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtPage != pages[i].ttxtPage || ++ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType != pages[i].ttxtType || ++ strcmp(teletextSubtitlePages[totalTtxtSubtitlePages].ttxtLanguage, pages[i].ttxtLanguage)) { ++ mod |= CHANNELMOD_PIDS; ++ teletextSubtitlePages[totalTtxtSubtitlePages] = pages[i]; ++ } ++ totalTtxtSubtitlePages++; ++ } ++ modification |= mod; ++ Channels.SetModified(); ++} ++ + void cChannel::SetCaIds(const int *CaIds) + { + if (caids[0] && caids[0] <= CA_USER_MAX) +@@ -511,11 +531,24 @@ cString cChannel::ToText(const cChannel + q += IntArrayToString(q, Channel->dpids, 10, Channel->dlangs, Channel->dtypes); + } + *q = 0; ++ const int TBufferSize = 5 + 1 + (MAXTXTPAGES * (3 + 1 + MAXLANGCODE1 + 1)) + 10; // '12345;150=deu,151=fin,...', +10: paranoia ++ char tpidbuf[TBufferSize]; ++ q = tpidbuf; ++ q += snprintf(q, sizeof(tpidbuf), "%d", Channel->tpid); ++ if (Channel->fixedTtxtSubtitlePages > 0) { ++ q += snprintf(q, sizeof(tpidbuf) - (q - tpidbuf), ";"); ++ for (int i = 0; i < Channel->fixedTtxtSubtitlePages; ++i) { ++ tTeletextSubtitlePage page = Channel->teletextSubtitlePages[i]; ++ q += snprintf(q, sizeof(tpidbuf) - (q - tpidbuf), ++ i + 1 < Channel->fixedTtxtSubtitlePages ? "%d=%s," : "%d=%s", ++ page.PageNumber(), page.ttxtLanguage); ++ } ++ } + char caidbuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia + q = caidbuf; + q += IntArrayToString(q, Channel->caids, 16); + *q = 0; +- buffer = cString::sprintf("%s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d\n", FullName, Channel->frequency, *Channel->parameters, *cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid); ++ buffer = cString::sprintf("%s:%d:%s:%s:%d:%s:%s:%s:%s:%d:%d:%d:%d\n", FullName, Channel->frequency, *Channel->parameters, *cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, tpidbuf, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid); + } + return buffer; + } +@@ -549,6 +582,7 @@ bool cChannel::Parse(const char *s) + char *parambuf = NULL; + char *vpidbuf = NULL; + char *apidbuf = NULL; ++ char *tpidbuf = NULL; + char *caidbuf = NULL; + #ifdef __FreeBSD__ + namebuf = MALLOC(char, 256); +@@ -556,10 +590,11 @@ bool cChannel::Parse(const char *s) + parambuf = MALLOC(char, 256); + vpidbuf = MALLOC(char, 256); + apidbuf = MALLOC(char, 256); ++ tpidbuf = MALLOC(char, 256); + caidbuf = MALLOC(char, 256); +- int fields = sscanf(s, "%255[^:]:%d :%255[^:]:%9[^:] :%d :%255[^:]:%255[^:]:%d :%255[^:]:%d :%d :%d :%d ", namebuf, &frequency, parambuf, sourcebuf, &srate, vpidbuf, apidbuf, &tpid, caidbuf, &sid, &nid, &tid, &rid); ++ int fields = sscanf(s, "%255[^:]:%d :%255[^:]:%9[^:] :%d :%255[^:]:%255[^:]:%255[^:]:%255[^:]:%d :%d :%d :%d ", namebuf, &frequency, parambuf, sourcebuf, &srate, vpidbuf, apidbuf, tpidbuf, caidbuf, &sid, &nid, &tid, &rid); + #else +- int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%d :%a[^:]:%d :%d :%d :%d ", &namebuf, &frequency, ¶mbuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpid, &caidbuf, &sid, &nid, &tid, &rid); ++ int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%a[^:]:%a[^:]:%d :%d :%d :%d ", &namebuf, &frequency, ¶mbuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpidbuf, &caidbuf, &sid, &nid, &tid, &rid); + #endif + if (fields >= 9) { + if (fields == 9) { +@@ -659,7 +694,37 @@ bool cChannel::Parse(const char *s) + dpids[NumDpids] = 0; + dtypes[NumDpids] = 0; + } +- ++ if (tpidbuf) { ++ char *p; ++ fixedTtxtSubtitlePages = 0; ++ // 2001;150=deu,151=fin ++ if ((p = strchr(tpidbuf, ';')) != NULL) { ++ char *q, *strtok_next; ++ *p++ = 0; ++ while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { ++ if (fixedTtxtSubtitlePages < MAXTXTPAGES) { ++ int page; ++ char *l = strchr(q, '='); ++ if (l) ++ *l++ = 0; ++ if (sscanf(q, "%d", &page) == 1) { ++ teletextSubtitlePages[fixedTtxtSubtitlePages] = tTeletextSubtitlePage(page); ++ if (l) ++ strn0cpy(teletextSubtitlePages[fixedTtxtSubtitlePages].ttxtLanguage, l, MAXLANGCODE1); ++ fixedTtxtSubtitlePages++; ++ } ++ else ++ esyslog("ERROR: invalid Teletext page!"); // no need to set ok to 'false' ++ } ++ else ++ esyslog("ERROR: too many Teletext pages!"); // no need to set ok to 'false' ++ p = NULL; ++ } ++ totalTtxtSubtitlePages = fixedTtxtSubtitlePages; ++ } ++ if (sscanf(tpidbuf, "%d", &tpid) != 1) ++ return false; ++ } + if (caidbuf) { + char *p = caidbuf; + char *q; +@@ -696,6 +761,7 @@ bool cChannel::Parse(const char *s) + free(sourcebuf); + free(vpidbuf); + free(apidbuf); ++ free(tpidbuf); + free(caidbuf); + free(namebuf); + if (!GetChannelID().Valid()) { +--- a/pat.c ++++ b/pat.c +@@ -17,6 +17,7 @@ + #include "libsi/section.h" + #include "libsi/descriptor.h" + #include "thread.h" ++#include "vdrttxtsubshooks.h" + + #define PMT_SCAN_TIMEOUT 10 // seconds + +@@ -347,6 +348,8 @@ void cPatFilter::Process(u_short Pid, u_ + char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" }; + char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" }; + int Tpid = 0; ++ tTeletextSubtitlePage TeletextSubtitlePages[MAXTXTPAGES]; ++ int NumTPages = 0; + int NumApids = 0; + int NumDpids = 0; + int NumSpids = 0; +@@ -438,8 +441,21 @@ void cPatFilter::Process(u_short Pid, u_ + NumSpids++; + } + break; +- case SI::TeletextDescriptorTag: ++ case SI::TeletextDescriptorTag: { + Tpid = esPid; ++ SI::TeletextDescriptor *sd = (SI::TeletextDescriptor *)d; ++ SI::TeletextDescriptor::Teletext ttxt; ++ for (SI::Loop::Iterator it; sd->teletextLoop.getNext(ttxt, it); ) { ++ bool isSubtitlePage = (ttxt.getTeletextType() == 0x02) || (ttxt.getTeletextType() == 0x05); ++ if ((NumTPages < MAXTXTPAGES) && ttxt.languageCode[0] && isSubtitlePage) { ++ strn0cpy(TeletextSubtitlePages[NumTPages].ttxtLanguage, I18nNormalizeLanguageCode(ttxt.languageCode), MAXLANGCODE1); ++ TeletextSubtitlePages[NumTPages].ttxtPage = ttxt.getTeletextPageNumber(); ++ TeletextSubtitlePages[NumTPages].ttxtMagazine = ttxt.getTeletextMagazineNumber(); ++ TeletextSubtitlePages[NumTPages].ttxtType = ttxt.getTeletextType(); ++ NumTPages++; ++ } ++ } ++ } + break; + case SI::ISO639LanguageDescriptorTag: { + SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; +@@ -541,6 +557,12 @@ void cPatFilter::Process(u_short Pid, u_ + } + if (Setup.UpdateChannels >= 2) { + Channel->SetPids(Vpid, Ppid, Vtype, Apids, Atypes, ALangs, Dpids, Dtypes, DLangs, Spids, SLangs, Tpid); ++ if (NumTPages < MAXTXTPAGES) { ++ int manualPageNumber = cVDRTtxtsubsHookListener::Hook()->ManualPageNumber(Channel); ++ if (manualPageNumber) ++ TeletextSubtitlePages[NumTPages++] = tTeletextSubtitlePage(manualPageNumber); ++ } ++ Channel->SetTeletextSubtitlePages(TeletextSubtitlePages, NumTPages); + if (!cSource::IsType(Channel->Source(), 'I')) + Channel->SetCaIds(CaDescriptors->CaIds()); + Channel->SetSubtitlingDescriptors(SubtitlingTypes, CompositionPageIds, AncillaryPageIds); diff --git a/multimedia/vdr/pkg-plist b/multimedia/vdr/pkg-plist index d2bd13017f6c..abcd9493d40a 100644 --- a/multimedia/vdr/pkg-plist +++ b/multimedia/vdr/pkg-plist @@ -134,6 +134,7 @@ include/vdr/ci.h include/vdr/config.h include/vdr/channels.h include/vdr/Make.global +%%TTXPATCH%%include/vdr/vdrttxtsubshooks.h @exec mkdir -p %D/etc/vdr/plugins @exec chown %%VDR_USER%%:%%VDR_GROUP%% %D/etc/vdr %D/etc/vdr/plugins @unexec if cmp -s %D/etc/vdr/remote.conf.sample %D/etc/vdr/remote.conf; then rm -f %D/etc/vdr/remote.conf; fi |