summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Kendall <mkendall@mythtv.org>2010-11-30 03:32:38 (GMT)
committer Mark Kendall <mkendall@mythtv.org>2010-11-30 03:32:38 (GMT)
commit9fc9ee1b0d328d840877f42d0d99152bf984e906 (patch)
tree4d8ae851061e48d07f1a19fcb644b452abe4c729
parent255cdf9bce8c37a9045b9f74bf36813ff0461a17 (diff)
Refactor TeletextDecoder and TeletextScreen and add a new TeletextReader
class. This follows the approach used in the other subtitle and caption classes whereby the screen object handles OSD representation of the data, the reader object holds the state and data and the decoder object feeds new data into the reader. This simplifies setup and initialisation of the teletext objects and removes the requirement to lock the OSD from the decoder, which was causing endless problems. The previous behaviour of always decoding teletext packets is also reinstated which radically improves responsiveness. Actually decoding and parsing the packets is trivial for a modern processor and hence should have no impact on performance. I will backport to release-0-24-fixes in a few days if there are no reported problems. Refs #9271 git-svn-id: http://svn.mythtv.org/svn/trunk@27381 7dbf422c-18fa-0310-86e9-fd20926502f2
-rw-r--r--mythtv/libs/libmythtv/avformatdecoder.cpp9
-rw-r--r--mythtv/libs/libmythtv/avformatdecoder.h1
-rw-r--r--mythtv/libs/libmythtv/decoderbase.h1
-rw-r--r--mythtv/libs/libmythtv/libmythtv.pro4
-rw-r--r--mythtv/libs/libmythtv/mythplayer.cpp27
-rw-r--r--mythtv/libs/libmythtv/mythplayer.h6
-rw-r--r--mythtv/libs/libmythtv/teletextdecoder.cpp63
-rw-r--r--mythtv/libs/libmythtv/teletextdecoder.h42
-rw-r--r--mythtv/libs/libmythtv/teletextreader.cpp609
-rw-r--r--mythtv/libs/libmythtv/teletextreader.h162
-rw-r--r--mythtv/libs/libmythtv/teletextscreen.cpp674
-rw-r--r--mythtv/libs/libmythtv/teletextscreen.h153
12 files changed, 841 insertions, 910 deletions
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp
index 7c07634..6d9f8b4 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 487ab2b..3400943 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 c143a8b..3882686 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 17ceff2..d404d12 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 b9601fc..198e1fa 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 325efee..d676064 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 f9db7fc..88c9c45 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 0cd2ed5..d7175d2 100644
--- a/mythtv/libs/libmythtv/teletextdecoder.h
+++ b/mythtv/libs/libmythtv/teletextdecoder.h
@@ -3,52 +3,20 @@
#include <stdint.h>
-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 0000000..9d07c7d
--- a/dev/null
+++ b/mythtv/libs/libmythtv/teletextreader.cpp
@@ -0,0 +1,609 @@
+#include "teletextreader.h"
+
+#include <string.h>
+#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<int> (key);
+ else if (m_pageinput[1] == ' ')
+ m_pageinput[1] = '0' + static_cast<int> (key);
+ else if (m_pageinput[2] == ' ')
+ {
+ m_pageinput[2] = '0' + static_cast<int> (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<int> (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 0000000..088abb0
--- a/dev/null
+++ b/mythtv/libs/libmythtv/teletextreader.h
@@ -0,0 +1,162 @@
+#ifndef TELETEXTREADER_H
+#define TELETEXTREADER_H
+
+#include <stdint.h>
+#include <map>
+
+#include <QString>
+#include <QMutex>
+
+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, TeletextSubPage> int_to_subpage_t;
+
+class TeletextPage
+{
+ public:
+ int pagenum;
+ int current_subpage;
+ int_to_subpage_t subpages;
+};
+typedef map<int, TeletextPage> 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 4be77e4..f1830d2 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<int> (key);
- else if (m_pageinput[1] == ' ')
- m_pageinput[1] = '0' + static_cast<int> (key);
- else if (m_pageinput[2] == ' ')
- {
- m_pageinput[2] = '0' + static_cast<int> (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<int> (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 a876609..c20113c 100644
--- a/mythtv/libs/libmythtv/teletextscreen.h
+++ b/mythtv/libs/libmythtv/teletextscreen.h
@@ -4,93 +4,10 @@
#include <QFont>
#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, TeletextSubPage> int_to_subpage_t;
-
-class TeletextPage
-{
- public:
- int pagenum;
- int current_subpage;
- int_to_subpage_t subpages;
-};
-typedef map<int, TeletextPage> 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<int, QImage*> m_rowImages;
- int m_fontStretch;
- int m_fontHeight;
+ int m_fontStretch;
+ int m_fontHeight;
public:
static const QColor kColorBlack;