summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Grimm <git@e-tobi.net>2010-02-14 22:33:13 +0100
committerTobias Grimm <git@e-tobi.net>2010-02-14 22:33:13 +0100
commit481745255e5bb50287595e3134f517c6cbdcccea (patch)
treea52fcbb772d3743df8bb77259b17127cc0192194
parent35e75af67d6f13893c0301b5b88eb7b27f147bba (diff)
downloadvdr-plugin-ttxtsubs-481745255e5bb50287595e3134f517c6cbdcccea.tar.gz
vdr-plugin-ttxtsubs-481745255e5bb50287595e3134f517c6cbdcccea.tar.bz2
Dramatic code drop, removed live receiver code
live and replay data will be feed by the VDR patch
-rw-r--r--Makefile3
-rw-r--r--siinfo.c682
-rw-r--r--siinfo.h56
-rw-r--r--ttxtsubs.c105
-rw-r--r--ttxtsubsdisplay.h1
-rw-r--r--ttxtsubsdisplayer.c54
-rw-r--r--ttxtsubsdisplayer.h11
-rw-r--r--ttxtsubsfilter.c163
-rw-r--r--ttxtsubsfilter.h46
-rw-r--r--ttxtsubsreceiver.c301
-rw-r--r--ttxtsubsreceiver.h59
11 files changed, 16 insertions, 1465 deletions
diff --git a/Makefile b/Makefile
index c8e11a6..70c5ddd 100644
--- a/Makefile
+++ b/Makefile
@@ -47,8 +47,7 @@ DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
### The object files (add further files here):
-OBJS = $(PLUGIN).o ttxtsubsdisplayer.o ttxtsubsdisplay.o teletext.o siinfo.o \
- ttxtsubsfilter.o ttxtsubsreceiver.o \
+OBJS = $(PLUGIN).o ttxtsubsdisplayer.o ttxtsubsdisplay.o teletext.o \
ttxtsubspagemenu.o ttxtsubschannelsettings.o
### Implicit rules:
diff --git a/siinfo.c b/siinfo.c
deleted file mode 100644
index ee2709c..0000000
--- a/siinfo.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/*
- * 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 <sys/ioctl.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/poll.h>
-#include <time.h>
-#include <netinet/in.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <map>
-
-#include <vdr/device.h>
-#include <vdr/dvbdevice.h>
-#include <vdr/channels.h>
-
-#include "linux/dvb/dmx.h"
-#include "siinfo.h"
-
-#include "ttxtsubsglobals.h"
-#include "ttxtsubschannelsettings.h"
-
-#define DESCR_TELETEXT 0x56
-#define DESCR_DVBSUBTITLES 0x59
-
-
-#define PACK __attribute__ ((__packed__))
-
-
-// ETSI 300468 6.2.40
-struct PACK ttxt_descr {
- uint8_t tag;
- uint8_t length;
- struct PACK {
- uint8_t lang[3];
- uint8_t type_mag; // 5 bits type, 3 bits mag
- uint8_t page_no;
- } d[1];
-};
-
-struct PACK sect_header {
- uint8_t table_id;
- uint16_t syntax_len;
- uint16_t transport_stream_id;
- uint8_t ver_cur;
- uint8_t section_number;
- uint8_t last_section_number;
-};
-
-// H.222.0 2.4.4.3, Table 2-25
-struct PACK PAT_sect {
- uint8_t table_id;
- uint16_t syntax_len;
- uint16_t transport_stream_id;
- uint8_t vers_curr;
- uint8_t sect_no;
- uint8_t last_sect;
- struct PACK {
- uint16_t program_number;
- uint16_t res_PMTPID;
- } d[1];
-};
-
-// H.222.0 2.4.4.8, Table 2-28
-struct PACK PMT_stream {
- uint8_t stream_type;
- uint16_t res_PID;
- uint16_t res_ES_info_len;
- uint8_t descrs[2];
-};
-
-struct PACK PMT_sect {
- uint8_t table_id;
- uint16_t syntax_len;
- uint16_t program_number;
- uint8_t vers_curr;
- uint8_t sect_no;
- uint8_t last_sect;
- uint16_t res_pcr;
- uint16_t res_program_info_length;
- struct PMT_stream s;
-};
-
-
-static int SetSectFilt(int fd, uint16_t pid, uint8_t tnr, uint8_t mask)
-{
- int ret;
-
- struct dmx_sct_filter_params p;
-
- memset(&p, 0, sizeof(p));
-
- p.filter.filter[0] = tnr;
- p.filter.mask[0] = mask;
- p.pid = pid;
- p.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
-
- if ((ret = ioctl(fd, DMX_SET_FILTER, &p)) < 0)
- perror("DMX SET FILTER:");
-
- return ret;
-}
-
-
-static int
-read_timeout(int fd, void *buf, size_t count, int timeout_ms) {
- int ret = -1;
- struct pollfd pi;
-
- pi.fd = fd;
- pi.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
-
- ret = poll(&pi, 1, timeout_ms);
- if(ret < 0)
- return errno;
- if(ret == 0) { // timeout
- esyslog("ttxtsubs: Service Information read: timeout!");
- return -1;
- }
-
- if(pi.revents == POLLIN) {
- ret = read(fd, buf, count);
- return ret;
- } else
- return -1;
-}
-
-/*
- * PID - pid to collect on
- * table_id - table id to filter out (H.222.0 table 2-26)
- * sects - pointer to char *[256], points to array of table sections, initially empty
- * numsects - number of sections in table
- * returns - 0 if everything ok
- */
-#define SECTSIZE 1024
-static int CollectSections(int card_no, int pid, int table_id, char **sects, int *numsects)
-{
- int fd;
- int ret = -1;
- int last_section = 0;
- int done = 0;
- char *p = NULL;
- int n;
- char name[100];
- time_t start_time;
-
- // printf("CollectSections %d/%d\n", pid, table_id); // XXXX
-
- snprintf(name, sizeof(name), "/dev/dvb/adapter%d/demux0", card_no);
-
- memset(sects, 0, sizeof(char*) * 256);
-
- if((fd = open(name, O_RDWR)) < 0){
- perror("DEMUX DEVICE 1: ");
- return -1;
- }
- // printf("ttxtsubs: siinfo.c: checking pid %d\n", pid); // XXXX
- if(SetSectFilt(fd, pid, table_id, 0xff)) {
- ret = -1;
- goto bail;
- }
-
- start_time = time(NULL);
-
- do {
- struct sect_header *h;
- int i;
-
- if((start_time + 1) < time(NULL)) {
- ret = -1;
- done = 1;
- break;
- }
-
- if(p == NULL)
- p = (char *) malloc(SECTSIZE);
-
- n = read_timeout(fd, p, SECTSIZE, 250);
-
- if(n < 8)
- continue;
-
- h = (struct sect_header *) p;
-
- if(n != ((ntohs(h->syntax_len) & 0xfff) + 3)) {
- esyslog("ttxtsubs: bad section length: %x / %x!\n", n, ntohs(h->syntax_len) & 0xfff);
- continue;
- }
-
- if(!(h->ver_cur & 0x01)) // if not current
- continue;
-
- last_section = h->last_section_number;
-
- if(!sects[h->section_number]) { // section_number
- sects[h->section_number] = p;
- p = NULL;
- }
-
- for(i = 0; i <= last_section; i++) {
- if(!sects[i]) {
- break;
- }
-
- if(i == last_section) {
- *numsects = last_section + 1;
- ret = 0;
- done = 1;
- }
- }
-
- } while (!done);
-
- bail:
- close(fd);
- return ret;
-}
-
-// When using a full featured card with hw_sections=0, at frequency change
-// there seems to sometimes be left one (or more?) section block from the
-// previous channel somewhere in the pipe. Whe need to remove that.
-static void DiscardBufferedSections(int card_no, uint16_t pid, int table_id)
-{
- int fd;
- char name[100];
- int ret = -1;
- int n = 0;
- char buf[SECTSIZE];
-
- snprintf(name, sizeof(name), "/dev/dvb/adapter%d/demux0", card_no);
-
- if((fd = open(name, O_RDWR)) < 0){
- perror("DEMUX DEVICE 1: ");
- return;
- }
-
- if(SetSectFilt(fd, pid, table_id, 0xff)) {
- goto bail;
- }
-
- // first read one section
- read_timeout(fd, buf, SECTSIZE, 1000);
-
- // this loop doesn't seem to be needed
- do {
- struct pollfd pi;
- pi.fd = fd;
- pi.events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
-
- ret = poll(&pi, 1, 0);
- if(ret > 0 && (pi.revents & POLLIN)) {
- // TODO: Do something more useful if read fails!
- if(read(fd, buf, SECTSIZE) < 0) { }
- n++;
- }
- } while (ret > 0);
-
- if(n)
- printf("\nttxtsubs: DiscardBufferedSections: Discarded %d extra buffered sections\n\n", n + 1); // XXX
- bail:
- close(fd);
-}
-
-static void FreeSects(char **sects)
-{
- int i;
-
- for(i = 0; i < 256; i++) {
- if(sects[i]) {
- free(sects[i]);
- sects[i] = NULL;
- }
- }
-}
-
-
-static void addpageinfo(struct ttxtinfo *info, uint16_t pid, struct ttxt_descr *descr, int descr_index)
-{
- struct ttxtpidinfo *pd;
- struct ttxtpageinfo *pa;
-
- if(!info->p) {
- info->p = (struct ttxtpidinfo *) malloc(sizeof(*(info->p)));
- memset((char *) info->p, 0, sizeof(*(info->p)));
- info->p[0].pid = pid;
- info->pidcount++;
- }
-
- if(pid != info->p[info->pidcount - 1].pid) {
- info->pidcount++;
- info->p = (struct ttxtpidinfo *) realloc(info->p, sizeof(info->p[0]) * info->pidcount);
- memset((char *) &(info->p[info->pidcount - 1]), 0, sizeof(info->p[0]));
- info->p[info->pidcount - 1].pid = pid;
- }
-
- pd = &(info->p[info->pidcount - 1]);
-
- pd->pagecount++;
- if(!pd->i) {
- pd->i = (struct ttxtpageinfo *) malloc(sizeof(pd->i[0]));
- } else {
- pd->i = (struct ttxtpageinfo *) realloc(pd->i, sizeof(pd->i[0]) * pd->pagecount);
- }
- memset((char *) &(pd->i[pd->pagecount - 1]), 0, sizeof(pd->i[0]));
-
- pa = &(pd->i[pd->pagecount - 1]);
-
- pa->lang[0] = descr->d[descr_index].lang[0];
- pa->lang[1] = descr->d[descr_index].lang[1];
- pa->lang[2] = descr->d[descr_index].lang[2];
- 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;
- esyslog("ttxtsubs: Warning: Remapped page number %01x%02x to %01x%02x!\n",
- mag, pa->page, mag, newpage);
- pa->page = newpage;
- }
- }
-}
-
-
-static int HasVPID(int vpid, char **pmtsects, int numsects)
-{
- int found = 0;
- int i;
-
- for(i = 0; i < numsects && !found; i++) {
- struct PMT_sect *psect;
- char *sp;
- char *end;
-
- psect = (struct PMT_sect *) pmtsects[i];
- end = pmtsects[i] + (ntohs(psect->syntax_len) & 0x3ff) - 7;
- // skip extra program info
- sp = ((char *) &(psect->s)) + (ntohs(psect->res_program_info_length) & 0xfff);
-
- while(sp < end && !found) {
- struct PMT_stream *s = (struct PMT_stream *) sp;
-
- if(s->stream_type == 1 || s->stream_type == 2) { // Video stream
- if((ntohs(s->res_PID) & 0x1fff) == vpid) {
- //printf("Found ttxt by vpid: %d/%d\n", s->stream_type, (ntohs(s->res_PID) & 0x1fff));
- found = 1;
- break;
- }
- }
- sp += (ntohs(s->res_ES_info_len) & 0xfff) + 5;
- }
- }
-
- return found;
-}
-
-static void ExtractTtxtInfo(char **pmtsects, int numsects, struct ttxtinfo *info, int *foundinfo)
-{
- int i;
-
- for(i = 0; i < numsects; i++) {
- struct PMT_sect *psect;
- char *sp;
- char *end;
-
- psect = (struct PMT_sect *) pmtsects[i];
- end = pmtsects[i] + (ntohs(psect->syntax_len) & 0x3ff) - 7;
- // skip extra program info
- sp = ((char *) &(psect->s)) + (ntohs(psect->res_program_info_length) & 0xfff);
-
- while(sp < end) {
- struct PMT_stream *s = (struct PMT_stream *) sp;
-
- if(s->stream_type == 6) { // PES private data
- uint8_t *descr;
-
- for(descr = s->descrs; descr < s->descrs + (ntohs(s->res_ES_info_len) & 0xfff); descr += descr[1] + 2) {
- if(descr[0] == DESCR_TELETEXT) {
- struct ttxt_descr *t = (struct ttxt_descr *) descr;
- int i, count = t->length / sizeof(t->d[0]);
- for(i = 0; i < count; i++) {
- addpageinfo(info, ntohs(s->res_PID) & 0x1fff, t, i);
- //printf("%c%c%c: type %d, page: %01x%02x\n", t->d[i].lang[0], t->d[i].lang[1], t->d[i].lang[2], t->d[i].type_mag >> 3, t->d[i].type_mag & 0x7, t->d[i].page_no);
- *foundinfo = 1;
- }
- }
- }
- }
- sp += (ntohs(s->res_ES_info_len) & 0xfff) + 5;
- }
- }
-}
-
-/*
- * if vpid != 0, we first search if we can find the vpid in this PMT,
- * and if so we go get the ttxt pid
- * return <> 0 on error
- */
-static int FindTtxtInfoInPMT(int card_no, int pid, int vpid, struct ttxtinfo *info, int *foundinfo)
-{
- int ret = -1;
- char *pmtsects[256];
- int numsects;
-
- // printf("FindTtxtInfoInPMT pid: %d, vpid: %d\n", pid, vpid); // XXXX
-
- ret = CollectSections(card_no, pid, 0x02, pmtsects, &numsects);
- if(ret)
- goto bail;
-
- if(vpid != 0) {
- if(!HasVPID(vpid, pmtsects, numsects)) {
- goto bail;
- }
- }
-
- ExtractTtxtInfo(pmtsects, numsects, info, foundinfo);
-
- bail:
- FreeSects(pmtsects);
- return ret;
-}
-
-
-/*
- * find the ttxt_info in the PMT via the PAT, try first with the SID
- * and if that fails with the VPID
- * return <> 0 on error;
- */
-int GetTtxtInfo(int card_no, const cChannel *c, struct ttxtinfo *info)
-{
- int ret = -1;
- char *patsects[256];
- int numsects;
- int i;
- int j;
- uint16_t pmt_pid = 0;
- int foundinfo = 0;
- int retry;
-
- memset((char *) info, 0, sizeof(*info));
-
-#if 1
- // <manual page selection patch>
- cTtxtSubsChannelSetting *cs =
- TtxtSubsChannelSettings.Get(c);
-
- if (cs && cs->PageMode() == PAGE_MODE_MANUAL) {
- struct ttxt_descr descr;
-
- if (cs->PageNumber() > 0) {
- int temp = cs->PageNumber();
- if (temp>=800) temp-=800;
- char langs[MAXLANGUAGES][2][4];
- char hi[MAXLANGUAGES][2];
- //put as the first language the first one configured,
- //so that FindSubs will later accept it
- memcpy(langs,globals.languages(),sizeof(langs));
- memcpy(hi,globals.hearingImpaireds(),sizeof(hi));
- for (i = 0; i < MAXLANGUAGES; i++) {
- for (j = 0; j < 2 ; j++) {
- if (!langs[i][j][0]) continue;
-
- descr.d[0].lang[0] = langs[i][j][0];
- descr.d[0].lang[1] = langs[i][j][1];
- descr.d[0].lang[2] = langs[i][j][2];
- if (hi[i][j])
- descr.d[0].type_mag = (TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE << 3) + (temp / 100);
- else
- descr.d[0].type_mag = (TTXT_SUBTITLE_PAGE << 3) + (temp / 100);
-
- temp = temp % 100;
- descr.d[0].page_no = ((temp / 10) << 4) + (temp % 10);
-
- addpageinfo(info, c->Tpid(), &descr, 0);
- return 0;
- }
- }
- //no language configured
- return -1;
- }
- }
- if (cs && cs->PageMode() == PAGE_MODE_DISABLED) {
- return -1;
- }
- // </manual page selection patch>
-#endif
-
- for(retry = 0; retry <= 1 && !foundinfo; retry++) { // XXX retry two times due to flaky pat scanning with hw_sections=0
-
- // printf("GetTtxtInfo A sid: %d, vpid: %d\n", sid, vpid); // XXXX
-
-#if 1
- // firmware fixed now?
- DiscardBufferedSections(card_no, 0, 0);
-#endif
-
- ret = CollectSections(card_no, 0, 0, patsects, &numsects);
- if(ret)
- goto bail;
-
- if(c->Sid() != 0) {
- int found;
-
- for(i = 0, found = 0; i < numsects && !found; i++) {
- int numdescrs;
- struct PAT_sect *s = (struct PAT_sect *) patsects[i];
-
- numdescrs = ((ntohs(s->syntax_len) & 0x3FF) - 7) / 4;
-
- for(j = 0; j < numdescrs && !found; j++) {
- uint16_t pno = ntohs(s->d[j].program_number);
-
- if(pno == 0)
- continue; // network pid
-
- if(pno == c->Sid()) {
- pmt_pid = ntohs(s->d[j].res_PMTPID) & 0x1fff;
- found = 1;
- }
- }
- }
- }
-
- if(pmt_pid != 0) {
- // printf("GetTtxtInfo B pmt_pid: %d, vpid: %d\n", pmt_pid, vpid); // XXXX
- ret = FindTtxtInfoInPMT(card_no, pmt_pid, 0, info, &foundinfo);
- } else {
- // SID not found, try searching VID in all SIDS
- if(c->Vpid() != 0) {
- int done;
- for(i = 0, done = 0; i < numsects && !done; i++) {
- int numdescrs;
- struct PAT_sect *s = (struct PAT_sect *) patsects[i];
-
- numdescrs = ((ntohs(s->syntax_len) & 0x3FF) - 7) / 4;
-
- for(j = 0; j < numdescrs && !done; j++) {
- uint16_t pno = ntohs(s->d[j].program_number);
-
- if(pno == 0)
- continue; // network pid
-
- pmt_pid = ntohs(s->d[j].res_PMTPID) & 0x1fff;
-
- // printf("GetTtxtInfo C pmt_pid: %d, vpid: %d\n", pmt_pid, vpid); // XXXX
- ret = FindTtxtInfoInPMT(card_no, pmt_pid, c->Vpid(), info, &foundinfo);
- if(ret) {
- done = 1;
- }
- if(foundinfo)
- done = 1;
- }
- }
- }
- }
-
- FreeSects(patsects);
- }
-
-bail:
- return ret;
-}
-
-
-void FreeTtxtInfoData(struct ttxtinfo *info)
-{
- int i;
-
- for(i = 0; i < info->pidcount; i++) {
- free((void *) info->p[i].i);
- }
-
- free((void *) info->p);
-}
-
-
-void DupTtxtInfo(struct ttxtinfo *in, struct ttxtinfo *out)
-{
- int i;
-
- out->pidcount = in->pidcount;
- out->p = (struct ttxtpidinfo *) malloc(sizeof(out->p[0]) * in->pidcount);
-
- for(i = 0; i < in->pidcount; i++) {
- out->p[i] = in->p[i];
- out->p[i].i = (struct ttxtpageinfo *) malloc(sizeof(out->p[0].i[0]) * in->p[i].pagecount);
- memcpy((void *) out->p[i].i, (void *) in->p[i].i, sizeof(out->p[0].i[0]) * in->p[i].pagecount);
- }
-}
-
-
-struct ttxtpidinfo *FindSubs(struct ttxtinfo *info, int *pid, int *pageno, char *lang)
-{
- 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].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;
- strncpy(lang, info->p[i].i[j].lang, 3);
- foundPI = &(info->p[i]);
- }
- }
- }
- }
-
- if(foundPI) {
- return foundPI;
- }
-
- if(info->pidcount == 0)
- isyslog("ttxtsubs: No teletext subtitles on channel.");
- else {
- isyslog("ttxtsubs: Wanted subtitle language(s) not found on channel, available languages:");
- 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;
- isyslog("ttxtsubs: %03x: %c%c%c %s", 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)" :
- type == TTXT_PROGRAMME_SCHEDULE_PAGE ? "(Programme Schedule Page)" :
- type == TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE ? "(Hearing Impaired)" : "(Unknown type)");
- }
- }
- }
-
- *pid = 0;
- *pageno = -1;
- return NULL;
-}
diff --git a/siinfo.h b/siinfo.h
deleted file mode 100644
index 9297d7e..0000000
--- a/siinfo.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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
- *
- */
-
-#define TTXT_INITIAL_PAGE 1
-#define TTXT_SUBTITLE_PAGE 2
-#define TTXT_ADDITIONAL_INFO_PAGE 3
-#define TTXT_PROGRAMME_SCHEDULE_PAGE 4
-#define TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE 5
-
-struct ttxtpageinfo {
- char lang[3];
- uint8_t type;
- uint8_t mag;
- uint8_t page;
-};
-
-struct ttxtpidinfo {
- uint16_t pid;
- int pagecount;
- struct ttxtpageinfo *i;
-};
-
-// XXX should be an object instead and use c++ vectors etc
-struct ttxtinfo {
- int pidcount;
- struct ttxtpidinfo *p;
-};
-
-/*
- * find the ttxt_info in the PMT via the PAT, try first with the SID
- * and if that fails with the VPID
- * return <> 0 on error;
- */
-int GetTtxtInfo(int card_no, const cChannel *c, struct ttxtinfo *info);
-
-void FreeTtxtInfoData(struct ttxtinfo *info);
-void DupTtxtInfo(struct ttxtinfo *in, struct ttxtinfo *out);
-
-struct ttxtpidinfo *FindSubs(struct ttxtinfo *info, int *pid, int *pageno, char *lang);
diff --git a/ttxtsubs.c b/ttxtsubs.c
index bd48d92..f4a6949 100644
--- a/ttxtsubs.c
+++ b/ttxtsubs.c
@@ -42,7 +42,6 @@
#include "ttxtsubsglobals.h"
#include "ttxtsubsdisplayer.h"
#include "utils.h"
-#include "siinfo.h"
#include "ttxtsubspagemenu.h"
#include "ttxtsubschannelsettings.h"
@@ -159,7 +158,6 @@ public:
// -- internal
private:
- void StartTtxtLive(const cDevice *Device, tChannelID chnid, int pid, int page);
void StartTtxtPlay(int page);
void StopTtxt(void);
void ShowTtxt(void);
@@ -168,7 +166,8 @@ public:
void parseHIs(const char *val);
private:
- cTtxtSubsDisplayer *mDispl;
+ cTtxtSubsPlayer *mDispl;
+ cMutex mDisplLock;;
char mOldLanguage[4]; // language chosen from previous version
int mOldHearingImpaired; // HI setting chosen from previous version
@@ -359,6 +358,7 @@ void cPluginTtxtsubs::Action(void)
cn=switchChannel;
dev=switchDevice;
getchmutex.Unlock();
+ int page = 0;
if (cn!=lastc) {
StopTtxt();
lastc=0;
@@ -367,71 +367,15 @@ void cPluginTtxtsubs::Action(void)
cString x = mReplayChannelId.ToString();
if (cs && cs->PageMode() == PAGE_MODE_MANUAL) {
int tmp = cs->PageNumber();
- int page = (tmp / 100);
+ page = (tmp / 100);
tmp = tmp % 100;
page = (page << 4) + (tmp / 10);
page = (page << 4) + tmp % 10;
- StartTtxtPlay(page);
- lastc=cn;
}
- else
- {
- StartTtxtPlay(0x000);
- lastc=cn;
- }
}
- else {
- cChannel *c = Channels.GetByNumber(cn);
- if(c) {
- //int manual_page = TtxtSubsChannelSettings.Page(c->GetChannelID());
- //if (manual_page>0) {
- // printf("ttxtsubs: manual page %03x selected\n", manual_page);
- // if (c->Tpid()) StartTtxtLive(dev, c->GetChannelID(), c->Tpid(), manual_page);
- //} else if(manual_page==0) {
- struct ttxtinfo info;
- int pid, page;
- char lang[4] = "";
- bool geterror=true;
- if((globals.dvbSources() == 0) || ((globals.dvbSources() == 1) && c->IsSat()) || ((globals.dvbSources() == 2) && c->IsTerr()) || ((globals.dvbSources() == 3) && c->IsCable()))
- {
- int tries=0; //sometimes it doesn't find subtitles even if they're there
- //the problem is that while the dish is moving it's picking the signal
- //from a different satellite, so what really should be done is to
- //check if the dish is positioned
- while(tries<=2) {
- if (geterror=GetTtxtInfo(dev->ActualDevice()->CardIndex(), c, &info)) {
- esyslog("ttxtsubs: Error: GetTtxtInfo failed!");
- break;
- }
- else {
- if(FindSubs(&info, &pid, &page, lang)) {
- //dprint("CHANNELSWITCH, pid: %d page: %x\n", pid, page);
- for(int i = 0; i < gNumLanguages; i++) {
- if(!memcmp(lang, gLanguages[i][0], 3) ||
- !memcmp(lang, gLanguages[i][1], 3)) {
- globals.mI18nLanguage = i - 1;
- }
- }
- if(globals.mI18nLanguage < 0 || globals.mI18nLanguage >= I18nLanguages()->Size())
- globals.mI18nLanguage = 0; // default to iso8859-1 if no predefined charset
- if (mReplay)
- StartTtxtPlay(page);
- else
- StartTtxtLive(dev, c->GetChannelID(), pid, page);
- FreeTtxtInfoData(&info);
- break;
- } else { //!FindSubs
- FreeTtxtInfoData(&info);
- tries++;
- }
- }
- } //while(tries<=2)
- }
- lastc=cn;
- //}
- }
- }
- }
+ StartTtxtPlay(0x000);
+ lastc=cn;
+ }
}
}
@@ -442,7 +386,6 @@ void cPluginTtxtsubs::ChannelSwitch(const cDevice *Device, int ChannelNumber)
gettimeofday(&tv, NULL);
#endif
//dprint("cPluginTtxtsubs::ChannelSwitch(devicenr: %d, channelnr: %d) - mDispl: %x\n", Device->DeviceNumber(), ChannelNumber, mDispl); // XXX
-
if(Device->IsPrimaryDevice() && !Device->Replaying()) {
if(ChannelNumber) {
getchmutex.Lock();
@@ -474,17 +417,10 @@ void cPluginTtxtsubs::Replaying(const cControl *Control, const char *Name, const
void cPluginTtxtsubs::PlayerTeletextData(uint8_t *p, int length, bool IsPesRecording, const struct tTeletextSubtitlePage teletextSubtitlePages[])
{
- if (!mDispl)
- return;
-
- cTtxtSubsPlayer *r = dynamic_cast<cTtxtSubsPlayer *>(mDispl);
-
- if(!r) {
- esyslog("ttxtsubs: ERROR: not a cTtxtSubsPlayer!");
- return;
- }
-
- r->PES_data(p, length, IsPesRecording, teletextSubtitlePages);
+ mDisplLock.Lock();
+ if (mDispl)
+ mDispl->PES_data(p, length, IsPesRecording, teletextSubtitlePages);
+ mDisplLock.Unlock();
}
int cPluginTtxtsubs::ManualPageNumber(const cChannel *channel)
@@ -498,23 +434,6 @@ int cPluginTtxtsubs::ManualPageNumber(const cChannel *channel)
// -- internal
-void cPluginTtxtsubs::StartTtxtLive(const cDevice *Device, tChannelID chnid, int pid, int page)
-{
- //dprint("cPluginTtxtsubs::StartTtxtLive(devicenr: %d, pid: %d, page: %03x)\n",
- // Device->DeviceNumber(), pid, page); // XXX
-
- if(!mDispl) {
- cTtxtSubsLiveReceiver *r;
- //dprint("teletext subtitles started on pid %d\n", pid);
- mDispl = r = new cTtxtSubsLiveReceiver(chnid, pid, page); // takes 0.01-0.015 s
- if(!cDevice::PrimaryDevice()->ActualDevice()->AttachReceiver(r))
- // takes 0.02-0.04 s on a full featured card
- esyslog("ttxtsubs: Error: AttachReceiver failed!");
- ShowTtxt();
- } else
- esyslog("ttxtsubs: Error: StartTtxtLive called when already started!");
-}
-
void cPluginTtxtsubs::StartTtxtPlay(int backup_page)
{
//dprint("cPluginTtxtsubs::StartTtxtPlay\n");
@@ -532,7 +451,9 @@ void cPluginTtxtsubs::StopTtxt(void)
//dprint("cPluginTtxtsubs::StopTtxt\n");
HideTtxt();
+ mDisplLock.Lock();
DELETENULL(mDispl); // takes 0.03-0.04 s
+ mDisplLock.Unlock();
}
void cPluginTtxtsubs::ShowTtxt(void)
diff --git a/ttxtsubsdisplay.h b/ttxtsubsdisplay.h
index 622a0f6..bed07d3 100644
--- a/ttxtsubsdisplay.h
+++ b/ttxtsubsdisplay.h
@@ -20,6 +20,7 @@
#include "teletext.h"
#include <vdr/tools.h>
+#include <vdr/osd.h>
struct ttxt_data_field;
struct timeval;
diff --git a/ttxtsubsdisplayer.c b/ttxtsubsdisplayer.c
index 6bf434f..179bba2 100644
--- a/ttxtsubsdisplayer.c
+++ b/ttxtsubsdisplayer.c
@@ -21,8 +21,8 @@
#include "ttxtsubsdisplayer.h"
#include "ttxtsubsdisplay.h"
#include "utils.h"
-#include "siinfo.h"
#include "ttxtsubsglobals.h"
+#include <vdr/channels.h>
// ----- class cTtxtSubsDisplayer -----
@@ -84,58 +84,6 @@ void cTtxtSubsDisplayer::HideDisplay(void)
mDisp->Hide();
}
-
-// ----- class cTtxtSubsLiveReceiver -----
-
-cTtxtSubsLiveReceiver::cTtxtSubsLiveReceiver(tChannelID ChnId, int Pid, int textpage)
- :
-#if defined(APIVERSNUM) && APIVERSNUM < 10712
- cReceiver(ChnId, -1, Pid),
-#endif
- cTtxtSubsDisplayer(textpage)
-{
-#if defined(APIVERSNUM) && APIVERSNUM >= 10712
- AddPid(Pid);
-#endif
- SetDescription("ttxtsubs live receiver");
-}
-
-cTtxtSubsLiveReceiver::~cTtxtSubsLiveReceiver(void)
-{
- Detach();
-}
-
-void cTtxtSubsLiveReceiver::Activate(bool On)
-{
- //dprint("cTtxtSubsLiveReceiver::Activate: On:%d\n", On);
-}
-
-// Take TS packets and break out the teletext data
-// Buffer the data for processing in a separate thread
-// XXX We should do some filtering here to avoid unneccessary load!
-void cTtxtSubsLiveReceiver::Receive(uchar *Data, int Length)
-{
- int i;
-
- if(Length != 188) // should never happen
- return;
-
- if(Data[1] & 0x80) // transport_error_indicator
- return;
-
- // payload_unit_start_indicator
- for(i = (Data[1] & 0x40) ? 1 : 0; i < 4; i++) {
- if(0xff == Data[4 + i*46]) // stuffing data
- continue;
-
- uint64_t sched_time = cTimeMs::Now() + globals.liveDelay();
- cFrame *f = new cFrame(Data + 4 + i*46, 46 + sizeof(sched_time));
- memcpy(f->Data() + 46, &sched_time, sizeof(sched_time));
- mRingBuf.Put(f);
- mGetCond.Broadcast();
- }
-}
-
// ----- class cTtxtSubsPlayer -----
cTtxtSubsPlayer::cTtxtSubsPlayer(int backup_textpage)
diff --git a/ttxtsubsdisplayer.h b/ttxtsubsdisplayer.h
index 0d30c75..20b296e 100644
--- a/ttxtsubsdisplayer.h
+++ b/ttxtsubsdisplayer.h
@@ -18,7 +18,6 @@
*
*/
-#include <vdr/receiver.h>
#include <vdr/ringbuffer.h>
class cTtxtSubsDisplay;
@@ -41,16 +40,6 @@ class cTtxtSubsDisplayer : public cThread {
int mRun;
};
-class cTtxtSubsLiveReceiver : public cReceiver, public cTtxtSubsDisplayer {
- public:
- cTtxtSubsLiveReceiver(tChannelID ChnId, int Pid, int textpage);
- ~cTtxtSubsLiveReceiver(void);
-
- protected:
- virtual void Activate(bool On);
- virtual void Receive(uchar *Data, int Length);
-};
-
class cTtxtSubsPlayer : public cTtxtSubsDisplayer {
public:
cTtxtSubsPlayer(int backup_textpage);
diff --git a/ttxtsubsfilter.c b/ttxtsubsfilter.c
deleted file mode 100644
index 3dff56f..0000000
--- a/ttxtsubsfilter.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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 <string.h>
-
-#include "ttxtsubsfilter.h"
-#include "teletext.h"
-
-cTtxtSubsFilter::cTtxtSubsFilter(void)
- :
- mCount(0),
- mPages(0)
-{
- int i;
- for(i = 0; i < 8; i++)
- mMagPage[i] = -1;
-}
-
-
-cTtxtSubsFilter::~cTtxtSubsFilter(void)
-{
- FreePages();
-}
-
-
-void cTtxtSubsFilter::SetPages(size_t count, uint16_t *pages)
-{
- FreePages();
-
- mPages = (uint16_t *) malloc(count * sizeof(uint16_t));
-
- memcpy((char *) mPages, (char *) pages, count * sizeof(uint16_t));
-
- mCount = count;
-}
-
-// XXX IF MERGING PAGES FROM SEVERAL PIDS (which we currently don't)
-// Need to insert a line Y0 if
-// - there has been data from other streams inserted and the next line is not a Y0
-// there has been data from other magazines and the next line for this mag is not a Y0
-// indata and outdata are pointers to a ttxt data row buffers,
-// if return value <> 0 outdata countains data to pass on
-int cTtxtSubsFilter::Filter(char *indata, char *outdata)
-{
- int mp;
- int mag; // X in ETSI EN 300 706
- int packet; // Y
- int result = 0;
-
- struct ttxt_data_field *d = (struct ttxt_data_field *) indata;
-
- mp = UNHAM_INV(d->mag_addr_ham[0], d->mag_addr_ham[1]);
- mag = mp & 0x7;
- packet = (mp >> 3) & 0x1f;
-
- // packet 0, change page no in this magazine
- if(packet == 0) {
- uint8_t no;
- int newindex;
-
- no = UNHAM_INV(d->data[0], d->data[1]);
-
- mMagPage[mag] = newindex = Find(mCount, mPages, (mag << 8) | no);
-
- if(newindex != -1) {
- //dprint("Filter: %x%02x (%d)\n", mag, no, newindex); // XXX
-
- MakeY0(outdata, indata, mPages[newindex]);
- result = 1;
- }
- } else if(packet >= 1 && packet <= 25) {
- if(mMagPage[mag] != -1) {
- memcpy(outdata, indata, sizeof(ttxt_data_field));
- result = 1;
- }
- }
-
- return result;
-}
-
-
-void cTtxtSubsFilter::FreePages(void)
-{
- mCount = 0;
-
- free(mPages);
- mPages = NULL;
-}
-
-
-int cTtxtSubsFilter::Find(int count, uint16_t *pages, uint16_t pageno){
-
- int i;
- for(i = 0; i < count; i++) {
- if(pages[i] == pageno)
- return i;
- }
-
- return -1;
-}
-
-
-// make a new Y0 line with the flags in
-void cTtxtSubsFilter::MakeY0(char *outdata, char *indata, uint16_t newpageno)
-{
- struct ttxt_data_field *i = (struct ttxt_data_field *) indata;
- 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]];
- o->mag_addr_ham[1] = invtab[hambuf[1]];
-
- // new page number
- ham8_4byte(newpageno & 0xff, hambuf);
- o->data[0] = invtab[hambuf[0]];
- o->data[1] = invtab[hambuf[1]];
-
- // copy flags
- memcpy(o->data + 2, i->data + 2, 6);
-
- // new text
- unsigned char txtbuf[32];
- size_t txtlen;
- size_t n;
-
- txtlen = snprintf((char *) txtbuf, 32, "%03x", newpageno < 0x100 ? newpageno + 0x800 : newpageno);
-
- for(n = 0; n < txtlen; n++) {
- if(parity(txtbuf[n]))
- o->data[n + 8] = invtab[txtbuf[n] | 0x80]; // XXX wrong parity?
- else
- o->data[n + 8] = invtab[txtbuf[n]]; // XXX wrong parity?
- }
- for(; n < 32; n++)
- o->data[n + 8] = invtab[(unsigned char) ' ']; // space already has right parity
-}
diff --git a/ttxtsubsfilter.h b/ttxtsubsfilter.h
deleted file mode 100644
index f1e94f1..0000000
--- a/ttxtsubsfilter.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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
- *
- */
-
-// ----- cTtxtSubsFilter -----
-
-// Filters out the pages on one teletext stream
-class cTtxtSubsFilter
-{
- public:
- cTtxtSubsFilter(void);
- virtual ~cTtxtSubsFilter(void);
-
- void SetPages(size_t count, uint16_t *pages);
-
- // indata and outdata are pointers to a ttxt data row buffers,
- // if return value <> 0 outdata countains data to pass on
- int Filter(char *indata, char *outdata);
-
- private:
- void FreePages(void);
- int Find(int count, uint16_t *pages, uint16_t pageno);
- void MakeY0(char *outdata, char *indata, uint16_t newpageno);
-
- int mCount; // number of pages to filter out
- uint16_t *mPages; // array of page numbers
- int mMagPage[8]; /* index into pages for each mag number, or -1 if
- not currently collecting pages for that mag */
-};
-
diff --git a/ttxtsubsreceiver.c b/ttxtsubsreceiver.c
deleted file mode 100644
index f7e20d3..0000000
--- a/ttxtsubsreceiver.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * 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 <vdr/receiver.h>
-#include <vdr/ringbuffer.h>
-
-#include "siinfo.h"
-#include "ttxtsubsfilter.h"
-#include "ttxtsubsreceiver.h"
-#include "teletext.h"
-
-#define MAXINDEXPAGELINES 24
-
-struct ringBufItem {
- encodedPTS pts;
- uint8_t data[46];
-};
-
-// ----- cTtxtSubsReceiver -----
-
-cTtxtSubsReceiver::cTtxtSubsReceiver(tChannelID ChnId, int Ca, struct ttxtpidinfo *PI)
- :
-#if defined(APIVERSNUM) && APIVERSNUM < 10712
- cReceiver(ChnId, -1, PI->pid),
-#endif
- mGetMutex(),
- mGetCond(),
- mRingBuf(sizeof(ringBufItem) * 500, true),
- mPI(*PI),
- mIndexPageLines(0),
- mIndexPageCol(0),
- mIndexPageNo(0)
-{
- int count = 0;
- uint16_t *pages = (uint16_t *) malloc(sizeof(uint16_t) * mPI.pagecount);
-
-#if defined(APIVERSNUM) && APIVERSNUM >= 10712
- AddPid(PI->pid);
-#endif
-
- mPTS.valid = 0;
-
- // find a free page to put the index page on
- mIndexPageNo = 0x100;
- int again;
- do {
- again = 0;
- for(int i = 0; i < count; i++) {
- if(pages[i] == mIndexPageNo) {
- mIndexPageNo++;
- if((mIndexPageNo & 0x000f) == 0x000a)
- mIndexPageNo += 6;
- again = 1;
- }
- }
- } while(again);
-
- // get pages to record
- for(int i = 0; i < mPI.pagecount; i++) {
- // only subtitle pages
- if(mPI.i[i].type != TTXT_SUBTITLE_PAGE &&
- mPI.i[i].type != TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE)
- continue;
-
- pages[count] = (mPI.i[i].mag << 8) + mPI.i[i].page;
-
- AddIndexInfo(mPI.i[i].lang, mPI.i[i].type, pages[count]);
-
- count++;
- }
-
- mFilter.SetPages(count, pages);
- EndIndexInfo();
-
- free(pages);
-}
-
-
-cTtxtSubsReceiver::~cTtxtSubsReceiver()
-{
- // get any waiting threads going
- mGetCond.Broadcast();
- Detach();
-}
-
-
-// returns pointer buf if there is new data
-uint8_t *cTtxtSubsReceiver::Get(uint8_t *buf, encodedPTS *pts)
-{
- cFrame *f;
-
- f = mRingBuf.Get();
- if(f) {
- ringBufItem *i = (ringBufItem*) f->Data();
- if(pts) {
- *pts = i->pts;
- }
-
- memcpy(buf, i->data, 46);
- mRingBuf.Drop(f);
- // dprint("cTtxtSubsReceiver::Get: returned data!\n");
- return buf;
- } else {
- return NULL;
- }
-}
-
-
-void cTtxtSubsReceiver::IndexPage(char ***lines, int *linecount)
-{
- static char *lineptrs[MAXINDEXPAGELINES];
-
- for(int i = 0; i < mIndexPageLines; i++)
- lineptrs[i] = (char *) mIndexPage[i];
-
- *linecount = mIndexPageLines;
- *lines = lineptrs;
-}
-
-
-// wait for more data
-void cTtxtSubsReceiver::Wait(void)
-{
- mGetMutex.Lock();
- mGetCond.Wait(mGetMutex);
- mGetMutex.Unlock();
-}
-
-
-void cTtxtSubsReceiver::Activate(bool On)
-{
-}
-
-
-// Take TS packets and break out the teletext data
-// Buffer the data for processing in a separate thread
-// XXX We should do some filtering here to avoid unneccessary load!
-void cTtxtSubsReceiver::Receive(uchar *Data, int Length)
-{
- int i = 0;
-
- if(Length != 188) // should never happen
- return;
-
- 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++) {
-
- if(0xff == Data[4 + i*46]) // stuffing data
- continue;
-
- if(mFilter.Filter((char *) Data + 4 + i*46, (char *) it.data)) {
- // dprint("Forward Packet:\n");
-
- cFrame *f = new cFrame((uchar *) &it, sizeof(ringBufItem));
- mRingBuf.Put(f);
- mGetCond.Broadcast();
- }
- }
-}
-
-static void init_line(uint8_t *buf, uint8_t Y, uint8_t mag)
-{
- struct ttxt_data_field *d = (struct ttxt_data_field *) buf;
- uint8_t magbuf[2];
-
- d->data_unit_id = 0x02; // EBU Teletxt non-subtitle data
- d->data_unit_length = 0x2c;
- d->par_loff = 0xc0; // reserved bits + unknown line
- d->framing_code = 0xe4;
- ham8_4byte((Y << 3) | (mag & 0x7), magbuf);
- d->mag_addr_ham[0] = invtab[magbuf[0]];
- d->mag_addr_ham[1] = invtab[magbuf[1]];
-}
-
-static void copy_inv_par(uint8_t *dest, uint8_t *src, int count)
-{
- for(int i = 0; i < count; i++)
- if(parity(src[i]))
- dest[i] = invtab[src[i] | 0x80];
- else
- dest[i] = invtab[src[i]];
-}
-
-void cTtxtSubsReceiver::AddIndexInfo(char *lang, int type, uint16_t page)
-{
- //dprint("AddIndexInfo: %c%c%c/%d/%03x\n", lang[0], lang[1], lang[2], type, page); // XXX
-
- if(mIndexPageLines == MAXINDEXPAGELINES) {
- esyslog("ttxtsubs: cTtxtSubsReceiver::AddIndexInfo: Index page full!");
- return;
- }
-
- if(mIndexPageLines == 0) { // make Y0 and info text
- struct ttxt_data_field *d = (struct ttxt_data_field *) mIndexPage[0];
- uint8_t buf[40];
- size_t txtlen;
-
- init_line(mIndexPage[mIndexPageLines], mIndexPageLines, mIndexPageNo >> 8);
-
- d->data[0] = invtab[ham8_4nibble(mIndexPageNo & 0x000f)];
- d->data[1] = invtab[ham8_4nibble((mIndexPageNo >> 4) & 0x000f)];
- uint8_t ham_inv_zero = invtab[ham8_4nibble(0)];
- d->data[2] = ham_inv_zero;
- d->data[3] = ham_inv_zero;
- d->data[4] = ham_inv_zero;
- d->data[5] = ham_inv_zero;
- d->data[6] = ham_inv_zero;
- d->data[7] = ham_inv_zero;
-
- txtlen = snprintf((char *) buf, 32, "%03x", mIndexPageNo);
- copy_inv_par(d->data + 8, buf, txtlen);
- for(int i = txtlen; i < 32; i++)
- d->data[i+8] = invtab[(unsigned char) ' ']; // space already has correct parity
-
- mIndexPageLines++;
-
- init_line(mIndexPage[mIndexPageLines], mIndexPageLines, mIndexPageNo >> 8);
- d = (struct ttxt_data_field *) mIndexPage[mIndexPageLines];
- const char *header = "Subtitles Index Page";
- txtlen = strlen(header);
- copy_inv_par(d->data, (uint8_t *) header, txtlen);
- for(int i = txtlen; i < 40; i++)
- d->data[i] = invtab[(unsigned char) ' ']; // space already has correct parity
-
- mIndexPageLines++;
- }
-
- struct ttxt_data_field *d = (struct ttxt_data_field *) mIndexPage[mIndexPageLines];
- uint8_t buf[10];
-
- if(mIndexPageCol == 0) {
- init_line(mIndexPage[mIndexPageLines], mIndexPageLines, mIndexPageNo >> 8);
- for(int i = 0; i < 40; i++)
- d->data[i+8] = invtab[(unsigned char) ' ']; // space already has correct parity
- }
-
- if(page < 0x100)
- page += 0x800;
-
- snprintf((char *) buf, 10, "%c%c%c%c%03x ", lang[0], lang[1], lang[2],
- type == TTXT_SUBTITLE_PAGE ? ' ' :
- type == TTXT_SUBTITLE_HEARING_IMPAIRED_PAGE ? 'h' : 'x',
- page);
-
- copy_inv_par(d->data+ mIndexPageCol*8, buf, 8);
-
- mIndexPageCol++;
-
- if(mIndexPageCol == 5) {
- mIndexPageCol = 0;
- mIndexPageLines++;
- }
-}
-
-void cTtxtSubsReceiver::EndIndexInfo(void)
-{
- if(mIndexPageCol != 0) {
- mIndexPageCol = 0;
- mIndexPageLines++;
- }
-}
diff --git a/ttxtsubsreceiver.h b/ttxtsubsreceiver.h
deleted file mode 100644
index 008303b..0000000
--- a/ttxtsubsreceiver.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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
- *
- */
-
-class cRingBufferFrame;
-
-struct encodedPTS {
- uint8_t valid;
- uint8_t data[5];
-};
-
-class cTtxtSubsReceiver : public cReceiver
-{
- public:
- cTtxtSubsReceiver(tChannelID ChnId, int Ca, struct ttxtpidinfo *PI);
- virtual ~cTtxtSubsReceiver();
-
- // returns pointer buf if there is new data
- uint8_t *Get(uint8_t *buf, encodedPTS *pts = NULL);
- // wait for more data
- void Wait(void);
-
- void IndexPage(char ***lines, int *linecount);
-
- protected:
- virtual void Activate(bool On);
- virtual void Receive(uchar *Data, int Length);
-
- virtual void AddIndexInfo(char *lang, int type, uint16_t page);
- virtual void EndIndexInfo(void);
-
- private:
- cMutex mGetMutex;
- cCondVar mGetCond;
- cRingBufferFrame mRingBuf;
- struct ttxtpidinfo mPI;
- cTtxtSubsFilter mFilter;
- uint8_t mIndexPage[24][46];
- uint8_t mIndexPageLines;
- uint8_t mIndexPageCol;
- uint16_t mIndexPageNo;
- encodedPTS mPTS;
-};