MythTV  master
teletextextractorreader.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
4 
5 void TeletextExtractorReader::PageUpdated(int page, int subpage)
6 {
7  m_updated_pages.insert(qMakePair(page, subpage));
8  TeletextReader::PageUpdated(page, subpage);
9 }
10 
12  int page, int subpage, uint8_t *page_ptr, int lang)
13 {
14  m_updated_pages.insert(qMakePair(page, subpage));
15  TeletextReader::HeaderUpdated(page, subpage, page_ptr, lang);
16 }
17 
18 /************************************************************************
19  * Everything below this message in this file is based on some VLC
20  * teletext code which was in turn based on some ProjectX teletext code.
21  ************************************************************************/
22 
23 /*****************************************************************************
24  * telx.c : Minimalistic Teletext subtitles decoder
25  *****************************************************************************
26  * Copyright (C) 2007 Vincent Penne
27  * Some code converted from ProjectX java dvb decoder (c) 2001-2005 by dvb.matt
28  * $Id: 2b01e6a460b7c3693bccd690e3dbc018832d2777 $
29  *
30  * This program is free software; you can redistribute it and/or modify
31  * it under the terms of the GNU General Public License as published by
32  * the Free Software Foundation; either version 2 of the License, or
33  * (at your option) any later version.
34  *
35  * This program is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38  * GNU General Public License for more details.
39  *
40  * You should have received a copy of the GNU General Public License
41  * along with this program; if not, write to the Free Software
42  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
43  *****************************************************************************/
44 
45 /*
46  * My doc only mentions 13 national characters, but experiments show there
47  * are more, in france for example I already found two more (0x9 and 0xb).
48  *
49  * Conversion is in this order :
50  *
51  * 0x23 0x24 0x40 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x7b 0x7c 0x7d 0x7e
52  * (these are the standard ones)
53  * 0x08 0x09 0x0a 0x0b 0x0c 0x0d (apparently a control character) 0x0e 0x0f
54  */
55 
56 static const uint16_t ppi_national_subsets[][20] =
57 {
58  { 0x00a3, 0x0024, 0x0040, 0x00ab, 0x00bd, 0x00bb, 0x005e, 0x0023,
59  0x002d, 0x00bc, 0x00a6, 0x00be, 0x00f7 }, /* english, 000 */
60 
61  { 0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x005e, 0x005f,
62  0x00b0, 0x00e4, 0x00f6, 0x00fc, 0x00df }, /* german, 001 */
63 
64  { 0x0023, 0x00a4, 0x00c9, 0x00c4, 0x00d6, 0x00c5, 0x00dc, 0x005f,
65  0x00e9, 0x00e4, 0x00f6, 0x00e5, 0x00fc
66  }, /* swedish, finnish, hungarian, 010 */
67 
68  { 0x00a3, 0x0024, 0x00e9, 0x00b0, 0x00e7, 0x00bb, 0x005e, 0x0023,
69  0x00f9, 0x00e0, 0x00f2, 0x00e8, 0x00ec }, /* italian, 011 */
70 
71  { 0x00e9, 0x00ef, 0x00e0, 0x00eb, 0x00ea, 0x00f9, 0x00ee, 0x0023,
72  0x00e8, 0x00e2, 0x00f4, 0x00fb, 0x00e7, 0, 0x00eb, 0, 0x00ef
73  }, /* french, 100 */
74 
75  { 0x00e7, 0x0024, 0x00a1, 0x00e1, 0x00e9, 0x00ed, 0x00f3, 0x00fa,
76  0x00bf, 0x00fc, 0x00f1, 0x00e8, 0x00e0 }, /* portuguese, spanish, 101 */
77 
78  { 0x0023, 0x016f, 0x010d, 0x0165, 0x017e, 0x00fd, 0x00ed, 0x0159,
79  0x00e9, 0x00e1, 0x011b, 0x00fa, 0x0161 }, /* czech, slovak, 110 */
80 
81  { 0x0023, 0x00a4, 0x0162, 0x00c2, 0x015e, 0x0102, 0x00ce, 0x0131,
82  0x0163, 0x00e2, 0x015f, 0x0103, 0x00ee }, /* rumanian, 111 */
83 
84  /* I have these tables too, but I don't know how they can be triggered */
85  { 0x0023, 0x0024, 0x0160, 0x0117, 0x0119, 0x017d, 0x010d, 0x016b,
86  0x0161, 0x0105, 0x0173, 0x017e, 0x012f }, /* lettish, lithuanian, 1000 */
87 
88  { 0x0023, 0x0144, 0x0105, 0x005a, 0x015a, 0x0141, 0x0107, 0x00f3,
89  0x0119, 0x017c, 0x015b, 0x0142, 0x017a }, /* polish, 1001 */
90 
91  { 0x0023, 0x00cb, 0x010c, 0x0106, 0x017d, 0x0110, 0x0160, 0x00eb,
92  0x010d, 0x0107, 0x017e, 0x0111, 0x0161
93  }, /* serbian, croatian, slovenian, 1010 */
94 
95  { 0x0023, 0x00f5, 0x0160, 0x00c4, 0x00d6, 0x017e, 0x00dc, 0x00d5,
96  0x0161, 0x00e4, 0x00f6, 0x017e, 0x00fc }, /* estonian, 1011 */
97 
98  { 0x0054, 0x011f, 0x0130, 0x015e, 0x00d6, 0x00c7, 0x00dc, 0x011e,
99  0x0131, 0x015f, 0x00f6, 0x00e7, 0x00fc }, /* turkish, 1100 */
100 };
101 
102 // utc-2 --> utf-8
103 // this is not a general function, but it's enough for what we do here
104 // the result buffer need to be at least 4 bytes long
105 static void to_utf8(char *res, uint16_t ch)
106 {
107  if(ch >= 0x80)
108  {
109  if(ch >= 0x800)
110  {
111  res[0] = (ch >> 12) | 0xE0;
112  res[1] = ((ch >> 6) & 0x3F) | 0x80;
113  res[2] = (ch & 0x3F) | 0x80;
114  res[3] = 0;
115  }
116  else
117  {
118  res[0] = (ch >> 6) | 0xC0;
119  res[1] = (ch & 0x3F) | 0x80;
120  res[2] = 0;
121  }
122  }
123  else
124  {
125  res[0] = ch;
126  res[1] = 0;
127  }
128 }
129 
134 QString decode_teletext(int codePage, const uint8_t data[40])
135 {
136  QString res;
137  char utf8[7];
138 
139  const uint16_t *pi_active_national_set = ppi_national_subsets[codePage];
140 
141  for (int i = 0; i < 40; ++i)
142  {
143  //int in = bytereverse(data[i]) & 0x7f;
144  int in = data[i] & 0x7f;
145  uint16_t out = 32;
146 
147  switch (in)
148  {
149  /* special national characters */
150  case 0x23:
151  out = pi_active_national_set[0];
152  break;
153  case 0x24:
154  out = pi_active_national_set[1];
155  break;
156  case 0x40:
157  out = pi_active_national_set[2];
158  break;
159  case 0x5b:
160  out = pi_active_national_set[3];
161  break;
162  case 0x5c:
163  out = pi_active_national_set[4];
164  break;
165  case 0x5d:
166  out = pi_active_national_set[5];
167  break;
168  case 0x5e:
169  out = pi_active_national_set[6];
170  break;
171  case 0x5f:
172  out = pi_active_national_set[7];
173  break;
174  case 0x60:
175  out = pi_active_national_set[8];
176  break;
177  case 0x7b:
178  out = pi_active_national_set[9];
179  break;
180  case 0x7c:
181  out = pi_active_national_set[10];
182  break;
183  case 0x7d:
184  out = pi_active_national_set[11];
185  break;
186  case 0x7e:
187  out = pi_active_national_set[12];
188  break;
189 
190  case 0x0a:
191  case 0x0b:
192  case 0x0d:
193  //wtf? looks like some kind of garbage for me
194  out = 32;
195  break;
196 
197  default:
198  /* non documented national range 0x08 - 0x0f */
199  if (in >= 0x08 && in <= 0x0f)
200  {
201  out = pi_active_national_set[13 + in - 8];
202  break;
203  }
204 
205  /* normal ascii */
206  if (in > 32 && in < 0x7f)
207  out = in;
208  }
209 
210  /* handle undefined national characters */
211  if (out == 0)
212  out = '?'; //' ' or '?' ?
213 
214  /* convert to utf-8 */
215  to_utf8(utf8, out);
216  res += QString::fromUtf8(utf8, strlen(utf8));
217  }
218 
219  return res;
220 }
221 
222 //QString DechiperTtxFlags(int flags) {
223 // QString res;
224 
225 // if (flags & TP_SUPPRESS_HEADER)
226 // res += "TP_SUPPRESS_HEADER ";
227 // if (flags & TP_UPDATE_INDICATOR)
228 // res += "TP_UPDATE_INDICATOR ";
229 // if (flags & TP_INTERRUPTED_SEQ)
230 // res += "TP_INTERRUPTED_SEQ ";
231 // if (flags & TP_INHIBIT_DISPLAY)
232 // res += "TP_INHIBIT_DISPLAY ";
233 // if (flags & TP_MAGAZINE_SERIAL)
234 // res += "TP_MAGAZINE_SERIAL ";
235 // if (flags & TP_ERASE_PAGE)
236 // res += "TP_ERASE_PAGE ";
237 // if (flags & TP_NEWSFLASH)
238 // res += "TP_NEWSFLASH ";
239 // if (flags & TP_SUBTITLE)
240 // res += "TP_SUBTITLE ";
241 
242 // return res.trimmed();
243 //}
244 
245 /* vim: set expandtab tabstop=4 shiftwidth=4: */
QSet< QPair< int, int > > m_updated_pages
static void to_utf8(char *res, uint16_t ch)
void PageUpdated(int page, int subpage) override
static const uint16_t ppi_national_subsets[][20]
virtual void HeaderUpdated(int page, int subpage, uint8_t *page_ptr, int lang)
unsigned short uint16_t
Definition: iso6937tables.h:1
QString decode_teletext(int codePage, const uint8_t data[40])
Get decoded ttx as a string.
virtual void PageUpdated(int page, int subpage)
void HeaderUpdated(int page, int subpage, uint8_t *page_ptr, int lang) override