~ubuntu-branches/ubuntu/maverick/zapping/maverick

« back to all changes in this revision

Viewing changes to libvbi/teletext_decoder.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-03-08 23:19:08 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050308231908-oip7rfv6lcmo8c0e
Tags: 0.9.2-2ubuntu1
Rebuilt for Python transition (2.3 -> 2.4)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  libzvbi - Teletext decoder
 
3
 *
 
4
 *  Copyright (C) 2000, 2001, 2002, 2003, 2004 Michael H. Schimek
 
5
 *
 
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.
 
9
 *
 
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.
 
14
 *
 
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.
 
18
 */
 
19
 
 
20
/* $Id: teletext_decoder.c,v 1.8 2005/01/31 07:09:21 mschimek Exp $ */
 
21
 
 
22
#include "../site_def.h"
 
23
 
 
24
#include <stdlib.h>             /* malloc() */
 
25
#include <assert.h>
 
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"
 
31
 
 
32
/**
 
33
 * @addtogroup Teletext Teletext Decoder
 
34
 * @ingroup HiDec
 
35
 */
 
36
 
 
37
#ifndef TELETEXT_DECODER_CHSW_TEST
 
38
#  define TELETEXT_DECODER_CHSW_TEST 0
 
39
#endif
 
40
 
 
41
#ifndef TELETEXT_DECODER_LOG
 
42
#  define TELETEXT_DECODER_LOG 0
 
43
#endif
 
44
 
 
45
#define log(templ, args...)                                             \
 
46
do {                                                                    \
 
47
        if (TELETEXT_DECODER_LOG)                                       \
 
48
                fprintf (stderr, templ , ##args);                       \
 
49
} while (0)
 
50
 
 
51
#define MAG8(mag0) ((mag0) ? (mag0) : 8)
 
52
 
 
53
/* ETS 300 706 Table 30 Colour Map */
 
54
 
 
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),
 
73
 
 
74
        /* Private colors */
 
75
 
 
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)
 
80
};
 
81
 
 
82
/** @internal */
 
83
const char *
 
84
page_function_name              (page_function          function)
 
85
{
 
86
        switch (function) {
 
87
 
 
88
#undef CASE
 
89
#define CASE(function) case PAGE_FUNCTION_##function : return #function ;
 
90
 
 
91
        CASE (ACI)
 
92
        CASE (EPG)
 
93
        CASE (DISCARD)
 
94
        CASE (UNKNOWN)
 
95
        CASE (LOP)
 
96
        CASE (DATA)
 
97
        CASE (GPOP)
 
98
        CASE (POP)
 
99
        CASE (GDRCS)
 
100
        CASE (DRCS)
 
101
        CASE (MOT)
 
102
        CASE (MIP)
 
103
        CASE (BTT)
 
104
        CASE (AIT)
 
105
        CASE (MPT)
 
106
        CASE (MPT_EX)
 
107
        CASE (TRIGGER)
 
108
 
 
109
        }
 
110
 
 
111
        return NULL;
 
112
}
 
113
 
 
114
/** @internal */
 
115
const char *
 
116
page_coding_name                (page_coding            coding)
 
117
{
 
118
        switch (coding) {
 
119
 
 
120
#undef CASE
 
121
#define CASE(coding) case PAGE_CODING_##coding : return #coding ;
 
122
 
 
123
        CASE (UNKNOWN)
 
124
        CASE (ODD_PARITY)
 
125
        CASE (UBYTES)
 
126
        CASE (TRIPLETS)
 
127
        CASE (HAMMING84)
 
128
        CASE (AIT)
 
129
        CASE (META84)
 
130
 
 
131
        }
 
132
 
 
133
        return NULL;
 
134
}
 
135
 
 
136
/** @internal */
 
137
const char *
 
138
object_type_name                (object_type            type)
 
139
{
 
140
        switch (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";
 
145
        }
 
146
 
 
147
        return NULL;
 
148
}
 
149
 
 
150
/** @internal */
 
151
const char *
 
152
drcs_mode_name                  (drcs_mode              mode)
 
153
{
 
154
        switch (mode) {
 
155
 
 
156
#undef CASE
 
157
#define CASE(mode) case DRCS_MODE_##mode : return #mode ;
 
158
 
 
159
        CASE (12_10_1)
 
160
        CASE (12_10_2)
 
161
        CASE (12_10_4)
 
162
        CASE (6_5_4)
 
163
        CASE (SUBSEQUENT_PTU)
 
164
        CASE (NO_DATA)
 
165
 
 
166
        }
 
167
 
 
168
        return NULL;
 
169
}
 
170
 
 
171
/**
 
172
 * @param type Teletext page type.
 
173
 *
 
174
 * Returns the name of a Teletext page type, for example VBI3_SUBTITLE_PAGE ->
 
175
 * "SUBTITLE_PAGE". This is mainly intended for debugging.
 
176
 * 
 
177
 * @returns
 
178
 * Static ASCII string, NULL if @a type is invalid.
 
179
 */
 
180
const char *
 
181
vbi3_ttx_page_type_name         (vbi3_ttx_page_type     type)
 
182
{
 
183
        switch (type) {
 
184
 
 
185
#undef CASE
 
186
#define CASE(type) case VBI3_##type : return #type ;
 
187
 
 
188
        CASE (NO_PAGE)
 
189
        CASE (NORMAL_PAGE)
 
190
        CASE (SUBTITLE_PAGE)
 
191
        CASE (SUBTITLE_INDEX)
 
192
        CASE (NONSTD_SUBPAGES)
 
193
        CASE (PROGR_WARNING)
 
194
        CASE (CURRENT_PROGR)
 
195
        CASE (NOW_AND_NEXT)
 
196
        CASE (PROGR_INDEX)
 
197
        CASE (PROGR_SCHEDULE)
 
198
        CASE (UNKNOWN_PAGE)
 
199
        CASE (NOT_PUBLIC)
 
200
        CASE (CA_DATA)
 
201
        CASE (PFC_EPG_DATA)
 
202
        CASE (PFC_DATA)
 
203
        CASE (DRCS_PAGE)
 
204
        CASE (POP_PAGE)
 
205
        CASE (SYSTEM_PAGE)
 
206
        CASE (KEYWORD_SEARCH_LIST)
 
207
        CASE (TOP_BLOCK)
 
208
        CASE (TOP_GROUP)
 
209
        CASE (NEWSFLASH_PAGE)
 
210
        CASE (TRIGGER_DATA)
 
211
        CASE (ACI_PAGE)
 
212
        CASE (TOP_PAGE)
 
213
 
 
214
        }
 
215
 
 
216
        return NULL;
 
217
}
 
218
 
 
219
/** @internal */
 
220
void
 
221
pagenum_dump                    (const pagenum *        pn,
 
222
                                 FILE *                 fp)
 
223
{
 
224
        fprintf (fp, "%s %3x.%04x",
 
225
                 page_function_name (pn->function),
 
226
                 pn->pgno, pn->subno);
 
227
}
 
228
 
 
229
static void
 
230
cache_page_raw_dump             (const cache_page *     cp,
 
231
                                 FILE *                 fp,
 
232
                                 page_coding            coding)
 
233
{
 
234
        unsigned int i;
 
235
        unsigned int j;
 
236
 
 
237
        fprintf (fp, "Page %03x.%04x\n", cp->pgno, cp->subno);
 
238
 
 
239
        for (j = 0; j < 25; ++j) {
 
240
                switch (coding) {
 
241
                case PAGE_CODING_TRIPLETS:
 
242
                        for (i = 0; i < 13; ++i) {
 
243
                                const uint8_t *p;
 
244
 
 
245
                                p = &cp->data.lop.raw[j][1 + i * 3];
 
246
                                fprintf (fp, "%05x ", vbi3_unham24p (p));
 
247
                        }
 
248
 
 
249
                        break;
 
250
 
 
251
                case PAGE_CODING_HAMMING84:
 
252
                        for (i = 0; i < 40; ++i) {
 
253
                                unsigned int c;
 
254
 
 
255
                                c = cp->data.lop.raw[j][i];
 
256
                                fprintf (fp, "%x", vbi3_unham8 (c));
 
257
                        }
 
258
 
 
259
                        break;
 
260
 
 
261
                default:
 
262
                        for (i = 0; i < 40; ++i) {
 
263
                                unsigned int c;
 
264
 
 
265
                                c = cp->data.lop.raw[j][i];
 
266
                                fprintf (fp, "%02x ", c);
 
267
                        }
 
268
 
 
269
                        break;
 
270
                }
 
271
 
 
272
                for (i = 0; i < 40; ++i)
 
273
                        fputc (vbi3_printable (cp->data.lop.raw[j][i]), fp);
 
274
 
 
275
                fputc ('\n', fp);
 
276
        }
 
277
}
 
278
 
 
279
/** @internal */
 
280
void
 
281
extension_dump                  (const extension *      ext,
 
282
                                 FILE *                 fp)
 
283
{
 
284
        unsigned int i;
 
285
 
 
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=",
 
291
                 ext->designations,
 
292
                 ext->charset_code[0],
 
293
                 ext->charset_code[1],
 
294
                 ext->def_screen_color,
 
295
                 ext->def_row_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);
 
301
 
 
302
        for (i = 0; i < 4; ++i)
 
303
                fprintf (fp, "%u, ", ext->drcs_clut[i + 2]);
 
304
 
 
305
        fputs ("\n  12x10x2 dclut=", fp);
 
306
 
 
307
        for (i = 0; i < 4; ++i)
 
308
                fprintf (fp, "%u, ", ext->drcs_clut[i + 6]);
 
309
 
 
310
        fputs ("\n  12x10x4 global dclut=", fp);
 
311
 
 
312
        for (i = 0; i < 16; ++i)
 
313
                fprintf (fp, "%u, ", ext->drcs_clut[i + 10]);
 
314
 
 
315
        fputs ("\n  12x10x4 dclut=", fp);
 
316
 
 
317
        for (i = 0; i < 16; ++i)
 
318
                fprintf (fp, "%u, ", ext->drcs_clut[i + 26]);
 
319
 
 
320
        fputs ("\n  color_map=\n", fp);
 
321
 
 
322
        for (i = 0; i < 40; ++i) {
 
323
                fprintf (fp, "%08x, ", ext->color_map[i]);
 
324
 
 
325
                if ((i % 8) == 7)
 
326
                        fputc ('\n', fp);
 
327
        }
 
328
 
 
329
        fputc ('\n', fp);
 
330
}
 
331
 
 
332
static vbi3_bool
 
333
unham8_page_number              (pagenum *              pn,
 
334
                                 const uint8_t          buffer[6],
 
335
                                 unsigned int           mag0)
 
336
{
 
337
        int b1, b2, b3;
 
338
 
 
339
        b1 = vbi3_unham16p (buffer + 0);
 
340
        b2 = vbi3_unham16p (buffer + 2);
 
341
        b3 = vbi3_unham16p (buffer + 4);
 
342
 
 
343
        if ((b1 | b2 | b3) < 0)
 
344
                return FALSE;
 
345
 
 
346
        mag0 ^= ((b3 >> 5) & 6) + (b2 >> 7);
 
347
 
 
348
        pn->function    = PAGE_FUNCTION_UNKNOWN;
 
349
        pn->pgno        = MAG8 (mag0) * 256 + b1;
 
350
        pn->subno       = (b3 * 256 + b2) & 0x3F7F;
 
351
 
 
352
        /* subno flags? */
 
353
 
 
354
        return TRUE;
 
355
}
 
356
 
 
357
static void
 
358
clear_lop                       (cache_page *           cp)
 
359
{
 
360
        memset (cp->data.lop.raw, 0x20, sizeof (cp->data.lop.raw));
 
361
 
 
362
        /* NO_PAGE (pgno): (pgno & 0xFF) == 0xFF. */
 
363
        memset (cp->data.lop.link, -1, sizeof (cp->data.lop.link));
 
364
 
 
365
        cp->data.lop.have_flof = FALSE;
 
366
}
 
367
 
 
368
static void
 
369
clear_enhancement               (cache_page *           cp)
 
370
{
 
371
        /* Valid range of mode 0x00 ... 0x1F, broken -1. */
 
372
        memset (cp->data.enh_lop.enh, -1, sizeof (cp->data.enh_lop.enh));
 
373
}
 
374
 
 
375
/*
 
376
        10.5 (Global) Public Object Page
 
377
*/
 
378
 
 
379
static void
 
380
clear_pop_page                  (cache_page *           cp)
 
381
{
 
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));
 
385
 
 
386
        /* Valid range of mode 0x00 ... 0x1F, broken -1. */
 
387
        memset (cp->data.pop.triplet, -1, sizeof (cp->data.pop.triplet));
 
388
}
 
389
 
 
390
static vbi3_bool
 
391
decode_pop_packet               (cache_page *           cp,
 
392
                                 const uint8_t          buffer[40],
 
393
                                 unsigned int           packet)
 
394
{
 
395
        int n18[13];
 
396
        int designation;
 
397
        int err;
 
398
        unsigned int i;
 
399
 
 
400
        designation = vbi3_unham8 (buffer[0]);
 
401
 
 
402
        err = 0;
 
403
 
 
404
        for (i = 0; i < 13; ++i)
 
405
                err |= n18[i] = vbi3_unham24p (buffer + 1 + i * 3);
 
406
 
 
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);
 
410
 
 
411
                for (i = 1; i < 13; ++i)
 
412
                        log ("... %u: %d %x %u %u\n",
 
413
                             i, n18[i], n18[i],
 
414
                             n18[i] & 0x1FF, (n18[i] >> 9) & 0x1FF);
 
415
        }
 
416
 
 
417
        if ((designation | err) < 0) {
 
418
                return FALSE;
 
419
        }
 
420
 
 
421
        if (26 == packet)
 
422
                packet += designation;
 
423
 
 
424
        switch (packet) {
 
425
        case 1 ... 2:
 
426
                /* 10.5.1.2: Must be pointer table. */
 
427
                if (0 && !(designation & 1)) {
 
428
                        return FALSE;
 
429
                }
 
430
 
 
431
                /* fall through */
 
432
 
 
433
        case 3 ... 4:
 
434
                if (designation & 1) {
 
435
                        unsigned int index;
 
436
 
 
437
                        /* Pointer table. */
 
438
 
 
439
                        index = (packet - 1) * 12 * 2;
 
440
 
 
441
                        /* 10.5.1.2: triplet[0] is reserved. */
 
442
                        for (i = 1; i < 13; ++i) {
 
443
                                cp->data.pop.pointer[index + 0] =
 
444
                                        n18[i] & 0x1FF;
 
445
                                cp->data.pop.pointer[index + 1] =
 
446
                                        n18[i] >> 9;
 
447
 
 
448
                                log ("PT %2u %2u (%2u): %3u %3u\n",
 
449
                                     packet, i, index,
 
450
                                     n18[i] & 0x1FF,
 
451
                                     n18[i] >> 9);
 
452
                                
 
453
                                index += 2;
 
454
                        }
 
455
 
 
456
                        return TRUE;
 
457
                }
 
458
 
 
459
                /* fall through */
 
460
 
 
461
        case 5 ... 42:
 
462
        {
 
463
                triplet *trip;
 
464
 
 
465
                trip = &cp->data.pop.triplet[(packet - 3) * 13];
 
466
 
 
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);
 
471
                        
 
472
                        ++trip;
 
473
                }
 
474
 
 
475
                return TRUE;
 
476
        }
 
477
 
 
478
        default:
 
479
                assert (!"reached");
 
480
        }
 
481
 
 
482
        return FALSE;
 
483
}
 
484
 
 
485
static vbi3_bool
 
486
convert_pop_page                (cache_page *           dst,
 
487
                                 const cache_page *     src,
 
488
                                 page_function          function)
 
489
{
 
490
        unsigned int packet;
 
491
        const uint8_t *raw;
 
492
 
 
493
        assert (dst != src);
 
494
 
 
495
        clear_pop_page (dst);
 
496
 
 
497
        dst->function = function;
 
498
 
 
499
        raw = src->data.unknown.raw[1];
 
500
 
 
501
        for (packet = 1; packet <= 25; ++packet) {
 
502
                if (src->lop_packets & (1 << packet))
 
503
                        if (!decode_pop_packet (dst, raw, packet))
 
504
                                return FALSE;
 
505
 
 
506
                raw += 40;
 
507
        }
 
508
 
 
509
        assert ((39 * 13 + 1) == N_ELEMENTS (dst->data.pop.triplet));
 
510
        assert ((16 * 13 + 1) == N_ELEMENTS (src->data.enh_lop.enh));
 
511
 
 
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));
 
516
 
 
517
        return TRUE;
 
518
}
 
519
 
 
520
/*
 
521
        10.6 Magazine Organization Table
 
522
 */
 
523
 
 
524
static void
 
525
decode_mot_page_lut             (magazine *             mag,
 
526
                                 const uint8_t          buffer[2],
 
527
                                 vbi3_pgno              pgno)
 
528
{
 
529
        int n0, n1;
 
530
 
 
531
        n0 = vbi3_unham8 (buffer[0]);
 
532
        n1 = vbi3_unham8 (buffer[1]);
 
533
 
 
534
        if ((n0 | n1) < 0)
 
535
                return;
 
536
 
 
537
        /* n0 & 8 "global objects required" ignored. */
 
538
        /* n1 & 8 "global drcs required" ignored. */
 
539
 
 
540
        mag->pop_lut[pgno] = n0 & 7;
 
541
        mag->drcs_lut[pgno] = n1 & 7;
 
542
}
 
543
 
 
544
static void
 
545
decode_mot_page_pop             (vbi3_teletext_decoder *        td,
 
546
                                 pop_link               pop[4],
 
547
                                 const uint8_t          buffer[40])
 
548
{
 
549
        unsigned int i;
 
550
 
 
551
        for (i = 0; i < 4; ++i) {
 
552
                int n4[10];
 
553
                int err;
 
554
                unsigned int j;
 
555
                page_stat *ps;
 
556
 
 
557
                err = 0;
 
558
 
 
559
                for (j = 0; j < 10; ++j)
 
560
                        err |= n4[j] = vbi3_unham8 (buffer[j]);
 
561
 
 
562
                if (err < 0)
 
563
                        continue;
 
564
 
 
565
                buffer += 10;
 
566
 
 
567
                /* n4[0] & 8 "link page number may be superseded
 
568
                   by X/27/4 or X/27/5 data" ignored. */
 
569
 
 
570
                pop->pgno = MAG8 (n4[0] & 7) * 256 + n4[1] * 16 + n4[2];
 
571
 
 
572
                ps = cache_network_page_stat (td->network, pop->pgno);
 
573
 
 
574
                ps->page_type = VBI3_SYSTEM_PAGE;
 
575
                ps->subcode = n4[3]; /* highest S1 transmitted */
 
576
 
 
577
                if (n4[4] & 1) {
 
578
                        /* No side-panels, no black background
 
579
                           colour substitution. */
 
580
                        CLEAR (pop->fallback);
 
581
                } else {
 
582
                        unsigned int s = (n4[4] >> 1) & 3;
 
583
 
 
584
                        pop->fallback.black_bg_substitution = n4[4] >> 3;
 
585
 
 
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];
 
589
                }
 
590
 
 
591
                pop->default_obj[0].type = (object_type)(n4[5] & 3);
 
592
                pop->default_obj[0].address = (n4[7] << 4) + n4[6];
 
593
 
 
594
                pop->default_obj[1].type = (object_type)(n4[5] >> 2);
 
595
                pop->default_obj[1].address = (n4[9] << 4) + n4[8];
 
596
 
 
597
                ++pop;
 
598
        }
 
