diff options
author | Tobias Grimm <git@e-tobi.net> | 2010-02-14 22:33:13 +0100 |
---|---|---|
committer | Tobias Grimm <git@e-tobi.net> | 2010-02-14 22:33:13 +0100 |
commit | 481745255e5bb50287595e3134f517c6cbdcccea (patch) | |
tree | a52fcbb772d3743df8bb77259b17127cc0192194 | |
parent | 35e75af67d6f13893c0301b5b88eb7b27f147bba (diff) | |
download | vdr-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-- | Makefile | 3 | ||||
-rw-r--r-- | siinfo.c | 682 | ||||
-rw-r--r-- | siinfo.h | 56 | ||||
-rw-r--r-- | ttxtsubs.c | 105 | ||||
-rw-r--r-- | ttxtsubsdisplay.h | 1 | ||||
-rw-r--r-- | ttxtsubsdisplayer.c | 54 | ||||
-rw-r--r-- | ttxtsubsdisplayer.h | 11 | ||||
-rw-r--r-- | ttxtsubsfilter.c | 163 | ||||
-rw-r--r-- | ttxtsubsfilter.h | 46 | ||||
-rw-r--r-- | ttxtsubsreceiver.c | 301 | ||||
-rw-r--r-- | ttxtsubsreceiver.h | 59 |
11 files changed, 16 insertions, 1465 deletions
@@ -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); @@ -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; -}; |