summaryrefslogtreecommitdiff
path: root/ttxtsubsfilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'ttxtsubsfilter.c')
-rw-r--r--ttxtsubsfilter.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/ttxtsubsfilter.c b/ttxtsubsfilter.c
new file mode 100644
index 0000000..a50a3fb
--- /dev/null
+++ b/ttxtsubsfilter.c
@@ -0,0 +1,158 @@
+
+#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(int count, uint16_t *pages)
+{
+ FreePages();
+
+ mPages = (uint16_t *) malloc(count * sizeof(uint16_t));
+
+ memcpy((char *) mPages, (char *) pages, count * sizeof(uint16_t));
+
+ mCount = count;
+
+ if(0) {
+ int i;
+ fprintf(stderr, "SetPages: %d, ", count);
+ for(i = 0; i < count; i++)
+ fprintf(stderr, "%03x ", pages[i]);
+ fprintf(stderr, "\n");
+ }
+}
+
+// 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;
+
+ if (0) { // XXX
+ uint8_t buf[2];
+ ham8_4byte(mp, buf);
+ fprintf(stderr, "unham %02x %02x -> %02x, ham: %02x %02x\n",
+ invtab[d->mag_addr_ham[0]], invtab[d->mag_addr_ham[1]],
+ mp,
+ buf[0], buf[1]);
+ }
+
+ // 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) {
+ //fprintf(stderr, "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;
+
+ if(mPages) {
+ 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];
+
+ // 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
+ char txtbuf[32];
+ size_t txtlen;
+ size_t n;
+
+ txtlen = snprintf(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[' ']; // space already has right parity
+}