599
}
 
600
 
 
601
static void
 
602
decode_mot_page_drcs            (vbi3_teletext_decoder *        td,
 
603
                                 vbi3_pgno              pgno[8],
 
604
                                 const uint8_t          buffer[40])
 
605
{
 
606
        unsigned int i;
 
607
 
 
608
        for (i = 0; i < 8; ++i) {
 
609
                int n4[4];
 
610
                int err;
 
611
                unsigned int j;
 
612
                page_stat *ps;
 
613
 
 
614
                err = 0;
 
615
 
 
616
                for (j = 0; j < 4; ++j)
 
617
                        err |= n4[j] = vbi3_unham8 (buffer[j]);
 
618
 
 
619
                if (err < 0)
 
620
                        continue;
 
621
 
 
622
                buffer += 4;
 
623
 
 
624
                /* n4[0] & 8 "link page number may be superseded
 
625
                   by X/27/4 or X/27/5 data" ignored. */
 
626
 
 
627
                pgno[i] = MAG8 (n4[0] & 7) * 256 + n4[1] * 16 + n4[2];
 
628
 
 
629
                ps = cache_network_page_stat (td->network, pgno[i]);
 
630
 
 
631
                ps->page_type = VBI3_SYSTEM_PAGE;
 
632
                ps->subcode = n4[3]; /* highest S1 transmitted */
 
633
        }
 
634
}
 
635
 
 
636
static void
 
637
decode_mot_page                 (vbi3_teletext_decoder *        td,
 
638
                                 const cache_page *     cp)
 
639
{
 
640
        magazine *mag;
 
641
        const uint8_t *raw;
 
642
        unsigned int packet;
 
643
        vbi3_pgno pgno;
 
644
 
 
645
        mag = cache_network_magazine (td->network, cp->pgno);
 
646
 
 
647
        raw = cp->data.unknown.raw[1];
 
648
 
 
649
        pgno = 0;
 
650
 
 
651
        for (packet = 1; packet <= 8; ++packet) {
 
652
                if (cp->lop_packets & (1 << packet)) {
 
653
                        vbi3_pgno i;
 
654
 
 
655
                        for (i = 0x00; i <= 0x09; raw += 2, ++i)
 
656
                                decode_mot_page_lut (mag, raw, pgno + i);
 
657
 
 
658
                        for (i = 0x10; i <= 0x19; raw += 2, ++i)
 
659
                                decode_mot_page_lut (mag, raw, pgno + i);
 
660
                } else {
 
661
                        raw += 40;
 
662
                }
 
663
 
 
664
                pgno += 0x20;
 
665
        }
 
666
 
 
667
        pgno = 0;
 
668
 
 
669
        for (packet = 9; packet <= 14; ++packet) {
 
670
                if (cp->lop_packets & (1 << packet)) {
 
671
                        vbi3_pgno i;
 
672
 
 
673
                        for (i = 0x0A; i <= 0x0F; raw += 2, ++i)
 
674
                                decode_mot_page_lut (mag, raw, pgno + i);
 
675
 
 
676
                        if (14 == packet) /* 0xFA ... 0xFF, rest unused */
 
677
                                break;
 
678
 
 
679
                        for (i = 0x1A; i <= 0x1F; raw += 2, ++i)
 
680
                                decode_mot_page_lut (mag, raw, pgno + i);
 
681
 
 
682
                        for (i = 0x2A; i <= 0x2F; raw += 2, ++i)
 
683
                                decode_mot_page_lut (mag, raw, pgno + i);
 
684
 
 
685
                        raw += 40 - 3 * 6 * 2;
 
686
                } else {
 
687
                        raw += 40;
 
688
                }
 
689
 
 
690
                pgno += 0x30;
 
691
        }
 
692
 
 
693
        /* Level 2.5 POP links. */
 
694
 
 
695
        for (packet = 19; packet <= 20; ++packet)
 
696
                if (cp->lop_packets & (1 << packet))
 
697
                        decode_mot_page_pop (td, mag->pop_link[0]
 
698
                                             + (packet - 19) * 4,
 
699
                                             cp->data.unknown.raw[packet]);
 
700
 
 
701
        /* Level 2.5 DRCS links. */
 
702
 
 
703
        if (cp->lop_packets & (1 << 21))
 
704
                decode_mot_page_drcs (td, mag->drcs_link[0],
 
705
                                      cp->data.unknown.raw[21]);
 
706
 
 
707
        /* Level 3.5 POP links. */
 
708
 
 
709
        for (packet = 22; packet <= 23; ++packet)
 
710
                if (cp->lop_packets & (1 << packet))
 
711
                        decode_mot_page_pop (td, mag->pop_link[1]
 
712
                                             + (packet - 22) * 4,
 
713
                                             cp->data.unknown.raw[packet]);
 
714
 
 
715
        /* Level 3.5 DRCS links. */
 
716
 
 
717
        if (cp->lop_packets & (1 << 24))
 
718
                decode_mot_page_drcs (td, mag->drcs_link[1],
 
719
                                      cp->data.unknown.raw[24]);
 
720
}
 
721
 
 
722
/*
 
723
        11.2 Table Of Pages navigation
 
724
*/
 
725
 
 
726
static vbi3_bool
 
727
top_page_number                 (pagenum *              pn,
 
728
                                 const uint8_t          buffer[8])
 
729
{
 
730
        int n4[8];
 
731
        int err;
 
732
        unsigned int i;
 
733
        vbi3_pgno pgno;
 
734
        vbi3_subno subno;
 
735
 
 
736
        err = 0;
 
737
 
 
738
        for (i = 0; i < 8; ++i)
 
739
                err |= n4[i] = vbi3_unham8 (buffer[i]);
 
740
 
 
741
        pgno = n4[0] * 256 + n4[1] * 16 + n4[2];
 
742
 
 
743
        if (err < 0
 
744
            || pgno < 0x100
 
745
            || pgno > 0x8FF)
 
746
                return FALSE;
 
747
 
 
748
        subno = (n4[3] << 12) | (n4[4] << 8) | (n4[5] << 4) | n4[6];
 
749
 
 
750
        switch ((top_page_function) n4[7]) {
 
751
        case TOP_PAGE_FUNCTION_AIT:
 
752
                pn->function = PAGE_FUNCTION_AIT;
 
753
                break;
 
754
 
 
755
        case TOP_PAGE_FUNCTION_MPT:
 
756
                pn->function = PAGE_FUNCTION_MPT;
 
757
                break;
 
758
 
 
759
        case TOP_PAGE_FUNCTION_MPT_EX:
 
760
                pn->function = PAGE_FUNCTION_MPT_EX;
 
761
                break;
 
762
 
 
763
        default:
 
764
                pn->function = PAGE_FUNCTION_UNKNOWN;
 
765
                break;
 
766
        }
 
767
 
 
768
        pn->pgno = pgno;
 
769
        pn->subno = subno & 0x3F7F; /* flags? */
 
770
 
 
771
        return TRUE;
 
772
}
 
773
 
 
774
/* 11.2 Basic TOP Table */
 
775
 
 
776
static vbi3_bool
 
777
top_page_stat                   (cache_network *        cn,
 
778
                                 vbi3_pgno              pgno,
 
779
                                 btt_page_type          btt_type)
 
780
{
 
781
        page_stat *ps;
 
782
        vbi3_ttx_page_type page_type;
 
783
        unsigned int subcode;
 
784
        vbi3_bool changed;
 
785
 
 
786
        subcode = SUBCODE_SINGLE_PAGE;
 
787
 
 
788
        switch (btt_type) {
 
789
        case BTT_NO_PAGE:
 
790
                page_type = VBI3_NO_PAGE;
 
791
                subcode = SUBCODE_UNKNOWN;
 
792
                break;
 
793
 
 
794
                /* Observation: BTT_SUBTITLE only when the page is
 
795
                   transmitted, otherwise BTT_NO_PAGE. */
 
796
        case BTT_SUBTITLE:
 
797
                page_type = VBI3_SUBTITLE_PAGE;
 
798
                break;
 
799
 
 
800
        case BTT_PROGR_INDEX_M:
 
801
                subcode = SUBCODE_MULTI_PAGE;
 
802
                /* fall through */
 
803
 
 
804
        case BTT_PROGR_INDEX_S:
 
805
                /* Usually _SCHEDULE, not _INDEX. */
 
806
                page_type = VBI3_PROGR_SCHEDULE;
 
807
                break;
 
808
 
 
809
        case BTT_BLOCK_M:
 
810
                subcode = SUBCODE_MULTI_PAGE;
 
811
                /* fall through */
 
812
 
 
813
        case BTT_BLOCK_S:
 
814
                page_type = VBI3_TOP_BLOCK;
 
815
                break;
 
816
 
 
817
        case BTT_GROUP_M:
 
818
                subcode = SUBCODE_MULTI_PAGE;
 
819
                /* fall through */
 
820
 
 
821
        case BTT_GROUP_S:
 
822
                page_type = VBI3_TOP_GROUP;
 
823
                break;
 
824
 
 
825
        case BTT_NORMAL_M:
 
826
        case BTT_NORMAL_11:     /* ? */
 
827
                subcode = SUBCODE_MULTI_PAGE;
 
828
                /* fall through */
 
829
 
 
830
        case BTT_NORMAL_S:
 
831
        case BTT_NORMAL_9:      /* ? */
 
832
                page_type = VBI3_NORMAL_PAGE;
 
833
                break;
 
834
 
 
835
        default:
 
836
                page_type = VBI3_UNKNOWN_PAGE;
 
837
                subcode = SUBCODE_UNKNOWN;
 
838
                break;
 
839
        }
 
840
 
 
841
        log ("BTT %04x: %2u %04x %s\n",
 
842
             pgno, btt_type, subcode,
 
843
             vbi3_ttx_page_type_name (page_type));
 
844
 
 
845
        ps = cache_network_page_stat (cn, pgno);
 
846
 
 
847
        changed = FALSE;
 
848
 
 
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;
 
854
                changed = TRUE;
 
855
        }
 
856
 
 
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).
 
861
 
 
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;
 
868
        }
 
869
 
 
870
        return changed;
 
871
}
 
872
 
 
873
static vbi3_bool
 
874
top_link_stat                   (cache_network *        cn,
 
875
                                 unsigned int           link)
 
876
{
 
877
        pagenum *pn;
 
878
        page_stat *ps;
 
879
 
 
880
        cn->have_top = TRUE;
 
881
 
 
882
        pn = &cn->btt_link[link];
 
883
 
 
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);
 
892
                }
 
893
 
 
894
                ps = cache_network_page_stat (cn, pn->pgno);
 
895
                ps->page_type = VBI3_TOP_PAGE;
 
896
 
 
897
                return TRUE;
 
898
 
 
899
        default:
 
900
                return FALSE;
 
901
        }
 
902
}
 
903
 
 
904
static void
 
905
decode_btt_page                 (vbi3_teletext_decoder *        td,
 
906
                                 const cache_page *     cp)
 
907
{
 
908
        unsigned int packet;
 
909
        const uint8_t *raw;
 
910
        cache_network *cn;
 
911
        vbi3_bool changed;
 
912
        vbi3_pgno pgno;
 
913
 
 
914
        raw = cp->data.unknown.raw[1];
 
915
 
 
916
        changed = FALSE;
 
917
 
 
918
        pgno = 0x100;
 
919
 
 
920
        for (packet = 1; packet <= 20; ++packet) {
 
921
                unsigned int i;
 
922
 
 
923
                if (cp->lop_packets & (1 << packet)) {
 
924
                        for (i = 0; i < 40; ++i) {
 
925
                                btt_page_type btt_type;
 
926
 
 
927
                                btt_type = vbi3_unham8 (raw[i]);
 
928
 
 
929
                                if ((int) btt_type < 0) {
 
930
                                        pgno = vbi3_add_bcd (pgno, 1);
 
931
                                        continue;
 
932
                                }
 
933
 
 
934
                                changed |= top_page_stat (td->network,
 
935
                                                          pgno, btt_type);
 
936
 
 
937
                                pgno = vbi3_add_bcd (pgno, 1);
 
938
                        }
 
939
                } else {
 
940
                        pgno = vbi3_add_bcd (pgno, 0x40);
 
941
                }
 
942
 
 
943
                raw += 40;
 
944
        }
 
945
 
 
946
        /* Links to other TOP pages. */
 
947
 
 
948
        cn = td->network;
 
949
 
 
950
        for (packet = 21; packet <= 22; ++packet) {
 
951
                if (cp->lop_packets & (1 << packet)) {
 
952
                        unsigned int l;
 
953
                        unsigned int i;
 
954
 
 
955
                        l = (packet - 21) * 5;
 
956
 
 
957
                        for (i = 0; i < 5; ++i) {
 
958
                                if (top_page_number (&cn->btt_link[l], raw))
 
959
                                        top_link_stat (cn, l);
 
960
 
 
961
                                raw += 8;
 
962
                                ++l;
 
963
                        }
 
964
                } else {
 
965
                        raw += 40;
 
966
                }
 
967
        }
 
968
 
 
969
        /* What's in packet 23? */
 
970
 
 
971
        if (changed && (td->handlers.event_mask & VBI3_EVENT_PAGE_TYPE)) {
 
972
                vbi3_event e;
 
973
 
 
974
                e.type          = VBI3_EVENT_PAGE_TYPE;
 
975
                e.network       = &td->network->network;
 
976
                e.timestamp     = td->time;
 
977
 
 
978
                _vbi3_event_handler_list_send (&td->handlers, &e);
 
979
        }
 
980
}
 
981
 
 
982
/* 11.2 Additional Information Table */
 
983
 
 
984
static vbi3_bool
 
985
decode_ait_packet               (cache_page *           cp,
 
986
                                 const uint8_t          buffer[40],
 
987
                                 unsigned int           packet)
 
988
{
 
989
        unsigned int i;
 
990
 
 
991
        assert (46 * sizeof (ait_title) == sizeof (cp->data.ait.title));
 
992
 
 
993
        if (packet < 1 || packet > 23)
 
994
                return FALSE;
 
995
 
 
996
        for (i = 0; i < 2; ++i) {
 
997
                ait_title temp;
 
998
                unsigned int j;
 
999
                int c;
 
1000
 
 
1001
                if (!top_page_number (&temp.page, buffer))
 
1002
                        continue;
 
1003
 
 
1004
                buffer += 8;
 
1005
 
 
1006
                for (j = 0; j < 12; ++j) {
 
1007
                        /* Usually filled up with spaces, but zeroes also
 
1008
                           possible. */
 
1009
                        c = vbi3_unpar8 (buffer[j]);
 
1010
                        if (c && c < 0x20)
 
1011
                                break;
 
1012
 
 
1013
                        temp.text[j] = c;
 
1014
                }
 
1015
 
 
1016
                if (j < 12)
 
1017
                        continue;
 
1018
 
 
1019
                buffer += 12;
 
1020
 
 
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);
 
1031
                }
 
1032
 
 
1033
                cp->data.ait.title[packet * 2 - 2 + i] = temp;
 
1034
        }
 
1035
 
 
1036
        return TRUE;
 
1037
}
 
1038
 
 
1039
static vbi3_bool
 
1040
convert_ait_page                (cache_page *           dst,
 
1041
                                 const cache_page *     src)
 
1042
{
 
1043
        unsigned int packet;
 
1044
        const uint8_t *raw;
 
1045
 
 
1046
        /* NO_PAGE (pgno): (pgno & 0xFF) == 0xFF. */
 
1047
        memset (&dst->data.ait, -1, sizeof (dst->data.ait));
 
1048
 
 
1049
        dst->function = PAGE_FUNCTION_AIT;
 
1050
 
 
1051
        raw = src->data.unknown.raw[1];
 
1052
 
 
1053
        for (packet = 1; packet <= 23; ++packet) {
 
1054
                if (src->lop_packets & (1 << packet))
 
1055
                        if (!decode_ait_packet (dst, raw, packet))
 
1056
                                return FALSE;
 
1057
 
 
1058
                raw += 40;
 
1059
        }
 
1060
 
 
1061
        dst->data.ait.checksum = 0; /* changed */
 
1062
 
 
1063
        return TRUE;
 
1064
}
 
1065
 
 
1066
/* 11.2 Multi-Page Table */
 
1067
 
 
1068
static void
 
1069
decode_mpt_page                 (vbi3_teletext_decoder *        td,
 
1070
                                 const cache_page *     cp)
 
1071
{
 
1072
        unsigned int packet;
 
1073
        const uint8_t *raw;
 
1074
        vbi3_pgno pgno;
 
1075
 
 
1076
        raw = cp->data.unknown.raw[1];
 
1077
 
 
1078
        pgno = 0x100;
 
1079
 
 
1080
        for (packet = 1; packet <= 20; ++packet) {
 
1081
                if (cp->lop_packets & (1 << packet)) {
 
1082
                        unsigned int i;
 
1083
 
 
1084
                        for (i = 0; i < 40; ++i) {
 
1085
                                page_stat *ps;
 
1086
                                vbi3_ttx_page_type page_type;
 
1087
                                unsigned int subcode;
 
1088
                                int n;
 
1089
 
 
1090
                                if ((n = vbi3_unham8 (raw[i])) < 0) {
 
1091
                                        pgno = vbi3_add_bcd (pgno, 1);
 
1092
                                        continue;
 
1093
                                }
 
1094
 
 
1095
                                ps = cache_network_page_stat
 
1096
                                        (td->network, pgno);
 
1097
 
 
1098
                                page_type = ps->page_type;
 
1099
                                subcode = ps->subcode;
 
1100
 
 
1101
                                log ("MPT %04x: %04x %x %s\n",
 
1102
                                     pgno, subcode, n,
 
1103
                                     vbi3_ttx_page_type_name (page_type));
 
1104
 
 
1105
                                if (n > 9) {
 
1106
                                        /* Has more than 9 subpages, details
 
1107
                                           may follow in MPT-EX. */
 
1108
                                        n = 0x10;
 
1109
                                }
 
1110
 
 
1111
                                if (SUBCODE_UNKNOWN == subcode)
 
1112
                                        subcode = 0x0000;
 
1113
                                else if (SUBCODE_MULTI_PAGE == subcode)
 
1114
                                        subcode = 0x0002; /* at least */
 
1115
 
 
1116
                                if (VBI3_NO_PAGE != page_type
 
1117
                                    && VBI3_UNKNOWN_PAGE != page_type
 
1118
                                    && (unsigned int) n > subcode) {
 
1119
                                        ps->subcode = n;
 
1120
                                }
 
1121
 
 
1122
                                pgno = vbi3_add_bcd (pgno, 1);
 
1123
                        }
 
1124
                } else {
 
1125
                        pgno = vbi3_add_bcd (pgno, 0x40);
 
1126
                }
 
1127
 
 
1128
                raw += 40;
 
1129
        }
 
1130
}
 
1131
 
 
1132
/* 11.2 Multi-Page Extension Table */
 
1133
 
 
1134
static void
 
1135
decode_mpt_ex_page              (vbi3_teletext_decoder *        td,
 
1136
                                 const cache_page *     cp)
 
