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_updatedPages.insert(qMakePair(page, subpage));
8  TeletextReader::PageUpdated(page, subpage);
9 }
10 
12  int page, int subpage, tt_line_array& page_ptr, int lang)
13 {
14  m_updatedPages.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 using ppi_natl_array = std::array<const uint16_t,21>;
57 static const std::array<const ppi_natl_array,13> ppi_national_subsets
58 {{
59  { 0x00a3, 0x0024, 0x0040, 0x00ab, 0x00bd, 0x00bb, 0x005e, 0x0023,
60  0x002d, 0x00bc, 0x00a6, 0x00be, 0x00f7 }, /* english, 000 */
61 
62  { 0x0023, 0x0024, 0x00a7, 0x00c4, 0x00d6, 0x00dc, 0x005e, 0x005f,
63  0x00b0, 0x00e4, 0x00f6, 0x00fc, 0x00df }, /* german, 001 */
64 
65  { 0x0023, 0x00a4, 0x00c9, 0x00c4, 0x00d6, 0x00c5, 0x00dc, 0x005f,
66  0x00e9, 0x00e4, 0x00f6, 0x00e5, 0x00fc
67  }, /* swedish, finnish, hungarian, 010 */
68 
69  { 0x00a3, 0x0024, 0x00e9, 0x00b0, 0x00e7, 0x00bb, 0x005e, 0x0023,
70  0x00f9, 0x00e0, 0x00f2, 0x00e8, 0x00ec }, /* italian, 011 */
71 
72  { 0x00e9, 0x00ef, 0x00e0, 0x00eb, 0x00ea, 0x00f9, 0x00ee, 0x0023,
73  0x00e8, 0x00e2, 0x00f4, 0x00fb, 0x00e7, 0x0000, 0x00eb, 0x0000,
74  0x00ef
75  }, /* french, 100 */
76 
77  { 0x00e7, 0x0024, 0x00a1, 0x00e1, 0x00e9, 0x00ed, 0x00f3, 0x00fa,
78  0x00bf, 0x00fc, 0x00f1, 0x00e8, 0x00e0 }, /* portuguese, spanish, 101 */
79 
80  { 0x0023, 0x016f, 0x010d, 0x0165, 0x017e, 0x00fd, 0x00ed, 0x0159,
81  0x00e9, 0x00e1, 0x011b, 0x00fa, 0x0161 }, /* czech, slovak, 110 */
82 
83  { 0x0023, 0x00a4, 0x0162, 0x00c2, 0x015e, 0x0102, 0x00ce, 0x0131,
84  0x0163, 0x00e2, 0x015f, 0x0103, 0x00ee }, /* rumanian, 111 */
85 
86  /* I have these tables too, but I don't know how they can be triggered */
87  { 0x0023, 0x0024, 0x0160, 0x0117, 0x0119, 0x017d, 0x010d, 0x016b,
88  0x0161, 0x0105, 0x0173, 0x017e, 0x012f }, /* lettish, lithuanian, 1000 */
89 
90  { 0x0023, 0x0144, 0x0105, 0x005a, 0x015a, 0x0141, 0x0107, 0x00f3,
91  0x0119, 0x017c, 0x015b, 0x0142, 0x017a }, /* polish, 1001 */
92 
93  { 0x0023, 0x00cb, 0x010c, 0x0106, 0x017d, 0x0110, 0x0160, 0x00eb,
94  0x010d, 0x0107, 0x017e, 0x0111, 0x0161
95  }, /* serbian, croatian, slovenian, 1010 */
96 
97  { 0x0023, 0x00f5, 0x0160, 0x00c4, 0x00d6, 0x017e, 0x00dc, 0x00d5,
98  0x0161, 0x00e4, 0x00f6, 0x017e, 0x00fc }, /* estonian, 1011 */
99 
100  { 0x0054, 0x011f, 0x0130, 0x015e, 0x00d6, 0x00c7, 0x00dc, 0x011e,
101  0x0131, 0x015f, 0x00f6, 0x00e7, 0x00fc }, /* turkish, 1100 */
102 }};
103 
104 // utc-2 --> utf-8
105 // this is not a general function, but it's enough for what we do here
106 // the result buffer need to be at least 4 bytes long
107 static void to_utf8(std::string &res, uint16_t ch)
108 {
109  if(ch >= 0x80)
110  {
111  if(ch >= 0x800)
112  {
113  res = { static_cast<char>( (ch >> 12) | 0xE0),
114  static_cast<char>(((ch >> 6) & 0x3F) | 0x80),
115  static_cast<char>( (ch & 0x3F) | 0x80) };
116  }
117  else
118  {
119  res = { static_cast<char>((ch >> 6) | 0xC0),
120  static_cast<char>((ch & 0x3F) | 0x80) } ;
121  }
122  }
123  else
124  {
125  res = { static_cast<char>(ch) };
126  }
127 }
128 
133 QString decode_teletext(int codePage, const tt_line_array& data)
134 {
135  QString res;
136  std::string utf8 {};
137 
138  const ppi_natl_array pi_active_national_set = ppi_national_subsets[codePage];
139 
140  for (int i = 0; i < 40; ++i)
141  {
142  //int in = bytereverse(data[i]) & 0x7f;
143  int in = data[i] & 0x7f;
144  uint16_t out = 32;
145 
146  switch (in)
147  {
148  /* special national characters */
149  case 0x23:
150  out = pi_active_national_set[0];
151  break;
152  case 0x24:
153  out = pi_active_national_set[1];
154  break;
155  case 0x40:
156  out = pi_active_national_set[2];
157  break;
158  case 0x5b:
159  out = pi_active_national_set[3];
160  break;
161  case 0x5c:
162  out = pi_active_national_set[4];
163  break;
164  case 0x5d:
165  out = pi_active_national_set[5];
166  break;
167  case 0x5e:
168  out = pi_active_national_set[6];
169  break;
170  case 0x5f:
171  out = pi_active_national_set[7];
172  break;
173  case 0x60:
174  out = pi_active_national_set[8];
175  break;
176  case 0x7b:
177  out = pi_active_national_set[9];
178  break;
179  case 0x7c:
180  out = pi_active_national_set[10];
181  break;
182  case 0x7d:
183  out = pi_active_national_set[11];
184  break;
185  case 0x7e:
186  out = pi_active_national_set[12];
187  break;
188 
189  case 0x0a:
190  case 0x0b:
191  case 0x0d:
192  //wtf? looks like some kind of garbage for me
193  out = 32;
194  break;
195 
196  default:
197  /* non documented national range 0x08 - 0x0f */
198  if (in >= 0x08 && in <= 0x0f)
199  {
200  out = pi_active_national_set[13 + in - 8];
201  break;
202  }
203 
204  /* normal ascii */
205  if (in > 32 && in < 0x7f)
206  out = in;
207  }
208 
209  /* handle undefined national characters */
210  if (out == 0)
211  out = '?'; //' ' or '?' ?
212 
213  /* convert to utf-8 */
214  to_utf8(utf8, out);
215  res += QString::fromUtf8(utf8.c_str());
216  }
217 
218  return res;
219 }
220 
221 //QString DechiperTtxFlags(int flags) {
222 // QString res;
223 
224 // if (flags & TP_SUPPRESS_HEADER)
225 // res += "TP_SUPPRESS_HEADER ";
226 // if (flags & TP_UPDATE_INDICATOR)
227 // res += "TP_UPDATE_INDICATOR ";
228 // if (flags & TP_INTERRUPTED_SEQ)
229 // res += "TP_INTERRUPTED_SEQ ";
230 // if (flags & TP_INHIBIT_DISPLAY)
231 // res += "TP_INHIBIT_DISPLAY ";
232 // if (flags & TP_MAGAZINE_SERIAL)
233 // res += "TP_MAGAZINE_SERIAL ";
234 // if (flags & TP_ERASE_PAGE)
235 // res += "TP_ERASE_PAGE ";
236 // if (flags & TP_NEWSFLASH)
237 // res += "TP_NEWSFLASH ";
238 // if (flags & TP_SUBTITLE)
239 // res += "TP_SUBTITLE ";
240 
241 // return res.trimmed();
242 //}
243 
244 /* vim: set expandtab tabstop=4 shiftwidth=4: */
ppi_natl_array
std::array< const uint16_t, 21 > ppi_natl_array
Definition: teletextextractorreader.cpp:56
TeletextExtractorReader::HeaderUpdated
void HeaderUpdated(int page, int subpage, tt_line_array &page_ptr, int lang) override
Definition: teletextextractorreader.cpp:11
TeletextReader::PageUpdated
virtual void PageUpdated(int page, int subpage)
Definition: teletextreader.cpp:512
teletextextractorreader.h
to_utf8
static void to_utf8(std::string &res, uint16_t ch)
Definition: teletextextractorreader.cpp:107
decode_teletext
QString decode_teletext(int codePage, const tt_line_array &data)
Get decoded ttx as a string.
Definition: teletextextractorreader.cpp:133
TeletextExtractorReader::PageUpdated
void PageUpdated(int page, int subpage) override
Definition: teletextextractorreader.cpp:5
TeletextReader::HeaderUpdated
virtual void HeaderUpdated(int page, int subpage, tt_line_array &page_ptr, int lang)
Definition: teletextreader.cpp:521
tt_line_array
std::array< uint8_t, 40 > tt_line_array
Definition: teletextreader.h:36
ppi_national_subsets
static const std::array< const ppi_natl_array, 13 > ppi_national_subsets
Definition: teletextextractorreader.cpp:58
TeletextExtractorReader::m_updatedPages
QSet< QPair< int, int > > m_updatedPages
Definition: teletextextractorreader.h:34
uint16_t
unsigned short uint16_t
Definition: iso6937tables.h:3