Ticket #368: mythtv_teletext_20060111.patch

File mythtv_teletext_20060111.patch, 75.5 KB (added by beebof, 14 years ago)

new patc

  • libs/libmythtv/NuppelVideoPlayer.h

     
    1313#include "jitterometer.h"
    1414#include "recordingprofile.h"
    1515#include "videooutbase.h"
     16#include "teletextdecoder.h"
    1617#include "tv_play.h"
    1718
    1819extern "C" {
     
    158159    char        *GetScreenGrab(int secondsin, int &buflen,
    159160                               int &vw, int &vh, float &ar);
    160161    LiveTVChain *GetTVChain(void)             { return livetvchain; }
     162    TeletextDecoder *GetTeletextDecoder(void);
    161163
    162164    // Start/Reset/Stop playing
    163165    void StartPlaying(void);
     
    473475    bool      osdHasSubtitles;
    474476    long long osdSubtitlesExpireAt;
    475477    MythDeque<AVSubtitle> nonDisplayedSubtitles;
     478    TeletextDecoder *tt_decoder;
    476479
    477480    // OSD stuff
    478481    OSD      *osd;
  • libs/libmythtv/NuppelVideoPlayer.cpp

     
    117117      wtxt(0), rtxt(0), text_size(0), ccline(""), cccol(0), ccrow(0),
    118118      // Support for captions, teletext, etc. decoded by libav
    119119      osdHasSubtitles(false),       osdSubtitlesExpireAt(-1),
     120      tt_decoder(NULL),
    120121      // OSD stuff
    121122      osd(NULL),                    timedisplay(NULL),
    122123      dialogname(""),               dialogtype(0),
     
    213214            delete [] txtbuffers[i].buffer;
    214215    }
    215216
     217    if (tt_decoder)
     218        delete tt_decoder;
     219
    216220    SetDecoder(NULL);
    217221
    218222    if (FiltMan)
     
    228232        delete videoOutput;
    229233}
    230234
     235TeletextDecoder *NuppelVideoPlayer::GetTeletextDecoder(void)
     236{
     237    if (!tt_decoder)
     238        tt_decoder = new TeletextDecoder();
     239    return tt_decoder;
     240}
     241
    231242void NuppelVideoPlayer::SetWatchingRecording(bool mode)
    232243{
    233244    watchingrecording = mode;
  • libs/libmythtv/vbilut.h

     
    1717extern const short          hamm24err[];
    1818extern const int            hamm24cor[];
    1919
     20enum vbimode
     21{
     22    VBI_IVTV,        /// < IVTV packet
     23    VBI_DVB,         /// < DVB packet
     24    VBI_DVB_SUBTITLE /// < DVB subtitle packet
     25};
     26
     27int hamm8(const uint8_t *p, int *err);
     28int hamm84(const uint8_t *p, int *err);
     29int hamm16(const uint8_t *p, int *err);
     30
    2031#endif // _VBILUT_H_
  • libs/libmythtv/teletextdecoder.cpp

     
     1/* =============================================================
     2 * File  : vbidecoder.cpp
     3 * Author: Frank Muenchow <beebof@gmx.de>
     4 *         Martin Barnasconi
     5 * Date  : 2005-10-25
     6 *
     7 * This program is free software; you can redistribute it
     8 * and/or modify it under the terms of the GNU General
     9 * Public License as published by the Free Software Foundation;
     10 * either version 2, or (at your option)
     11 * any later version.
     12 *
     13 * This program is distributed in the hope that it will be useful,
     14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     16 * GNU General Public License for more details.
     17 *
     18 * ============================================================= */
     19#include <cstring>
     20
     21#include <stdint.h>
     22#include <ctype.h>
     23
     24extern "C" {
     25#include <inttypes.h>
     26#include "ivtv_myth.h"
     27#include "vbitext/vt.h"
     28}
     29
     30using namespace std;
     31
     32#include "osd.h"
     33#include "teletextdecoder.h"
     34#include "vbilut.h"
     35#include "mythcontext.h"
     36#include "osdtypeteletext.h"
     37#include "ccdecoder.h"
     38
     39/******************************************************************/
     40//Decoder section
     41//
     42
     43TeletextDecoder::TeletextDecoder() :
     44// private stuff
     45    m_teletextviewer(NULL), m_decodertype(-1)
     46{
     47}
     48
     49TeletextDecoder::~TeletextDecoder()
     50{
     51}
     52
     53/** \fn TeletextDecoder::Decode(const uint8_t*, int)
     54 *  \brief Decodes teletext data
     55 *
     56 *  \param buf Points to the teletext data
     57 *  \param vbimode VBI-Mode (as defined in vbilut.h)
     58 */
     59void TeletextDecoder::Decode(const uint8_t *buf, int vbimode)
     60{
     61    int err = 0;
     62    int latin1 = -1;
     63    uint8_t magazine, packet, header;
     64    int zahl1;
     65    int pagenum, subpagenum;
     66    int lang, flags;
     67
     68    if (m_teletextviewer == NULL)
     69    {
     70        VERBOSE(VB_VBI,QString("TeletextDecoder: No Teletext Viewer defined!"));
     71        return;
     72    }
     73
     74    m_decodertype = vbimode;
     75
     76    switch (vbimode)
     77    {
     78        case VBI_IVTV:
     79            header = hamm16(buf, &err);
     80
     81            if (err & 0xf000)
     82                return; // error in data header
     83
     84            magazine = header & 7;
     85            packet = (header >> 3) & 0x1f;
     86
     87            buf += 2;
     88            break;
     89
     90        case VBI_DVB:
     91        case VBI_DVB_SUBTITLE:
     92            zahl1 = hamm84(buf,&err) * 16 + hamm84(buf+1,&err);
     93
     94            magazine = 0;
     95            if (buf[0] & 0x40)
     96                magazine += 1;
     97            if (buf[0] & 0x10)
     98                magazine += 2;
     99            if (buf[0] & 0x04)
     100                magazine += 4;
     101
     102            packet = 0;
     103            if (buf[0] & 0x01)
     104                packet += 1;
     105            if (buf[1] & 0x40)
     106                packet += 2;
     107            if (buf[1] & 0x10)
     108                packet += 4;
     109            if (buf[1] & 0x04)
     110                packet += 8;
     111            if (buf[1] & 0x01)
     112                packet += 16;
     113
     114            if (err == 1)
     115                return;  // error in data header
     116
     117            buf += 2;
     118            break;
     119
     120        default:
     121            return; // error in vbimode
     122    }
     123
     124    switch (packet)
     125    {
     126        case 0:  // Page Header
     127            int b1, b2, b3, b4;
     128            switch (vbimode)
     129            {
     130                case VBI_IVTV:
     131                    b1 = hamm16(buf, &err);// page number
     132                    b2 = hamm16(buf+2, &err);// subpage number + flags
     133                    b3 = hamm16(buf+4, &err);// subpage number + flags
     134                    b4 = hamm16(buf+6, &err);// language code + more flags
     135                    if (err & 0xf000)
     136                        return;
     137                   
     138                    break;
     139
     140                case VBI_DVB:
     141                case VBI_DVB_SUBTITLE:
     142                    b1 = hamm84(buf+1, &err)*16+hamm84(buf, &err);
     143                    b2 = hamm84(buf+3, &err)*16+hamm84(buf+2, &err);
     144                    b3 = hamm84(buf+5, &err)*16+hamm84(buf+4, &err);
     145                    b4 = hamm84(buf+7, &err)*16+hamm84(buf+6, &err);
     146                    if (err == 1)
     147                        return;
     148                   
     149                    break;
     150
     151                default:
     152                    return; // error in vbimode
     153            }
     154
     155            VERBOSE(VB_VBI, QString("Page Header found: "
     156                                    "Magazine %1, Page Number %2")
     157                    .arg(magazine).arg(b1));
     158            subpagenum= (b2 + b3 * 256) & 0x3f7f;
     159            pagenum = (magazine?:8)*256 + b1;
     160
     161            lang = "\0\4\2\6\1\5\3\7"[b4 >> 5] + (latin1 ? 0 : 8);
     162            flags = b4 & 0x1F;
     163            flags |= b3 & 0xC0;
     164            flags |= (b2 & 0x80) >> 2;
     165            m_teletextviewer->AddPageHeader(pagenum,subpagenum,buf,vbimode,lang,flags);
     166
     167            break;
     168
     169        default: // Page Data
     170            m_teletextviewer->AddTeletextData((magazine?:8), packet, buf, vbimode);
     171            break;
     172    }
     173    return;
     174}
     175
     176/** \fn TeletextDecoder::SetViewer(OSDTypeTeletext*)
     177 *  \brief Sets the Teletext Viewer Class
     178 */
     179void TeletextDecoder::SetViewer(OSDTypeTeletext *view)
     180{
     181    m_teletextviewer = view;
     182}
     183
     184/** \fn TeletextDecoder::GetDecoderType(void) const
     185 *  \brief returns the actual decoder type (DVB,IVTV,DVB_SUBTITLE...)
     186 *         At the moment, this is just for the decision in tv_play.cpp
     187 *         if to use the new TeletextDecoder class or the old one
     188 */
     189int TeletextDecoder::GetDecoderType(void) const
     190{
     191    return m_decodertype;
     192}
     193
  • libs/libmythtv/avformatdecoder.cpp

     
    265265      video_codec_id(kCodec_NONE),
    266266      maxkeyframedist(-1),
    267267      ccd(new CCDecoder(this)),
     268      ttd(NULL),
    268269      // Audio
    269270      audioSamples(new short int[AVCODEC_MAX_AUDIO_FRAME_SIZE]),
    270271      allow_ac3_passthru(false),    allow_dts_passthru(false),
     
    290291#endif
    291292
    292293    audioIn.sample_size = -32; // force SetupAudioStream to run once
     294    ttd = GetNVP()->GetTeletextDecoder();
    293295}
    294296
    295297AvFormatDecoder::~AvFormatDecoder()
     
    17191721                // SECAM lines  6-23
    17201722                // PAL   lines  6-22
    17211723                // NTSC  lines 10-21 (rare)
    1722                 //ttd->Decode(buf+1, VBI_IVTV);
     1724                ttd->Decode(buf+1, VBI_IVTV);
    17231725                break;
    17241726            case VBI_TYPE_CC:
    17251727                // PAL   line 22 (rare)
     
    17561758    const uint8_t *buf     = pkt->data;
    17571759    const uint8_t *buf_end = pkt->data + pkt->size;
    17581760
    1759     while (buf < buf_end);
     1761
     1762    while (buf < buf_end)
    17601763    {
    17611764        if (*buf == 0x10)
    17621765            buf++; // skip
     
    17661769        if (*buf == 0x02)
    17671770        {
    17681771            buf += 3;
    1769             //ttd->Decode(buf+1, VBI_DVB);
     1772            ttd->Decode(buf+1, VBI_DVB);
    17701773        }
    17711774        else if (*buf == 0x03)
    17721775        {
    17731776            buf += 3;
    1774             //ttd->Decode(buf+1, VBI_DVB_SUBTITLE);
     1777            ttd->Decode(buf+1, VBI_DVB_SUBTITLE);
    17751778        }
    17761779        else
    17771780        {
    17781781            VERBOSE(VB_VBI, QString("VBI: Unknown descriptor: %1").arg(*buf));
    17791782        }
    1780 
    17811783        buf += 43;
    17821784    }
    17831785}
     
    23312333
    23322334        if (len > 0 &&
    23332335            curstream->codec->codec_type == CODEC_TYPE_DATA &&
    2334             curstream->codec->codec_id   == CODEC_ID_MPEG2VBI)
     2336            curstream->codec->codec_id   == CODEC_ID_DVB_VBI)
    23352337        {
    23362338            ProcessDVBDataPacket(curstream, pkt);
    2337 
    23382339            av_free_packet(pkt);
    23392340            continue;
    23402341        }
  • libs/libmythtv/osdtypeteletext.cpp

     
     1/* =============================================================
     2* File  : osdtypeteletext.cpp
     3* Author: Frank Muenchow <beebof@gmx.de>
     4*         Martin Barnasconi
     5* Date  : 2005-10-25
     6*
     7* This program is free software; you can redistribute it
     8* and/or modify it under the terms of the GNU General
     9* Public License as published by the Free Software Foundation;
     10* either version 2, or (at your option)
     11* any later version.
     12*
     13* This program is distributed in the hope that it will be useful,
     14* but WITHOUT ANY WARRANTY; without even the implied warranty of
     15* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     16* GNU General Public License for more details.
     17*
     18* ============================================================= */
     19#include "osd.h"
     20#include "osdsurface.h"
     21#include "osdtypes.h"
     22#include "osdtypeteletext.h"
     23#include "ttfont.h"
     24#include "vbilut.h"
     25
     26#include <qcolor.h>
     27#include <qapplication.h>
     28#include <iostream>
     29#include <cmath>
     30#include <qmutex.h>
     31
     32using namespace std;
     33
     34QColor m_color_black;
     35QColor m_color_red;
     36QColor m_color_green;
     37QColor m_color_yellow;
     38QColor m_color_blue;
     39QColor m_color_magenta;
     40QColor m_color_cyan;
     41QColor m_color_white;
     42
     43/*****************************************************************************/
     44OSDTypeTeletext::OSDTypeTeletext(const QString &name, QRect displayrect,
     45                                TTFFont *font)
     46    : OSDType(name)
     47{
     48    m_surface = NULL;
     49
     50    m_displayrect = displayrect;
     51    m_font = font;
     52
     53    m_tt_colspace = m_displayrect.width()  / COLS;
     54    m_tt_rowspace = m_displayrect.height() / ROWS;
     55
     56    m_color_black   = QColor(  0,  0,  0);
     57    m_color_red     = QColor(255,  0,  0);
     58    m_color_green   = QColor(  0,255,  0);
     59    m_color_yellow  = QColor(255,255,  0);
     60    m_color_blue    = QColor(  0,  0,255);
     61    m_color_magenta = QColor(255,  0,255);
     62    m_color_cyan    = QColor(  0,255,255);
     63    m_color_white   = QColor(255,255,255);
     64
     65    Reset();
     66
     67    m_curpage = 0x100;
     68    m_cursubpage = -1;
     69    m_curpage_showheader = true;
     70
     71    m_pageinput[0] = '1';
     72    m_pageinput[1] = '0';
     73    m_pageinput[2] = '0';
     74
     75    m_displaying = false;
     76
     77    // fill Bitswap
     78    for (int i = 0; i < 256; i++)
     79    {
     80        bitswap[i] = 0;
     81        for (int bit = 0; bit < 8; bit++)
     82            if (i & (1 << bit))
     83                bitswap[i] |= (1 << (7-bit));
     84    }
     85}
     86
     87OSDTypeTeletext::OSDTypeTeletext(const OSDTypeTeletext &other)
     88    : OSDType(other.m_name)
     89{
     90}
     91
     92OSDTypeTeletext::~OSDTypeTeletext()
     93{
     94}
     95
     96/** \fn OSDTypeTeletext::Reset()
     97*  \brief Resets the teletext data cache
     98*/
     99void OSDTypeTeletext::Reset()
     100{
     101    for (int mag = 0; mag < 8; ++mag)
     102    {
     103        QMutexLocker lock(&m_magazines[mag].lock);
     104
     105        // clear all sub pages in page
     106        std::map<int, TeletextPage>::iterator iter;
     107        iter = m_magazines[mag].pages.begin();
     108        while (iter != m_magazines[mag].pages.end())
     109        {
     110            TeletextPage *page = &iter->second;
     111            page->subpages.clear();
     112            ++iter;
     113        }
     114
     115        // clear pages
     116        m_magazines[mag].pages.clear();
     117        m_magazines[mag].current_page = 0;
     118        m_magazines[mag].current_subpage = 0;
     119    }
     120
     121    m_curpage = 0x100;
     122    m_cursubpage = -1;
     123    m_curpage_showheader = true;
     124}
     125
     126/** \fn OSDTypeTeletext::CharConversion(char, int)
     127*  \brief converts the given character to the given language
     128*/
     129char OSDTypeTeletext::CharConversion(char ch, int lang)
     130{
     131    int c = 0;
     132    for (int j = 0; j < 14; j++)
     133    {
     134        c = ch & 0x7F;
     135        if (c == lang_chars[0][j])
     136            ch = lang_chars[lang + 1][j];
     137    }
     138    return ch;
     139}
     140
     141/** \fn OSDTypeTeletext::AddPageHeader(int, int, uint8_t*, int)
     142*  \brief Adds a new page header
     143*         (page=0 if none)
     144*/
     145void OSDTypeTeletext::AddPageHeader(int page, int subpage, const uint8_t* buf, int vbimode, int lang, int flags)
     146{
     147    if (page < 256)
     148        return;
     149
     150    int magazine = MAGAZINE(page);
     151    int lastPage = m_magazines[magazine - 1].current_page;
     152    int lastSubPage = m_magazines[magazine - 1].current_subpage;
     153
     154    // update the last fetched page if the magazine is the same
     155    // and the page no. is different
     156    if (page != lastPage || subpage != lastSubPage)
     157        PageUpdated(lastPage, lastSubPage);
     158
     159    m_fetchpage = page;
     160    m_fetchsubpage = subpage;
     161
     162    TeletextSubPage *ttpage = FindSubPage(page, subpage);
     163
     164    if (ttpage == NULL)
     165    {
     166        ttpage = &m_magazines[magazine - 1].pages[page].subpages[subpage];
     167        m_magazines[magazine - 1].pages[page].pagenum = page;
     168        ttpage->subpagenum = subpage;
     169
     170        for (int i=0; i < 6; i++)
     171            ttpage->floflink[i] = 0;
     172    }
     173
     174    m_magazines[magazine - 1].current_page = page;
     175    m_magazines[magazine - 1].current_subpage = subpage;
     176
     177    ttpage->lang = lang;
     178    ttpage->flags = flags;
     179    ttpage->flof = 0;
     180
     181    ttpage->subtitle = (vbimode == VBI_DVB_SUBTITLE);
     182
     183    for (int j = 0; j < 8; j++)
     184        ttpage->data[0][j] = 32;
     185
     186    if (vbimode == VBI_DVB || vbimode == VBI_DVB_SUBTITLE)
     187    {
     188        for (int j = 8; j < 40; j++)
     189            ttpage->data[0][j] = bitswap[buf[j]];
     190    }
     191    else
     192    {
     193        memcpy(ttpage->data[0]+0, buf, 40);
     194        memset(ttpage->data[0]+40, ' ', sizeof(ttpage->data)-40);
     195    }
     196   
     197    if ( !(ttpage->flags & TP_INTERRUPTED_SEQ))
     198        HeaderUpdated(ttpage->data[0],ttpage->lang);
     199}
     200
     201/** \fn OSDTypeTeletext::AddTeletextData(int, int, uint8_t*)
     202*  \brief Adds Teletext Data from TeletextDecoder
     203*/
     204void OSDTypeTeletext::AddTeletextData(int magazine, int row,
     205                                      const uint8_t* buf, int vbimode)
     206{
     207    int b1, b2, b3, err;
     208
     209    if (magazine < 1 || magazine > 8)
     210        return;
     211
     212    int currentpage = m_magazines[magazine - 1].current_page;
     213    int currentsubpage = m_magazines[magazine -1].current_subpage;
     214    if (currentpage == 0)
     215        return;
     216
     217    TeletextSubPage *ttpage = FindSubPage(currentpage, currentsubpage);
     218
     219    if (ttpage == NULL)
     220        return;
     221
     222    switch (row)
     223    {
     224        case 1 ... 24: // Page Data
     225            if (vbimode == VBI_DVB || vbimode == VBI_DVB_SUBTITLE)
     226            {
     227                for (int j = 0; j < 40; j++)
     228                ttpage->data[row][j] = bitswap[buf[j]];
     229            }
     230            else
     231            {
     232                memcpy(ttpage->data[row], buf, 40);
     233            }
     234            break;
     235        case 26:
     236            /* XXX TODO: Level 1.5, 2.5, 3.5
     237            *      Character location & override
     238            * Level 2.5, 3.5
     239            *      Modifying display attributes
     240            * All levels
     241            *      VCR Programming
     242            * See 12.3
     243            */
     244            break;
     245        case 27: // FLOF data (FastText)
     246            switch (vbimode)
     247            {
     248                case VBI_IVTV:
     249                    b1 = hamm8(buf, &err);
     250                    b2 = hamm8(buf + 37, & err);
     251                    if (err & 0xF00)
     252                        return;
     253                     break;
     254                case VBI_DVB:
     255                case VBI_DVB_SUBTITLE:
     256                    b1 = hamm84(buf, &err);
     257                    b2 = hamm84(buf + 37, &err);
     258                    if (err == 1)
     259                        return;
     260                    break;
     261                default:
     262                    return;
     263            }
     264            if (b1 != 0 || not(b2 & 8))
     265                return;
     266
     267            for (int i = 0; i < 6; ++i)
     268            {
     269                err = 0;
     270                switch (vbimode)
     271                {
     272                    case VBI_IVTV:
     273                        b1 = hamm16(buf+1+6*i, &err);
     274                        b2 = hamm16(buf+3+6*i, &err);
     275                        b3 = hamm16(buf+5+6*i, &err);
     276                        if (err & 0xF000)
     277                            return;
     278                        break;
     279                    case VBI_DVB:
     280                    case VBI_DVB_SUBTITLE:
     281                        b1 = hamm84(buf+2+6*i, &err) * 16 +
     282                        hamm84(buf+1+6*i, &err);
     283                        b2 = hamm84(buf+4+6*i, &err) * 16 +
     284                        hamm84(buf+3+6*i, &err);
     285                        b3 = hamm84(buf+6+6*i, &err) * 16 +
     286                        hamm84(buf+5+6*i, &err);
     287                        if (err == 1)
     288                            return;
     289                        break;
     290                    default:
     291                        return;
     292                }
     293
     294                int x = (b2 >> 7) | ((b3 >> 5) & 0x06);
     295                ttpage->floflink[i] = ((magazine ^ x) ?: 8) * 256 + b1;
     296                ttpage->flof = 1;
     297            }
     298            break;
     299
     300        case 31: // private streams
     301            break;
     302
     303        default: /// other packet codes...
     304            break;
     305    }
     306}
     307
     308/** \fn OSDTypeTeletext::PageUpdated(int)
     309*  \brief Updates the page, if given pagenumber is the same
     310*         as the current shown page
     311*/
     312void OSDTypeTeletext::PageUpdated(int page, int subpage)
     313{
     314    if (!m_displaying)
     315        return;
     316
     317    if (page != m_curpage)
     318        return;
     319
     320    if (subpage != m_cursubpage && m_cursubpage != -1)
     321        return;
     322
     323
     324    if (m_surface != NULL)
     325    {
     326        m_surface->SetChanged(true);
     327        m_surface->ClearUsed();
     328        DrawPage();
     329    }
     330}
     331
     332/** \fn OSDTypeTeletext::HeaderUpdated(uint8_t*,int)
     333*  \brief Updates the header (given in page with language lang)
     334*
     335*  \param page Pointer to the header which should be displayed
     336*  \param lang Language of the header
     337*
     338*/
     339void OSDTypeTeletext::HeaderUpdated(uint8_t *page, int lang)
     340{
     341    if (!m_displaying)
     342        return;
     343
     344    if (page == NULL)
     345        return;
     346
     347    if (m_curpage_showheader == false)
     348        return;
     349
     350    if (m_surface != NULL)
     351        DrawHeader(page, lang);
     352}
     353
     354/** \fn OSDTypeTeletext::FindPage(int, int)
     355 *  \brief Finds the given page
     356 *
     357 *  \param page Page number
     358 *  \param direction find page before or after the given page
     359 *  \return TeletextPage (NULL if not found)
     360 */
     361TeletextPage* OSDTypeTeletext::FindPage(int page, int direction)
     362{
     363    TeletextPage *res = NULL;
     364    int mag = MAGAZINE(page);
     365
     366    if (mag > 8 || mag < 1)
     367        return NULL;
     368
     369    QMutexLocker lock(&m_magazines[mag - 1].lock);
     370
     371    std::map<int, TeletextPage>::iterator pageIter;
     372    pageIter = m_magazines[mag - 1].pages.find(page);
     373    if (pageIter == m_magazines[mag - 1].pages.end())
     374        return NULL;
     375
     376    res = &pageIter->second;
     377    if (direction == -1)
     378    {
     379        --pageIter;
     380        if (pageIter == m_magazines[mag - 1].pages.end())
     381        {
     382            std::map<int, TeletextPage>::reverse_iterator iter;
     383            iter = m_magazines[mag - 1].pages.rbegin();
     384            res = &iter->second;
     385        }
     386        else
     387            res = &pageIter->second;
     388    }
     389
     390    if (direction == 1)
     391    {
     392        ++pageIter;
     393        if (pageIter == m_magazines[mag - 1].pages.end())
     394        {
     395            pageIter = m_magazines[mag - 1].pages.begin();
     396            res = &pageIter->second;
     397        }
     398        else
     399            res = &pageIter->second;
     400    }
     401
     402    return res;
     403}
     404
     405/** \fn OSDTypeTeletext::FindSubPage(int, int, int)
     406*  \brief Finds the given page
     407*
     408*  \param page Page number
     409*  \param subpage Subpage number (if set to -1, find the first subpage)
     410*  \param direction find page before or after the given page (only if Subpage is not -1)
     411*  \return TeletextSubPage (NULL if not found)
     412*/
     413TeletextSubPage* OSDTypeTeletext::FindSubPage(int page, int subpage, int direction)
     414{
     415    TeletextSubPage *res = NULL;
     416    int mag = MAGAZINE(page);
     417
     418    if (mag > 8 || mag < 1)
     419        return NULL;
     420
     421    QMutexLocker lock(&m_magazines[mag - 1].lock);
     422
     423    if (subpage == -1)
     424    {
     425        // return the first subpage found
     426        std::map<int, TeletextPage>::iterator pageIter;
     427        pageIter = m_magazines[mag - 1].pages.find(page);
     428        if (pageIter == m_magazines[mag - 1].pages.end())
     429            return NULL;
     430
     431        TeletextPage *page = &pageIter->second;
     432        std::map<int, TeletextSubPage>::iterator subpageIter;
     433        subpageIter = page->subpages.begin();
     434        if (subpageIter == page->subpages.end())
     435            return NULL;
     436
     437        return &subpageIter->second;
     438    }
     439    else
     440    {
     441        // try to find the subpage given
     442        std::map<int, TeletextPage>::iterator pageIter;
     443        pageIter = m_magazines[mag - 1].pages.find(page);
     444        if (pageIter == m_magazines[mag - 1].pages.end())
     445            return NULL;
     446
     447        TeletextPage *page = &pageIter->second;
     448        std::map<int, TeletextSubPage>::iterator subpageIter;
     449        subpageIter = page->subpages.find(subpage);
     450        if (subpageIter == page->subpages.end())
     451            return NULL;
     452
     453        res = &subpageIter->second;
     454        if (direction == -1)
     455        {
     456            --subpageIter;
     457            if (subpageIter == page->subpages.end())
     458            {
     459                std::map<int, TeletextSubPage>::reverse_iterator iter;
     460                iter = page->subpages.rbegin();
     461                res = &iter->second;
     462            }
     463            else
     464                res = &subpageIter->second;
     465        }
     466
     467        if (direction == 1)
     468        {
     469            ++subpageIter;
     470            if (subpageIter == page->subpages.end())
     471            {
     472                subpageIter = page->subpages.begin();
     473                res = &subpageIter->second;
     474            }
     475            else
     476                res = &subpageIter->second;
     477        }
     478    }
     479
     480    return res;
     481}
     482
     483/** \fn OSDTypeTeletext::KeyPress(uint)
     484*  \brief What to do if a key is pressed
     485*
     486*  \param key pressed key
     487*  \sa TTKey
     488*/
     489void OSDTypeTeletext::KeyPress(uint key)
     490{
     491    int newPage = m_curpage;
     492    int newSubPage = m_cursubpage;
     493    bool numeric_input = false;
     494
     495    TeletextSubPage *curpage = FindSubPage(m_curpage, m_cursubpage);
     496    TeletextPage *page;
     497
     498    switch (key)
     499    {
     500        case TTKey::k0 ... TTKey::k9:
     501            numeric_input = true;
     502            m_curpage_showheader = true;
     503            if (m_pageinput[0] == ' ')
     504                m_pageinput[0] = '0' + static_cast<int> (key);
     505            else if (m_pageinput[1] == ' ')
     506                m_pageinput[1] = '0' + static_cast<int> (key);
     507            else if (m_pageinput[2] == ' ')
     508            {
     509                m_pageinput[2] = '0' + static_cast<int> (key);
     510                newPage = ((m_pageinput[0] - '0') * 256) +
     511                    ((m_pageinput[1] - '0') * 16) +
     512                    (m_pageinput[2] - '0');
     513                newSubPage = -1;
     514            }
     515            else
     516            {
     517                m_pageinput[0] = '0' + static_cast<int> (key);
     518                m_pageinput[1] = ' ';
     519                m_pageinput[2] = ' ';
     520            }
     521
     522            break;
     523
     524        case TTKey::kNextPage:
     525        {
     526            TeletextPage *ttpage = FindPage(m_curpage, 1);
     527            if (ttpage)
     528                newPage = ttpage->pagenum;
     529            newSubPage = -1;
     530            m_curpage_showheader = true;
     531            break;
     532        }
     533
     534        case TTKey::kPrevPage:
     535        {
     536            TeletextPage *ttpage = FindPage(m_curpage, -1);
     537            if (ttpage)
     538                newPage = ttpage->pagenum;
     539            newSubPage = -1;
     540            m_curpage_showheader = true;
     541            break;
     542        }
     543
     544        case TTKey::kNextSubPage:
     545        {
     546            TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage, 1);
     547            if (ttpage)
     548                newSubPage = ttpage->subpagenum;
     549            m_curpage_showheader = true;
     550            break;
     551        }
     552
     553        case TTKey::kPrevSubPage:
     554        {
     555            TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage, -1);
     556            if (ttpage)
     557                newSubPage = ttpage->subpagenum;
     558            m_curpage_showheader = true;
     559            break;
     560        }
     561
     562        case TTKey::kHold:
     563            break;
     564
     565        case TTKey::kTransparent:
     566            m_transparent = !m_transparent;
     567            PageUpdated(m_curpage, m_cursubpage);
     568            break;
     569
     570        case TTKey::kRevealHidden:
     571            m_revealHidden = !m_revealHidden;
     572            PageUpdated(m_curpage, m_cursubpage);
     573            break;
     574
     575        case TTKey::kFlofRed:
     576        {
     577            if (!curpage)
     578                return;
     579
     580            if ((page = FindPage(curpage->floflink[0])) != NULL)
     581            {
     582                newPage = page->pagenum;
     583                newSubPage = -1;
     584                m_curpage_showheader = true;
     585            }
     586            break;
     587        }
     588
     589        case TTKey::kFlofGreen:
     590        {
     591            if (!curpage)
     592                return;
     593
     594            if ((page = FindPage(curpage->floflink[1])) != NULL)
     595            {
     596                newPage = page->pagenum;
     597                newSubPage = -1;
     598                m_curpage_showheader = true;
     599            }
     600            break;
     601        }
     602
     603        case TTKey::kFlofYellow:
     604        {
     605            if (!curpage)
     606                return;
     607
     608            if ((page = FindPage(curpage->floflink[2])) != NULL)
     609            {
     610                newPage = page->pagenum;
     611                newSubPage = -1;
     612                m_curpage_showheader = true;
     613            }
     614            break;
     615        }
     616
     617        case TTKey::kFlofBlue:
     618        {
     619            if (!curpage)
     620                return;
     621
     622            if ((page = FindPage(curpage->floflink[3])) != NULL)
     623            {
     624                newPage = page->pagenum;
     625                newSubPage = -1;
     626                m_curpage_showheader = true;
     627            }
     628            break;
     629        }
     630
     631        case TTKey::kFlofWhite:
     632        {
     633            if (!curpage)
     634                return;
     635
     636            if ((page = FindPage(curpage->floflink[4])) != NULL)
     637            {
     638                newPage = page->pagenum;
     639                newSubPage = -1;
     640                m_curpage_showheader = true;
     641            }
     642            break;
     643        }
     644    }
     645
     646    if (newPage < 0x100)
     647        newPage = 0x100;
     648    if (newPage > 0x899)
     649        newPage = 0x899;
     650
     651    if (!numeric_input)
     652    {
     653        m_pageinput[0] = (newPage / 256) + '0';
     654        m_pageinput[1] = ((newPage % 256) / 16) + '0';
     655        m_pageinput[2] = (newPage % 16) + '0';
     656    }
     657
     658    if (newPage != m_curpage || newSubPage != m_cursubpage)
     659    {
     660        m_curpage = newPage;
     661        m_cursubpage = newSubPage;
     662        m_revealHidden = false;
     663        PageUpdated(m_curpage, m_cursubpage);
     664    }
     665}
     666
     667/** \fn OSDTypeTeletext::SetForegroundColor(int)
     668*  \brief Set the font color to the given color.
     669*
     670*   NOTE: TTColor::TRANSPARENT does not do anything!
     671*  \sa TTColor
     672*/
     673void OSDTypeTeletext::SetForegroundColor(int color)
     674{
     675    switch (color & ~TTColor::TRANSPARENT)
     676    {
     677        case TTColor::BLACK:   m_font->setColor(m_color_black);   break;
     678        case TTColor::RED:     m_font->setColor(m_color_red);     break;
     679        case TTColor::GREEN:   m_font->setColor(m_color_green);   break;
     680        case TTColor::YELLOW:  m_font->setColor(m_color_yellow);  break;
     681        case TTColor::BLUE:    m_font->setColor(m_color_blue);    break;
     682        case TTColor::MAGENTA: m_font->setColor(m_color_magenta); break;
     683        case TTColor::CYAN:    m_font->setColor(m_color_cyan);    break;
     684        case TTColor::WHITE:   m_font->setColor(m_color_white);   break;
     685    }
     686
     687    m_font->setShadow(0,0);
     688    m_font->setOutline(0);
     689}
     690
     691/** \fn OSDTypeTeletext:SetBackgroundColor(int)
     692*  \brief Set the background color to the given color
     693*
     694*  \sa TTColor
     695*/
     696void OSDTypeTeletext::SetBackgroundColor(int ttcolor)
     697{
     698    QColor color;
     699
     700    switch (ttcolor & ~TTColor::TRANSPARENT)
     701    {
     702        case TTColor::BLACK:   color = m_color_black;   break;
     703        case TTColor::RED:     color = m_color_red;     break;
     704        case TTColor::GREEN:   color = m_color_green;   break;
     705        case TTColor::YELLOW:  color = m_color_yellow;  break;
     706        case TTColor::BLUE:    color = m_color_blue;    break;
     707        case TTColor::MAGENTA: color = m_color_magenta; break;
     708        case TTColor::CYAN:    color = m_color_cyan;    break;
     709        case TTColor::WHITE:   color = m_color_white;   break;
     710    }
     711
     712    int r = color.red();
     713    int g = color.green();
     714    int b = color.blue();
     715
     716    float y = (0.299*r) + (0.587*g) + (0.114*b);
     717    float u = (0.564*(b - y)); // = -0.169R-0.331G+0.500B
     718    float v = (0.713*(r - y)); // = 0.500R-0.419G-0.081B
     719
     720    m_bgcolor_y = (uint8_t)(y);
     721    m_bgcolor_u = (uint8_t)(127 + u);
     722    m_bgcolor_v = (uint8_t)(127 + v);
     723    m_bgcolor_a = (ttcolor & TTColor::TRANSPARENT) ? 0x00 : 0xff;
     724}
     725
     726/** \fn OSDTypeTeletext::DrawBackground(int, int)
     727*  \brief draws background in the color set in setBackgroundColor
     728*
     729*  \param x X position (40 cols)
     730*  \param y Y position (25 rows)
     731*/
     732void OSDTypeTeletext::DrawBackground(int x, int y)
     733{
     734    x *= m_tt_colspace;
     735    x += m_displayrect.left();
     736
     737    y *= m_tt_rowspace;
     738    y += m_displayrect.top();
     739
     740    DrawRect(x, y, m_tt_colspace, m_tt_rowspace);
     741}
     742
     743/** \fn OSDTypeteletext::drawRect(int, int, int, int)
     744*  \brief draws a Rectangle at position x and y (width dx, height dy)
     745*         with the color set in setBackgroundColor
     746*
     747*  \param x X position at the screen
     748*  \param y Y position at the screen
     749*  \param dx width
     750*  \param dy height
     751*/
     752void OSDTypeTeletext::DrawRect(int x, int y, int dx, int dy)
     753{
     754    QRect all(x, y, dx, dy);
     755    m_surface->AddRect(all);
     756
     757    int luma_stride = m_surface->width;
     758    int chroma_stride = m_surface->width >> 1;
     759    int ye = y + dy;
     760
     761    unsigned char *buf_y = m_surface->y + (luma_stride * y) + x;
     762    unsigned char *buf_u = m_surface->u + (chroma_stride * (y>>1)) + (x>>1);
     763    unsigned char *buf_v = m_surface->v + (chroma_stride * (y>>1)) + (x>>1);
     764    unsigned char *buf_a = m_surface->alpha + (luma_stride * y) + x;
     765
     766    for (; y<ye; ++y)
     767    {
     768        for (int i=0; i<dx; ++i)
     769        {
     770            buf_y[i] = m_bgcolor_y;
     771            buf_a[i] = m_bgcolor_a;
     772        }
     773
     774        if ((y & 1) == 0)
     775        {
     776            for (int i=0; i<dx; ++i)
     777            {
     778                buf_u[i>>1] = m_bgcolor_u;
     779                buf_v[i>>1] = m_bgcolor_v;
     780            }
     781
     782            buf_u += chroma_stride;
     783            buf_v += chroma_stride;
     784        }
     785
     786        buf_y += luma_stride;
     787        buf_a += luma_stride;
     788    }
     789}
     790
     791/** \fn OSDTypeTeletext::DrawCharacter(int, int, QChar, int)
     792*  \brief Draws a character at posistion x, y
     793*
     794*  \param x X position (40 cols)
     795*  \param y Y position (25 rows)
     796*  \param ch Character
     797*  \param doubleheight if different to 0, draw doubleheighted character
     798*/
     799void OSDTypeTeletext::DrawCharacter(int x, int y, QChar ch, int doubleheight)
     800{
     801    if (!m_font)
     802        return;
     803
     804    QString line = ch;
     805
     806    x *= m_tt_colspace;
     807    x += m_displayrect.left();
     808
     809    y *= m_tt_rowspace;
     810    y += m_displayrect.top();
     811
     812    m_font->DrawString(m_surface, x, y, line,
     813                    m_surface->width, m_surface->height,
     814                    255, doubleheight!=0);
     815}
     816
     817/** \fn OSDTypeTeletext::DrawMosaic(int, int, code, int)
     818*  \brief Draws a mosaic as defined in ETSI EN 300 706
     819*
     820*  \param x X position (40 cols)
     821*  \param y Y position (25 rows)
     822*  \param code Code
     823*  \param doubleheight if different to 0, draw doubleheighted mosaic)
     824*/
     825void OSDTypeTeletext::DrawMosaic(int x, int y, int code, int doubleheight)
     826{
     827    (void)x;
     828    (void)y;
     829    (void)code;
     830
     831    x *= m_tt_colspace;
     832    x += m_displayrect.left();
     833
     834    y *= m_tt_rowspace;
     835    y += m_displayrect.top();
     836
     837    int dx = (int)round(m_tt_colspace / 2)+1;
     838    int dy = (int)round(m_tt_rowspace / 3)+1;
     839
     840    if (doubleheight != 0)
     841    {
     842        dx *= 2;
     843        dy *= 2;
     844    }
     845
     846    if (code & 0x10) DrawRect(x,      y + 2*dy, dx, dy);
     847    if (code & 0x40) DrawRect(x + dx, y + 2*dy, dx, dy);
     848    if (code & 0x01) DrawRect(x,      y,        dx, dy);
     849    if (code & 0x02) DrawRect(x + dx, y,        dx, dy);
     850    if (code & 0x04) DrawRect(x,      y + dy,   dx, dy);
     851    if (code & 0x08) DrawRect(x + dx, y + dy,   dx, dy);
     852}
     853
     854void OSDTypeTeletext::DrawLine(const uint8_t* page, uint row, int lang)
     855{
     856    bool mosaic;
     857    bool conceal;
     858    bool seperation;
     859    bool flash;
     860    bool doubleheight;
     861    bool blink;
     862    bool hold;
     863    bool endbox;
     864    bool startbox;
     865
     866    char last_ch = ' ';
     867    char ch;
     868
     869    uint fgcolor = TTColor::WHITE;
     870    uint bgcolor = TTColor::BLACK;
     871    uint newfgcolor = TTColor::WHITE;
     872    uint newbgcolor = TTColor::BLACK;
     873
     874    if (m_curpage_issubtitle || m_transparent)
     875    {
     876        bgcolor    = TTColor::TRANSPARENT;
     877        newbgcolor = TTColor::TRANSPARENT;
     878    }
     879
     880    SetForegroundColor(fgcolor);
     881    SetBackgroundColor(bgcolor);
     882
     883    mosaic = false;
     884    seperation = false;
     885    conceal = false;
     886    flash = false;
     887    doubleheight = false;
     888    blink = false;
     889    hold = false;
     890    endbox = false;
     891    startbox = false;
     892
     893    if (row == 1)
     894    {
     895        for (uint x = 0; x < 8; x++)
     896            DrawBackground(x, 1);
     897    }
     898
     899    for (uint x = (row == 1 ? 8 : 0); x < COLS; ++x)
     900    {
     901        if (startbox)
     902        {
     903            bgcolor = bgcolor = TTColor::BLACK;
     904            startbox = false;
     905        }
     906
     907        if (endbox)
     908        {
     909            bgcolor = TTColor::TRANSPARENT;
     910            endbox = false;
     911        }
     912
     913        SetForegroundColor(fgcolor);
     914        SetBackgroundColor(bgcolor);
     915
     916        ch = page[x] & 0x7F;
     917        switch (ch)
     918        {
     919            case 0x00 ... 0x07: // alpha + foreground color
     920                fgcolor = ch & 7;
     921                mosaic = false;
     922                conceal = false;
     923                goto ctrl;
     924            case 0x08: // flash
     925                // XXX
     926                goto ctrl;
     927            case 0x09: // steady
     928                flash = false;
     929                goto ctrl;
     930            case 0x0a: // end box
     931                endbox = true;
     932                goto ctrl;
     933            case 0x0b: // start box
     934                if (x < COLS - 1 && (page[x + 1] & 0x7F != 0x0b))
     935                    startbox = true;
     936                goto ctrl;
     937            case 0x0c: // normal height
     938                doubleheight = 0;
     939                goto ctrl;
     940            case 0x0d: // double height
     941                doubleheight = row < ROWS-1;
     942                goto ctrl;
     943            case 0x10 ... 0x17: // graphics + foreground color
     944                fgcolor = ch & 7;
     945                mosaic = true;
     946                conceal = false;
     947                goto ctrl;
     948            case 0x18: // conceal display
     949                conceal = true;
     950                goto ctrl;
     951            case 0x19: // contiguous graphics
     952                seperation = false;
     953                goto ctrl;
     954            case 0x1a: // separate graphics
     955                seperation = true;
     956                goto ctrl;
     957            case 0x1c: // black background
     958                bgcolor = TTColor::BLACK;
     959                goto ctrl;
     960            case 0x1d: // new background
     961                bgcolor = fgcolor;
     962                goto ctrl;
     963            case 0x1e: // hold graphics
     964                hold = true;
     965                goto ctrl;
     966            case 0x1f: // release graphics
     967                hold = false;
     968                goto ctrl;
     969            case 0x0e: // SO (reserved, double width)
     970            case 0x0f: // SI (reserved, double size)
     971            case 0x1b: // ESC (reserved)
     972                ch = ' ';
     973                break;
     974            ctrl:
     975                ch = ' ';
     976                if (hold && mosaic)
     977                    ch = last_ch;
     978            break;
     979
     980            case 0x80 ... 0x9f: // these aren't used
     981                ch = ' '; // BAD_CHAR;
     982                break;
     983            default:
     984                if (conceal && !m_revealHidden)
     985                    ch = ' ';
     986                break;
     987        }
     988
     989        newfgcolor = fgcolor;
     990        newbgcolor = bgcolor;
     991
     992        SetForegroundColor(newfgcolor);
     993        SetBackgroundColor(newbgcolor);
     994        if ((row != 0) || (x > 7))
     995        {
     996            if (m_transparent)
     997                SetBackgroundColor(TTColor::TRANSPARENT);
     998
     999            DrawBackground(x, row);
     1000            if (doubleheight != 0)
     1001                    DrawBackground(x, row +1);
     1002
     1003            if ((mosaic) && (ch < 0x40 || ch > 0x5F))
     1004            {
     1005                SetBackgroundColor(newfgcolor);
     1006                DrawMosaic(x, row, ch, doubleheight);
     1007            }
     1008            else
     1009            {
     1010                if (doubleheight != 0)
     1011                    DrawCharacter(x, row+1, CharConversion(ch, lang), doubleheight);
     1012                else
     1013                    DrawCharacter(x, row, CharConversion(ch, lang), doubleheight);
     1014            }
     1015        }
     1016    }
     1017}
     1018
     1019void OSDTypeTeletext::DrawHeader(const uint8_t* page, int lang)
     1020{
     1021    if (!m_displaying)
     1022        return;
     1023
     1024    DrawLine(page, 1, lang);
     1025    StatusUpdated();
     1026}
     1027
     1028void OSDTypeTeletext::DrawPage(void)
     1029{
     1030    if (!m_displaying)
     1031        return;
     1032
     1033    TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage);
     1034
     1035    if (ttpage == NULL)
     1036        return;
     1037
     1038    m_cursubpage = ttpage->subpagenum;
     1039
     1040    int a = 0;
     1041    if ((ttpage->subtitle) || (ttpage->flags &
     1042            (TP_SUPPRESS_HEADER + TP_NEWSFLASH + TP_SUBTITLE)))
     1043    {
     1044        a = 1;
     1045        m_curpage_showheader = false;
     1046        m_curpage_issubtitle = true;
     1047    }
     1048    else
     1049    {
     1050        m_curpage_issubtitle = false;
     1051        m_curpage_showheader = true;
     1052        DrawHeader(ttpage->data[0], ttpage->lang);
     1053    }
     1054
     1055    for (int y = ROWS-a; y >= 2; y--)
     1056        DrawLine(ttpage->data[y-1], y, ttpage->lang);
     1057}
     1058
     1059void OSDTypeTeletext::Reinit(float wchange, float hchange)
     1060{
     1061    m_displayrect = QRect((int)(m_displayrect.x() * wchange),
     1062                        (int)(m_displayrect.y() * hchange),
     1063                        (int)(m_displayrect.width() * wchange),
     1064                        (int)(m_displayrect.height() * hchange));
     1065
     1066    m_tt_colspace = m_displayrect.width()  / COLS;
     1067    m_tt_rowspace = m_displayrect.height() / ROWS;
     1068}
     1069
     1070void OSDTypeTeletext::Draw(OSDSurface *surface, int fade, int maxfade,
     1071                        int xoff, int yoff)
     1072{
     1073    (void)surface;
     1074    (void)fade;
     1075    (void)maxfade;
     1076    (void)xoff;
     1077    (void)yoff;
     1078
     1079    m_surface = surface;
     1080    DrawPage();
     1081}
     1082
     1083void OSDTypeTeletext::StatusUpdated(void)
     1084{
     1085    SetForegroundColor(TTColor::WHITE);
     1086    SetBackgroundColor(TTColor::BLACK);
     1087
     1088    if (!m_transparent)
     1089        for (int i = 0; i < 40; ++i)
     1090            DrawBackground(i, 0);
     1091
     1092    DrawCharacter(1, 0, 'P', 0);
     1093    DrawCharacter(2, 0, m_pageinput[0], 0);
     1094    DrawCharacter(3, 0, m_pageinput[1], 0);
     1095    DrawCharacter(4, 0, m_pageinput[2], 0);
     1096
     1097    TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage);
     1098
     1099    if (ttpage == NULL)
     1100    {
     1101        SetBackgroundColor(TTColor::BLACK);
     1102        SetForegroundColor(TTColor::WHITE);
     1103
     1104        if (!m_transparent)
     1105            for (int i = 7; i < 40; i++)
     1106                DrawBackground(i, 0);
     1107
     1108        char *str = "Page Not Available";
     1109        for (unsigned int i = 0; i < strlen(str); ++i)
     1110            DrawCharacter(i+10, 0, str[i], 0);
     1111
     1112        return;
     1113    }
     1114
     1115    // get list of available sub pages
     1116    QString str = "";
     1117    int count = 1, selected = 0;
     1118    TeletextPage *page = FindPage(m_curpage);
     1119    if (page)
     1120    {
     1121        std::map<int, TeletextSubPage>::iterator subpageIter;
     1122        subpageIter = page->subpages.begin();
     1123        while (subpageIter != page->subpages.end())
     1124        {
     1125            TeletextSubPage *subpage = &subpageIter->second;
     1126
     1127            if (subpage->subpagenum == m_cursubpage)
     1128            {
     1129                selected = count;
     1130                str += "*";
     1131            }
     1132            else
     1133                str += " ";
     1134
     1135            str += QString().sprintf("%02X", subpage->subpagenum);
     1136
     1137            ++subpageIter;
     1138            ++count;
     1139        }
     1140    }
     1141
     1142    if (str != "")
     1143    {
     1144        // if there are less than 9 subpages fill the empty slots with spaces
     1145        if (count < 10)
     1146        {
     1147            QString spaces;
     1148            spaces.fill(' ', 27 - str.length());
     1149            str = "  <" + str + spaces + " > ";
     1150        }
     1151        else
     1152        {
     1153            // try to centralize the selected sub page in the list
     1154            int startPos = selected - 5;
     1155            if (startPos < 0)
     1156                startPos = 0;
     1157            if (startPos + 9 >= count)
     1158                startPos = count - 10;
     1159
     1160            str = "  <" + str.mid(startPos * 3, 27) + " > ";
     1161        }
     1162
     1163        SetForegroundColor(TTColor::WHITE);
     1164        for (int x = 0; x < 11; x++)
     1165        {
     1166            if (m_transparent)
     1167                SetBackgroundColor(TTColor::TRANSPARENT);
     1168            else
     1169                SetBackgroundColor(TTColor::BLACK);
     1170
     1171            DrawBackground(x * 3 + 7, 0);
     1172
     1173            if (str[x * 3] == '*')
     1174            {
     1175                str[x * 3] = ' ';
     1176                SetBackgroundColor(TTColor::RED);
     1177            }
     1178
     1179            DrawBackground(x * 3 + 8, 0);
     1180            DrawBackground(x * 3 + 9, 0);
     1181
     1182            DrawCharacter(x * 3 + 7, 0, str[x * 3], 0);
     1183            DrawCharacter(x * 3 + 8, 0, str[x * 3 + 1], 0);
     1184            DrawCharacter(x * 3 + 9, 0, str[x * 3 + 2], 0);
     1185        }
     1186    }
     1187}
     1188
  • libs/libmythtv/osdtypes.cpp

     
    1111#include "ttfont.h"
    1212#include "osdsurface.h"
    1313#include "osdlistbtntype.h"
     14#include "osdtypeteletext.h"
    1415
    1516#include "mythcontext.h"
    1617
     
    101102            OSDTypeText *newtext = new OSDTypeText(*item);
    102103            AddType(newtext);
    103104        }
     105        else if (OSDTypeTeletext *item = dynamic_cast<OSDTypeTeletext*>(type))
     106        {
     107            OSDTypeTeletext *newtt = new OSDTypeTeletext(*item);
     108            AddType(newtt);
     109        }
    104110        else if (OSDTypePositionImage *item =
    105111                  dynamic_cast<OSDTypePositionImage*>(type))
    106112        {
     
    180186        {
    181187            item->Reinit(wchange, hchange);
    182188        }
     189        else if (OSDTypeTeletext *item = dynamic_cast<OSDTypeTeletext*>(type))
     190        {
     191            item->Reinit(wchange, hchange);
     192        }
    183193        else if (OSDTypePositionImage *item =
    184194                 dynamic_cast<OSDTypePositionImage*>(type))
    185195        {
     
    657667 
    658668void OSDTypeText::DrawString(OSDSurface *surface, QRect rect,
    659669                             const QString &text, int fade, int maxfade,
    660                              int xoff, int yoff)
     670                             int xoff, int yoff, bool doubl)
    661671{
    662672    if (m_centered || m_right)
    663673    {
     
    694704    if (m_usingalt && m_altfont)
    695705        font = m_altfont;
    696706
    697     font->DrawString(surface, x, y, text, maxx, maxy, alphamod);
     707    font->DrawString(surface, x, y, text, maxx, maxy, alphamod, doubl);
    698708}
    699709
    700710//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • libs/libmythtv/tv_play.cpp

     
    3333#include "config.h"
    3434#include "livetvchain.h"
    3535#include "playgroup.h"
     36#include "osdtypeteletext.h"
     37#include "teletextdecoder.h"
    3638
    3739#ifndef HAVE_ROUND
    3840#define round(x) ((int) ((x) + 0.5))
     
    119121            "W");
    120122    REG_KEY("TV Playback", "TOGGLECC", "Toggle Closed Captioning/Teletext",
    121123            "T");
     124    REG_KEY("TV Playback", "MENURED",        "Menu Red",        "F2");
     125    REG_KEY("TV Playback", "MENUGREEN",      "Menu Green",      "F3");
     126    REG_KEY("TV Playback", "MENUYELLOW",     "Menu Yellow",     "F4");
     127    REG_KEY("TV Playback", "MENUBLUE",       "Menu Blue",       "F5");
     128    REG_KEY("TV Playback", "MENUWHITE",      "Menu White",      "F6");
     129    REG_KEY("TV Playback", "REVEAL",         "Teletext reveal hidden Text", "F7");
    122130    REG_KEY("TV Playback", "DISPCC1", "Display CC1", "");
    123131    REG_KEY("TV Playback", "DISPCC2", "Display CC2", "");
    124132    REG_KEY("TV Playback", "DISPCC3", "Display CC3", "");
     
    179187  Global:   Return, Enter, Space, Esc
    180188
    181189  Global:          F1,
    182   Playback: Ctrl-B,   F7,F8,F9,F10,F11
     190  Playback: Ctrl-B,   F2,F3,F4,F5,F6,F7,F8,F9,F10,F11
    183191 */
    184192}
    185193
     
    212220      exitPlayer(false), paused(false), errored(false),
    213221      stretchAdjustment(false),
    214222      audiosyncAdjustment(false), audiosyncBaseline(LONG_LONG_MIN),
    215       editmode(false), zoomMode(false), sigMonMode(false),
     223      editmode(false),     zoomMode(false),
     224      teletextmode(false), sigMonMode(false),
    216225      update_osd_pos(false), endOfRecording(false), requestDelete(false),
    217226      doSmartForward(false),
    218227      queuedTranscode(false), getRecorderPlaybackInfo(false),
     
    10841093
    10851094    if (nvp->IsPlaying())
    10861095    {
     1096        TeletextDecoder *tt_dec = nvp->GetTeletextDecoder();
     1097       
     1098        // This is needed because the OSDType does the decoding/caching of
     1099        // the teletext pages
     1100        OSDSet *oset = GetOSD()->GetSet("teletext");
     1101        if (oset)
     1102        {
     1103            OSDType *traw = oset->GetType("teletext");
     1104            OSDTypeTeletext *tt_view = dynamic_cast<OSDTypeTeletext*>(traw);
     1105            tt_dec->SetViewer(tt_view);
     1106        }
     1107
    10871108        activenvp = nvp;
    10881109        activerbuffer = prbuffer;
    10891110        StartOSD();
     
    17531774            return;
    17541775    }
    17551776
     1777    //XXX ivtv/dvb teletext
     1778    if (teletextmode)
     1779    {
     1780        int passThru = 0;
     1781
     1782        for (unsigned int i = 0; i < actions.size() && !handled; i++)
     1783        {
     1784            QString action = actions[i];
     1785            handled = true;
     1786            if (action == "UP")
     1787                TeletextNavigate(-1);
     1788            else if (action == "DOWN")
     1789                TeletextNavigate(-2);
     1790            else if (action == "RIGHT")
     1791                TeletextNavigate(-3);
     1792            else if (action == "LEFT")
     1793                TeletextNavigate(-4);
     1794            else if (action == "TOGGLEASPECT")
     1795                TeletextNavigate(-5);
     1796            else if (action == "MENURED")
     1797                TeletextNavigate(-6);
     1798            else if (action == "MENUGREEN")
     1799                TeletextNavigate(-7);
     1800            else if (action == "MENUYELLOW")
     1801                TeletextNavigate(-8);
     1802            else if (action == "MENUBLUE")
     1803                TeletextNavigate(-9);
     1804            else if (action == "MENUWHITE")
     1805                TeletextNavigate(-10);
     1806            else if (action == "REVEAL")
     1807                TeletextNavigate(-11);
     1808            else if (action == "0" || action == "1" || action == "2" ||
     1809                     action == "3" || action == "4" || action == "5" ||
     1810                     action == "6" || action == "7" || action == "8" ||
     1811                     action == "9")
     1812                TeletextNavigate(action.toInt());
     1813            else if (action == "MENU" || action == "TOGGLECC" ||
     1814                     action == "ESCAPE")
     1815                TeletextStop();
     1816            else
     1817                handled = false;
     1818        }
     1819        if (!passThru)
     1820            return;
     1821    }
     1822
    17561823    if (zoomMode)
    17571824    {
    17581825        int passThru = 0;
     
    20012068        handled = true;
    20022069
    20032070        if (action == "TOGGLECC" && !browsemode)
    2004         {
    2005             if (vbimode == VBIMode::NTSC_CC)
     2071        {
     2072            int dec_type = nvp->GetTeletextDecoder()->GetDecoderType();
     2073            if (dec_type != -1)
     2074                TeletextStart();
     2075            else if (vbimode == VBIMode::NTSC_CC)
    20062076                nvp->ToggleCC(vbimode, 0);
    20072077            else if (ccInputMode)
    20082078            {
     
    32333303            aud->ToggleMute();
    32343304            muted = true;
    32353305        }
     3306        OSDSet *oset = GetOSD()->GetSet("teletext");
     3307        if (oset)
     3308        {
     3309            OSDType *traw = oset->GetType("teletext");
     3310            OSDTypeTeletext *tt_view = dynamic_cast<OSDTypeTeletext*>(traw);
     3311            if (tt_view)
     3312                tt_view->Reset();
     3313        }
    32363314    }
    32373315
    32383316    if (nvp && (activenvp == nvp) && paused)
     
    34613539            aud->ToggleMute();
    34623540            muted = true;
    34633541        }
     3542        OSDSet *oset = GetOSD()->GetSet("teletext");
     3543        if (oset)
     3544        {
     3545            OSDType *traw = oset->GetType("teletext");
     3546            OSDTypeTeletext *tt_view = dynamic_cast<OSDTypeTeletext*>(traw);
     3547            if (tt_view)
     3548                tt_view->Reset();
     3549        }
    34643550    }
    34653551
    34663552    if (nvp && (activenvp == nvp) && paused && GetOSD())
     
    47724858        GetOSD()->SetSettingsText(msg, 3);
    47734859}
    47744860
     4861//XXX new teletext
     4862void TV::TeletextStart(void)
     4863{
     4864    if (activenvp != nvp)
     4865        return;
     4866
     4867    if (paused || !GetOSD())
     4868        return;
     4869
     4870    TeletextDecoder *tt_dec = nvp->GetTeletextDecoder();
     4871    OSDSet *oset = GetOSD()->GetSet("teletext");
     4872    if (!oset)
     4873    {
     4874        VERBOSE(VB_IMPORTANT, LOC_ERR + "No teletext set available");
     4875        return;
     4876    }
     4877
     4878    OSDType *traw = oset->GetType("teletext");
     4879    OSDTypeTeletext *tt_view = dynamic_cast<OSDTypeTeletext*>(traw);
     4880    if (!tt_view)
     4881    {
     4882        VERBOSE(VB_IMPORTANT, LOC_ERR + "No teletext type available");
     4883        return;
     4884    }
     4885
     4886    tt_dec->SetViewer(tt_view);
     4887    tt_view->SetDisplaying(true);
     4888
     4889    teletextmode = true;
     4890
     4891    oset->Display();
     4892    GetOSD()->SetVisible(oset, 0);
     4893}
     4894
     4895void TV::TeletextNavigate(int page)
     4896{
     4897    if (!GetOSD())
     4898        return;
     4899
     4900    OSDSet *oset = GetOSD()->GetSet("teletext");
     4901    if (!oset)
     4902    {
     4903        VERBOSE(VB_IMPORTANT, LOC_ERR + "No teletext set available");
     4904        return;
     4905    }
     4906
     4907    OSDType *traw = oset->GetType("teletext");
     4908    OSDTypeTeletext *tt = dynamic_cast<OSDTypeTeletext*>(traw);
     4909    if (!tt)
     4910    {
     4911        VERBOSE(VB_IMPORTANT, LOC_ERR + "No teletext type available");
     4912        return;
     4913    }
     4914
     4915    switch (page)
     4916    {
     4917        case -1:
     4918            tt->KeyPress(TTKey::kNextPage);
     4919            break;
     4920        case -2:
     4921            tt->KeyPress(TTKey::kPrevPage);
     4922            break;
     4923        case -3:
     4924            tt->KeyPress(TTKey::kNextSubPage);
     4925            break;
     4926        case -4:
     4927            tt->KeyPress(TTKey::kPrevSubPage);
     4928            break;
     4929        case -5:
     4930            tt->KeyPress(TTKey::kTransparent);
     4931            break;
     4932        case -6:
     4933            tt->KeyPress(TTKey::kFlofRed);
     4934            break;
     4935        case -7:
     4936            tt->KeyPress(TTKey::kFlofGreen);
     4937            break;
     4938        case -8:
     4939            tt->KeyPress(TTKey::kFlofYellow);
     4940            break;
     4941        case -9:
     4942            tt->KeyPress(TTKey::kFlofBlue);
     4943            break;
     4944        case -10:
     4945            tt->KeyPress(TTKey::kFlofWhite);
     4946            break;
     4947        case -11:
     4948            tt->KeyPress(TTKey::kRevealHidden);
     4949            break;
     4950        case 0 ... 9:
     4951            tt->KeyPress(page);
     4952            break;
     4953    }
     4954}
     4955
     4956void TV::TeletextStop(void)
     4957{
     4958    if (!teletextmode || !GetOSD())
     4959        return;
     4960
     4961    OSDSet *oset = GetOSD()->GetSet("teletext");
     4962    if (oset)
     4963    {
     4964        OSDType *traw = oset->GetType("teletext");
     4965        OSDTypeTeletext *tt_view = dynamic_cast<OSDTypeTeletext*>(traw);
     4966        if (tt_view)
     4967           tt_view->SetDisplaying(false);
     4968    }   
     4969    GetOSD()->HideSet("teletext");
     4970
     4971    // nvp->GetTeletextDecoder()->SetViewer(NULL);
     4972
     4973    teletextmode = false;
     4974}
     4975
    47754976void TV::BrowseChannel(const QString &chan)
    47764977{
    47774978    if (!activerecorder->CheckChannel(chan))
     
    49665167    QString action = item->getAction();
    49675168
    49685169    if (action == "TOGGLECC")
    4969         nvp->ToggleCC(vbimode, 0);
     5170    {
     5171        if (nvp->GetTeletextDecoder()->GetDecoderType() != -1)
     5172            TeletextStart();
     5173        else
     5174            nvp->ToggleCC(vbimode, 0);
     5175    }
    49705176    else if (action.left(6) == "DISPCC")
    49715177        nvp->ToggleCC(vbimode, action.right(1).toInt());
    49725178    else if (action.left(7) == "DISPTXT")
     
    56945900        activerbuffer->IgnoreLiveEOF(false);
    56955901    }
    56965902
     5903    //if (nvp)
     5904    //    nvp->GetTeletextDecoder()->Reset();
     5905
    56975906    if (!nvp || (nvp && activenvp == nvp))
    56985907    {
    56995908        UpdateOSDProgInfo("program_info");
  • libs/libmythtv/libmythtv.pro

     
    188188    SOURCES += progfind.cpp             ttfont.cpp
    189189
    190190    # Teletext stuff
     191    HEADERS += teletextdecoder.h        osdtypeteletext.h
    191192    HEADERS += vbilut.h
     193    SOURCES += teletextdecoder.cpp      osdtypeteletext.cpp
    192194    SOURCES += vbilut.cpp
    193195
    194196    # C stuff
  • libs/libmythtv/osdtypeteletext.h

     
     1#ifndef OSD_TYPE_TELETEXT_H_
     2#define OSD_TYPE_TELETEXT_H_
     3
     4#include <vector>
     5using namespace std;
     6
     7#include <qstring.h>
     8#include <qrect.h>
     9#include <qmap.h>
     10#include <qvaluelist.h>
     11#include <qobject.h>
     12#include <qcolor.h>
     13#include <qmutex.h>
     14
     15#include "osdtypes.h"
     16#include "teletextdecoder.h"
     17
     18class TTFFont;
     19class OSDType;
     20class OSDSurface;
     21class TV;
     22
     23class TTColor
     24{
     25  public:
     26    static const uint BLACK       = 0;
     27    static const uint RED         = 1;
     28    static const uint GREEN       = 2;
     29    static const uint YELLOW      = 3;
     30    static const uint BLUE        = 4;
     31    static const uint MAGENTA     = 5;
     32    static const uint CYAN        = 6;
     33    static const uint WHITE       = 7;
     34    static const uint TRANSPARENT = 8;
     35};
     36
     37class TTKey
     38{
     39  public:
     40    static const uint k0            = 0;
     41    static const uint k1            = 1;
     42    static const uint k2            = 2;
     43    static const uint k3            = 3;
     44    static const uint k4            = 4;
     45    static const uint k5            = 5;
     46    static const uint k6            = 6;
     47    static const uint k7            = 7;
     48    static const uint k8            = 8;
     49    static const uint k9            = 9;
     50    static const uint kNextPage     = 10;
     51    static const uint kPrevPage     = 11;
     52    static const uint kNextSubPage  = 12;
     53    static const uint kPrevSubPage  = 13;
     54    static const uint kHold         = 14;
     55    static const uint kTransparent  = 15;
     56    static const uint kFlofRed      = 16;
     57    static const uint kFlofGreen    = 17;
     58    static const uint kFlofYellow   = 18;
     59    static const uint kFlofBlue     = 19;
     60    static const uint kFlofWhite    = 20;
     61    static const uint kRevealHidden = 21;
     62};
     63
     64#define TP_SUPPRESS_HEADER  0x01
     65#define TP_UPDATE_INDICATOR 0x02
     66#define TP_INTERRUPTED_SEQ  0x04
     67#define TP_INHIBIT_DISPLAY  0x08
     68#define TP_MAGAZINE_SERIAL  0x10
     69#define TP_ERASE_PAGE       0x20
     70#define TP_NEWSFLASH        0x40
     71#define TP_SUBTITLE         0x80
     72
     73class TeletextSubPage
     74{
     75  public:
     76    int pagenum, subpagenum;  ///< the wanted page number
     77    int lang;                 ///< language code
     78    int flags;                ///< misc flags
     79    uint8_t data[25][40];     ///< page data
     80    int flof;                 ///< page has FastText links
     81    int floflink[6];          ///< FastText links (FLOF)
     82    bool subtitle;            ///< page is subtitle page
     83};
     84
     85class TeletextPage
     86{
     87  public:
     88    int pagenum;
     89    int current_subpage;
     90    std::map<int, TeletextSubPage> subpages;
     91};
     92
     93#define MAGAZINE(page) page / 256
     94
     95class TeletextMagazine
     96{
     97  public:
     98    QMutex lock;
     99    int current_page;
     100    int current_subpage;
     101    std::map<int, TeletextPage> pages;
     102};
     103
     104class OSDTypeTeletext : public OSDType
     105{
     106    Q_OBJECT
     107  public:
     108    OSDTypeTeletext(const QString &name, QRect displayrect, TTFFont *font);
     109    OSDTypeTeletext(const OSDTypeTeletext &other);
     110    ~OSDTypeTeletext();
     111
     112    void Reset();
     113
     114    void Reinit(float wchange, float hchange);
     115
     116    void Draw(OSDSurface *surface, int fade, int maxfade, int xoff, int yoff);
     117
     118    void SetForegroundColor(int color);
     119    void SetBackgroundColor(int color);
     120
     121    void DrawBackground(int x, int y);
     122    void DrawRect(int x, int y, int dx, int dy);
     123    void DrawCharacter(int x, int y, QChar ch, int doubleheight = 0);
     124    void DrawMosaic(int x, int y, int code, int doubleheight);
     125
     126    void DrawLine(const uint8_t* page, uint row, int lang);
     127    void DrawHeader(const uint8_t* page, int lang);
     128    void DrawPage(void);
     129
     130    void NewsFlash(void) {};
     131
     132    void AddPageHeader(int page, int subpage, const uint8_t *buf, int vbimode, int lang, int flags);
     133    void AddTeletextData(int magazine, int row, const uint8_t* buf, int vbimode);
     134
     135    void PageUpdated(int page, int subpage);
     136    void HeaderUpdated(uint8_t* page, int lang);
     137    void StatusUpdated(void);
     138
     139    void KeyPress(uint key);
     140
     141    void SetDisplaying(bool display) { m_displaying = display; };
     142
     143  private:
     144    QMutex       m_lock;
     145    QRect        m_displayrect;
     146
     147    TTFFont     *m_font;
     148    OSDSurface  *m_surface;
     149    OSDTypeBox  *m_box;
     150
     151    int          m_tt_colspace;
     152    int          m_tt_rowspace;
     153
     154    uint8_t      m_bgcolor_y;
     155    uint8_t      m_bgcolor_u;
     156    uint8_t      m_bgcolor_v;
     157    uint8_t      m_bgcolor_a;
     158
     159    // last fetched page
     160    int m_fetchpage;
     161    int m_fetchsubpage;
     162
     163    // currently displayed page:
     164    int m_curpage;
     165    int m_cursubpage;
     166    int m_pageinput[3];
     167    bool m_curpage_showheader;
     168    bool m_curpage_issubtitle;
     169
     170    bool m_transparent;
     171    bool m_revealHidden;
     172
     173    bool m_displaying;
     174
     175    TeletextMagazine m_magazines[8];
     176    unsigned char    bitswap[256];
     177
     178    char CharConversion(char ch, int lang);
     179    TeletextSubPage *FindSubPage(int page, int subpage, int direction = 0);
     180    TeletextPage    *FindPage(int page, int direction = 0);
     181
     182    static const uint COLS = 40;
     183    static const uint ROWS = 26;
     184};
     185
     186#endif
     187
  • libs/libmythtv/osdtypes.h

     
    186186
    187187  private:
    188188    void DrawString(OSDSurface *surface, QRect rect, const QString &text,
    189                     int fade, int maxfade, int xoff, int yoff);
     189                    int fade, int maxfade, int xoff, int yoff,
     190                    bool double_size=false);
    190191
    191192    QRect m_displaysize;
    192193    QRect m_screensize;
  • libs/libmythtv/tv_play.h

     
    257257    void DoSkipCommercials(int direction);
    258258    void DoEditMode(void);
    259259
     260    void TeletextStart(void);
     261    void TeletextNavigate(int num);
     262    void TeletextStop(void);
     263   
    260264    void DoQueueTranscode(void); 
    261265
    262266    void SetAutoCommercialSkip(int skipMode = 0);
     
    361365    long long audiosyncBaseline;
    362366    bool editmode;          ///< Are we in video editing mode
    363367    bool zoomMode;
     368    bool teletextmode;   ///< Are we in teletext switching mode?
    364369    bool sigMonMode;     ///< Are we in signal monitoring mode?
    365370    bool update_osd_pos; ///< Redisplay osd?
    366371    bool endOfRecording; ///< !nvp->IsPlaying() && StateIsPlaying(internalState)
  • libs/libmythtv/avformatdecoder.h

     
    88#include "format.h"
    99#include "decoderbase.h"
    1010#include "ccdecoder.h"
     11#include "teletextdecoder.h"
     12#include "vbilut.h"
    1113
    1214extern "C" {
    1315#include "frame.h"
     
    232234
    233235    // Caption/Subtitle/Teletext decoders
    234236    CCDecoder        *ccd;
     237    TeletextDecoder  *ttd;
    235238
    236239    // Audio
    237240    short int        *audioSamples;
  • libs/libmythtv/osdsurface.cpp

     
    8686    memset(u, 127, size / 4);
    8787    memset(v, 127, size / 4);
    8888    memset(alpha, 0, size);
     89    usedRegionsLock.lock();
    8990    usedRegions = QRegion();
     91    usedRegionsLock.unlock();
    9092}
    9193
    9294void OSDSurface::ClearUsed(void)
    9395{
     96    usedRegionsLock.lock();
    9497    QMemArray<QRect> rects = usedRegions.rects();
    9598    QMemArray<QRect>::Iterator it = rects.begin();
    9699    QRect drawRect;
     
    129132    }
    130133
    131134    usedRegions = QRegion();
     135    usedRegionsLock.unlock();
    132136}
    133137
    134138bool OSDSurface::IntersectsDrawn(QRect &newrect)
    135139{
     140    QMutexLocker lock(&usedRegionsLock);
    136141    QMemArray<QRect> rects = usedRegions.rects();
    137142    QMemArray<QRect>::Iterator it = rects.begin();
    138143    for (; it != rects.end(); ++it)
     
    143148
    144149void OSDSurface::AddRect(QRect &newrect)
    145150{
     151    usedRegionsLock.lock();
    146152    usedRegions = usedRegions.unite(newrect);
     153    usedRegionsLock.unlock();
    147154}
    148155
    149156///////////////////////////////////////////////////////////////////////////
     
    551558 */
    552559void OSDSurface::BlendToYV12(unsigned char *yuvptr) const
    553560{
     561    usedRegionsLock.lock();
    554562    const OSDSurface *surface = this;
    555563    blendtoyv12_8_fun blender = blendtoyv12_8_init(surface);
    556564
     
    649657            }
    650658        }
    651659    }
     660    usedRegionsLock.unlock();
    652661}
    653662
    654663static void BlendToBlack(unsigned char *argbptr, uint width, uint outheight)
     
    686695                             uint outheight, bool blend_to_black,
    687696                             uint threshold) const
    688697{
     698    usedRegionsLock.lock();
    689699    const OSDSurface *surface = this;
    690700    blendtoargb_8_fun blender = blendtoargb_8_init(surface);
    691701    const unsigned char *cm = surface->cm;
     
    756766    }
    757767    if (blend_to_black)
    758768        BlendToBlack(argbptr, stride>>2, outheight);
     769
     770    usedRegionsLock.unlock();
    759771}
    760772
    761773/** \fn OSDSurface::DitherToI44(unsigned char*,bool,uint,uint) const
     
    772784void OSDSurface::DitherToI44(unsigned char *outbuf, bool ifirst,
    773785                             uint stride, uint outheight) const
    774786{
     787    usedRegionsLock.lock();
    775788    const OSDSurface *surface = this;
    776789    int ashift = ifirst ? 0 : 4;
    777790    int amask = ifirst ? 0x0f : 0xf0;
     
    855868    }
    856869
    857870    delete_dithertoia44_8_context(dcontext);
     871    usedRegionsLock.unlock();
    858872}
    859873
    860874/** \fn OSDSurface::DitherToIA44(unsigned char*,uint,uint) const
  • libs/libmythtv/vbilut.cpp

     
    325325    0x00000, 0x00800, 0x01000, 0x02000, 0x04000, 0x08000, 0x10000, 0x20000,
    326326    0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
    327327};
     328
     329int hamm8(const uint8_t *p, int *err)
     330{
     331    int a =hammtab[p[0]];
     332    *err += a;
     333    return a & 15;
     334}
     335
     336int hamm84(const uint8_t *p, int *err)
     337{
     338    int a = hamm84tab[p[0]];
     339
     340    if (a == 255)
     341        *err = 1;
     342
     343    return a;
     344}
     345
     346int hamm16(const uint8_t *p, int *err)
     347{
     348    int a = hammtab[p[0]];
     349    int b = hammtab[p[1]];
     350    *err += a;
     351    *err += b;
     352    return (a & 15) | (b & 15) * 16;
     353}
  • libs/libmythtv/ttfont.cpp

     
    157157   delete rmap;
    158158}
    159159
    160 Raster_Map *TTFFont::calc_size(int *width, int *height, const QString &text)
     160Raster_Map *TTFFont::calc_size(int *width, int *height,
     161                               const QString &text, bool double_size)
    161162{
    162163   unsigned int i, pw, ph;
    163164   Raster_Map *rtmp;
     
    165166   pw = 0;
    166167   ph = ((max_ascent) - max_descent) / 64;
    167168
     169   if (double_size)
     170       ph *= 2;
     171
    168172   for (i = 0; i < text.length(); i++)
    169173   {
    170174       unsigned short j = text[i].unicode();
     
    200204}
    201205
    202206void TTFFont::render_text(Raster_Map *rmap, Raster_Map *rchr,
    203                           const QString &text, int *xorblah, int *yor)
     207                          const QString &text, int *xorblah, int *yor,
     208                          bool double_size)
    204209{
    205210   FT_F26Dot6 x, y, xmin, ymin, xmax, ymax;
    206211   FT_BBox bbox;
    207212   unsigned int i, ioff, iread;
    208    char *off, *read, *_off, *_read;
     213   char *off, *off2, *read, *_off, *_off2, *_read;
    209214   int x_offset, y_offset;
    210215   unsigned short j, previous;
    211216   Raster_Map *rtmp;
     
    326331
    327332       _read = (char *)rtmp->bitmap + iread;
    328333       _off = (char *)rmap->bitmap + ioff;
    329 
     334       _off2 = _off - rmap->cols;
     335       
    330336       for (y = ymin; y <= ymax; y++)
    331337       {
    332338           read = _read;
    333339           off = _off;
     340           off2 = _off2;
    334341
    335342           for (x = xmin; x <= xmax; x++)
    336343           {
    337                *off = *read;
     344               *off = *read;
     345               if (double_size)
     346               {
     347                   *off2 = *read;
     348                   off2++;
     349               }
    338350               off++;
    339351               read++;
    340352           }
    341353           _read -= rtmp->cols;
    342354           _off -= rmap->cols;
     355           if (double_size)
     356           {
     357               _off -= rmap->cols;
     358               _off2 -= rmap->cols;
     359               _off2 -= rmap->cols;
     360           }
    343361       }
    344362       if (glyphs[j]->advance.x == 0)
    345363           x_offset += 4;
     
    413431
    414432void TTFFont::DrawString(OSDSurface *surface, int x, int y,
    415433                         const QString &text, int maxx, int maxy,
    416                          int alphamod)
     434                         int alphamod, bool double_size)
    417435{
    418436   int                  width, height, w, h, inx, iny, clipx, clipy;
    419437   Raster_Map          *rmap, *rtmp;
     
    425443   inx = 0;
    426444   iny = 0;
    427445
    428    rtmp = calc_size(&w, &h, text);
     446   rtmp = calc_size(&w, &h, text, double_size);
    429447   if (w <= 0 || h <= 0)
    430448   {
    431449       destroy_font_raster(rtmp);
     
    433451   }
    434452   rmap = create_font_raster(w, h);
    435453
    436    render_text(rmap, rtmp, text, &inx, &iny);
     454   render_text(rmap, rtmp, text, &inx, &iny, double_size);
    437455
    438456   is_pixmap = 1;
    439457
     
    442460   width = maxx;
    443461   height = maxy;
    444462
     463   if (double_size)
     464       height *= 2;
     465
    445466   clipx = 0;
    446467   clipy = 0;
    447468
  • libs/libmythtv/osd.cpp

     
    2626#include "libmyth/oldsettings.h"
    2727#include "udpnotify.h"
    2828
     29#include "osdtypeteletext.h"
    2930#include "osdlistbtntype.h"
    3031
    3132static float sq(float a) { return a*a; }
     
    115116
    116117void OSD::SetDefaults(void)
    117118{
     119    OSDSet *container = NULL;
     120// TODO begin -- deleted in teletext patch
    118121    TTFFont *ccfont = GetFont("cc_font");
    119122    if (!ccfont)
    120123    {
     
    130133    if (!ccfont)
    131134        return;
    132135
    133     OSDSet *container = GetSet("cc_page");
    134     if (!container)
     136    if (!GetSet("cc_page"))
    135137    {
    136138        QString name = "cc_page";
    137139        container = new OSDSet(name, true,
     
    157159                                          sub_dispw, sub_disph);
    158160        container->AddType(ccpage);
    159161    }
     162// TODO end -- deleted in teletext patch
    160163
    161     container = GetSet("menu");
    162     if (!container)
     164    if (!GetSet("teletext"))
    163165    {
     166        QString name = "teletext";
     167        container = new OSDSet(name, true,
     168                               osdBounds.width(), osdBounds.height(),
     169                               wmult, hmult, frameint);
     170        container->SetAllowFade(false);
     171        container->SetWantsUpdates(true);
     172        AddSet(container, name);
     173        QRect area = QRect(20, 20, 620, 440);
     174        normalizeRect(area);
     175        // XXX TODO use special teletextfont
     176        QString fontname = "teletextfont";
     177        TTFFont *font = GetFont(fontname);
     178        if (!font)
     179        {
     180            int fontsize = 440 / 26;
     181            font = LoadFont(gContext->GetSetting("OSDCCFont"), fontsize);
     182
     183            if (font)
     184                fontMap[fontname] = font;
     185        }
     186
     187        OSDTypeTeletext *ttpage = new OSDTypeTeletext(name, area, font);
     188 
     189        container->AddType(ttpage);
     190    }
     191   
     192    if (!GetSet("menu"))
     193    {
    164194        QString name = "menu";
    165195        container = new OSDSet(name, true,
    166196                               osdBounds.width(), osdBounds.height(),
  • libs/libmythtv/teletextdecoder.h

     
     1#ifndef VBIDECODER_H_
     2#define VBIDECODER_H_
     3
     4#include <stdint.h>
     5
     6#include <qwaitcondition.h>
     7#include <qobject.h>
     8#include <qmutex.h>
     9
     10class OSDTypeTeletext;
     11class OSDType;
     12class CCDecoder;
     13
     14class TeletextReader
     15{
     16  public:
     17    virtual ~TeletextReader() { }
     18    virtual void AddTextData(unsigned char *buf, int len,
     19                             long long timecode, char type) = 0;
     20};
     21
     22class TeletextDecoder : public QObject
     23{
     24    Q_OBJECT
     25  public:
     26    TeletextDecoder();
     27    ~TeletextDecoder();
     28
     29    // Sets
     30    void SetViewer(OSDTypeTeletext*);
     31
     32    // Gets
     33    int GetDecoderType(void) const;
     34
     35    void Decode(const uint8_t *buf, int vbimode);
     36
     37  private:
     38
     39    OSDTypeTeletext        *m_teletextviewer;
     40    int                     m_decodertype;
     41};
     42
     43#endif
  • libs/libmythtv/osdsurface.h

     
    22#define OSDSURFACE_H_
    33
    44#include <qregion.h>
     5#include <qmutex.h>
    56#include "blend.h"
    67
    78#define MAX_NEG_CROP 1024
     
    6162    int size;
    6263
    6364    QRegion usedRegions;
    64 
     65    mutable QMutex usedRegionsLock;
    6566#ifdef MMX
    6667    short int rec_lut[256];
    6768#else
  • libs/libmythtv/ttfont.h

     
    4242     bool isValid(void) { return valid; }
    4343
    4444     void DrawString(OSDSurface *surface, int x, int y, const QString &text,
    45                      int maxx, int maxy, int alphamod = 255);
     45                     int maxx, int maxy, int alphamod = 255,
     46                     bool double_size = false);
    4647     void CalcWidth(const QString &text, int *width_return);
    4748
    4849     int SpaceWidth() { return spacewidth; }
     
    5859     Raster_Map *duplicate_raster(FT_BitmapGlyph bmap);
    5960     void clear_raster(Raster_Map *rmap);
    6061     void destroy_font_raster(Raster_Map *rmap);
    61      Raster_Map *calc_size(int *width, int *height, const QString &text);
     62     Raster_Map *calc_size(int *width, int *height, const QString &text,
     63                           bool double_size = false);
    6264     void render_text(Raster_Map *rmap, Raster_Map *rchr, const QString &text,
    63                       int *xorblah, int *yor);
     65                      int *xorblah, int *yor, bool double_size = false);
    6466     void merge_text(OSDSurface *surface, Raster_Map *rmap, int offset_x,
    6567                     int offset_y, int xstart, int ystart, int width,
    6668                     int height, int alphamod, kTTF_Color k = kTTF_Normal);
  • libs/libavformat/mpegts.c

     
    5555    int comp_page;
    5656    int anc_page;
    5757    int sub_id;
     58    int txt_type;
    5859} dvb_caption_info_t;
    5960
    6061static int mpegts_parse_desc(dvb_caption_info_t *dvbci,
     
    618619        if (dvbci.sub_id && (stream_type == STREAM_TYPE_PRIVATE_DATA))
    619620            stream_type = STREAM_TYPE_SUBTITLE_DVB;
    620621
     622        if (dvbci.txt_type && (stream_type == STREAM_TYPE_PRIVATE_DATA))
     623            stream_type = STREAM_TYPE_VBI_DVB;
    621624#ifdef DEBUG_SI
    622625        av_log(NULL, AV_LOG_DEBUG, "stream_type=%d pid=0x%x\n", stream_type, pid);
    623626#endif
     
    784787        case STREAM_TYPE_AUDIO_AAC:
    785788        case STREAM_TYPE_AUDIO_AC3:
    786789        case STREAM_TYPE_AUDIO_DTS:
    787 //        case STREAM_TYPE_PRIVATE_DATA:
     790        case STREAM_TYPE_VBI_DVB:
    788791        case STREAM_TYPE_SUBTITLE_DVB:
    789792            val = 1;
    790793            break;
     
    839842                dvbci->language[2] = get8(p, desc_end);
    840843                dvbci->language[3] = 0;
    841844                break;
     845            case DVB_VBI_DESCID:
     846                dvbci->language[0] = get8(p, desc_end);
     847                dvbci->language[1] = get8(p, desc_end);
     848                dvbci->language[2] = get8(p, desc_end);
     849                dvbci->txt_type = (get8(p, desc_end)) >> 3;
     850                break;
    842851            default:
    843852                break;
    844853        }
     
    12731282            codec_type = CODEC_TYPE_AUDIO;
    12741283            codec_id = CODEC_ID_DTS;
    12751284            break;
    1276 //        case STREAM_TYPE_PRIVATE_DATA:
    1277 //            codec_type = CODEC_TYPE_DATA;
    1278 //            codec_id = CODEC_ID_DVB_VBI;
    1279 //            break;
     1285        case STREAM_TYPE_VBI_DVB:
     1286            codec_type = CODEC_TYPE_DATA;
     1287            codec_id = CODEC_ID_DVB_VBI;
     1288            break;
    12801289        case STREAM_TYPE_SUBTITLE_DVB:
    12811290            codec_type = CODEC_TYPE_SUBTITLE;
    12821291            codec_id = CODEC_ID_DVB_SUBTITLE;
  • libs/libavformat/mpegts.h

     
    3737#define SDT_TID   0x42
    3838
    3939/* descriptor ids */
     40#define DVB_VBI_DESCID              0x56
    4041#define DVB_SUBT_DESCID             0x59
    4142
    4243#define STREAM_TYPE_VIDEO_MPEG1     0x01
     
    5354#define STREAM_TYPE_AUDIO_DTS       0x8a
    5455
    5556#define STREAM_TYPE_SUBTITLE_DVB    0x100
     57#define STREAM_TYPE_VBI_DVB         0x101
    5658
    5759unsigned int mpegts_crc32(const uint8_t *data, int len);
    5860extern AVOutputFormat mpegts_mux;