1137
{
 
1138
        unsigned int packet;
 
1139
        const uint8_t *raw;
 
1140
 
 
1141
        raw = cp->data.unknown.raw[1];
 
1142
 
 
1143
        for (packet = 1; packet <= 23; ++packet) {
 
1144
                if (cp->lop_packets & (1 << packet)) {
 
1145
                        unsigned int i;
 
1146
 
 
1147
                        for (i = 0; i < 5; ++i) {
 
1148
                                pagenum pn;
 
1149
                                page_stat *ps;
 
1150
                                vbi3_ttx_page_type page_type;
 
1151
                                unsigned int subcode;
 
1152
 
 
1153
                                if (!top_page_number (&pn, raw)) {
 
1154
                                        raw += 8;
 
1155
                                        continue;
 
1156
                                }
 
1157
 
 
1158
                                pn.subno = vbi3_dec2bcd (pn.subno & 0x7F);
 
1159
 
 
1160
                                if (TELETEXT_DECODER_LOG) {
 
1161
                                        log ("MPT-EX %3u: ",
 
1162
                                             (packet - 1) * 5 + i);
 
1163
                                        pagenum_dump (&pn, stderr);
 
1164
                                        fputc ('\n', stderr);
 
1165
                                }
 
1166
 
 
1167
                                if (pn.pgno < 0x100)
 
1168
                                        break;
 
1169
                                else if (pn.pgno > 0x8FF
 
1170
                                         || pn.subno < 0x02
 
1171
                                         || pn.subno > 0x99)
 
1172
                                        continue;
 
1173
 
 
1174
                                ps = cache_network_page_stat
 
1175
                                        (td->network, pn.pgno);
 
1176
 
 
1177
                                page_type = ps->page_type;
 
1178
                                subcode = ps->subcode;
 
1179
 
 
1180
                                if (SUBCODE_UNKNOWN == subcode)
 
1181
                                        subcode = 0x0000;
 
1182
                                else if (SUBCODE_MULTI_PAGE == subcode)
 
1183
                                        subcode = 0x0002; /* at least */
 
1184
 
 
1185
                                if (VBI3_NO_PAGE != page_type
 
1186
                                    && VBI3_UNKNOWN_PAGE != page_type
 
1187
                                    && (unsigned int) pn.subno > subcode) {
 
1188
                                        ps->subcode = pn.subno;
 
1189
                                }
 
1190
 
 
1191
                                raw += 8;
 
1192
                        }
 
1193
                } else {
 
1194
                        raw += 40;
 
1195
                }
 
1196
        }
 
1197
}
 
1198
 
 
1199
/*
 
1200
        11.3 Magazine Inventory Page
 
1201
*/
 
1202
 
 
1203
static vbi3_bool
 
1204
mip_page_stat                   (cache_network *        cn,
 
1205
                                 const cache_page *     cp,
 
1206
                                 const uint8_t **       raw,
 
1207
                                 unsigned int *         sub_index,
 
1208
                                 vbi3_pgno              pgno)
 
1209
{
 
1210
        page_stat *ps;
 
1211
        vbi3_ttx_page_type page_type;
 
1212
        vbi3_ttx_page_type old_type;
 
1213
        int code;
 
1214
        unsigned int subcode;
 
1215
        unsigned int old_subcode;
 
1216
        vbi3_bool changed;
 
1217
 
 
1218
        code = vbi3_unham16p (*raw);
 
1219
        *raw += 2;
 
1220
 
 
1221
        if (code < 0)
 
1222
                return FALSE;
 
1223
 
 
1224
        changed = FALSE;
 
1225
 
 
1226
        ps = cache_network_page_stat (cn, pgno);
 
1227
 
 
1228
        page_type = VBI3_UNKNOWN_PAGE;
 
1229
        subcode = SUBCODE_UNKNOWN;
 
1230
 
 
1231
        old_type = ps->page_type;
 
1232
        old_subcode = ps->subcode;
 
1233
 
 
1234
        switch (code) {
 
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) */
 
1251
                page_type = code;
 
1252
                subcode = 0;
 
1253
                break;
 
1254
 
 
1255
        case 0x02 ... 0x4F: /* VBI3_NORMAL_PAGE with 2 ... 79 subpages */
 
1256
                page_type = VBI3_NORMAL_PAGE;
 
1257
                subcode = vbi3_dec2bcd (code);
 
1258
                break;
 
1259
 
 
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 */
 
1266
        {
 
1267
                unsigned int packet = *sub_index / 13;
 
1268
                const uint8_t *raw;
 
1269
                int n;
 
1270
 
 
1271
                if (packet > 24 || 0 == (cp->lop_packets & (1 << packet)))
 
1272
                        return FALSE;
 
1273
 
 
1274
                raw = &cp->data.unknown.raw[packet][*sub_index % 13];
 
1275
 
 
1276
                n = vbi3_unham16p (raw) | (vbi3_unham8 (raw[2]) << 8);
 
1277
 
 
1278
                if (n < 0) {
 
1279
                        return FALSE;
 
1280
                } else if (0x1 == (code & 0xF)) {
 
1281
                        /* 4096+ subpages? Strange but true. */
 
1282
                        subcode = n + (1 << 12);
 
1283
                } else if (n < 2) {
 
1284
                        return FALSE;
 
1285
                } else {
 
1286
                        subcode = n;
 
1287
                }
 
1288
 
 
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 :
 
1294
                                             VBI3_NORMAL_PAGE;
 
1295
                break;
 
1296
        }
 
1297
 
 
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 */
 
1305
                return FALSE;
 
1306
 
 
1307
        case 0x70 ... 0x77:
 
1308
                page_type = VBI3_SUBTITLE_PAGE;
 
1309
                subcode = 0;
 
1310
 
 
1311
                if (0xFF == ps->charset_code) {
 
1312
                        const magazine *mag;
 
1313
                        vbi3_charset_code cs_code;
 
1314
 
 
1315
                        mag = cache_network_magazine (cn, cp->pgno);
 
1316
 
 
1317
                        cs_code = (mag->extension.charset_code[0]
 
1318
                                   & (unsigned int) ~7)
 
1319
                                | (code & 7);
 
1320
 
 
1321
                        if (vbi3_character_set_from_code (cs_code)) {
 
1322
                                ps->charset_code = cs_code;
 
1323
                        } else {
 
1324
                                ps->charset_code = cs_code & 7;
 
1325
                        }
 
1326
 
 
1327
                        changed = TRUE;
 
1328
                }
 
1329
 
 
1330
                break;
 
1331
 
 
1332
        case 0x79:          /* VBI3_NONSTD_SUBPAGES (e.g. clock page) */
 
1333
                page_type = VBI3_NONSTD_SUBPAGES;
 
1334
                subcode = 0x3F7F;
 
1335
                break;
 
1336
 
 
1337
        case 0x82 ... 0xCF: /* VBI3_PROGR_SCHEDULE with 2 ... 79 subpages */
 
1338
                page_type = VBI3_PROGR_SCHEDULE;
 
1339
                subcode = vbi3_dec2bcd (code & 0x7F);
 
1340
                break;
 
1341
 
 
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 */
 
1348
                page_type = code;
 
1349
                subcode = old_subcode;
 
1350
                break;
 
1351
 
 
1352
        case 0xE8 ... 0xEB:
 
1353
                page_type = VBI3_DRCS_PAGE;
 
1354
                subcode = old_subcode;
 
1355
                break;
 
1356
 
 
1357
        case 0xEC ... 0xEF:
 
1358
                page_type = VBI3_POP_PAGE;
 
1359
                subcode = old_subcode;
 
1360
                break;
 
1361
        }
 
1362
 
 
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;
 
1368
                changed = TRUE;
 
1369
        }
 
1370
 
 
1371
        if (SUBCODE_UNKNOWN == old_subcode)
 
1372
                old_subcode = 0x0000;
 
1373
        else if (SUBCODE_MULTI_PAGE == old_subcode)
 
1374
                old_subcode = 0x0002; /* at least */
 
1375
 
 
1376
        if (subcode > old_subcode) {
 
1377
                ps->subcode = subcode;
 
1378
        }
 
1379
 
 
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));
 
1383
 
 
1384
        return changed;
 
1385
}
 
1386
 
 
1387
static void
 
1388
decode_mip_page                 (vbi3_teletext_decoder *        td,
 
1389
                                 const cache_page *     cp)
 
1390
{
 
1391
        unsigned int packet;
 
1392
        unsigned int sub_index;
 
1393
        const uint8_t *raw;
 
1394
        vbi3_bool changed;
 
1395
        vbi3_pgno pgno;
 
1396
 
 
1397
        sub_index = 15 * 13;
 
1398
 
 
1399
        raw = cp->data.unknown.raw[1];
 
1400
 
 
1401
        changed = FALSE;
 
1402
 
 
1403
        pgno = cp->pgno & 0xF00;
 
1404
 
 
1405
        for (packet = 1; packet <= 8; ++packet) {
 
1406
                /* 11.3.2: Packets which contain only 0x00 VBI3_NO_PAGE
 
1407
                   are optional. */
 
1408
                if (cp->lop_packets & (1 << packet)) {
 
1409
                        vbi3_pgno i;
 
1410
 
 
1411
                        for (i = 0x00; i <= 0x09; ++i)
 
1412
                                changed |= mip_page_stat (td->network, cp,
 
1413
                                                          &raw, &sub_index,
 
1414
                                                          pgno + i);
 
1415
 
 
1416
                        for (i = 0x10; i <= 0x19; ++i)
 
1417
                                changed |= mip_page_stat (td->network, cp,
 
1418
                                                          &raw, &sub_index,
 
1419
                                                          pgno + i);
 
1420
                } else {
 
1421
                        raw += 40;
 
1422
                }
 
1423
 
 
1424
                pgno += 0x20;
 
1425
        }
 
1426
 
 
1427
        pgno = cp->pgno & 0xF00;
 
1428
 
 
1429
        for (packet = 9; packet <= 14; ++packet) {
 
1430
                /* 11.3.2: Packets which contain only 0x00 VBI3_NO_PAGE
 
1431
                   are optional. */
 
1432
                if (cp->lop_packets & (1 << packet)) {
 
1433
                        vbi3_pgno i;
 
1434
 
 
1435
                        for (i = 0x0A; i <= 0x0F; ++i)
 
1436
                                changed |= mip_page_stat (td->network, cp,
 
1437
                                                          &raw, &sub_index,
 
1438
                                                          pgno + i);
 
1439
 
 
1440
                        if (14 == packet) /* 0xFA ... 0xFF, rest unused */
 
1441
                                break;
 
1442
 
 
1443
                        for (i = 0x1A; i <= 0x1F; ++i)
 
1444
                                changed |= mip_page_stat (td->network, cp,
 
1445
                                                          &raw, &sub_index,
 
1446
                                                          pgno + i);
 
1447
 
 
1448
                        for (i = 0x2A; i <= 0x2F; ++i)
 
1449
                                changed |= mip_page_stat (td->network, cp,
 
1450
                                                          &raw, &sub_index,
 
1451
                                                          pgno + i);
 
1452
                } else {
 
1453
                        raw += 40;
 
1454
                }
 
1455
 
 
1456
                pgno += 0x30;
 
1457
        }
 
1458
 
 
1459
        if (changed && (td->handlers.event_mask & VBI3_EVENT_PAGE_TYPE)) {
 
1460
                vbi3_event e;
 
1461
 
 
1462
                e.type          = VBI3_EVENT_PAGE_TYPE;
 
1463
                e.network       = &td->network->network;
 
1464
                e.timestamp     = td->time;
 
1465
 
 
1466
                _vbi3_event_handler_list_send (&td->handlers, &e);
 
1467
        }
 
1468
}
 
1469
 
 
1470
/*
 
1471
        14. Dynamically Re-definable Characters download page
 
1472
*/
 
1473
 
 
1474
static void
 
1475
cache_page_drcs_dump            (const cache_page *     cp,
 
1476
                                 FILE *                 fp)
 
1477
{
 
1478
        unsigned int i;
 
1479
        const uint8_t *p;
 
1480
 
 
1481
        fprintf (fp, "DRCS page %03x.%04x\n", cp->pgno, cp->subno);
 
1482
 
 
1483
        p = cp->data.drcs.chars[0];
 
1484
 
 
1485
        for (i = 0; i < DRCS_PTUS_PER_PAGE; ++i) {
 
1486
                unsigned int j;
 
1487
 
 
1488
                fprintf (fp, "#%2u mode %02x\n ", i, cp->data.drcs.mode[i]);
 
1489
 
 
1490
                for (j = 0; j < 10; ++j) {
 
1491
                        unsigned int k;
 
1492
 
 
1493
                        for (k = 0; k < 6; ++k)
 
1494
                                fprintf (fp, "%x%x", p[k] & 15, p[k] >> 4);
 
1495
 
 
1496
                        p += 6;
 
1497
                        fputs ("\n ", fp);
 
1498
                }
 
1499
        }
 
1500
}
 
1501
 
 
1502
static const unsigned int
 
1503
expand1 [64] = {
 
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
 
1520
};
 
1521
 
 
1522
static const unsigned int
 
1523
expand2 [8] = {
 
1524
        0x000000, 0x110000, 0x001100, 0x111100,
 
1525
        0x000011, 0x110011, 0x001111, 0x111111,
 
1526
};
 
1527
 
 
1528
static void
 
1529
decode_drcs_page                (cache_page *           cp)
 
1530
{
 
1531
        uint8_t *s;
 
1532
        uint8_t *d;
 
1533
        uint64_t invalid;
 
1534
        unsigned int i;
 
1535
 
 
1536
        invalid = 0;
 
1537
 
 
1538
        s = cp->data.drcs.lop.raw[1];
 
1539
 
 
1540
        for (i = 0; i < DRCS_PTUS_PER_PAGE / 2; ++i) {
 
1541
                if (cp->lop_packets & (2 << i)) {
 
1542
                        unsigned int j;
 
1543
 
 
1544
                        for (j = 0; j < 40; ++j)
 
1545
                                if (vbi3_unpar8 (s[j]) < 0x40) {
 
1546
                                        invalid |= ((uint64_t) 3) << (i * 2);
 
1547
                                        break;
 
1548
                                }
 
1549
                } else {
 
1550
                        invalid |= ((uint64_t) 3) << (i * 2);
 
1551
                }
 
1552
 
 
1553
                s += 40;
 
1554
        }
 
1555
 
 
1556
        d = cp->data.drcs.chars[0];
 
1557
        s = cp->data.drcs.lop.raw[1];
 
1558
 
 
1559
        for (i = 0; i < DRCS_PTUS_PER_PAGE; ++i) {
 
1560
                unsigned int j;
 
1561
                unsigned int q;
 
1562
 
 
1563
                switch ((drcs_mode) cp->data.drcs.mode[i]) {
 
1564
                case DRCS_MODE_12_10_1:
 
1565
                        if (invalid & (((uint64_t) 1) << i)) {
 
1566
                                s += 20;
 
1567
                                d += 60;
 
1568
                        } else {
 
1569
                                for (j = 0; j < 20; ++j) {
 
1570
                                        q = expand1[*s++ & 0x3F];
 
1571
                                        d[0] = q;
 
1572
                                        d[1] = q >> 8;
 
1573
                                        d[2] = q >> 16;
 
1574
                                        d += 3;
 
1575
                                }
 
1576
                        }
 
1577
 
 
1578
                        break;
 
1579
 
 
1580
                case DRCS_MODE_12_10_2:
 
1581
                        if (invalid & (((uint64_t) 3) << i)) {
 
1582
                                invalid |= ((uint64_t) 3) << i;
 
1583
                                s += 40;
 
1584
                                d += 60;
 
1585
                        } else {
 
1586
                                for (j = 0; j < 20; ++j) {
 
1587
                                        q = expand1[s[ 0] & 0x3F]
 
1588
                                          + expand1[s[20] & 0x3F] * 2;
 
1589
                                        ++s;
 
1590
                                        d[0] = q;
 
1591
                                        d[1] = q >> 8;
 
1592
                                        d[2] = q >> 16;
 
1593
                                        d += 3;
 
1594
                                }
 
1595
                        }
 
1596
 
 
1597
                        i += 1;
 
1598
 
 
1599
                        break;
 
1600
 
 
1601
                case DRCS_MODE_12_10_4:
 
1602
                        if (invalid & (((uint64_t) 15) << i)) {
 
1603
                                invalid |= ((uint64_t) 15) << i;
 
1604
                                s += 80;
 
1605
                                d += 60;
 
1606
                        } else {
 
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;
 
1612
                                        ++s;
 
1613
                                        d[0] = q;
 
1614
                                        d[1] = q >> 8;
 
1615
                                        d[2] = q >> 16;
 
1616
                                        d += 3;
 
1617
                                }
 
1618
                        }
 
1619
 
 
1620
                        i += 3;
 
1621
 
 
1622
                        break;
 
1623
 
 
1624
                case DRCS_MODE_6_5_4:
 
1625
                        if (invalid & (((uint64_t) 1) << i)) {
 
1626
                                s += 20;
 
1627
                                d += 60;
 
1628
                        } else {
 
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;
 
1634
                                        d[0] = q;
 
1635
                                        d[1] = q >> 8;
 
1636
                                        d[2] = q >> 16;
 
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;
 
1641
                                        s += 4;
 
1642
                                        d[3] = q;
 
1643
                                        d[4] = q >> 8;
 
1644
                                        d[5] = q >> 16;
 
1645
                                        memcpy (d + 6, d, 6);
 
1646
                                        d += 12;
 
1647
                                }
 
1648
                        }
 
1649
 
 
1650
                        break;
 
1651
 
 
1652
                default:
 
1653
                        s += 20;
 
1654
                        d += 60;
 
1655
                        break;
 
1656
                }
 
1657
        }
 
1658
 
 
1659
        cp->data.drcs.invalid &= invalid;
 
1660
 
 
1661
        if (0)
 
1662
                cache_page_drcs_dump (cp, stderr);
 
1663
}
 
1664
 
 
1665
/**
 
1666
 * @internal
 
1667
 *
 
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.
 
1670
 */
 
1671
cache_page *
 
1672
_vbi3_convert_cached_page       (cache_page *           cp,
 
1673
                                 page_function          new_function)
 
1674
{
 
1675
        cache_page temp;
 
1676
        cache_page *cp1;
 
1677
 
 
1678
        if (PAGE_FUNCTION_UNKNOWN != cp->function) {
 
1679
                return NULL;
 
1680
        }
 
1681
 
 
1682
        log ("Convert page %s -> %s\n",
 
1683
             page_function_name (cp->function),
 
1684
             page_function_name (new_function));
 
1685
 
 
1686
        cache_page_copy (&temp, cp);
 
1687
 
 
1688
        switch (new_function) {
 
1689
        case PAGE_FUNCTION_LOP:
 
1690
                temp.function = new_function;
 
1691
                break;
 
1692
 
 
1693
        case PAGE_FUNCTION_GPOP:
 
1694
        case PAGE_FUNCTION_POP:
 
1695
                if (!convert_pop_page (&temp, cp, new_function))
 
1696
                        return NULL;
 
1697
                break;
 
1698
 
 
1699
        case PAGE_FUNCTION_GDRCS:
 
1700
        case PAGE_FUNCTION_DRCS:
 
1701
        {
 
1702
                unsigned int i;
 
1703
 
 
1704
                /* 14.1: Packet X/28/3 is optional when PTUs use only
 
1705
                   mode 12x10x1. B.2: X/28 must be transmitted before
 
1706
                   packets 1 ... 24.
 
1707
 
 
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. */
 
1712
 
 
1713
                for (i = 0; i < DRCS_PTUS_PER_PAGE; ++i)
 
1714
                        temp.data.drcs.mode[i] = DRCS_MODE_12_10_1;
 
1715
 
 
1716
                temp.function = new_function;
 
1717
                temp.data.drcs.invalid = (uint64_t) -1; /* all */
 
1718
 
 
1719
                decode_drcs_page (&temp);
 
1720
 
 
1721
                break;
 
1722
        }
 
1723
 
 
1724
        case PAGE_FUNCTION_AIT:
 
1725
                if (!convert_ait_page (&temp, cp))
 
1726
                        return NULL;
 
1727
                break;
 
1728
 
 
1729
        default:
 
1730
                /* Needs no conversion. */
 
1731
                assert (!"reached");
 
1732
        }
 
1733
 
 
1734
        if (!(cp1 = _vbi3_cache_put_page (cp->network->cache,
 
1735
                                         cp->network,
 
1736
                                         &temp)))
 
1737
                return NULL;
 
1738
 
 
1739
        cache_page_unref (cp);
 
1740
 
 
1741
        return cp1;
 
1742
}
 
