diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp index 7c07634ec0e..6d9f8b4f640 100644 --- a/mythtv/libs/libmythtv/avformatdecoder.cpp +++ b/mythtv/libs/libmythtv/avformatdecoder.cpp @@ -28,6 +28,7 @@ using namespace std; #include "dvbdescriptors.h" #include "cc608decoder.h" #include "cc708decoder.h" +#include "teletextdecoder.h" #include "subtitlereader.h" #include "interactivetv.h" #include "DVDRingBuffer.h" @@ -277,7 +278,8 @@ AvFormatDecoder::AvFormatDecoder(MythPlayer *parent, // Closed Caption & Teletext decoders ccd608(new CC608Decoder(parent->GetCC608Reader())), ccd708(new CC708Decoder(parent->GetCC708Reader())), - ttd(new TeletextDecoder(parent)), subReader(parent->GetSubReader()), + ttd(new TeletextDecoder(parent->GetTeletextReader())), + subReader(parent->GetSubReader()), // Interactive TV itv(NULL), // Audio @@ -3511,11 +3513,6 @@ int AvFormatDecoder::GetTeletextDecoderType(void) const return ttd->GetDecoderType(); } -void AvFormatDecoder::SetTeletextDecoderViewer(TeletextViewer *view) -{ - ttd->SetViewer(view); -} - QString AvFormatDecoder::GetXDS(const QString &key) const { return ccd608->GetXDS(key); diff --git a/mythtv/libs/libmythtv/avformatdecoder.h b/mythtv/libs/libmythtv/avformatdecoder.h index 487ab2bd84a..3400943c1f7 100644 --- a/mythtv/libs/libmythtv/avformatdecoder.h +++ b/mythtv/libs/libmythtv/avformatdecoder.h @@ -158,7 +158,6 @@ class AvFormatDecoder : public DecoderBase virtual int64_t NormalizeVideoTimecode(AVStream *st, int64_t timecode); virtual int GetTeletextDecoderType(void) const; - virtual void SetTeletextDecoderViewer(TeletextViewer*); virtual QString GetXDS(const QString&) const; diff --git a/mythtv/libs/libmythtv/decoderbase.h b/mythtv/libs/libmythtv/decoderbase.h index c143a8b8485..38826863199 100644 --- a/mythtv/libs/libmythtv/decoderbase.h +++ b/mythtv/libs/libmythtv/decoderbase.h @@ -188,7 +188,6 @@ class DecoderBase inline int NextTrack(uint type); virtual int GetTeletextDecoderType(void) const { return -1; } - virtual void SetTeletextDecoderViewer(TeletextViewer*) {;} virtual QString GetXDS(const QString&) const { return QString::null; } diff --git a/mythtv/libs/libmythtv/libmythtv.pro b/mythtv/libs/libmythtv/libmythtv.pro index 17ceff29fdd..d404d129c69 100644 --- a/mythtv/libs/libmythtv/libmythtv.pro +++ b/mythtv/libs/libmythtv/libmythtv.pro @@ -197,8 +197,8 @@ HEADERS += datadirect.h SOURCES += datadirect.cpp # Teletext stuff -HEADERS += teletextdecoder.h vbilut.h -SOURCES += teletextdecoder.cpp vbilut.cpp +HEADERS += teletextdecoder.h teletextreader.h vbilut.h +SOURCES += teletextdecoder.cpp teletextreader.cpp vbilut.cpp # MPEG parsing stuff HEADERS += mpeg/tspacket.h mpeg/pespacket.h diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp index b9601fca7ec..198e1facbb5 100644 --- a/mythtv/libs/libmythtv/mythplayer.cpp +++ b/mythtv/libs/libmythtv/mythplayer.cpp @@ -210,7 +210,6 @@ MythPlayer::MythPlayer(bool muted) ttPageNum(0x888), // Support for captions, teletext, etc. decoded by libav textDesired(false), enableCaptions(false), disableCaptions(false), - initTeletext(false), // CC608/708 db_prefer708(true), cc608(this), cc708(this), // MHEG/MHI Interactive TV visible in OSD @@ -617,7 +616,6 @@ void MythPlayer::ReinitOSD(void) uint old = textDisplayMode; ToggleCaptions(old); osd->Reinit(visible, aspect); - SetupTeletextViewer(); EnableCaptions(old, false); } } @@ -1433,26 +1431,6 @@ bool MythPlayer::ToggleCaptions(uint type) return textDisplayMode; } -void MythPlayer::SetupTeletextViewer(void) -{ - if (QThread::currentThread() != playerThread) - { - initTeletext = true; - return; - } - - if (osd) - { - QMutexLocker locker(&osdLock); - TeletextViewer* ttview = (TeletextViewer*)osd->InitTeletext(); - if (ttview && decoder) - { - initTeletext = false; - decoder->SetTeletextDecoderViewer(ttview); - } - } -} - void MythPlayer::SetCaptionsEnabled(bool enable, bool osd_msg) { QMutexLocker locker(&osdLock); @@ -2050,7 +2028,6 @@ void MythPlayer::VideoStart(void) videoOutput->GetOSDBounds(total, visible, aspect, scaling, 1.0f); osd->Init(visible, aspect); videoOutput->InitOSD(osd); - SetupTeletextViewer(); osd->EnableSubtitles(kDisplayNone); #ifdef USING_MHEG @@ -2543,10 +2520,6 @@ void MythPlayer::EventLoop(void) if (disableCaptions) SetCaptionsEnabled(false, false); - // (re)initialise the teletext viewer - if (initTeletext) - SetupTeletextViewer(); - // refresh the position map for an in-progress recording while editing if (hasFullPositionMap && watchingrecording && player_ctx->recorder && player_ctx->recorder->IsValidRecorder() && deleteMap.IsEditing()) diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h index 325efee36df..d6760649e0a 100644 --- a/mythtv/libs/libmythtv/mythplayer.h +++ b/mythtv/libs/libmythtv/mythplayer.h @@ -15,7 +15,7 @@ #include "osd.h" #include "jitterometer.h" #include "videooutbase.h" -#include "teletextdecoder.h" +#include "teletextreader.h" #include "subtitlereader.h" #include "tv_play.h" #include "yuv2rgb.h" @@ -254,11 +254,11 @@ class MPUBLIC MythPlayer virtual bool PrepareAudioSample(int64_t &timecode); // Public Closed caption and teletext stuff - void SetupTeletextViewer(void); uint GetCaptionMode(void) const { return textDisplayMode; } CC708Reader* GetCC708Reader(void) { return &cc708; } CC608Reader* GetCC608Reader(void) { return &cc608; } SubtitleReader* GetSubReader(void) { return &subReader; } + TeletextReader* GetTeletextReader(void) { return &ttxReader; } // Public Audio/Subtitle/EIA-608/EIA-708 stream selection - thread safe void TracksChanged(uint trackType); @@ -634,12 +634,12 @@ class MPUBLIC MythPlayer // Support for captions, teletext, etc. decoded by libav SubtitleReader subReader; + TeletextReader ttxReader; /// This allows us to enable captions/subtitles later if the streams /// are not immediately available when the video starts playing. bool textDesired; bool enableCaptions; bool disableCaptions; - bool initTeletext; // CC608/708 bool db_prefer708; diff --git a/mythtv/libs/libmythtv/teletextdecoder.cpp b/mythtv/libs/libmythtv/teletextdecoder.cpp index f9db7fc2af9..88c9c458f7d 100644 --- a/mythtv/libs/libmythtv/teletextdecoder.cpp +++ b/mythtv/libs/libmythtv/teletextdecoder.cpp @@ -31,14 +31,10 @@ using namespace std; #include "osd.h" #include "teletextdecoder.h" +#include "teletextreader.h" #include "vbilut.h" -#include "mythplayer.h" #include "mythverbose.h" -/******************************************************************/ -//Decoder section -// - /** \fn TeletextDecoder::Decode(const unsigned char*, int) * \brief Decodes teletext data * @@ -50,36 +46,8 @@ void TeletextDecoder::Decode(const unsigned char *buf, int vbimode) int err = 0, latin1 = -1, zahl1, pagenum, subpagenum, lang, flags; uint magazine, packet, header; - if (!m_player) - return; - - int mode = m_player->GetCaptionMode(); - if (!((mode == kDisplayNUVTeletextCaptions) || - (mode == kDisplayTeletextCaptions) || - (mode == kDisplayTeletextMenu))) - { - return; - } - - if (!m_player->TryLockOSD()) - { - VERBOSE(VB_PLAYBACK, "TeletextDecoder: Failed to get OSD lock."); - return; - } - - if (!m_teletextviewer && m_player) - { - m_player->UnlockOSD(); - m_player->SetupTeletextViewer(); - return; - } - - if (!m_teletextviewer) - { - VERBOSE(VB_VBI, "TeletextDecoder: No Teletext Viewer defined!"); - m_player->UnlockOSD(); + if (!m_teletext_reader) return; - } m_decodertype = vbimode; @@ -89,10 +57,7 @@ void TeletextDecoder::Decode(const unsigned char *buf, int vbimode) header = hamm16(buf, &err); if (err & 0xf000) - { - m_player->UnlockOSD(); return; // error in data header - } magazine = header & 7; packet = (header >> 3) & 0x1f; @@ -125,16 +90,12 @@ void TeletextDecoder::Decode(const unsigned char *buf, int vbimode) packet += 16; if (err == 1) - { - m_player->UnlockOSD(); return; // error in data header - } buf += 2; break; default: - m_player->UnlockOSD(); return; // error in vbimode } @@ -150,10 +111,7 @@ void TeletextDecoder::Decode(const unsigned char *buf, int vbimode) b3 = hamm16(buf+4, &err);// subpage number + flags b4 = hamm16(buf+6, &err);// language code + more flags if (err & 0xf000) - { - m_player->UnlockOSD(); return; - } break; @@ -164,22 +122,14 @@ void TeletextDecoder::Decode(const unsigned char *buf, int vbimode) b3 = hamm84(buf+5, &err)*16+hamm84(buf+4, &err); b4 = hamm84(buf+7, &err)*16+hamm84(buf+6, &err); if (err == 1) - { - m_player->UnlockOSD(); return; - } break; default: - m_player->UnlockOSD(); return; // error in vbimode } - //VERBOSE(VB_VBI, QString("Page Header found: " - // "Magazine %1, Page Number %2") - // .arg(magazine).arg(b1)); - subpagenum= (b2 + b3 * 256) & 0x3f7f; pagenum = (magazine?:8)*256 + b1; @@ -187,15 +137,14 @@ void TeletextDecoder::Decode(const unsigned char *buf, int vbimode) flags = b4 & 0x1F; flags |= b3 & 0xC0; flags |= (b2 & 0x80) >> 2; - m_teletextviewer->AddPageHeader(pagenum, subpagenum, buf, - vbimode, lang, flags); + m_teletext_reader->AddPageHeader(pagenum, subpagenum, buf, + vbimode, lang, flags); break; default: // Page Data - m_teletextviewer->AddTeletextData((magazine?:8), packet, - buf, vbimode); + m_teletext_reader->AddTeletextData((magazine?:8), packet, + buf, vbimode); break; } - m_player->UnlockOSD(); } diff --git a/mythtv/libs/libmythtv/teletextdecoder.h b/mythtv/libs/libmythtv/teletextdecoder.h index 0cd2ed5da42..d7175d28caf 100644 --- a/mythtv/libs/libmythtv/teletextdecoder.h +++ b/mythtv/libs/libmythtv/teletextdecoder.h @@ -3,52 +3,20 @@ #include -class TeletextViewer -{ - public: - TeletextViewer() { } - virtual ~TeletextViewer() { } - - virtual void KeyPress(uint key) { (void) key; } - virtual void SetPage(int page, int subpage) { (void) page; (void) subpage; } - virtual void SetDisplaying(bool displaying) { (void) displaying; } - - virtual void Reset(void) = 0; - virtual void AddPageHeader(int page, int subpage, - const uint8_t *buf, int vbimode, - int lang, int flags) = 0; - virtual void AddTeletextData(int magazine, int row, - const uint8_t* buf, int vbimode) = 0; -}; - -class MythPlayer; +class TeletextReader; class TeletextDecoder { public: - TeletextDecoder(MythPlayer *player) - : m_player(player), m_teletextviewer(NULL), m_decodertype(-1) {} + TeletextDecoder(TeletextReader *reader) + : m_teletext_reader(reader), m_decodertype(-1) {} virtual ~TeletextDecoder() {} - /// Sets the TeletextViewer which will get the text from this decoder. - void SetViewer(TeletextViewer *viewer) - { m_teletextviewer = viewer; } - - /** - * \brief Returns the actual decoder type (DVB,IVTV,DVB_SUBTITLE...) - * - * This is used for the decision in NuppelVideoPlayer - * to this TeletextDecoder or the caption only decoder. - */ - int GetDecoderType(void) const - { return m_decodertype; } - + int GetDecoderType(void) const { return m_decodertype; } void Decode(const unsigned char *buf, int vbimode); private: - - MythPlayer *m_player; - TeletextViewer *m_teletextviewer; + TeletextReader *m_teletext_reader; int m_decodertype; }; diff --git a/mythtv/libs/libmythtv/teletextreader.cpp b/mythtv/libs/libmythtv/teletextreader.cpp new file mode 100644 index 00000000000..9d07c7dab4d --- /dev/null +++ b/mythtv/libs/libmythtv/teletextreader.cpp @@ -0,0 +1,609 @@ +#include "teletextreader.h" + +#include +#include "vbilut.h" + +#define MAGAZINE(page) (page / 256) + +TeletextReader::TeletextReader() + : m_curpage(0x100), m_cursubpage(-1), + m_curpage_showheader(true), m_curpage_issubtitle(false), + m_transparent(false), m_revealHidden(false), + m_header_changed(false), m_page_changed(false), + m_fetchpage(0), m_fetchsubpage(0) +{ + memset(m_pageinput, 0, sizeof(m_pageinput)); + memset(m_header, 0, sizeof(m_header)); + for (int i = 0; i < 256; i++) + { + m_bitswap[i] = 0; + for (int bit = 0; bit < 8; bit++) + if (i & (1 << bit)) + m_bitswap[i] |= (1 << (7-bit)); + } + Reset(); +} + +TeletextReader::~TeletextReader() +{ +} + +void TeletextReader::KeyPress(unsigned int key) +{ + int newPage = m_curpage; + int newSubPage = m_cursubpage; + bool numeric_input = false; + + TeletextSubPage *curpage = FindSubPage(m_curpage, m_cursubpage); + TeletextPage *page; + + switch (key) + { + case TTKey::k0 ... TTKey::k9: + numeric_input = true; + m_curpage_showheader = true; + if (m_pageinput[0] == ' ') + m_pageinput[0] = '0' + static_cast (key); + else if (m_pageinput[1] == ' ') + m_pageinput[1] = '0' + static_cast (key); + else if (m_pageinput[2] == ' ') + { + m_pageinput[2] = '0' + static_cast (key); + newPage = ((m_pageinput[0] - '0') * 256) + + ((m_pageinput[1] - '0') * 16) + + (m_pageinput[2] - '0'); + newSubPage = -1; + } + else + { + m_pageinput[0] = '0' + static_cast (key); + m_pageinput[1] = ' '; + m_pageinput[2] = ' '; + } + + PageUpdated(m_curpage, m_cursubpage); + break; + + case TTKey::kNextPage: + { + TeletextPage *ttpage = FindPage(m_curpage, 1); + if (ttpage) + newPage = ttpage->pagenum; + newSubPage = -1; + m_curpage_showheader = true; + break; + } + + case TTKey::kPrevPage: + { + TeletextPage *ttpage = FindPage(m_curpage, -1); + if (ttpage) + newPage = ttpage->pagenum; + newSubPage = -1; + m_curpage_showheader = true; + break; + } + + case TTKey::kNextSubPage: + { + TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage, 1); + if (ttpage) + newSubPage = ttpage->subpagenum; + m_curpage_showheader = true; + break; + } + + case TTKey::kPrevSubPage: + { + TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage, -1); + if (ttpage) + newSubPage = ttpage->subpagenum; + m_curpage_showheader = true; + break; + } + + case TTKey::kHold: + break; + + case TTKey::kTransparent: + m_transparent = !m_transparent; + PageUpdated(m_curpage, m_cursubpage); + break; + + case TTKey::kRevealHidden: + m_revealHidden = !m_revealHidden; + PageUpdated(m_curpage, m_cursubpage); + break; + + case TTKey::kFlofRed: + { + if (!curpage) + return; + + if ((page = FindPage(curpage->floflink[0])) != NULL) + { + newPage = page->pagenum; + newSubPage = -1; + m_curpage_showheader = true; + } + break; + } + + case TTKey::kFlofGreen: + { + if (!curpage) + return; + + if ((page = FindPage(curpage->floflink[1])) != NULL) + { + newPage = page->pagenum; + newSubPage = -1; + m_curpage_showheader = true; + } + break; + } + + case TTKey::kFlofYellow: + { + if (!curpage) + return; + + if ((page = FindPage(curpage->floflink[2])) != NULL) + { + newPage = page->pagenum; + newSubPage = -1; + m_curpage_showheader = true; + } + break; + } + + case TTKey::kFlofBlue: + { + if (!curpage) + return; + + if ((page = FindPage(curpage->floflink[3])) != NULL) + { + newPage = page->pagenum; + newSubPage = -1; + m_curpage_showheader = true; + } + break; + } + + case TTKey::kFlofWhite: + { + if (!curpage) + return; + + if ((page = FindPage(curpage->floflink[4])) != NULL) + { + newPage = page->pagenum; + newSubPage = -1; + m_curpage_showheader = true; + } + break; + } + } + + if (newPage < 0x100) + newPage = 0x100; + if (newPage > 0x899) + newPage = 0x899; + + if (!numeric_input) + { + m_pageinput[0] = (newPage / 256) + '0'; + m_pageinput[1] = ((newPage % 256) / 16) + '0'; + m_pageinput[2] = (newPage % 16) + '0'; + } + + if (newPage != m_curpage || newSubPage != m_cursubpage) + { + m_curpage = newPage; + m_cursubpage = newSubPage; + m_revealHidden = false; + PageUpdated(m_curpage, m_cursubpage); + } +} + +QString TeletextReader::GetPage(void) +{ + QString str = ""; + int mag = MAGAZINE(m_curpage); + if (mag > 8 || mag < 1) + return str; + + int count = 1, selected = 0; + const TeletextPage *page = FindPage(m_curpage); + if (page) + { + m_magazines[mag - 1].lock.lock(); + int_to_subpage_t::const_iterator subpageIter; + subpageIter = page->subpages.begin(); + while (subpageIter != page->subpages.end()) + { + const TeletextSubPage *subpage = &subpageIter->second; + + if (subpage->subpagenum == m_cursubpage) + { + selected = count; + str += "*"; + } + else + str += " "; + + str += QString().sprintf("%02X", subpage->subpagenum); + + ++subpageIter; + ++count; + } + m_magazines[mag - 1].lock.unlock(); + } + + if (str.isEmpty()) + return str; + + // if there are less than 9 subpages fill the empty slots with spaces + if (count < 10) + { + QString spaces; + spaces.fill(' ', 27 - str.length()); + str = " <" + str + spaces + " > "; + } + else + { + // try to centralize the selected sub page in the list + int startPos = selected - 5; + if (startPos < 0) + startPos = 0; + if (startPos + 9 >= count) + startPos = count - 10; + + str = " <" + str.mid(startPos * 3, 27) + " > "; + } + return str; +} + +void TeletextReader::SetPage(int page, int subpage) +{ + if (page < 0x100 || page > 0x899) + return; + + m_pageinput[0] = (page / 256) + '0'; + m_pageinput[1] = ((page % 256) / 16) + '0'; + m_pageinput[2] = (page % 16) + '0'; + + m_curpage = page; + m_cursubpage = subpage; + PageUpdated(m_curpage, m_cursubpage); +} + +void TeletextReader::Reset(void) +{ + for (uint mag = 0; mag < 8; mag++) + { + QMutexLocker lock(&m_magazines[mag].lock); + + // clear all sub pages in page + int_to_page_t::iterator iter; + iter = m_magazines[mag].pages.begin(); + while (iter != m_magazines[mag].pages.end()) + { + TeletextPage *page = &iter->second; + page->subpages.clear(); + ++iter; + } + + // clear pages + m_magazines[mag].pages.clear(); + m_magazines[mag].current_page = 0; + m_magazines[mag].current_subpage = 0; + m_magazines[mag].loadingpage.active = false; + } + memset(m_header, ' ', 40); + + m_curpage = 0x100; + m_cursubpage = -1; + m_curpage_showheader = true; + + m_pageinput[0] = '1'; + m_pageinput[1] = '0'; + m_pageinput[2] = '0'; +} + +void TeletextReader::AddPageHeader(int page, int subpage, const uint8_t *buf, + int vbimode, int lang, int flags) +{ + int magazine = MAGAZINE(page); + if (magazine < 1 || magazine > 8) + return; + int lastPage = m_magazines[magazine - 1].current_page; + int lastSubPage = m_magazines[magazine - 1].current_subpage; + + // update the last fetched page if the magazine is the same + // and the page no. is different + + if ((page != lastPage || subpage != lastSubPage) && + m_magazines[magazine - 1].loadingpage.active) + { + TeletextSubPage *ttpage = FindSubPage(lastPage, lastSubPage); + if (!ttpage) + { + ttpage = &(m_magazines[magazine - 1] + .pages[lastPage].subpages[lastSubPage]); + m_magazines[magazine - 1].pages[lastPage].pagenum = lastPage; + ttpage->subpagenum = lastSubPage; + } + + memcpy(ttpage, &m_magazines[magazine - 1].loadingpage, + sizeof(TeletextSubPage)); + + m_magazines[magazine - 1].loadingpage.active = false; + + PageUpdated(lastPage, lastSubPage); + } + + m_fetchpage = page; + m_fetchsubpage = subpage; + + TeletextSubPage *ttpage = &m_magazines[magazine - 1].loadingpage; + + m_magazines[magazine - 1].current_page = page; + m_magazines[magazine - 1].current_subpage = subpage; + + memset(ttpage->data, ' ', sizeof(ttpage->data)); + + ttpage->active = true; + ttpage->subpagenum = subpage; + + for (uint i = 0; i < 6; i++) + ttpage->floflink[i] = 0; + + ttpage->lang = lang; + ttpage->flags = flags; + ttpage->flof = 0; + + ttpage->subtitle = (vbimode == VBI_DVB_SUBTITLE); + + memset(ttpage->data[0], ' ', 8 * sizeof(uint8_t)); + + if (vbimode == VBI_DVB || vbimode == VBI_DVB_SUBTITLE) + { + for (uint j = 8; j < 40; j++) + ttpage->data[0][j] = m_bitswap[buf[j]]; + } + else + { + memcpy(ttpage->data[0]+0, buf, 40); + } + + if ( !(ttpage->flags & TP_INTERRUPTED_SEQ)) + { + memcpy(m_header, ttpage->data[0], 40); + HeaderUpdated(ttpage->data[0],ttpage->lang); + } +} + +void TeletextReader::AddTeletextData(int magazine, int row, + const uint8_t* buf, int vbimode) +{ + int b1, b2, b3, err = 0; + + if (magazine < 1 || magazine > 8) + return; + + int currentpage = m_magazines[magazine - 1].current_page; + if (!currentpage) + return; + + TeletextSubPage *ttpage = &m_magazines[magazine - 1].loadingpage; + + switch (row) + { + case 1 ... 24: // Page Data + if (vbimode == VBI_DVB || vbimode == VBI_DVB_SUBTITLE) + { + for (uint j = 0; j < 40; j++) + ttpage->data[row][j] = m_bitswap[buf[j]]; + } + else + { + memcpy(ttpage->data[row], buf, 40); + } + break; + case 26: + /* XXX TODO: Level 1.5, 2.5, 3.5 + * Character location & override + * Level 2.5, 3.5 + * Modifying display attributes + * All levels + * VCR Programming + * See 12.3 + */ + break; + case 27: // FLOF data (FastText) + switch (vbimode) + { + case VBI_IVTV: + b1 = hamm8(buf, &err); + b2 = hamm8(buf + 37, &err); + if (err & 0xF000) + return; + break; + case VBI_DVB: + case VBI_DVB_SUBTITLE: + b1 = hamm84(buf, &err); + b2 = hamm84(buf + 37, &err); + if (err == 1) + return; + break; + default: + return; + } + if (b1 != 0 || not(b2 & 8)) + return; + + for (int i = 0; i < 6; ++i) + { + err = 0; + switch (vbimode) + { + case VBI_IVTV: + b1 = hamm16(buf+1+6*i, &err); + b2 = hamm16(buf+3+6*i, &err); + b3 = hamm16(buf+5+6*i, &err); + if (err & 0xF000) + return; + break; + case VBI_DVB: + case VBI_DVB_SUBTITLE: + b1 = hamm84(buf+2+6*i, &err) * 16 + + hamm84(buf+1+6*i, &err); + b2 = hamm84(buf+4+6*i, &err) * 16 + + hamm84(buf+3+6*i, &err); + b3 = hamm84(buf+6+6*i, &err) * 16 + + hamm84(buf+5+6*i, &err); + if (err == 1) + return; + break; + default: + return; + } + + int x = (b2 >> 7) | ((b3 >> 5) & 0x06); + ttpage->floflink[i] = ((magazine ^ x) ?: 8) * 256 + b1; + ttpage->flof = 1; + } + break; + + case 31: // private streams + break; + + default: /// other packet codes... + break; + } +} + +void TeletextReader::PageUpdated(int page, int subpage) +{ + if (page != m_curpage) + return; + if (subpage != m_cursubpage && m_cursubpage != -1) + return; + m_page_changed = true; +} + +void TeletextReader::HeaderUpdated(uint8_t * page, int lang) +{ + (void)lang; + + if (page == NULL) + return; + + if (m_curpage_showheader == false) + return; + + m_header_changed = true; +} + +const TeletextPage *TeletextReader::FindPageInternal( + int page, int direction) const +{ + int mag = MAGAZINE(page); + + if (mag > 8 || mag < 1) + return NULL; + + QMutexLocker lock(&m_magazines[mag - 1].lock); + + int_to_page_t::const_iterator pageIter; + pageIter = m_magazines[mag - 1].pages.find(page); + if (pageIter == m_magazines[mag - 1].pages.end()) + return NULL; + + const TeletextPage *res = &pageIter->second; + if (direction == -1) + { + --pageIter; + if (pageIter == m_magazines[mag - 1].pages.end()) + { + int_to_page_t::const_reverse_iterator iter; + iter = m_magazines[mag - 1].pages.rbegin(); + res = &iter->second; + } + else + res = &pageIter->second; + } + + if (direction == 1) + { + ++pageIter; + if (pageIter == m_magazines[mag - 1].pages.end()) + { + pageIter = m_magazines[mag - 1].pages.begin(); + res = &pageIter->second; + } + else + res = &pageIter->second; + } + + return res; +} + +const TeletextSubPage *TeletextReader::FindSubPageInternal( + int page, int subpage, int direction) const +{ + int mag = MAGAZINE(page); + + if (mag > 8 || mag < 1) + return NULL; + + QMutexLocker lock(&m_magazines[mag - 1].lock); + + int_to_page_t::const_iterator pageIter; + pageIter = m_magazines[mag - 1].pages.find(page); + if (pageIter == m_magazines[mag - 1].pages.end()) + return NULL; + + const TeletextPage *ttpage = &(pageIter->second); + int_to_subpage_t::const_iterator subpageIter = + ttpage->subpages.begin(); + + // try to find the subpage given, or first if subpage == -1 + if (subpage != -1) + subpageIter = ttpage->subpages.find(subpage); + + if (subpageIter == ttpage->subpages.end()) + return NULL; + + if (subpage == -1) + return &(subpageIter->second); + + const TeletextSubPage *res = &(subpageIter->second); + if (direction == -1) + { + --subpageIter; + if (subpageIter == ttpage->subpages.end()) + { + int_to_subpage_t::const_reverse_iterator iter = + ttpage->subpages.rbegin(); + res = &(iter->second); + } + else + { + res = &(subpageIter->second); + } + } + + if (direction == 1) + { + ++subpageIter; + if (subpageIter == ttpage->subpages.end()) + subpageIter = ttpage->subpages.begin(); + + res = &(subpageIter->second); + } + + return res; +} diff --git a/mythtv/libs/libmythtv/teletextreader.h b/mythtv/libs/libmythtv/teletextreader.h new file mode 100644 index 00000000000..088abb0517b --- /dev/null +++ b/mythtv/libs/libmythtv/teletextreader.h @@ -0,0 +1,162 @@ +#ifndef TELETEXTREADER_H +#define TELETEXTREADER_H + +#include +#include + +#include +#include + +using namespace std; + +typedef enum +{ + kTTColorBlack = 0, + kTTColorRed = 1, + kTTColorGreen = 2, + kTTColorYellow = 3, + kTTColorBlue = 4, + kTTColorMagenta = 5, + kTTColorCyan = 6, + kTTColorWhite = 7, + kTTColorTransparent = 8, +} TTColor; + +class TTKey +{ + public: + static const uint k0 = 0; + static const uint k1 = 1; + static const uint k2 = 2; + static const uint k3 = 3; + static const uint k4 = 4; + static const uint k5 = 5; + static const uint k6 = 6; + static const uint k7 = 7; + static const uint k8 = 8; + static const uint k9 = 9; + static const uint kNextPage = 10; + static const uint kPrevPage = 11; + static const uint kNextSubPage = 12; + static const uint kPrevSubPage = 13; + static const uint kHold = 14; + static const uint kTransparent = 15; + static const uint kFlofRed = 16; + static const uint kFlofGreen = 17; + static const uint kFlofYellow = 18; + static const uint kFlofBlue = 19; + static const uint kFlofWhite = 20; + static const uint kRevealHidden = 21; +}; + +#define TP_SUPPRESS_HEADER 0x01 +#define TP_UPDATE_INDICATOR 0x02 +#define TP_INTERRUPTED_SEQ 0x04 +#define TP_INHIBIT_DISPLAY 0x08 +#define TP_MAGAZINE_SERIAL 0x10 +#define TP_ERASE_PAGE 0x20 +#define TP_NEWSFLASH 0x40 +#define TP_SUBTITLE 0x80 + +class TeletextSubPage +{ + public: + int pagenum; ///< the wanted page + int subpagenum; ///< the wanted subpage + int lang; ///< language code + int flags; ///< misc flags + uint8_t data[25][40]; ///< page data + int flof; ///< page has FastText links + int floflink[6]; ///< FastText links (FLOF) + bool subtitle; ///< page is subtitle page + bool active; ///< data has arrived since page last cleared +}; + +typedef map int_to_subpage_t; + +class TeletextPage +{ + public: + int pagenum; + int current_subpage; + int_to_subpage_t subpages; +}; +typedef map int_to_page_t; + +class TeletextMagazine +{ + public: + mutable QMutex lock; + int current_page; + int current_subpage; + TeletextSubPage loadingpage; + int_to_page_t pages; +}; + +class TeletextReader +{ + public: + TeletextReader(); + ~TeletextReader(); + + // OSD/Player methods + void Reset(void); + void KeyPress(uint key); + QString GetPage(void); + void SetPage(int page, int subpage); + void SetSubPage(int subpage) { m_cursubpage = subpage; } + bool PageChanged(void) { return m_page_changed; } + void SetPageChanged(bool changed) { m_page_changed = changed; } + void SetShowHeader(bool show) { m_curpage_showheader = show; } + void SetHeaderChanged(bool changed) { m_header_changed = changed; } + bool IsSubtitle(void) { return m_curpage_issubtitle; } + void SetIsSubtitle(bool sub) { m_curpage_issubtitle = sub; } + bool IsTransparent(void) { return m_transparent; } + bool RevealHidden(void) { return m_revealHidden; } + int GetPageInput(uint num) { return m_pageinput[num]; } + TeletextSubPage* FindSubPage(void) + { return FindSubPage(m_curpage, m_cursubpage); } + uint8_t* GetHeader(void) { return m_header; } + + // Decoder methods + void AddPageHeader(int page, int subpage, const uint8_t *buf, + int vbimode, int lang, int flags); + void AddTeletextData(int magazine, int row, + const uint8_t* buf, int vbimode); + + + private: + void NewsFlash(void) {}; + void PageUpdated(int page, int subpage); + void HeaderUpdated(uint8_t *page, int lang); + + const TeletextSubPage *FindSubPage(int page, int subpage, int dir=0) const + { return FindSubPageInternal(page, subpage, dir); } + TeletextSubPage *FindSubPage(int page, int subpage, int dir = 0) + { return (TeletextSubPage*) FindSubPageInternal(page, subpage, dir); } + + const TeletextPage *FindPage(int page, int dir = 0) const + { return (TeletextPage*) FindPageInternal(page, dir); } + TeletextPage *FindPage(int page, int dir = 0) + { return (TeletextPage*) FindPageInternal(page, dir); } + + const TeletextSubPage *FindSubPageInternal(int,int,int) const; + const TeletextPage *FindPageInternal(int,int) const; + + mutable int m_curpage; + mutable int m_cursubpage; + mutable bool m_curpage_showheader; + mutable bool m_curpage_issubtitle; + int m_pageinput[3]; + bool m_transparent; + bool m_revealHidden; + uint8_t m_header[40]; + mutable bool m_header_changed; + mutable bool m_page_changed; + TeletextMagazine m_magazines[8]; + unsigned char m_bitswap[256]; + int m_fetchpage; + int m_fetchsubpage; +}; + +#endif // TELETEXTREADER_H diff --git a/mythtv/libs/libmythtv/teletextscreen.cpp b/mythtv/libs/libmythtv/teletextscreen.cpp index 4be77e429ee..f1830d2b7c2 100644 --- a/mythtv/libs/libmythtv/teletextscreen.cpp +++ b/mythtv/libs/libmythtv/teletextscreen.cpp @@ -11,8 +11,7 @@ #include "mythpainter.h" #include "teletextscreen.h" -#define LOC QString("Teletext: ") -#define MAGAZINE(page) (page / 256) +#define LOC QString("TeletextScreen: ") const QColor TeletextScreen::kColorBlack = QColor( 0, 0, 0,255); const QColor TeletextScreen::kColorRed = QColor(255, 0, 0,255); @@ -42,28 +41,13 @@ static char cvt_char(char ch, int lang) TeletextScreen::TeletextScreen(MythPlayer *player, const char * name, int fontStretch) : MythScreenType((MythScreenType*)NULL, name), - m_player(player), m_safeArea(QRect()), + m_player(player), m_teletextReader(NULL), + m_safeArea(QRect()), m_colWidth(10), m_rowHeight(10), - m_fetchpage(0), m_fetchsubpage(0), m_bgColor(QColor(kColorBlack)), - m_curpage(0x100), m_cursubpage(-1), - m_curpage_showheader(true), m_curpage_issubtitle(false), - m_transparent(false), m_revealHidden(false), - m_displaying(false), m_header_changed(false), - m_page_changed(false), m_fontStretch(fontStretch), + m_displaying(false), m_fontStretch(fontStretch), m_fontHeight(10) { - memset(m_pageinput, 0, sizeof(m_pageinput)); - memset(m_header, 0, sizeof(m_header)); - for (int i = 0; i < 256; i++) - { - m_bitswap[i] = 0; - for (int bit = 0; bit < 8; bit++) - if (i & (1 << bit)) - m_bitswap[i] |= (1 << (7-bit)); - } - - Reset(); } TeletextScreen::~TeletextScreen() @@ -73,7 +57,9 @@ TeletextScreen::~TeletextScreen() bool TeletextScreen::Create(void) { - return m_player; + if (m_player) + m_teletextReader = m_player->GetTeletextReader(); + return m_player && m_teletextReader; } void TeletextScreen::CleanUp(void) @@ -173,7 +159,7 @@ void TeletextScreen::Pulse(void) if (oldsafe != m_safeArea) { - m_page_changed = true; + m_teletextReader->SetPageChanged(true); int max_width = (int)((float)m_colWidth * kTextPadding); m_fontHeight = (int)((float)m_rowHeight * kTextPadding); @@ -201,25 +187,23 @@ void TeletextScreen::Pulse(void) return; } - if (!m_page_changed) + if (!m_teletextReader->PageChanged()) return; - QMutexLocker locker(&m_lock); - CleanUp(); - const TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage); + const TeletextSubPage *ttpage = m_teletextReader->FindSubPage(); if (!ttpage) { // no page selected so show the header and a list of available pages DrawHeader(NULL, 0); - m_page_changed = false; + m_teletextReader->SetPageChanged(false); OptimiseDisplayedArea(); return; } - m_cursubpage = ttpage->subpagenum; + m_teletextReader->SetSubPage(ttpage->subpagenum); int a = 0; if ((ttpage->subtitle) || @@ -227,223 +211,34 @@ void TeletextScreen::Pulse(void) { a = 1; // when showing subtitles we don't want to see the teletext // header line, so we skip that line... - m_curpage_showheader = false; - m_curpage_issubtitle = true; + m_teletextReader->SetShowHeader(false); + m_teletextReader->SetIsSubtitle(true); } else { - m_curpage_issubtitle = false; - m_curpage_showheader = true; - DrawHeader(m_header, ttpage->lang); - - m_header_changed = false; + m_teletextReader->SetShowHeader(true); + m_teletextReader->SetIsSubtitle(false); + DrawHeader(m_teletextReader->GetHeader(), ttpage->lang); + m_teletextReader->SetHeaderChanged(false); } for (int y = kTeletextRows - a; y >= 2; y--) DrawLine(ttpage->data[y-1], y, ttpage->lang); - m_page_changed = false; + m_teletextReader->SetPageChanged(false); OptimiseDisplayedArea(); } void TeletextScreen::KeyPress(uint key) { - if (!m_displaying) - return; - - QMutexLocker locker(&m_lock); - - int newPage = m_curpage; - int newSubPage = m_cursubpage; - bool numeric_input = false; - - TeletextSubPage *curpage = FindSubPage(m_curpage, m_cursubpage); - TeletextPage *page; - - switch (key) - { - case TTKey::k0 ... TTKey::k9: - numeric_input = true; - m_curpage_showheader = true; - if (m_pageinput[0] == ' ') - m_pageinput[0] = '0' + static_cast (key); - else if (m_pageinput[1] == ' ') - m_pageinput[1] = '0' + static_cast (key); - else if (m_pageinput[2] == ' ') - { - m_pageinput[2] = '0' + static_cast (key); - newPage = ((m_pageinput[0] - '0') * 256) + - ((m_pageinput[1] - '0') * 16) + - (m_pageinput[2] - '0'); - newSubPage = -1; - } - else - { - m_pageinput[0] = '0' + static_cast (key); - m_pageinput[1] = ' '; - m_pageinput[2] = ' '; - } - - PageUpdated(m_curpage, m_cursubpage); - break; - - case TTKey::kNextPage: - { - TeletextPage *ttpage = FindPage(m_curpage, 1); - if (ttpage) - newPage = ttpage->pagenum; - newSubPage = -1; - m_curpage_showheader = true; - break; - } - - case TTKey::kPrevPage: - { - TeletextPage *ttpage = FindPage(m_curpage, -1); - if (ttpage) - newPage = ttpage->pagenum; - newSubPage = -1; - m_curpage_showheader = true; - break; - } - - case TTKey::kNextSubPage: - { - TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage, 1); - if (ttpage) - newSubPage = ttpage->subpagenum; - m_curpage_showheader = true; - break; - } - - case TTKey::kPrevSubPage: - { - TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage, -1); - if (ttpage) - newSubPage = ttpage->subpagenum; - m_curpage_showheader = true; - break; - } - - case TTKey::kHold: - break; - - case TTKey::kTransparent: - m_transparent = !m_transparent; - PageUpdated(m_curpage, m_cursubpage); - break; - - case TTKey::kRevealHidden: - m_revealHidden = !m_revealHidden; - PageUpdated(m_curpage, m_cursubpage); - break; - - case TTKey::kFlofRed: - { - if (!curpage) - return; - - if ((page = FindPage(curpage->floflink[0])) != NULL) - { - newPage = page->pagenum; - newSubPage = -1; - m_curpage_showheader = true; - } - break; - } - - case TTKey::kFlofGreen: - { - if (!curpage) - return; - - if ((page = FindPage(curpage->floflink[1])) != NULL) - { - newPage = page->pagenum; - newSubPage = -1; - m_curpage_showheader = true; - } - break; - } - - case TTKey::kFlofYellow: - { - if (!curpage) - return; - - if ((page = FindPage(curpage->floflink[2])) != NULL) - { - newPage = page->pagenum; - newSubPage = -1; - m_curpage_showheader = true; - } - break; - } - - case TTKey::kFlofBlue: - { - if (!curpage) - return; - - if ((page = FindPage(curpage->floflink[3])) != NULL) - { - newPage = page->pagenum; - newSubPage = -1; - m_curpage_showheader = true; - } - break; - } - - case TTKey::kFlofWhite: - { - if (!curpage) - return; - - if ((page = FindPage(curpage->floflink[4])) != NULL) - { - newPage = page->pagenum; - newSubPage = -1; - m_curpage_showheader = true; - } - break; - } - } - - if (newPage < 0x100) - newPage = 0x100; - if (newPage > 0x899) - newPage = 0x899; - - if (!numeric_input) - { - m_pageinput[0] = (newPage / 256) + '0'; - m_pageinput[1] = ((newPage % 256) / 16) + '0'; - m_pageinput[2] = (newPage % 16) + '0'; - } - - if (newPage != m_curpage || newSubPage != m_cursubpage) - { - m_curpage = newPage; - m_cursubpage = newSubPage; - m_revealHidden = false; - PageUpdated(m_curpage, m_cursubpage); - } + if (m_teletextReader) + m_teletextReader->KeyPress(key); } void TeletextScreen::SetPage(int page, int subpage) { - QMutexLocker locker(&m_lock); - - if (page < 0x100 || page > 0x899) - return; - - m_pageinput[0] = (page / 256) + '0'; - m_pageinput[1] = ((page % 256) / 16) + '0'; - m_pageinput[2] = (page % 16) + '0'; - - m_curpage = page; - m_cursubpage = subpage; - PageUpdated(m_curpage, m_cursubpage); + if (m_teletextReader) + m_teletextReader->SetPage(page, subpage); } void TeletextScreen::SetDisplaying(bool display) @@ -455,224 +250,8 @@ void TeletextScreen::SetDisplaying(bool display) void TeletextScreen::Reset(void) { - QMutexLocker locker(&m_lock); - - for (uint mag = 0; mag < 8; mag++) - { - QMutexLocker lock(&m_magazines[mag].lock); - - // clear all sub pages in page - int_to_page_t::iterator iter; - iter = m_magazines[mag].pages.begin(); - while (iter != m_magazines[mag].pages.end()) - { - TeletextPage *page = &iter->second; - page->subpages.clear(); - ++iter; - } - - // clear pages - m_magazines[mag].pages.clear(); - m_magazines[mag].current_page = 0; - m_magazines[mag].current_subpage = 0; - m_magazines[mag].loadingpage.active = false; - } - memset(m_header, ' ', 40); - - m_curpage = 0x100; - m_cursubpage = -1; - m_curpage_showheader = true; - - m_pageinput[0] = '1'; - m_pageinput[1] = '0'; - m_pageinput[2] = '0'; -} - -void TeletextScreen::AddPageHeader(int page, int subpage, - const uint8_t * buf, - int vbimode, int lang, int flags) -{ - if (!m_displaying) - return; - - QMutexLocker locker(&m_lock); - - int magazine = MAGAZINE(page); - if (magazine < 1 || magazine > 8) - return; - int lastPage = m_magazines[magazine - 1].current_page; - int lastSubPage = m_magazines[magazine - 1].current_subpage; - - // update the last fetched page if the magazine is the same - // and the page no. is different - - if ((page != lastPage || subpage != lastSubPage) && - m_magazines[magazine - 1].loadingpage.active) - { - TeletextSubPage *ttpage = FindSubPage(lastPage, lastSubPage); - if (!ttpage) - { - ttpage = &(m_magazines[magazine - 1] - .pages[lastPage].subpages[lastSubPage]); - m_magazines[magazine - 1].pages[lastPage].pagenum = lastPage; - ttpage->subpagenum = lastSubPage; - } - - memcpy(ttpage, &m_magazines[magazine - 1].loadingpage, - sizeof(TeletextSubPage)); - - m_magazines[magazine - 1].loadingpage.active = false; - - PageUpdated(lastPage, lastSubPage); - } - - m_fetchpage = page; - m_fetchsubpage = subpage; - - TeletextSubPage *ttpage = &m_magazines[magazine - 1].loadingpage; - - m_magazines[magazine - 1].current_page = page; - m_magazines[magazine - 1].current_subpage = subpage; - - memset(ttpage->data, ' ', sizeof(ttpage->data)); - - ttpage->active = true; - ttpage->subpagenum = subpage; - - for (uint i = 0; i < 6; i++) - ttpage->floflink[i] = 0; - - ttpage->lang = lang; - ttpage->flags = flags; - ttpage->flof = 0; - - ttpage->subtitle = (vbimode == VBI_DVB_SUBTITLE); - - memset(ttpage->data[0], ' ', 8 * sizeof(uint8_t)); - - if (vbimode == VBI_DVB || vbimode == VBI_DVB_SUBTITLE) - { - for (uint j = 8; j < 40; j++) - ttpage->data[0][j] = m_bitswap[buf[j]]; - } - else - { - memcpy(ttpage->data[0]+0, buf, 40); - } - - if ( !(ttpage->flags & TP_INTERRUPTED_SEQ)) - { - memcpy(m_header, ttpage->data[0], 40); - HeaderUpdated(ttpage->data[0],ttpage->lang); - } -} - -/** - * \brief Adds Teletext Data from TeletextDecoder - */ -void TeletextScreen::AddTeletextData(int magazine, int row, - const uint8_t * buf, int vbimode) -{ - if (!m_displaying) - return; - - QMutexLocker locker(&m_lock); - - int b1, b2, b3, err = 0; - - if (magazine < 1 || magazine > 8) - return; - - int currentpage = m_magazines[magazine - 1].current_page; - if (!currentpage) - return; - - TeletextSubPage *ttpage = &m_magazines[magazine - 1].loadingpage; - - switch (row) - { - case 1 ... 24: // Page Data - if (vbimode == VBI_DVB || vbimode == VBI_DVB_SUBTITLE) - { - for (uint j = 0; j < 40; j++) - ttpage->data[row][j] = m_bitswap[buf[j]]; - } - else - { - memcpy(ttpage->data[row], buf, 40); - } - break; - case 26: - /* XXX TODO: Level 1.5, 2.5, 3.5 - * Character location & override - * Level 2.5, 3.5 - * Modifying display attributes - * All levels - * VCR Programming - * See 12.3 - */ - break; - case 27: // FLOF data (FastText) - switch (vbimode) - { - case VBI_IVTV: - b1 = hamm8(buf, &err); - b2 = hamm8(buf + 37, &err); - if (err & 0xF000) - return; - break; - case VBI_DVB: - case VBI_DVB_SUBTITLE: - b1 = hamm84(buf, &err); - b2 = hamm84(buf + 37, &err); - if (err == 1) - return; - break; - default: - return; - } - if (b1 != 0 || not(b2 & 8)) - return; - - for (int i = 0; i < 6; ++i) - { - err = 0; - switch (vbimode) - { - case VBI_IVTV: - b1 = hamm16(buf+1+6*i, &err); - b2 = hamm16(buf+3+6*i, &err); - b3 = hamm16(buf+5+6*i, &err); - if (err & 0xF000) - return; - break; - case VBI_DVB: - case VBI_DVB_SUBTITLE: - b1 = hamm84(buf+2+6*i, &err) * 16 + - hamm84(buf+1+6*i, &err); - b2 = hamm84(buf+4+6*i, &err) * 16 + - hamm84(buf+3+6*i, &err); - b3 = hamm84(buf+6+6*i, &err) * 16 + - hamm84(buf+5+6*i, &err); - if (err == 1) - return; - break; - default: - return; - } - - int x = (b2 >> 7) | ((b3 >> 5) & 0x06); - ttpage->floflink[i] = ((magazine ^ x) ?: 8) * 256 + b1; - ttpage->flof = 1; - } - break; - - case 31: // private streams - break; - - default: /// other packet codes... - break; - } + if (m_teletextReader) + m_teletextReader->Reset(); } void TeletextScreen::DrawHeader(const uint8_t *page, int lang) @@ -758,7 +337,7 @@ void TeletextScreen::DrawLine(const uint8_t *page, uint row, int lang) uint newfgcolor = kTTColorWhite; uint newbgcolor = kTTColorBlack; - if (m_curpage_issubtitle || m_transparent) + if (m_teletextReader->IsSubtitle() || m_teletextReader->IsTransparent()) { bgcolor = kTTColorTransparent; newbgcolor = kTTColorTransparent; @@ -888,7 +467,7 @@ void TeletextScreen::DrawLine(const uint8_t *page, uint row, int lang) ch = ' '; // BAD_CHAR; break; default: - if (conceal && !m_revealHidden) + if (conceal && !m_teletextReader->RevealHidden()) ch = ' '; break; } @@ -896,8 +475,7 @@ void TeletextScreen::DrawLine(const uint8_t *page, uint row, int lang) // Hide FastText/FLOF menu characters if not available if (flof_link_count && (flof_link_count <= 6)) { - const TeletextSubPage *ttpage = - FindSubPage(m_curpage, m_cursubpage); + const TeletextSubPage *ttpage = m_teletextReader->FindSubPage(); if (ttpage) { @@ -913,7 +491,7 @@ void TeletextScreen::DrawLine(const uint8_t *page, uint row, int lang) SetBackgroundColor(newbgcolor); if ((row != 0) || (x > 7)) { - if (m_transparent) + if (m_teletextReader->IsTransparent()) SetBackgroundColor(kTTColorTransparent); DrawBackground(x, row); @@ -1036,26 +614,19 @@ void TeletextScreen::DrawStatus(void) SetForegroundColor(kTTColorWhite); SetBackgroundColor(kTTColorBlack); - if (!m_transparent) + if (!m_teletextReader->IsTransparent()) for (int i = 0; i < 40; ++i) DrawBackground(i, 0); DrawCharacter(1, 0, 'P', 0); - DrawCharacter(2, 0, m_pageinput[0], 0); - DrawCharacter(3, 0, m_pageinput[1], 0); - DrawCharacter(4, 0, m_pageinput[2], 0); + DrawCharacter(2, 0, m_teletextReader->GetPageInput(0), 0); + DrawCharacter(3, 0, m_teletextReader->GetPageInput(1), 0); + DrawCharacter(4, 0, m_teletextReader->GetPageInput(2), 0); - const TeletextSubPage *ttpage = FindSubPage(m_curpage, m_cursubpage); + const TeletextSubPage *ttpage = m_teletextReader->FindSubPage(); if (!ttpage) { - SetBackgroundColor(kTTColorBlack); - SetForegroundColor(kTTColorWhite); - - if (!m_transparent) - for (int i = 7; i < 40; i++) - DrawBackground(i, 0); - QString str = QObject::tr("Page Not Available", "Requested Teletext page not available"); for (int i = 0; (i < 30) && i < str.length(); i++) @@ -1064,59 +635,14 @@ void TeletextScreen::DrawStatus(void) return; } - // get list of available sub pages - QString str = ""; - int count = 1, selected = 0; - const TeletextPage *page = FindPage(m_curpage); - if (page) - { - int_to_subpage_t::const_iterator subpageIter; - subpageIter = page->subpages.begin(); - while (subpageIter != page->subpages.end()) - { - const TeletextSubPage *subpage = &subpageIter->second; - - if (subpage->subpagenum == m_cursubpage) - { - selected = count; - str += "*"; - } - else - str += " "; - - str += QString().sprintf("%02X", subpage->subpagenum); - - ++subpageIter; - ++count; - } - } - + QString str = m_teletextReader->GetPage(); if (str.isEmpty()) return; - // if there are less than 9 subpages fill the empty slots with spaces - if (count < 10) - { - QString spaces; - spaces.fill(' ', 27 - str.length()); - str = " <" + str + spaces + " > "; - } - else - { - // try to centralize the selected sub page in the list - int startPos = selected - 5; - if (startPos < 0) - startPos = 0; - if (startPos + 9 >= count) - startPos = count - 10; - - str = " <" + str.mid(startPos * 3, 27) + " > "; - } - SetForegroundColor(kTTColorWhite); for (int x = 0; x < 11; x++) { - if (m_transparent) + if (m_teletextReader->IsTransparent()) SetBackgroundColor(kTTColorTransparent); else SetBackgroundColor(kTTColorBlack); @@ -1138,134 +664,6 @@ void TeletextScreen::DrawStatus(void) } } -void TeletextScreen::PageUpdated(int page, int subpage) -{ - if (!m_displaying) - return; - if (page != m_curpage) - return; - if (subpage != m_cursubpage && m_cursubpage != -1) - return; - m_page_changed = true; -} - -void TeletextScreen::HeaderUpdated(uint8_t * page, int lang) -{ - (void)lang; - - if (!m_displaying) - return; - - if (page == NULL) - return; - - if (m_curpage_showheader == false) - return; - - m_header_changed = true; -} - -const TeletextPage *TeletextScreen::FindPageInternal( - int page, int direction) const -{ - int mag = MAGAZINE(page); - - if (mag > 8 || mag < 1) - return NULL; - - QMutexLocker lock(&m_magazines[mag - 1].lock); - - int_to_page_t::const_iterator pageIter; - pageIter = m_magazines[mag - 1].pages.find(page); - if (pageIter == m_magazines[mag - 1].pages.end()) - return NULL; - - const TeletextPage *res = &pageIter->second; - if (direction == -1) - { - --pageIter; - if (pageIter == m_magazines[mag - 1].pages.end()) - { - int_to_page_t::const_reverse_iterator iter; - iter = m_magazines[mag - 1].pages.rbegin(); - res = &iter->second; - } - else - res = &pageIter->second; - } - - if (direction == 1) - { - ++pageIter; - if (pageIter == m_magazines[mag - 1].pages.end()) - { - pageIter = m_magazines[mag - 1].pages.begin(); - res = &pageIter->second; - } - else - res = &pageIter->second; - } - - return res; -} - -const TeletextSubPage *TeletextScreen::FindSubPageInternal( - int page, int subpage, int direction) const -{ - int mag = MAGAZINE(page); - - if (mag > 8 || mag < 1) - return NULL; - - QMutexLocker lock(&m_magazines[mag - 1].lock); - - int_to_page_t::const_iterator pageIter; - pageIter = m_magazines[mag - 1].pages.find(page); - if (pageIter == m_magazines[mag - 1].pages.end()) - return NULL; - - const TeletextPage *ttpage = &(pageIter->second); - int_to_subpage_t::const_iterator subpageIter = - ttpage->subpages.begin(); - - // try to find the subpage given, or first if subpage == -1 - if (subpage != -1) - subpageIter = ttpage->subpages.find(subpage); - - if (subpageIter == ttpage->subpages.end()) - return NULL; - - if (subpage == -1) - return &(subpageIter->second); - - const TeletextSubPage *res = &(subpageIter->second); - if (direction == -1) - { - --subpageIter; - if (subpageIter == ttpage->subpages.end()) - { - int_to_subpage_t::const_reverse_iterator iter = - ttpage->subpages.rbegin(); - res = &(iter->second); - } - else - { - res = &(subpageIter->second); - } - } - - if (direction == 1) - { - ++subpageIter; - if (subpageIter == ttpage->subpages.end()) - subpageIter = ttpage->subpages.begin(); - - res = &(subpageIter->second); - } - - return res; -} - bool TeletextScreen::InitialiseFont() { static bool initialised = false; diff --git a/mythtv/libs/libmythtv/teletextscreen.h b/mythtv/libs/libmythtv/teletextscreen.h index a876609de95..c20113c23aa 100644 --- a/mythtv/libs/libmythtv/teletextscreen.h +++ b/mythtv/libs/libmythtv/teletextscreen.h @@ -4,93 +4,10 @@ #include #include "mythscreentype.h" -#include "teletextdecoder.h" +#include "teletextreader.h" #include "mythplayer.h" -typedef enum -{ - kTTColorBlack = 0, - kTTColorRed = 1, - kTTColorGreen = 2, - kTTColorYellow = 3, - kTTColorBlue = 4, - kTTColorMagenta = 5, - kTTColorCyan = 6, - kTTColorWhite = 7, - kTTColorTransparent = 8, -} TTColor; - -class TTKey -{ - public: - static const uint k0 = 0; - static const uint k1 = 1; - static const uint k2 = 2; - static const uint k3 = 3; - static const uint k4 = 4; - static const uint k5 = 5; - static const uint k6 = 6; - static const uint k7 = 7; - static const uint k8 = 8; - static const uint k9 = 9; - static const uint kNextPage = 10; - static const uint kPrevPage = 11; - static const uint kNextSubPage = 12; - static const uint kPrevSubPage = 13; - static const uint kHold = 14; - static const uint kTransparent = 15; - static const uint kFlofRed = 16; - static const uint kFlofGreen = 17; - static const uint kFlofYellow = 18; - static const uint kFlofBlue = 19; - static const uint kFlofWhite = 20; - static const uint kRevealHidden = 21; -}; - -#define TP_SUPPRESS_HEADER 0x01 -#define TP_UPDATE_INDICATOR 0x02 -#define TP_INTERRUPTED_SEQ 0x04 -#define TP_INHIBIT_DISPLAY 0x08 -#define TP_MAGAZINE_SERIAL 0x10 -#define TP_ERASE_PAGE 0x20 -#define TP_NEWSFLASH 0x40 -#define TP_SUBTITLE 0x80 - -class TeletextSubPage -{ - public: - int pagenum; ///< the wanted page - int subpagenum; ///< the wanted subpage - int lang; ///< language code - int flags; ///< misc flags - uint8_t data[25][40]; ///< page data - int flof; ///< page has FastText links - int floflink[6]; ///< FastText links (FLOF) - bool subtitle; ///< page is subtitle page - bool active; ///< data has arrived since page last cleared -}; -typedef map int_to_subpage_t; - -class TeletextPage -{ - public: - int pagenum; - int current_subpage; - int_to_subpage_t subpages; -}; -typedef map int_to_page_t; - -class TeletextMagazine -{ - public: - mutable QMutex lock; - int current_page; - int current_subpage; - TeletextSubPage loadingpage; - int_to_page_t pages; -}; - -class TeletextScreen: public MythScreenType, public TeletextViewer +class TeletextScreen: public MythScreenType { static bool InitialiseFont(void); @@ -103,14 +20,10 @@ class TeletextScreen: public MythScreenType, public TeletextViewer virtual void Pulse(void); // TeletextViewer interface methods - virtual void KeyPress(uint key); - virtual void SetPage(int page, int subpage); - virtual void SetDisplaying(bool display); - virtual void Reset(void); - virtual void AddPageHeader(int page, int subpage, const uint8_t *buf, - int vbimode, int lang, int flags); - virtual void AddTeletextData(int magazine, int row, - const uint8_t* buf, int vbimode); + void KeyPress(uint key); + void SetPage(int page, int subpage); + void SetDisplaying(bool display); + void Reset(void); private: void CleanUp(); @@ -127,52 +40,16 @@ class TeletextScreen: public MythScreenType, public TeletextViewer void DrawStatus(void); void DrawPage(void); - void NewsFlash(void) {}; - void PageUpdated(int page, int subpage); - void HeaderUpdated(uint8_t *page, int lang); - - const TeletextSubPage *FindSubPage(int page, int subpage, int dir=0) const - { return FindSubPageInternal(page, subpage, dir); } - TeletextSubPage *FindSubPage(int page, int subpage, int dir = 0) - { return (TeletextSubPage*) FindSubPageInternal(page, subpage, dir); } - - const TeletextPage *FindPage(int page, int dir = 0) const - { return (TeletextPage*) FindPageInternal(page, dir); } - TeletextPage *FindPage(int page, int dir = 0) - { return (TeletextPage*) FindPageInternal(page, dir); } - - const TeletextSubPage *FindSubPageInternal(int,int,int) const; - const TeletextPage *FindPageInternal(int,int) const; - - MythPlayer *m_player; - QRect m_safeArea; - int m_colWidth; - int m_rowHeight; - - QMutex m_lock; - - int m_fetchpage; - int m_fetchsubpage; - QColor m_bgColor; - - // currently displayed page: - mutable int m_curpage; - mutable int m_cursubpage; - mutable bool m_curpage_showheader; - mutable bool m_curpage_issubtitle; - - int m_pageinput[3]; - bool m_transparent; - bool m_revealHidden; - bool m_displaying; - uint8_t m_header[40]; - mutable bool m_header_changed; - mutable bool m_page_changed; - TeletextMagazine m_magazines[8]; - unsigned char m_bitswap[256]; + MythPlayer *m_player; + TeletextReader *m_teletextReader; + QRect m_safeArea; + int m_colWidth; + int m_rowHeight; + QColor m_bgColor; + bool m_displaying; QHash m_rowImages; - int m_fontStretch; - int m_fontHeight; + int m_fontStretch; + int m_fontHeight; public: static const QColor kColorBlack;