From 523f0df2e5c22d2a7b7df9e0cd279e4298f9ad2d Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sat, 7 Feb 2009 21:11:09 +0000 Subject: [PATCH] Teletext --- GNUmakefile | 4 +- audioplayer.cc | 2 +- boxstack.cc | 24 +- boxx.cc | 21 +- boxx.h | 3 +- colour.cc | 1 + colour.h | 1 + defines.h | 3 +- demuxer.cc | 84 +- demuxer.h | 29 +- demuxerts.cc | 42 +- demuxerts.h | 12 +- draintarget.h | 5 +- dssourcepin.cc | 2 +- localmediafile.h | 4 + main.cc | 7 + media.cc | 2 + media.h | 3 +- mediafile.cc | 62 +- mediaplayer.h | 3 +- mediaprovider.h | 5 + message.h | 3 + objects.mk | 3 +- osdwin.cc | 2 +- player.cc | 59 +- player.h | 15 + playerlive.h | 3 + playerliveradio.cc | 15 +- playerliveradio.h | 3 + playerlivetv.cc | 59 +- playerlivetv.h | 12 + playermedia.cc | 6 +- playerradio.cc | 2 +- serialize.cc | 6 + stream.cc | 8 +- surface.cc | 4 +- surface.h | 5 +- surfacemvp.cc | 8 +- surfacemvp.h | 4 +- surfacewin.cc | 14 +- surfacewin.h | 5 +- teletextdecodervbiebu.cc | 834 ++++++++++ teletextdecodervbiebu.h | 330 ++++ teletxt/COPYING | 340 ++++ teletxt/README | 98 ++ teletxt/tables.h | 112 ++ teletxt/txtfont.cc | 3371 ++++++++++++++++++++++++++++++++++++++ teletxt/txtfont.h | 14 + tfeed.cc | 88 + tfeed.h | 55 + vaudioselector.cc | 435 ++++- vaudioselector.h | 25 +- vfeed.cc | 2 +- vmedialist.cc | 4 +- vmediaview.cc | 5 +- vteletextview.cc | 346 ++++ vteletextview.h | 64 + vvideolivetv.cc | 115 +- vvideolivetv.h | 1 + vvideomedia.cc | 17 +- vvideorec.cc | 82 +- vvideorec.h | 2 + wjpeg.cc | 10 +- wjpeg.h | 2 +- wselectlist.cc | 3 +- wselectlist.h | 3 +- 66 files changed, 6714 insertions(+), 199 deletions(-) create mode 100644 teletextdecodervbiebu.cc create mode 100644 teletextdecodervbiebu.h create mode 100644 teletxt/COPYING create mode 100644 teletxt/README create mode 100644 teletxt/tables.h create mode 100644 teletxt/txtfont.cc create mode 100644 teletxt/txtfont.h create mode 100644 tfeed.cc create mode 100644 tfeed.h create mode 100644 vteletextview.cc create mode 100644 vteletextview.h diff --git a/GNUmakefile b/GNUmakefile index c879744..88ad464 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,8 +6,8 @@ CXX=$(CROSS)g++ LD=$(CROSS)g++ INCLUDES = -I../jpeg/jpeg-6b -CXXFLAGS_DEV = -g -O0 -Wall -Wshadow -Werror -DDEV -D_GNU_SOURCE $(INCLUDES) -CXXFLAGS_REL = -O3 -Wall -Wshadow -Werror -D_GNU_SOURCE $(INCLUDES) +CXXFLAGS_DEV = -g -O0 -Wall -Wshadow -DDEV -D_GNU_SOURCE $(INCLUDES) +CXXFLAGS_REL = -O3 -Wall -Wshadow -D_GNU_SOURCE $(INCLUDES) LDFLAGS = -Wall -static LIBPATHS = diff --git a/audioplayer.cc b/audioplayer.cc index a982437..f0930c1 100644 --- a/audioplayer.cc +++ b/audioplayer.cc @@ -74,7 +74,7 @@ AudioPlayer::AudioPlayer(Boxx *parent) : afeed(this) uri=NULL; demuxer=new DemuxerAudio(); logger->log("AudioPlayer", Log::DEBUG, "Audio player ctorII"); - if (!demuxer->init(this, audio, NULL, 0, DemuxerAudio::PACKET_SIZE+200)) + if (!demuxer->init(this, audio, NULL, NULL, 0, DemuxerAudio::PACKET_SIZE+200,0)) { logger->log("AudioPlayer", Log::ERR, "Demuxer failed to init"); shutdown(); diff --git a/boxstack.cc b/boxstack.cc index 8e183a5..f7cdbb5 100644 --- a/boxstack.cc +++ b/boxstack.cc @@ -72,7 +72,7 @@ int BoxStack::shutdown() int BoxStack::add(Boxx* v) { if (!initted) return 0; - + Log::getInstance()->log("BoxStack", Log::DEBUG, "add called"); #ifndef WIN32 pthread_mutex_lock(&boxLock); #else @@ -80,7 +80,16 @@ int BoxStack::add(Boxx* v) #endif Log::getInstance()->log("BoxStack", Log::DEBUG, "Locked for add"); - if (numBoxes == 16) return 0; + if (numBoxes == 16) + { //Error + Log::getInstance()->log("BoxStack", Log::ERR, "More than 16 boxes! Unlocked for add"); +#ifndef WIN32 + pthread_mutex_unlock(&boxLock); +#else + ReleaseMutex(boxLock); +#endif + return 0; + } boxes[numBoxes++] = v; #ifndef WIN32 @@ -215,8 +224,7 @@ void BoxStack::deleteBox(int z) void BoxStack::update(Boxx* toUpdate, Region* regionToUpdate) { -// Log::getInstance()->log("BoxStack", Log::DEBUG, "Update called"); - // Get the z index of the box + Log::getInstance()->log("BoxStack", Log::DEBUG, "Update called"); #ifndef WIN32 pthread_mutex_lock(&boxLock); @@ -225,6 +233,7 @@ void BoxStack::update(Boxx* toUpdate, Region* regionToUpdate) #endif Log::getInstance()->log("BoxStack", Log::DEBUG, "Locked for update"); + // Get the z index of the box int z; for (z = 0; z < numBoxes; z++) { @@ -234,6 +243,13 @@ void BoxStack::update(Boxx* toUpdate, Region* regionToUpdate) if (z == numBoxes) { // not a Box we have! +#ifndef WIN32 + pthread_mutex_unlock(&boxLock); +#else + MessageBox(0,"the evil error","error",0); + ReleaseMutex(boxLock); +#endif + Log::getInstance()->log("BoxStack", Log::ERR, "Unlocked for update! box not inside boxstack"); return; } diff --git a/boxx.cc b/boxx.cc index 1a26213..81b8878 100644 --- a/boxx.cc +++ b/boxx.cc @@ -346,20 +346,33 @@ void Boxx::drawTextCentre(const char* text, int x, int y, const Colour& colour) else surface->drawTextCentre(text, x, y, colour.rgba()); } -void Boxx::drawPixel(UINT x, UINT y, const Colour& colour) +void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw) { - if (parent) parent->drawPixel(area.x + x, area.y + y, colour); + if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw); else { - int c = ( (0xFF000000 ) + int c = ( (colour.alpha << 24 ) | (colour.red << 16) | (colour.green << 8) | (colour.blue ) ); - surface->drawPixel(x, y, c); + surface->drawPixel(x, y, c,fastdraw); } } +void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw) +{ + if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw); + else + { + int c = ( (0xFF000000 ) + | (colour.red << 16) + | (colour.green << 8) + | (colour.blue ) ); + + surface->drawPixel(x, y, c,fastdraw); + } +} void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm) { if (parent) parent->drawBitmap(area.x + x, area.y + y, bm); diff --git a/boxx.h b/boxx.h index d5eb7c1..0e7a4b9 100644 --- a/boxx.h +++ b/boxx.h @@ -102,8 +102,9 @@ class Boxx void drawText(const char* text, int x, int y, int width, const Colour& colour); void drawTextRJ(const char* text, int x, int y, const Colour& colour); void drawTextCentre(const char* text, int x, int y, const Colour& colour); - void drawPixel(UINT x, UINT y, const Colour& colour); + void drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw=false); void drawBitmap(UINT x, UINT y, const Bitmap& bm); + void drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw=false); /* This is for system which need a locking of the drawing surface to speed up drawing */ void startFastDraw(); diff --git a/colour.cc b/colour.cc index 7d309e8..f1b8f68 100644 --- a/colour.cc +++ b/colour.cc @@ -33,6 +33,7 @@ Colour Colour::VIEWBACKGROUND(0, 0, 100); Colour Colour::TABVIEWBACKGROUND(0, 0, 120); Colour Colour::TITLEBARBACKGROUND(0, 0, 200); Colour Colour::SELECTHIGHLIGHT(240, 250, 80); +Colour Colour::SELECTDARKHIGHLIGHT(120, 125, 40); Colour Colour::LIGHTTEXT(255, 255, 255); Colour Colour::DARKTEXT(0, 0, 100); Colour Colour::DANGER(200, 0, 0); diff --git a/colour.h b/colour.h index 58d0664..9c9687c 100644 --- a/colour.h +++ b/colour.h @@ -59,6 +59,7 @@ class Colour static Colour TABVIEWBACKGROUND; static Colour TITLEBARBACKGROUND; static Colour SELECTHIGHLIGHT; + static Colour SELECTDARKHIGHLIGHT; static Colour LIGHTTEXT; static Colour DARKTEXT; static Colour DANGER; diff --git a/defines.h b/defines.h index b400304..9f5815e 100644 --- a/defines.h +++ b/defines.h @@ -51,7 +51,8 @@ void MILLISLEEP(ULONG a); #else int max(int, int); - + int min(UINT, int); + #define Surface_TYPE SurfaceMVP #define Thread_TYPE ThreadP #include diff --git a/demuxer.cc b/demuxer.cc index 398a737..054baca 100644 --- a/demuxer.cc +++ b/demuxer.cc @@ -207,12 +207,14 @@ Demuxer* Demuxer::getInstance() return instance; } -int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, ULONG demuxMemoryV, ULONG demuxMemoryA, DVBSubtitles* tsubtitles) +int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, DrainTarget* teletext, + ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT, DVBSubtitles* tsubtitles) { if (!initted) { if ( !videostream.init(video, demuxMemoryV) || - !audiostream.init(audio, demuxMemoryA)) + !audiostream.init(audio, demuxMemoryA) || + !teletextstream.init(teletext, demuxMemoryT)) { Log::getInstance()->log("Demuxer", Log::CRIT, "Failed to initialize demuxer"); @@ -220,6 +222,11 @@ int Demuxer::init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, U return 0; } } + if (teletext) { + isteletextdecoded = true; + } else { + isteletextdecoded = false; + } reset(); initted = true; @@ -232,7 +239,7 @@ void Demuxer::reset() { Log::getInstance()->log("Demuxer", Log::DEBUG, "Reset called"); flush(); - video_current = audio_current = -1; + video_current = audio_current = teletext_current = subtitle_current = -1; horizontal_size = vertical_size = 0; aspect_ratio = (enum AspectRatio) 0; frame_rate = bit_rate = 0; @@ -246,12 +253,17 @@ void Demuxer::reset() { avail_ac3audchan[i] = false; } + for (int i = 0; i <= (PESTYPE_SUBSTREAM_DVBSUBTITLEMAX - PESTYPE_SUBSTREAM_DVBSUBTITLE0); i++) + { + avail_dvbsubtitlechan[i] = false; + } } int Demuxer::shutdown() { videostream.shutdown(); audiostream.shutdown(); + teletextstream.shutdown(); initted = false; return 1; } @@ -262,6 +274,7 @@ void Demuxer::flush() videostream.flush(); audiostream.flush(); + teletextstream.flush(); } void Demuxer::flushAudio() @@ -272,7 +285,7 @@ void Demuxer::flushAudio() void Demuxer::seek() { vid_seeking = aud_seeking = true; - video_pts = audio_pts = 0; + video_pts = audio_pts = teletext_pts = 0; } void Demuxer::setAudioStream(int id) @@ -285,6 +298,16 @@ void Demuxer::setVideoStream(int id) video_current = id; } +void Demuxer::setTeletextStream(int id) +{ + teletext_current = id; +} + +void Demuxer::setDVBSubtitleStream(int id) +{ + subtitle_current = id; +} + void Demuxer::setAspectRatio(enum AspectRatio ar) { if (aspect_ratio != ar) @@ -312,6 +335,11 @@ bool Demuxer::writeVideo() return videostream.drain(); } +bool Demuxer::writeTeletext() +{ + return teletextstream.drain(); +} + bool Demuxer::submitPacket(PESPacket& packet) { UINT sent = 0; @@ -350,11 +378,32 @@ bool Demuxer::submitPacket(PESPacket& packet) } } else if (packet_type == PESTYPE_PRIVATE_1 && - packet.getSubstream() == 0x20) + packet.getSubstream() >= PESTYPE_SUBSTREAM_DVBSUBTITLE0 && + packet.getSubstream() <= PESTYPE_SUBSTREAM_DVBSUBTITLEMAX) { - if (subtitles) subtitles->put(packet); + avail_dvbsubtitlechan[packet.getSubstream()-PESTYPE_SUBSTREAM_DVBSUBTITLE0]=true; + if (subtitle_current == -1) subtitle_current = packet.getSubstream(); + if (subtitles && packet.getSubstream()==subtitle_current) + { + subtitles->put(packet); + } sent = packet.getSize(); } + else if (isteletextdecoded && packet_type == PESTYPE_PRIVATE_1 && + packet.getSubstream() >= PESTYPE_SUBSTREAM_TELETEXT0 && + packet.getSubstream() <= PESTYPE_SUBSTREAM_TELETEXTMAX) + { + + if (teletext_current == -1) teletext_current = packet.getSubstream(); + if (teletext_current == packet.getSubstream() ) + { + sent = teletextstream.put(&packetdata[0], packet.getSize(), MPTYPE_TELETEXT); + } + else + { + sent = packet.getSize(); + } + } else { sent = packet.getSize(); @@ -435,6 +484,14 @@ pre_1_3_19_Recording: //This is for old recordings stuff and live TV } } break; + case 0x10: //Teletext Is this correct? + packet.setSubstream(substream_id); + // Extract teletxt PTS if it exists + if (packet.hasPTS()) + { + teletext_pts = packet.getPTS(); + } + break; default: if (!ispre_1_3_19) { @@ -540,12 +597,19 @@ bool* Demuxer::getac3AudioChannels() return avail_ac3audchan; } -int Demuxer::getselAudioChannel() +bool* Demuxer::getSubtitleChannels() { - return audio_current; + return avail_dvbsubtitlechan; +} + +int Demuxer::getselSubtitleChannel() +{ + return subtitle_current; } -void Demuxer::setAudioChannel(int aud_channel) +int Demuxer::getselAudioChannel() { - audio_current = aud_channel; + return audio_current; } + + diff --git a/demuxer.h b/demuxer.h index db5a8a6..bef9e79 100644 --- a/demuxer.h +++ b/demuxer.h @@ -79,15 +79,21 @@ class Demuxer Demuxer(); virtual ~Demuxer(); static Demuxer* getInstance(); - int init(Callback* callback, DrainTarget* audio, DrainTarget* video, ULONG demuxMemoryV, ULONG demuxMemoryA, DVBSubtitles* tsubtitles = NULL); + int init(Callback* tcallback, DrainTarget* audio, DrainTarget* video, + DrainTarget* teletext, + ULONG demuxMemoryV, ULONG demuxMemoryA, ULONG demuxMemoryT, + DVBSubtitles* tsubtitles=NULL); virtual void reset(); virtual void flush(); void flushAudio(); void seek(); void setVideoStream(int id); void setAudioStream(int id); + void setTeletextStream(int id); + void setDVBSubtitleStream(int id); bool writeAudio(); bool writeVideo(); + bool writeTeletext(); virtual int scan(UCHAR* buf, int len) = 0; virtual int findPTS(UCHAR* buf, int len, ULLONG* dest) = 0; @@ -99,8 +105,9 @@ class Demuxer bool* getmpAudioChannels(); //Maybe virtual ? bool* getac3AudioChannels(); //Maybe virtual ? + bool* getSubtitleChannels(); int getselAudioChannel(); - void setAudioChannel(int aud_channel); + int getselSubtitleChannel(); int getHorizontalSize() { return horizontal_size; } int getVerticalSize() { return vertical_size; } @@ -150,6 +157,18 @@ class Demuxer }; enum PESTYPE_SUBSTREAM { + PESTYPE_SUBSTREAM_TELETEXT0 = 0x10, + PESTYPE_SUBSTREAM_TELETEXT1,PESTYPE_SUBSTREAM_TELETEXT2, PESTYPE_SUBSTREAM_TELETEXT3, + PESTYPE_SUBSTREAM_TELETEXT4,PESTYPE_SUBSTREAM_TELETEXT5,PESTYPE_SUBSTREAM_TELETEXT6, + PESTYPE_SUBSTREAM_TELETEXT7, PESTYPE_SUBSTREAM_TELETEXT8, PESTYPE_SUBSTREAM_TELETEXT9, + PESTYPE_SUBSTREAM_TELETEXT10,PESTYPE_SUBSTREAM_TELETEXT11,PESTYPE_SUBSTREAM_TELETEXT12, + PESTYPE_SUBSTREAM_TELETEXT13,PESTYPE_SUBSTREAM_TELETEXT14,PESTYPE_SUBSTREAM_TELETEXT15, + PESTYPE_SUBSTREAM_TELETEXTMAX=PESTYPE_SUBSTREAM_TELETEXT15, + PESTYPE_SUBSTREAM_DVBSUBTITLE0=0x20, + PESTYPE_SUBSTREAM_DVBSUBTITLE1,PESTYPE_SUBSTREAM_DVBSUBTITLE2,PESTYPE_SUBSTREAM_DVBSUBTITLE3, + PESTYPE_SUBSTREAM_DVBSUBTITLE4,PESTYPE_SUBSTREAM_DVBSUBTITLE5,PESTYPE_SUBSTREAM_DVBSUBTITLE6, + PESTYPE_SUBSTREAM_DVBSUBTITLE7, + PESTYPE_SUBSTREAM_DVBSUBTITLEMAX=PESTYPE_SUBSTREAM_DVBSUBTITLE7, PESTYPE_SUBSTREAM_AC30 = 0x80, PESTYPE_SUBSTREAM_AC31,PESTYPE_SUBSTREAM_AC32, PESTYPE_SUBSTREAM_AC33, PESTYPE_SUBSTREAM_AC34,PESTYPE_SUBSTREAM_AC35,PESTYPE_SUBSTREAM_AC36, @@ -167,11 +186,12 @@ class Demuxer Stream videostream; Stream audiostream; DVBSubtitles* subtitles; + Stream teletextstream; int shutdown(); bool initted; bool vid_seeking; bool aud_seeking; - int video_current, audio_current; + int video_current, audio_current, teletext_current, subtitle_current; // Video stream information void setAspectRatio(enum AspectRatio); @@ -186,6 +206,8 @@ class Demuxer ULLONG video_pts; ULLONG video_pts_seek; ULLONG audio_pts; + ULLONG teletext_pts; + bool isteletextdecoded; // Constants static const int FrameRates[9]; @@ -193,6 +215,7 @@ class Demuxer bool ispre_1_3_19; bool avail_mpaudchan[PESTYPE_AUDMAX-PESTYPE_AUD0+1]; bool avail_ac3audchan[PESTYPE_SUBSTREAM_AC3MAX-PESTYPE_SUBSTREAM_AC30+1]; + bool avail_dvbsubtitlechan[PESTYPE_SUBSTREAM_DVBSUBTITLEMAX-PESTYPE_SUBSTREAM_DVBSUBTITLE0+1]; }; #endif diff --git a/demuxerts.cc b/demuxerts.cc index 03c6a9c..c60f4b0 100644 --- a/demuxerts.cc +++ b/demuxerts.cc @@ -21,13 +21,14 @@ #include "demuxerts.h" #include "log.h" -DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID) +DemuxerTS::DemuxerTS(int p_vID, int p_aID, int p_subID, int p_tID) { vID = p_vID; vActive = false; aID = p_aID; aActive = false; subID = p_subID; subActive = false; atype = 0; subLength = 0; + tID = p_tID; } void DemuxerTS::flush() @@ -47,10 +48,13 @@ void DemuxerTS::flush() break; } subPacket.init(PESTYPE_PRIVATE_1); +tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX); + vActive = false; aActive = false; subActive = false; subLength = 0; + tActive = false; } int DemuxerTS::scan(UCHAR *buf, int len) @@ -99,6 +103,14 @@ void DemuxerTS::setSubID(int p_subID) subLength = 0; } +void DemuxerTS::setTID(int p_tID) +{ + tID = p_tID; + tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX); + tActive = false; + +} + int DemuxerTS::findPTS(UCHAR* buf, int len, ULLONG* dest) { UINT LoPattern = 0x100 | PESTYPE_VID0, @@ -267,7 +279,19 @@ int DemuxerTS::processTS(UCHAR* buf) } subActive = true; } - + if (isteletextdecoded && pid == tID) + { + if (tActive) + { + if (!parsed) + { + parsePacketDetails(tPacket); + parsed = true; + } + rc = submitPacket(tPacket); + } + tActive = true; + } if (rc == 0) return 0; parsed = false; @@ -296,16 +320,28 @@ int DemuxerTS::processTS(UCHAR* buf) subLength = (buf[4] << 8) + buf[5]; buf += 6; datalen -= 6; } + if (isteletextdecoded && pid == tID) + { + tPacket.init(PESTYPE_PRIVATE_1,PESTYPE_SUBSTREAM_TELETEXTMAX); + buf += 6; datalen -= 6; + } } if ( (pid == vID && vActive) || (pid == aID && aActive) || + (pid == tID && tActive) || (pid == subID && subActive) ) { PESPacket* packet = NULL; if (pid == vID) packet = &vPacket; if (pid == aID) packet = &aPacket; - if (pid == subID) packet = &subPacket; + if (pid == subID) { +#ifdef WIN32 + MessageBox(0,"sub","usb",0); +#endif + packet = &subPacket; + } + if (pid == tID) packet = &tPacket; if (packet != NULL) { if (packet->write(buf, datalen) == 0) diff --git a/demuxerts.h b/demuxerts.h index 0df7cd6..e1f1923 100644 --- a/demuxerts.h +++ b/demuxerts.h @@ -30,14 +30,16 @@ class DemuxerTS : public Demuxer { public: - DemuxerTS(int p_vID = 0, int p_aID = 0, int p_subID = 0); + DemuxerTS(int p_vID = 0, int p_aID = 0, int p_subID = 0, int p_tID = 0); void flush(); int scan(UCHAR* buf, int len); int findPTS(UCHAR* buf, int len, ULLONG* dest); void setVID(int p_vID); + void setTID(int p_tID); void setAID(int p_aID, int type); void setSubID(int p_subID); int getVID() { return vID; } + int getTID() { return tID; } int getAID() { return aID; } int getSubID() { return subID; } int put(UCHAR* buf, int len); @@ -51,11 +53,13 @@ class DemuxerTS : public Demuxer PESPacket vPacket; // Video PES packet under construction PESPacket aPacket; // Audio PES packet under construction PESPacket subPacket; // Subtitles PES packet under construction - int vID, aID, subID; // TS IDs for video/audio/subtitles + PESPacket tPacket; // Teletext PES packet under construction + int vID, aID, subID,tID; // TS IDs for video/audio/subtitles + int atype; - bool vActive, aActive; // Whether video/audio is actively being captured bool subActive; // Same for subtitles - UINT subLength; // Expected length of subtitle packet + UINT subLength; // Expected length of subtitle packet +bool vActive, aActive, tActive; // Whether video/audio is actively being captured }; #endif diff --git a/draintarget.h b/draintarget.h index 751e551..4c73612 100644 --- a/draintarget.h +++ b/draintarget.h @@ -29,6 +29,7 @@ #define MPTYPE_AC3 0x02 #define MPTYPE_AC3_PRE13 0x03 //old vdr recording compatmode #define MPTYPE_MPEG_AUDIO_LAYER3 0x04 //for media mp3 playback +#define MPTYPE_TELETEXT 0x05 //for EBU VBI teletext struct MediaPacket { @@ -36,11 +37,11 @@ struct MediaPacket ULONG length; //length of the packet // The fields below are not needed by the MVP UCHAR type; + ULLONG pts; + bool synched; #ifdef WIN32 ULLONG recording_byte_pos; //position in recording - ULLONG pts; long long presentation_time;/* in 100 ns units*/ - bool synched; bool disconti; #endif }; diff --git a/dssourcepin.cc b/dssourcepin.cc index cd6049d..d5aa13a 100644 --- a/dssourcepin.cc +++ b/dssourcepin.cc @@ -717,7 +717,7 @@ HRESULT DsSourcePin::GetMediaTypeAc3(int iPosition, AM_MEDIA_TYPE *pmt) wfe.wFormatTag = WAVE_FORMAT_UNKNOWN; wfe.wBitsPerSample = 0; pmt->subtype = MEDIASUBTYPE_DOLBY_AC3; - // pmt->subtype = MEDIASUBTYPE_DOLBY_AC3_SPDIF; + // pmt->subtype = MEDIASUBTYPE_DOLBY_AC3_SPDIF; pmt->formattype = FORMAT_WaveFormatEx; pmt->cbFormat = sizeof(wfe); pmt->pbFormat = (BYTE*)CoTaskMemAlloc(sizeof(wfe)); diff --git a/localmediafile.h b/localmediafile.h index b83ee76..6da202e 100644 --- a/localmediafile.h +++ b/localmediafile.h @@ -25,7 +25,11 @@ #include "media.h" #include #include +#ifndef WIN32 #include +#else + +#endif #include #include "log.h" diff --git a/main.cc b/main.cc index ac5a593..fee7214 100644 --- a/main.cc +++ b/main.cc @@ -520,8 +520,15 @@ void MILLISLEEP(ULONG a) #endif } +int min(UINT a, int b) +{ + if (a > b) return b; + else return a; +} + int max(int a, int b) { if (a > b) return a; else return b; } + diff --git a/media.cc b/media.cc index ec036f9..6361585 100644 --- a/media.cc +++ b/media.cc @@ -20,7 +20,9 @@ #include "media.h" #include +#ifndef WIN32 #include +#endif #ifndef SNPRINTF #define SNPRINTF snprintf #endif diff --git a/media.h b/media.h index b2b37f8..7ad0522 100644 --- a/media.h +++ b/media.h @@ -21,8 +21,9 @@ #ifndef MEDIA_H #define MEDIA_H -using namespace std; + #include +using namespace std; #include #include #include "defines.h" diff --git a/mediafile.cc b/mediafile.cc index 2e558dc..d01f1ae 100644 --- a/mediafile.cc +++ b/mediafile.cc @@ -18,11 +18,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifndef WIN32 +#include +#else +#include "threadwin.h" +#include +#endif + #include "mediafile.h" #include "media.h" #include #include -#include + #include #include "log.h" @@ -83,10 +90,12 @@ ULONG MediaFile::getMediaType(const char * filename) { Media * MediaFile::createMedia(const char * dirname, const char * filename, bool withURI) { Media * rt=NULL; - char *buffer; - asprintf(&buffer, "%s/%s", dirname, filename); - struct stat st; + char *buffer=(char*)malloc(strlen(dirname)+strlen(filename)+2); + sprintf(buffer, "%s/%s", dirname, filename); + ULONG mtype=MEDIA_TYPE_UNKNOWN; +#ifndef WIN32 + struct stat st; if (stat(buffer, &st) == 0) { if (S_ISDIR(st.st_mode)) { mtype=MEDIA_TYPE_DIR; @@ -95,12 +104,29 @@ Media * MediaFile::createMedia(const char * dirname, const char * filename, bool mtype=getMediaType(filename); } } +#else + WIN32_FILE_ATTRIBUTE_DATA att; + GetFileAttributesEx(buffer,GetFileExInfoStandard,&att); + if (att.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + mtype=MEDIA_TYPE_DIR; + } else { + mtype=getMediaType(filename); + } +#endif + //only consider entries we accept by type here if (mtype != MEDIA_TYPE_UNKNOWN) { rt =new Media(); rt->setMediaType(mtype); rt->setFileName(filename); +#ifndef WIN32 rt->setTime(st.st_mtime); +#else + struct timespec targetTime; + targetTime.tv_sec=(*((__int64*) &att.ftCreationTime)-WINDOWS_TIME_BASE_OFFSET)/(10*1000*1000); + targetTime.tv_nsec=((*((__int64*)&att.ftCreationTime)-WINDOWS_TIME_BASE_OFFSET)%(10*1000*1000))*100; + rt->setTime(targetTime.tv_sec); +#endif Log::getInstance()->log("Media",Log::DEBUG,"created Media %s, type=%d",filename,mtype); if (withURI) { MediaURI u(providerid,buffer,NULL); @@ -118,15 +144,25 @@ MediaList* MediaFile::getMediaList(const MediaURI * parent){ rt=new MediaList(parent); const char *dirname=parent->getName(); //open the directory and read out the entries +#ifndef WIN32 DIR *d=opendir(dirname); struct dirent *e; union { // according to "The GNU C Library Reference Manual" struct dirent d; char b[offsetof(struct dirent, d_name) + NAME_MAX + 1]; } u; - while (d != NULL && (readdir_r(d,&u.d,&e) == 0) && e != NULL) { - const char * fname=e->d_name; + const char * fname=e->d_name; +#else + WIN32_FIND_DATA e; + HANDLE d; + d=FindFirstFile(dirname,&e); + if (d==INVALID_HANDLE_VALUE) { + return rt; + } + do { + const char * fname=e.cFileName; +#endif if ( fname == NULL) continue; if (strcmp(fname,".") == 0) continue; if (strcmp(fname,"..") == 0) continue; @@ -138,10 +174,15 @@ MediaList* MediaFile::getMediaList(const MediaURI * parent){ else { if (m) delete m; } +#ifndef WIN32 } if (d != NULL) closedir(d); +#else + } while (FindNextFile(d,&e)); + FindClose(d); +#endif return rt; - } +} int MediaFile::openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, ULONG xsize, ULONG ysize) { @@ -155,9 +196,14 @@ int MediaFile::openMedium(ULONG channel, const MediaURI * uri, ULLONG * size, UL Log::getInstance()->log("Media::openMedium",Log::ERR,"unable to open file fn=%s,chan=%u",uri->getName(),channel); return -1; } - struct stat st; + ULLONG mysize=0; +#ifndef WIN32 + struct stat st; if ( fstat(fileno(fp),&st) == 0) mysize=st.st_size; +#else + mysize=_filelength(_fileno(fp)); +#endif if (mysize == 0) { Log::getInstance()->log("Media::openMedium",Log::ERR,"unable to open file fn=%s,chan=%u",uri->getName(),channel); fclose(fp); diff --git a/mediaplayer.h b/mediaplayer.h index c3dfcf2..ada5c97 100644 --- a/mediaplayer.h +++ b/mediaplayer.h @@ -21,8 +21,9 @@ #ifndef MEDIAPLAYER #define MEDIAPLAYER -using namespace std; + #include +using namespace std; #include #include #include "mediaprovider.h" diff --git a/mediaprovider.h b/mediaprovider.h index 04c17b7..f5b1e94 100644 --- a/mediaprovider.h +++ b/mediaprovider.h @@ -23,7 +23,12 @@ #include #include +#ifndef WIN32 #include +#else + +#endif + #include "defines.h" class Media; diff --git a/message.h b/message.h index 0c50be4..7d5d794 100644 --- a/message.h +++ b/message.h @@ -71,6 +71,9 @@ class Message const static ULONG CHANGED_REMOTECONTROL = 29; const static ULONG DELETE_SELECTED_TIMER = 30; const static ULONG CHANGED_DEVICEOPTIONS = 31; + const static ULONG TELETEXTUPDATE = 32; + const static ULONG TELETEXTUPDATEFIRSTLINE = 33; + const static ULONG SUBTITLE_CHANGE_CHANNEL = 34; }; #endif diff --git a/objects.mk b/objects.mk index ad2727e..f724306 100644 --- a/objects.mk +++ b/objects.mk @@ -23,5 +23,6 @@ OBJECTS1 = command.o log.o tcp.o dsock.o thread.o timers.o i18n.o mutex.o bitmap.o dvbsubtitles.o \ imagereader.o vcolourtuner.o mediaoptions.o mediaplayer.o mediafile.o \ serialize.o localmediafile.o vmediaview.o vvideomedia.o playermedia.o \ - demuxermedia.o + demuxermedia.o tfeed.o vteletextview.o teletextdecodervbiebu.o \ + teletxt/txtfont.o diff --git a/osdwin.cc b/osdwin.cc index bf829b3..aff35f7 100644 --- a/osdwin.cc +++ b/osdwin.cc @@ -231,7 +231,7 @@ void OsdWin::Render() } void OsdWin::RenderDS(LPDIRECT3DSURFACE9 present){ - if (!initted) return; + if (!initted) return; if (external_driving) { InternalRendering(present); lastrendertime=timeGetTime(); diff --git a/player.cc b/player.cc index 774cda9..9400d0e 100644 --- a/player.cc +++ b/player.cc @@ -37,7 +37,7 @@ // ----------------------------------- Called from outside, one offs or info funcs Player::Player(MessageQueue* tmessageQueue, void* tmessageReceiver, OSDReceiver* tosdReceiver) -: vfeed(this), afeed(this) +: vfeed(this), afeed(this), tfeed(this) { messageQueue = tmessageQueue; messageReceiver = tmessageReceiver; @@ -82,7 +82,11 @@ int Player::init() subtitles = new DVBSubtitles(osdReceiver); if (!subtitles) return 0; - if (!demuxer->init(this, audio, video, 2097152, 524288, subtitles)) + teletext = new TeletextDecoderVBIEBU(); + if (!teletext) return 0; + teletext->setRecordigMode(true); + + if (!demuxer->init(this, audio, video,teletext, 2097152, 524288,65536, subtitles)) { logger->log("Player", Log::ERR, "Demuxer failed to init"); shutdown(); @@ -91,6 +95,7 @@ int Player::init() vfeed.init(); afeed.init(); + tfeed.init(); video->stop(); video->blank(); @@ -110,6 +115,8 @@ int Player::shutdown() demuxer = NULL; delete subtitles; subtitles = NULL; + delete teletext; + teletext = NULL; #ifdef WIN32 CloseHandle(mutex); @@ -167,14 +174,34 @@ bool* Player::getDemuxerAc3AudioChannels() return demuxer->getac3AudioChannels(); } +bool* Player::getDemuxerSubtitleChannels() +{ + return demuxer->getSubtitleChannels(); +} + int Player::getCurrentAudioChannel() { return demuxer->getselAudioChannel(); } +int Player::getCurrentSubtitleChannel() +{ + return demuxer->getselSubtitleChannel(); +} + +void Player::setSubtitleChannel(int newChannel) +{ + return demuxer->setDVBSubtitleStream(newChannel); +} + +int *Player::getTeletxtSubtitlePages() +{ + return teletext->getSubtitlePages(); +} + void Player::setAudioChannel(int newChannel, int type) { - demuxer->setAudioChannel(newChannel); + demuxer->setAudioStream(newChannel); } bool Player::toggleSubtitles() @@ -192,6 +219,20 @@ bool Player::toggleSubtitles() return subtitlesShowing; } +void Player::turnSubtitlesOn(bool ison) { + if (ison) + { + subtitlesShowing = true; + subtitles->show(); + } + else + { + subtitlesShowing = false; + subtitles->hide(); + } + +} + // ----------------------------------- Externally called events void Player::play() @@ -371,6 +412,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) threadStop(); vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); demuxer->flush(); state = S_FFWD; @@ -384,6 +426,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) threadStop(); vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); demuxer->flush(); state = S_FBWD; @@ -394,6 +437,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) { vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); threadStop(); video->stop(); @@ -416,6 +460,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) threadStop(); vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); demuxer->flush(); state = S_PAUSE_I; @@ -451,6 +496,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) audio->systemMuteOn(); vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); threadStop(); video->unPause(); @@ -465,6 +511,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) audio->systemMuteOn(); vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); threadStop(); video->unPause(); @@ -477,6 +524,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) { vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); threadStop(); video->stop(); @@ -504,6 +552,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) threadStop(); vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); demuxer->flush(); state = S_PAUSE_I; @@ -712,6 +761,7 @@ void Player::switchState(UCHAR toState, ULONG jumpFrame) logger->log("Player", Log::DEBUG, "Immediate play"); afeed.start(); vfeed.start(); + tfeed.start(); subtitles->start(); video->sync(); audio->sync(); @@ -781,6 +831,7 @@ void Player::restartAtFrame(ULONG newFrame) { vfeed.stop(); afeed.stop(); + tfeed.stop(); subtitles->stop(); threadStop(); video->stop(); @@ -793,6 +844,7 @@ void Player::restartAtFrame(ULONG newFrame) demuxer->setFrameNum(newFrame); videoStartup = true; afeed.start(); + tfeed.start(); vfeed.start(); subtitles->start(); threadStart(); @@ -943,6 +995,7 @@ void Player::threadMethod() demuxer->setFrameNum(currentFrameNumber); videoStartup = true; afeed.start(); + tfeed.start(); vfeed.start(); subtitles->start(); audio->play(); diff --git a/player.h b/player.h index b009956..3db0a11 100644 --- a/player.h +++ b/player.h @@ -38,6 +38,9 @@ #include "defines.h" #include "vfeed.h" #include "afeed.h" +#include "tfeed.h" + +#include "teletextdecodervbiebu.h" class MessageQueue; class Audio; @@ -60,7 +63,10 @@ class Player : public Thread_TYPE, public Callback void setLengthBytes(ULLONG length); void setLengthFrames(ULONG length); void setAudioChannel(int newChannel, int type); + void setSubtitleChannel(int newChannel); bool toggleSubtitles(); + void turnSubtitlesOn(bool ison); + bool isSubtitlesOn() {return subtitlesShowing;}; void play(); void stop(); @@ -79,7 +85,12 @@ class Player : public Thread_TYPE, public Callback UCHAR getIScanRate() { return ifactor; } bool* getDemuxerMpegAudioChannels(); bool* getDemuxerAc3AudioChannels(); + bool* getDemuxerSubtitleChannels(); + int *getTeletxtSubtitlePages(); int getCurrentAudioChannel(); + int getCurrentSubtitleChannel(); + + TeletextDecoderVBIEBU * getTeletextDecoder(){return teletext;}; void call(void*); // for callback interface @@ -133,6 +144,10 @@ class Player : public Thread_TYPE, public Callback VDR* vdr; VFeed vfeed; AFeed afeed; + TFeed tfeed; + TeletextDecoderVBIEBU *teletext; + + bool initted; bool startup; diff --git a/playerlive.h b/playerlive.h index 88beca2..601ddef 100644 --- a/playerlive.h +++ b/playerlive.h @@ -47,10 +47,13 @@ class PlayerLive virtual void setChannel(ULONG index)=0; virtual void stop()=0; virtual void setAudioChannel(int newChannel,int type)=0; + virtual void setSubtitleChannel(int newChannel)=0; virtual bool* getDemuxerMpegAudioChannels()=0; virtual bool* getDemuxerAc3AudioChannels()=0; virtual int getCurrentAudioChannel()=0; + virtual int getCurrentSubtitleChannel()=0; + virtual int *getTeletxtSubtitlePages()=0; }; #endif diff --git a/playerliveradio.cc b/playerliveradio.cc index e4a5f38..6b6f35f 100644 --- a/playerliveradio.cc +++ b/playerliveradio.cc @@ -61,7 +61,7 @@ int PlayerLiveRadio::init() demuxer = new DemuxerTS(); if (!demuxer) return 0; - if (!demuxer->init(this, audio, NULL, 0, 200000)) + if (!demuxer->init(this, audio, NULL, NULL, 0, 200000,0)) { logger->log("PlayerLiveRadio", Log::ERR, "Demuxer failed to init"); shutdown(); @@ -103,11 +103,24 @@ int PlayerLiveRadio::getCurrentAudioChannel() return demuxer->getAID(); } +int *PlayerLiveRadio::getTeletxtSubtitlePages(){ + return NULL; +} + +int PlayerLiveRadio::getCurrentSubtitleChannel(){ + return demuxer->getSubID(); +} + void PlayerLiveRadio::setAudioChannel(int newChannel, int type) { return demuxer->setAID(newChannel, type); } +void PlayerLiveRadio::setSubtitleChannel(int newChannel) +{ + return demuxer->setSubID(newChannel); +} + // ----------------------------------- Externally called events void PlayerLiveRadio::go(ULONG index) diff --git a/playerliveradio.h b/playerliveradio.h index 9f6aee3..9a3865a 100644 --- a/playerliveradio.h +++ b/playerliveradio.h @@ -61,10 +61,13 @@ class PlayerLiveRadio : public PlayerLive, public Thread_TYPE, public Callback, virtual void setChannel(ULONG index); virtual void stop(); virtual void setAudioChannel(int newChannel, int type); + virtual void setSubtitleChannel(int newChannel); virtual bool* getDemuxerMpegAudioChannels(); virtual bool* getDemuxerAc3AudioChannels(); virtual int getCurrentAudioChannel(); + virtual int *getTeletxtSubtitlePages(); + virtual int getCurrentSubtitleChannel(); void call(void*); // for callback interface diff --git a/playerlivetv.cc b/playerlivetv.cc index 5df0680..47972be 100644 --- a/playerlivetv.cc +++ b/playerlivetv.cc @@ -35,7 +35,7 @@ // ----------------------------------- Called from outside, one offs or info funcs PlayerLiveTV::PlayerLiveTV(MessageQueue* tmessageQueue, void* tmessageReceiver, OSDReceiver* tosdReceiver, ChannelList* tchanList) -: vfeed(this), afeed(this) +: vfeed(this), afeed(this), tfeed(this) { messageQueue = tmessageQueue; messageReceiver = tmessageReceiver; @@ -70,8 +70,10 @@ int PlayerLiveTV::init() if (!demuxer) return 0; subtitles = new DVBSubtitles(osdReceiver); if (!subtitles) return 0; + + teletext = new TeletextDecoderVBIEBU(); - if (!demuxer->init(this, audio, video, 2097152, 524288, subtitles)) + if (!demuxer->init(this, audio, video, teletext, 2097152, 524288, 65536)) { logger->log("PlayerLiveTV", Log::ERR, "Demuxer failed to init"); shutdown(); @@ -80,6 +82,7 @@ int PlayerLiveTV::init() vfeed.init(); afeed.init(); + tfeed.init(); video->stop(); video->blank(); @@ -97,7 +100,8 @@ int PlayerLiveTV::shutdown() delete demuxer; delete subtitles; - + delete teletext; + teletext = NULL; return 1; } @@ -121,6 +125,20 @@ void PlayerLiveTV::setAudioChannel(int newChannel, int type) return demuxer->setAID(newChannel,type); } +void PlayerLiveTV::setSubtitleChannel(int newChannel) +{ + return demuxer->setSubID(newChannel); +} + +int *PlayerLiveTV::getTeletxtSubtitlePages() +{ + return teletext->getSubtitlePages(); +} + +int PlayerLiveTV::getCurrentSubtitleChannel(){ + return demuxer->getSubID(); +} + bool PlayerLiveTV::toggleSubtitles() { if (!subtitlesShowing) @@ -136,6 +154,20 @@ bool PlayerLiveTV::toggleSubtitles() return subtitlesShowing; } + +void PlayerLiveTV::turnSubtitlesOn(bool ison) { + if (ison) + { + subtitlesShowing = true; + subtitles->show(); + } + else + { + subtitlesShowing = false; + subtitles->hide(); + } + +} // ----------------------------------- Externally called events void PlayerLiveTV::go(ULONG index) @@ -322,6 +354,7 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); subtitles->start(); + tfeed.start(); state = newState; return; @@ -353,6 +386,7 @@ void PlayerLiveTV::switchState(UCHAR newState) vfeed.stop(); afeed.stop(); subtitles->stop(); + tfeed.stop(); video->blank(); video->reset(); @@ -373,8 +407,8 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); - subtitles->start(); - + subtitles->start(); + tfeed.start(); state = newState; return; } @@ -384,9 +418,9 @@ void PlayerLiveTV::switchState(UCHAR newState) clearStreamChunks(); vfeed.stop(); afeed.stop(); - subtitles->stop(); - video->stop(); - video->blank(); +subtitles->stop(); + tfeed.stop(); + video->stop(); video->blank(); audio->stop(); audio->reset(); video->reset(); @@ -420,6 +454,7 @@ void PlayerLiveTV::switchState(UCHAR newState) vfeed.stop(); afeed.stop(); subtitles->stop(); + tfeed.stop(); video->stop(); video->blank(); audio->stop(); @@ -442,6 +477,7 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); subtitles->start(); + tfeed.start(); state = newState; return; @@ -453,6 +489,7 @@ void PlayerLiveTV::switchState(UCHAR newState) vfeed.stop(); afeed.stop(); subtitles->stop(); + tfeed.stop(); video->stop(); video->blank(); audio->stop(); @@ -481,6 +518,7 @@ void PlayerLiveTV::switchState(UCHAR newState) vfeed.stop(); afeed.stop(); subtitles->stop(); + tfeed.stop(); video->stop(); video->blank(); audio->stop(); @@ -496,6 +534,7 @@ void PlayerLiveTV::switchState(UCHAR newState) vfeed.stop(); afeed.stop(); subtitles->stop(); + tfeed.stop(); video->stop(); video->blank(); audio->stop(); @@ -518,6 +557,7 @@ void PlayerLiveTV::switchState(UCHAR newState) afeed.start(); vfeed.start(); subtitles->start(); + tfeed.start(); state = newState; return; @@ -614,7 +654,8 @@ void PlayerLiveTV::threadMethod() } if (chan->numSPids > 0) demuxer->setSubID(chan->spids[0].pid); - + demuxer->setTID(chan->tpid); + teletext->ResetDecoder(); int streamSuccess = vdr->streamChannel(chan->number, this); if (!checkError() && !streamSuccess) { diff --git a/playerlivetv.h b/playerlivetv.h index eb589c7..ebc3a46 100644 --- a/playerlivetv.h +++ b/playerlivetv.h @@ -42,8 +42,11 @@ #include "defines.h" #include "vfeed.h" #include "afeed.h" +#include "tfeed.h" #include "vdr.h" +#include "teletextdecodervbiebu.h" + class MessageQueue; class Audio; class Video; @@ -65,11 +68,18 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub virtual void setChannel(ULONG index); virtual void stop(); virtual void setAudioChannel(int newChannel,int type); + virtual void setSubtitleChannel(int newChannel); virtual bool toggleSubtitles(); + virtual void turnSubtitlesOn(bool ison); + virtual bool isSubtitlesOn() {return subtitlesShowing;}; virtual bool* getDemuxerMpegAudioChannels(); virtual bool* getDemuxerAc3AudioChannels(); virtual int getCurrentAudioChannel(); + virtual int getCurrentSubtitleChannel(); + virtual int *getTeletxtSubtitlePages(); + + TeletextDecoderVBIEBU * getTeletextDecoder(){return teletext;}; void call(void*); // for callback interface @@ -100,9 +110,11 @@ class PlayerLiveTV : public PlayerLive, public Thread_TYPE, public Callback, pub Video* video; DemuxerTS* demuxer; DVBSubtitles* subtitles; + TeletextDecoderVBIEBU *teletext; VDR* vdr; VFeed vfeed; AFeed afeed; + TFeed tfeed; ChannelList* chanList; queue instructions; diff --git a/playermedia.cc b/playermedia.cc index 14209d3..536ed4c 100644 --- a/playermedia.cc +++ b/playermedia.cc @@ -57,7 +57,7 @@ PlayerMedia::PlayerMedia(Boxx *parent) : afeed(this), vfeed(this) sequence=0; demuxer=new DemuxerMedia(); logger->log("PlayerMedia", Log::DEBUG, "ctorII"); - if (!demuxer->init(this, audio, video, 2097152, 524288)) + if (!demuxer->init(this, audio, video, NULL, 2097152, 524288, 0)) { logger->log("PlayerMedia", Log::ERR, "Demuxer failed to init"); shutdown(); @@ -703,7 +703,7 @@ void PlayerMedia::call(void* caller) void PlayerMedia::setAudioChannel(int newChannel) { - demuxer->setAudioChannel(newChannel); + demuxer->setAudioStream(newChannel); } bool* PlayerMedia::getDemuxerMpegAudioChannels() @@ -760,7 +760,7 @@ char * PlayerMedia::getInfo() { else { sprintf(brbuf,"CBR, %d kBit/s",br*4/10); } - snprintf(ibuf,500,"%s: %dx%d\n" + SNPRINTF(ibuf,500,"%s: %dx%d\n" "%s: %s\n" "%s: %s\n", tr("Format"), diff --git a/playerradio.cc b/playerradio.cc index a16ff23..ddd15ba 100644 --- a/playerradio.cc +++ b/playerradio.cc @@ -74,7 +74,7 @@ int PlayerRadio::init(ULLONG tlengthBytes, ULONG tlengthPackets) demuxer = new DemuxerVDR(); if (!demuxer) return 0; - if (!demuxer->init(this, audio, NULL, 0, 40000)) + if (!demuxer->init(this, audio, NULL, NULL, 0, 40000, 0)) { logger->log("PlayerRadio", Log::ERR, "Demuxer failed to init"); shutdown(); diff --git a/serialize.cc b/serialize.cc index 75baa7a..92720f4 100644 --- a/serialize.cc +++ b/serialize.cc @@ -20,7 +20,13 @@ #include "serialize.h" #include +#ifndef WIN32 #include +#else +#include +#endif + + #ifndef SNPRINTF #define SNPRINTF snprintf #endif diff --git a/stream.cc b/stream.cc index caa3aa5..f053f02 100644 --- a/stream.cc +++ b/stream.cc @@ -76,11 +76,12 @@ int Stream::put(const UCHAR* inbuf, int len, UCHAR type) newPacket.length = len; newPacket.pos_buffer = 0; newPacket.type = type; -#ifdef WIN32 + newPacket.pts=0; newPacket.synched=false; +#ifdef WIN32 newPacket.disconti=false; - newPacket.pts=0; newPacket.presentation_time=0; +#endif if (type!=MPTYPE_MPEG_AUDIO_LAYER3) {//no PES //Extract the pts... if ((inbuf[7] & 0x80) && len>14 ) { @@ -90,12 +91,13 @@ int Stream::put(const UCHAR* inbuf, int len, UCHAR type) ( (ULLONG)(inbuf[11] & 0xFE) << 14 ) | ( (ULLONG)(inbuf[12]) << 7 ) | ( (ULLONG)(inbuf[13] & 0xFE) >> 1 ); +#ifdef WIN32 //ok we have the pts now convert it to a continously time code in 100ns units newPacket.presentation_time=(ULLONG)(newPacket.pts*10000LL/90LL); newPacket.presentation_time-=draintarget->SetStartOffset(newPacket.presentation_time,&newPacket.disconti); +#endif } } -#endif lock(); int front, back; diff --git a/surface.cc b/surface.cc index 70f3024..13a1daa 100644 --- a/surface.cc +++ b/surface.cc @@ -55,6 +55,7 @@ int Surface::drawText(const char* text, int x, int y, int width, ULONG rgba) X = 0; cx = 0; + startFastDraw(); for (i=0; i> (32 - X)) & 0x1) { - drawPixel(x+X+cx, y+Y, rgba); + drawPixel(x+X+cx, y+Y, rgba,true); pixels++; } } } cx += w; } + endFastDraw(); return 1; } diff --git a/surface.h b/surface.h index 628b621..ce412ac 100644 --- a/surface.h +++ b/surface.h @@ -61,9 +61,8 @@ class Surface virtual void display()=0; virtual int fillblt(int x, int y, int width, int height, unsigned int c)=0; - virtual void drawPixel(int x, int y, unsigned int c)=0; - virtual void drawPixel(int x, int y, Colour& c)=0; - virtual void drawHorzLine(int x1, int x2, int y, unsigned int c)=0; + virtual void drawPixel(int x, int y, unsigned int c, bool fastdraw=false)=0; + virtual void drawPixel(int x, int y, Colour& c, bool fastdraw=false)=0; virtual void drawHorzLine(int x1, int x2, int y, unsigned int c)=0; virtual void drawVertLine(int x, int y1, int y2, unsigned int c)=0; virtual void drawBitmap(int x, int y, const Bitmap& bm)=0; virtual int updateToScreen(int sx, int sy, int w, int h, int dx, int dy)=0; diff --git a/surfacemvp.cc b/surfacemvp.cc index 7280453..5fd5b59 100644 --- a/surfacemvp.cc +++ b/surfacemvp.cc @@ -200,7 +200,7 @@ int SurfaceMVP::fillblt(int x, int y, int width, int height, unsigned int c) return ioctl(fdOsd, GFX_FB_OSD_FILLBLT, &fblt); } -void SurfaceMVP::drawPixel(int x, int y, unsigned int c) +void SurfaceMVP::drawPixel(int x, int y, unsigned int c, bool fastdraw) { int offset; unsigned char r, g, b, a, Y, U, V; @@ -225,9 +225,9 @@ void SurfaceMVP::drawPixel(int x, int y, unsigned int c) *(surface.base[1] + (offset & 0xfffffffe)) = U; *(surface.base[1] + (offset & 0xfffffffe) + 1) = V; *(surface.base[2] + offset) = a; - } -void SurfaceMVP::drawPixel(int x, int y, Colour& c) + +void SurfaceMVP::drawPixel(int x, int y, Colour& c, bool fastdraw) { int offset; unsigned char Y, U, V; @@ -251,9 +251,7 @@ void SurfaceMVP::drawPixel(int x, int y, Colour& c) *(surface.base[1] + (offset & 0xfffffffe)) = U; *(surface.base[1] + (offset & 0xfffffffe) + 1) = V; *(surface.base[2] + offset) = 0xff; - } - void SurfaceMVP::drawHorzLine(int x1, int x2, int y, unsigned int c) { diff --git a/surfacemvp.h b/surfacemvp.h index 752a24a..91598b5 100644 --- a/surfacemvp.h +++ b/surfacemvp.h @@ -161,8 +161,8 @@ class SurfaceMVP : public Surface unsigned long getSurfaceHandle(); int fillblt(int x, int y, int width, int height, unsigned int rgba); - void drawPixel(int x, int y, unsigned int c); - void drawPixel(int x, int y, Colour& c); + void drawPixel(int x, int y, unsigned int c, bool fastdraw=false); + void drawPixel(int x, int y, Colour& c, bool fastdraw=false); void drawHorzLine(int x1, int x2, int y, unsigned int c); void drawVertLine(int x, int y1, int y2, unsigned int c); void drawBitmap(int x, int y, const Bitmap& bm); diff --git a/surfacewin.cc b/surfacewin.cc index 106a3c3..5153c38 100644 --- a/surfacewin.cc +++ b/surfacewin.cc @@ -29,7 +29,7 @@ SurfaceWin::SurfaceWin(int id) d3dtexture=NULL; d3dsurface=NULL; sheight=swidth=0; - fastdraw=false; +// fastdraw=false; event = CreateEvent(NULL,/*FALSE*/TRUE,FALSE,NULL); } @@ -151,7 +151,7 @@ void SurfaceWin::startFastDraw(){ return ; } } - fastdraw=true; +// fastdraw=true; } void SurfaceWin::endFastDraw(){ OsdWin* osd=((OsdWin*)(Osd::getInstance())); @@ -160,19 +160,19 @@ void SurfaceWin::endFastDraw(){ return ; } osd->EndPainting(); - fastdraw=false; +// fastdraw=false; } -void SurfaceWin::drawPixel(int x, int y, Colour & colour) { +void SurfaceWin::drawPixel(int x, int y, Colour & colour, bool fastdraw) { int c = ( (0xFF000000 ) | (colour.red << 16) | (colour.green << 8) | (colour.blue ) ); - drawPixel(x, y, c); + drawPixel(x, y, c, fastdraw); } -void SurfaceWin::drawPixel(int x, int y, unsigned int c) +void SurfaceWin::drawPixel(int x, int y, unsigned int c, bool fastdraw) { //FixMe: locking for every single Pixel will be painfully slow OsdWin* osd; @@ -230,7 +230,7 @@ void SurfaceWin::drawBitmap(int x, int y, const Bitmap& bm) startFastDraw(); for (UINT j = 0; j < bm.getHeight(); ++j) for (UINT i = 0; i < bm.getWidth(); ++i) - drawPixel(x+i, y+j, bm.getColour(i,j)); + drawPixel(x+i, y+j, bm.getColour(i,j),true); endFastDraw(); } diff --git a/surfacewin.h b/surfacewin.h index 0004ac7..8d9cd9d 100644 --- a/surfacewin.h +++ b/surfacewin.h @@ -39,8 +39,8 @@ class SurfaceWin : public Surface void endFastDraw(); int fillblt(int x, int y, int width, int height, unsigned int c); - void drawPixel(int x, int y, unsigned int c); - void drawPixel(int x, int y, Colour& c); + void drawPixel(int x, int y, Colour& c, bool fastdraw=false); + void drawPixel(int x, int y, unsigned int c, bool fastdraw=false); void drawHorzLine(int x1, int x2, int y, unsigned int c); void drawVertLine(int x, int y1, int y2, unsigned int c); void drawBitmap(int x, int y, const Bitmap& bm); @@ -60,7 +60,6 @@ class SurfaceWin : public Surface D3DLOCKED_RECT lockrect; UINT sheight,swidth; HANDLE event; - bool fastdraw; }; #endif diff --git a/teletextdecodervbiebu.cc b/teletextdecodervbiebu.cc new file mode 100644 index 0000000..44e2c16 --- /dev/null +++ b/teletextdecodervbiebu.cc @@ -0,0 +1,834 @@ +/* + Copyright 2008 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +/* Portions from vdr osdteletext plugin "txtrender.c": */ +/*************************************************************************** + * * + * txtrender.c - Teletext display abstraction and teletext code * + * renderer * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * Changelog: * + * 2005-03 initial version (c) Udo Richter * + * * + ***************************************************************************/ + +#include "teletextdecodervbiebu.h" +#include "teletxt/tables.h" +#include "message.h" +#include "command.h" +#include "video.h" + +#ifdef WIN32 +#include +#endif + +TeletextDecoderVBIEBU::TeletextDecoderVBIEBU() +{ + selectedpage=0x100; + ourpage=false; + flags=lang=0; + + CleanPage(); + FirstG0CodePage=0; + SecondG0CodePage=0; + dirty=false; + txtview=NULL; + firstlineupdate=0; + gotcha=false; + char digits[]={'1','0','0'}; + setKeyinDigits(digits,false); + isrecording=false; + for (int i=0;i<10;i++) record_pages[i]=-1; + + +} + +TeletextDecoderVBIEBU::~TeletextDecoderVBIEBU() +{ + + +} + +long long TeletextDecoderVBIEBU::SetStartOffset(long long curreftime, bool *rsync) +{ + return 0; +} + +void TeletextDecoderVBIEBU::ResetTimeOffsets() +{ + +} + + + +void TeletextDecoderVBIEBU::ResetDecoder() +{ + gotcha=false; + ourpage=false; + firstlineupdate=0; + selectedpage=0x100; + CleanPage(); + char digits[]={'1','0','0'}; + setKeyinDigits(digits,false); + for (int i=0;i<10;i++) record_pages[i]=-1; + +} + +void TeletextDecoderVBIEBU::setPage(unsigned int newpage) +{ + selectedpage=newpage; + gotcha=false; + ourpage=false; + firstlineupdate=0; + for (int i=0;i<25;i++) { + memset(curpage[i],0,40); + } +} + +void TeletextDecoderVBIEBU::CleanPage() +{ + int x,y; + for (int i=0;i<25;i++) { + memset(curpage[i],0,40); + } + for (y=0;y<25;y++) { + for (x=0;x<40;x++) { + cTeletextChar c; + c.SetFGColor(ttcWhite); + c.SetBGColor(ttcBlack); + c.SetCharset(CHARSET_LATIN_G0); + c.SetChar(' '); + if (flags&0x60) { + c.SetBoxedOut(true); + } + setChar(x,y,c); + } + } + +} +void TeletextDecoderVBIEBU::setKeyinDigits(char digits[3],bool inKeying) +{ + int x; + inkeying=inKeying; + for (x=0;x<3;x++) { + cTeletextChar c; + c.SetFGColor(ttcWhite); + c.SetBGColor(ttcBlack); + c.SetCharset(CHARSET_LATIN_G0); + c.SetChar(digits[x]); + if (flags&0x60) { + c.SetBoxedOut(true); + } + setChar(x+3,0,c); + keyindigits[x]=digits[x]; + } +} + +void TeletextDecoderVBIEBU::PrepareMediaSample(const MediaPacketList& mplist, UINT samplepos) +{ + mediapacket = mplist.front(); +} + +static ULLONG PTSDifference(ULLONG pts1, ULLONG pts2) +{ + // Assume pts1, pts2 < 2^33; calculate pts1 - pts2 + if (pts1 > pts2) + return pts1 - pts2; + else + return (1LL<<33) + pts1 - pts2; +} + +UINT TeletextDecoderVBIEBU::DeliverMediaSample(const UCHAR* buffer, UINT *samplepos) +{ + if (mediapacket.type != MPTYPE_TELETEXT) + { + *samplepos= 0; + return 1; //Skip it! + } + unsigned int headerstrip; + unsigned char txtdata[43]; + headerstrip=buffer[mediapacket.pos_buffer+8]+9; + //headerstrip+=4; //substream id + unsigned int datapos=0; + unsigned int datatype=buffer[mediapacket.pos_buffer+headerstrip+0]; + //Chris should we use here the pts data from mediapacket ? + // in this case the data fields should also be added in mediamvp + if (mediapacket.synched) + { // An entry exists in the work list + ULLONG nowPTS = Video::getInstance()->getCurrentTimestamp(); + if (PTSDifference(mediapacket.pts, nowPTS) >= 1200*90000) { + *samplepos=0; + return 1;//bad data skip it + } + if (nowPTS < (mediapacket.pts-4000) ) { + *samplepos=0; + return 0; + } + } + + if (( datatype>=0x10 && datatype <=0x1F) || + ( datatype>=0x99 && datatype <=0x9B)) { + //EBU VBI DATA + datapos++; + while (datapos< (mediapacket.length-headerstrip)) { + unsigned int unit_id=buffer[mediapacket.pos_buffer+headerstrip+datapos]; + datapos++; + unsigned int unit_length=buffer[mediapacket.pos_buffer+headerstrip+datapos]; + datapos++; + switch (unit_id) { + case 0x02: + case 0x03: {//Teletext with and without subtitles + //call teletext decoder + unsigned int field=buffer[mediapacket.pos_buffer+headerstrip+datapos]; + + if ((datapos+44)< (mediapacket.length-headerstrip)) { + for (int i=0;i<42;i++) { + txtdata[i]=invtab[buffer[mediapacket.pos_buffer+headerstrip+datapos+2+i]]; + } + DecodeTeletext(txtdata,field); + } + }break; + case 0xC0: //inverted Teletext + //call teletext decoder + break; + + case 0xC3: //VPS + //what to do with this, in the moment we do not need it + break; + case 0xC4: //WSS + //what to do with this, in the moment we do not need it + break; + case 0xC5: //CC + //what to do with this, in the moment we do not need it + break; + case 0xC6: //monochrome 4:2:2 samples, what is that? + //what to do with this, in the moment we do not need it + break; + default: + // case 0x00,0x01,0x04..0x7f,0x80..0xbf,0xc1,0xc2,0xc7..0xfe,0xff: //discard + //discard + break; + }; + datapos+=unit_length; + // while (buffer[mediapacket.pos_buffer+headerstrip+datapos]==0xFF &&(datapos< (mediapacket.length-headerstrip))) { + // datapos++; //stuffing bytes + // } + + + } + *samplepos=0; + return 1; + + + } else { + *samplepos= 0; + return 1; //Skip it! and discard data + } + + return 0; + +} +// This part is inspired by the vdr-plugin-osdteletext of Udo Richter and Marcel Wiesweg +void TeletextDecoderVBIEBU::DecodeTeletext(const UCHAR* buffer, unsigned int field) //needs to be exactly 42 byte long!! +{ + UCHAR hdrbuf[5]; + for (int i=0;i<5;i++) hdrbuf[i]=(unhamtab[buffer[2*i]]&0xF) | ((unhamtab[buffer[2*i+1]]&0xF)<< 4); + int header=hdrbuf[0]; + int magazin=header & 0x7; + int line = (header>>3) & 0x1f; + if (magazin==0) magazin=8; + if (line==0) + { + if (ourpage) { + gotcha=true; + inkeying=false; + RenderTeletextCode(false); + } else { + RenderTeletextCode(true); + } + int pagenumber=hdrbuf[1]; + int pagemagazin=magazin<<8 | pagenumber; + int pagesubnumber=(hdrbuf[2]) || ((hdrbuf[3]<<8) & 0x3f7f); + + if (pagemagazin == selectedpage) ourpage=true; + else ourpage=false; + if (isrecording) { + for (int i=0;i<10;i++) { + if (pagemagazin==record_pages[i]) break; + if (record_pages[i]==-1) { + record_pages[i]=pagemagazin; + break; + } + } + } + if (hdrbuf[3] &0x80) { //This is a subtitle + for (int i=0;i<10;i++) { + if (pagemagazin==record_pages[i]) break; + if (record_pages[i]==-1) { + record_pages[i]=pagemagazin; + break; + } + } + } + + + if (ourpage) { + lang=((hdrbuf[4]>>5) & 0x07); + flags=hdrbuf[2] & 0x80; + flags|=(hdrbuf[3]&0x40)|((hdrbuf[3]>>2)&0x20); //?????? + flags|=((hdrbuf[4]<<4)&0x10)|((hdrbuf[4]<<2)&0x08)|(hdrbuf[4]&0x04)|((hdrbuf[4]>>1)&0x02)|((hdrbuf[4]>>4)&0x01); + for (int i=0;i<25;i++) { + memset(curpage[i],0,40); + } + } + + memcpy(curpage[line],buffer+2,40); + } else if (ourpage && (line<=25)) { + memcpy(curpage[line],buffer+2,40); + + } +} + + +/* from osdteletext plugin: (slightly adapted for vomp)*/ +// Font tables + +// teletext uses 7-bit numbers to identify a font set. +// There are three font sets involved: +// Primary G0, Secondary G0, and G2 font set. + +// Font tables are organized in blocks of 8 fonts: + +enumCharsets FontBlockG0_0000[8] = { + CHARSET_LATIN_G0_EN, + CHARSET_LATIN_G0_DE, + CHARSET_LATIN_G0_SV_FI, + CHARSET_LATIN_G0_IT, + CHARSET_LATIN_G0_FR, + CHARSET_LATIN_G0_PT_ES, + CHARSET_LATIN_G0_CZ_SK, + CHARSET_LATIN_G0 +}; + +enumCharsets FontBlockG2Latin[8]={ + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2 +}; + +enumCharsets FontBlockG0_0001[8] = { + CHARSET_LATIN_G0_PL, + CHARSET_LATIN_G0_DE, + CHARSET_LATIN_G0_SV_FI, + CHARSET_LATIN_G0_IT, + CHARSET_LATIN_G0_FR, + CHARSET_LATIN_G0, + CHARSET_LATIN_G0_CZ_SK, + CHARSET_LATIN_G0 +}; + +enumCharsets FontBlockG0_0010[8] = { + CHARSET_LATIN_G0_EN, + CHARSET_LATIN_G0_DE, + CHARSET_LATIN_G0_SV_FI, + CHARSET_LATIN_G0_IT, + CHARSET_LATIN_G0_FR, + CHARSET_LATIN_G0_PT_ES, + CHARSET_LATIN_G0_TR, + CHARSET_LATIN_G0 +}; + + +enumCharsets FontBlockG0_0011[8] = { + CHARSET_LATIN_G0, + CHARSET_LATIN_G0, + CHARSET_LATIN_G0, + CHARSET_LATIN_G0, + CHARSET_LATIN_G0, + CHARSET_LATIN_G0_SR_HR_SL, + CHARSET_LATIN_G0, + CHARSET_LATIN_G0_RO +}; + +enumCharsets FontBlockG0_0100[8] = { + CHARSET_CYRILLIC_G0_SR_HR, + CHARSET_LATIN_G0_DE, + CHARSET_LATIN_G0_EE, + CHARSET_LATIN_G0_LV_LT, + CHARSET_CYRILLIC_G0_RU_BG, + CHARSET_CYRILLIC_G0_UK, + CHARSET_LATIN_G0_CZ_SK, + CHARSET_INVALID +}; + +enumCharsets FontBlockG2_0100[8] = { + CHARSET_CYRILLIC_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_LATIN_G2, + CHARSET_CYRILLIC_G2, + CHARSET_CYRILLIC_G2, + CHARSET_LATIN_G2, + CHARSET_INVALID +}; + +enumCharsets FontBlockG0_0110[8] = { + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_LATIN_G0_TR, + CHARSET_GREEK_G0 +}; + +enumCharsets FontBlockG2_0110[8] = { + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_LATIN_G2, + CHARSET_GREEK_G2 +}; + +enumCharsets FontBlockG0_1000[8] = { + CHARSET_LATIN_G0_EN, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_LATIN_G0_FR, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_ARABIC_G0 +}; + +enumCharsets FontBlockG2_1000[8] = { + CHARSET_ARABIC_G2, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_ARABIC_G2, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_ARABIC_G2 +}; + +enumCharsets FontBlockG0_1010[8] = { + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_HEBREW_G0, + CHARSET_INVALID, + CHARSET_ARABIC_G0, +}; + +enumCharsets FontBlockG2_1010[8] = { + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_ARABIC_G2, + CHARSET_INVALID, + CHARSET_ARABIC_G2, +}; + +enumCharsets FontBlockInvalid[8] = { + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID, + CHARSET_INVALID +}; + + + +// The actual font table definition: +// Split the 7-bit number into upper 4 and lower 3 bits, +// use upper 4 bits for outer array, +// use lower 3 bits for inner array + +struct structFontBlock { + enumCharsets *G0Block; + enumCharsets *G2Block; +}; + +structFontBlock FontTable[16] = { + { FontBlockG0_0000, FontBlockG2Latin }, // 0000 block + { FontBlockG0_0001, FontBlockG2Latin }, // 0001 block + { FontBlockG0_0010, FontBlockG2Latin }, // 0010 block + { FontBlockG0_0011, FontBlockG2Latin }, // 0011 block + { FontBlockG0_0100, FontBlockG2_0100 }, // 0100 block + { FontBlockInvalid, FontBlockInvalid }, // 0101 block + { FontBlockG0_0110, FontBlockG2_0110 }, // 0110 block + { FontBlockInvalid, FontBlockInvalid }, // 0111 block + { FontBlockG0_1000, FontBlockG2_1000 }, // 1000 block + { FontBlockInvalid, FontBlockInvalid }, // 1001 block + { FontBlockG0_1010, FontBlockG2_1010 }, // 1010 block + { FontBlockInvalid, FontBlockInvalid }, // 1011 block + { FontBlockInvalid, FontBlockInvalid }, // 1100 block + { FontBlockInvalid, FontBlockInvalid }, // 1101 block + { FontBlockInvalid, FontBlockInvalid }, // 1110 block + { FontBlockInvalid, FontBlockInvalid } // 1111 block +}; + +inline enumCharsets GetG0Charset(int codepage) { + return FontTable[codepage>>3].G0Block[codepage&7]; +} +inline enumCharsets GetG2Charset(int codepage) { + return FontTable[codepage>>3].G2Block[codepage&7]; +} + +enum enumSizeMode { + // Possible size modifications of characters + sizeNormal, + sizeDoubleWidth, + sizeDoubleHeight, + sizeDoubleSize +}; + +void TeletextDecoderVBIEBU::RenderTeletextCode(bool renderfirstlineonly) { + int x,y; + bool EmptyNextLine=false; + // Skip one line, in case double height chars were/will be used + + // Get code pages: + int LocalG0CodePage=(FirstG0CodePage & 0x78) + | ((lang & 0x04)>>2) | (lang & 0x02) | ((lang & 0x01)<<2); + enumCharsets FirstG0=GetG0Charset(LocalG0CodePage); + enumCharsets SecondG0=GetG0Charset(SecondG0CodePage); + // Reserved for later use: + // enumCharsets FirstG2=GetG2Charset(LocalG0CodePage); + + for (y=0;y<24;(EmptyNextLine?y+=2:y++)) { + // Start of line: Set start of line defaults + + // Hold Mosaics mode: Remember last mosaic char/charset + // for next spacing code + bool HoldMosaics=false; + unsigned char HoldMosaicChar=' '; + enumCharsets HoldMosaicCharset=FirstG0; + + enumSizeMode Size=sizeNormal; + // Font size modification + bool SecondCharset=false; + // Use primary or secondary G0 charset + bool GraphicCharset=false; + // Graphics charset used? + bool SeparateGraphics=false; + // Use separated vs. contiguous graphics charset + bool NoNextChar=false; + // Skip display of next char, for double-width + EmptyNextLine=false; + // Skip next line, for double-height + + cTeletextChar c; + // auto.initialized to everything off + c.SetFGColor(ttcWhite); + c.SetBGColor(ttcBlack); + c.SetCharset(FirstG0); + + if (y==0 && (flags&0x10)) { + if (!inkeying ) c.SetBoxedOut(true); + + } + if (flags&0x60) { + if (!(inkeying && y==0) ) c.SetBoxedOut(true); + + } + if (y==0) { + + for (x=0;x<8;x++) { + cTeletextChar c2=c; + + if (x>=3 && x<6){ + c2.SetChar(keyindigits[x-3]); + + } + else + c2.SetChar(' '); + setChar(x,0,c2); + } + } + + // Pre-scan for double-height and double-size codes + for (x=0;x<40;x++) { + if (y==0 && x<8) x=8; + if ((curpage[y][x] & 0x7f)==0x0D || (curpage[y][x] & 0x7f)==0x0F) + EmptyNextLine=true; + } + + // Move through line + for (x=0;x<40;x++) { + unsigned char ttc=curpage[y][x] & 0x7f; + // skip parity check + + if (y==0 && x<8) continue; + if (y==0 && x<31 && renderfirstlineonly && gotcha && !inkeying) continue; + // no displayable data here... + +/* // Debug only: Output line data and spacing codes + if (y==6) { + if (ttc<0x20) + printf("%s ",names[ttc]); + else + printf("%02x ",ttc); + if (x==39) printf("\n"); + } +*/ + + // Handle all 'Set-At' spacing codes + switch (ttc) { + case 0x09: // Steady + c.SetBlink(false); + break; + case 0x0C: // Normal Size + if (Size!=sizeNormal) { + Size=sizeNormal; + HoldMosaicChar=' '; + HoldMosaicCharset=FirstG0; + } + break; + case 0x18: // Conceal + c.SetConceal(true); + break; + case 0x19: // Contiguous Mosaic Graphics + SeparateGraphics=false; + if (GraphicCharset) + c.SetCharset(CHARSET_GRAPHICS_G1); + break; + case 0x1A: // Separated Mosaic Graphics + SeparateGraphics=true; + if (GraphicCharset) + c.SetCharset(CHARSET_GRAPHICS_G1_SEP); + break; + case 0x1C: // Black Background + c.SetBGColor(ttcBlack); + break; + case 0x1D: // New Background + c.SetBGColor(c.GetFGColor()); + break; + case 0x1E: // Hold Mosaic + HoldMosaics=true; + break; + } + + // temporary copy of character data: + cTeletextChar c2=c; + // c2 will be text character or space character or hold mosaic + // c2 may also have temporary flags or charsets + + if (ttc<0x20) { + // Spacing code, display space or hold mosaic + if (HoldMosaics) { + c2.SetChar(HoldMosaicChar); + c2.SetCharset(HoldMosaicCharset); + } else { + c2.SetChar(' '); + } + } else { + // Character code + c2.SetChar(ttc); + if (GraphicCharset) { + if (ttc&0x20) { + // real graphics code, remember for HoldMosaics + HoldMosaicChar=ttc; + HoldMosaicCharset=c.GetCharset(); + } else { + // invalid code, pass-through to G0 + c2.SetCharset(SecondCharset?SecondG0:FirstG0); + } + } + } + + // Handle double-height and double-width extremes + if (y>=23) { + if (Size==sizeDoubleHeight) Size=sizeNormal; + if (Size==sizeDoubleSize) Size=sizeDoubleWidth; + } + if (x>=38) { + if (Size==sizeDoubleWidth) Size=sizeNormal; + if (Size==sizeDoubleSize) Size=sizeDoubleHeight; + } + + // Now set character code + + if (NoNextChar) { + // Suppress this char due to double width last char + NoNextChar=false; + } else { + switch (Size) { + case sizeNormal: + // Normal sized + setChar(x,y,c2); + if (EmptyNextLine && y<23) { + // Clean up next line + setChar(x,y+1,c2.ToChar(' ').ToCharset(FirstG0)); + } + break; + case sizeDoubleWidth: + // Double width + setChar(x,y,c2.ToDblWidth(dblw_Left)); + setChar(x+1,y,c2.ToDblWidth(dblw_Right)); + if (EmptyNextLine && y<23) { + // Clean up next line + setChar(x ,y+1,c2.ToChar(' ').ToCharset(FirstG0)); + setChar(x+1,y+1,c2.ToChar(' ').ToCharset(FirstG0)); + } + NoNextChar=true; + break; + case sizeDoubleHeight: + // Double height + setChar(x,y,c2.ToDblHeight(dblh_Top)); + setChar(x,y+1,c2.ToDblHeight(dblh_Bottom)); + break; + case sizeDoubleSize: + // Double Size + setChar(x , y,c2.ToDblHeight(dblh_Top ).ToDblWidth(dblw_Left )); + setChar(x+1, y,c2.ToDblHeight(dblh_Top ).ToDblWidth(dblw_Right)); + setChar(x ,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Left )); + setChar(x+1,y+1,c2.ToDblHeight(dblh_Bottom).ToDblWidth(dblw_Right)); + NoNextChar=true; + break; + } + } + + // Handle all 'Set-After' spacing codes + if (ttc>=0x00 && ttc<=0x07) { // Set FG color + if (GraphicCharset) { + // Actual switch from graphics charset + HoldMosaicChar=' '; + HoldMosaicCharset=FirstG0; + } + c.SetFGColor((enumTeletextColor)ttc); + c.SetCharset(SecondCharset?SecondG0:FirstG0); + GraphicCharset=false; + c.SetConceal(false); + } else if (ttc==0x08) { + c.SetBlink(true); + } else if (ttc==0x0A) { + c.SetBoxedOut(true); + } else if (ttc==0x0B) { + // Start Box + c.SetBoxedOut(false); + } else if (ttc==0x0D) { + if (Size!=sizeDoubleHeight) { + Size=sizeDoubleHeight; + HoldMosaicChar=' '; + HoldMosaicCharset=FirstG0; + } + } else if (ttc==0x0E) { + if (Size!=sizeDoubleWidth) { + Size=sizeDoubleWidth; + HoldMosaicChar=' '; + HoldMosaicCharset=FirstG0; + } + } else if (ttc==0x0E) { + if (Size!=sizeDoubleSize) { + Size=sizeDoubleSize; + HoldMosaicChar=' '; + HoldMosaicCharset=FirstG0; + } + } else if (ttc>=0x10 && ttc<=0x17) { + if (!GraphicCharset) { + // Actual switch to graphics charset + HoldMosaicChar=' '; + HoldMosaicCharset=FirstG0; + } + c.SetFGColor((enumTeletextColor)(ttc-0x10)); + c.SetCharset(SeparateGraphics?CHARSET_GRAPHICS_G1_SEP:CHARSET_GRAPHICS_G1); + GraphicCharset=true; + c.SetConceal(false); + } else if (ttc==0x1B) { + SecondCharset=!SecondCharset; + if (!GraphicCharset) c.SetCharset(SecondCharset?SecondG0:FirstG0); + } else if (ttc==0x1F) { + HoldMosaics=false; + } + + } // end for x + if (renderfirstlineonly) break; + } // end for y + + for (x=0;x<40;x++) { + // Clean out last line + cTeletextChar c; + c.SetFGColor(ttcWhite); + c.SetBGColor(ttcBlack); + c.SetCharset(FirstG0); + c.SetChar(' '); + if (flags&0x60) { + c.SetBoxedOut(true); + } + setChar(x,24,c); + } + for (y=0;y<25;y++) { + for (x=0;x<40;x++) { + if (isDirty(x,y)) { + dirty=true; + break; + } + if (dirty) break; + } + if (dirty) break; + } + + if (dirty && txtview!=NULL ) { + + if ( !renderfirstlineonly) { + Message* m= new Message(); + m->message = Message::TELETEXTUPDATE; + m->to = txtview; + m->from = this; + m->parameter = 0; + Command::getInstance()->postMessageFromOuterSpace(m); + } else if (firstlineupdate==10) { + Message* m= new Message(); + m->message = Message::TELETEXTUPDATEFIRSTLINE; + m->to = txtview; + m->from = this; + m->parameter = 0; + Command::getInstance()->postMessageFromOuterSpace(m); + firstlineupdate=0; + } else firstlineupdate++; + + + } + +} diff --git a/teletextdecodervbiebu.h b/teletextdecodervbiebu.h new file mode 100644 index 0000000..0566a40 --- /dev/null +++ b/teletextdecodervbiebu.h @@ -0,0 +1,330 @@ +/* + Copyright 2008 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +/* Portions from vdr osdteletext plugin "txtrender.c": */ +/*************************************************************************** + * * + * txtrender.h - Teletext display abstraction and teletext code * + * renderer * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * Changelog: * + * 2005-03 initial version (c) Udo Richter * + * * + ***************************************************************************/ + +#ifndef TXTDECVBIEBU_H +#define TXTDECVBIEBU_H + +#include "draintarget.h" +#include "log.h" + +/* from osdteletext begin */ + +// Teletext character sets +enum enumCharsets { + CHARSET_LATIN_G0 = 0x0000, // native latin (partially todo) + CHARSET_LATIN_G0_CZ_SK = 0x0100, // Czech/Slovak (todo) + CHARSET_LATIN_G0_EN = 0x0200, // English + CHARSET_LATIN_G0_EE = 0x0300, // Estonian (todo) + CHARSET_LATIN_G0_FR = 0x0400, // French + CHARSET_LATIN_G0_DE = 0x0500, // German + CHARSET_LATIN_G0_IT = 0x0600, // Italian + CHARSET_LATIN_G0_LV_LT = 0x0700, // Lettish/Lithuanian (todo) + CHARSET_LATIN_G0_PL = 0x0800, // Polish (todo) + CHARSET_LATIN_G0_PT_ES = 0x0900, // Portugese/Spanish + CHARSET_LATIN_G0_RO = 0x0A00, // Romanian (todo) + CHARSET_LATIN_G0_SR_HR_SL = 0x0B00, // Serbian/Croatian/Slovenian (todo) + CHARSET_LATIN_G0_SV_FI = 0x0C00, // Swedish/Finnish + CHARSET_LATIN_G0_TR = 0x0D00, // Turkish (todo) + CHARSET_LATIN_G2 = 0x0E00, // Latin G2 supplementary set (todo) + CHARSET_CYRILLIC_G0_SR_HR = 0x0F00, // Serbian/Croatian (todo) + CHARSET_CYRILLIC_G0_RU_BG = 0x1000, // Russian/Bulgarian (todo) + CHARSET_CYRILLIC_G0_UK = 0x1100, // Ukrainian (todo) + CHARSET_CYRILLIC_G2 = 0x1200, // Cyrillic G2 Supplementary (todo) + CHARSET_GREEK_G0 = 0x1300, // Greek G0 (todo) + CHARSET_GREEK_G2 = 0x1400, // Greeek G2 (todo) + CHARSET_ARABIC_G0 = 0x1500, // Arabic G0 (todo) + CHARSET_ARABIC_G2 = 0x1600, // Arabic G2 (todo) + CHARSET_HEBREW_G0 = 0x1700, // Hebrew G0 (todo) + CHARSET_GRAPHICS_G1 = 0x1800, // G1 graphics set + CHARSET_GRAPHICS_G1_SEP = 0x1900, // G1 graphics set, separated + CHARSET_GRAPHICS_G3 = 0x1A00, // G3 graphics set (todo) + CHARSET_INVALID = 0x1F00 // no charset defined +}; + +// Macro to get the lowest non-0 bit position from a bit mask +// Should evaluate to const on a const mask +#define LowestSet2Bit(mask) ((mask)&0x0001?0:1) +#define LowestSet4Bit(mask) ((mask)&0x0003?LowestSet2Bit(mask):LowestSet2Bit((mask)>>2)+2) +#define LowestSet8Bit(mask) ((mask)&0x000f?LowestSet4Bit(mask):LowestSet4Bit((mask)>>4)+4) +#define LowestSet16Bit(mask) ((mask)&0x00ff?LowestSet8Bit(mask):LowestSet8Bit((mask)>>8)+8) +#define LowestSet32Bit(mask) ((mask)&0xffff?LowestSet16Bit(mask):LowestSet16Bit((mask)>>16)+16) + + +// Character modifcation double height: +enum enumDblHeight { + dblh_Normal=0x00000000, // normal height + dblh_Top =0x04000000, // upper half character + dblh_Bottom=0x08000000 // lower half character +}; +// Character modifcation double width: +enum enumDblWidth { + dblw_Normal=0x00000000, // normal width + dblw_Left =0x10000000, // left half character + dblw_Right =0x20000000 // right half character +}; + +// Teletext colors +enum enumTeletextColor { + // level 1: + ttcBlack=0, + ttcRed=1, + ttcGreen=2, + ttcYellow=3, + ttcBlue=4, + ttcMagenta=5, + ttcCyan=6, + ttcWhite=7, + // level 2.5: + ttcTransparent=8, + ttcHalfRed=9, + ttcHalfGreen=10, + ttcHalfYellow=11, + ttcHalfBlue=12, + ttcHalfMagenta=13, + ttcHalfCyan=14, + ttcGrey=15, + // unnamed, level 2.5: + ttcColor16=16, ttcColor17=17, ttcColor18=18, ttcColor19=19, + ttcColor20=20, ttcColor21=21, ttcColor22=22, ttcColor23=23, + ttcColor24=24, ttcColor25=25, ttcColor26=26, ttcColor27=27, + ttcColor28=28, ttcColor29=29, ttcColor30=30, ttcColor31=31, + + ttcFirst=0, ttcLast=31 +}; +inline enumTeletextColor& operator++(enumTeletextColor& c) { return c=enumTeletextColor(int(c)+1); } +inline enumTeletextColor operator++(enumTeletextColor& c, int) { enumTeletextColor tmp(c); ++c; return tmp; } + +class cTeletextChar { + // Wrapper class that represents a teletext character, + // including colors and effects. Should optimize back + // to 4 byte unsigned int on compile. + +protected: + unsigned int c; + + static const unsigned int CHAR = 0x000000FF; + // character code + static const unsigned int CHARSET = 0x00001F00; + // character set code, see below + static const unsigned int BOXOUT = 0x00004000; + // 'boxed' mode hidden area + static const unsigned int DIRTY = 0x00008000; + // 'dirty' bit - internal marker only + static const unsigned int FGCOLOR = 0x001F0000; + // 5-bit foreground color code, 3 bit used for now + static const unsigned int BGCOLOR = 0x03E00000; + // 5-bit background color code, 3 bit used for now + static const unsigned int DBLHEIGHT = 0x0C000000; + // show double height + static const unsigned int DBLWIDTH = 0x30000000; + // show double width (todo) + static const unsigned int CONCEAL = 0x40000000; + // character concealed + static const unsigned int BLINK = 0x80000000; + // blinking character + + cTeletextChar(unsigned int cc) { c=cc; } + +public: + cTeletextChar() { c=0; } + + // inline helper functions: + // For each parameter encoded into the 32-bit int, there is + // a Get...() to read, a Set...() to write, and a To...() to + // return a modified copy + + inline unsigned char GetChar() + { return c&CHAR; } + inline void SetChar(unsigned char chr) + { c=(c&~CHAR)|chr; } + inline cTeletextChar ToChar(unsigned char chr) + { return cTeletextChar((c&~CHAR)|chr); } + + inline enumCharsets GetCharset() + { return (enumCharsets)(c&CHARSET); } + inline void SetCharset(enumCharsets charset) + { c=(c&~CHARSET)|charset; } + inline cTeletextChar ToCharset(enumCharsets charset) + { return cTeletextChar((c&~CHARSET)|charset); } + + inline enumTeletextColor GetFGColor() + { return (enumTeletextColor)((c&FGCOLOR) >> LowestSet32Bit(FGCOLOR)); } + inline void SetFGColor(enumTeletextColor fgc) + { c=(c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR)); } + inline cTeletextChar ToFGColor(enumTeletextColor fgc) + { return cTeletextChar((c&~FGCOLOR) | (fgc << LowestSet32Bit(FGCOLOR))); } + + inline enumTeletextColor GetBGColor() + { return (enumTeletextColor)((c&BGCOLOR) >> LowestSet32Bit(BGCOLOR)); } + inline void SetBGColor(enumTeletextColor bgc) + { c=(c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR)); } + inline cTeletextChar ToBGColor(enumTeletextColor bgc) + { return cTeletextChar((c&~BGCOLOR) | (bgc << LowestSet32Bit(BGCOLOR))); } + + inline bool GetBoxedOut() + { return c&BOXOUT; } + inline void SetBoxedOut(bool BoxedOut) + { c=(BoxedOut)?(c|BOXOUT):(c&~BOXOUT); } + inline cTeletextChar ToBoxedOut(bool BoxedOut) + { return cTeletextChar((BoxedOut)?(c|BOXOUT):(c&~BOXOUT)); } + + inline bool GetDirty() + { return c&DIRTY; } + inline void SetDirty(bool Dirty) + { c=(Dirty)?(c|DIRTY):(c&~DIRTY); } + inline cTeletextChar ToDirty(bool Dirty) + { return cTeletextChar((Dirty)?(c|DIRTY):(c&~DIRTY)); } + + inline enumDblHeight GetDblHeight() + { return (enumDblHeight)(c&DBLHEIGHT); } + inline void SetDblHeight(enumDblHeight dh) + { c=(c&~(DBLHEIGHT)) | dh; } + inline cTeletextChar ToDblHeight(enumDblHeight dh) + { return cTeletextChar((c&~(DBLHEIGHT)) | dh); } + + inline enumDblWidth GetDblWidth() + { return (enumDblWidth)(c&DBLWIDTH); } + inline void SetDblWidth(enumDblWidth dw) + { c=(c&~(DBLWIDTH)) | dw; } + inline cTeletextChar ToDblWidth(enumDblWidth dw) + { return cTeletextChar((c&~(DBLWIDTH)) | dw); } + + inline bool GetConceal() + { return c&CONCEAL; } + inline void SetConceal(bool Conceal) + { c=(Conceal)?(c|CONCEAL):(c&~CONCEAL); } + inline cTeletextChar ToConceal(bool Conceal) + { return cTeletextChar((Conceal)?(c|CONCEAL):(c&~CONCEAL)); } + + inline bool GetBlink() + { return c&BLINK; } + inline void SetBlink(bool Blink) + { c=(Blink)?(c|BLINK):(c&~BLINK); } + inline cTeletextChar ToBlink(bool Blink) + { return cTeletextChar((Blink)?(c|BLINK):(c&~BLINK)); } + + bool operator==(cTeletextChar &chr) { return c==chr.c; } + bool operator!=(cTeletextChar &chr) { return c!=chr.c; } +}; +/* from osdteletext end*/ + +class VTeletextView; + +/* Decoder of teletext matrial present in Data stream for VBI reinsertion more or less according to EBU specs*/ +class TeletextDecoderVBIEBU: public DrainTarget { +public: + TeletextDecoderVBIEBU(); + virtual ~TeletextDecoderVBIEBU(); + + virtual long long SetStartOffset(long long curreftime, bool *rsync); + virtual void ResetTimeOffsets(); + + void ResetDecoder(); + void setKeyinDigits(char digits[3],bool inKeying); + void setPage(unsigned int newpage); + int getPage() {return selectedpage;}; + void setRecordigMode(bool isrecord) {isrecording=isrecord;}; + int *getSubtitlePages() {return record_pages;}; + + + virtual void PrepareMediaSample(const MediaPacketList& mplist, UINT samplepos); + virtual UINT DeliverMediaSample(const UCHAR* buffer, UINT *samplepos); + + void registerTeletextView(VTeletextView* view) {txtview=view;}; + void unRegisterTeletextView(VTeletextView* view) {if (txtview==view) txtview=NULL;}; + VTeletextView* getTeletxtView() {return txtview;}; + + cTeletextChar getChar(int x, int y) { + // Read character content from page + if (x<0 || x>=40 || y<0 || y>=25) { + Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds read access to teletext page"); + return cTeletextChar(); + } + return Page[x][y].ToDirty(false); + } + bool isDirty(int x, int y) { + if (x<0 || x>=40 || y<0 || y>=25) { + Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds dirty access to teletext page"); + return false; + } + return Page[x][y].GetDirty(); + } + void setChar(int x, int y, cTeletextChar c) { + // Set character at given location + + if (x<0 || x>=40 || y<0 || y>=25) { + Log::getInstance()->log("TeletextDecoderVBIEBU", Log::DEBUG, "Warning: out of bounds write access to teletext page"); + return; + } + if (getChar(x,y) != c) { + Page[x][y]=c.ToDirty(true); + dirty=true; + } + } + + +protected: + void DecodeTeletext(const UCHAR* buffer, unsigned int field); + void RenderTeletextCode(bool renderfirstlineonly); + void CleanPage(); + + int selectedpage; + int lang; + int flags; + UCHAR curpage[25][40]; //Line DataCache + cTeletextChar Page[40][25]; + char keyindigits[3]; + + + // Font Code pages + int FirstG0CodePage; // 7-bit number, lower 3 bits ignored + int SecondG0CodePage; // 7-bit number + + bool ourpage; + bool dirty; + bool gotcha; + bool inkeying; + bool isrecording; + int record_pages[10];//Only 10 Pages per record; + unsigned int firstlineupdate; + VTeletextView *txtview; +private: + MediaPacket mediapacket; + + + +}; + +#endif diff --git a/teletxt/COPYING b/teletxt/COPYING new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/teletxt/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/teletxt/README b/teletxt/README new file mode 100644 index 0000000..865dc52 --- /dev/null +++ b/teletxt/README @@ -0,0 +1,98 @@ +This is a "plugin" for the Video Disk Recorder (VDR). + +Written by: Marcel Wiesweg + +Project's homepage: http://www.wiesweg-online.de/linux/vdr + +Latest version available at: http://www.wiesweg-online.de/linux/vdr + +See the file COPYING for license information. + +Description: + +Osd-Teletext displays the teletext directly on the OSD. +Both sound and video are played in the background. + + +Keys: + 1,...,9: insert page number + Up: page+ + Down: page- + Right: sub page+ + Left: sub page- + Back: close teletext plugin + + All other user interaction ("Actions") is configurably assigned to the other + available keys. + You can e.g. configure that you jump to page 100 when you press Red. + In this example, the Action "Jump to 100" is assigned to key "Red". + Have a look at the plugin's setup page to learn the current assignment + and adapt it to your needs. + + Available Keys: Blue, Red, Yellow, Green, Play, Stop, FastFwd, FastRwd + Actions: "Zoom", "Half page", "Switch channel", "Switch background", + "Jump to..." a specific page. + + Description of the actions: + Zoom: Zoom to upper half/lower half/back to full page + Half Page: Reduce OSD window to the lower half of the screen and display upper half/lower half/back to full size + Switch channel:Show pages of a channel different from the one currently tuned to. + This does _not_ include any tuning or channel switching with vdr's core. + You must have tuned to the channel chosen some time before so that the pages have been stored on disk. + When you press the key associated with that action, you are asked for the channel number. + Press OK after you entered it with the number keys. + Jump to...: Jumps to the page you configure. + Switch background: Changes the in the setup configurable background color immediately + to black and back to your degree of transparency. + + How to configure the key bindings: + In the plugins setup menu, you can assign one of actions to each key. + You can choose freely which actions you need, you are not forced to assign + an action to a key at all if you do not need it. + If you select "Jump to...", specify the page number in the line immediately below. + + +Other Setup options: + Background transparency: + number between 0 (transparent) and 255 (black). Default is 127 (also used by VDR) + Show Clock: Toggles whether an additional clock is drawn approximately every second. + The clock shows the current system time, not any time broadcast via teletext. + Let VDR set the system time from a transponder to have the exact time. + Auto-update pages: + Continuously checks whether a page has changed and updates it if yes. + OSD width, OSD height: + Adjusts the width and height of the OSD independent from VDR's settings. + The valid range is 40 to 56 for the width and 12 to 21 for the height. + Minimum user inactivity: + Sets a timeout (in minutes) for user inactivity. When this timespan has elapsed + and the user did not press any keys, the plugin will be closed. Set to 0 to disable this. + Note that disabling timeout will also effectively disable VDR's auto-shutdown feature + as long as the plugin is active. + Key bindings: See above. + +Command line options: + A few settings are given on the command line rather than in the setup menu. + Available options: + + -d --directory=DIR The directory where the temporary + files will be stored. + (standard value: /vtx, recommended: /tmp/vtx + or /var/cache/vdr/osdteletext.) + Ensure that the directory exists and is writable. + -n --max-cache=NUM Maximum size in megabytes of cache used + to store the pages on the harddisk. + (standard value: a calculated value below 50 MB) + -s --cache-system=SYS Set the cache system to be used. + Choose "legacy" for the traditional + one-file-per-page system. + Default is "packed" for the + one-file-for-a-few-pages system. + +Colors: + On all sorts of output devices which are not limited as to color depth + the original teletext colors will be displayed. (Only difference: Cyan is used instead of + white to make reading easier). + On the classic full-featured DVB card and other limited devices, the colors will be reduced to four. + The mapping is currently optimized for German ARD, ZDF and RTL. If you are for some reason + really and definitely not satisfied with my choices, edit colormapping.h and recompile. + diff --git a/teletxt/tables.h b/teletxt/tables.h new file mode 100644 index 0000000..08fe344 --- /dev/null +++ b/teletxt/tables.h @@ -0,0 +1,112 @@ +/* This file is copied from Ralph Metzler's vbidecode package. */ + +/* + tables.h - some data conversion tables for vbidecode +*/ + +#ifndef _TABLES_H +#define _TABLES_H + +unsigned char invtab[256] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +unsigned char unhamtab[256] = { + 0x01, 0xff, 0x81, 0x01, 0xff, 0x00, 0x01, 0xff, + 0xff, 0x02, 0x01, 0xff, 0x0a, 0xff, 0xff, 0x07, + 0xff, 0x00, 0x01, 0xff, 0x00, 0x80, 0xff, 0x00, + 0x06, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x03, 0xff, + 0xff, 0x0c, 0x01, 0xff, 0x04, 0xff, 0xff, 0x07, + 0x06, 0xff, 0xff, 0x07, 0xff, 0x07, 0x07, 0x87, + 0x06, 0xff, 0xff, 0x05, 0xff, 0x00, 0x0d, 0xff, + 0x86, 0x06, 0x06, 0xff, 0x06, 0xff, 0xff, 0x07, + 0xff, 0x02, 0x01, 0xff, 0x04, 0xff, 0xff, 0x09, + 0x02, 0x82, 0xff, 0x02, 0xff, 0x02, 0x03, 0xff, + 0x08, 0xff, 0xff, 0x05, 0xff, 0x00, 0x03, 0xff, + 0xff, 0x02, 0x03, 0xff, 0x03, 0xff, 0x83, 0x03, + 0x04, 0xff, 0xff, 0x05, 0x84, 0x04, 0x04, 0xff, + 0xff, 0x02, 0x0f, 0xff, 0x04, 0xff, 0xff, 0x07, + 0xff, 0x05, 0x05, 0x85, 0x04, 0xff, 0xff, 0x05, + 0x06, 0xff, 0xff, 0x05, 0xff, 0x0e, 0x03, 0xff, + 0xff, 0x0c, 0x01, 0xff, 0x0a, 0xff, 0xff, 0x09, + 0x0a, 0xff, 0xff, 0x0b, 0x8a, 0x0a, 0x0a, 0xff, + 0x08, 0xff, 0xff, 0x0b, 0xff, 0x00, 0x0d, 0xff, + 0xff, 0x0b, 0x0b, 0x8b, 0x0a, 0xff, 0xff, 0x0b, + 0x0c, 0x8c, 0xff, 0x0c, 0xff, 0x0c, 0x0d, 0xff, + 0xff, 0x0c, 0x0f, 0xff, 0x0a, 0xff, 0xff, 0x07, + 0xff, 0x0c, 0x0d, 0xff, 0x0d, 0xff, 0x8d, 0x0d, + 0x06, 0xff, 0xff, 0x0b, 0xff, 0x0e, 0x0d, 0xff, + 0x08, 0xff, 0xff, 0x09, 0xff, 0x09, 0x09, 0x89, + 0xff, 0x02, 0x0f, 0xff, 0x0a, 0xff, 0xff, 0x09, + 0x88, 0x08, 0x08, 0xff, 0x08, 0xff, 0xff, 0x09, + 0x08, 0xff, 0xff, 0x0b, 0xff, 0x0e, 0x03, 0xff, + 0xff, 0x0c, 0x0f, 0xff, 0x04, 0xff, 0xff, 0x09, + 0x0f, 0xff, 0x8f, 0x0f, 0xff, 0x0e, 0x0f, 0xff, + 0x08, 0xff, 0xff, 0x05, 0xff, 0x0e, 0x0d, 0xff, + 0xff, 0x0e, 0x0f, 0xff, 0x0e, 0x8e, 0xff, 0x0e, +}; + +unsigned char cct2vtx_table[] = + { 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, + + 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, + 0x3c, 0x3d, 0x3e, 0xef, + + 0x40, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, + 0x4c, 0x4d, 0x4e, 0x4f, + + 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, + 0x5c, 0x5d, 0x5e, 0x5f, + + 0x60, 0x61, 0x62, 0x63, + 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, + 0x6c, 0x6d, 0x6e, 0x6f, + + 0x70, 0x71, 0x72, 0x73, + 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, + 0x7c, 0x7d, 0x7e, 0x7f + }; + +#endif diff --git a/teletxt/txtfont.cc b/teletxt/txtfont.cc new file mode 100644 index 0000000..438ff7d --- /dev/null +++ b/teletxt/txtfont.cc @@ -0,0 +1,3371 @@ +#include "txtfont.h" + +unsigned int TXT_Mask[11]= { + 0x0000, // ************ **** + 0x39C0, // **###**###** **** + 0x39C0, // **###**###** **** + 0x0000, // ************ **** + 0x39C0, // **###**###** **** + 0x39C0, // **###**###** **** + 0x0000, // ************ **** + 0x39C0, // **###**###** **** + 0x39C0, // **###**###** **** + 0x0000 // ************ **** + }; + +unsigned int TXT_Font[][11]= { + { // 0x20 = Leerzeichen + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x21 = ! + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x22 = " + 0x0000, // ************ **** + 0x39C0, // **###**###** **** + 0x18C0, // ***##***##** **** + 0x3180, // **##***##*** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x23 = # = NC + 0x0000, // ************ **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x0000 // ************ **** + }, + { // 0x24 = $ = NC + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x6660, // *##**##**##* **** + 0x6600, // *##**##***** **** + 0x3FC0, // **########** **** + 0x0660, // *****##**##* **** + 0x6660, // *##**##**##* **** + 0x3FC0, // **########** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + }, + { // 0x25 = % + 0x0000, // ************ **** + 0x70C0, // *###****##** **** + 0xD980, // ##*##**##*** **** + 0x7300, // *###**##**** **** + 0x0600, // *****##***** **** + 0x0CE0, // ****##**###* **** + 0x19B0, // ***##**##*## **** + 0x30E0, // **##****###* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x26 = & + 0x0000, // ************ **** + 0x1E00, // ***####***** **** + 0x3300, // **##**##**** **** + 0x3300, // **##**##**** **** + 0x1E00, // ***####***** **** + 0x3330, // **##**##**## **** + 0x61C0, // *##****###** **** + 0x3F30, // **######**## **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x27 = ' + 0x0000, // ************ **** + 0x0700, // *****###**** **** + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x28 = ( + 0x0000, // ************ **** + 0x0700, // *****###**** **** + 0x0C00, // ****##****** **** + 0x1800, // ***##******* **** + 0x1800, // ***##******* **** + 0x1800, // ***##******* **** + 0x0C00, // ****##****** **** + 0x0700, // *****###**** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x29 = ) + 0x0000, // ************ **** + 0x0E00, // ****###***** **** + 0x0300, // ******##**** **** + 0x0180, // *******##*** **** + 0x0180, // *******##*** **** + 0x0180, // *******##*** **** + 0x0300, // ******##**** **** + 0x0E00, // ****###***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x2A = * + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x6660, // *##**##**##* **** + 0x36C0, // **##*##*##** **** + 0x0F00, // ****####**** **** + 0x36C0, // **##*##*##** **** + 0x6660, // *##**##**##* **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x2B = + + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x2C = , + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x3800, // **###******* **** + 0x1800, // ***##******* **** + 0x3000, // **##******** **** + }, + { // 0x2D = - + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x2E = . + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x1800, // ***##******* **** + 0x1800, // ***##******* **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x2F = / + 0x0000, // ************ **** + 0x00C0, // ********##** **** + 0x0180, // *******##*** **** + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0C00, // ****##****** **** + 0x1800, // ***##******* **** + 0x3000, // **##******** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + + { // 0x30 = 0 + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x38E0, // **###***###* **** + 0x38E0, // **###***###* **** + 0x38E0, // **###***###* **** + 0x38E0, // **###***###* **** + 0x38E0, // **###***###* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x31 = 1 + 0x0000, // ************ **** + 0x0700, // *****###**** **** + 0x1F00, // ***#####**** **** + 0x0700, // *****###**** **** + 0x0700, // *****###**** **** + 0x0700, // *****###**** **** + 0x0700, // *****###**** **** + 0x0700, // *****###**** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x32 = 2 + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x30E0, // **##****###* **** + 0x00E0, // ********###* **** + 0x01C0, // *******###** **** + 0x0780, // *****####*** **** + 0x1E00, // ***####***** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x33 = 3 + 0x0000, // ************ **** + 0x3FE0, // **#########* **** + 0x00C0, // ********##** **** + 0x0080, // *******##*** **** + 0x07E0, // *****######* **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x34 = 4 + 0x0000, // ************ **** + 0x00E0, // ********###* **** + 0x03C0, // ******####** **** + 0x0700, // *****###**** **** + 0x1C00, // ***###****** **** + 0x38E0, // **###***###* **** + 0x3FE0, // **#########* **** + 0x00E0, // ********###* **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x35 = 5 + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3FC0, // **########** **** + 0x00E0, // ********###* **** + 0x30E0, // **##****###* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x36 = 6 + 0x0000, // ************ **** + 0x0700, // *****###**** **** + 0x0E00, // ****###***** **** + 0x1C00, // ***###****** **** + 0x3FC0, // **########** **** + 0x3860, // **###****##* **** + 0x3860, // **###****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x37 = 7 + 0x0000, // ************ **** + 0x7FE0, // *##########* **** + 0x01C0, // *******###** **** + 0x0380, // ******###*** **** + 0x0700, // *****###**** **** + 0x0E00, // ****###***** **** + 0x1C00, // ***###****** **** + 0x3800, // **###******* **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x38 = 8 + 0x0000, // ************ **** + 0x0F80, // ****#####*** **** + 0x38E0, // **###***###* **** + 0x38E0, // **###***###* **** + 0x0F80, // ****#####*** **** + 0x38E0, // **###***###* **** + 0x38E0, // **###***###* **** + 0x0F80, // ****#####*** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x39 = 9 + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x30E0, // **##****###* **** + 0x30E0, // **##****###* **** + 0x1FC0, // ***#######** **** + 0x0380, // ******###*** **** + 0x0700, // *****###**** **** + 0x0E00, // ****###***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x3A = : + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x0000, // ************ **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x3B = ; + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x1800, // ***##******* **** + }, + { // 0x3C = < + 0x0000, // ************ **** + 0x00E0, // ********###* **** + 0x0380, // ******###*** **** + 0x0E00, // ****###***** **** + 0x3800, // **###******* **** + 0x0E00, // ****###***** **** + 0x0380, // ******###*** **** + 0x00E0, // ********###* **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x3D = = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x3E = > + 0x0000, // ************ **** + 0x7000, // *###******** **** + 0x1C00, // ***###****** **** + 0x0700, // *****###**** **** + 0x01C0, // *******###** **** + 0x0700, // *****###**** **** + 0x1C00, // ***###****** **** + 0x7000, // *###******** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + { // 0x3F = ? + 0x0000, // ************ **** + 0x1F80, // ***######*** **** + 0x30C0, // **##****##** **** + 0x30C0, // **##****##** **** + 0x0180, // *******##*** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + }, + + { // 0x40 = § = NC + 0x0000, // ************ **** + 0x1F80, // ***######*** **** + 0x30C0, // **##****##** **** + 0x3000, // **##******** **** + 0x1F80, // ***######*** **** + 0x30C0, // **##****##** **** + 0x1F80, // ***######*** **** + 0x00C0, // ********##** **** + 0x30C0, // **##****##** **** + 0x1F80 // ***######*** **** + }, + { // 0x41 = A + 0x0000, // ************ **** + 0x0F00, // ****####**** **** + 0x1980, // ***##**##*** **** + 0x30C0, // **##****##** **** + 0x6060, // *##******##* **** + 0x7FE0, // *##########* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x42 = B + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FC0, // **########** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x43 = C + 0x0000, // ************ **** + 0x0FC0, // ****######** **** + 0x1860, // ***##****##* **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x1860, // ***##****##* **** + 0x0FC0, // ****######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x44 = D + 0x0000, // ************ **** + 0x3F80, // **#######*** **** + 0x30C0, // **##****##** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30C0, // **##****##** **** + 0x3F80, // **#######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x45 = E + 0x0000, // ************ **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3F80, // **#######*** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x46 = F + 0x0000, // ************ **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3F80, // **#######*** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x47 = G + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x33E0, // **##**#####* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x48 = H + 0x0000, // ************ **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x7FE0, // *##########* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x49 = I + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x4A = J + 0x0000, // ************ **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x4B = K + 0x0000, // ************ **** + 0x30E0, // **##****###* **** + 0x3180, // **##***##*** **** + 0x3700, // **##*###**** **** + 0x3C00, // **####****** **** + 0x3700, // **##*###**** **** + 0x3180, // **##***##*** **** + 0x30E0, // **##****###* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x4C = L + 0x0000, // ************ **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x4D = M + 0x0000, // ************ **** + 0x70E0, // *###****###* **** + 0x79E0, // *####**####* **** + 0x6F60, // *##*####*##* **** + 0x6660, // *##**##**##* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x4E = N + 0x0000, // ************ **** + 0x7060, // *###*****##* **** + 0x7860, // *####****##* **** + 0x6C60, // *##*##***##* **** + 0x6660, // *##**##**##* **** + 0x6360, // *##***##*##* **** + 0x61E0, // *##****####* **** + 0x60E0, // *##*****###* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x4F = O + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + + { // 0x50 = P + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FC0, // **########** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x51 = Q + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3360, // **##**##*##* **** + 0x1FC0, // ***#######** **** + 0x0180, // *******##*** **** + 0x00E0 // ********###* **** + }, + { // 0x52 = R + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FC0, // **########** **** + 0x3300, // **##**##**** **** + 0x31C0, // **##***###** **** + 0x30E0, // **##****###* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x53 = S + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x54 = T + 0x0000, // ************ **** + 0x7FE0, // *##########* **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x55 = U + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x56 = V + 0x0000, // ************ **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x30C0, // **##****##** **** + 0x30C0, // **##****##** **** + 0x1980, // ***##**##*** **** + 0x0F00, // ****####**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x57 = W + 0x0000, // ************ **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x6660, // *##**##**##* **** + 0x6660, // *##**##**##* **** + 0x6F60, // *##*####*##* **** + 0x39C0, // **###**###** **** + 0x30C0, // **##****##** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x58 = X + 0x0000, // ************ **** + 0x30C0, // **##****##** **** + 0x1980, // ***##**##*** **** + 0x0F00, // ****####**** **** + 0x0600, // *****##***** **** + 0x0F00, // ****####**** **** + 0x1980, // ***##**##*** **** + 0x30C0, // **##****##** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x59 = Y + 0x0000, // ************ **** + 0x6060, // *##******##* **** + 0x30C0, // **##****##** **** + 0x1980, // ***##**##*** **** + 0x0F00, // ****####**** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x5A = Z + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x0180, // *******##*** **** + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0C00, // ****##****** **** + 0x1800, // ***##******* **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x5B = Ä = NC + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x5C = Ö = NC + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x5D = Ü = NC + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x5E = ^ = NC + 0x0600, // *****##***** **** + 0x0F00, // ****####**** **** + 0x1980, // ***##**##*** **** + 0x30C0, // **##****##** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x5F = _ = NC + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x7FE0 // *##########* **** + }, + + { // 0x60 = ° = NC + 0x0000, // ************ **** + 0x0000, // *****####*** **** + 0x0000, // ****##**##** **** + 0x0000, // *****####*** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x61 = a + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x62 = b + 0x0000, // ************ **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x37C0, // **##*#####** **** + 0x3860, // **###****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x63 = c + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0FE0, // ****#######* **** + 0x1800, // ***##******* **** + 0x3000, // **##******** **** + 0x1800, // ***##******* **** + 0x0FE0, // ****#######* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x64 = d + 0x0000, // ************ **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x1F60, // ***#####*##* **** + 0x30E0, // **##****###* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FE0, // ***########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x65 = e + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x66 = f + 0x0000, // ************ **** + 0x07E0, // *****######* **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x3F80, // **#######*** **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x67 = g + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x1F60, // ***#####*##* **** + 0x30E0, // **##****###* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0060, // *********##* **** + 0x1FC0 // ***#######** **** + }, + { // 0x68 = h + 0x0000, // ************ **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x37C0, // **##*#####** **** + 0x3860, // **###****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x69 = i + 0x0000, // ************ **** + 0x0E00, // ****###***** **** + 0x0000, // ************ **** + 0x0E00, // ****###***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x1F80, // ***######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x6A = j + 0x0000, // ************ **** + 0x00E0, // ********###* **** + 0x0000, // ************ **** + 0x01E0, // *******####* **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x0060, // *********##* **** + 0x3060, // **##*****##* **** + 0x1FC0 // ***#######** **** + }, + { // 0x6B = k + 0x0000, // ************ **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x30E0, // **##****###* **** + 0x3180, // **##***##*** **** + 0x3E00, // **#####***** **** + 0x3180, // **##***##*** **** + 0x30E0, // **##****###* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x6C = l + 0x0000, // ************ **** + 0x1E00, // ***####***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x6D = m + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x6DC0, // *##*##*###** **** + 0x6660, // *##**##**##* **** + 0x6660, // *##**##**##* **** + 0x6660, // *##**##**##* **** + 0x6660, // *##**##**##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x6E = n + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x37C0, // **##*#####** **** + 0x3860, // **###****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x6F = o + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + + { // 0x70 = p + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x37C0, // **##*#####** **** + 0x3860, // **###****##* **** + 0x3060, // **##*****##* **** + 0x3860, // **###****##* **** + 0x37C0, // **##*#####** **** + 0x3000, // **##******** **** + 0x3000 // **##******** **** + }, + { // 0x71 = q + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x1EC0, // ***####*##** **** + 0x31C0, // **##***###** **** + 0x30C0, // **##****##** **** + 0x31C0, // **##***###** **** + 0x1EC0, // ***####*##** **** + 0x00C0, // ********##** **** + 0x01E0 // *******####* **** + }, + { // 0x72 = r + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x33E0, // **##**#####* **** + 0x3C00, // **####****** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x73 = s + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0060, // *********##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x74 = t + 0x0000, // ************ **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x3F80, // **#######*** **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x0C00, // ****##****** **** + 0x07E0, // *****######* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x75 = u + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x76 = v + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x6060, // *##******##* **** + 0x30C0, // **##****##** **** + 0x1980, // ***##**##*** **** + 0x0F00, // ****####**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x77 = w + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x6060, // *##******##* **** + 0x6660, // *##**##**##* **** + 0x6660, // *##**##**##* **** + 0x36C0, // **##*##*##** **** + 0x2980, // ***##**##*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x78 = x + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x70E0, // *###****###* **** + 0x1980, // ***##**##*** **** + 0x0F00, // ****####**** **** + 0x1980, // ***##**##*** **** + 0x70E0, // *###****###* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x79 = y + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x18C0, // ***##***##** **** + 0x0D80, // ****##*##*** **** + 0x0700, // *****###**** **** + 0x0600, // *****##***** **** + 0x0C00, // ****##****** **** + 0x3800 // **###******* **** + }, + { // 0x7A = z + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x3FE0, // **#########* **** + 0x0180, // *******##*** **** + 0x0700, // *****###**** **** + 0x0C00, // ****##****** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x7B = ä = NC + 0x0000, // ************ **** + 0x3180, // **##***##*** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x7C = ö = NC + 0x0000, // ************ **** + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x7D = ü = NC + 0x0000, // ************ **** + 0x10C0, // ***##***##** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x7E = ß = NC + 0x0000, // ************ **** + 0x0F80, // ****#####*** **** + 0x18C0, // ***##***##** **** + 0x30C0, // **##****##** **** + 0x3380, // **##**###*** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x33C0, // **##**####** **** + 0x3000, // **##******** **** + 0x3000 // **##******** **** + }, + { // 0x7F = Block + 0x0000, // ************ **** + 0x7FE0, // *##########* **** + 0x7FE0, // *##########* **** + 0x7FE0, // *##########* **** + 0x7FE0, // *##########* **** + 0x7FE0, // *##########* **** + 0x7FE0, // *##########* **** + 0x7FE0, // *##########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + + { // 0x80 = + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x63E0, // *##***#####* **** + 0x6660, // *##**##**##* **** + 0x6660, // *##**##**##* **** + 0x63E0, // *##***#####* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000 // ************ **** + }, + { // 0x81 = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x82 = + 0x0000, // ************ **** + 0x3000, // **##******** **** + 0x7000, // *###******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3180, // **##***##*** **** + 0x0300, // ******##**** **** + 0x0660, // *****##**##* **** + 0x07E0, // *****######* **** + 0x0060 // *********##* **** + }, + { // 0x83 = + 0x0000, // ************ **** + 0x0FC0, // ****######** **** + 0x1860, // ***##****##* **** + 0x0C00, // ****##****** **** + 0x3F00, // **######**** **** + 0x0C00, // ****##****** **** + 0x3E60, // **#####**##* **** + 0x33C0, // **##**####** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x84 = + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x6660, // *##**##**##* **** + 0x6600, // *##**##***** **** + 0x3FC0, // **########** **** + 0x0660, // *****##**##* **** + 0x6660, // *##**##**##* **** + 0x3FC0, // **########** **** + 0x0600, // *****##***** **** + 0x0000 // ************ **** + }, + { // 0x85 = + 0x07F0, // *****####### **** + 0x0C00, // ****##****** **** + 0x19F0, // ***##**##### **** + 0x1800, // ***##******* **** + 0x19F0, // ***##**##### **** + 0x1800, // ***##******* **** + 0x19F0, // ***##**##### **** + 0x0C00, // ****##****** **** + 0x07F0, // *****####### **** + 0x0000 // ************ **** + }, + { // 0x86 = + 0xFFC0, // ##########** **** + 0x1C60, // ***###***##* **** + 0x0830, // ****#*****## **** + 0x7F30, // *#######**## **** + 0x4130, // *#*****#**## **** + 0x7F30, // *#######**## **** + 0x0830, // ****#*****## **** + 0x1C60, // ***###***##* **** + 0xFFC0, // ##########** **** + 0x0000 // ************ **** + }, + { // 0x87 = + 0xFFC0, // ##########** **** + 0x0060, // *********##* **** + 0x3E30, // **#####***## **** + 0x6330, // *##***##**## **** + 0x0E30, // ****###***## **** + 0x1830, // ***##*****## **** + 0x1830, // ***##*****## **** + 0x0060, // *********##* **** + 0xFFC0, // ##########** **** + 0x0000 // ************ **** + }, + { // 0x88 = + 0x0000, // ************ **** + 0x3980, // ***##**##*** **** + 0x3980, // ***##**##*** **** + 0x3980, // ***##**##*** **** + 0x3980, // ***##**##*** **** + 0x3980, // ***##**##*** **** + 0x3980, // ***##**##*** **** + 0x3980, // ***##**##*** **** + 0x3980, // ***##**##*** **** + 0x0000 // ************ **** + }, + { // 0x89 = + 0x0000, // ************ **** + 0x7C00, // *#####****** **** + 0x0C00, // ****##****** **** + 0x3800, // **###******* **** + 0x0C00, // ****##****** **** + 0x7980, // *####**##*** **** + 0x0300, // ******##**** **** + 0x0660, // *****##**##* **** + 0x07E0, // *****######* **** + 0x0060 // *********##* **** + }, + { // 0x8A = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x8B = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x1C00, // ***###****** **** + 0x7FF0, // *########### **** + 0x1C00, // ***###****** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x8C = + 0x0000, // ************ **** + 0x3000, // **##******** **** + 0x7000, // *###******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x33C0, // **##**####** **** + 0x0660, // *****##**##* **** + 0x00C0, // ********##** **** + 0x0300, // ******##**** **** + 0x07E0 // *****######* **** + }, + { // 0x8D = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0380, // ******###*** **** + 0xFFE0, // ###########* **** + 0x0380, // ******###*** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x8E = + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0F00, // ****####**** **** + 0x1F80, // ***######*** **** + 0x36C0, // **##*##*##** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600 // *****##***** **** + }, + { // 0x8F = + 0x0000, // ************ **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x0000 // ************ **** + }, + + { // 0x90 = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x3000, // **##******** **** + 0x3F80, // **#######*** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x91 = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x92 = + 0x0000, // ************ **** + 0x3180, // **##***##*** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x93 = + 0x0000, // ************ **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x0000 // ************ **** + }, + { // 0x94 = + 0x0000, // ************ **** + 0x6060, // *##******##* **** + 0x30C0, // **##****##** **** + 0x1F80, // ***######*** **** + 0x30C0, // **##****##** **** + 0x30C0, // **##****##** **** + 0x1F80, // ***######*** **** + 0x30C0, // **##****##** **** + 0x6060, // *##******##* **** + 0x0000 // ************ **** + }, + { // 0x95 = + 0xFFC0, // ##########** **** + 0x0060, // *********##* **** + 0xFF30, // ########**## **** + 0x0030, // **********## **** + 0xFF30, // ########**## **** + 0x0030, // **********## **** + 0xFF30, // ########**## **** + 0x0060, // *********##* **** + 0xFFC0, // ##########** **** + 0x0000 // ************ **** + }, + { // 0x96 = + 0xFFC0, // ##########** **** + 0x0060, // *********##* **** + 0x3E30, // **#####***## **** + 0x4730, // *#***###**## **** + 0x4730, // *#***###**## **** + 0x7F30, // *#######**## **** + 0x3E30, // **#####***## **** + 0x0060, // *********##* **** + 0xFFC0, // ##########** **** + 0x0000 // ************ **** + }, + { // 0x97 = + 0xFFC0, // ##########** **** + 0x0860, // ****#****##* **** + 0x1C30, // ***###****## **** + 0x0030, // **********## **** + 0x7F30, // *#######**## **** + 0x0030, // **********## **** + 0x1C30, // ***###****## **** + 0x0860, // ****#****##* **** + 0xFFC0, // ##########** **** + 0x0000 // ************ **** + }, + { // 0x98 = + 0x0000, // ************ **** + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x99 = + 0x0E00, // ****###***** **** + 0x1B00, // ***##*##**** **** + 0x0E00, // ****###***** **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x9A = + 0x0000, // ************ **** + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x9B = + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x9C = + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x9D = + 0x0700, // *****###**** **** + 0x0700, // *****###**** **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x9E = + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0x9F = _ + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x7FE0 // *##########* **** + }, + + + { // 0xA0 = 0x20a + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA1 = 0x21a + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA2 = 0x22a + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA3 = 0x23a + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA4 = 0x24a + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA5 = 0x25a + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA6 = 0x26a + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA7 = 0x27a + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA8 = 0x28a + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xA9 = 0x29a + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xAA = 0x2Aa + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xAB = 0x2Ba + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xAC = 0x2Ca + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xAD = 0x2Da + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xAE = 0x2Ea + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xAF = 0x2Fa + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + + { // 0xB0 = 0x30a + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB1 = 0x31a + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB2 = 0x32a + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB3 = 0x33a + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB4 = 0x34a + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB5 = 0x35a + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB6 = 0x36a + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB7 = 0x37a + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB8 = 0x38a + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xB9 = 0x39a + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xBA = 0x3Aa + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xBB = 0x3Ba + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xBC = 0x3Ca + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xBD = 0x3Da + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xBE = 0x3Ea + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + { // 0xBF = 0x3Fa + 0xFFFF, // ############ **** + 0xFFFF, // ############ **** + 0xFFFF, // ############ **** + 0xFFFF, // ############ **** + 0xFFFF, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00 // ######****** **** + }, + + { // 0xC0 = + 0x0600, // *****##***** **** + 0x0C00, // ****##****** **** + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x6060, // *##******##* **** + 0x7FE0, // *##########* **** + 0x6000, // *##********* **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xC1 = + 0x0600, // *****##***** **** + 0x0300, // ******##**** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000 // ************ **** + }, + { // 0xC2 = + 0x0C00, // ****##****** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xC3 = + 0x0000, // ************ **** + 0x0FC0, // ****######** **** + 0x1860, // ***##****##* **** + 0x0C00, // ****##****** **** + 0x3F00, // **######**** **** + 0x0C00, // ****##****** **** + 0x3E60, // **#####**##* **** + 0x33C0, // **##**####** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xC4 = + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x6660, // *##**##**##* **** + 0x6600, // *##**##***** **** + 0x3FC0, // **########** **** + 0x0660, // *****##**##* **** + 0x6660, // *##**##**##* **** + 0x3F60, // **########** **** + 0x06C0, // *****##***** **** + 0x0000 // ************ **** + }, + { // 0xC5 = + 0x3CC0, // **####**##** **** + 0x6780, // *##**####*** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xC6 = + 0x3C60, // **####***##* **** + 0x67C0, // *##**#####** **** + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xC7 = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xC8 = + 0x0600, // *****##***** **** + 0x0300, // ******##**** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xC9 = + 0x0600, // *****##***** **** + 0x0300, // ******##**** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xCA = + 0x0C00, // ****##****** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0E00, // ****###***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x1F80, // ***######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xCB = + 0x0000, // ************ **** + 0x0780, // *****####*** **** + 0x0CC0, // ****##**##** **** + 0x0780, // *****####*** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xCC = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0FE0, // ****#######* **** + 0x1800, // ***##******* **** + 0x3000, // **##******** **** + 0x1800, // ***##******* **** + 0x0FE0, // ****#######* **** + 0x0300, // ******##**** **** + 0x0E00 // ****###***** **** + }, + { // 0xCD = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0310, // ******###*** **** + 0xFFE0, // ###########* **** + 0x0310, // ******###*** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xCE = + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0F00, // ****####**** **** + 0x1F80, // ***######*** **** + 0x36C0, // **##*##*##** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600 // *****##***** **** + }, + { // 0xCF = + 0x0000, // ************ **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x0000 // ************ **** + }, + + { // 0xD0 = + 0x0C00, // ****##****** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD1 = + 0x0600, // *****##***** **** + 0x0300, // ******##**** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD2 = + 0x0E00, // ****###***** **** + 0x1B00, // ***##*##**** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD3 = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD4 = + 0x0000, // ************ **** + 0x1980, // ***##**##*** **** + 0x0000, // ************ **** + 0x0E00, // ****###***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x1F80, // ***######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD5 = + 0x1E60, // ***####**##* **** + 0x33C0, // **##**####** **** + 0x1F80, // ***######*** **** + 0x30C0, // **##****##** **** + 0x6060, // *##******##* **** + 0x7FE0, // *##########* **** + 0x6060, // *##******##* **** + 0x6060, // *##******##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD6 = + 0x1E60, // ***####**##* **** + 0x33C0, // **##**####** **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD7 = + 0x0000, // ************ **** + 0x0FC0, // ****######** **** + 0x1860, // ***##****##* **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x1860, // ***##****##* **** + 0x0FC0, // ****######** **** + 0x0300, // ******##**** **** + 0x0E00 // ****###***** **** + }, + { // 0xD8 = + 0x0700, // *****###**** **** + 0x0D80, // ****##*##*** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xD9 = + 0x0700, // *****###**** **** + 0x0D80, // ****##*##*** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xDA = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0FE0, // ****#######* **** + 0x1800, // ***##******* **** + 0x3000, // **##******** **** + 0x1800, // ***##******* **** + 0x0FE0, // ****#######* **** + 0x0300, // ******##**** **** + 0x0E00 // ****###***** **** + }, + { // 0xDB = + 0x0000, // ************ **** + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xDC = + 0x0700, // *****###**** **** + 0x0D80, // ****##*##*** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xDD = + 0x0600, // *****##***** **** + 0x0300, // ******##**** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xDE = + 0x0F00, // ****####**** **** + 0x1980, // ***##**##*** **** + 0x0000, // ************ **** + 0x0E00, // ****###***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x1F80, // ***######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xDF = + 0x0000, // ************ **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x7FE0, // *##########* **** + 0x1980, // ***##**##*** **** + 0x1980, // ***##**##*** **** + 0x0000 // ************ **** + }, + + { // 0xE0 = + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xE1 = + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0600, // *****##***** **** + 0x1800, // ***##******* **** + 0x30C0, // **##****##** **** + 0x30C0, // **##****##** **** + 0x1F00, // ***######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xE2 = + 0x0000, // ************ **** + 0x18C0, // ***##***##** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xE3 = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0FE0, // ****#######* **** + 0x1800, // ***##******* **** + 0x3000, // **##******** **** + 0x1800, // ***##******* **** + 0x0FE0, // ****#######* **** + 0x0300, // ******##**** **** + 0x0E00 // ****###***** **** + }, + { // 0xE4 = + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x6660, // *##**##**##* **** + 0x6600, // *##**##***** **** + 0x3FC0, // **########** **** + 0x0660, // *****##**##* **** + 0x6660, // *##**##**##* **** + 0x3FC0, // **########** **** + 0x0600, // *****##***** **** + 0x0000 // ************ **** + }, + { // 0xE5 = + 0x0000, // ************ **** + 0x3F80, // **#######*** **** + 0x6180, // *##****##*** **** + 0x6180, // *##****##*** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x7FE0, // *##########* **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xE6 = + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xE7 = + 0x1E60, // ***####**##* **** + 0x33C0, // **##**####** **** + 0x3860, // **###****##* **** + 0x3C60, // **####***##* **** + 0x3660, // **##*##**##* **** + 0x3360, // **##**##*##* **** + 0x31E0, // **##***####* **** + 0x30E0, // **##****###* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xE8 = + 0x1E60, // ***####**##* **** + 0x33C0, // **##**####** **** + 0x0000, // ************ **** + 0x37C0, // **##*#####** **** + 0x3860, // **###****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xE9 = + 0x0600, // *****##***** **** + 0x0300, // ******##**** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xEA = + 0x0C00, // ****##****** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xEB = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x7F80, // *########*** **** + 0x00C0, // ********##** **** + 0x3FC0, // **########** **** + 0x60C0, // *##*****##** **** + 0x3FE0, // **#########* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xEC = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3000, // **##******** **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xED = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x0E00, // ****###***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x1F80, // ***######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xEE = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xEF = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x0000, // ************ **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x30E0, // **##****###* **** + 0x1F60, // ***#####*##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + + { // 0xF0 = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF1 = + 0x0C00, // ****##****** **** + 0x0600, // *****##***** **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3FE0, // **#########* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF2 = + 0x0C00, // ****##****** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x3000, // **##******** **** + 0x3F00, // **######**** **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF3 = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF4 = + 0x19C0, // ***##**##*** **** + 0x0000, // ************ **** + 0x3FC0, // **########** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x0600, // *****##***** **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF5 = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF6 = + 0x0600, // *****##***** **** + 0x0300, // ******##**** **** + 0x1FC0, // ***#######** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF7 = + 0x0300, // ******##**** **** + 0x0600, // *****##***** **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x3060, // **##*****##* **** + 0x1FC0, // ***#######** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF8 = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x3DC0, // **####*###** **** + 0x0660, // *****##**##* **** + 0x3FE0, // **#########* **** + 0x6600, // *##**##***** **** + 0x3FC0, // **########** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xF9 = + 0x0000, // ************ **** + 0x0FE0, // ****#######* **** + 0x1B00, // ***##*##**** **** + 0x3300, // **##**##**** **** + 0x7FC0, // *#########** **** + 0x6300, // *##***##**** **** + 0x6300, // *##***##**** **** + 0x63E0, // *##***#####* **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xFA = + 0x0000, // ************ **** + 0x0300, // ******##**** **** + 0x0FC0, // ****######** **** + 0x0180, // *******##*** **** + 0x1FC0, // ***#######** **** + 0x30C0, // **##****##** **** + 0x30C0, // **##****##** **** + 0x1F80, // ***######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xFB = + 0x0000, // ************ **** + 0x3F80, // **#######*** **** + 0x30C0, // **##****##** **** + 0x3060, // **##*****##* **** + 0x7C60, // *#####***##* **** + 0x3060, // **##*****##* **** + 0x30C0, // **##****##** **** + 0x3F80, // **#######*** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + { // 0xFC = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0180, // *******##*** **** + 0x3FC0, // **########** **** + 0x6360, // *##***##*##* **** + 0x6660, // *##**##**##* **** + 0x6C60, // *##*##***##* **** + 0x3FC0, // **########** **** + 0x1800, // ***##******* **** + 0x0000 // ************ **** + }, + { // 0xFD = + 0x0060, // *********##* **** + 0x3FC0, // **########** **** + 0x61E0, // *##****####* **** + 0x6360, // *##***##*##* **** + 0x6660, // *##**##**##* **** + 0x6C60, // *##*##***##* **** + 0x7860, // *####****##* **** + 0x3FC0, // **########** **** + 0x6000, // *##********* **** + 0x0000 // ************ **** + }, + { // 0xFE = + 0x0000, // ************ **** + 0x3000, // **##******** **** + 0x3000, // **##******** **** + 0x3F80, // **#######*** **** + 0x30C0, // **##****##** **** + 0x30C0, // **##****##** **** + 0x30C0, // **##****##** **** + 0x3F80, // **#######*** **** + 0x3000, // **##******** **** + 0x3000 // **##******** **** + }, + { // 0xFF = + 0x3C00, // **####****** **** + 0x1800, // ***##******* **** + 0x1F80, // ***######*** **** + 0x18C0, // ***##***##** **** + 0x18C0, // ***##***##** **** + 0x1F80, // ***######*** **** + 0x1800, // ***##******* **** + 0x3C00, // **####****** **** + 0x0000, // ************ **** + 0x0000 // ************ **** + }, + + { // 0x60a = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x61a = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x62a = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x63a = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x64a = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x65a = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x66a = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x67a = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x68a = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x69a = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x6Aa = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x6Ba = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x6Ca = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x6Da = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x6Ea = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + { // 0x6Fa = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0 // ******###### **** + }, + + { // 0x70a = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x71a = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x72a = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x73a = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x74a = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x75a = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x76a = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x77a = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x78a = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x79a = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x7Aa = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x7Ba = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x7Ca = + 0x0000, // ************ **** + 0x0000, // ************ **** + 0x0000, // ************ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x7Da = + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFC00, // ######****** **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x7Ea = + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0x03F0, // ******###### **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0 // ############ **** + }, + { // 0x7Fa = + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + 0xFFF0, // ############ **** + } +}; + + + +int NationalOptionSubsetG0Default[13]= + {0x23,0x94,0x80,0 ,0 ,0 ,0x5e,0x5f,0 ,0 ,0 ,0 ,0 }; + +int NationalOptionSubsetCZ_SK[13]= + {0x23,0 ,0 ,0 ,0 ,0 ,0xed,0 ,0xec,0xeb,0 ,0xef,0 }; +int NationalOptionSubsetEN[13]= + {0x83,0x24,0x80,0x8b,0x8c,0x8d,0x8e,0x23,0x81,0x82,0x88,0x89,0x8a}; +int NationalOptionSubsetEE[13]= + {0x23,0xc6,0 ,0x5b,0x5c,0 ,0x5d,0xd6,0 ,0x7b,0x7c,0 ,0x7d}; +int NationalOptionSubsetFR[13]= + {0xd3,0xd4,0xd0,0xdb,0xdc,0xc1,0xde,0x23,0xd1,0xd2,0xd8,0xd9,0xcc}; +int NationalOptionSubsetDE[13]= + {0x23,0x24,0x40,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x7b,0x7c,0x7d,0x7e}; +int NationalOptionSubsetIT[13]= + {0x83,0x24,0xd3,0x60,0xcc,0x8d,0x8e,0x23,0xdd,0xc1,0xc8,0xc9,0xca}; +int NationalOptionSubsetLV_LT[13]= + {0x23,0x24,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 }; +int NationalOptionSubsetPL[13]= + {0x23,0 ,0 ,0 ,0 ,0 ,0 ,0xee,0 ,0 ,0 ,0 ,0 }; +int NationalOptionSubsetPT_ES[13]= + {0xcc,0x24,0xe0,0xeb,0xec,0xed,0xee,0xef,0xe1,0x7d,0xe8,0xc9,0xc2}; +int NationalOptionSubsetRO[13]= + {0x23,0x94,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0xd2,0 ,0 ,0xde}; +int NationalOptionSubsetSR_HR_SL[13]= + {0x23,0 ,0 ,0 ,0 ,0xfb,0 ,0xdb,0 ,0 ,0 ,0 ,0 }; +int NationalOptionSubsetSV_FI[13]= + {0x23,0x94,0x90,0x5b,0x5c,0x9d,0x5d,0x5f,0x91,0x7b,0x7c,0x99,0x7d}; +int NationalOptionSubsetTR[13]= + {0 ,0 ,0 ,0 ,0x5c,0xd7,0x5d,0 ,0 ,0 ,0x7c,0xcc,0x7d}; + + + +inline int NationalOptionSubset(int chr) { + switch (chr) { + case 0x23: return 0; + case 0x24: return 1; + case 0x40: return 2; + case 0x5b: return 3; + case 0x5c: return 4; + case 0x5d: return 5; + case 0x5e: return 6; + case 0x5f: return 7; + case 0x60: return 8; + case 0x7b: return 9; + case 0x7c: return 10; + case 0x7d: return 11; + case 0x7e: return 12; + } + return -1; +} + +inline unsigned int LeftBits(unsigned int bits) { + // Scale bit positions 0xfc00 to 0xfff0 positions + unsigned int res=0; + if (bits&0x8000) res|=0xC000; + if (bits&0x4000) res|=0x3000; + if (bits&0x2000) res|=0x0C00; + if (bits&0x1000) res|=0x0300; + if (bits&0x0800) res|=0x00C0; + if (bits&0x0400) res|=0x0030; + return res; +} +inline unsigned int RightBits(unsigned int bits) { + // Scale bit positions 0x03f0 to 0xfff0 positions + unsigned int res=0; + if (bits&0x0200) res|=0xC000; + if (bits&0x0100) res|=0x3000; + if (bits&0x0080) res|=0x0C00; + if (bits&0x0040) res|=0x0300; + if (bits&0x0020) res|=0x00C0; + if (bits&0x0010) res|=0x0030; + return res; +} + + + +unsigned int* GetFontChar(cTeletextChar c, unsigned int *buffer) { + // Get character bitmap for character/charset + + enumCharsets font=c.GetCharset(); + int chr=c.GetChar(); + unsigned int *bitmap=NULL; + int i; + int NationalOption=NationalOptionSubset(chr); + + switch (font) { + case CHARSET_LATIN_G0: + if (NationalOption>=0) { + if (NationalOptionSubsetG0Default[NationalOption]>0) + bitmap=TXT_Font[NationalOptionSubsetG0Default[NationalOption]-0x20]; + } else { + if (chr>=0x20 && chr<0x80) { + bitmap=TXT_Font[chr-0x20]; + } + } + break; + case CHARSET_LATIN_G0_EN: + if (NationalOption>=0) { + if (NationalOptionSubsetEN[NationalOption]>0) + bitmap=TXT_Font[NationalOptionSubsetEN[NationalOption]-0x20]; + } else { + if (chr>=0x20 && chr<0x80) { + bitmap=TXT_Font[chr-0x20]; + } + } + break; + case CHARSET_LATIN_G0_FR: + if (NationalOption>=0) { + if (NationalOptionSubsetFR[NationalOption]>0) + bitmap=TXT_Font[NationalOptionSubsetFR[NationalOption]-0x20]; + } else { + if (chr>=0x20 && chr<0x80) { + bitmap=TXT_Font[chr-0x20]; + } + } + break; + case CHARSET_LATIN_G0_IT: + if (NationalOption>=0) { + if (NationalOptionSubsetIT[NationalOption]>0) + bitmap=TXT_Font[NationalOptionSubsetIT[NationalOption]-0x20]; + } else { + if (chr>=0x20 && chr<0x80) { + bitmap=TXT_Font[chr-0x20]; + } + } + break; + case CHARSET_LATIN_G0_PT_ES: + if (NationalOption>=0) { + if (NationalOptionSubsetPT_ES[NationalOption]>0) + bitmap=TXT_Font[NationalOptionSubsetPT_ES[NationalOption]-0x20]; + } else { + if (chr>=0x20 && chr<0x80) { + bitmap=TXT_Font[chr-0x20]; + } + } + break; + case CHARSET_LATIN_G0_SV_FI: + if (NationalOption>=0) { + if (NationalOptionSubsetSV_FI[NationalOption]>0) + bitmap=TXT_Font[NationalOptionSubsetSV_FI[NationalOption]-0x20]; + } else { + if (chr>=0x20 && chr<0x80) { + bitmap=TXT_Font[chr-0x20]; + } + } + break; + case CHARSET_LATIN_G0_DE: + if (chr>=0x20 && chr<0x80) { + bitmap=TXT_Font[chr-0x20]; + } + break; + case CHARSET_LATIN_G0_CZ_SK: + case CHARSET_LATIN_G0_EE: + case CHARSET_LATIN_G0_LV_LT: + case CHARSET_LATIN_G0_PL: + case CHARSET_LATIN_G0_RO: + case CHARSET_LATIN_G0_SR_HR_SL: + case CHARSET_LATIN_G0_TR: + // Partially supported latin charsets + if (chr>=0x20 && chr<0x80 && NationalOption<0) { + bitmap=TXT_Font[chr-0x20]; + } + break; + + case CHARSET_LATIN_G2: + case CHARSET_CYRILLIC_G0_SR_HR: + case CHARSET_CYRILLIC_G0_RU_BG: + case CHARSET_CYRILLIC_G0_UK: + case CHARSET_CYRILLIC_G2: + case CHARSET_GREEK_G0: + case CHARSET_GREEK_G2: + case CHARSET_ARABIC_G0: + case CHARSET_ARABIC_G2: + case CHARSET_HEBREW_G0: + // totally unsupported + break; + + case CHARSET_GRAPHICS_G1: + if (chr>=0x20 && chr<0x40) { + bitmap=TXT_Font[chr-0x20+0x80]; + } else if (chr>=0x60 && chr<0x80) { + bitmap=TXT_Font[chr-0x60+0xE0]; + } + break; + case CHARSET_GRAPHICS_G1_SEP: + if (chr>=0x20 && chr<0x40) { + bitmap=TXT_Font[chr-0x20+0x80]; + } else if (chr>=0x60 && chr<0x80) { + bitmap=TXT_Font[chr-0x60+0xE0]; + } + if (bitmap) { + for (i=0;i<10;i++) buffer[i]=bitmap[i]&TXT_Mask[i]; + bitmap=buffer; + } + break; + + case CHARSET_GRAPHICS_G3: + case CHARSET_INVALID: + // Totally unsupported + break; + } + + + + if (!buffer) { + printf("Warning: Undefined char: %x %x\n",font,chr); + return NULL; + } + + switch (c.GetDblHeight()) { + case dblh_Top: + // Scale top 5 lines to full height + buffer[8]=buffer[9]=bitmap[4]; + buffer[6]=buffer[7]=bitmap[3]; + buffer[4]=buffer[5]=bitmap[2]; + buffer[2]=buffer[3]=bitmap[1]; + buffer[1]=buffer[0]=bitmap[0]; + bitmap=buffer; + break; + case dblh_Bottom: + // Scale bottom 5 lines to full height + buffer[0]=buffer[1]=bitmap[5]; + buffer[2]=buffer[3]=bitmap[6]; + buffer[4]=buffer[5]=bitmap[7]; + buffer[6]=buffer[7]=bitmap[8]; + buffer[8]=buffer[9]=bitmap[9]; + bitmap=buffer; + default:; + } + + switch (c.GetDblWidth()) { + case dblw_Left: + // Scale 6 left columns to full width + buffer[0]=LeftBits(bitmap[0]); + buffer[1]=LeftBits(bitmap[1]); + buffer[2]=LeftBits(bitmap[2]); + buffer[3]=LeftBits(bitmap[3]); + buffer[4]=LeftBits(bitmap[4]); + buffer[5]=LeftBits(bitmap[5]); + buffer[6]=LeftBits(bitmap[6]); + buffer[7]=LeftBits(bitmap[7]); + buffer[8]=LeftBits(bitmap[8]); + buffer[9]=LeftBits(bitmap[9]); + bitmap=buffer; + break; + case dblw_Right: + // Scale 6 right columns to full width + buffer[0]=RightBits(bitmap[0]); + buffer[1]=RightBits(bitmap[1]); + buffer[2]=RightBits(bitmap[2]); + buffer[3]=RightBits(bitmap[3]); + buffer[4]=RightBits(bitmap[4]); + buffer[5]=RightBits(bitmap[5]); + buffer[6]=RightBits(bitmap[6]); + buffer[7]=RightBits(bitmap[7]); + buffer[8]=RightBits(bitmap[8]); + buffer[9]=RightBits(bitmap[9]); + bitmap=buffer; + default:; + } + + return bitmap; +} diff --git a/teletxt/txtfont.h b/teletxt/txtfont.h new file mode 100644 index 0000000..220bab3 --- /dev/null +++ b/teletxt/txtfont.h @@ -0,0 +1,14 @@ +#ifndef __TXTFONT_H +#define __TXTFONT_H + +#include "../teletextdecodervbiebu.h" + +unsigned int* GetFontChar(cTeletextChar c, unsigned int *buffer); +// Get a character bitmap for character/charset +// Also handle double width/height partial characters +// buffer must be an unsigned int[10] buffer, that *may* be used +// to store the character - a different pointer may be returned too. +// returns NULL if undefined character + + +#endif diff --git a/tfeed.cc b/tfeed.cc new file mode 100644 index 0000000..d876a5d --- /dev/null +++ b/tfeed.cc @@ -0,0 +1,88 @@ +/* + Copyright 2008 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "tfeed.h" + +#include "log.h" +#include "demuxer.h" +#include "callback.h" + +TFeed::TFeed(Callback* tcb) +: cb(*tcb) +{ + teletextEnabled = 1; +} + +int TFeed::init() +{ + return 1; +} + +int TFeed::shutdown() +{ + // FIXME + return 1; +} + +void TFeed::disable() +{ + teletextEnabled = 0; +} + +void TFeed::enable() +{ + teletextEnabled = 1; +} + +int TFeed::start() +{ + teletextEnabled = 1; + return threadStart(); +} + +void TFeed::stop() +{ + threadCancel(); +} + +void TFeed::threadMethod() +{ + bool tlen; + + while(1) + { + threadCheckExit(); + + + tlen = Demuxer::getInstance()->writeTeletext(); + + if (tlen) + { + cb.call(this); +// Log::getInstance()->log("Tfeed", Log::DEBUG, "written"); + } + else + { + //MILLISLEEP(100); + MILLISLEEP(20); //Performance Issue Marten + } + + } +} diff --git a/tfeed.h b/tfeed.h new file mode 100644 index 0000000..9206a64 --- /dev/null +++ b/tfeed.h @@ -0,0 +1,55 @@ +/* + Copyright 2008 Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef TFEED_H +#define TFEED_H + +#include +#include + +#ifdef WIN32 +#include "threadwin.h" +#else +#include "threadp.h" +#endif + +class Callback; + +class TFeed : public Thread_TYPE +{ + public: + TFeed(Callback* tcb); + + int init(); + int shutdown(); + + int start(); + void stop(); + void enable(); + void disable(); + + private: + void threadMethod(); + void threadPostStopCleanup() {}; + int teletextEnabled; + Callback& cb; +}; + +#endif diff --git a/vaudioselector.cc b/vaudioselector.cc index 3315d73..6347adc 100644 --- a/vaudioselector.cc +++ b/vaudioselector.cc @@ -32,31 +32,84 @@ #include "log.h" #include "channel.h" + + VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels, - bool* availableAc3AudioChannels, int currentAudioChannel, RecInfo* recInfo) + bool* availableAc3AudioChannels, int currentAudioChannel, bool *availableSubtitleChannels,int*ttxtpages, + int currentSubtitleChannel,int currentSubtitleType, RecInfo* recInfo) { Log::getInstance()->log("VAS", Log::DEBUG, "%i", currentAudioChannel); + parent = tparent; liveMode = false; + subtitles =false; + editsubtitles = false; + + int i; + if (availableSubtitleChannels != NULL) { + for (i = 0; i < PES_DVBSUBTITLE_MAXCHANNELS; i++) { + if (availableSubtitleChannels[i]) + { + AudioSubtitleChannel* sc = new AudioSubtitleChannel(); + sc->type = 0x10;//dvbsubtitle + sc->name = NULL; + sc->pestype = PES_DVBSUBTITLE_START+ i; + scl.push_back(sc); + } + } + for (i=0;i<10;i++) { + if (ttxtpages[i]>0) { + AudioSubtitleChannel* sc = new AudioSubtitleChannel(); + int length=strlen(tr("TTxt:"))+1+1+3+1; + sc->type = 0x11;//Teletxt + sc->name = new char[length]; + SNPRINTF(sc->name,length,"%s %3x",tr("TTxt:"),ttxtpages[i]); + sc->pestype = ttxtpages[i]; + scl.push_back(sc); + } + } + } + + if (scl.size()>0) { + AudioSubtitleChannel* sc = new AudioSubtitleChannel(); + sc->type = 0xFF;//special + sc->name = new char[strlen(tr("No Subtitles"))+1]; + strcpy(sc->name,tr("No Subtitles")); + sc->pestype = 0; + scl.insert(scl.begin(),sc); + subtitles=true; + } + + + + if (subtitles) { + setSize(400, 120); + } else { + setSize(200, 120); + } - setSize(200, 120); createBuffer(); - sl.setPosition(40, 30); - sl.setSize(area.w - 45, area.h - 30); - add(&sl); + asl.setPosition(40, 30); + asl.setSize(200 - 45, area.h - 30); + add(&asl); + + if (subtitles) { + ssl.setPosition(200+40,30); + ssl.setSize(200 - 45, area.h - 30); + add(&ssl); + } // Load data from availableAudioChannels, currentAudioChannel and recInfo - int i; for (i = 0; i < PES_AUDIO_MAXCHANNELS; i++) { if (availableMpegAudioChannels[i]) { - AudioChannel* ac = new AudioChannel(); + AudioSubtitleChannel* ac = new AudioSubtitleChannel(); ac->type = 0; ac->name = NULL; ac->pestype = PES_AUDIO_START + i; @@ -69,7 +122,7 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels, { if (availableAc3AudioChannels[i]) { - AudioChannel* ac = new AudioChannel(); + AudioSubtitleChannel* ac = new AudioSubtitleChannel(); ac->type = 1;//ac3 ac->name = NULL; ac->pestype = PES_AUDIO_AC3_START + i; @@ -78,15 +131,22 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels, } } + + + + + unsigned char numchan_recinfo = recInfo->numComponents; unsigned char numchan_siz = acl.size(); + unsigned char numchan_subtitles_siz = scl.size(); int mp_audcounter = 0; int ac3_counter = 0; int ac3_offset = 0; + int dvb_subcounter = 1; for (i = 0; i < numchan_siz; i++) { - AudioChannel* ac = acl[i]; + AudioSubtitleChannel* ac = acl[i]; if (ac) { if (ac->type==0) @@ -102,26 +162,35 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels, int type_int; for (i = 0; i < numchan_recinfo; i++) - { - if (recInfo->streams[i] != 2) continue; //not an audio component + { + type = recInfo->types[i]; lang = recInfo->languages[i]; description = recInfo->descriptions[i]; - AudioChannel* ac = NULL; + AudioSubtitleChannel* ac = NULL; type_int = 0; - - switch (type) - { - case 1: //mpaudio mono - case 3: //mpaudio stereo - if (mp_audcounter < numchan_siz) ac = acl[mp_audcounter]; - type_int = 0; - break; - case 5: //ac3 - if (ac3_counter + ac3_offset < numchan_siz) ac = acl[ac3_counter + ac3_offset]; - type_int = 1; - break; - } + if (recInfo->streams[i] == 2) { + switch (type) + { + case 1: //mpaudio mono + case 3: //mpaudio stereo + if (mp_audcounter < numchan_siz) ac = acl[mp_audcounter]; + type_int = 0; + break; + case 5: //ac3 + if (ac3_counter + ac3_offset < numchan_siz) ac = acl[ac3_counter + ac3_offset]; + type_int = 1; + break; + } + } else if (recInfo->streams[i] == 3){ + /* switch (type) + { + case 20:*/ + if (dvb_subcounter < numchan_subtitles_siz) ac = scl[dvb_subcounter]; + type_int=0x10; + /* break; + };*/ + } else continue; //neither audio nor subtitle if (ac) { @@ -148,6 +217,9 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels, case 1: //ac3 ac3_counter++; break; + case 0x10: + dvb_subcounter++; + break; } } @@ -160,11 +232,11 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels, { for(i = 0; i < audioChannelListSize; i++) { - AudioChannel* ac = acl[i]; + AudioSubtitleChannel* ac = acl[i]; if (ac->name) { - sl.addOption(ac->name, (ULONG)ac, (ac->pestype == currentAudioChannel)); + asl.addOption(ac->name, (ULONG)ac, (ac->pestype == currentAudioChannel)); } else { @@ -180,34 +252,114 @@ VAudioSelector::VAudioSelector(void* tparent, bool* availableMpegAudioChannels, { SNPRINTF(tempString, 299, "unknown"); } - sl.addOption(tempString, (ULONG)ac, (ac->pestype == currentAudioChannel)); + asl.addOption(tempString, (ULONG)ac, (ac->pestype == currentAudioChannel)); } } } else { - sl.addOption(tr("No audio channel data available"), 0, 1); + asl.addOption(tr("No audio channel data available"), 0, 1); } + + int subtitlesChannelListSize = scl.size(); + + if (subtitles) { + ssl.setDarkSelOption(true); + for(i = 0; i < subtitlesChannelListSize; i++) + { + AudioSubtitleChannel* sc = scl[i]; + bool selected=false; + if (sc->pestype == currentSubtitleChannel && sc->type ==currentSubtitleType) selected=true; + + if (sc->name) + { + ssl.addOption(sc->name, (ULONG)sc, selected); + } + else + { + if (sc->type==0x10) + { + SNPRINTF(tempString, 299, "%lu", (ULONG)(sc->pestype - PES_DVBSUBTITLE_START)); + } + else + { + SNPRINTF(tempString, 299, "unknown"); + } + ssl.addOption(tempString, (ULONG)sc, selected); + } + } + } + } -VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudioChannel) +VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudioChannel,int currentSubtitletype,int currentSubtitleChannel,int*ttxtpages) { parent = tparent; liveMode = true; + editsubtitles = false; + subtitles =false; + UINT i; + + for (i = 0; i < channel->numSPids; i++) + { + AudioSubtitleChannel* sc = new AudioSubtitleChannel(); + sc->type = 0x10; + sc->name = new char[strlen(channel->spids[i].name) + 1]; + strcpy(sc->name, channel->spids[i].name); + sc->pestype = channel->spids[i].pid; + scl.push_back(sc); + } + if (ttxtpages) { + for (i=0;i<10;i++) { + if (ttxtpages[i]>0) { + AudioSubtitleChannel* sc = new AudioSubtitleChannel(); + int length=strlen(tr("TTxt:"))+1+1+3+1; + sc->type = 0x11;//Teletxt + sc->name = new char[length]; + SNPRINTF(sc->name,length,"%s %3x",tr("TTxt:"),ttxtpages[i]); + sc->pestype = ttxtpages[i]; + scl.push_back(sc); + } + } + } + + + if (scl.size()>0) { + AudioSubtitleChannel* sc = new AudioSubtitleChannel(); + sc->type = 0xFF;//special + sc->name = new char[strlen(tr("No Subtitles"))+1]; + strcpy(sc->name,tr("No Subtitles")); + sc->pestype = 0; + scl.insert(scl.begin(),sc); + subtitles=true; + } + + - setSize(200, 120); + if (subtitles) { + setSize(400, 120); + } else { + setSize(200, 120); + } createBuffer(); - sl.setPosition(40, 30); - sl.setSize(area.w - 45, area.h - 30); - add(&sl); + + asl.setPosition(40, 30); + asl.setSize(200 - 45, area.h - 30); + add(&asl); + + if (subtitles) { + ssl.setPosition(200+40,30); + ssl.setSize(200 - 45, area.h - 30); + add(&ssl); + } // Load data from availableAudioChannels, currentAudioChannel and recInfo - for (UINT i = 0; i < channel->numAPids; i++) + for (i = 0; i < channel->numAPids; i++) { - AudioChannel* ac = new AudioChannel(); + AudioSubtitleChannel* ac = new AudioSubtitleChannel(); ac->type = 0; ac->name = new char[strlen(channel->apids[i].name) + 1]; strcpy(ac->name, channel->apids[i].name); @@ -217,9 +369,9 @@ VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudio if (Audio::getInstance()->supportsAc3()) { - for (UINT i = 0; i < channel->numDPids; i++) + for (i = 0; i < channel->numDPids; i++) { - AudioChannel* ac = new AudioChannel(); + AudioSubtitleChannel* ac = new AudioSubtitleChannel(); ac->type = 1; ac->name = new char[strlen(channel->dpids[i].name) + 1]; strcpy(ac->name, channel->dpids[i].name); @@ -232,15 +384,28 @@ VAudioSelector::VAudioSelector(void* tparent, Channel* channel, int currentAudio if (audioChannelListSize) { - for(int i = 0; i < audioChannelListSize; i++) + for(int j = 0; j < audioChannelListSize; j++) { - AudioChannel* ac = acl[i]; - sl.addOption(ac->name, (ULONG)ac, (ac->pestype == currentAudioChannel)); + AudioSubtitleChannel* ac = acl[j]; + asl.addOption(ac->name, (ULONG)ac, (ac->pestype == currentAudioChannel)); } } else { - sl.addOption(tr("No audio channel data available"), 0, 1); + asl.addOption(tr("No audio channel data available"), 0, 1); + } + int subtitlesChannelListSize = scl.size(); + + if (subtitles) { + ssl.setDarkSelOption(true); + for(int j = 0; j < subtitlesChannelListSize; j++) + { + AudioSubtitleChannel* sc = scl[j]; + bool selected=false; + if ((sc->type==currentSubtitletype) && (sc->pestype == currentSubtitleChannel)) selected=true; + ssl.addOption(sc->name, (ULONG)sc, selected); + + } } } @@ -256,7 +421,19 @@ VAudioSelector::~VAudioSelector() } acl.clear(); - sl.clear(); + asl.clear(); + + int subtitleChannelListSize = scl.size(); + for(int i = 0; i < subtitleChannelListSize; i++) + { + // FIXME memory leak - nobody is deleting audio channel name? // try: + delete[] scl[i]->name; + Log::getInstance()->log("VAudioSelector", Log::DEBUG, "Deleted char[] on close"); + delete scl[i]; + } + scl.clear(); + + ssl.clear(); Message* m = new Message(); m->from = this; @@ -273,9 +450,16 @@ void VAudioSelector::draw() rectangle(0, 0, area.w, 30, Colour::TITLEBARBACKGROUND); drawText(tr("Audio"), 45, 5, Colour::LIGHTTEXT); + if (subtitles) { + drawText(tr("Subtitles"), 45+200, 5, Colour::LIGHTTEXT); + ssl.setBackgroundColour(backgroundColour); + ssl.draw(); + } + + asl.setBackgroundColour(backgroundColour); + asl.draw(); - sl.setBackgroundColour(backgroundColour); - sl.draw(); + } int VAudioSelector::handleCommand(int command) @@ -291,37 +475,81 @@ int VAudioSelector::handleCommand(int command) case Remote::DF_UP: case Remote::UP: { - sl.up(); - sl.draw(); - - BoxStack::getInstance()->update(this); - - Message* m = new Message(); - m->from = this; - m->to = parent; - m->message = Message::AUDIO_CHANGE_CHANNEL; - m->parameter = (((AudioChannel*)sl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioChannel*)sl.getCurrentOptionData())->type &0xFF)<<16 ; - Command::getInstance()->postMessageNoLock(m); + if (editsubtitles) { + ssl.up(); + ssl.draw(); + BoxStack::getInstance()->update(this); + Message* m = new Message(); + m->from = this; + m->to = parent; + m->message = Message::SUBTITLE_CHANGE_CHANNEL; + m->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ; + Command::getInstance()->postMessageNoLock(m); + } else { + asl.up(); + asl.draw(); + BoxStack::getInstance()->update(this); + Message* m = new Message(); + m->from = this; + m->to = parent; + m->message = Message::AUDIO_CHANGE_CHANNEL; + m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ; + Command::getInstance()->postMessageNoLock(m); + } return 2; } case Remote::DF_DOWN: case Remote::DOWN: { - sl.down(); - sl.draw(); - - BoxStack::getInstance()->update(this); - - Message* m = new Message(); - m->from = this; - m->to = parent; - m->message = Message::AUDIO_CHANGE_CHANNEL; - m->parameter = (((AudioChannel*)sl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioChannel*)sl.getCurrentOptionData())->type &0xFF)<<16 ; - Command::getInstance()->postMessageNoLock(m); + if (editsubtitles) { + ssl.down(); + ssl.draw(); + BoxStack::getInstance()->update(this); + Message* m = new Message(); + m->from = this; + m->to = parent; + m->message = Message::SUBTITLE_CHANGE_CHANNEL; + m->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ; + Command::getInstance()->postMessageNoLock(m); + } else { + asl.down(); + asl.draw(); + BoxStack::getInstance()->update(this); + Message* m = new Message(); + m->from = this; + m->to = parent; + m->message = Message::AUDIO_CHANGE_CHANNEL; + m->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ; + Command::getInstance()->postMessageNoLock(m); + } return 2; } + case Remote::LEFT: + { + if (editsubtitles && subtitles) { + ssl.setDarkSelOption(true); + asl.setDarkSelOption(false); + editsubtitles=false; + asl.draw(); + ssl.draw(); + BoxStack::getInstance()->update(this); + } + return 2; + } + case Remote::RIGHT: + { + if (!editsubtitles && subtitles) { + ssl.setDarkSelOption(false); + asl.setDarkSelOption(true); + editsubtitles=true; + asl.draw(); + ssl.draw(); + BoxStack::getInstance()->update(this); + } + return 2; + } } return 1; @@ -331,26 +559,69 @@ void VAudioSelector::processMessage(Message* m) { if (m->message == Message::MOUSE_MOVE) { - UINT lastsel=sl.getCurrentOption(); - if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) - { - sl.draw(); - BoxStack::getInstance()->update(this); - if ((int)lastsel!=sl.getCurrentOption()) - { - Message* m2 = new Message(); - m2->from = this; - m2->to = parent; - m2->message = Message::AUDIO_CHANGE_CHANNEL; - m2->parameter = (((AudioChannel*)sl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioChannel*)sl.getCurrentOptionData())->type &0xFF)<<16 ; - Command::getInstance()->postMessageNoLock(m2); + + UINT lastsel=asl.getCurrentOption(); + + if (((m->parameter>>16)-getScreenX()) < 200 && asl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) + { + editsubtitles=false; + ssl.setDarkSelOption(true); + asl.setDarkSelOption(false); + asl.draw(); + ssl.draw(); + BoxStack::getInstance()->update(this); + if ((int)lastsel!=asl.getCurrentOption()) + { + Message* m2 = new Message(); + m2->from = this; + m2->to = parent; + m2->message = Message::AUDIO_CHANGE_CHANNEL; + m2->parameter = (((AudioSubtitleChannel*)asl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)asl.getCurrentOptionData())->type &0xFF)<<16 ; + Command::getInstance()->postMessageNoLock(m2); + } + return; + } - } + lastsel=ssl.getCurrentOption(); + + if (ssl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) + { + editsubtitles=true; + ssl.setDarkSelOption(false); + asl.setDarkSelOption(true); + asl.draw(); + ssl.draw(); + BoxStack::getInstance()->update(this); + if ((int)lastsel!=ssl.getCurrentOption()) + { + Message* m2 = new Message(); + m2->from = this; + m2->to = parent; + m2->message = Message::SUBTITLE_CHANGE_CHANNEL; + m2->parameter = (((AudioSubtitleChannel*)ssl.getCurrentOptionData())->pestype &0xFFFF)|(((AudioSubtitleChannel*)ssl.getCurrentOptionData())->type &0xFF)<<16 ; + Command::getInstance()->postMessageNoLock(m2); + } + return; + } } else if (m->message == Message::MOUSE_LBDOWN) { - if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) + if (asl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) + { + editsubtitles=false; + ssl.setDarkSelOption(true); + asl.setDarkSelOption(false); + asl.draw(); + ssl.draw(); + BoxStack::getInstance()->handleCommand(Remote::OK); //simulate OK press + } + else if (ssl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY())) { + editsubtitles=true; + ssl.setDarkSelOption(false); + asl.setDarkSelOption(true); + asl.draw(); + ssl.draw(); BoxStack::getInstance()->handleCommand(Remote::OK); //simulate OK press } else diff --git a/vaudioselector.h b/vaudioselector.h index 31db81c..09d8afc 100644 --- a/vaudioselector.h +++ b/vaudioselector.h @@ -36,8 +36,10 @@ class Channel; #define PES_AUDIO_MAXCHANNELS 0x20 #define PES_AUDIO_AC3_MAXCHANNELS 0x08 #define PES_AUDIO_AC3_START 0x80 +#define PES_DVBSUBTITLE_MAXCHANNELS 0x08 +#define PES_DVBSUBTITLE_START 0x20 -class AudioChannel +class AudioSubtitleChannel { public: int type; @@ -45,15 +47,22 @@ class AudioChannel int pestype; }; -typedef vector AudioChannelList; + + +typedef vector AudioSubtitleChannelList; class VAudioSelector : public TBBoxx { public: VAudioSelector(void* parent, bool* availableMpegAudioChannels, // Recording mode - bool* availableAc3AudioChannels, int currentAudioChannel, RecInfo* recInfo); + bool* availableAc3AudioChannels, int currentAudioChannel, + bool *availableSubtitleChannels, + int*ttxtpages, + int currentSubtitleChannel,int currentSubtitleType, + RecInfo* recInfo); - VAudioSelector(void* tparent, Channel* channel, int currentAudioChannel); // Live mode + VAudioSelector(void* tparent, Channel* channel, int currentAudioChannel, + int currentSubtitleChannel,int currentSubtitletype,int*ttxtpages); // Live mode VAudioSelector(void* parent, Channel* channel); @@ -65,11 +74,15 @@ class VAudioSelector : public TBBoxx private: void* parent; - WSelectList sl; + WSelectList asl; + WSelectList ssl; bool liveMode; + bool subtitles; + bool editsubtitles; - AudioChannelList acl; + AudioSubtitleChannelList acl; + AudioSubtitleChannelList scl; }; #endif diff --git a/vfeed.cc b/vfeed.cc index d7bd908..b351cf8 100644 --- a/vfeed.cc +++ b/vfeed.cc @@ -75,7 +75,7 @@ void VFeed::threadMethod() else { // Log::getInstance()->log("VFeed", Log::DEBUG, "No data delay"); - MILLISLEEP(50); + MILLISLEEP(20); } } } diff --git a/vmedialist.cc b/vmedialist.cc index 47b2d9a..cb73b9b 100644 --- a/vmedialist.cc +++ b/vmedialist.cc @@ -818,7 +818,7 @@ int VMediaList::handleCommand(int command) else playAudio(command==Remote::PLAY,true,true); break; - case MEDIA_TYPE_VIDEO: + case MEDIA_TYPE_VIDEO: { Log::getInstance()->log("VMediaList", Log::DEBUG, "play video file %s", media->getFileName()); //OK - simply today @@ -840,7 +840,7 @@ int VMediaList::handleCommand(int command) BoxStack::getInstance()->update(v); v->go(false); //play video - break; + }break; case MEDIA_TYPE_PICTURE: Log::getInstance()->log("VMediaList", Log::DEBUG, "show picture file %s", media->getFileName()); diff --git a/vmediaview.cc b/vmediaview.cc index 07c9915..00a7c06 100644 --- a/vmediaview.cc +++ b/vmediaview.cc @@ -539,7 +539,7 @@ int VMediaView::handleCommand(int command) showPicture(VMediaList::MV_NONE,slideshow,true); rt=2; break; - case Remote::MENU: + case Remote::MENU: { stopSlideshow(true); destroyPictureBanner(); destroyInfo(); @@ -548,7 +548,8 @@ int VMediaView::handleCommand(int command) ct->draw(); BoxStack::getInstance()->update(ct); rt=2; - break; + + } break; case Remote::BACK: { setPictureMode(false); diff --git a/vteletextview.cc b/vteletextview.cc new file mode 100644 index 0000000..08274ee --- /dev/null +++ b/vteletextview.cc @@ -0,0 +1,346 @@ +/* + Copyright 2005-2008 Chris Tallon, Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ +#include +#include "vteletextview.h" +#include "video.h" +#include "timers.h" +#include "boxstack.h" +#include "remote.h" +#include "teletxt/txtfont.h" + +float interpol_table_fac1[16][22]; +float interpol_table_fac2[16][22]; +float interpol_table_fac3[16][22]; +float interpol_table_fac4[16][22]; +int interpol_lowbit[16]; +int interpol_upbit[16]; +int interpol_lowline[22]; +int interpol_upline[22]; + +void initpol_tables(){ + int charsizex; + int charsizey; + charsizex=16; + if (Video::getInstance()->getFormat() == Video::PAL) + { + charsizey=22; + } else { + charsizey=18; + } + int ttcharsizex=12; + int ttcharsizey=10; + for (int py=0;pygetFormat() == Video::PAL) + { + //setSize(680, 550); + setSize(680,22); //Only first line + setPosition(40, 13); + } + else + { + setPosition(40, 15); + //setSize(680, 450); + setSize(680,18);//only first line + } + createBuffer(); + keyindigit=1; + page=0x100; + +} + +VTeletextView::~VTeletextView () +{ + // Make sure the timer is deleted + pv->draw(); + BoxStack::getInstance()->update(pv); + Timers::getInstance()->cancelTimer(this, 1); + ttdecoder->unRegisterTeletextView(this); + +} + +void VTeletextView::draw(bool completedraw, bool onlyfirstline) +{ + Boxx::draw(); + int x,y; + + for (y=0;y<25;y++) { + for (x=0;x<40;x++) { + if (ttdecoder->isDirty(x,y) || completedraw) { + cTeletextChar c=ttdecoder->getChar(x,y); + c.SetDirty(false); + //Skip Blinking and conceal + drawChar(x,y,c); + ttdecoder->setChar(x,y,c); + } + } + if (onlyfirstline) break; + } + + +} + +Colour VTeletextView::enumTeletextColorToCoulour(enumTeletextColor ttcol) +{ + switch (ttcol) { + case ttcBlack: + return Colour(0,0,0); + case ttcRed: + return Colour(255,0,0); + case ttcGreen: + return Colour(0,255,0); + case ttcYellow: + return Colour(255,255,0); + case ttcBlue: + return Colour(0,0,255); + case ttcMagenta: + return Colour(255,0,255); + case ttcCyan: + return Colour(0,255,255); + case ttcWhite: + return Colour(255,255,255); + case ttcTransparent: + return Colour(0,0,0,0); + case ttcHalfRed: + return Colour(127,0,0); + case ttcHalfGreen: + return Colour(0,127,0); + case ttcHalfYellow: + return Colour(127,127,0); + case ttcHalfBlue: + return Colour(0,0,127); + case ttcHalfMagenta: + return Colour(127,0,127); + case ttcHalfCyan: + return Colour(0,127,127); + case ttcGrey: + return Colour(127,127,127); + default: + return Colour(0,0,0); + }; +} + +//Next function inspired by osdteletext plugin +void VTeletextView::drawChar(int x, int y, cTeletextChar c) +{ + unsigned int buffer [10]; + unsigned int * charmap=GetFontChar(c,buffer); + if (!charmap) { //invalid char + memset(&buffer,0,10); + charmap=buffer; + } + enumTeletextColor ttforegcolour=c.GetFGColor(); + enumTeletextColor ttbackgcolour=c.GetBGColor(); + if (c.GetBoxedOut()) { + ttforegcolour=ttcTransparent; + ttbackgcolour=ttcTransparent; + } + int charsizex; + int charsizey; + charsizex=16; + bool firstline=false; + if (y==0) firstline=true; + if (Video::getInstance()->getFormat() == Video::PAL) + { + charsizey=22; + } else { + charsizey=18; + } + int ttcharsizex=12; + int ttcharsizey=10; + int screenposx=charsizex*x; //12*40= 480 250 + int screenposy=y*charsizey; + Boxx* drawtarget=this; + if (!firstline) { + + drawtarget=pv; + screenposy+=this->getScreenY(); + screenposx+=this->getScreenX(); + + } + + Colour fgcharcl=enumTeletextColorToCoulour(ttforegcolour); + Colour bgcharcl=enumTeletextColorToCoulour(ttbackgcolour); + + drawtarget->startFastDraw(); + for (int py=0;py>upperbit)) ? fgcharcl: bgcharcl; + Colour ulc=( upperbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl; + Colour luc=( lowerbitline &(0x8000>>upperbit)) ? fgcharcl: bgcharcl; + Colour llc=( lowerbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl; + float fac1,fac2,fac3,fac4; + fac1=interpol_table_fac1[px][py]; + fac2=interpol_table_fac2[px][py]; + fac3=interpol_table_fac3[px][py]; + fac4=interpol_table_fac4[px][py]; + + Colour res(uuc.red*fac1+ulc.red*fac2+luc.red*fac3+llc.red*fac4, + uuc.green*fac1+ulc.green*fac2+luc.green*fac3+llc.green*fac4, + uuc.blue*fac1+ulc.blue*fac2+luc.blue*fac3+llc.blue*fac4, + uuc.alpha*fac1+ulc.alpha*fac2+luc.alpha*fac3+llc.alpha*fac4); //if this is too slow make a table + drawtarget->drawPixelAlpha(screenposx+px,screenposy+py,res, true); + } + } + + + drawtarget->endFastDraw(); + + +} + +int VTeletextView::handleCommand(int command) { + if (subtitlemode) return 0; //Ok we are in subtitle mode, we are a slave of the player + switch (command) { + case Remote::OK: + return 2; + case Remote::BACK: + return 4; + case Remote::ZERO: + case Remote::ONE: + case Remote::TWO: + case Remote::THREE: + case Remote::FOUR: + case Remote::FIVE: + case Remote::SIX: + case Remote::SEVEN: + case Remote::EIGHT: + case Remote::NINE: + { + // key in teletext page + doKey(command); + return 2; + } + }; + + return 0; + +} + +void VTeletextView::doKey(int command) +{ + char pagenums[3]; + if (keyindigit==1){ + if (command==9) return; //not allowed + page=command<<8; + pagenums[0]=command+ 48; + pagenums[1]='-'; + pagenums[2]='-'; + keyindigit++; + } else if (keyindigit==2) { + page|=command<<4; + pagenums[0]=48+((page &0xF00)>>8); + pagenums[1]=command+ 48; + pagenums[2]='-'; + keyindigit++; + } else if (keyindigit==3) { + page|=command; + pagenums[0]=48+((page &0xF00)>>8); + pagenums[1]=48+((page &0x0F0)>>4); + pagenums[2]=48+command; + keyindigit=1; + ttdecoder->setPage(page); + } + ttdecoder->setKeyinDigits(pagenums,true); + Region toupdate; + toupdate.w=16*40; + if (Video::getInstance()->getFormat() == Video::PAL) { + toupdate.h=22; + + } else { + toupdate.h=18; + + } + toupdate.x=0; + toupdate.y=0; + + draw(false,true); + BoxStack::getInstance()->update(this,&toupdate); + +} + +void VTeletextView::timercall(int clientReference) +{ + +} + +void VTeletextView::processMessage(Message* m) +{ + if (m->message == Message::TELETEXTUPDATE) + { + draw(false,false); + BoxStack::getInstance()->update(this); + BoxStack::getInstance()->update(pv); + + } else if (m->message == Message::TELETEXTUPDATEFIRSTLINE) + { + Region toupdate; + toupdate.w=16*40; + if (Video::getInstance()->getFormat() == Video::PAL) { + toupdate.h=22; + + } else { + toupdate.h=18; + + } + toupdate.x=0; + toupdate.y=0; + + + + draw(false,true); + BoxStack::getInstance()->update(this,&toupdate); + + } +} + + diff --git a/vteletextview.h b/vteletextview.h new file mode 100644 index 0000000..d69a4a6 --- /dev/null +++ b/vteletextview.h @@ -0,0 +1,64 @@ +/* + Copyright 2005-2008 Chris Tallon, Marten Richter + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef VTELETEXTVIEW_H +#define VTELETEXTVIEW_H + +#include + +#include "boxx.h" +#include "timerreceiver.h" +#include "teletextdecodervbiebu.h" + +class VTeletextView : public Boxx, public TimerReceiver +{ + public: + VTeletextView (TeletextDecoderVBIEBU* TTdecoder, Boxx* playerview); + ~VTeletextView (); + void draw(bool completedraw, bool onlyfirstline); + void draw() {draw(true,false);}; + void drawChar(int x, int y, cTeletextChar c); + + Colour enumTeletextColorToCoulour(enumTeletextColor ttcol); + + void processMessage(Message* m); + + void setSubtitleMode(bool mode) {subtitlemode=mode;}; + bool isInSubtitleMode() {return subtitlemode;}; + + int handleCommand(int command); + void timercall(int clientReference); + + + private: + void doKey(int command); + + + protected: + TeletextDecoderVBIEBU* ttdecoder; + int keyindigit; + int page; + bool subtitlemode; + Boxx* pv; + + +}; + +#endif diff --git a/vvideolivetv.cc b/vvideolivetv.cc index afa4292..40838fe 100644 --- a/vvideolivetv.cc +++ b/vvideolivetv.cc @@ -40,6 +40,7 @@ #include "vepg.h" #include "bitmap.h" #include "log.h" +#include "vteletextview.h" VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList) { @@ -180,7 +181,7 @@ VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, V textYellow.setBackgroundColour(osdBack); textYellow.setPosition(boxYellow.getX2(), 98); textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30); - textYellow.setText(""); + textYellow.setText("Teletext"); osd.add(&textYellow); textBlue.setBackgroundColour(osdBack); @@ -396,6 +397,7 @@ int VVideoLiveTV::handleCommand(int command) } case Remote::YELLOW: { + doTeletext(); //TODO: Add a selector for subtitles or teletext return 2; } case Remote::GUIDE: @@ -573,10 +575,45 @@ void VVideoLiveTV::doKey(int command) delete[] keyingString; } +void VVideoLiveTV::doTeletext(bool subtitlemode) +{ + bool exists=true; + + // Cancel keying + if (keying) + { + keying = 0; + // and reset the display - this is a copy from setNowNextData + char formatChanNum[20]; + SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number); + osdChanNum.setText(formatChanNum); + osdChanName.setText((*chanList)[osdChannelIndex]->name); + } + if (osd.getVisible()) clearScreen(); + // Draw the teletxt + VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView(); + if (vtxv==NULL) { + vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this); + ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv); + exists=false; + } + vtxv->setSubtitleMode(subtitlemode); + vtxv->draw(); + draw(); + + if (!exists) { + BoxStack::getInstance()->add(vtxv); + } + BoxStack::getInstance()->update(this); + BoxStack::getInstance()->update(vtxv); +} + void VVideoLiveTV::doAudioSelector() { // If the osd is already visisble there might be a timer for it Timers::getInstance()->cancelTimer(this, 1); + //This causes a deadlock with the timertrhread itself is locked + // Cancel keying if (keying) @@ -588,9 +625,24 @@ void VVideoLiveTV::doAudioSelector() osdChanNum.setText(formatChanNum); osdChanName.setText((*chanList)[osdChannelIndex]->name); } + int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel(); + int subtitleType=0x10; + if (!(static_cast(player))->isSubtitlesOn()) { + if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() && + ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode() + ) { + subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage(); + subtitleType=0x11; + + } else { + subtitleType=0xFF; //turnedOff + subtitleChannel=0; + } + } // Draw the selector - vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel()); + vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(), + subtitleType,subtitleChannel,player->getTeletxtSubtitlePages()); Colour osdBack = Colour(0, 0, 0, 128); vas->setBackgroundColour(osdBack); vas->setPosition(0, osd.getScreenY() - vas->getHeight()); @@ -760,6 +812,7 @@ void VVideoLiveTV::timercall(int ref) { if (keying) { + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start."); UINT newChannel = 0; for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i); @@ -769,9 +822,11 @@ void VVideoLiveTV::timercall(int ref) m->parameter = newChannel; m->tag = 1; // signal to call displayOSD(); Command::getInstance()->postMessageFromOuterSpace(m); + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end."); } else { + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start."); // We have received a timer, we are not keying. If still prebuffering, don't remove the bar if (preBuffering < 100) { @@ -779,27 +834,39 @@ void VVideoLiveTV::timercall(int ref) Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s return; } - + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1."); osd.setVisible(false); okTriggeredOSD = false; + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2."); draw(); + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4."); boxstack->update(this, osd.getRegion()); + + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3."); + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end."); } } else if (ref == 2) { + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start."); setClock(); if (osd.getVisible()) { clock.draw(); boxstack->update(this, osd.getRegion()); } + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end."); } } bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData) { UINT newChannel = 0; + VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView(); + if (vtxt ) { + BoxStack::getInstance()->remove(vtxt); + + } if (changeType == INDEX) { @@ -857,9 +924,11 @@ bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData) if (textUnavailable.getVisible()) { textUnavailable.setVisible(false); + + } + draw(); BoxStack::getInstance()->update(this); - } return true; } @@ -915,6 +984,44 @@ void VVideoLiveTV::processMessage(Message* m) { Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %i", m->parameter); player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16); + } + else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL) + { + Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %i", m->parameter); + int type=((m->parameter & 0xFF0000)>>16); + switch (type) { + case 0x10: { //dvbsubtitle + if (streamType = VDR::VIDEO){ + player->setSubtitleChannel((m->parameter & 0xFFFF)); + (static_cast(player))->turnSubtitlesOn(true); + VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView(); + if (vtxt && vtxt->isInSubtitleMode()) { + BoxStack::getInstance()->remove(vtxt); + } + } + } break; + case 0xFF: { //nosubtitles + if (streamType = VDR::VIDEO){ + (static_cast(player))->turnSubtitlesOn(false); + VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView(); + if (vtxt && vtxt->isInSubtitleMode()) { + BoxStack::getInstance()->remove(vtxt); + } + } + } break; + case 0x11: { //videotext + (static_cast(player))->turnSubtitlesOn(false); + doTeletext(true); + ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF)); + } break; + }; + if (vas) { + BoxStack::getInstance()->update(vas); + //BoxStack::getInstance()->update(&osd); //eveil error + } + BoxStack::getInstance()->update(this, osd.getRegion()); + + } else if (m->message == Message::PLAYER_EVENT) { diff --git a/vvideolivetv.h b/vvideolivetv.h index 8057d40..0ff6e84 100644 --- a/vvideolivetv.h +++ b/vvideolivetv.h @@ -102,6 +102,7 @@ class VVideoLiveTV : public Boxx, public TimerReceiver, public OSDReceiver void doEPG(); void doSummary(); void doAudioSelector(); + void doTeletext(bool subtitle=false); void stop(); UINT upChannel(UINT index); UINT downChannel(UINT index); diff --git a/vvideomedia.cc b/vvideomedia.cc index ac7fb21..daca8b1 100644 --- a/vvideomedia.cc +++ b/vvideomedia.cc @@ -486,7 +486,8 @@ void VVideoMedia::doAudioSelector() RecInfo ri; ri.summary=new char[strlen(myMedia->getDisplayName())+1]; strcpy(ri.summary,myMedia->getDisplayName()); - vas = new VAudioSelector(this, availableMpegAudioChannels, availableAc3AudioChannels, currentAudioChannel, &ri); + vas = new VAudioSelector(this, availableMpegAudioChannels, availableAc3AudioChannels, currentAudioChannel, NULL,NULL,0,0, &ri); + vas->setBackgroundColour(barBlue); vas->setPosition(0, barRegion.y - 120); @@ -691,11 +692,11 @@ void VVideoMedia::doSummary() stlen+=strlen(tr("Time"))+50; char *pinfo=player->getInfo(); stlen+=strlen(pinfo)+10; - char buf[stlen]; - char tsbuf[stlen]; - char tsbuf2[stlen]; - char tbuf[Media::TIMEBUFLEN]; - snprintf(buf,stlen,"%s\n" + char *buf=new char [stlen]; + char *tsbuf=new char [stlen]; + char *tsbuf2=new char [stlen]; + char *tbuf=new char[Media::TIMEBUFLEN]; + SNPRINTF(buf,stlen,"%s\n" "%s: %llu Bytes\n" "%s\n" "%s: %s\n" @@ -728,6 +729,10 @@ void VVideoMedia::doSummary() vsummary->draw(); BoxStack::getInstance()->update(this); + delete [] buf; + delete [] tsbuf; + delete [] tsbuf2; + delete [] tbuf; } void VVideoMedia::removeSummary() diff --git a/vvideorec.cc b/vvideorec.cc index 0204dc4..e5c1bc0 100644 --- a/vvideorec.cc +++ b/vvideorec.cc @@ -19,6 +19,7 @@ */ #include "vvideorec.h" +#include "vteletextview.h" #include "command.h" #include "osd.h" @@ -398,6 +399,30 @@ int VVideoRec::handleCommand(int command) return 1; } +void VVideoRec::doTeletext() +{ + + bool exists=true; + + + // Draw the teletxt + VTeletextView *vtxv=player->getTeletextDecoder()->getTeletxtView(); + if (vtxv==NULL) { + vtxv= new VTeletextView((player)->getTeletextDecoder(),this); + (player)->getTeletextDecoder()->registerTeletextView(vtxv); + exists=false; + } + vtxv->setSubtitleMode(true); + vtxv->draw(); + draw(); + + if (!exists) { + BoxStack::getInstance()->add(vtxv); + } + BoxStack::getInstance()->update(this); + BoxStack::getInstance()->update(vtxv); +} + void VVideoRec::processMessage(Message* m) { Log::getInstance()->log("VVideoRec", Log::DEBUG, "Message received"); @@ -522,6 +547,41 @@ void VVideoRec::processMessage(Message* m) Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received change audio channel to %i", m->parameter); player->setAudioChannel(m->parameter&0xFFFF,(m->parameter&0xFF0000)>> 16 ); } + else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL) + { + Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received change subtitle channel to %i", m->parameter); + int type=((m->parameter & 0xFF0000)>>16); + switch (type) { + case 0x10: { //dvbsubtitle + player->setSubtitleChannel((m->parameter & 0xFFFF)); + player->turnSubtitlesOn(true); + VTeletextView *vtxt=((Player*)player)->getTeletextDecoder()->getTeletxtView(); + if (vtxt && vtxt->isInSubtitleMode()) { + BoxStack::getInstance()->remove(vtxt); + } + } break; + case 0xFF: { //nosubtitles + + player->turnSubtitlesOn(false); + VTeletextView *vtxt=((Player*)player)->getTeletextDecoder()->getTeletxtView(); + if (vtxt && vtxt->isInSubtitleMode()) { + BoxStack::getInstance()->remove(vtxt); + } + + } break; + case 0x11: { //videotext + player->turnSubtitlesOn(false); + doTeletext(); + ((Player*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF)); + } break; + }; + if (vas) { + BoxStack::getInstance()->update(vas); + } + BoxStack::getInstance()->update(this); + + + } else if (m->message == Message::CHILD_CLOSE) { if (m->from == vas) @@ -570,14 +630,32 @@ void VVideoRec::toggleChopSides() void VVideoRec::doAudioSelector() { bool* availableMpegAudioChannels = player->getDemuxerMpegAudioChannels(); - bool* availableAc3AudioChannels = 0; + bool* availableAc3AudioChannels = NULL; + bool* availableSubtitleChannels = player->getDemuxerSubtitleChannels(); + int *availableTTxtpages = player->getTeletxtSubtitlePages(); int currentAudioChannel = player->getCurrentAudioChannel(); if (Audio::getInstance()->supportsAc3()) { availableAc3AudioChannels = player->getDemuxerAc3AudioChannels(); } + int subtitleChannel=player->getCurrentSubtitleChannel(); + int subtitleType=0x10; + if (!(player)->isSubtitlesOn()) { + if ((player)->getTeletextDecoder()->getTeletxtView() && + (player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode() + ) { + subtitleChannel=(player)->getTeletextDecoder()->getPage(); + subtitleType=0x11; + + } else { + subtitleType=0xFF; //turnedOff + subtitleChannel=0; + } + } + - vas = new VAudioSelector(this, availableMpegAudioChannels, availableAc3AudioChannels, currentAudioChannel, myRec->recInfo); + vas = new VAudioSelector(this, availableMpegAudioChannels, availableAc3AudioChannels, currentAudioChannel,availableSubtitleChannels, availableTTxtpages, + subtitleChannel, subtitleType, myRec->recInfo); vas->setBackgroundColour(barBlue); vas->setPosition(0, barRegion.y - 120); diff --git a/vvideorec.h b/vvideorec.h index 8c89b74..081c88b 100644 --- a/vvideorec.h +++ b/vvideorec.h @@ -59,6 +59,8 @@ class VVideoRec : public Boxx, public TimerReceiver, public OSDReceiver void clearOSD(); void clearOSDArea(UINT posX, UINT posY, UINT width, UINT height); + void doTeletext(); + private: BoxStack* boxstack; VDR* vdr; diff --git a/wjpeg.cc b/wjpeg.cc index b3c2999..bde3d5a 100644 --- a/wjpeg.cc +++ b/wjpeg.cc @@ -22,7 +22,11 @@ #include #include #include +#ifndef WIN32 #include +#else + +#endif #include "i18n.h" @@ -103,11 +107,13 @@ ULONG WindowsResourceJpegReader::initRead(const char *filename) buffer=NULL; size=0; FreeResource(hres); + } ULONG WindowsResourceJpegReader::getSize(){ return (ULONG)size; } #else + #define LocalReader LocalJpegReader class LocalJpegReader: public JpegReader { public: @@ -549,7 +555,7 @@ int WJpeg::init(char* tfileName) delete reader; reader=NULL; owningReader=false; - snprintf(errbuf,200,"unable to open %s",tfileName); + SNPRINTF(errbuf,200,"unable to open %s",tfileName); return 0; } return 1; @@ -575,7 +581,7 @@ void WJpeg::draw() if (drawJpeg(&ctl,sfc,reader,backgroundColour) ) ok=true; } else { - snprintf(errbuf,200,"jpeg reader not initialized"); + SNPRINTF(errbuf,200,"jpeg reader not initialized"); } if (! ok) { drawTextCentre(tr("Jpeg ERROR"), 240, 170, Colour::LIGHTTEXT); diff --git a/wjpeg.h b/wjpeg.h index de3a085..154cfc9 100644 --- a/wjpeg.h +++ b/wjpeg.h @@ -176,7 +176,7 @@ class WJpeg : public Boxx if (xb < 0 || yb < 0 ) { return; } - sfc->drawPixel((UINT)xb,(UINT)yb,c); + sfc->drawPixel((UINT)xb,(UINT)yb,c,true); } /** diff --git a/wselectlist.cc b/wselectlist.cc index baa3005..707932d 100644 --- a/wselectlist.cc +++ b/wselectlist.cc @@ -31,6 +31,7 @@ WSelectList::WSelectList() noLoop = 0; gap = 1; showseloption = true; + darkseloption = false; backgroundColour = Colour::VIEWBACKGROUND; } @@ -116,7 +117,7 @@ void WSelectList::draw() if (i == selectedOption && showseloption) { - rectangle(0, ypos, area.w, fontHeight, Colour::SELECTHIGHLIGHT); + rectangle(0, ypos, area.w, fontHeight, darkseloption ? Colour::SELECTDARKHIGHLIGHT: Colour::SELECTHIGHLIGHT); drawOptionLine(options[i].text, 5, ypos, area.w - 5, Colour::DARKTEXT); } else diff --git a/wselectlist.h b/wselectlist.h index 88d65f0..03ba361 100644 --- a/wselectlist.h +++ b/wselectlist.h @@ -47,6 +47,7 @@ class WSelectList : public Boxx void setNoLoop(); void setShowSelOption(bool set) { showseloption = set; }; + void setDarkSelOption(bool set) { darkseloption = set; }; int addOption(const char* text, ULONG data, int selected); void draw(); void setBackgroundColour(const Colour& colour); @@ -79,7 +80,7 @@ class WSelectList : public Boxx int columns[10]; int numColumns; int noLoop; - bool showseloption; + bool showseloption, darkseloption; UINT gap; Colour backgroundColour; -- 2.39.2