1743
 
 
1744
static void
 
1745
eacem_trigger                   (vbi3_teletext_decoder *        td,
 
1746
                                 cache_page *           cp)
 
1747
{
 
1748
#if 0 /* TODO */
 
1749
 
 
1750
        vbi3_page_priv pgp;
 
1751
        uint8_t *d;
 
1752
        unsigned int i;
 
1753
 
 
1754
        if (0)
 
1755
                cache_page_raw_dump (cp, stderr, PAGE_CODING_ODD_PARITY);
 
1756
 
 
1757
        _vbi3_page_priv_init (&pgp);
 
1758
 
 
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,
 
1762
                                             0))
 
1763
                return;
 
1764
 
 
1765
        /* Latin-1!! */
 
1766
        d = (uint8_t *) pgp.pg.text;
 
1767
 
 
1768
        for (i = 1 * 40; i < 25 * 40; ++i) {
 
1769
                int c;
 
1770
 
 
1771
                c = pgp.pg.text[i].unicode;
 
1772
                *d++ = (c < 0x20 || c > 0xFF) ? 0x20 : c;
 
1773
        }
 
1774
 
 
1775
        *d = 0;
 
1776
 
 
1777
        _vbi3_trigger_list_add_eacem (&td->triggers,
 
1778
                                     &td->handlers,
 
1779
                                     (uint8_t *) pgp.pg.text,
 
1780
                                     &td->network->network,
 
1781
                                     td->time);
 
1782
#endif
 
1783
 
 
1784
}
 
1785
 
 
1786
static vbi3_charset_code
 
1787
page_charset_code               (vbi3_teletext_decoder *        td,
 
1788
                                 const cache_page *     cp)
 
1789
{
 
1790
        vbi3_charset_code code;
 
1791
        const magazine *mag;
 
1792
 
 
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;
 
1797
 
 
1798
                if (vbi3_character_set_from_code (code))
 
1799
                        return code;
 
1800
 
 
1801
                code = cp->data.ext_lop.ext.charset_code[0];
 
1802
 
 
1803
                if (vbi3_character_set_from_code (code))
 
1804
                        return code;
 
1805
        }
 
1806
 
 
1807
        mag = cache_network_magazine (td->network, cp->pgno);
 
1808
 
 
1809
        code = (mag->extension.charset_code[0] &
 
1810
                (unsigned int) ~7) + cp->national;
 
1811
 
 
1812
        if (vbi3_character_set_from_code (code))
 
1813
                return code;
 
1814
 
 
1815
        code = mag->extension.charset_code[0];
 
1816
 
 
1817
        if (vbi3_character_set_from_code (code))
 
1818
                return code;
 
1819
 
 
1820
        return 0xFF; /* unknown */
 
1821
}
 
1822
 
 
1823
/* 9.3.1 Teletext packet 0, Page Header. */
 
1824
 
 
1825
static int
 
1826
same_header                     (vbi3_pgno              cur_pgno,
 
1827
                                 const uint8_t *        cur,
 
1828
                                 vbi3_pgno              ref_pgno,
 
1829
                                 const uint8_t *        ref)
 
1830
{
 
1831
        uint8_t buf[3];
 
1832
        unsigned int i;
 
1833
        unsigned int j;
 
1834
        int neq;
 
1835
        int err;
 
1836
 
 
1837
        /* NB this assumes vbi3_is_bcd (cur_pgno),
 
1838
           which follows from roll_header. */
 
1839
 
 
1840
        buf[2] =  (cur_pgno       & 15) + '0';
 
1841
        buf[1] = ((cur_pgno >> 4) & 15) + '0';
 
1842
        buf[0] =  (cur_pgno >> 8)       + '0';
 
1843
 
 
1844
        vbi3_par (buf, 3);
 
1845
 
 
1846
        j = 32;
 
1847
 
 
1848
        neq = 0;
 
1849
        err = 0;
 
1850
 
 
1851
        /* Header: 8 byte page address & control, 24 text,
 
1852
                   8 byte hh:mm:ss (usually). */
 
1853
 
 
1854
        for (i = 8; i < 29; ++i) {
 
1855
                if (cur[0] == buf[0]
 
1856
                    && cur[1] == buf[1]
 
1857
                    && cur[2] == buf[2])
 
1858
                        break;
 
1859
                err |= vbi3_unpar8 (*cur);
 
1860
                err |= vbi3_unpar8 (*ref);
 
1861
                neq |= *cur++ ^ *ref++;
 
1862
        }
 
1863
 
 
1864
        /* Skip page number. */
 
1865
 
 
1866
        j = i;
 
1867
        i += 3;
 
1868
        cur += 3;
 
1869
        ref += 3;
 
1870
 
 
1871
        for (; i < 32; ++i) {
 
1872
                err |= vbi3_unpar8 (*cur);
 
1873
                err |= vbi3_unpar8 (*ref);
 
1874
                neq |= *cur++ ^ *ref++;
 
1875
        }
 
1876
 
 
1877
        /* Parity error or no page number. */
 
1878
        if (err < 0 || j >= 32)
 
1879
                return -3; /* inconclusive */
 
1880
 
 
1881
        if (!neq) {
 
1882
                /* I have yet to see equal headers from different
 
1883
                   networks, so this is probably correct. */
 
1884
                return TRUE;
 
1885
        }
 
1886
 
 
1887
        /* Comparing headers from different magazines
 
1888
           can result in false negatives. */
 
1889
        if ((cur_pgno ^ ref_pgno) & 0xF00)
 
1890
                return -2; /* inconclusive */
 
1891
 
 
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 */
 
1897
        }
 
1898
 
 
1899
        /* Pages with headers from the same network can still differ,
 
1900
           but what more can we do. */
 
1901
 
 
1902
        return FALSE;
 
1903
}
 
1904
 
 
1905
#if 0
 
1906
 
 
1907
/* Note "clock" may not be a clock. */
 
1908
static vbi3_bool
 
1909
same_clock                      (const uint8_t *        cur,
 
1910
                                 const uint8_t *        ref)
 
1911
{
 
1912
        unsigned int i;
 
1913
 
 
1914
        for (i = 32; i < 40; ++i) {
 
1915
                if (*cur != *ref
 
1916
                    && (vbi3_ipar8 (*cur) | vbi3_ipar8 (*ref)) >= 0)
 
1917
                        return FALSE;
 
1918
                ++cur;
 
1919
                ++ref;
 
1920
        }
 
1921
 
 
1922
        return TRUE;
 
1923
}
 
1924
 
 
1925
#endif
 
1926
 
 
1927
static void
 
1928
network_event                   (vbi3_teletext_decoder *        td)
 
1929
{
 
1930
        vbi3_event e;
 
1931
 
 
1932
        e.type = VBI3_EVENT_NETWORK;
 
1933
        e.network = &td->network->network;
 
1934
        e.timestamp = td->time;
 
1935
 
 
1936
        _vbi3_event_handler_list_send (&td->handlers, &e);
 
1937
 
 
1938
        e.type = VBI3_EVENT_TOP_CHANGE;
 
1939
 
 
1940
        _vbi3_event_handler_list_send (&td->handlers, &e);
 
1941
 
 
1942
/* XXX?
 
1943
        e.type = VBI3_EVENT_PAGE_TYPE;
 
1944
 
 
1945
        _vbi3_event_handler_list_send (&td->handlers, &e);
 
1946
 
 
1947
        e.type = VBI3_EVENT_PROG_INFO;
 
1948
        e.ev.prog_info = &cn->program_info;
 
1949
 
 
1950
        _vbi3_event_handler_list_send (&td->handlers, &e);
 
1951
*/
 
1952
        /* XXX ASPECT? */
 
1953
        /* XXX PROG_ID? */
 
1954
}
 
1955
 
 
1956
static void
 
1957
detect_channel_change           (vbi3_teletext_decoder *        td,
 
1958
                                 const cache_page *     cp)
 
1959
{
 
1960
        vbi3_network *nk;
 
1961
        int r;
 
1962
 
 
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);
 
1968
        } else {
 
1969
                r = same_header (cp->pgno, cp->data.lop.raw[0] + 8,
 
1970
                                 td->header_page.pgno, td->header + 8);
 
1971
        }
 
1972
 
 
1973
        switch (r) {
 
1974
        case TRUE:
 
1975
                if (TELETEXT_DECODER_CHSW_TEST) {
 
1976
                        fprintf (stderr, "+");
 
1977
                        fflush (stderr);
 
1978
                }
 
1979
 
 
1980
                td->header_page.pgno = cp->pgno;
 
1981
                COPY (td->header, cp->data.lop.raw[0]);
 
1982
 
 
1983
                /* Cancel reset. */
 
1984
                td->virtual_reset (td, NULL, -1.0);
 
1985
 
 
1986
                if (0) { /* XXX improve */
 
1987
 
 
1988
                nk = &td->network->network;
 
1989
 
 
1990
                if (!nk->name
 
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]))
 
1995
                                network_event (td);
 
1996
                }
 
1997
 
 
1998
                }
 
1999
 
 
2000
                break;
 
2001
 
 
2002
        case FALSE:
 
2003
                if (TELETEXT_DECODER_CHSW_TEST) {
 
2004
                        fprintf (stderr, "-");
 
2005
                        fflush (stderr);
 
2006
                }
 
2007
 
 
2008
                td->header_page.pgno = cp->pgno;
 
2009
                COPY (td->header, cp->data.lop.raw[0]);
 
2010
 
 
2011
                /* Reset at next vbi3_teletext_decoder_decode() call. */
 
2012
                td->virtual_reset (td, NULL, td->time + 0.0);
 
2013
 
 
2014
                break;
 
2015
 
 
2016
        default:
 
2017
                if (TELETEXT_DECODER_CHSW_TEST) {
 
2018
                        fprintf (stderr, "%d", -r);
 
2019
                        fflush (stderr);
 
2020
                }
 
2021
 
 
2022
                if (-1 == 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);
 
2030
                }
 
2031
 
 
2032
                break;
 
2033
        }
 
2034
}
 
2035
 
 
2036
static void
 
2037
store_page                      (vbi3_teletext_decoder *        td,
 
2038
                                 cache_page *           cp)
 
2039
{
 
2040
        cache_page *cp1;
 
2041
 
 
2042
        if (td->reset_time > 0) {
 
2043
                /* Suspended because we suspect a channel change. */
 
2044
                if (PAGE_FUNCTION_LOP != cp->function)
 
2045
                        return;
 
2046
        }
 
2047
 
 
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);
 
2051
        }
 
2052
 
 
2053
        switch (cp->function) {
 
2054
        case PAGE_FUNCTION_EPG:
 
2055
        case PAGE_FUNCTION_ACI:
 
2056
        case PAGE_FUNCTION_DISCARD:
 
2057
        case PAGE_FUNCTION_DATA:
 
2058
                /* Discard. */
 
2059
                break;
 
2060
 
 
2061
        case PAGE_FUNCTION_LOP:
 
2062
        {
 
2063
                page_stat *ps;
 
2064
                vbi3_bool roll_header;
 
2065
 
 
2066
                if (0)
 
2067
                        cache_page_raw_dump (cp, stderr,
 
2068
                                             PAGE_CODING_ODD_PARITY);
 
2069
 
 
2070
                roll_header = (vbi3_is_bcd (cp->pgno)
 
2071
                               && 0 == (cp->flags &
 
2072
                                        (C5_NEWSFLASH |
 
2073
                                         C6_SUBTITLE |
 
2074
                                         C7_SUPPRESS_HEADER |
 
2075
                                         C9_INTERRUPTED |
 
2076
                                         C10_INHIBIT_DISPLAY)));
 
2077
 
 
2078
                if (roll_header)
 
2079
                        detect_channel_change (td, cp);
 
2080
 
 
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)
 
2086
                        return;
 
2087
 
 
2088
                /* Collect information about pages
 
2089
                   not listed in MIP and BTT. */
 
2090
 
 
2091
                ps = cache_network_page_stat (td->network, cp->pgno);
 
2092
 
 
2093
                ps->flags = cp->flags;
 
2094
 
 
2095
                switch ((vbi3_ttx_page_type) ps->page_type) {
 
2096
                case VBI3_NO_PAGE:
 
2097
                case VBI3_UNKNOWN_PAGE:
 
2098
                        if (cp->flags & C6_SUBTITLE)
 
2099
                                ps->page_type = VBI3_SUBTITLE_PAGE;
 
2100
                        else
 
2101
                                ps->page_type = VBI3_NORMAL_PAGE;
 
2102
 
 
2103
                        if (0xFF == ps->charset_code)
 
2104
                                ps->charset_code = page_charset_code (td, cp);
 
2105
 
 
2106
                        break;
 
2107
 
 
2108
                case VBI3_NORMAL_PAGE:
 
2109
                        if (cp->flags & C6_SUBTITLE)
 
2110
                                ps->page_type = VBI3_SUBTITLE_PAGE;
 
2111
 
 
2112
                        if (0xFF == ps->charset_code)
 
2113
                                ps->charset_code = page_charset_code (td, cp);
 
2114
 
 
2115
                        break;
 
2116
 
 
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);
 
2128
                        break;
 
2129
 
 
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);
 
2134
                        } else {
 
2135
                                /* Fixes bug in ORF 1 BTT. */
 
2136
                                ps->page_type = VBI3_NORMAL_PAGE;
 
2137
                        }
 
2138
 
 
2139
                        break;
 
2140
 
 
2141
                default:
 
2142
                        break;
 
2143
                }
 
2144
 
 
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,
 
2149
                             cp->lop_packets,
 
2150
                             cp->x26_designations,
 
2151
                             cp->x27_designations,
 
2152
                             cp->x28_designations);
 
2153
 
 
2154
                        cp1 = _vbi3_cache_put_page (td->cache, td->network, cp);
 
2155
 
 
2156
                        if (cp1) {
 
2157
                                vbi3_event e;
 
2158
 
 
2159
                                e.type          = VBI3_EVENT_TTX_PAGE;
 
2160
                                e.network       = &td->network->network;
 
2161
                                e.timestamp     = td->time;
 
2162
 
 
2163
                                e.ev.ttx_page.pgno = cp->pgno;
 
2164
                                e.ev.ttx_page.subno = cp->subno;
 
2165
 
 
2166
                                e.ev.ttx_page.flags =
 
2167
                                        (roll_header ? VBI3_ROLL_HEADER : 0)
 
2168
                                        | (cp->flags & (C5_NEWSFLASH |
 
2169
                                                        C6_SUBTITLE |
 
2170
                                                        C8_UPDATE |
 
2171
                                                        C11_MAGAZINE_SERIAL));
 
2172
 
 
2173
                                _vbi3_event_handler_list_send
 
2174
                                        (&td->handlers, &e);
 
2175
 
 
2176
                                cache_page_unref (cp1);
 
2177
                        }
 
2178
                }
 
2179
 
 
2180
                break;
 
2181
        }
 
2182
 
 
2183
        case PAGE_FUNCTION_GPOP:
 
2184
        case PAGE_FUNCTION_POP:
 
2185
                /* Page was decoded on the fly. */
 
2186
 
 
2187
                if (td->handlers.event_mask & VBI3_EVENT_TTX_PAGE) {
 
2188
                        cp1 = _vbi3_cache_put_page
 
2189
                                (td->cache, td->network, cp);
 
2190
 
 
2191
                        cache_page_unref (cp1);
 
2192
                }
 
2193
 
 
2194
                break;
 
2195
 
 
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);
 
2204
 
 
2205
                        cp1 = _vbi3_cache_put_page
 
2206
                                (td->cache, td->network, cp);
 
2207
 
 
2208
                        cache_page_unref (cp1);
 
2209
                }
 
2210
 
 
2211
                break;
 
2212
 
 
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);
 
2218
                break;
 
2219
 
 
2220
        case PAGE_FUNCTION_MIP:
 
2221
                /* Magazine Inventory Page -
 
2222
                   Store valid information in td->network->pages[]. */
 
2223
                decode_mip_page (td, cp);
 
2224
                break;
 
2225
 
 
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);
 
2231
                break;
 
2232
 
 
2233
        case PAGE_FUNCTION_AIT:
 
2234
                /* Page was decoded on the fly. */
 
2235
                cp1 = _vbi3_cache_put_page (td->cache, td->network, cp);
 
2236
 
 
2237
                if (cp1) {
 
2238
                        unsigned int i;
 
2239
                        unsigned int sum;
 
2240
 
 
2241
                        sum = 0;
 
2242
 
 
2243
                        for (i = 0; i < sizeof (cp->data.ait.title); ++i)
 
2244
                                sum += ((uint8_t *) &cp->data.ait.title)[i];
 
2245
 
 
2246
                        if (cp->data.ait.checksum != sum
 
2247
                            && (td->handlers.event_mask
 
2248
                                & VBI3_EVENT_TOP_CHANGE)) {
 
2249
                                vbi3_event e;
 
2250
 
 
2251
                                e.type          = VBI3_EVENT_TOP_CHANGE;
 
2252
                                e.network       = &td->network->network;
 
2253
                                e.timestamp     = td->time;
 
2254
 
 
2255
                                _vbi3_event_handler_list_send
 
2256
                                        (&td->handlers, &e);
 
2257
                        }
 
2258
 
 
2259
                        cp1->data.ait.checksum = sum;
 
2260
 
 
2261
                        cache_page_unref (cp1);
 
2262
                }
 
2263
 
 
2264
                break;
 
2265
 
 
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);
 
2271
                break;
 
2272
 
 
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);
 
2278
                break;
 
2279
 
 
2280
        case PAGE_FUNCTION_TRIGGER:
 
2281
                if (td->handlers.event_mask & VBI3_EVENT_TRIGGER)
 
2282
                        eacem_trigger (td, cp);
 
2283
                break;
 
2284
 
 
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);
 
2293
                break;
 
2294
        }
 
2295
}
 
2296
 
 
2297
#if 0 /* TODO */
 
2298
 
 
2299
static vbi3_bool
 
2300
epg_callback                    (vbi3_pfc_demux *       pc,
 
2301
                                 void *                 user_data,
 
2302
                                 const vbi3_pfc_block * block)
 
2303
{
 
2304
        vbi3_teletext_decoder *td = user_data;
 
2305
 
 
2306
        return TRUE;
 
2307
}
 
2308
 
 
2309
#endif
 
2310
 
 
2311
static vbi3_bool
 
2312
decode_packet_0                 (vbi3_teletext_decoder *        td,
 
2313
                                 cache_page *           cp,
 
2314
                                 const uint8_t          buffer[42],
 
2315
                                 unsigned int           mag0)
 
