2
* libzvbi - Teletext decoder
4
* Copyright (C) 2000, 2001, 2002, 2003, 2004 Michael H. Schimek
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
/* $Id: teletext_decoder.c,v 1.8 2005/01/31 07:09:21 mschimek Exp $ */
22
#include "../site_def.h"
24
#include <stdlib.h> /* malloc() */
26
#include "hamm.h" /* vbi3_unham functions */
27
#include "packet-830.h" /* vbi3_decode_teletext_830x functions */
28
#include "conv.h" /* _vbi3_strdup_locale_teletext() */
29
#include "page-priv.h"
30
#include "teletext_decoder-priv.h"
33
* @addtogroup Teletext Teletext Decoder
37
#ifndef TELETEXT_DECODER_CHSW_TEST
38
# define TELETEXT_DECODER_CHSW_TEST 0
41
#ifndef TELETEXT_DECODER_LOG
42
# define TELETEXT_DECODER_LOG 0
45
#define log(templ, args...) \
47
if (TELETEXT_DECODER_LOG) \
48
fprintf (stderr, templ , ##args); \
51
#define MAG8(mag0) ((mag0) ? (mag0) : 8)
53
/* ETS 300 706 Table 30 Colour Map */
55
static const vbi3_rgba
56
default_color_map [40] = {
57
VBI3_RGBA (0x00, 0x00, 0x00), VBI3_RGBA (0xFF, 0x00, 0x00),
58
VBI3_RGBA (0x00, 0xFF, 0x00), VBI3_RGBA (0xFF, 0xFF, 0x00),
59
VBI3_RGBA (0x00, 0x00, 0xFF), VBI3_RGBA (0xFF, 0x00, 0xFF),
60
VBI3_RGBA (0x00, 0xFF, 0xFF), VBI3_RGBA (0xFF, 0xFF, 0xFF),
61
VBI3_RGBA (0x00, 0x00, 0x00), VBI3_RGBA (0x77, 0x00, 0x00),
62
VBI3_RGBA (0x00, 0x77, 0x00), VBI3_RGBA (0x77, 0x77, 0x00),
63
VBI3_RGBA (0x00, 0x00, 0x77), VBI3_RGBA (0x77, 0x00, 0x77),
64
VBI3_RGBA (0x00, 0x77, 0x77), VBI3_RGBA (0x77, 0x77, 0x77),
65
VBI3_RGBA (0xFF, 0x00, 0x55), VBI3_RGBA (0xFF, 0x77, 0x00),
66
VBI3_RGBA (0x00, 0xFF, 0x77), VBI3_RGBA (0xFF, 0xFF, 0xBB),
67
VBI3_RGBA (0x00, 0xCC, 0xAA), VBI3_RGBA (0x55, 0x00, 0x00),
68
VBI3_RGBA (0x66, 0x55, 0x22), VBI3_RGBA (0xCC, 0x77, 0x77),
69
VBI3_RGBA (0x33, 0x33, 0x33), VBI3_RGBA (0xFF, 0x77, 0x77),
70
VBI3_RGBA (0x77, 0xFF, 0x77), VBI3_RGBA (0xFF, 0xFF, 0x77),
71
VBI3_RGBA (0x77, 0x77, 0xFF), VBI3_RGBA (0xFF, 0x77, 0xFF),
72
VBI3_RGBA (0x77, 0xFF, 0xFF), VBI3_RGBA (0xDD, 0xDD, 0xDD),
76
VBI3_RGBA (0x00, 0x00, 0x00), VBI3_RGBA (0xFF, 0xAA, 0x99),
77
VBI3_RGBA (0x44, 0xEE, 0x00), VBI3_RGBA (0xFF, 0xDD, 0x00),
78
VBI3_RGBA (0xFF, 0xAA, 0x99), VBI3_RGBA (0xFF, 0x00, 0xFF),
79
VBI3_RGBA (0x00, 0xFF, 0xFF), VBI3_RGBA (0xEE, 0xEE, 0xEE)
84
page_function_name (page_function function)
89
#define CASE(function) case PAGE_FUNCTION_##function : return #function ;
116
page_coding_name (page_coding coding)
121
#define CASE(coding) case PAGE_CODING_##coding : return #coding ;
138
object_type_name (object_type type)
141
case OBJECT_TYPE_NONE: return "NONE/LOCAL_ENH";
142
case OBJECT_TYPE_ACTIVE: return "ACTIVE";
143
case OBJECT_TYPE_ADAPTIVE: return "ADAPTIVE";
144
case OBJECT_TYPE_PASSIVE: return "PASSIVE";
152
drcs_mode_name (drcs_mode mode)
157
#define CASE(mode) case DRCS_MODE_##mode : return #mode ;
163
CASE (SUBSEQUENT_PTU)
172
* @param type Teletext page type.
174
* Returns the name of a Teletext page type, for example VBI3_SUBTITLE_PAGE ->
175
* "SUBTITLE_PAGE". This is mainly intended for debugging.
178
* Static ASCII string, NULL if @a type is invalid.
181
vbi3_ttx_page_type_name (vbi3_ttx_page_type type)
186
#define CASE(type) case VBI3_##type : return #type ;
191
CASE (SUBTITLE_INDEX)
192
CASE (NONSTD_SUBPAGES)
197
CASE (PROGR_SCHEDULE)
206
CASE (KEYWORD_SEARCH_LIST)
209
CASE (NEWSFLASH_PAGE)
221
pagenum_dump (const pagenum * pn,
224
fprintf (fp, "%s %3x.%04x",
225
page_function_name (pn->function),
226
pn->pgno, pn->subno);
230
cache_page_raw_dump (const cache_page * cp,
237
fprintf (fp, "Page %03x.%04x\n", cp->pgno, cp->subno);
239
for (j = 0; j < 25; ++j) {
241
case PAGE_CODING_TRIPLETS:
242
for (i = 0; i < 13; ++i) {
245
p = &cp->data.lop.raw[j][1 + i * 3];
246
fprintf (fp, "%05x ", vbi3_unham24p (p));
251
case PAGE_CODING_HAMMING84:
252
for (i = 0; i < 40; ++i) {
255
c = cp->data.lop.raw[j][i];
256
fprintf (fp, "%x", vbi3_unham8 (c));
262
for (i = 0; i < 40; ++i) {
265
c = cp->data.lop.raw[j][i];
266
fprintf (fp, "%02x ", c);
272
for (i = 0; i < 40; ++i)
273
fputc (vbi3_printable (cp->data.lop.raw[j][i]), fp);
281
extension_dump (const extension * ext,
286
fprintf (fp, "Extension:\n"
287
" designations %08x\n"
288
" charset=%u,%u def_screen_color=%u row_color=%u\n"
289
" bbg_subst=%u panel=%u,%u clut=%u,%u\n"
290
" 12x10x2 global dclut=",
292
ext->charset_code[0],
293
ext->charset_code[1],
294
ext->def_screen_color,
296
ext->fallback.black_bg_substitution,
297
ext->fallback.left_panel_columns,
298
ext->fallback.right_panel_columns,
299
ext->foreground_clut,
300
ext->background_clut);
302
for (i = 0; i < 4; ++i)
303
fprintf (fp, "%u, ", ext->drcs_clut[i + 2]);
305
fputs ("\n 12x10x2 dclut=", fp);
307
for (i = 0; i < 4; ++i)
308
fprintf (fp, "%u, ", ext->drcs_clut[i + 6]);
310
fputs ("\n 12x10x4 global dclut=", fp);
312
for (i = 0; i < 16; ++i)
313
fprintf (fp, "%u, ", ext->drcs_clut[i + 10]);
315
fputs ("\n 12x10x4 dclut=", fp);
317
for (i = 0; i < 16; ++i)
318
fprintf (fp, "%u, ", ext->drcs_clut[i + 26]);
320
fputs ("\n color_map=\n", fp);
322
for (i = 0; i < 40; ++i) {
323
fprintf (fp, "%08x, ", ext->color_map[i]);
333
unham8_page_number (pagenum * pn,
334
const uint8_t buffer[6],
339
b1 = vbi3_unham16p (buffer + 0);
340
b2 = vbi3_unham16p (buffer + 2);
341
b3 = vbi3_unham16p (buffer + 4);
343
if ((b1 | b2 | b3) < 0)
346
mag0 ^= ((b3 >> 5) & 6) + (b2 >> 7);
348
pn->function = PAGE_FUNCTION_UNKNOWN;
349
pn->pgno = MAG8 (mag0) * 256 + b1;
350
pn->subno = (b3 * 256 + b2) & 0x3F7F;
358
clear_lop (cache_page * cp)
360
memset (cp->data.lop.raw, 0x20, sizeof (cp->data.lop.raw));
362
/* NO_PAGE (pgno): (pgno & 0xFF) == 0xFF. */
363
memset (cp->data.lop.link, -1, sizeof (cp->data.lop.link));
365
cp->data.lop.have_flof = FALSE;
369
clear_enhancement (cache_page * cp)
371
/* Valid range of mode 0x00 ... 0x1F, broken -1. */
372
memset (cp->data.enh_lop.enh, -1, sizeof (cp->data.enh_lop.enh));
376
10.5 (Global) Public Object Page
380
clear_pop_page (cache_page * cp)
382
/* Valid range 0 ... 506 (39 packets * 13 triplets),
383
unused pointers 511 (10.5.1.2), broken -1. */
384
memset (cp->data.pop.pointer, -1, sizeof (cp->data.pop.pointer));
386
/* Valid range of mode 0x00 ... 0x1F, broken -1. */
387
memset (cp->data.pop.triplet, -1, sizeof (cp->data.pop.triplet));
391
decode_pop_packet (cache_page * cp,
392
const uint8_t buffer[40],
400
designation = vbi3_unham8 (buffer[0]);
404
for (i = 0; i < 13; ++i)
405
err |= n18[i] = vbi3_unham24p (buffer + 1 + i * 3);
407
if (TELETEXT_DECODER_LOG) {
408
log ("POP page %x.%x flags %x packet %u designation %d\n",
409
cp->pgno, cp->subno, cp->flags, packet, designation);
411
for (i = 1; i < 13; ++i)
412
log ("... %u: %d %x %u %u\n",
414
n18[i] & 0x1FF, (n18[i] >> 9) & 0x1FF);
417
if ((designation | err) < 0) {
422
packet += designation;
426
/* 10.5.1.2: Must be pointer table. */
427
if (0 && !(designation & 1)) {
434
if (designation & 1) {
439
index = (packet - 1) * 12 * 2;
441
/* 10.5.1.2: triplet[0] is reserved. */
442
for (i = 1; i < 13; ++i) {
443
cp->data.pop.pointer[index + 0] =
445
cp->data.pop.pointer[index + 1] =
448
log ("PT %2u %2u (%2u): %3u %3u\n",
465
trip = &cp->data.pop.triplet[(packet - 3) * 13];
467
for (i = 0; i < 13; ++i) {
468
trip->address = (n18[i] >> 0) & 0x3F;
469
trip->mode = (n18[i] >> 6) & 0x1F;
470
trip->data = (n18[i] >> 11);
486
convert_pop_page (cache_page * dst,
487
const cache_page * src,
488
page_function function)
495
clear_pop_page (dst);
497
dst->function = function;
499
raw = src->data.unknown.raw[1];
501
for (packet = 1; packet <= 25; ++packet) {
502
if (src->lop_packets & (1 << packet))
503
if (!decode_pop_packet (dst, raw, packet))
509
assert ((39 * 13 + 1) == N_ELEMENTS (dst->data.pop.triplet));
510
assert ((16 * 13 + 1) == N_ELEMENTS (src->data.enh_lop.enh));
512
if (src->x26_designations)
513
memcpy (dst->data.pop.triplet + 23 * 13,
514
src->data.enh_lop.enh,
515
sizeof (src->data.enh_lop.enh));
521
10.6 Magazine Organization Table
525
decode_mot_page_lut (magazine * mag,
526
const uint8_t buffer[2],
531
n0 = vbi3_unham8 (buffer[0]);
532
n1 = vbi3_unham8 (buffer[1]);
537
/* n0 & 8 "global objects required" ignored. */
538
/* n1 & 8 "global drcs required" ignored. */
540
mag->pop_lut[pgno] = n0 & 7;
541
mag->drcs_lut[pgno] = n1 & 7;
545
decode_mot_page_pop (vbi3_teletext_decoder * td,
547
const uint8_t buffer[40])
551
for (i = 0; i < 4; ++i) {
559
for (j = 0; j < 10; ++j)
560
err |= n4[j] = vbi3_unham8 (buffer[j]);
567
/* n4[0] & 8 "link page number may be superseded
568
by X/27/4 or X/27/5 data" ignored. */
570
pop->pgno = MAG8 (n4[0] & 7) * 256 + n4[1] * 16 + n4[2];
572
ps = cache_network_page_stat (td->network, pop->pgno);
574
ps->page_type = VBI3_SYSTEM_PAGE;
575
ps->subcode = n4[3]; /* highest S1 transmitted */
578
/* No side-panels, no black background
579
colour substitution. */
580
CLEAR (pop->fallback);
582
unsigned int s = (n4[4] >> 1) & 3;
584
pop->fallback.black_bg_substitution = n4[4] >> 3;
586
/* s: 0+0, 16+0, 0+16, 8+8 */
587
pop->fallback.left_panel_columns = "\00\20\00\10"[s];
588
pop->fallback.right_panel_columns = "\00\00\20\10"[s];
591
pop->default_obj[0].type = (object_type)(n4[5] & 3);
592
pop->default_obj[0].address = (n4[7] << 4) + n4[6];
594
pop->default_obj[1].type = (object_type)(n4[5] >> 2);
595
pop->default_obj[1].address = (n4[9] << 4) + n4[8];
602
decode_mot_page_drcs (vbi3_teletext_decoder * td,
604
const uint8_t buffer[40])
608
for (i = 0; i < 8; ++i) {
616
for (j = 0; j < 4; ++j)
617
err |= n4[j] = vbi3_unham8 (buffer[j]);
624
/* n4[0] & 8 "link page number may be superseded
625
by X/27/4 or X/27/5 data" ignored. */
627
pgno[i] = MAG8 (n4[0] & 7) * 256 + n4[1] * 16 + n4[2];
629
ps = cache_network_page_stat (td->network, pgno[i]);
631
ps->page_type = VBI3_SYSTEM_PAGE;
632
ps->subcode = n4[3]; /* highest S1 transmitted */
637
decode_mot_page (vbi3_teletext_decoder * td,
638
const cache_page * cp)
645
mag = cache_network_magazine (td->network, cp->pgno);
647
raw = cp->data.unknown.raw[1];
651
for (packet = 1; packet <= 8; ++packet) {
652
if (cp->lop_packets & (1 << packet)) {
655
for (i = 0x00; i <= 0x09; raw += 2, ++i)
656
decode_mot_page_lut (mag, raw, pgno + i);
658
for (i = 0x10; i <= 0x19; raw += 2, ++i)
659
decode_mot_page_lut (mag, raw, pgno + i);
669
for (packet = 9; packet <= 14; ++packet) {
670
if (cp->lop_packets & (1 << packet)) {
673
for (i = 0x0A; i <= 0x0F; raw += 2, ++i)
674
decode_mot_page_lut (mag, raw, pgno + i);
676
if (14 == packet) /* 0xFA ... 0xFF, rest unused */
679
for (i = 0x1A; i <= 0x1F; raw += 2, ++i)
680
decode_mot_page_lut (mag, raw, pgno + i);
682
for (i = 0x2A; i <= 0x2F; raw += 2, ++i)
683
decode_mot_page_lut (mag, raw, pgno + i);
685
raw += 40 - 3 * 6 * 2;
693
/* Level 2.5 POP links. */
695
for (packet = 19; packet <= 20; ++packet)
696
if (cp->lop_packets & (1 << packet))
697
decode_mot_page_pop (td, mag->pop_link[0]
699
cp->data.unknown.raw[packet]);
701
/* Level 2.5 DRCS links. */
703
if (cp->lop_packets & (1 << 21))
704
decode_mot_page_drcs (td, mag->drcs_link[0],
705
cp->data.unknown.raw[21]);
707
/* Level 3.5 POP links. */
709
for (packet = 22; packet <= 23; ++packet)
710
if (cp->lop_packets & (1 << packet))
711
decode_mot_page_pop (td, mag->pop_link[1]
713
cp->data.unknown.raw[packet]);
715
/* Level 3.5 DRCS links. */
717
if (cp->lop_packets & (1 << 24))
718
decode_mot_page_drcs (td, mag->drcs_link[1],
719
cp->data.unknown.raw[24]);
723
11.2 Table Of Pages navigation
727
top_page_number (pagenum * pn,
728
const uint8_t buffer[8])
738
for (i = 0; i < 8; ++i)
739
err |= n4[i] = vbi3_unham8 (buffer[i]);
741
pgno = n4[0] * 256 + n4[1] * 16 + n4[2];
748
subno = (n4[3] << 12) | (n4[4] << 8) | (n4[5] << 4) | n4[6];
750
switch ((top_page_function) n4[7]) {
751
case TOP_PAGE_FUNCTION_AIT:
752
pn->function = PAGE_FUNCTION_AIT;
755
case TOP_PAGE_FUNCTION_MPT:
756
pn->function = PAGE_FUNCTION_MPT;
759
case TOP_PAGE_FUNCTION_MPT_EX:
760
pn->function = PAGE_FUNCTION_MPT_EX;
764
pn->function = PAGE_FUNCTION_UNKNOWN;
769
pn->subno = subno & 0x3F7F; /* flags? */
774
/* 11.2 Basic TOP Table */
777
top_page_stat (cache_network * cn,
779
btt_page_type btt_type)
782
vbi3_ttx_page_type page_type;
783
unsigned int subcode;
786
subcode = SUBCODE_SINGLE_PAGE;
790
page_type = VBI3_NO_PAGE;
791
subcode = SUBCODE_UNKNOWN;
794
/* Observation: BTT_SUBTITLE only when the page is
795
transmitted, otherwise BTT_NO_PAGE. */
797
page_type = VBI3_SUBTITLE_PAGE;
800
case BTT_PROGR_INDEX_M:
801
subcode = SUBCODE_MULTI_PAGE;
804
case BTT_PROGR_INDEX_S:
805
/* Usually _SCHEDULE, not _INDEX. */
806
page_type = VBI3_PROGR_SCHEDULE;
810
subcode = SUBCODE_MULTI_PAGE;
814
page_type = VBI3_TOP_BLOCK;
818
subcode = SUBCODE_MULTI_PAGE;
822
page_type = VBI3_TOP_GROUP;
826
case BTT_NORMAL_11: /* ? */
827
subcode = SUBCODE_MULTI_PAGE;
831
case BTT_NORMAL_9: /* ? */
832
page_type = VBI3_NORMAL_PAGE;
836
page_type = VBI3_UNKNOWN_PAGE;
837
subcode = SUBCODE_UNKNOWN;
841
log ("BTT %04x: %2u %04x %s\n",
842
pgno, btt_type, subcode,
843
vbi3_ttx_page_type_name (page_type));
845
ps = cache_network_page_stat (cn, pgno);
849
if (ps->page_type != page_type
850
&& (VBI3_UNKNOWN_PAGE == ps->page_type
851
|| VBI3_SUBTITLE_PAGE == ps->page_type
852
|| VBI3_SUBTITLE_PAGE == page_type)) {
853
ps->page_type = page_type;
857
/* We only ever increase the subcode, such that the table
858
is consistent when BTT, MIP and the number of received
859
subpages disagree. SUBCODE_MULTI_PAGE means the page
860
has subpages, how many is not known (yet).
862
Interestingly there doesn't seem to be a btt_type for
863
clock pages, I saw only BTT_NORMAL_S. */
864
if (SUBCODE_UNKNOWN == ps->subcode
865
|| (SUBCODE_SINGLE_PAGE == ps->subcode
866
&& SUBCODE_MULTI_PAGE == subcode)) {
867
ps->subcode = subcode;
874
top_link_stat (cache_network * cn,
882
pn = &cn->btt_link[link];
884
switch (pn->function) {
885
case PAGE_FUNCTION_MPT:
886
case PAGE_FUNCTION_AIT:
887
case PAGE_FUNCTION_MPT_EX:
888
if (TELETEXT_DECODER_LOG) {
889
log ("BTT %2u: ", link);
890
pagenum_dump (pn, stderr);
891
fputc ('\n', stderr);
894
ps = cache_network_page_stat (cn, pn->pgno);
895
ps->page_type = VBI3_TOP_PAGE;
905
decode_btt_page (vbi3_teletext_decoder * td,
906
const cache_page * cp)
914
raw = cp->data.unknown.raw[1];
920
for (packet = 1; packet <= 20; ++packet) {
923
if (cp->lop_packets & (1 << packet)) {
924
for (i = 0; i < 40; ++i) {
925
btt_page_type btt_type;
927
btt_type = vbi3_unham8 (raw[i]);
929
if ((int) btt_type < 0) {
930
pgno = vbi3_add_bcd (pgno, 1);
934
changed |= top_page_stat (td->network,
937
pgno = vbi3_add_bcd (pgno, 1);
940
pgno = vbi3_add_bcd (pgno, 0x40);
946
/* Links to other TOP pages. */
950
for (packet = 21; packet <= 22; ++packet) {
951
if (cp->lop_packets & (1 << packet)) {
955
l = (packet - 21) * 5;
957
for (i = 0; i < 5; ++i) {
958
if (top_page_number (&cn->btt_link[l], raw))
959
top_link_stat (cn, l);
969
/* What's in packet 23? */
971
if (changed && (td->handlers.event_mask & VBI3_EVENT_PAGE_TYPE)) {
974
e.type = VBI3_EVENT_PAGE_TYPE;
975
e.network = &td->network->network;
976
e.timestamp = td->time;
978
_vbi3_event_handler_list_send (&td->handlers, &e);
982
/* 11.2 Additional Information Table */
985
decode_ait_packet (cache_page * cp,
986
const uint8_t buffer[40],
991
assert (46 * sizeof (ait_title) == sizeof (cp->data.ait.title));
993
if (packet < 1 || packet > 23)
996
for (i = 0; i < 2; ++i) {
1001
if (!top_page_number (&temp.page, buffer))
1006
for (j = 0; j < 12; ++j) {
1007
/* Usually filled up with spaces, but zeroes also
1009
c = vbi3_unpar8 (buffer[j]);
1021
if (TELETEXT_DECODER_LOG) {
1022
log ("AIT %2u: ", packet * 2 - 2 + i);
1023
pagenum_dump (&temp.page, stderr);
1024
fputc (' ', stderr);
1025
for (j = 0; j < 12; ++j)
1026
log ("%02x ", temp.text[j] & 0xFF);
1027
fputc ('>', stderr);
1028
for (j = 0; j < 12; ++j)
1029
fputc (vbi3_printable (temp.text[j]), stderr);
1030
fputs ("<\n", stderr);
1033
cp->data.ait.title[packet * 2 - 2 + i] = temp;
1040
convert_ait_page (cache_page * dst,
1041
const cache_page * src)
1043
unsigned int packet;
1046
/* NO_PAGE (pgno): (pgno & 0xFF) == 0xFF. */
1047
memset (&dst->data.ait, -1, sizeof (dst->data.ait));
1049
dst->function = PAGE_FUNCTION_AIT;
1051
raw = src->data.unknown.raw[1];
1053
for (packet = 1; packet <= 23; ++packet) {
1054
if (src->lop_packets & (1 << packet))
1055
if (!decode_ait_packet (dst, raw, packet))
1061
dst->data.ait.checksum = 0; /* changed */
1066
/* 11.2 Multi-Page Table */
1069
decode_mpt_page (vbi3_teletext_decoder * td,
1070
const cache_page * cp)
1072
unsigned int packet;
1076
raw = cp->data.unknown.raw[1];
1080
for (packet = 1; packet <= 20; ++packet) {
1081
if (cp->lop_packets & (1 << packet)) {
1084
for (i = 0; i < 40; ++i) {
1086
vbi3_ttx_page_type page_type;
1087
unsigned int subcode;
1090
if ((n = vbi3_unham8 (raw[i])) < 0) {
1091
pgno = vbi3_add_bcd (pgno, 1);
1095
ps = cache_network_page_stat
1096
(td->network, pgno);
1098
page_type = ps->page_type;
1099
subcode = ps->subcode;
1101
log ("MPT %04x: %04x %x %s\n",
1103
vbi3_ttx_page_type_name (page_type));
1106
/* Has more than 9 subpages, details
1107
may follow in MPT-EX. */
1111
if (SUBCODE_UNKNOWN == subcode)
1113
else if (SUBCODE_MULTI_PAGE == subcode)
1114
subcode = 0x0002; /* at least */
1116
if (VBI3_NO_PAGE != page_type
1117
&& VBI3_UNKNOWN_PAGE != page_type
1118
&& (unsigned int) n > subcode) {
1122
pgno = vbi3_add_bcd (pgno, 1);
1125
pgno = vbi3_add_bcd (pgno, 0x40);
1132
/* 11.2 Multi-Page Extension Table */
1135
decode_mpt_ex_page (vbi3_teletext_decoder * td,
1136
const cache_page * cp)
1138
unsigned int packet;
1141
raw = cp->data.unknown.raw[1];
1143
for (packet = 1; packet <= 23; ++packet) {
1144
if (cp->lop_packets & (1 << packet)) {
1147
for (i = 0; i < 5; ++i) {
1150
vbi3_ttx_page_type page_type;
1151
unsigned int subcode;
1153
if (!top_page_number (&pn, raw)) {
1158
pn.subno = vbi3_dec2bcd (pn.subno & 0x7F);
1160
if (TELETEXT_DECODER_LOG) {
1161
log ("MPT-EX %3u: ",
1162
(packet - 1) * 5 + i);
1163
pagenum_dump (&pn, stderr);
1164
fputc ('\n', stderr);
1167
if (pn.pgno < 0x100)
1169
else if (pn.pgno > 0x8FF
1174
ps = cache_network_page_stat
1175
(td->network, pn.pgno);
1177
page_type = ps->page_type;
1178
subcode = ps->subcode;
1180
if (SUBCODE_UNKNOWN == subcode)
1182
else if (SUBCODE_MULTI_PAGE == subcode)
1183
subcode = 0x0002; /* at least */
1185
if (VBI3_NO_PAGE != page_type
1186
&& VBI3_UNKNOWN_PAGE != page_type
1187
&& (unsigned int) pn.subno > subcode) {
1188
ps->subcode = pn.subno;
1200
11.3 Magazine Inventory Page
1204
mip_page_stat (cache_network * cn,
1205
const cache_page * cp,
1206
const uint8_t ** raw,
1207
unsigned int * sub_index,
1211
vbi3_ttx_page_type page_type;
1212
vbi3_ttx_page_type old_type;
1214
unsigned int subcode;
1215
unsigned int old_subcode;
1218
code = vbi3_unham16p (*raw);
1226
ps = cache_network_page_stat (cn, pgno);
1228
page_type = VBI3_UNKNOWN_PAGE;
1229
subcode = SUBCODE_UNKNOWN;
1231
old_type = ps->page_type;
1232
old_subcode = ps->subcode;
1235
case 0x00: /* VBI3_NO_PAGE */
1236
case 0x01: /* VBI3_NORMAL_PAGE, single page */
1237
case 0x78: /* VBI3_SUBTITLE_INDEX */
1238
case 0x7A: /* VBI3_PROGR_WARNING (adult content etc) */
1239
case 0x7C: /* VBI3_CURRENT_PROGR, single page */
1240
case 0x7D: /* VBI3_NOW_AND_NEXT */
1241
case 0x7F: /* VBI3_PROGR_INDEX, single page */
1242
case 0x80: /* VBI3_NOT_PUBLIC */
1243
case 0x81: /* VBI3_PROGR_SCHEDULE, single page */
1244
case 0xE3: /* VBI3_PFC_EPG_DATA */
1245
case 0xE4: /* VBI3_PFC_DATA */
1246
case 0xE7: /* VBI3_SYSTEM_PAGE, e.g. MOT and MIP */
1247
case 0xF9: /* VBI3_KEYWORD_SEARCH_LIST, single page */
1248
case 0xFC: /* VBI3_TRIGGER_DATA */
1249
case 0xFD: /* VBI3_ACI_PAGE (automatic channel installation) */
1250
case 0xFE: /* VBI3_TOP_PAGE (AIT, MPT, MPT-EX) */
1255
case 0x02 ... 0x4F: /* VBI3_NORMAL_PAGE with 2 ... 79 subpages */
1256
page_type = VBI3_NORMAL_PAGE;
1257
subcode = vbi3_dec2bcd (code);
1260
case 0x50 ... 0x51: /* normal page */
1261
case 0xD0 ... 0xD1: /* program */
1262
case 0xE0 ... 0xE1: /* page format CA */
1263
case 0x7B: /* current program, multi-page */
1264
case 0x7E: /* program index, multi-page */
1265
case 0xF8: /* keyword search list, multi-page */
1267
unsigned int packet = *sub_index / 13;
1271
if (packet > 24 || 0 == (cp->lop_packets & (1 << packet)))
1274
raw = &cp->data.unknown.raw[packet][*sub_index % 13];
1276
n = vbi3_unham16p (raw) | (vbi3_unham8 (raw[2]) << 8);
1280
} else if (0x1 == (code & 0xF)) {
1281
/* 4096+ subpages? Strange but true. */
1282
subcode = n + (1 << 12);
1289
page_type = (code == 0xF8) ? VBI3_KEYWORD_SEARCH_LIST :
1290
(code == 0x7E) ? VBI3_PROGR_INDEX :
1291
(code == 0x7B) ? VBI3_CURRENT_PROGR :
1292
(code >= 0xE0) ? VBI3_CA_DATA :
1293
(code >= 0xD0) ? VBI3_PROGR_SCHEDULE :
1298
case 0x52 ... 0x5F: /* reserved */
1299
case 0x60 ... 0x61: /* reserved, we use them as
1300
VBI3_TOP_BLOCK (= BTT_BLOCK_S/M)
1301
VBI3_TOP_GROUP (= BTT_GROUP_S/M) */
1302
case 0x62 ... 0x6F: /* reserved */
1303
case 0xD2 ... 0xDF: /* reserved */
1304
case 0xFF: /* reserved, we use it as VBI3_UNKNOWN_PAGE */
1308
page_type = VBI3_SUBTITLE_PAGE;
1311
if (0xFF == ps->charset_code) {
1312
const magazine *mag;
1313
vbi3_charset_code cs_code;
1315
mag = cache_network_magazine (cn, cp->pgno);
1317
cs_code = (mag->extension.charset_code[0]
1318
& (unsigned int) ~7)
1321
if (vbi3_character_set_from_code (cs_code)) {
1322
ps->charset_code = cs_code;
1324
ps->charset_code = cs_code & 7;
1332
case 0x79: /* VBI3_NONSTD_SUBPAGES (e.g. clock page) */
1333
page_type = VBI3_NONSTD_SUBPAGES;
1337
case 0x82 ... 0xCF: /* VBI3_PROGR_SCHEDULE with 2 ... 79 subpages */
1338
page_type = VBI3_PROGR_SCHEDULE;
1339
subcode = vbi3_dec2bcd (code & 0x7F);
1342
case 0xE2: /* Page format CA, undefined number of subpages. */
1343
case 0xE5: /* VBI3_DRCS_PAGE */
1344
case 0xE6: /* VBI3_POP_PAGE */
1345
case 0xF0 ... 0xF3: /* broadcaster system page */
1346
case 0xF4 ... 0xF6: /* test page */
1347
case 0xF7: /* displayable system page */
1349
subcode = old_subcode;
1353
page_type = VBI3_DRCS_PAGE;
1354
subcode = old_subcode;
1358
page_type = VBI3_POP_PAGE;
1359
subcode = old_subcode;
1363
if (old_type != page_type
1364
&& (VBI3_UNKNOWN_PAGE == old_type
1365
|| VBI3_SUBTITLE_PAGE == old_type
1366
|| VBI3_SUBTITLE_PAGE == page_type)) {
1367
ps->page_type = page_type;
1371
if (SUBCODE_UNKNOWN == old_subcode)
1372
old_subcode = 0x0000;
1373
else if (SUBCODE_MULTI_PAGE == old_subcode)
1374
old_subcode = 0x0002; /* at least */
1376
if (subcode > old_subcode) {
1377
ps->subcode = subcode;
1380
log ("MIP %04x: %02x:%02x:%04x %s\n",
1381
pgno, page_type, ps->charset_code, subcode,
1382
vbi3_ttx_page_type_name (page_type));
1388
decode_mip_page (vbi3_teletext_decoder * td,
1389
const cache_page * cp)
1391
unsigned int packet;
1392
unsigned int sub_index;
1397
sub_index = 15 * 13;
1399
raw = cp->data.unknown.raw[1];
1403
pgno = cp->pgno & 0xF00;
1405
for (packet = 1; packet <= 8; ++packet) {
1406
/* 11.3.2: Packets which contain only 0x00 VBI3_NO_PAGE
1408
if (cp->lop_packets & (1 << packet)) {
1411
for (i = 0x00; i <= 0x09; ++i)
1412
changed |= mip_page_stat (td->network, cp,
1416
for (i = 0x10; i <= 0x19; ++i)
1417
changed |= mip_page_stat (td->network, cp,
1427
pgno = cp->pgno & 0xF00;
1429
for (packet = 9; packet <= 14; ++packet) {
1430
/* 11.3.2: Packets which contain only 0x00 VBI3_NO_PAGE
1432
if (cp->lop_packets & (1 << packet)) {
1435
for (i = 0x0A; i <= 0x0F; ++i)
1436
changed |= mip_page_stat (td->network, cp,
1440
if (14 == packet) /* 0xFA ... 0xFF, rest unused */
1443
for (i = 0x1A; i <= 0x1F; ++i)
1444
changed |= mip_page_stat (td->network, cp,
1448
for (i = 0x2A; i <= 0x2F; ++i)
1449
changed |= mip_page_stat (td->network, cp,
1459
if (changed && (td->handlers.event_mask & VBI3_EVENT_PAGE_TYPE)) {
1462
e.type = VBI3_EVENT_PAGE_TYPE;
1463
e.network = &td->network->network;
1464
e.timestamp = td->time;
1466
_vbi3_event_handler_list_send (&td->handlers, &e);
1471
14. Dynamically Re-definable Characters download page
1475
cache_page_drcs_dump (const cache_page * cp,
1481
fprintf (fp, "DRCS page %03x.%04x\n", cp->pgno, cp->subno);
1483
p = cp->data.drcs.chars[0];
1485
for (i = 0; i < DRCS_PTUS_PER_PAGE; ++i) {
1488
fprintf (fp, "#%2u mode %02x\n ", i, cp->data.drcs.mode[i]);
1490
for (j = 0; j < 10; ++j) {
1493
for (k = 0; k < 6; ++k)
1494
fprintf (fp, "%x%x", p[k] & 15, p[k] >> 4);
1502
static const unsigned int
1504
0x000000, 0x100000, 0x010000, 0x110000,
1505
0x001000, 0x101000, 0x011000, 0x111000,
1506
0x000100, 0x100100, 0x010100, 0x110100,
1507
0x001100, 0x101100, 0x011100, 0x111100,
1508
0x000010, 0x100010, 0x010010, 0x110010,
1509
0x001010, 0x101010, 0x011010, 0x111010,
1510
0x000110, 0x100110, 0x010110, 0x110110,
1511
0x001110, 0x101110, 0x011110, 0x111110,
1512
0x000001, 0x100001, 0x010001, 0x110001,
1513
0x001001, 0x101001, 0x011001, 0x111001,
1514
0x000101, 0x100101, 0x010101, 0x110101,
1515
0x001101, 0x101101, 0x011101, 0x111101,
1516
0x000011, 0x100011, 0x010011, 0x110011,
1517
0x001011, 0x101011, 0x011011, 0x111011,
1518
0x000111, 0x100111, 0x010111, 0x110111,
1519
0x001111, 0x101111, 0x011111, 0x111111
1522
static const unsigned int
1524
0x000000, 0x110000, 0x001100, 0x111100,
1525
0x000011, 0x110011, 0x001111, 0x111111,
1529
decode_drcs_page (cache_page * cp)
1538
s = cp->data.drcs.lop.raw[1];
1540
for (i = 0; i < DRCS_PTUS_PER_PAGE / 2; ++i) {
1541
if (cp->lop_packets & (2 << i)) {
1544
for (j = 0; j < 40; ++j)
1545
if (vbi3_unpar8 (s[j]) < 0x40) {
1546
invalid |= ((uint64_t) 3) << (i * 2);
1550
invalid |= ((uint64_t) 3) << (i * 2);
1556
d = cp->data.drcs.chars[0];
1557
s = cp->data.drcs.lop.raw[1];
1559
for (i = 0; i < DRCS_PTUS_PER_PAGE; ++i) {
1563
switch ((drcs_mode) cp->data.drcs.mode[i]) {
1564
case DRCS_MODE_12_10_1:
1565
if (invalid & (((uint64_t) 1) << i)) {
1569
for (j = 0; j < 20; ++j) {
1570
q = expand1[*s++ & 0x3F];
1580
case DRCS_MODE_12_10_2:
1581
if (invalid & (((uint64_t) 3) << i)) {
1582
invalid |= ((uint64_t) 3) << i;
1586
for (j = 0; j < 20; ++j) {
1587
q = expand1[s[ 0] & 0x3F]
1588
+ expand1[s[20] & 0x3F] * 2;
1601
case DRCS_MODE_12_10_4:
1602
if (invalid & (((uint64_t) 15) << i)) {
1603
invalid |= ((uint64_t) 15) << i;
1607
for (j = 0; j < 20; ++j) {
1608
q = expand1[s[ 0] & 0x3F]
1609
+ expand1[s[20] & 0x3F] * 2
1610
+ expand1[s[40] & 0x3F] * 4
1611
+ expand1[s[60] & 0x3F] * 8;
1624
case DRCS_MODE_6_5_4:
1625
if (invalid & (((uint64_t) 1) << i)) {
1629
for (j = 0; j < 5; ++j) {
1630
q = expand2[s[0] & 7]
1631
+ expand2[s[1] & 7] * 2
1632
+ expand2[s[2] & 7] * 4
1633
+ expand2[s[3] & 7] * 8;
1637
q = expand2[(s[0] >> 3) & 7]
1638
+ expand2[(s[1] >> 3) & 7] * 2
1639
+ expand2[(s[2] >> 3) & 7] * 4
1640
+ expand2[(s[3] >> 3) & 7] * 8;
1645
memcpy (d + 6, d, 6);
1659
cp->data.drcs.invalid &= invalid;
1662
cache_page_drcs_dump (cp, stderr);
1668
* Since MOT, MIP and X/28 are optional, the function of a system page
1669
* may not be clear until we format a LOP and find a link.
1672
_vbi3_convert_cached_page (cache_page * cp,
1673
page_function new_function)
1678
if (PAGE_FUNCTION_UNKNOWN != cp->function) {
1682
log ("Convert page %s -> %s\n",
1683
page_function_name (cp->function),
1684
page_function_name (new_function));
1686
cache_page_copy (&temp, cp);
1688
switch (new_function) {
1689
case PAGE_FUNCTION_LOP:
1690
temp.function = new_function;
1693
case PAGE_FUNCTION_GPOP:
1694
case PAGE_FUNCTION_POP:
1695
if (!convert_pop_page (&temp, cp, new_function))
1699
case PAGE_FUNCTION_GDRCS:
1700
case PAGE_FUNCTION_DRCS:
1704
/* 14.1: Packet X/28/3 is optional when PTUs use only
1705
mode 12x10x1. B.2: X/28 must be transmitted before
1708
Since we didn't readily recognize the page as DRCS,
1709
X/28/3 has been omitted, so 12x10x1 must be assumed.
1710
When we missed X/28/3 due to a transmission error
1711
we will correct the page when retransmitted. */
1713
for (i = 0; i < DRCS_PTUS_PER_PAGE; ++i)
1714
temp.data.drcs.mode[i] = DRCS_MODE_12_10_1;
1716
temp.function = new_function;
1717
temp.data.drcs.invalid = (uint64_t) -1; /* all */
1719
decode_drcs_page (&temp);
1724
case PAGE_FUNCTION_AIT:
1725
if (!convert_ait_page (&temp, cp))
1730
/* Needs no conversion. */
1731
assert (!"reached");
1734
if (!(cp1 = _vbi3_cache_put_page (cp->network->cache,
1739
cache_page_unref (cp);
1745
eacem_trigger (vbi3_teletext_decoder * td,
1755
cache_page_raw_dump (cp, stderr, PAGE_CODING_ODD_PARITY);
1757
_vbi3_page_priv_init (&pgp);
1759
/* Must format the page for proper Level 1.5 characters. */
1760
if (!_vbi3_page_priv_from_cache_page (&pgp, cp,
1761
VBI3_WST_LEVEL, VBI3_WST_LEVEL_1p5,
1766
d = (uint8_t *) pgp.pg.text;
1768
for (i = 1 * 40; i < 25 * 40; ++i) {
1771
c = pgp.pg.text[i].unicode;
1772
*d++ = (c < 0x20 || c > 0xFF) ? 0x20 : c;
1777
_vbi3_trigger_list_add_eacem (&td->triggers,
1779
(uint8_t *) pgp.pg.text,
1780
&td->network->network,
1786
static vbi3_charset_code
1787
page_charset_code (vbi3_teletext_decoder * td,
1788
const cache_page * cp)
1790
vbi3_charset_code code;
1791
const magazine *mag;
1793
if (cp->x28_designations
1794
& cp->data.ext_lop.ext.designations & 0x11) {
1795
code = (cp->data.ext_lop.ext.charset_code[0]
1796
& (unsigned int) ~7) + cp->national;
1798
if (vbi3_character_set_from_code (code))
1801
code = cp->data.ext_lop.ext.charset_code[0];
1803
if (vbi3_character_set_from_code (code))
1807
mag = cache_network_magazine (td->network, cp->pgno);
1809
code = (mag->extension.charset_code[0] &
1810
(unsigned int) ~7) + cp->national;
1812
if (vbi3_character_set_from_code (code))
1815
code = mag->extension.charset_code[0];
1817
if (vbi3_character_set_from_code (code))
1820
return 0xFF; /* unknown */
1823
/* 9.3.1 Teletext packet 0, Page Header. */
1826
same_header (vbi3_pgno cur_pgno,
1827
const uint8_t * cur,
1829
const uint8_t * ref)
1837
/* NB this assumes vbi3_is_bcd (cur_pgno),
1838
which follows from roll_header. */
1840
buf[2] = (cur_pgno & 15) + '0';
1841
buf[1] = ((cur_pgno >> 4) & 15) + '0';
1842
buf[0] = (cur_pgno >> 8) + '0';
1851
/* Header: 8 byte page address & control, 24 text,
1852
8 byte hh:mm:ss (usually). */
1854
for (i = 8; i < 29; ++i) {
1855
if (cur[0] == buf[0]
1857
&& cur[2] == buf[2])
1859
err |= vbi3_unpar8 (*cur);
1860
err |= vbi3_unpar8 (*ref);
1861
neq |= *cur++ ^ *ref++;
1864
/* Skip page number. */
1871
for (; i < 32; ++i) {
1872
err |= vbi3_unpar8 (*cur);
1873
err |= vbi3_unpar8 (*ref);
1874
neq |= *cur++ ^ *ref++;
1877
/* Parity error or no page number. */
1878
if (err < 0 || j >= 32)
1879
return -3; /* inconclusive */
1882
/* I have yet to see equal headers from different
1883
networks, so this is probably correct. */
1887
/* Comparing headers from different magazines
1888
can result in false negatives. */
1889
if ((cur_pgno ^ ref_pgno) & 0xF00)
1890
return -2; /* inconclusive */
1892
/* Often headers show the current date. Check for false
1893
negative due to date transition. 23xmmxss -> 00xmmxss. */
1894
if (((ref[32] * 256 + ref[33]) & 0x7F7F) == 0x3233
1895
&& ((cur[32] * 256 + cur[33]) & 0x7F7F) == 0x3030) {
1896
return -1; /* inconclusive */
1899
/* Pages with headers from the same network can still differ,
1900
but what more can we do. */
1907
/* Note "clock" may not be a clock. */
1909
same_clock (const uint8_t * cur,
1910
const uint8_t * ref)
1914
for (i = 32; i < 40; ++i) {
1916
&& (vbi3_ipar8 (*cur) | vbi3_ipar8 (*ref)) >= 0)
1928
network_event (vbi3_teletext_decoder * td)
1932
e.type = VBI3_EVENT_NETWORK;
1933
e.network = &td->network->network;
1934
e.timestamp = td->time;
1936
_vbi3_event_handler_list_send (&td->handlers, &e);
1938
e.type = VBI3_EVENT_TOP_CHANGE;
1940
_vbi3_event_handler_list_send (&td->handlers, &e);
1943
e.type = VBI3_EVENT_PAGE_TYPE;
1945
_vbi3_event_handler_list_send (&td->handlers, &e);
1947
e.type = VBI3_EVENT_PROG_INFO;
1948
e.ev.prog_info = &cn->program_info;
1950
_vbi3_event_handler_list_send (&td->handlers, &e);
1957
detect_channel_change (vbi3_teletext_decoder * td,
1958
const cache_page * cp)
1963
if (0 == td->header_page.pgno) {
1964
/* First page after channel change, test may
1965
return inconclusive due to hamming error. */
1966
r = same_header (cp->pgno, cp->data.lop.raw[0] + 8,
1967
cp->pgno, cp->data.lop.raw[0] + 8);
1969
r = same_header (cp->pgno, cp->data.lop.raw[0] + 8,
1970
td->header_page.pgno, td->header + 8);
1975
if (TELETEXT_DECODER_CHSW_TEST) {
1976
fprintf (stderr, "+");
1980
td->header_page.pgno = cp->pgno;
1981
COPY (td->header, cp->data.lop.raw[0]);
1984
td->virtual_reset (td, NULL, -1.0);
1986
if (0) { /* XXX improve */
1988
nk = &td->network->network;
1991
&& 0 == nk->call_sign[0]
1992
&& 0 == (nk->cni_vps | nk->cni_8301 | nk->cni_8302)) {
1993
if (_vbi3_network_set_name_from_ttx_header
1994
(nk, cp->data.lop.raw[0]))
2003
if (TELETEXT_DECODER_CHSW_TEST) {
2004
fprintf (stderr, "-");
2008
td->header_page.pgno = cp->pgno;
2009
COPY (td->header, cp->data.lop.raw[0]);
2011
/* Reset at next vbi3_teletext_decoder_decode() call. */
2012
td->virtual_reset (td, NULL, td->time + 0.0);
2017
if (TELETEXT_DECODER_CHSW_TEST) {
2018
fprintf (stderr, "%d", -r);
2023
/* Date transition. */
2024
td->header_page.pgno = cp->pgno;
2025
COPY (td->header, cp->data.lop.raw[0]);
2026
} else if (td->reset_time <= 0) {
2027
/* Suspect a channel change. */
2028
td->virtual_reset (td, NULL, td->time
2029
+ td->cni_830_timeout);
2037
store_page (vbi3_teletext_decoder * td,
2042
if (td->reset_time > 0) {
2043
/* Suspended because we suspect a channel change. */
2044
if (PAGE_FUNCTION_LOP != cp->function)
2048
if (0 && !vbi3_is_bcd (cp->pgno) && 0xFF != (0xFF & cp->pgno)) {
2049
fprintf (stderr, "store_page:\n");
2050
cache_page_raw_dump (cp, stderr, PAGE_CODING_ODD_PARITY);
2053
switch (cp->function) {
2054
case PAGE_FUNCTION_EPG:
2055
case PAGE_FUNCTION_ACI:
2056
case PAGE_FUNCTION_DISCARD:
2057
case PAGE_FUNCTION_DATA:
2061
case PAGE_FUNCTION_LOP:
2064
vbi3_bool roll_header;
2067
cache_page_raw_dump (cp, stderr,
2068
PAGE_CODING_ODD_PARITY);
2070
roll_header = (vbi3_is_bcd (cp->pgno)
2071
&& 0 == (cp->flags &
2074
C7_SUPPRESS_HEADER |
2076
C10_INHIBIT_DISPLAY)));
2079
detect_channel_change (td, cp);
2081
/* We know there was a channel change, or the check was
2082
inconclusive and we suspect there was a change, or
2083
a change was already suspected but the header is unsuitable
2084
to make a decision now. Discard received data. */
2085
if (td->reset_time > 0)
2088
/* Collect information about pages
2089
not listed in MIP and BTT. */
2091
ps = cache_network_page_stat (td->network, cp->pgno);
2093
ps->flags = cp->flags;
2095
switch ((vbi3_ttx_page_type) ps->page_type) {
2097
case VBI3_UNKNOWN_PAGE:
2098
if (cp->flags & C6_SUBTITLE)
2099
ps->page_type = VBI3_SUBTITLE_PAGE;
2101
ps->page_type = VBI3_NORMAL_PAGE;
2103
if (0xFF == ps->charset_code)
2104
ps->charset_code = page_charset_code (td, cp);
2108
case VBI3_NORMAL_PAGE:
2109
if (cp->flags & C6_SUBTITLE)
2110
ps->page_type = VBI3_SUBTITLE_PAGE;
2112
if (0xFF == ps->charset_code)
2113
ps->charset_code = page_charset_code (td, cp);
2117
case VBI3_TOP_BLOCK:
2118
case VBI3_TOP_GROUP:
2119
case VBI3_SUBTITLE_INDEX:
2120
case VBI3_NONSTD_SUBPAGES:
2121
case VBI3_PROGR_WARNING:
2122
case VBI3_CURRENT_PROGR:
2123
case VBI3_NOW_AND_NEXT:
2124
case VBI3_PROGR_INDEX:
2125
case VBI3_PROGR_SCHEDULE:
2126
if (0xFF == ps->charset_code)
2127
ps->charset_code = page_charset_code (td, cp);
2130
case VBI3_SUBTITLE_PAGE:
2131
if (cp->flags & C6_SUBTITLE) {
2132
/* Keep up-to-date, just in case. */
2133
ps->charset_code = page_charset_code (td, cp);
2135
/* Fixes bug in ORF 1 BTT. */
2136
ps->page_type = VBI3_NORMAL_PAGE;
2145
if (td->handlers.event_mask & VBI3_EVENT_TTX_PAGE) {
2146
log ("... store %03x.%04x, "
2147
"packets=%x x26=%x x27=%x x28=%x\n",
2148
cp->pgno, cp->subno,
2150
cp->x26_designations,
2151
cp->x27_designations,
2152
cp->x28_designations);
2154
cp1 = _vbi3_cache_put_page (td->cache, td->network, cp);
2159
e.type = VBI3_EVENT_TTX_PAGE;
2160
e.network = &td->network->network;
2161
e.timestamp = td->time;
2163
e.ev.ttx_page.pgno = cp->pgno;
2164
e.ev.ttx_page.subno = cp->subno;
2166
e.ev.ttx_page.flags =
2167
(roll_header ? VBI3_ROLL_HEADER : 0)
2168
| (cp->flags & (C5_NEWSFLASH |
2171
C11_MAGAZINE_SERIAL));
2173
_vbi3_event_handler_list_send
2174
(&td->handlers, &e);
2176
cache_page_unref (cp1);
2183
case PAGE_FUNCTION_GPOP:
2184
case PAGE_FUNCTION_POP:
2185
/* Page was decoded on the fly. */
2187
if (td->handlers.event_mask & VBI3_EVENT_TTX_PAGE) {
2188
cp1 = _vbi3_cache_put_page
2189
(td->cache, td->network, cp);
2191
cache_page_unref (cp1);
2196
case PAGE_FUNCTION_GDRCS:
2197
case PAGE_FUNCTION_DRCS:
2198
/* (Global) Dynamically Redefinable Characters download page -
2199
Identify valid PTUs, convert PTU bit planes to character
2200
pixmaps and store in cp->data.drcs.chars[]. Note
2201
characters can span multiple packets. */
2202
if (td->handlers.event_mask & VBI3_EVENT_TTX_PAGE) {
2203
decode_drcs_page (cp);
2205
cp1 = _vbi3_cache_put_page
2206
(td->cache, td->network, cp);
2208
cache_page_unref (cp1);
2213
case PAGE_FUNCTION_MOT:
2214
/* Magazine Organization Table -
2215
Store valid (G)POP and (G)DRCS links in
2216
td->network->magazine[n], update td->network->pages[]. */
2217
decode_mot_page (td, cp);
2220
case PAGE_FUNCTION_MIP:
2221
/* Magazine Inventory Page -
2222
Store valid information in td->network->pages[]. */
2223
decode_mip_page (td, cp);
2226
case PAGE_FUNCTION_BTT:
2227
/* Basic TOP Table -
2228
Store valid information in td->network->pages[], valid
2229
links to other BTT pages in td->network->btt_link[]. */
2230
decode_btt_page (td, cp);
2233
case PAGE_FUNCTION_AIT:
2234
/* Page was decoded on the fly. */
2235
cp1 = _vbi3_cache_put_page (td->cache, td->network, cp);
2243
for (i = 0; i < sizeof (cp->data.ait.title); ++i)
2244
sum += ((uint8_t *) &cp->data.ait.title)[i];
2246
if (cp->data.ait.checksum != sum
2247
&& (td->handlers.event_mask
2248
& VBI3_EVENT_TOP_CHANGE)) {
2251
e.type = VBI3_EVENT_TOP_CHANGE;
2252
e.network = &td->network->network;
2253
e.timestamp = td->time;
2255
_vbi3_event_handler_list_send
2256
(&td->handlers, &e);
2259
cp1->data.ait.checksum = sum;
2261
cache_page_unref (cp1);
2266
case PAGE_FUNCTION_MPT:
2267
/* Multi-Page Table -
2268
Store valid information about single-digit subpages in
2269
td->network->pages[]. */
2270
decode_mpt_page (td, cp);
2273
case PAGE_FUNCTION_MPT_EX:
2274
/* Multi-Page Extension Table -
2275
Store valid information about multi-digit subpages in
2276
td->network->pages[]. */
2277
decode_mpt_ex_page (td, cp);
2280
case PAGE_FUNCTION_TRIGGER:
2281
if (td->handlers.event_mask & VBI3_EVENT_TRIGGER)
2282
eacem_trigger (td, cp);
2285
case PAGE_FUNCTION_UNKNOWN:
2286
/* The page is not listed in MIP, MOT or BTT, or
2287
we have no MIP, MOT or BTT (yet), and
2288
the page has no X/28/0 or /4, and
2289
the page has a non-bcd page number, and
2290
was not referenced from another page (yet). */
2291
cp1 = _vbi3_cache_put_page (td->cache, td->network, cp);
2292
cache_page_unref (cp1);
2300
epg_callback (vbi3_pfc_demux * pc,
2302
const vbi3_pfc_block * block)
2304
vbi3_teletext_decoder *td = user_data;
2312
decode_packet_0 (vbi3_teletext_decoder * td,
2314
const uint8_t buffer[42],
2321
cache_page *cached_cp;
2323
if ((page = vbi3_unham16p (buffer + 2)) < 0) {
2324
_vbi3_teletext_decoder_resync (td);
2326
log ("Hamming error in packet 0 page number\n");
2331
pgno = ((0 == mag0) ? 0x800 : mag0 << 8) + page;
2333
if (0 && !vbi3_is_bcd (page) && 0xFF != page) {
2334
fprintf (stderr, "System page %x\n", pgno);
2336
log ("Packet 0 page %x\n", pgno);
2340
if (td->current->flags & C11_MAGAZINE_SERIAL) {
2341
/* New pgno terminates the most recently
2344
if (td->current->pgno != pgno) {
2345
store_page (td, td->current);
2346
cp->function = PAGE_FUNCTION_DISCARD;
2349
/* A new pgno terminates the most recently
2350
received page of the same magazine. */
2351
if (0 != ((cp->pgno ^ pgno) & 0xFF)) {
2352
store_page (td, cp);
2353
cp->function = PAGE_FUNCTION_DISCARD;
2358
/* A.1: mFF time filling / terminator. */
2361
cp->function = PAGE_FUNCTION_DISCARD;
2365
subno = (vbi3_unham16p (buffer + 4)
2366
+ vbi3_unham16p (buffer + 6) * 256);
2369
flags = vbi3_unham16p (buffer + 8);
2371
if ((int)(subno | flags) < 0) {
2373
cp->function = PAGE_FUNCTION_DISCARD;
2379
if (PAGE_FUNCTION_DISCARD != cp->function
2381
&& cp->flags == (flags << 16) + subno) {
2382
/* Repeated header for time filling. */
2387
cp->national = vbi3_rev8 (flags) & 7;
2388
cp->flags = (flags << 16) + subno;
2390
if (vbi3_is_bcd (page)) {
2393
log ("Normal page %03x.%04x flags %06x\n",
2394
cp->pgno, subno, cp->flags);
2396
if (!vbi3_is_bcd (subno)) {
2398
cp->function = PAGE_FUNCTION_DISCARD;
2404
cp->subno = subno & 0x000F;
2406
log ("System page %03x.%04x flags %06x\n",
2407
cp->pgno, cp->subno, cp->flags);
2410
if (cp->flags & C4_ERASE_PAGE)
2413
cached_cp = _vbi3_cache_get_page (td->cache, td->network,
2414
cp->pgno, cp->subno,
2415
/* subno mask */ -1);
2418
log ("... %03x.%04x is cached, "
2419
"packets=%x x26=%x x27=%x x28=%x\n",
2420
cached_cp->pgno, cached_cp->subno,
2421
cached_cp->lop_packets,
2422
cached_cp->x26_designations,
2423
cached_cp->x27_designations,
2424
cached_cp->x28_designations);
2426
/* Page is already cached. We load it into our page buffer,
2427
add received data and store the page back when complete.
2428
Note packet decoders write only correct data, this way
2429
we can fix broken pages in two or more passes. */
2431
memcpy (&cp->data, &cached_cp->data,
2432
cache_page_size (cached_cp)
2433
- (sizeof (*cp) - sizeof (cp->data)));
2435
cp->function = cached_cp->function;
2437
switch (cp->function) {
2438
case PAGE_FUNCTION_UNKNOWN:
2439
case PAGE_FUNCTION_LOP:
2440
/* Store header packet. */
2441
memcpy (cp->data.unknown.raw[0], buffer + 2, 40);
2448
cp->lop_packets = cached_cp->lop_packets;
2449
cp->x26_designations = cached_cp->x26_designations;
2450
cp->x27_designations = cached_cp->x27_designations;
2451
cp->x28_designations = cached_cp->x28_designations;
2453
cache_page_unref (cached_cp);
2459
/* Page is not cached, we rebuild from scratch.
2460
EPG, DATA and TRIGGER pages are never cached, they must
2461
be handled by the appropriate demultiplexer.
2462
Data from MOT, MIP, BTT, MPT and MPT_EX pages is cached
2463
in the cache_network struct, not as page data. */
2465
ps = cache_network_page_stat (td->network, cp->pgno);
2467
log ("... rebuild %03x.%04x from scratch\n",
2468
cp->pgno, cp->subno);
2470
/* Determine the page function from A.10 reserved page numbers.
2471
A.1: MIP and MOT always use subno 0.
2472
XXX should erase MIP/MOT/TOP tables on C4. */
2474
if (0x1B0 == cp->pgno) {
2475
cp->function = PAGE_FUNCTION_ACI;
2476
ps->page_type = VBI3_ACI_PAGE;
2477
} else if (0x1F0 == cp->pgno) {
2478
cp->function = PAGE_FUNCTION_BTT;
2479
ps->page_type = VBI3_TOP_PAGE;
2480
CLEAR (cp->data.ext_lop);
2481
} else if (0xFD == page && 0 == cp->subno) {
2482
cp->function = PAGE_FUNCTION_MIP;
2483
ps->page_type = VBI3_SYSTEM_PAGE;
2484
CLEAR (cp->data.ext_lop);
2485
} else if (0xFE == page && 0 == cp->subno) {
2486
cp->function = PAGE_FUNCTION_MOT;
2487
ps->page_type = VBI3_SYSTEM_PAGE;
2488
CLEAR (cp->data.ext_lop);
2490
cp->function = PAGE_FUNCTION_UNKNOWN;
2493
clear_enhancement (cp);
2495
/* No X/28 packets received. */
2496
cp->data.ext_lop.ext.designations = 0;
2498
/* Store header packet. */
2499
memcpy (cp->data.unknown.raw[0] + 0, buffer + 2, 40);
2502
/* Packet 0 received. */
2503
cp->lop_packets = 1;
2504
cp->x26_designations = 0;
2505
cp->x27_designations = 0;
2506
cp->x28_designations = 0;
2509
/* Determine the page function from MOT, MIP or BTT data. Another
2510
opportunity arises when we receive packet X/28, see there. */
2512
if (PAGE_FUNCTION_UNKNOWN == cp->function) {
2515
ps = cache_network_page_stat (td->network, cp->pgno);
2517
switch ((vbi3_ttx_page_type) ps->page_type) {
2519
/* Who's wrong here? */
2520
ps->page_type = VBI3_UNKNOWN_PAGE;
2521
cp->function = PAGE_FUNCTION_DISCARD;
2524
case VBI3_NORMAL_PAGE:
2525
case VBI3_TOP_BLOCK:
2526
case VBI3_TOP_GROUP:
2527
case VBI3_SUBTITLE_PAGE:
2528
case VBI3_SUBTITLE_INDEX:
2529
case VBI3_NONSTD_SUBPAGES:
2530
case VBI3_CURRENT_PROGR:
2531
case VBI3_NOW_AND_NEXT:
2532
case VBI3_PROGR_WARNING:
2533
case VBI3_PROGR_INDEX:
2534
case VBI3_PROGR_SCHEDULE:
2535
cp->function = PAGE_FUNCTION_LOP;
2538
case VBI3_SYSTEM_PAGE:
2539
/* Not ACI, BTT, MOT or MIP (reserved page number),
2540
not MPT, AIT or MPT-EX (VBI3_TOP_PAGE),
2541
so it remains unknown. */
2551
for (i = 0; i < N_ELEMENTS (cn->btt_link); ++i)
2552
if (cn->btt_link[i].pgno == cp->pgno)
2555
if (i < N_ELEMENTS (cn->btt_link)) {
2556
switch (cn->btt_link[i].function) {
2557
case PAGE_FUNCTION_MPT:
2558
case PAGE_FUNCTION_MPT_EX:
2560
cn->btt_link[i].function;
2563
case PAGE_FUNCTION_AIT:
2567
cache_page_copy (&temp, cp);
2568
convert_ait_page (cp, &temp);
2570
cp->function = PAGE_FUNCTION_AIT;
2576
assert (!"reached");
2580
log ("%03x.%04x claims to be "
2581
"TOP page, but no link found\n",
2582
cp->pgno, cp->subno);
2588
case VBI3_DRCS_PAGE:
2592
/* 14.1: Packet X/28/3 is optional when PTUs use only
2593
mode 12x10x1. B.2: X/28 must be transmitted before
2596
We have only the header yet, so let's default.
2597
Conversion of packets 1 ... 24 we may have cached
2598
before takes place when the page is complete. */
2599
for (i = 0; i < DRCS_PTUS_PER_PAGE; ++i)
2600
cp->data.drcs.mode[i] = DRCS_MODE_12_10_1;
2602
cp->function = PAGE_FUNCTION_DRCS;
2611
cache_page_copy (&temp, cp);
2612
convert_pop_page (cp, &temp, PAGE_FUNCTION_POP);
2617
case VBI3_TRIGGER_DATA:
2618
cp->function = PAGE_FUNCTION_TRIGGER;
2621
case VBI3_PFC_EPG_DATA:
2623
cp->function = PAGE_FUNCTION_EPG;
2626
if (0 == td->epg_stream[0].block.pgno) {
2627
_vbi3_pfc_demux_init (&td->epg_stream[0],
2631
_vbi3_pfc_demux_init (&td->epg_stream[1],
2639
case VBI3_NOT_PUBLIC:
2642
case VBI3_KEYWORD_SEARCH_LIST:
2643
cp->function = PAGE_FUNCTION_DISCARD;
2647
if (vbi3_is_bcd (page))
2648
cp->function = PAGE_FUNCTION_LOP;
2649
/* else remains unknown. */
2653
log ("... identified as %s\n",
2654
page_function_name (cp->function));
2657
switch (cp->function) {
2658
case PAGE_FUNCTION_ACI:
2659
case PAGE_FUNCTION_TRIGGER:
2663
case PAGE_FUNCTION_BTT:
2664
case PAGE_FUNCTION_AIT:
2665
case PAGE_FUNCTION_MPT:
2666
case PAGE_FUNCTION_MPT_EX:
2668
/* Observation: BTT with 3Fx0, others with 0000. */
2671
case PAGE_FUNCTION_LOP:
2672
/* 0000 single page, 0001 ... 0079 multi page
2673
2359 clock page / subpages not to be cached. */
2676
case PAGE_FUNCTION_EPG:
2677
case PAGE_FUNCTION_DATA:
2678
/* Uses different scheme, see EN 300 708 4.3.1 */
2681
case PAGE_FUNCTION_GPOP:
2682
case PAGE_FUNCTION_POP:
2683
case PAGE_FUNCTION_GDRCS:
2684
case PAGE_FUNCTION_DRCS:
2685
case PAGE_FUNCTION_MOT:
2686
case PAGE_FUNCTION_MIP:
2688
unsigned int last_packet;
2689
unsigned int continuity;
2691
/* A.1, B.6 Page numbering. */
2692
/* C12, C13 not observed in the field, last_packet
2693
is unreliable, so this information is pretty useless. */
2695
last_packet = subno >> 8;
2696
continuity = (subno >> 4) & 15;
2698
if (last_packet >= 26)
2699
log ("... last packet X/26/%u ci %u ",
2700
last_packet - 26, continuity);
2702
log ("... last packet X/%u ci %u ",
2703
last_packet, continuity);
2705
if (cp->flags & C13_PARTIAL_PAGE)
2706
log ("partial page");
2710
if (cp->flags & C12_FRAGMENT)
2711
log (" fragment\n");
2713
log (", complete or first fragment\n");
2718
case PAGE_FUNCTION_DISCARD:
2719
case PAGE_FUNCTION_UNKNOWN:
2726
/* 9.4.1 Teletext packet 26, enhancement data. */
2729
decode_packet_26 (vbi3_teletext_decoder * td,
2731
const uint8_t buffer[42])
2739
switch (cp->function) {
2740
case PAGE_FUNCTION_DISCARD:
2743
case PAGE_FUNCTION_GPOP:
2744
case PAGE_FUNCTION_POP:
2745
return decode_pop_packet (cp, buffer + 2, 26);
2747
case PAGE_FUNCTION_ACI:
2748
case PAGE_FUNCTION_EPG:
2749
case PAGE_FUNCTION_DATA:
2750
case PAGE_FUNCTION_GDRCS:
2751
case PAGE_FUNCTION_DRCS:
2752
case PAGE_FUNCTION_MOT:
2753
case PAGE_FUNCTION_MIP:
2754
case PAGE_FUNCTION_BTT:
2755
case PAGE_FUNCTION_AIT:
2756
case PAGE_FUNCTION_MPT:
2757
case PAGE_FUNCTION_MPT_EX:
2758
/* Not supposed to have X/26, tx error? */
2759
_vbi3_teletext_decoder_resync (td);
2762
case PAGE_FUNCTION_UNKNOWN:
2763
case PAGE_FUNCTION_LOP:
2764
case PAGE_FUNCTION_TRIGGER:
2768
designation = vbi3_unham8 (buffer[2]);
2772
for (i = 0; i < 13; ++i)
2773
err |= n18[i] = vbi3_unham24p (buffer + 3 + i * 3);
2775
if (TELETEXT_DECODER_LOG) {
2776
log ("Packet X/26/%u page %x.%x flags %x\n",
2777
designation, cp->pgno, cp->subno, cp->flags);
2779
for (i = 1; i < 13; ++i)
2780
log ("... %u: %d %x\n",
2784
if ((designation | err) < 0) {
2789
/* B.2, D.1.3: Packets X/26 must arrive in designation order
2790
0 ... 15. No check here if the sequence is correct
2791
and complete, that happens in page formatting. */
2792
if (cp->x26_designations != (0x0FFFFU >> (16 - designation))) {
2793
cp->x26_designations = 0;
2798
cp->x26_designations |= 1 << designation;
2800
trip = &cp->data.enh_lop.enh[designation * 13];
2802
for (i = 0; i < 13; ++i) {
2803
trip->address = (n18[i] >> 0) & 0x3F;
2804
trip->mode = (n18[i] >> 6) & 0x1F;
2805
trip->data = (n18[i] >> 11);
2813
/* 9.6 Teletext packet 27, page linking. */
2816
decode_packet_27 (vbi3_teletext_decoder * td,
2818
const uint8_t buffer[42])
2823
switch (cp->function) {
2824
case PAGE_FUNCTION_DISCARD:
2827
case PAGE_FUNCTION_ACI:
2828
case PAGE_FUNCTION_EPG:
2829
case PAGE_FUNCTION_DATA:
2830
case PAGE_FUNCTION_GPOP:
2831
case PAGE_FUNCTION_POP:
2832
case PAGE_FUNCTION_GDRCS:
2833
case PAGE_FUNCTION_DRCS:
2834
case PAGE_FUNCTION_MOT:
2835
case PAGE_FUNCTION_MIP:
2836
case PAGE_FUNCTION_BTT:
2837
case PAGE_FUNCTION_AIT:
2838
case PAGE_FUNCTION_MPT:
2839
case PAGE_FUNCTION_MPT_EX:
2840
case PAGE_FUNCTION_TRIGGER:
2841
/* Not supposed to have X/27, tx error? */
2842
_vbi3_teletext_decoder_resync (td);
2845
case PAGE_FUNCTION_UNKNOWN:
2846
case PAGE_FUNCTION_LOP:
2850
if ((designation = vbi3_unham8 (buffer[2])) < 0)
2853
log ("Packet X/27/%u page %03x.%x\n",
2854
designation, cp->pgno, cp->subno);
2858
switch (designation) {
2864
if ((control = vbi3_unham8 (buffer[39])) < 0)
2867
log ("... control %02x\n", control);
2869
/* CRC cannot be trusted, some stations transmit
2870
incorrect data. Link Control Byte bits 1 ... 3
2871
(disable green, yellow, blue key) cannot be
2872
trusted, EN 300 706 is ambiguous and not all
2873
stations follow the suggestions of ETR 287. */
2875
crc = buffer[40] + buffer[41] * 256;
2877
log ("... crc %04x\n", crc);
2879
/* ETR 287 section 10.4: Have FLOF, display row 24. */
2880
cp->data.lop.have_flof = control >> 3;
2891
for (i = 0; i < 6; ++i) {
2894
pn = &cp->data.lop.link[designation * 6 + i];
2896
/* Hamming error ignored. We just don't store
2897
broken page numbers. */
2898
unham8_page_number (pn, p,
2899
(unsigned int)(cp->pgno >> 8) & 7);
2902
log ("... link[%u] = %03x.%04x\n",
2903
i, pn->pgno, pn->subno);
2906
cp->x27_designations |= 1 << designation;
2917
/* (Never observed this in the field;
2918
let's hope the code is correct.) */
2920
for (i = 0; i < 6; ++i) {
2924
t1 = vbi3_unham24p (p + 0);
2925
t2 = vbi3_unham24p (p + 3);
2932
if (designation <= 5 && (t1 & (1 << 10))) {
2934
unsigned int validity;
2936
/* 9.6.2 Packets X/27/4 and X/27/5 format 1. */
2938
/* t1: tt ttmmm1uu uuxxvvff */
2939
/* t2: ss ssssssss ssssssx0 */
2941
pn = &cp->data.lop.link[designation * 6 + i];
2943
/* GPOP, POP, GDRCS, DRCS */
2944
pn->function = PAGE_FUNCTION_GPOP + (t1 & 3);
2946
validity = (t1 >> 2) & 3;
2948
mag0 = (cp->pgno ^ (t1 >> 3)) & 0x700;
2950
pn->pgno = ((0 == mag0) ? 0x800 : mag0)
2952
+ ((t1 >> 6) & 0x00F);
2954
/* NB this is "set of required subpages",
2955
not a real subno. */
2956
pn->subno = t2 >> 2;
2958
log ("... link[%u] = %s %x/%x\n",
2959
i, page_function_name (pn->function),
2960
pn->pgno, pn->subno);
2964
"The function of first four links in a
2965
packet X/27/4 with the link coding of
2966
table 15 is fixed for Level 2.5, as shown
2967
in table 16. The Page Validity bits may
2968
also indicate their use at Level 3.5. The
2969
function of the remaining two links in a
2970
packet X/27/4 and the first two links in
2971
a packet X/27/5 is defined by the Link
2972
Function and Page Validity bits. These
2973
links do not contain information
2974
relevant to a Level 2.5 decoder." */
2976
/* 9.6.3 Packets X/27/4 to X/27/7 format 2 -
2977
compositional linking in data broadcasting
2984
cp->x27_designations |= 1 << designation;
2990
/* Undefined, ignored. */
2998
9.4.2, 9.4.3, 9.5 Teletext packets 28 and 29,
2999
Level 2.5/3.5 enhancement.
3004
unsigned int buffer;
3009
get_bits (struct bit_stream * bs,
3016
n = count - bs->left;
3019
bs->buffer = *(bs->triplet)++;
3020
r |= bs->buffer << bs->left;
3029
return r & ((1UL << count) - 1);
3033
decode_packet_28_29 (vbi3_teletext_decoder * td,
3035
const uint8_t buffer[42],
3036
unsigned int packet)
3041
struct bit_stream bs;
3047
switch (cp->function) {
3048
case PAGE_FUNCTION_DISCARD:
3057
if ((designation = vbi3_unham8 (*p++)) < 0)
3060
log ("Packet %u/%u/%u page %03x.%x\n",
3061
(cp->pgno >> 8) & 7, packet, designation,
3062
cp->pgno, cp->subno);
3066
for (i = 0; i < 13; ++i) {
3067
err |= n18[i] = vbi3_unham24p (p);
3075
switch (designation) {
3078
/* X/28/0, M/29/0 Level 2.5 */
3085
triplet[13 ... 0], bit 18 ... 1:
3086
... ssss pppppp p 000 0000 a)
3087
reserved 0011 111111 1 001 0001 b)
3088
reserved 0011 111111 1 ccc ffff c)
3089
reserved cccc 000000 0 xx0 0000 d)
3090
reserved cccc 000000 1 000 0100 e)
3091
reserved cccc 000000 1 000 0101 f)
3092
... 000000 0 ccc ffff g)
3093
... 000000 1 111 0011 h)
3094
... 000010 0 111 0011 h)
3096
a) X/28/0 format 1 - function = LOP,
3097
coding = ODD_PARITY, primary and secondary
3098
character set code (0 ... 87) (EN 300 706,
3100
b) X/28/0 format 1 - function = DATA (PFC),
3101
coding = UBYTES (EN 300 708, 4.3.3)
3102
c) X/28/0 format 1 for other types of pages
3103
(EN 300 706, 9.4.2.4)
3104
d) X/28/0 format 2 (CA) - coding 0 ... 3.
3105
(EN 300 706, 9.4.3 and EN 300 708, 5.4.1)
3107
g) observed on SWR with cccffff != 0, in violation
3109
h) observed on ARTE, transmitted with various
3110
level one pages. Apparently not format 1 or 2.
3112
How am I supposed to distinguish a) with p=0 (en)
3113
or p=1 (de) from d)? Not to mention g) and h).
3116
if (0 == (n18[0] & 0x3F00)
3117
&& 0 != (n18[0] & 0x7F)) {
3120
log ("... format 2 ignored.\n");
3123
for (i = 0; i < 40; ++i)
3124
fprintf (stderr, "%02x ",
3126
fputc ('\n', stderr);
3128
for (i = 0; i < 13; ++i)
3129
fprintf (stderr, "%05x ",
3131
fputc ('\n', stderr);
3143
page_function function;
3146
/* X/28/0, M/29/0 Level 2.5 */
3147
/* X/28/4, M/29/4 Level 3.5 */
3152
function = get_bits (&bs, 4);
3153
coding = get_bits (&bs, 3);
3155
log ("... %s, %s\n",
3156
page_function_name (function),
3157
page_coding_name (coding));
3159
if (function > PAGE_FUNCTION_TRIGGER
3160
|| coding > PAGE_CODING_META84)
3161
break; /* undefined */
3164
if (PAGE_FUNCTION_UNKNOWN == cp->function) {
3166
case PAGE_FUNCTION_ACI:
3167
case PAGE_FUNCTION_EPG:
3168
case PAGE_FUNCTION_DISCARD:
3169
case PAGE_FUNCTION_UNKNOWN:
3170
/* libzvbi private */
3171
assert (!"reached");
3173
case PAGE_FUNCTION_LOP:
3174
/* ZDF and BR3 transmit GPOP 1EE/..
3175
with 1/28/0 function 0 =
3176
PAGE_FUNCTION_LOP, should be
3177
PAGE_FUNCTION_GPOP. Cannot
3181
case PAGE_FUNCTION_DATA:
3182
case PAGE_FUNCTION_MOT:
3183
case PAGE_FUNCTION_MIP:
3184
case PAGE_FUNCTION_BTT:
3185
case PAGE_FUNCTION_MPT:
3186
case PAGE_FUNCTION_MPT_EX:
3187
case PAGE_FUNCTION_TRIGGER:
3188
cp->function = function;
3191
case PAGE_FUNCTION_GPOP:
3192
case PAGE_FUNCTION_POP:
3196
cache_page_copy (&temp, cp);
3197
convert_pop_page (cp, &temp, function);
3202
case PAGE_FUNCTION_GDRCS:
3203
case PAGE_FUNCTION_DRCS:
3207
/* See comments in decode_packet_0. */
3208
for (i= 0; i < DRCS_PTUS_PER_PAGE; ++i)
3209
cp->data.drcs.mode[i] =
3212
cp->function = function;
3217
case PAGE_FUNCTION_AIT:
3221
cache_page_copy (&temp, cp);
3222
convert_ait_page (cp, &temp);
3227
} else if (function != cp->function) {
3228
/* Who's wrong here? */
3229
cp->function = PAGE_FUNCTION_DISCARD;
3233
/* 9.4.2.2: Rest of packet applies to LOP only. */
3234
if (PAGE_FUNCTION_LOP != function)
3237
/* All remaining triplets must be correct. */
3241
ext = &cp->data.ext_lop.ext;
3243
cp->x28_designations |= 1 << designation;
3245
/* 9.5.1: Rest of packet applies if zero. */
3246
if (function | coding)
3252
ext = &cache_network_magazine (td->network, cp->pgno)
3256
if (4 == designation
3257
&& (ext->designations & (1 << 0))) {
3258
/* 9.4.2.2: X/28/0 takes precedence over X/28/4,
3259
9.5.1: M/29/0 takes precendence over M/29/4,
3260
for all but the colour map entry coding. */
3261
get_bits (&bs, 7 + 7 + 1 + 1 + 1 + 4);
3263
unsigned int left_panel;
3264
unsigned int right_panel;
3265
unsigned int left_columns;
3267
ext->charset_code[0] = get_bits (&bs, 7);
3268
ext->charset_code[1] = get_bits (&bs, 7);
3270
left_panel = get_bits (&bs, 1);
3271
right_panel = get_bits (&bs, 1);
3273
/* 0 - panels required at Level 3.5 only,
3278
left_columns = get_bits (&bs, 4);
3280
if (left_panel && 0 == left_columns)
3283
ext->fallback.left_panel_columns =
3284
left_columns & -left_panel;
3285
ext->fallback.right_panel_columns =
3286
(16 - left_columns) & -right_panel;
3289
/* Color map for CLUTs 0 & 1 (desig. 4) or 2 & 3. */
3291
j = (4 == designation) ? 16 : 32;
3293
for (i = j - 16; i < j; ++i) {
3294
vbi3_rgba col = get_bits (&bs, 12);
3296
if (8 == i) /* transparent */
3299
col = VBI3_RGBA ((col ) & 15,
3303
ext->color_map[i] = col | (col << 4);
3306
/* libzvbi private, invariable. */
3307
memcpy (ext->color_map + 32, default_color_map + 32,
3308
8 * sizeof (*ext->color_map));
3310
if (4 == designation
3311
&& (ext->designations & (1 << 0))) {
3312
/* 9.4.2.2: X/28/0 takes precedence over X/28/4,
3313
9.5.1: M/29/0 takes precendence over M/29/4,
3314
for all but the colour map entry coding. */
3315
get_bits (&bs, 5 + 5 + 1 + 3);
3317
ext->def_screen_color = get_bits (&bs, 5);
3318
ext->def_row_color = get_bits (&bs, 5);
3320
ext->fallback.black_bg_substitution =
3323
i = get_bits (&bs, 3); /* color table remapping */
3325
ext->foreground_clut = "\00\00\00\10\10\20\20\20"[i];
3326
ext->background_clut = "\00\10\20\10\20\10\20\30"[i];
3329
ext->designations |= 1 << designation;
3332
extension_dump (ext, stderr);
3337
case 1: /* X/28/1, M/29/1 Level 3.5 DRCS CLUT */
3343
ext = &cp->data.ext_lop.ext;
3345
cp->x28_designations |= 1 << 1;
3347
ext = &cache_network_magazine (td->network, cp->pgno)
3351
/* 9.4.4: "Compatibility, not for Level 2.5/3.5 decoders."
3352
No more details, so we ignore this triplet. */
3355
for (i = 0; i < 8; ++i)
3356
ext->drcs_clut[i + 2] =
3357
vbi3_rev8 (get_bits (&bs, 5)) >> 3;
3359
for (i = 0; i < 32; ++i)
3360
ext->drcs_clut[i + 10] =
3361
vbi3_rev8 (get_bits (&bs, 5)) >> 3;
3363
ext->designations |= 1 << 1;
3370
/* CA key packet ignored. */
3377
page_function function;
3380
/* X/28/3 Level 3.5 DRCS download page modes */
3383
break; /* M/29/3 undefined */
3388
cp->x28_designations |= 1 << 3;
3390
function = get_bits (&bs, 4);
3391
coding = get_bits (&bs, 3);
3393
log ("... %s, %s\n",
3394
page_function_name (function),
3395
page_coding_name (coding));
3397
if (PAGE_FUNCTION_GDRCS != function
3398
&& PAGE_FUNCTION_DRCS != function)
3399
break; /* undefined */
3404
if (PAGE_FUNCTION_UNKNOWN == cp->function) {
3405
cp->function = function;
3406
} else if (function != cp->function) {
3407
/* Who's wrong here? */
3408
cp->function = PAGE_FUNCTION_DISCARD;
3412
get_bits (&bs, 11); /* reserved */
3414
for (i = 0; i < 48; ++i)
3415
cp->data.drcs.mode[i] = get_bits (&bs, 4);
3417
/* Rest reserved. */
3423
/* Undefined, ignored. */
3431
/* 9.8 Teletext packet 8/30, broadcast service data. */
3434
cni_change (vbi3_teletext_decoder * td,
3445
if (VBI3_CNI_TYPE_VPS != type
3446
&& 0 != cn->network.cni_vps
3447
&& (cn->network.cni_vps
3448
!= vbi3_convert_cni (VBI3_CNI_TYPE_VPS, type, cni))) {
3449
/* We cannot say with certainty if cni and cni_vps belong
3450
to the same network. If 0 == vbi3_convert_cni() we cannot
3451
convert, otherwise CNIs mismatch because the channel
3452
changed, the network transmits wrong CNIs or the
3453
conversion is incorrect.
3455
After n seconds, if we cannot confirm the cni_vps or
3456
receive a new one, we assume there was a channel change
3457
and the new network does not transmit a cni_vps. */
3458
cn->confirm_cni_vps = cn->network.cni_vps;
3459
timeout = td->cni_vps_timeout;
3462
if (VBI3_CNI_TYPE_8301 != type
3463
&& 0 != cn->network.cni_8301
3464
&& (cn->network.cni_8301
3465
!= vbi3_convert_cni (VBI3_CNI_TYPE_8301, type, cni))) {
3466
cn->confirm_cni_8301 = cn->network.cni_8301;
3467
timeout = td->cni_830_timeout;
3470
if (VBI3_CNI_TYPE_8302 != type
3471
&& 0 != cn->network.cni_8302
3472
&& (cn->network.cni_8302
3473
!= vbi3_convert_cni (VBI3_CNI_TYPE_8302, type, cni))) {
3474
cn->confirm_cni_8302 = cn->network.cni_8302;
3475
timeout = td->cni_830_timeout;
3478
if (timeout > 0.0) {
3479
td->virtual_reset (td, NULL,
3480
td->time + MAX (timeout, timeout_min));
3485
status_change (vbi3_teletext_decoder * td,
3486
const uint8_t buffer[42])
3488
const vbi3_character_set *cs;
3493
cs = vbi3_character_set_from_code (0); /* XXX ok? */
3494
title = _vbi3_strdup_locale_teletext (buffer + 22, 20, cs);
3502
vbi3_free (cn->program_info.title);
3503
cn->program_info.title = title;
3505
e.type = VBI3_EVENT_PROG_INFO;
3506
e.network = &cn->network;
3507
e.timestamp = td->time;
3508
e.ev.prog_info = &cn->program_info;
3510
_vbi3_event_handler_list_send (&td->handlers, &e);
3517
decode_packet_8_30 (vbi3_teletext_decoder * td,
3518
const uint8_t buffer[42])
3522
if ((designation = vbi3_unham8 (buffer[2])) < 0)
3525
log ("Packet 8/30/%d\n", designation);
3527
if (designation > 4)
3528
return TRUE; /* undefined, ignored */
3530
if (td->reset_time <= 0.0) {
3531
if (td->handlers.event_mask & VBI3_EVENT_TTX_PAGE) {
3534
if (!unham8_page_number (&pn, buffer + 3, 0))
3537
/* 9.8.1 Table 18 Note 2 */
3538
if (!NO_PAGE (pn.pgno)) {
3539
pn.function = PAGE_FUNCTION_LOP;
3540
td->network->initial_page = pn;
3544
if (td->handlers.event_mask & VBI3_EVENT_PROG_INFO) {
3551
for (i = 0; i < 20; ++i) {
3552
err |= vbi3_unpar8 (buffer[i + 22]);
3555
int c = buffer[i + 22];
3557
fprintf (stderr, "%2u %02x %02x %c\n",
3559
td->network->status[i],
3561
vbi3_printable (c));
3568
assert (20 == sizeof (td->network->status));
3570
s = td->network->status;
3572
if (0 != memcmp (s, buffer + 22, 20)) {
3573
if (status_change (td, buffer))
3574
memcpy (s, buffer + 22, 20);
3579
if (designation < 2) {
3585
if (!vbi3_decode_teletext_8301_cni (&cni, buffer))
3591
/* Should probably ignore this. */
3592
} else if (cni == cn->network.cni_8301) {
3593
/* No CNI change, no channel change. */
3595
cn->confirm_cni_8301 = 0;
3597
if (0 == cn->confirm_cni_vps
3598
&& 0 == cn->confirm_cni_8302) {
3599
/* All CNIs valid, cancel reset requests. */
3600
td->virtual_reset (td, NULL, -1.0);
3602
} else if (cni == cn->confirm_cni_8301) {
3603
/* The CNI is correct. */
3605
if (0 == cn->network.cni_8301) {
3606
/* First CNI, assume no channel change. */
3608
vbi3_network_set_cni
3609
(&cn->network, VBI3_CNI_TYPE_8301, cni);
3611
cn->confirm_cni_8301 = 0;
3613
if (0 == cn->confirm_cni_vps
3614
&& 0 == cn->confirm_cni_8302) {
3615
/* All CNIs valid, cancel reset
3617
td->virtual_reset (td, NULL, -1.0);
3623
/* Different CNI, channel change detected. */
3625
vbi3_network_init (&nk);
3626
vbi3_network_set_cni (&nk, VBI3_CNI_TYPE_8301,
3629
cn = _vbi3_cache_add_network
3630
(td->cache, &nk, td->videostd_set);
3632
td->virtual_reset (td, cn, 0.0 /* now */);
3634
cache_network_unref (cn);
3636
vbi3_network_destroy (&nk);
3641
/* The packet 8/30 format 1 CNI is poorly error
3642
protected. We accept this CNI after receiving it
3644
cn->confirm_cni_8301 = cni;
3646
if (0 == cn->network.cni_8301) {
3647
/* First CNI, channel change possible. */
3648
cni_change (td, VBI3_CNI_TYPE_8301, cni,
3649
td->cni_830_timeout);
3651
/* Assume a channel change with unknown CNI
3652
if we cannot confirm the new CNI or receive
3653
the old CNI again within n seconds. */
3654
td->virtual_reset (td, NULL, td->time
3655
+ td->cni_830_timeout);
3659
if (td->handlers.event_mask & VBI3_EVENT_LOCAL_TIME) {
3662
if (!vbi3_decode_teletext_8301_local_time
3663
(&e.ev.local_time.time,
3664
&e.ev.local_time.gmtoff,
3668
e.type = VBI3_EVENT_LOCAL_TIME;
3669
e.network = &td->network->network;
3670
e.timestamp = td->time;
3672
_vbi3_event_handler_list_send (&td->handlers, &e);
3680
if (!vbi3_decode_teletext_8302_cni (&cni, buffer))
3686
/* Should probably ignore this. */
3687
} else if (cni == cn->network.cni_8302) {
3688
/* No CNI change, no channel change. */
3690
cn->confirm_cni_8302 = 0; /* confirmed */
3692
if (0 == cn->confirm_cni_vps
3693
&& 0 == cn->confirm_cni_8301) {
3694
/* All CNIs valid, cancel reset requests. */
3695
td->virtual_reset (td, NULL, -1.0);
3698
if (0 == cn->network.cni_8302) {
3699
/* First CNI, channel change possible. */
3701
vbi3_network_set_cni
3702
(&cn->network, VBI3_CNI_TYPE_8302, cni);
3704
cn->confirm_cni_8302 = 0;
3706
cni_change (td, VBI3_CNI_TYPE_8302, cni, 0.0);
3708
if (0 == cn->confirm_cni_vps
3709
&& 0 == cn->confirm_cni_8301) {
3710
/* All CNIs valid, cancel reset
3712
td->virtual_reset (td, NULL, -1.0);
3718
/* Different CNI, channel change detected. */
3720
vbi3_network_init (&nk);
3721
vbi3_network_set_cni (&nk,
3722
VBI3_CNI_TYPE_8302, cni);
3724
cn = _vbi3_cache_add_network
3725
(td->cache, &nk, td->videostd_set);
3727
td->virtual_reset (td, cn, 0.0 /* now */);
3729
cache_network_unref (cn);
3731
vbi3_network_destroy (&nk);
3738
if (td->handlers.event_mask & VBI3_EVENT_PROG_ID) {
3739
vbi3_program_id pid;
3742
if (!vbi3_decode_teletext_8302_pdc (&pid, buffer))
3745
p = &td->network->program_id[pid.channel];
3747
if (p->cni != pid.cni
3748
|| p->pil != pid.pil
3749
|| ((p->luf ^ pid.luf) |
3752
|| p->pcs_audio != pid.pcs_audio
3753
|| p->pty != pid.pty) {
3758
e.type = VBI3_EVENT_PROG_ID;
3759
e.network = &td->network->network;
3760
e.timestamp = td->time;
3763
_vbi3_event_handler_list_send
3764
(&td->handlers, &e);
3767
#endif /* !ZAPPING8 */
3774
* @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
3775
* @param buffer Teletext packet as defined for @c VBI3_SLICED_TELETEXT_B,
3776
* i.e. 42 bytes without clock run-in and framing code.
3777
* @param timestamp System time in seconds when the Teletext packet
3780
* Decodes a teletext packet and update the decoder state.
3783
* @c FALSE if the packet contained incorrectable errors.
3786
vbi3_teletext_decoder_decode (vbi3_teletext_decoder * td,
3787
const uint8_t buffer[42],
3795
td->time = timestamp;
3797
if (td->reset_time > 0
3798
&& timestamp >= td->reset_time) {
3802
/* Deferred reset. */
3804
cn = _vbi3_cache_add_network
3805
(td->cache, NULL, td->videostd_set);
3807
td->virtual_reset (td, cn, 0.0 /* now */);
3808
cache_network_unref (cn);
3813
if ((pmag = vbi3_unham16p (buffer)) < 0)
3819
cp = &td->buffer[mag0];
3824
fprintf (stderr, "packet %xxx %d >",
3825
(0 == mag0) ? 8 : mag0, packet);
3827
for (i = 0; i < 40; i++)
3828
fputc (vbi3_printable (buffer[2 + i]), stderr);
3830
fprintf (stderr, "<\n");
3834
&& 0 == (td->handlers.event_mask
3835
& (VBI3_EVENT_TTX_PAGE |
3836
VBI3_EVENT_TRIGGER |
3837
VBI3_EVENT_PAGE_TYPE |
3838
VBI3_EVENT_TOP_CHANGE)))
3844
return decode_packet_0 (td, cp, buffer, (unsigned int) mag0);
3848
switch (cp->function) {
3849
case PAGE_FUNCTION_DISCARD:
3852
case PAGE_FUNCTION_GPOP:
3853
case PAGE_FUNCTION_POP:
3854
if (!decode_pop_packet (cp, buffer + 2,
3855
(unsigned int) packet))
3859
case PAGE_FUNCTION_GDRCS:
3860
case PAGE_FUNCTION_DRCS:
3861
memcpy (cp->data.drcs.lop.raw[packet],
3865
case PAGE_FUNCTION_AIT:
3866
if (!(decode_ait_packet (cp, buffer + 2,
3867
(unsigned int) packet)))
3871
case PAGE_FUNCTION_EPG:
3875
case PAGE_FUNCTION_LOP:
3876
case PAGE_FUNCTION_TRIGGER:
3883
for (i = 0; i < 40; ++i)
3884
err |= vbi3_unpar8 (buffer[2 + i]);
3889
memcpy (cp->data.unknown.raw[packet], buffer + 2, 40);
3894
case PAGE_FUNCTION_MOT:
3895
case PAGE_FUNCTION_MIP:
3896
case PAGE_FUNCTION_BTT:
3897
case PAGE_FUNCTION_MPT:
3898
case PAGE_FUNCTION_MPT_EX:
3900
memcpy (cp->data.unknown.raw[packet], buffer + 2, 40);
3904
cp->lop_packets |= 1 << packet;
3909
/* Page enhancement packet. */
3910
return decode_packet_26 (td, cp, buffer);
3914
return decode_packet_27 (td, cp, buffer);
3918
/* Level 2.5/3.5 enhancement. */
3919
return decode_packet_28_29 (td, cp, buffer,
3920
(unsigned int) packet);
3925
unsigned int channel;
3927
/* IDL packet (ETS 300 708). */
3929
channel = pmag & 15;
3933
return decode_packet_8_30 (td, buffer);
3935
/* 1 ... 3 = Packet 1/30 ... 3/30 */
3936
/* 4 = Low bit rate audio */
3937
/* 5 ... 6 = Datavideo */
3938
/* 7 = Packet 7/30 */
3939
/* 8 ... 11 = IDL Format A (Packet 8/31, 1/31 ... 3/31) */
3940
/* 12 = Low bit rate audio */
3941
/* 13 ... 14 = Datavideo */
3942
/* 15 = Packet 7/31 */
3945
log ("IDL %u\n", channel);
3953
assert (!"reached");
3963
vbi3_teletext_decoder_search_utf8_new
3964
(vbi3_teletext_decoder *td,
3965
const vbi3_network * nk,
3968
const char * pattern,
3971
vbi3_search_progress_cb *progress,
3974
assert (NULL != td);
3980
nk = &td->network->network;
3984
return vbi3_search_utf8_new (td->cache,
3988
progress, user_data);
3995
vbi3_teletext_decoder_get_top_title
3996
(vbi3_teletext_decoder * td,
3997
vbi3_top_title * tt,
3998
const vbi3_network * nk,
4005
assert (NULL != td);
4006
assert (NULL != tt);
4009
if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
4012
/* Current network. */
4016
r = cache_network_get_top_title (cn, tt, pgno, subno);
4019
cache_network_unref (cn);
4028
vbi3_teletext_decoder_get_top_titles
4029
(vbi3_teletext_decoder * td,
4030
const vbi3_network * nk,
4031
unsigned int * n_elements)
4036
assert (NULL != td);
4037
assert (NULL != n_elements);
4042
if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
4045
/* Current network. */
4049
tt = cache_network_get_top_titles (cn, n_elements);
4052
cache_network_unref (cn);
4061
vbi3_teletext_decoder_get_ttx_page_stat
4062
(vbi3_teletext_decoder * td,
4063
vbi3_ttx_page_stat * ps,
4064
const vbi3_network * nk,
4069
assert (NULL != td);
4070
assert (NULL != ps);
4072
if (pgno < 0x100 || pgno > 0x8FF)
4076
if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
4079
/* Current network. */
4083
cache_network_get_ttx_page_stat (cn, ps, pgno);
4086
cache_network_unref (cn);
4095
vbi3_teletext_decoder_get_page_va_list
4096
(vbi3_teletext_decoder * td,
4097
const vbi3_network * nk,
4100
va_list format_options)
4104
vbi3_subno subno_mask;
4107
assert (NULL != td);
4114
/* Current network. */
4118
if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
4124
if (VBI3_ANY_SUBNO == subno) {
4129
if (!(cp = _vbi3_cache_get_page (td->cache, cn, pgno,
4130
subno, subno_mask)))
4133
if (!(pg = vbi3_page_new ()))
4136
if (!_vbi3_page_priv_from_cache_page_va_list
4137
(pg->priv, cp, format_options)) {
4138
vbi3_page_delete (pg);
4143
cache_page_unref (cp);
4146
cache_network_unref (cn);
4155
vbi3_teletext_decoder_get_page (vbi3_teletext_decoder * td,
4156
const vbi3_network * nk,
4162
va_list format_options;
4164
va_start (format_options, subno);
4166
pg = vbi3_teletext_decoder_get_page_va_list
4167
(td, nk, pgno, subno, format_options);
4169
va_end (format_options);
4175
* @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
4176
* @param pid Program ID will be stored here.
4177
* @param channel Logical channel transmitting the ID, @c
4178
* VBI3_PID_CHANNEL_LCI_0 ... @c VBI3_PID_CHANNEL_LCI_3.
4180
* Returns the most recently on a logical channel received program ID.
4183
vbi3_teletext_decoder_get_program_id
4184
(vbi3_teletext_decoder * td,
4185
vbi3_program_id * pid,
4186
vbi3_pid_channel channel)
4191
assert (NULL != td);
4192
assert (NULL != pid);
4194
assert ((unsigned int) channel <= VBI3_PID_CHANNEL_LCI_3);
4196
*pid = td->network->program_id[channel];
4202
* @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
4204
* To be called after frame dropping, when Teletext packets might have
4205
* been lost. After a channel change call vbi3_teletext_decoder_reset()
4209
_vbi3_teletext_decoder_resync (vbi3_teletext_decoder * td)
4213
/* Discard all in progress pages. */
4215
for (i = 0; i < N_ELEMENTS (td->buffer); ++i)
4216
td->buffer[i].function = PAGE_FUNCTION_DISCARD;
4221
vbi3_pfc_demux_reset (&td->epg_stream[0]);
4222
vbi3_pfc_demux_reset (&td->epg_stream[1]);
4228
cache_network_dump_teletext (const cache_network * cn,
4234
pagenum_dump (&cn->initial_page, fp);
4236
for (i = 0; i < N_ELEMENTS (cn->btt_link); ++i) {
4237
fprintf (fp, "\nbtt_link[%u]=", i);
4238
pagenum_dump (cn->btt_link + i, fp);
4241
fputs ("\nstatus=\"", fp);
4243
for (i = 0; i < N_ELEMENTS (cn->status); ++i)
4244
fputc (vbi3_printable (cn->status[i]), fp);
4246
fputs ("\"\npage_stat=\n", fp);
4248
for (pgno = 0x100; pgno < 0x8FF; pgno += 8) {
4251
for (unit = 0; unit < 8; ++unit) {
4252
const page_stat *ps;
4254
ps = cache_network_const_page_stat (cn, pgno + unit);
4256
fprintf (fp, "%02x:%02x:%04x:%2u/%2u:%02x-%02x ",
4257
ps->page_type, ps->charset_code, ps->subcode,
4258
ps->n_subpages, ps->max_subpages,
4259
ps->subno_min, ps->subno_max);
4269
extension_init (extension * ext)
4275
ext->def_screen_color = VBI3_BLACK; /* A.5 */
4276
ext->def_row_color = VBI3_BLACK; /* A.5 */
4278
for (i = 0; i < 8; ++i)
4279
ext->drcs_clut[2 + i] = i & 3;
4281
for (i = 0; i < 32; ++i)
4282
ext->drcs_clut[2 + 8 + i] = i & 15;
4284
memcpy (ext->color_map, default_color_map,
4285
sizeof (ext->color_map));
4289
magazine_init (magazine * mag)
4291
extension_init (&mag->extension);
4293
/* Valid range 0 ... 7. */
4294
memset (mag->pop_lut, -1, sizeof (mag->pop_lut));
4295
memset (mag->drcs_lut, -1, sizeof (mag->pop_lut));
4297
/* NO_PAGE (pgno): (pgno & 0xFF) == 0xFF. */
4298
memset (mag->pop_link, -1, sizeof (mag->pop_link));
4299
memset (mag->drcs_link, -1, sizeof (mag->drcs_link));
4305
* Provides default magazine parameters to be used at Level 1 and 1.5.
4306
* Remember editors can redefine cache_network_magazine() at Level 2.5
4310
_vbi3_teletext_decoder_default_magazine
4313
static magazine default_magazine;
4315
if (!NO_PAGE (default_magazine.pop_link[0][0].pgno))
4316
magazine_init (&default_magazine);
4318
return &default_magazine;
4322
page_stat_init (page_stat * ps)
4326
ps->page_type = VBI3_UNKNOWN_PAGE;
4327
ps->charset_code = 0xFF;
4328
ps->subcode = SUBCODE_UNKNOWN;
4333
cache_network_destroy_teletext (cache_network * cn)
4340
* @param cn cache_network structure to be initialized.
4342
* Initializes the Teletext fields of a cache_network structure.
4345
cache_network_init_teletext (cache_network * cn)
4349
/* D.3: In absence of packet 8/30/0 ... 4 assume page 100. */
4350
cn->initial_page.function = PAGE_FUNCTION_LOP;
4351
cn->initial_page.pgno = 0x100;
4352
cn->initial_page.subno = VBI3_ANY_SUBNO;
4354
for (i = 0; i < N_ELEMENTS (cn->_magazines); ++i)
4355
magazine_init (&cn->_magazines[i]);
4357
for (i = 0; i < N_ELEMENTS (cn->_pages); ++i)
4358
page_stat_init (&cn->_pages[i]);
4360
/* NO_PAGE (pgno): (pgno & 0xFF) == 0xFF. */
4361
memset (cn->btt_link, -1, sizeof (cn->btt_link));
4365
cn->have_top = FALSE;
4368
/* Internal reset function, called by td->virtual_reset(). */
4370
reset (vbi3_teletext_decoder * td,
4376
assert (NULL != td);
4379
fprintf (stderr, "reset %f: %f -> %f\n",
4380
td->time, td->reset_time, time);
4382
if (time <= 0.0 || time > td->reset_time)
4383
td->reset_time = time;
4388
assert (NULL != cn);
4390
cache_network_unref (td->network);
4391
td->network = cache_network_ref (cn);
4394
td->epg_stream[0].block.pgno = 0;
4395
td->epg_stream[1].block.pgno = 0;
4398
td->header_page.pgno = 0;
4401
_vbi3_teletext_decoder_resync (td);
4403
e.type = VBI3_EVENT_RESET;
4404
e.network = &td->network->network;
4405
e.timestamp = td->time;
4407
_vbi3_event_handler_list_send (&td->handlers, &e);
4411
* @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
4412
* @param callback Function to be called on events.
4413
* @param user_data User pointer passed through to the @a callback function.
4415
* Removes an event handler from the Teletext decoder, if a handler with
4416
* this @a callback and @a user_data has been registered. You can
4417
* safely call this function from a handler removing itself or another
4421
vbi3_teletext_decoder_remove_event_handler
4422
(vbi3_teletext_decoder * td,
4423
vbi3_event_cb * callback,
4426
vbi3_cache_remove_event_handler (td->cache,
4430
_vbi3_event_handler_list_remove_by_callback (&td->handlers,
4436
* @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
4437
* @param event_mask Set of events (@c VBI3_EVENT_) the handler is waiting
4438
* for, can be -1 for all and 0 for none.
4439
* @param callback Function to be called on events by
4440
* vbi3_teletext_decoder_decode() and other vbi3_teletext functions as noted.
4441
* @param user_data User pointer passed through to the @a callback function.
4443
* Adds a new event handler to the Teletext decoder. When the @a callback
4444
* with @a user_data is already registered the function merely changes the
4445
* set of events it will receive in the future. When the @a event_mask is
4446
* empty the function does nothing or removes an already registered event
4447
* handler. You can safely call this function from an event handler.
4449
* Any number of handlers can be added, also different handlers for the
4450
* same event which will be called in registration order.
4453
* @c FALSE of failure (out of memory).
4456
vbi3_teletext_decoder_add_event_handler
4457
(vbi3_teletext_decoder * td,
4458
unsigned int event_mask,
4459
vbi3_event_cb * callback,
4462
unsigned int ttx_mask;
4463
unsigned int add_mask;
4464
unsigned int rem_mask;
4466
if (!vbi3_cache_add_event_handler (td->cache,
4472
ttx_mask = event_mask & (VBI3_EVENT_CLOSE |
4474
VBI3_EVENT_TTX_PAGE |
4475
VBI3_EVENT_NETWORK |
4476
VBI3_EVENT_TRIGGER |
4477
VBI3_EVENT_PROG_INFO |
4478
VBI3_EVENT_PAGE_TYPE |
4479
VBI3_EVENT_TOP_CHANGE |
4480
VBI3_EVENT_LOCAL_TIME |
4481
VBI3_EVENT_PROG_ID);
4483
add_mask = ttx_mask & ~td->handlers.event_mask;
4484
rem_mask = td->handlers.event_mask & ~event_mask;
4486
if (rem_mask & VBI3_EVENT_TRIGGER) {
4488
/* Don't fire old triggers. */
4489
_vbi3_trigger_list_delete (&td->triggers);
4493
if (0 == ttx_mask) {
4497
if (NULL != _vbi3_event_handler_list_add (&td->handlers,
4501
if (add_mask & (VBI3_EVENT_TTX_PAGE |
4502
VBI3_EVENT_TRIGGER)) {
4503
_vbi3_teletext_decoder_resync (td);
4508
vbi3_cache_remove_event_handler (td->cache,
4520
vbi3_teletext_decoder_get_network
4521
(vbi3_teletext_decoder *td,
4524
assert (NULL != td);
4525
assert (NULL != nk);
4530
return vbi3_network_copy (nk, &td->network->network);
4537
vbi3_teletext_decoder_get_cache (vbi3_teletext_decoder *td)
4539
assert (NULL != td);
4544
return vbi3_cache_ref (td->cache);
4548
* @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
4549
* @param nk Identifies the new network, can be @c NULL.
4551
* Resets the Teletext decoder, useful for example after a channel change.
4552
* This function sends a @c VBI3_EVENT_RESET.
4554
* You can pass a vbi3_network structure to identify the new network in
4555
* advance, before the decoder receives an ID if ever.
4558
vbi3_teletext_decoder_reset (vbi3_teletext_decoder * td,
4559
const vbi3_network * nk,
4560
vbi3_videostd_set videostd_set)
4564
assert (NULL != td);
4566
td->videostd_set = videostd_set;
4568
cn = _vbi3_cache_add_network (td->cache, nk, videostd_set);
4569
td->virtual_reset (td, cn, 0.0 /* now */);
4570
cache_network_unref (cn);
4575
* @param td Teletext decoder to be destroyed.
4577
* Frees all resources associated with @a td, except the structure itself.
4578
* This function sends a @c VBI3_EVENT_CLOSE.
4581
_vbi3_teletext_decoder_destroy (vbi3_teletext_decoder * td)
4585
assert (NULL != td);
4587
e.type = VBI3_EVENT_CLOSE;
4588
e.network = &td->network->network;
4589
e.timestamp = td->time;
4591
_vbi3_event_handler_list_send (&td->handlers, &e);
4593
_vbi3_event_handler_list_destroy (&td->handlers);
4596
_vbi3_trigger_list_delete (&td->triggers);
4599
cache_network_unref (td->network);
4601
/* Delete if we hold the last reference. */
4602
vbi3_cache_unref (td->cache);
4609
* @param td Teletext decoder to be initialized.
4610
* @param ca Cache to be used by this Teletext decoder, can be @c NULL.
4611
* To allocate a cache call vbi3_cache_new(). Caches have a reference
4612
* counter, you can vbi3_cache_unref() after calling this function.
4613
* @param nk Initial network (see vbi3_teletext_decoder_reset()),
4616
* Initializes a Teletext decoder structure.
4619
* @c FALSE on failure (out of memory).
4622
_vbi3_teletext_decoder_init (vbi3_teletext_decoder * td,
4624
const vbi3_network * nk,
4625
vbi3_videostd_set videostd_set)
4629
assert (NULL != td);
4634
td->cache = vbi3_cache_ref (ca);
4636
td->cache = vbi3_cache_new ();
4641
td->virtual_reset = reset;
4643
td->cni_830_timeout = 2.5; /* sec */
4644
td->cni_vps_timeout = 5 / 25.0; /* sec */
4646
_vbi3_event_handler_list_init (&td->handlers);
4648
td->videostd_set = videostd_set;
4650
cn = _vbi3_cache_add_network (td->cache, nk, videostd_set);
4651
reset (td, cn, 0.0 /* now */);
4652
cache_network_unref (cn);
4658
* @param td Teletext decoder allocated with vbi3_teletext_decoder_new(),
4661
* Frees all resources associated with @a td.
4662
* This function sends a @c VBI3_EVENT_CLOSE.
4665
vbi3_teletext_decoder_delete (vbi3_teletext_decoder * td)
4670
_vbi3_teletext_decoder_destroy (td);
4676
* @param ca Cache to be used by this Teletext decoder, can be @c NULL.
4677
* To allocate a cache call vbi3_cache_new(). Caches have a reference
4678
* counter, you can vbi3_cache_unref() after calling this function.
4680
* Allocates a new Teletext (ETS 300 706) decoder. Decoded data is
4681
* available through the following functions:
4682
* - vbi3_teletext_decoder_get_page()
4683
* - vbi3_teletext_decoder_get_program_id()
4685
* To be notified when new data is available call
4686
* vbi3_teletext_decoder_add_event_handler().
4689
* Pointer to newly allocated Teletext decoder which must be
4690
* freed with vbi3_teletext_decoder_delete() when done.
4691
* @c NULL on failure (out of memory).
4693
vbi3_teletext_decoder *
4694
vbi3_teletext_decoder_new (vbi3_cache * ca,
4695
const vbi3_network * nk,
4696
vbi3_videostd_set videostd_set)
4698
vbi3_teletext_decoder *td;
4700
if (!(td = vbi3_malloc (sizeof (*td)))) {
4701
vbi3_log_printf (VBI3_DEBUG, __FUNCTION__,
4702
"Out of memory (%u)", sizeof (*td));
4706
if (!_vbi3_teletext_decoder_init (td, ca, nk, videostd_set)) {