2316
{
 
2317
        int page;
 
2318
        vbi3_pgno pgno;
 
2319
        vbi3_subno subno;
 
2320
        unsigned int flags;
 
2321
        cache_page *cached_cp;
 
2322
 
 
2323
        if ((page = vbi3_unham16p (buffer + 2)) < 0) {
 
2324
                _vbi3_teletext_decoder_resync (td);
 
2325
 
 
2326
                log ("Hamming error in packet 0 page number\n");
 
2327
 
 
2328
                return FALSE;
 
2329
        }
 
2330
 
 
2331
        pgno = ((0 == mag0) ? 0x800 : mag0 << 8) + page;
 
2332
 
 
2333
        if (0 && !vbi3_is_bcd (page) && 0xFF != page) {
 
2334
                fprintf (stderr, "System page %x\n", pgno);
 
2335
        } else {
 
2336
                log ("Packet 0 page %x\n", pgno);
 
2337
        }
 
2338
 
 
2339
        if (td->current) {
 
2340
                if (td->current->flags & C11_MAGAZINE_SERIAL) {
 
2341
                        /* New pgno terminates the most recently
 
2342
                           received page. */
 
2343
 
 
2344
                        if (td->current->pgno != pgno) {
 
2345
                                store_page (td, td->current);
 
2346
                                cp->function = PAGE_FUNCTION_DISCARD;
 
2347
                        }
 
2348
                } else {
 
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;
 
2354
                        }
 
2355
                }
 
2356
        }
 
2357
 
 
2358
        /* A.1: mFF time filling / terminator. */
 
2359
        if (0xFF == page) {
 
2360
                td->current = NULL;
 
2361
                cp->function = PAGE_FUNCTION_DISCARD;
 
2362
                return TRUE;
 
2363
        }
 
2364
 
 
2365
        subno = (vbi3_unham16p (buffer + 4)
 
2366
                 + vbi3_unham16p (buffer + 6) * 256);
 
2367
 
 
2368
        /* C7 ... C14 */
 
2369
        flags = vbi3_unham16p (buffer + 8);
 
2370
 
 
2371
        if ((int)(subno | flags) < 0) {
 
2372
                td->current = NULL;
 
2373
                cp->function = PAGE_FUNCTION_DISCARD;
 
2374
                return FALSE;
 
2375
        }
 
2376
 
 
2377
        td->current = cp;
 
2378
 
 
2379
        if (PAGE_FUNCTION_DISCARD != cp->function
 
2380
            && cp->pgno == pgno
 
2381
            && cp->flags == (flags << 16) + subno) {
 
2382
                /* Repeated header for time filling. */
 
2383
                return TRUE;
 
2384
        }
 
2385
 
 
2386
        cp->pgno        = pgno;
 
2387
        cp->national    = vbi3_rev8 (flags) & 7;
 
2388
        cp->flags       = (flags << 16) + subno;
 
2389
 
 
2390
        if (vbi3_is_bcd (page)) {
 
2391
                subno &= 0x3F7F;
 
2392
 
 
2393
                log ("Normal page %03x.%04x flags %06x\n",
 
2394
                     cp->pgno, subno, cp->flags);
 
2395
 
 
2396
                if (!vbi3_is_bcd (subno)) {
 
2397
                        td->current = NULL;
 
2398
                        cp->function = PAGE_FUNCTION_DISCARD;
 
2399
                        return FALSE;
 
2400
                }
 
2401
 
 
2402
                cp->subno = subno;
 
2403
        } else {
 
2404
                cp->subno = subno & 0x000F;
 
2405
 
 
2406
                log ("System page %03x.%04x flags %06x\n",
 
2407
                     cp->pgno, cp->subno, cp->flags);
 
2408
        }
 
2409
 
 
2410
        if (cp->flags & C4_ERASE_PAGE)
 
2411
                goto erase;
 
2412
 
 
2413
        cached_cp = _vbi3_cache_get_page (td->cache, td->network,
 
2414
                                         cp->pgno, cp->subno,
 
2415
                                         /* subno mask */ -1);
 
2416
 
 
2417
        if (cached_cp) {
 
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);
 
2425
 
 
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. */
 
2430
 
 
2431
                memcpy (&cp->data, &cached_cp->data,
 
2432
                        cache_page_size (cached_cp)
 
2433
                        - (sizeof (*cp) - sizeof (cp->data)));
 
2434
 
 
2435
                cp->function = cached_cp->function;
 
2436
 
 
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);
 
2442
                        break;
 
2443
 
 
2444
                default:
 
2445
                        break;
 
2446
                }
 
2447
 
 
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;
 
2452
 
 
2453
                cache_page_unref (cached_cp);
 
2454
 
 
2455
                cached_cp = NULL;
 
2456
        } else {
 
2457
                page_stat *ps;
 
2458
                
 
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. */
 
2464
        erase:
 
2465
                ps = cache_network_page_stat (td->network, cp->pgno);
 
2466
 
 
2467
                log ("... rebuild %03x.%04x from scratch\n",
 
2468
                     cp->pgno, cp->subno);
 
2469
 
 
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. */
 
2473
 
 
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);
 
2489
                } else {
 
2490
                        cp->function = PAGE_FUNCTION_UNKNOWN;
 
2491
 
 
2492
                        clear_lop (cp);
 
2493
                        clear_enhancement (cp);
 
2494
 
 
2495
                        /* No X/28 packets received. */
 
2496
                        cp->data.ext_lop.ext.designations = 0;
 
2497
 
 
2498
                        /* Store header packet. */
 
2499
                        memcpy (cp->data.unknown.raw[0] + 0, buffer + 2, 40);
 
2500
                }
 
2501
 
 
2502
                /* Packet 0 received. */
 
2503
                cp->lop_packets = 1;
 
2504
                cp->x26_designations = 0;
 
2505
                cp->x27_designations = 0;
 
2506
                cp->x28_designations = 0;
 
2507
        }
 
2508
 
 
2509
        /* Determine the page function from MOT, MIP or BTT data. Another
 
2510
           opportunity arises when we receive packet X/28, see there. */
 
2511
 
 
2512
        if (PAGE_FUNCTION_UNKNOWN == cp->function) {
 
2513
                page_stat *ps;
 
2514
 
 
2515
                ps = cache_network_page_stat (td->network, cp->pgno);
 
2516
 
 
2517
                switch ((vbi3_ttx_page_type) ps->page_type) {
 
2518
                case VBI3_NO_PAGE:
 
2519
                        /* Who's wrong here? */
 
2520
                        ps->page_type = VBI3_UNKNOWN_PAGE;
 
2521
                        cp->function = PAGE_FUNCTION_DISCARD;
 
2522
                        break;
 
2523
 
 
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;
 
2536
                        break;
 
2537
 
 
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. */
 
2542
                        break;
 
2543
 
 
2544
                case VBI3_TOP_PAGE:
 
2545
                {
 
2546
                        cache_network *cn;
 
2547
                        unsigned int i;
 
2548
 
 
2549
                        cn = td->network;
 
2550
 
 
2551
                        for (i = 0; i < N_ELEMENTS (cn->btt_link); ++i)
 
2552
                                if (cn->btt_link[i].pgno == cp->pgno)
 
2553
                                        break;
 
2554
 
 
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:
 
2559
                                        cp->function =
 
2560
                                                cn->btt_link[i].function;
 
2561
                                        break;
 
2562
 
 
2563
                                case PAGE_FUNCTION_AIT:
 
2564
                                {
 
2565
                                        cache_page temp;
 
2566
 
 
2567
                                        cache_page_copy (&temp, cp);
 
2568
                                        convert_ait_page (cp, &temp);
 
2569
 
 
2570
                                        cp->function = PAGE_FUNCTION_AIT;
 
2571
 
 
2572
                                        break;
 
2573
                                }
 
2574
 
 
2575
                                default:
 
2576
                                        assert (!"reached");
 
2577
                                        break;
 
2578
                                }
 
2579
                        } else {
 
2580
                                log ("%03x.%04x claims to be "
 
2581
                                     "TOP page, but no link found\n",
 
2582
                                     cp->pgno, cp->subno);
 
2583
                        }
 
2584
 
 
2585
                        break;
 
2586
                }
 
2587
 
 
2588
                case VBI3_DRCS_PAGE:
 
2589
                {
 
2590
                        unsigned int i;
 
2591
 
 
2592
                        /* 14.1: Packet X/28/3 is optional when PTUs use only
 
2593
                           mode 12x10x1. B.2: X/28 must be transmitted before
 
2594
                           packets 1 ... 24.
 
2595
 
 
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;
 
2601
 
 
2602
                        cp->function = PAGE_FUNCTION_DRCS;
 
2603
 
 
2604
                        break;
 
2605
                }
 
2606
 
 
2607
                case VBI3_POP_PAGE:
 
2608
                {
 
2609
                        cache_page temp;
 
2610
 
 
2611
                        cache_page_copy (&temp, cp);
 
2612
                        convert_pop_page (cp, &temp, PAGE_FUNCTION_POP);
 
2613
 
 
2614
                        break;
 
2615
                }
 
2616
 
 
2617
                case VBI3_TRIGGER_DATA:
 
2618
                        cp->function = PAGE_FUNCTION_TRIGGER;
 
2619
                        break;
 
2620
 
 
2621
                case VBI3_PFC_EPG_DATA:
 
2622
                {
 
2623
                        cp->function = PAGE_FUNCTION_EPG;
 
2624
 
 
2625
#if 0 /* TODO */
 
2626
                        if (0 == td->epg_stream[0].block.pgno) {
 
2627
                                _vbi3_pfc_demux_init (&td->epg_stream[0],
 
2628
                                                     cp->pgno, 1,
 
2629
                                                     epg_callback, td);
 
2630
 
 
2631
                                _vbi3_pfc_demux_init (&td->epg_stream[1],
 
2632
                                                     cp->pgno, 2,
 
2633
                                                     epg_callback, td);
 
2634
                        }
 
2635
#endif
 
2636
                        break;
 
2637
                }
 
2638
 
 
2639
                case VBI3_NOT_PUBLIC:
 
2640
                case VBI3_CA_DATA:
 
2641
                case VBI3_PFC_DATA:
 
2642
                case VBI3_KEYWORD_SEARCH_LIST:
 
2643
                        cp->function = PAGE_FUNCTION_DISCARD;
 
2644
                        break;
 
2645
 
 
2646
                default:
 
2647
                        if (vbi3_is_bcd (page))
 
2648
                                cp->function = PAGE_FUNCTION_LOP;
 
2649
                        /* else remains unknown. */
 
2650
                        break;
 
2651
                }
 
2652
 
 
2653
                log ("... identified as %s\n",
 
2654
                     page_function_name (cp->function));
 
2655
        }
 
2656
 
 
2657
        switch (cp->function) {
 
2658
        case PAGE_FUNCTION_ACI:
 
2659
        case PAGE_FUNCTION_TRIGGER:
 
2660
                /* ? */
 
2661
                break;
 
2662
 
 
2663
        case PAGE_FUNCTION_BTT:
 
2664
        case PAGE_FUNCTION_AIT:
 
2665
        case PAGE_FUNCTION_MPT:
 
2666
        case PAGE_FUNCTION_MPT_EX:
 
2667
                /* ? */
 
2668
                /* Observation: BTT with 3Fx0, others with 0000. */
 
2669
                break;
 
2670
 
 
2671
        case PAGE_FUNCTION_LOP:
 
2672
                /* 0000 single page, 0001 ... 0079 multi page
 
2673
                   2359 clock page / subpages not to be cached. */
 
2674
                break;
 
2675
 
 
2676
        case PAGE_FUNCTION_EPG:
 
2677
        case PAGE_FUNCTION_DATA:
 
2678
                /* Uses different scheme, see EN 300 708 4.3.1 */
 
2679
                break;
 
2680
 
 
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:
 
2687
        {
 
2688
                unsigned int last_packet;
 
2689
                unsigned int continuity;
 
2690
 
 
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. */
 
2694
 
 
2695
                last_packet = subno >> 8;
 
2696
                continuity = (subno >> 4) & 15;
 
2697
 
 
2698
                if (last_packet >= 26)
 
2699
                        log ("... last packet X/26/%u ci %u ",
 
2700
                             last_packet - 26, continuity);
 
2701
                else
 
2702
                        log ("... last packet X/%u ci %u ",
 
2703
                             last_packet, continuity);
 
2704
 
 
2705
                if (cp->flags & C13_PARTIAL_PAGE)
 
2706
                        log ("partial page");
 
2707
                else
 
2708
                        log ("full page");
 
2709
 
 
2710
                if (cp->flags & C12_FRAGMENT)
 
2711
                        log (" fragment\n");
 
2712
                else
 
2713
                        log (", complete or first fragment\n");
 
2714
 
 
2715
                break;
 
2716
        }
 
2717
 
 
2718
        case PAGE_FUNCTION_DISCARD:
 
2719
        case PAGE_FUNCTION_UNKNOWN:
 
2720
                break;
 
2721
        }
 
2722
 
 
2723
        return TRUE;
 
2724
}
 
2725
 
 
2726
/* 9.4.1 Teletext packet 26, enhancement data. */
 
2727
 
 
2728
static vbi3_bool
 
2729
decode_packet_26                (vbi3_teletext_decoder *        td,
 
2730
                                 cache_page *           cp,
 
2731
                                 const uint8_t          buffer[42])
 
2732
{
 
2733
        int n18[13];
 
2734
        int designation;
 
2735
        int err;
 
2736
        triplet *trip;
 
2737
        unsigned int i;
 
2738
 
 
2739
        switch (cp->function) {
 
2740
        case PAGE_FUNCTION_DISCARD:
 
2741
                return TRUE;
 
2742
 
 
2743
        case PAGE_FUNCTION_GPOP:
 
2744
        case PAGE_FUNCTION_POP:
 
2745
                return decode_pop_packet (cp, buffer + 2, 26);
 
2746
 
 
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);
 
2760
                return FALSE;
 
2761
 
 
2762
        case PAGE_FUNCTION_UNKNOWN:
 
2763
        case PAGE_FUNCTION_LOP:
 
2764
        case PAGE_FUNCTION_TRIGGER:
 
2765
                break;
 
2766
        }
 
2767
 
 
2768
        designation = vbi3_unham8 (buffer[2]);
 
2769
 
 
2770
        err = 0;
 
2771
 
 
2772
        for (i = 0; i < 13; ++i)
 
2773
                err |= n18[i] = vbi3_unham24p (buffer + 3 + i * 3);
 
2774
 
 
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);
 
2778
 
 
2779
                for (i = 1; i < 13; ++i)
 
2780
                        log ("... %u: %d %x\n",
 
2781
                             i, n18[i], n18[i]);
 
2782
        }
 
2783
 
 
2784
        if ((designation | err) < 0) {
 
2785
                return FALSE;
 
2786
        }
 
2787
 
 
2788
#if 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;
 
2794
                return FALSE;
 
2795
        }
 
2796
#endif
 
2797
 
 
2798
        cp->x26_designations |= 1 << designation;
 
2799
 
 
2800
        trip = &cp->data.enh_lop.enh[designation * 13];
 
2801
 
 
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);
 
2806
 
 
2807
                ++trip;
 
2808
        }
 
2809
 
 
2810
        return TRUE;
 
2811
}
 
2812
 
 
2813
/* 9.6 Teletext packet 27, page linking. */
 
2814
 
 
2815
static vbi3_bool
 
2816
decode_packet_27                (vbi3_teletext_decoder *        td,
 
2817
                                 cache_page *           cp,
 
2818
                                 const uint8_t          buffer[42])
 
2819
{
 
2820
        const uint8_t *p;
 
2821
        int designation;
 
2822
 
 
2823
        switch (cp->function) {
 
2824
        case PAGE_FUNCTION_DISCARD:
 
2825
                return TRUE;
 
2826
 
 
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);
 
2843
                return FALSE;
 
2844
 
 
2845
        case PAGE_FUNCTION_UNKNOWN:
 
2846
        case PAGE_FUNCTION_LOP:
 
2847
                break;
 
2848
        }
 
2849
 
 
2850
        if ((designation = vbi3_unham8 (buffer[2])) < 0)
 
2851
                return FALSE;
 
2852
 
 
2853
        log ("Packet X/27/%u page %03x.%x\n",
 
2854
             designation, cp->pgno, cp->subno);
 
2855
 
 
2856
        p = buffer + 3;
 
2857
 
 
2858
        switch (designation) {
 
2859
        case 0:
 
2860
        {
 
2861
                int control;
 
2862
                unsigned int crc;
 
2863
 
 
2864
                if ((control = vbi3_unham8 (buffer[39])) < 0)
 
2865
                        return FALSE;
 
2866
 
 
2867
                log ("... control %02x\n", control);
 
2868
 
 
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. */
 
2874
 
 
2875
                crc = buffer[40] + buffer[41] * 256;
 
2876
 
 
2877
                log ("... crc %04x\n", crc);
 
2878
 
 
2879
                /* ETR 287 section 10.4: Have FLOF, display row 24. */
 
2880
                cp->data.lop.have_flof = control >> 3;
 
2881
 
 
2882
                /* fall through */
 
2883
        }
 
2884
 
 
2885
        case 1 ... 3:
 
2886
        {
 
2887
                unsigned int i;
 
2888
 
 
2889
                /* X/27/0 ... 4 */
 
2890
 
 
2891
                for (i = 0; i < 6; ++i) {
 
2892
                        pagenum *pn;
 
2893
 
 
2894
                        pn = &cp->data.lop.link[designation * 6 + i];
 
2895
 
 
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);
 
2900
                        p += 6;
 
2901
 
 
2902
                        log ("... link[%u] = %03x.%04x\n",
 
2903
                             i, pn->pgno, pn->subno);
 
2904
                }
 
2905
 
 
2906
                cp->x27_designations |= 1 << designation;
 
2907
 
 
2908
                break;
 
2909
        }
 
2910
 
 
2911
        case 4 ... 7:
 
2912
        {
 
2913
                unsigned int i;
 
2914
 
 
2915
                /* X/27/4 ... 7 */
 
2916
 
 
2917
                /* (Never observed this in the field;
 
2918
                    let's hope the code is correct.) */
 
2919
 
 
2920
                for (i = 0; i < 6; ++i) {
 
2921
                        pagenum *pn;
 
2922
                        int t1, t2;
 
2923
 
 
2924
                        t1 = vbi3_unham24p (p + 0);
 
2925
                        t2 = vbi3_unham24p (p + 3);
 
2926
 
 
2927
                        if ((t1 | t2) < 0)
 
2928
                                break;
 
2929
 
 
2930
                        p += 6;
 
2931
 
 
2932
                        if (designation <= 5 && (t1 & (1 << 10))) {
 
2933
                                unsigned int mag0;
 
2934
                                unsigned int validity;
 
2935
                                
 
2936
                                /* 9.6.2 Packets X/27/4 and X/27/5 format 1. */
 
2937
 
 
2938
                                /* t1: tt ttmmm1uu uuxxvvff */
 
2939
                                /* t2: ss ssssssss ssssssx0 */
 
2940
 
 
2941
                                pn = &cp->data.lop.link[designation * 6 + i];
 
2942
 
 
2943
                                /* GPOP, POP, GDRCS, DRCS */
 
2944
                                pn->function = PAGE_FUNCTION_GPOP + (t1 & 3);
 
2945
 
 
2946
                                validity = (t1 >> 2) & 3;
 
2947
 
 
2948
                                mag0 = (cp->pgno ^ (t1 >> 3)) & 0x700;
 
2949
 
 
2950
                                pn->pgno = ((0 == mag0) ? 0x800 : mag0)
 
2951
                                        + (t1 >> 10)
 
2952
                                        + ((t1 >> 6) & 0x00F);
 
2953
 
 
2954
                                /* NB this is "set of required subpages",
 
2955
                                   not a real subno. */
 
2956
                                pn->subno = t2 >> 2;
 
2957
 
 
2958
                                log ("... link[%u] = %s %x/%x\n",
 
2959
                                     i, page_function_name (pn->function),
 
2960
                                     pn->pgno, pn->subno);
 
2961
 
 
2962
                                /* XXX
 
2963
 
 
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." */
 
2975
                        } else {
 
2976
                                /* 9.6.3 Packets X/27/4 to X/27/7 format 2 -
 
2977
                                   compositional linking in data broadcasting
 
2978
                                   applications. */
 
2979
 
 
2980
                                /* Ignored. */
 
2981
                        }
 
2982
                }
 
2983
 
 
2984
                cp->x27_designations |= 1 << designation;
 
2985
 
 
2986
                break;
 
2987
        }
 
2988
 
 
2989
        case 8 ... 15:
 
2990
                /* Undefined, ignored. */
 
2991
                break;
 
2992
        }
 
2993
 
 
2994
        return TRUE;
 
2995
}
 
2996
 
 
2997
/*
 
2998
        9.4.2, 9.4.3, 9.5 Teletext packets 28 and 29,
 
2999
        Level 2.5/3.5 enhancement.
 
3000
*/
 
3001
 
 
3002
struct bit_stream {
 
3003
        int *                   triplet;
 
3004
        unsigned int            buffer;
 
3005
        unsigned int            left;
 
3006
};
 
3007
 
 
3008
static unsigned int
 
3009
get_bits                        (struct bit_stream *    bs,
 
3010
                                 unsigned int           count)
 
3011
{
 
3012
        unsigned int r;
 
3013
        int n;
 
3014
 
 
3015
        r = bs->buffer;
 
3016
        n = count - bs->left;
 
3017
 
 
3018
        if (n > 0) {
 
3019
                bs->buffer = *(bs->triplet)++;
 
3020
                r |= bs->buffer << bs->left;
 
3021
                bs->left = 18 - n;
 
3022
        } else {
 
3023
                n = count;
 
3024
                bs->left -= count;
 
3025
        }
 
3026
 
 
3027
        bs->buffer >>= n;
 
3028
 
 
3029
        return r & ((1UL << count) - 1);
 
3030
}
 
3031
 
 
3032
static vbi3_bool
 
3033
decode_packet_28_29             (vbi3_teletext_decoder *        td,
 
3034
                                 cache_page *           cp,
 
3035
                                 const uint8_t          buffer[42],
 
3036
                                 unsigned int           packet)
 
3037
{
 
3038
        const uint8_t *p;
 
3039
        int designation;
 
3040
        int n18[13];
 
3041
        struct bit_stream bs;
 
3042
        extension *ext;
 
3043
        unsigned int i;
 
3044
        unsigned int j;
 
3045
        int err;
 
3046
 
 
3047
        switch (cp->function) {
 
3048
        case PAGE_FUNCTION_DISCARD:
 
3049
                return TRUE;
 
3050
 
 
3051
        default:
 
3052
                break;
 
3053
        }
 
3054
 
 
3055
        p = buffer + 2;
 
3056
 
 
3057
        if ((designation = vbi3_unham8 (*p++)) < 0)
 
3058
                return FALSE;
 
3059
 
 
3060
        log ("Packet %u/%u/%u page %03x.%x\n",
 
3061
             (cp->pgno >> 8) & 7, packet, designation,
 
3062
             cp->pgno, cp->subno);
 
3063
 
 
3064
        err = 0;
 
3065
 
 
3066
        for (i = 0; i < 13; ++i) {
 
3067
                err |= n18[i] = vbi3_unham24p (p);
 
3068
                p += 3;
 
3069
        }
 
3070
 
 
3071
        bs.triplet = n18;
 
3072
        bs.buffer = 0;
 
3073
        bs.left = 0;
 
3074
 
 
3075
        switch (designation) {
 
3076
        case 0:
 
3077
        {
 
3078
                /* X/28/0, M/29/0 Level 2.5 */
 
3079
 
 
3080
                if (n18[0] < 0)
 
3081
                        return FALSE;
 
3082
 
 
3083
                if (28 == packet) {
 
3084
                        /*
 
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)
 
3095
 
 
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,
 
3099
                              9.4.2.2)
 
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)
 
3106
                           e), f) same as d)
 
3107
                           g) observed on SWR with cccffff != 0, in violation
 
3108
                              of c).
 
3109
                           h) observed on ARTE, transmitted with various
 
3110
                              level one pages. Apparently not format 1 or 2.
 
3111
 
 
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).
 
3114
                        */
 
3115
 
 
3116
                        if (0 == (n18[0] & 0x3F00)
 
3117
                            && 0 != (n18[0] & 0x7F)) {
 
3118
                                unsigned int i;
 
3119
 
 
3120
                                log ("... format 2 ignored.\n");
 
3121
 
 
3122
                                if (0) {
 
3123
                                        for (i = 0; i < 40; ++i)
 
3124
                                                fprintf (stderr, "%02x ",
 
3125
                                                         buffer[2 + i]);
 
3126
                                        fputc ('\n', stderr);
 
3127
 
 
3128
                                        for (i = 0; i < 13; ++i)
 
3129
                                                fprintf (stderr, "%05x ",
 
3130
                                                         n18[i]);
 
3131
                                        fputc ('\n', stderr);
 
3132
                                }
 
3133
 
 
3134
                                break;
 
3135
                        }
 
3136
                }
 
3137
 
 
3138
                /* fall through */
 
3139
        }
 
3140
 
 
3141
        case 4:
 
3142
        {
 
3143
                page_function function;
 
3144
                page_coding coding;
 
3145
 
 
3146
                /* X/28/0, M/29/0 Level 2.5 */
 
3147
                /* X/28/4, M/29/4 Level 3.5 */
 
3148
 
 
3149
                if (n18[0] < 0)
 
3150
                        return FALSE;
 
3151
 
 
3152
                function = get_bits (&bs, 4);
 
3153
                coding = get_bits (&bs, 3);
 
3154
 
 
3155
                log ("... %s, %s\n",
 
3156
                     page_function_name (function),
 
3157
                     page_coding_name (coding));
 
3158
 
 
3159
                if (function > PAGE_FUNCTION_TRIGGER
 
3160
                    || coding > PAGE_CODING_META84)
 
3161
                        break; /* undefined */
 
3162
 
 
3163
                if (28 == packet) {
 
3164
                        if (PAGE_FUNCTION_UNKNOWN == cp->function) {
 
3165
                                switch (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");
 
3172
 
 
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
 
3178
                                           trust function. */
 
3179
                                        break;
 
3180
 
 
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;
 
3189
                                        break;
 
3190
 
 
3191
                                case PAGE_FUNCTION_GPOP:
 
3192
                                case PAGE_FUNCTION_POP:
 
3193
                                {
 
3194
                                        cache_page temp;
 
3195
 
 
3196
                                        cache_page_copy (&temp, cp);
 
3197
                                        convert_pop_page (cp, &temp, function);
 
3198
 
 
3199
                                        break;
 
3200
                                }
 
3201
 
 
3202
                                case PAGE_FUNCTION_GDRCS:
 
3203
                                case PAGE_FUNCTION_DRCS:
 
3204
                                {
 
3205
                                        unsigned int i;
 
3206
 
 
3207
                                        /* See comments in decode_packet_0. */
 
3208
                                        for (i= 0; i < DRCS_PTUS_PER_PAGE; ++i)
 
3209
                                                cp->data.drcs.mode[i] =
 
3210
                                                        DRCS_MODE_12_10_1;
 
3211
 
 
3212
                                        cp->function = function;
 
3213
 
 
3214
                                        break;
 
3215
                                }
 
3216
 
 
3217
                                case PAGE_FUNCTION_AIT:
 
3218
                                {
 
3219
                                        cache_page temp;
 
3220
 
 
3221
                                        cache_page_copy (&temp, cp);
 
3222
                                        convert_ait_page (cp, &temp);
 
3223
 
 
3224
                                        break;
 
3225
                                }
 
3226
                                }
 
3227
                        } else if (function != cp->function) {
 
3228
                                /* Who's wrong here? */
 
3229
                                cp->function = PAGE_FUNCTION_DISCARD;
 
3230
                                return FALSE;
 
3231
                        }
 
3232
 
 
3233
                        /* 9.4.2.2: Rest of packet applies to LOP only. */
 
3234
                        if (PAGE_FUNCTION_LOP != function)
 
3235
                                break;
 
3236
 
 
3237
                        /* All remaining triplets must be correct. */
 
3238
                        if (err < 0)
 
3239
                                return FALSE;
 
3240
 
 
3241
                        ext = &cp->data.ext_lop.ext;
 
3242
 
 
3243
                        cp->x28_designations |= 1 << designation;
 
3244
                } else {
 
3245
                        /* 9.5.1: Rest of packet applies if zero. */
 
3246
                        if (function | coding)
 
3247
                                break;
 
3248
 
 
3249
                        if (err < 0)
 
3250
                                return FALSE;
 
3251
 
 
3252
                        ext = &cache_network_magazine (td->network, cp->pgno)
 
3253
                                ->extension;
 
3254
                }
 
3255
 
 
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);
 
3262
                } else {
 
3263
                        unsigned int left_panel;
 
3264
                        unsigned int right_panel;
 
3265
                        unsigned int left_columns;
 
3266
 
 
3267
                        ext->charset_code[0] = get_bits (&bs, 7);
 
3268
                        ext->charset_code[1] = get_bits (&bs, 7);
 
3269
 
 
3270
                        left_panel = get_bits (&bs, 1);
 
3271
                        right_panel = get_bits (&bs, 1);
 
3272
 
 
3273
                        /* 0 - panels required at Level 3.5 only,
 
3274
                           1 - at 2.5 and 3.5
 
3275
                           ignored. */
 
3276
                        get_bits (&bs, 1);
 
3277
 
 
3278
                        left_columns = get_bits (&bs, 4);
 
3279
 
 
3280
                        if (left_panel && 0 == left_columns)
 
3281
                                left_columns = 16;
 
3282
 
 
3283
                        ext->fallback.left_panel_columns =
 
3284
                                left_columns & -left_panel;
 
3285
                        ext->fallback.right_panel_columns =
 
3286
                                (16 - left_columns) & -right_panel;
 
3287
                }
 
3288
 
 
3289
                /* Color map for CLUTs 0 & 1 (desig. 4) or 2 & 3. */
 
3290
 
 
3291
                j = (4 == designation) ? 16 : 32;
 
3292
 
 
3293
                for (i = j - 16; i < j; ++i) {
 
3294
                        vbi3_rgba col = get_bits (&bs, 12);
 
3295
 
 
3296
                        if (8 == i) /* transparent */
 
3297
                                continue;
 
3298
 
 
3299
                        col = VBI3_RGBA ((col     ) & 15,
 
3300
                                        (col >> 4) & 15,
 
3301
                                        (col >> 8));
 
3302
 
 
3303
                        ext->color_map[i] = col | (col << 4);
 
3304
                }
 
3305
 
 
3306
                /* libzvbi private, invariable. */
 
3307
                memcpy (ext->color_map + 32, default_color_map + 32,
 
3308
                        8 * sizeof (*ext->color_map));
 
3309
 
 
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);
 
3316
                } else {
 
3317
                        ext->def_screen_color = get_bits (&bs, 5);
 
3318
                        ext->def_row_color = get_bits (&bs, 5);
 
3319
 
 
3320
                        ext->fallback.black_bg_substitution =
 
3321
                                get_bits (&bs, 1);
 
3322
 
 
3323
                        i = get_bits (&bs, 3); /* color table remapping */
 
3324
 
 
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];
 
3327
                }
 
3328
 
 
3329
                ext->designations |= 1 << designation;
 
3330
 
 
3331
                if (0)
 
3332
                        extension_dump (ext, stderr);
 
3333
 
 
3334
                break;
 
3335
        }
 
3336
 
 
3337
        case 1: /* X/28/1, M/29/1 Level 3.5 DRCS CLUT */
 
3338
        {
 
3339
                if (err < 0)
 
3340
                        return FALSE;
 
3341
 
 
3342
                if (28 == packet) {
 
3343
                        ext = &cp->data.ext_lop.ext;
 
3344
 
 
3345
                        cp->x28_designations |= 1 << 1;
 
3346
                } else {
 
3347
                        ext = &cache_network_magazine (td->network, cp->pgno)
 
3348
                                ->extension;
 
3349
                }
 
3350
 
 
3351
                /* 9.4.4: "Compatibility, not for Level 2.5/3.5 decoders."
 
3352
                   No more details, so we ignore this triplet. */
 
3353
                ++bs.triplet;
 
3354
 
 
3355
                for (i = 0; i < 8; ++i)
 
3356
                        ext->drcs_clut[i + 2] =
 
3357
                                vbi3_rev8 (get_bits (&bs, 5)) >> 3;
 
3358
 
 
3359
                for (i = 0; i < 32; ++i)
 
3360
                        ext->drcs_clut[i + 10] =
 
3361
                                vbi3_rev8 (get_bits (&bs, 5)) >> 3;
 
3362
 
 
3363
                ext->designations |= 1 << 1;
 
3364
 
 
3365
                break;
 
3366
        }
 
3367
 
 
3368
        case 2:
 
3369
        {
 
3370
                /* CA key packet ignored. */
 
3371
 
 
3372
                break;
 
3373
        }
 
3374
 
 
3375
        case 3:
 
3376
        {
 
3377
                page_function function;
 
3378
                page_coding coding;
 
3379
 
 
3380
                /* X/28/3 Level 3.5 DRCS download page modes */
 
3381
 
 
3382
                if (29 == packet)
 
3383
                        break; /* M/29/3 undefined */
 
3384
 
 
3385
                if (n18[0] < 0)
 
3386
                        return FALSE;
 
3387
 
 
3388
                cp->x28_designations |= 1 << 3;
 
3389
 
 
3390
                function = get_bits (&bs, 4);
 
3391
                coding = get_bits (&bs, 3);
 
3392
 
 
3393
                log ("... %s, %s\n",
 
3394
                     page_function_name (function),
 
3395
                     page_coding_name (coding));
 
3396
 
 
3397
                if (PAGE_FUNCTION_GDRCS != function
 
3398
                    && PAGE_FUNCTION_DRCS != function)
 
3399
                        break; /* undefined */
 
3400
 
 
3401
                if (err < 0)
 
3402
                        return FALSE;
 
3403
 
 
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;
 
3409
                        return FALSE;
 
3410
                }
 
3411
 
 
3412
                get_bits (&bs, 11); /* reserved */
 
3413
 
 
3414
                for (i = 0; i < 48; ++i)
 
3415
                        cp->data.drcs.mode[i] = get_bits (&bs, 4);
 
3416
 
 
3417
                /* Rest reserved. */
 
3418
 
 
3419
                break;
 
3420
        }
 
3421
 
 
3422
        case 5 ... 15:
 
3423
                /* Undefined, ignored. */
 
3424
 
 
3425
                break;
 
3426
        }
 
3427
 
 
3428
        return TRUE;
 
3429
}
 
3430
 
 
3431
/* 9.8 Teletext packet 8/30, broadcast service data. */
 
3432
 
 
3433
static void
 
3434
cni_change                      (vbi3_teletext_decoder *        td,
 
3435
                                 vbi3_cni_type          type,
 
3436
                                 unsigned int           cni,
 
3437
                                 double                 timeout_min)
 
3438
{
 
3439
        cache_network *cn;
 
3440
        double timeout;
 
3441
 
 
3442
        cn = td->network;
 
3443
        timeout = 0.0;
 
3444
 
 
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.
 
3454
 
 
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;
 
3460
        }
 
3461
 
 
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;
 
3468
        }
 
3469
 
 
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;
 
3476
        }
 
3477
 
 
3478
        if (timeout > 0.0) {
 
3479
                td->virtual_reset (td, NULL,
 
3480
                                   td->time + MAX (timeout, timeout_min));
 
3481
        }
 
3482
}
 
3483
 
 
3484
static vbi3_bool
 
3485
status_change                   (vbi3_teletext_decoder *        td,
 
3486
                                 const uint8_t          buffer[42])
 
3487
{
 
3488
        const vbi3_character_set *cs;
 
3489
        cache_network *cn;
 
3490
        char *title;
 
3491
        vbi3_event e;
 
3492
 
 
3493
        cs = vbi3_character_set_from_code (0); /* XXX ok? */
 
3494
        title = _vbi3_strdup_locale_teletext (buffer + 22, 20, cs);
 
3495
 
 
3496
        if (!title)
 
3497
                return FALSE;
 
3498
 
 
3499
#ifndef ZAPPING8
 
3500
        cn = td->network;
 
3501
 
 
3502
        vbi3_free (cn->program_info.title);
 
3503
        cn->program_info.title = title;
 
3504
 
 
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;
 
3509
 
 
3510
        _vbi3_event_handler_list_send (&td->handlers, &e);
 
3511
#endif
 
3512
 
 
3513
        return TRUE;
 
3514
}
 
3515
 
 
3516
static vbi3_bool
 
3517
decode_packet_8_30              (vbi3_teletext_decoder *        td,
 
3518
                                 const uint8_t          buffer[42])
 
3519
{
 
3520
        int designation;
 
3521
 
 
3522
        if ((designation = vbi3_unham8 (buffer[2])) < 0)
 
3523
                return FALSE;
 
3524
 
 
3525
        log ("Packet 8/30/%d\n", designation);
 
3526
 
 
3527
        if (designation > 4)
 
3528
                return TRUE; /* undefined, ignored */
 
3529
 
 
3530
        if (td->reset_time <= 0.0) {
 
3531
                if (td->handlers.event_mask & VBI3_EVENT_TTX_PAGE) {
 
3532
                        pagenum pn;
 
3533
 
 
3534
                        if (!unham8_page_number (&pn, buffer + 3, 0))
 
3535
                                return FALSE;
 
3536
 
 
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;
 
3541
                        }
 
3542
                }
 
3543
 
 
3544
                if (td->handlers.event_mask & VBI3_EVENT_PROG_INFO) {
 
3545
                        uint8_t *s;
 
3546
                        unsigned int i;
 
3547
                        int err;
 
3548
 
 
3549
                        err = 0;
 
3550
 
 
3551
                        for (i = 0; i < 20; ++i) {
 
3552
                                err |= vbi3_unpar8 (buffer[i + 22]);
 
3553
 
 
3554
                                if (0) {
 
3555
                                        int c = buffer[i + 22];
 
3556
 
 
3557
                                        fprintf (stderr, "%2u %02x %02x %c\n",
 
3558
                                                 i,
 
3559
                                                 td->network->status[i],
 
3560
                                                 c & 0x7F,
 
3561
                                                 vbi3_printable (c));
 
3562
                                }
 
3563
                        }
 
3564
 
 
3565
                        if (err < 0)
 
3566
                                return FALSE;
 
3567
 
 
3568
                        assert (20 == sizeof (td->network->status));
 
3569
 
 
3570
                        s = td->network->status;
 
3571
 
 
3572
                        if (0 != memcmp (s, buffer + 22, 20)) {
 
3573
                                if (status_change (td, buffer))
 
3574
                                        memcpy (s, buffer + 22, 20);
 
3575
                        }
 
3576
                }
 
3577
        }
 
3578
 
 
3579
        if (designation < 2) {
 
3580
                unsigned int cni;
 
3581
                cache_network *cn;
 
3582
 
 
3583
                /* 8/30 format 1 */
 
3584
 
 
3585
                if (!vbi3_decode_teletext_8301_cni (&cni, buffer))
 
3586
                        return FALSE;
 
3587
 
 
3588
                cn = td->network;
 
3589
 
 
3590
                if (0 == cni) {
 
3591
                        /* Should probably ignore this. */
 
3592
                } else if (cni == cn->network.cni_8301) {
 
3593
                        /* No CNI change, no channel change. */
 
3594
 
 
3595
                        cn->confirm_cni_8301 = 0;
 
3596
 
 
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);
 
3601
                        }
 
3602
                } else if (cni == cn->confirm_cni_8301) {
 
3603
                        /* The CNI is correct. */
 
3604
 
 
3605
                        if (0 == cn->network.cni_8301) {
 
3606
                                /* First CNI, assume no channel change. */
 
3607
 
 
3608
                                vbi3_network_set_cni
 
3609
                                        (&cn->network, VBI3_CNI_TYPE_8301, cni);
 
3610
 
 
3611
                                cn->confirm_cni_8301 = 0;
 
3612
 
 
3613
                                if (0 == cn->confirm_cni_vps
 
3614
                                    && 0 == cn->confirm_cni_8302) {
 
3615
                                        /* All CNIs valid, cancel reset
 
3616
                                           requests. */
 
3617
                                        td->virtual_reset (td, NULL, -1.0);
 
3618
                                }
 
3619
                        } else {
 
3620
                                vbi3_network nk;
 
3621
                                cache_network *cn;
 
3622
 
 
3623
                                /* Different CNI, channel change detected. */
 
3624
 
 
3625
                                vbi3_network_init (&nk);
 
3626
                                vbi3_network_set_cni (&nk, VBI3_CNI_TYPE_8301,
 
3627
                                                     cni);
 
3628
 
 
3629
                                cn = _vbi3_cache_add_network
 
3630
                                        (td->cache, &nk, td->videostd_set);
 
3631
 
 
3632
                                td->virtual_reset (td, cn, 0.0 /* now */);
 
3633
 
 
3634
                                cache_network_unref (cn);
 
3635
 
 
3636
                                vbi3_network_destroy (&nk);
 
3637
                        }
 
3638
 
 
3639
                        network_event (td);
 
3640
                } else {
 
3641
                        /* The packet 8/30 format 1 CNI is poorly error
 
3642
                           protected. We accept this CNI after receiving it
 
3643
                           twice in a row. */
 
3644
                        cn->confirm_cni_8301 = cni;
 
3645
 
 
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);
 
3650
                        } else {
 
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);
 
3656
                        }
 
3657
                }
 
3658
 
 
3659
                if (td->handlers.event_mask & VBI3_EVENT_LOCAL_TIME) {
 
3660
                        vbi3_event e;
 
3661
 
 
3662
                        if (!vbi3_decode_teletext_8301_local_time
 
3663
                            (&e.ev.local_time.time,
 
3664
                             &e.ev.local_time.gmtoff,
 
3665
                             buffer))
 
3666
                                return FALSE;
 
3667
 
 
3668
                        e.type          = VBI3_EVENT_LOCAL_TIME;
 
3669
                        e.network       = &td->network->network;
 
3670
                        e.timestamp     = td->time;
 
3671
 
 
3672
                        _vbi3_event_handler_list_send (&td->handlers, &e);
 
3673
                }
 
3674
        } else {
 
3675
                unsigned int cni;
 
3676
                cache_network *cn;
 
3677
 
 
3678
                /* 8/30 format 2 */
 
3679
 
 
3680
                if (!vbi3_decode_teletext_8302_cni (&cni, buffer))
 
3681
                        return FALSE;
 
3682
 
 
3683
                cn = td->network;
 
3684
 
 
3685
                if (0 == cni) {
 
3686
                        /* Should probably ignore this. */
 
3687
                } else if (cni == cn->network.cni_8302) {
 
3688
                        /* No CNI change, no channel change. */
 
3689
 
 
3690
                        cn->confirm_cni_8302 = 0; /* confirmed */
 
3691
 
 
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);
 
3696
                        }
 
3697
                } else {
 
3698
                        if (0 == cn->network.cni_8302) {
 
3699
                                /* First CNI, channel change possible. */
 
3700
 
 
3701
                                vbi3_network_set_cni
 
3702
                                        (&cn->network, VBI3_CNI_TYPE_8302, cni);
 
3703
 
 
3704
                                cn->confirm_cni_8302 = 0;
 
3705
 
 
3706
                                cni_change (td, VBI3_CNI_TYPE_8302, cni, 0.0);
 
3707
 
 
3708
                                if (0 == cn->confirm_cni_vps
 
3709
                                    && 0 == cn->confirm_cni_8301) {
 
3710
                                        /* All CNIs valid, cancel reset
 
3711
                                           requests. */
 
3712
                                        td->virtual_reset (td, NULL, -1.0);
 
3713
                                }
 
3714
                        } else {
 
3715
                                vbi3_network nk;
 
3716
                                cache_network *cn;
 
3717
 
 
3718
                                /* Different CNI, channel change detected. */
 
3719
 
 
3720
                                vbi3_network_init (&nk);
 
3721
                                vbi3_network_set_cni (&nk,
 
3722
                                                     VBI3_CNI_TYPE_8302, cni);
 
3723
 
 
3724
                                cn = _vbi3_cache_add_network
 
3725
                                        (td->cache, &nk, td->videostd_set);
 
3726
 
 
3727
                                td->virtual_reset (td, cn, 0.0 /* now */);
 
3728
 
 
3729
                                cache_network_unref (cn);
 
3730
 
 
3731
                                vbi3_network_destroy (&nk);
 
3732
                        }
 
3733
 
 
3734
                        network_event (td);
 
3735
                }
 
3736
 
 
3737
#ifndef ZAPPING8
 
3738
                if (td->handlers.event_mask & VBI3_EVENT_PROG_ID) {
 
3739
                        vbi3_program_id pid;
 
3740
                        vbi3_program_id *p;
 
3741
                        
 
3742
                        if (!vbi3_decode_teletext_8302_pdc (&pid, buffer))
 
3743
                                return FALSE;
 
3744
 
 
3745
                        p = &td->network->program_id[pid.channel];
 
3746
 
 
3747
                        if (p->cni != pid.cni
 
3748
                            || p->pil != pid.pil
 
3749
                            || ((p->luf ^ pid.luf) |
 
3750
                                (p->mi ^ pid.mi) |
 
3751
                                (p->prf ^ pid.prf))
 
3752
                            || p->pcs_audio != pid.pcs_audio
 
3753
                            || p->pty != pid.pty) {
 
3754
                                vbi3_event e;
 
3755
 
 
3756
                                *p = pid;
 
3757
 
 
3758
                                e.type          = VBI3_EVENT_PROG_ID;
 
3759
                                e.network       = &td->network->network;
 
3760
                                e.timestamp     = td->time;
 
3761
                                e.ev.prog_id    = p;
 
3762
 
 
3763
                                _vbi3_event_handler_list_send
 
3764
                                        (&td->handlers, &e);
 
3765
                        }
 
3766
                }
 
3767
#endif /* !ZAPPING8 */
 
3768
        }
 
3769
 
 
3770
        return TRUE;
 
3771
}
 
3772
 
 
3773
/**
 
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
 
3778
 *   was captured.
 
3779
 * 
 
3780
 * Decodes a teletext packet and update the decoder state.
 
3781
 * 
 
3782
 * Return value:
 
3783
 * @c FALSE if the packet contained incorrectable errors. 
 
3784
 */
 
3785
vbi3_bool
 
3786
vbi3_teletext_decoder_decode    (vbi3_teletext_decoder *        td,
 
3787
                                 const uint8_t          buffer[42],
 
3788
                                 double                 timestamp)
 
3789
{
 
3790
        cache_page *cp;
 
3791
        int pmag;
 
3792
        int mag0;
 
3793
        int packet;
 
3794
 
 
3795
        td->time = timestamp;
 
3796
 
 
3797
        if (td->reset_time > 0
 
3798
            && timestamp >= td->reset_time) {
 
3799
                cache_network *cn;
 
3800
                vbi3_event e;
 
3801
 
 
3802
                /* Deferred reset. */
 
3803
 
 
3804
                cn = _vbi3_cache_add_network
 
3805
                        (td->cache, NULL, td->videostd_set);
 
3806
 
 
3807
                td->virtual_reset (td, cn, 0.0 /* now */);
 
3808
                cache_network_unref (cn);
 
3809
 
 
3810
                network_event (td);
 
3811
        }
 
3812
 
 
3813
        if ((pmag = vbi3_unham16p (buffer)) < 0)
 
3814
                return FALSE;
 
3815
 
 
3816
        mag0 = pmag & 7;
 
3817
        packet = pmag >> 3;
 
3818
 
 
3819
        cp = &td->buffer[mag0];
 
3820
 
 
3821
        if (0) {
 
3822
                unsigned int i;
 
3823
 
 
3824
                fprintf (stderr, "packet %xxx %d >",
 
3825
                         (0 == mag0) ? 8 : mag0, packet);
 
3826
 
 
3827
                for (i = 0; i < 40; i++)
 
3828
                        fputc (vbi3_printable (buffer[2 + i]), stderr);
 
3829
 
 
3830
                fprintf (stderr, "<\n");
 
3831
        }
 
3832
 
 
3833
        if (packet < 30
 
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)))
 
3839
                return TRUE;
 
3840
 
 
3841
        switch (packet) {
 
3842
        case 0:
 
3843
                /* Page header. */
 
3844
                return decode_packet_0 (td, cp, buffer, (unsigned int) mag0);
 
3845
 
 
3846
        case 1 ... 25:
 
3847
                /* Page body. */
 
3848
                switch (cp->function) {
 
3849
                case PAGE_FUNCTION_DISCARD:
 
3850
                        return TRUE;
 
3851
 
 
3852
                case PAGE_FUNCTION_GPOP:
 
3853
                case PAGE_FUNCTION_POP:
 
3854
                        if (!decode_pop_packet (cp, buffer + 2,
 
3855
                                                (unsigned int) packet))
 
3856
                                return FALSE;
 
3857
                        break;
 
3858
 
 
3859
                case PAGE_FUNCTION_GDRCS:
 
3860
                case PAGE_FUNCTION_DRCS:
 
3861
                        memcpy (cp->data.drcs.lop.raw[packet],
 
3862
                                buffer + 2, 40);
 
3863
                        break;
 
3864
 
 
3865
                case PAGE_FUNCTION_AIT:
 
3866
                        if (!(decode_ait_packet (cp, buffer + 2,
 
3867
                                                 (unsigned int) packet)))
 
3868
                                return FALSE;
 
3869
                        break;
 
3870
 
 
3871
                case PAGE_FUNCTION_EPG:
 
3872
                        // TODO
 
3873
                        return TRUE;
 
3874
 
 
3875
                case PAGE_FUNCTION_LOP:
 
3876
                case PAGE_FUNCTION_TRIGGER:
 
3877
                {
 
3878
                        unsigned int i;
 
3879
                        int err;
 
3880
 
 
3881
                        err = 0;
 
3882
 
 
3883
                        for (i = 0; i < 40; ++i)
 
3884
                                err |= vbi3_unpar8 (buffer[2 + i]);
 
3885
 
 
3886
                        if (err < 0)
 
3887
                                return FALSE;
 
3888
 
 
3889
                        memcpy (cp->data.unknown.raw[packet], buffer + 2, 40);
 
3890
 
 
3891
                        break;
 
3892
                }
 
3893
 
 
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:
 
3899
                default:
 
3900
                        memcpy (cp->data.unknown.raw[packet], buffer + 2, 40);
 
3901
                        break;
 
3902
                }
 
3903
 
 
3904
                cp->lop_packets |= 1 << packet;
 
3905
 
 
3906
                break;
 
3907
 
 
3908
        case 26:
 
3909
                /* Page enhancement packet. */
 
3910
                return decode_packet_26 (td, cp, buffer);
 
3911
 
 
3912
        case 27:
 
3913
                /* Page linking. */
 
3914
                return decode_packet_27 (td, cp, buffer);
 
3915
 
 
3916
        case 28:
 
3917
        case 29:
 
3918
                /* Level 2.5/3.5 enhancement. */
 
3919
                return decode_packet_28_29 (td, cp, buffer,
 
3920
                                            (unsigned int) packet);
 
3921
 
 
3922
        case 30:
 
3923
        case 31:
 
3924
        {
 
3925
                unsigned int channel;
 
3926
 
 
3927
                /* IDL packet (ETS 300 708). */
 
3928
 
 
3929
                channel = pmag & 15;
 
3930
 
 
3931
                switch (channel) {
 
3932
                case 0:
 
3933
                        return decode_packet_8_30 (td, buffer);
 
3934
 
 
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 */
 
3943
 
 
3944
                default:
 
3945
                        log ("IDL %u\n", channel);
 
3946
                        break;
 
3947
                }
 
3948
 
 
3949
                break;
 
3950
        }
 
3951
 
 
3952
        default:
 
3953
                assert (!"reached");
 
3954
        }
 
3955
 
 
3956
        return TRUE;
 
3957
}
 
3958
 
 
3959
/**
 
3960
 * DOCUMENT ME
 
3961
 */
 
3962
vbi3_search *
 
3963
vbi3_teletext_decoder_search_utf8_new
 
3964
                                (vbi3_teletext_decoder *td,
 
3965
                                 const vbi3_network *   nk,
 
3966
                                 vbi3_pgno              pgno,
 
3967
                                 vbi3_subno             subno,
 
3968
                                 const char *           pattern,
 
3969
                                 vbi3_bool              casefold,
 
3970
                                 vbi3_bool              regexp,
 
3971
                                 vbi3_search_progress_cb *progress,
 
3972
                                 void *                 user_data)
 
3973
{
 
3974
        assert (NULL != td);
 
3975
 
 
3976
        if (NULL == nk) {
 
3977
                if (!td->network)
 
3978
                        return NULL;
 
3979
 
 
3980
                nk = &td->network->network;
 
3981
        }
 
3982
 
 
3983
/* XXX s/nk/cn ? */
 
3984
        return vbi3_search_utf8_new (td->cache,
 
3985
                                     nk, pgno, subno,
 
3986
                                     pattern,
 
3987
                                     casefold, regexp,
 
3988
                                     progress, user_data);
 
3989
}
 
3990
 
 
3991
/**
 
3992
 * DOCUMENT ME
 
3993
 */
 
3994
vbi3_bool
 
3995
vbi3_teletext_decoder_get_top_title
 
3996
                                (vbi3_teletext_decoder *        td,
 
3997
                                 vbi3_top_title *       tt,
 
3998
                                 const vbi3_network *   nk,
 
3999
                                 vbi3_pgno              pgno,
 
4000
                                 vbi3_subno             subno)
 
4001
{
 
4002
        cache_network *cn;
 
4003
        vbi3_bool r;
 
4004
 
 
4005
        assert (NULL != td);
 
4006
        assert (NULL != tt);
 
4007
 
 
4008
        if (nk) {
 
4009
                if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
 
4010
                        return FALSE;
 
4011
        } else {
 
4012
                /* Current network. */
 
4013
                cn = td->network;
 
4014
        }
 
4015
 
 
4016
        r = cache_network_get_top_title (cn, tt, pgno, subno);
 
4017
 
 
4018
        if (nk)
 
4019
                cache_network_unref (cn);
 
4020
 
 
4021
        return r;
 
4022
}
 
4023
 
 
4024
/**
 
4025
 * DOCUMENT ME
 
4026
 */
 
4027
vbi3_top_title *
 
4028
vbi3_teletext_decoder_get_top_titles
 
4029
                                (vbi3_teletext_decoder *        td,
 
4030
                                 const vbi3_network *   nk,
 
4031
                                 unsigned int *         n_elements)
 
4032
{
 
4033
        cache_network *cn;
 
4034
        vbi3_top_title *tt;
 
4035
 
 
4036
        assert (NULL != td);
 
4037
        assert (NULL != n_elements);
 
4038
 
 
4039
        *n_elements = 0;
 
4040
 
 
4041
        if (nk) {
 
4042
                if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
 
4043
                        return FALSE;
 
4044
        } else {
 
4045
                /* Current network. */
 
4046
                cn = td->network;
 
4047
        }
 
4048
 
 
4049
        tt = cache_network_get_top_titles (cn, n_elements);
 
4050
 
 
4051
        if (nk)
 
4052
                cache_network_unref (cn);
 
4053
 
 
4054
        return tt;
 
4055
}
 
4056
 
 
4057
/**
 
4058
 * DOCUMENT ME
 
4059
 */
 
4060
vbi3_bool
 
4061
vbi3_teletext_decoder_get_ttx_page_stat
 
4062
                                (vbi3_teletext_decoder *        td,
 
4063
                                 vbi3_ttx_page_stat *   ps,
 
4064
                                 const vbi3_network *   nk,
 
4065
                                 vbi3_pgno              pgno)
 
4066
{
 
4067
        cache_network *cn;
 
4068
 
 
4069
        assert (NULL != td);
 
4070
        assert (NULL != ps);
 
4071
 
 
4072
        if (pgno < 0x100 || pgno > 0x8FF)
 
4073
                return FALSE;
 
4074
 
 
4075
        if (nk) {
 
4076
                if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
 
4077
                        return FALSE;
 
4078
        } else {
 
4079
                /* Current network. */
 
4080
                cn = td->network;
 
4081
        }
 
4082
 
 
4083
        cache_network_get_ttx_page_stat (cn, ps, pgno);
 
4084
 
 
4085
        if (nk)
 
4086
                cache_network_unref (cn);
 
4087
 
 
4088
        return TRUE;
 
4089
}
 
4090
 
 
4091
/**
 
4092
 * DOCUMENT ME
 
4093
 */
 
4094
vbi3_page *
 
4095
vbi3_teletext_decoder_get_page_va_list
 
4096
                                (vbi3_teletext_decoder *        td,
 
4097
                                 const vbi3_network *   nk,
 
4098
                                 vbi3_pgno              pgno,
 
4099
                                 vbi3_subno             subno,
 
4100
                                 va_list                format_options)
 
4101
{
 
4102
        cache_network *cn;
 
4103
        cache_page *cp;
 
4104
        vbi3_subno subno_mask;
 
4105
        vbi3_page *pg;
 
4106
 
 
4107
        assert (NULL != td);
 
4108
 
 
4109
        cn = NULL;
 
4110
        cp = NULL;
 
4111
 
 
4112
        pg = NULL;
 
4113
 
 
4114
        /* Current network. */
 
4115
        cn = td->network;
 
4116
 
 
4117
        if (nk) {
 
4118
                if (!(cn = _vbi3_cache_get_network (td->cache, nk)))
 
4119
                        goto failure;
 
4120
        }
 
4121
 
 
4122
        subno_mask = -1;
 
4123
 
 
4124
        if (VBI3_ANY_SUBNO == subno) {
 
4125
                subno = 0;
 
4126
                subno_mask = 0;
 
4127
        }
 
4128
 
 
4129
        if (!(cp = _vbi3_cache_get_page (td->cache, cn, pgno,
 
4130
                                        subno, subno_mask)))
 
4131
                goto failure;
 
4132
 
 
4133
        if (!(pg = vbi3_page_new ()))
 
4134
                goto failure;
 
4135
 
 
4136
        if (!_vbi3_page_priv_from_cache_page_va_list
 
4137
            (pg->priv, cp, format_options)) {
 
4138
                vbi3_page_delete (pg);
 
4139
                pg = NULL;
 
4140
        }
 
4141
 
 
4142
 failure:
 
4143
        cache_page_unref (cp);
 
4144
 
 
4145
        if (nk)
 
4146
                cache_network_unref (cn);
 
4147
 
 
4148
        return pg;
 
4149
}
 
4150
 
 
4151
/**
 
4152
 * DOCUMENT ME
 
4153
 */
 
4154
vbi3_page *
 
4155
vbi3_teletext_decoder_get_page  (vbi3_teletext_decoder *        td,
 
4156
                                 const vbi3_network *   nk,
 
4157
                                 vbi3_pgno              pgno,
 
4158
                                 vbi3_subno             subno,
 
4159
                                 ...)
 
4160
{
 
4161
        vbi3_page *pg;
 
4162
        va_list format_options;
 
4163
 
 
4164
        va_start (format_options, subno);
 
4165
 
 
4166
        pg = vbi3_teletext_decoder_get_page_va_list
 
4167
                (td, nk, pgno, subno, format_options);
 
4168
 
 
4169
        va_end (format_options);
 
4170
 
 
4171
        return pg;
 
4172
}
 
4173
 
 
4174
/**
 
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.
 
4179
 *
 
4180
 * Returns the most recently on a logical channel received program ID.
 
4181
 */
 
4182
void
 
4183
vbi3_teletext_decoder_get_program_id
 
4184
                                (vbi3_teletext_decoder *        td,
 
4185
                                 vbi3_program_id *      pid,
 
4186
                                 vbi3_pid_channel       channel)
 
4187
{
 
4188
#ifdef ZAPPING8
 
4189
        assert (0);
 
4190
#else
 
4191
        assert (NULL != td);
 
4192
        assert (NULL != pid);
 
4193
 
 
4194
        assert ((unsigned int) channel <= VBI3_PID_CHANNEL_LCI_3);
 
4195
 
 
4196
        *pid = td->network->program_id[channel];
 
4197
#endif
 
4198
}
 
4199
 
 
4200
/**
 
4201
 * @internal
 
4202
 * @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
 
4203
 *
 
4204
 * To be called after frame dropping, when Teletext packets might have
 
4205
 * been lost. After a channel change call vbi3_teletext_decoder_reset()
 
4206
 * instead.
 
4207
 */
 
4208
void
 
4209
_vbi3_teletext_decoder_resync   (vbi3_teletext_decoder *        td)
 
4210
{
 
4211
        unsigned int i;
 
4212
 
 
4213
        /* Discard all in progress pages. */
 
4214
 
 
4215
        for (i = 0; i < N_ELEMENTS (td->buffer); ++i)
 
4216
                td->buffer[i].function = PAGE_FUNCTION_DISCARD;
 
4217
 
 
4218
        td->current = NULL;
 
4219
 
 
4220
#if 0 /* TODO */
 
4221
        vbi3_pfc_demux_reset (&td->epg_stream[0]);
 
4222
        vbi3_pfc_demux_reset (&td->epg_stream[1]);
 
4223
#endif
 
4224
}
 
4225
 
 
4226
/** @internal */
 
4227
void
 
4228
cache_network_dump_teletext     (const cache_network *  cn,
 
4229
                                 FILE *                 fp)
 
4230
{
 
4231
        unsigned int i;
 
4232
        vbi3_pgno pgno;
 
4233
 
 
4234
        pagenum_dump (&cn->initial_page, fp);
 
4235
 
 
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);
 
4239
        }
 
4240
 
 
4241
        fputs ("\nstatus=\"", fp);
 
4242
 
 
4243
        for (i = 0; i < N_ELEMENTS (cn->status); ++i)
 
4244
                fputc (vbi3_printable (cn->status[i]), fp);
 
4245
 
 
4246
        fputs ("\"\npage_stat=\n", fp);
 
4247
 
 
4248
        for (pgno = 0x100; pgno < 0x8FF; pgno += 8) {
 
4249
                vbi3_pgno unit;
 
4250
 
 
4251
                for (unit = 0; unit < 8; ++unit) {
 
4252
                        const page_stat *ps;
 
4253
 
 
4254
                        ps = cache_network_const_page_stat (cn, pgno + unit);
 
4255
 
 
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);
 
4260
                }
 
4261
 
 
4262
                fputc ('\n', fp);
 
4263
        }
 
4264
 
 
4265
        fputc ('\n', fp);
 
4266
}
 
4267
 
 
4268
static void
 
4269
extension_init                  (extension *            ext)
 
4270
{
 
4271
        unsigned int i;
 
4272
 
 
4273
        CLEAR (*ext);
 
4274
 
 
4275
        ext->def_screen_color   = VBI3_BLACK;   /* A.5 */
 
4276
        ext->def_row_color      = VBI3_BLACK;   /* A.5 */
 
4277
 
 
4278
        for (i = 0; i < 8; ++i)
 
4279
                ext->drcs_clut[2 + i] = i & 3;
 
4280
 
 
4281
        for (i = 0; i < 32; ++i)
 
4282
                ext->drcs_clut[2 + 8 + i] = i & 15;
 
4283
 
 
4284
        memcpy (ext->color_map, default_color_map,
 
4285
                sizeof (ext->color_map));
 
4286
}
 
4287
 
 
4288
static void
 
4289
magazine_init                   (magazine *             mag)
 
4290
{
 
4291
        extension_init (&mag->extension);
 
4292
 
 
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));
 
4296
 
 
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));
 
4300
}
 
4301
 
 
4302
/**
 
4303
 * @internal
 
4304
 *
 
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
 
4307
 * and 3.5.
 
4308
 */
 
4309
const magazine *
 
4310
_vbi3_teletext_decoder_default_magazine
 
4311
                                (void)
 
4312
{
 
4313
        static magazine default_magazine;
 
4314
 
 
4315
        if (!NO_PAGE (default_magazine.pop_link[0][0].pgno))
 
4316
                magazine_init (&default_magazine);
 
4317
 
 
4318
        return &default_magazine;
 
4319
}
 
4320
 
 
4321
static void
 
4322
page_stat_init                  (page_stat *            ps)
 
4323
{
 
4324
        CLEAR (*ps);
 
4325
 
 
4326
        ps->page_type           = VBI3_UNKNOWN_PAGE;
 
4327
        ps->charset_code        = 0xFF;
 
4328
        ps->subcode             = SUBCODE_UNKNOWN;
 
4329
}
 
4330
 
 
4331
/** @internal */
 
4332
void
 
4333
cache_network_destroy_teletext  (cache_network *        cn)
 
4334
{
 
4335
        /* Nothing. */
 
4336
}
 
4337
 
 
4338
/**
 
4339
 * @internal
 
4340
 * @param cn cache_network structure to be initialized.
 
4341
 *
 
4342
 * Initializes the Teletext fields of a cache_network structure.
 
4343
 */
 
4344
void
 
4345
cache_network_init_teletext     (cache_network *        cn)
 
4346
{
 
4347
        unsigned int i;
 
4348
 
 
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;
 
4353
 
 
4354
        for (i = 0; i < N_ELEMENTS (cn->_magazines); ++i)
 
4355
                magazine_init (&cn->_magazines[i]);
 
4356
 
 
4357
        for (i = 0; i < N_ELEMENTS (cn->_pages); ++i)
 
4358
                page_stat_init (&cn->_pages[i]);
 
4359
 
 
4360
        /* NO_PAGE (pgno): (pgno & 0xFF) == 0xFF. */
 
4361
        memset (cn->btt_link, -1, sizeof (cn->btt_link));
 
4362
 
 
4363
        CLEAR (cn->status);
 
4364
 
 
4365
        cn->have_top = FALSE;
 
4366
}
 
4367
 
 
4368
/* Internal reset function, called by td->virtual_reset(). */
 
4369
static void
 
4370
reset                           (vbi3_teletext_decoder *        td,
 
4371
                                 cache_network *        cn,
 
4372
                                 double                 time)
 
4373
{
 
4374
        vbi3_event e;
 
4375
 
 
4376
        assert (NULL != td);
 
4377
 
 
4378
        if (0)
 
4379
                fprintf (stderr, "reset %f: %f -> %f\n",
 
4380
                         td->time, td->reset_time, time);
 
4381
 
 
4382
        if (time <= 0.0 || time > td->reset_time)
 
4383
                td->reset_time = time;
 
4384
 
 
4385
        if (0.0 != time)
 
4386
                return;
 
4387
 
 
4388
        assert (NULL != cn);
 
4389
 
 
4390
        cache_network_unref (td->network);
 
4391
        td->network = cache_network_ref (cn);
 
4392
 
 
4393
#if 0 /* TODO */
 
4394
        td->epg_stream[0].block.pgno = 0;
 
4395
        td->epg_stream[1].block.pgno = 0;
 
4396
#endif
 
4397
 
 
4398
        td->header_page.pgno = 0;
 
4399
        CLEAR (td->header);
 
4400
 
 
4401
        _vbi3_teletext_decoder_resync (td);
 
4402
 
 
4403
        e.type          = VBI3_EVENT_RESET;
 
4404
        e.network       = &td->network->network;
 
4405
        e.timestamp     = td->time;
 
4406
 
 
4407
        _vbi3_event_handler_list_send (&td->handlers, &e);
 
4408
}
 
4409
 
 
4410
/**
 
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.
 
4414
 * 
 
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
 
4418
 * handler.
 
4419
 */
 
4420
void
 
4421
vbi3_teletext_decoder_remove_event_handler
 
4422
                                (vbi3_teletext_decoder *        td,
 
4423
                                 vbi3_event_cb *                callback,
 
4424
                                 void *                 user_data)
 
4425
{
 
4426
        vbi3_cache_remove_event_handler (td->cache,
 
4427
                                         callback,
 
4428
                                         user_data);
 
4429
 
 
4430
        _vbi3_event_handler_list_remove_by_callback (&td->handlers,
 
4431
                                                     callback,
 
4432
                                                     user_data);
 
4433
}
 
4434
 
 
4435
/**
 
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.
 
4442
 * 
 
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.
 
4448
 *
 
4449
 * Any number of handlers can be added, also different handlers for the
 
4450
 * same event which will be called in registration order.
 
4451
 *
 
4452
 * @returns
 
4453
 * @c FALSE of failure (out of memory).
 
4454
 */
 
4455
vbi3_bool
 
4456
vbi3_teletext_decoder_add_event_handler
 
4457
                                (vbi3_teletext_decoder *        td,
 
4458
                                 unsigned int           event_mask,
 
4459
                                 vbi3_event_cb *                callback,
 
4460
                                 void *                 user_data)
 
4461
{
 
4462
        unsigned int ttx_mask;
 
4463
        unsigned int add_mask;
 
4464
        unsigned int rem_mask;
 
4465
 
 
4466
        if (!vbi3_cache_add_event_handler (td->cache,
 
4467
                                           event_mask,
 
4468
                                           callback,
 
4469
                                           user_data))
 
4470
                return FALSE;
 
4471
 
 
4472
        ttx_mask = event_mask & (VBI3_EVENT_CLOSE |
 
4473
                                 VBI3_EVENT_RESET |
 
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);
 
4482
 
 
4483
        add_mask = ttx_mask & ~td->handlers.event_mask;
 
4484
        rem_mask = td->handlers.event_mask & ~event_mask;
 
4485
 
 
4486
        if (rem_mask & VBI3_EVENT_TRIGGER) {
 
4487
#ifndef ZAPPING8
 
4488
                /* Don't fire old triggers. */
 
4489
                _vbi3_trigger_list_delete (&td->triggers);
 
4490
#endif
 
4491
        }
 
4492
 
 
4493
        if (0 == ttx_mask) {
 
4494
                return TRUE;
 
4495
        }
 
4496
 
 
4497
        if (NULL != _vbi3_event_handler_list_add (&td->handlers,
 
4498
                                                  ttx_mask,
 
4499
                                                  callback,
 
4500
                                                  user_data)) {
 
4501
                if (add_mask & (VBI3_EVENT_TTX_PAGE |
 
4502
                                VBI3_EVENT_TRIGGER)) {
 
4503
                        _vbi3_teletext_decoder_resync (td);
 
4504
                }
 
4505
 
 
4506
                return TRUE;
 
4507
        } else {
 
4508
                vbi3_cache_remove_event_handler (td->cache,
 
4509
                                                 callback,
 
4510
                                                 user_data);
 
4511
        }
 
4512
 
 
4513
        return FALSE;
 
4514
}
 
4515
 
 
4516
/**
 
4517
 * DOCUMENT ME
 
4518
 */
 
4519
vbi3_bool
 
4520
vbi3_teletext_decoder_get_network
 
4521
                                (vbi3_teletext_decoder *td,
 
4522
                                 vbi3_network *         nk)
 
4523
{
 
4524
        assert (NULL != td);
 
4525
        assert (NULL != nk);
 
4526
 
 
4527
        if (!td->network)
 
4528
                return FALSE;
 
4529
 
 
4530
        return vbi3_network_copy (nk, &td->network->network);
 
4531
}
 
4532
 
 
4533
/**
 
4534
 * DOCUMENT ME
 
4535
 */
 
4536
vbi3_cache *
 
4537
vbi3_teletext_decoder_get_cache (vbi3_teletext_decoder *td)
 
4538
{
 
4539
        assert (NULL != td);
 
4540
 
 
4541
        if (!td->cache)
 
4542
                return NULL;
 
4543
 
 
4544
        return vbi3_cache_ref (td->cache);
 
4545
}
 
4546
 
 
4547
/**
 
4548
 * @param td Teletext decoder allocated with vbi3_teletext_decoder_new().
 
4549
 * @param nk Identifies the new network, can be @c NULL.
 
4550
 *
 
4551
 * Resets the Teletext decoder, useful for example after a channel change.
 
4552
 * This function sends a @c VBI3_EVENT_RESET.
 
4553
 *
 
4554
 * You can pass a vbi3_network structure to identify the new network in
 
4555
 * advance, before the decoder receives an ID if ever.
 
4556
 */
 
4557
void
 
4558
vbi3_teletext_decoder_reset     (vbi3_teletext_decoder *        td,
 
4559
                                 const vbi3_network *   nk,
 
4560
                                 vbi3_videostd_set      videostd_set)
 
4561
{
 
4562
        cache_network *cn;
 
4563
 
 
4564
        assert (NULL != td);
 
4565
 
 
4566
        td->videostd_set = videostd_set;
 
4567
 
 
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);
 
4571
}
 
4572
 
 
4573
/**
 
4574
 * @internal
 
4575
 * @param td Teletext decoder to be destroyed.
 
4576
 *
 
4577
 * Frees all resources associated with @a td, except the structure itself.
 
4578
 * This function sends a @c VBI3_EVENT_CLOSE.
 
4579
 */
 
4580
void
 
4581
_vbi3_teletext_decoder_destroy  (vbi3_teletext_decoder *        td)
 
4582
{
 
4583
        vbi3_event e;
 
4584
 
 
4585
        assert (NULL != td);
 
4586
 
 
4587
        e.type          = VBI3_EVENT_CLOSE;
 
4588
        e.network       = &td->network->network;
 
4589
        e.timestamp     = td->time;
 
4590
 
 
4591
        _vbi3_event_handler_list_send (&td->handlers, &e);
 
4592
 
 
4593
        _vbi3_event_handler_list_destroy (&td->handlers);
 
4594
 
 
4595
#ifndef ZAPPING8
 
4596
        _vbi3_trigger_list_delete (&td->triggers);
 
4597
#endif
 
4598
 
 
4599
        cache_network_unref (td->network);
 
4600
 
 
4601
        /* Delete if we hold the last reference. */
 
4602
        vbi3_cache_unref (td->cache);
 
4603
 
 
4604
        CLEAR (*td);
 
4605
}
 
4606
 
 
4607
/**
 
4608
 * @internal
 
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()),
 
4614
 *   can be @c NULL.
 
4615
 *
 
4616
 * Initializes a Teletext decoder structure.
 
4617
 *
 
4618
 * @returns
 
4619
 * @c FALSE on failure (out of memory).
 
4620
 */
 
4621
vbi3_bool
 
4622
_vbi3_teletext_decoder_init     (vbi3_teletext_decoder *        td,
 
4623
                                 vbi3_cache *           ca,
 
4624
                                 const vbi3_network *   nk,
 
4625
                                 vbi3_videostd_set      videostd_set)
 
4626
{
 
4627
        cache_network *cn;
 
4628
 
 
4629
        assert (NULL != td);
 
4630
 
 
4631
        CLEAR (*td);
 
4632
 
 
4633
        if (ca)
 
4634
                td->cache = vbi3_cache_ref (ca);
 
4635
        else
 
4636
                td->cache = vbi3_cache_new ();
 
4637
 
 
4638
        if (!td->cache)
 
4639
                return FALSE;
 
4640
 
 
4641
        td->virtual_reset = reset;
 
4642
 
 
4643
        td->cni_830_timeout = 2.5; /* sec */
 
4644
        td->cni_vps_timeout = 5 / 25.0; /* sec */
 
4645
 
 
4646
        _vbi3_event_handler_list_init (&td->handlers);
 
4647
 
 
4648
        td->videostd_set = videostd_set;
 
4649
 
 
4650
        cn = _vbi3_cache_add_network (td->cache, nk, videostd_set);
 
4651
        reset (td, cn, 0.0 /* now */);
 
4652
        cache_network_unref (cn);
 
4653
 
 
4654
        return TRUE;
 
4655
}
 
4656
 
 
4657
/**
 
4658
 * @param td Teletext decoder allocated with vbi3_teletext_decoder_new(),
 
4659
 *   can be @c NULL.
 
4660
 *
 
4661
 * Frees all resources associated with @a td.
 
4662
 * This function sends a @c VBI3_EVENT_CLOSE.
 
4663
 */
 
4664
void
 
4665
vbi3_teletext_decoder_delete    (vbi3_teletext_decoder *        td)
 
4666
{
 
4667
        if (NULL == td)
 
4668
                return;
 
4669
 
 
4670
        _vbi3_teletext_decoder_destroy (td);
 
4671
 
 
4672
        vbi3_free (td);
 
4673
}
 
4674
 
 
4675
/**
 
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.
 
4679
 *
 
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()
 
4684
 *
 
4685
 * To be notified when new data is available call
 
4686
 * vbi3_teletext_decoder_add_event_handler().
 
4687
 *
 
4688
 * @returns
 
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).
 
4692
 */
 
4693
vbi3_teletext_decoder *
 
4694
vbi3_teletext_decoder_new       (vbi3_cache *           ca,
 
4695
                                 const vbi3_network *   nk,
 
4696
                                 vbi3_videostd_set      videostd_set)
 
4697
{
 
4698
        vbi3_teletext_decoder *td;
 
4699
 
 
4700
        if (!(td = vbi3_malloc (sizeof (*td)))) {
 
4701
                vbi3_log_printf (VBI3_DEBUG, __FUNCTION__,
 
4702
                                "Out of memory (%u)", sizeof (*td));
 
4703
                return NULL;
 
4704
        }
 
4705
 
 
4706
        if (!_vbi3_teletext_decoder_init (td, ca, nk, videostd_set)) {
 
4707
                vbi3_free (td);
 
4708
                td = NULL;
 
4709
        }
 
4710
 
 
4711
        return td;
 
4712
}