]> git.vomp.tv Git - vompclient.git/blob - vteletextview.cc
Rewritten vomp discovery protocol
[vompclient.git] / vteletextview.cc
1 /*
2     Copyright 2005-2008 Chris Tallon, Marten Richter
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20 #include <math.h>
21 #include "vteletextview.h"
22 #include "video.h"
23 #include "timers.h"
24 #include "boxstack.h"
25 #include "remote.h"
26 #include "teletxt/txtfont.h"
27
28 unsigned int interpol_table_fac1[16][22];
29 unsigned int interpol_table_fac2[16][22];
30 unsigned int interpol_table_fac3[16][22];
31 unsigned int interpol_table_fac4[16][22];
32 int interpol_lowbit[16];
33 int interpol_upbit[16];
34 int interpol_lowline[22];
35 int interpol_upline[22];
36
37 void initpol_tables(){
38     int charsizex;
39     int charsizey;
40     charsizex=16;
41     if (Video::getInstance()->getFormat() == Video::PAL)
42     { 
43         charsizey=22;
44     } else {
45         charsizey=18;
46     }
47     int ttcharsizex=12;
48     int ttcharsizey=10;
49     for (int py=0;py<charsizey;py++) {
50         float fposy=((float)(ttcharsizey))/((float)(charsizey))*((float)py);
51         float yweight=fposy-floor(fposy);
52         float yinvweight=1.-yweight;
53         interpol_upline[py]=min((unsigned int)ceil(fposy),9);
54         interpol_lowline[py]=max((unsigned int)floor(fposy),0);
55         for (int px=0;px<charsizex;px++) {
56             float fposx=((float)(ttcharsizex))/((float)(charsizex))*((float)px);
57             float xweight=fposx-floor(fposx);
58             float xinvweight=1.-xweight;
59             interpol_upbit[px]= (min((unsigned int)ceil(fposx),11));
60             interpol_lowbit[px]= (max((unsigned int)floor(fposx),0));
61
62             interpol_table_fac1[px][py]=xweight*yweight*256.;
63             interpol_table_fac2[px][py]=xinvweight*yweight*256.;
64             interpol_table_fac3[px][py]=xweight*yinvweight*256.;
65             interpol_table_fac4[px][py]=xinvweight*yinvweight*256.;
66
67         }
68     }
69 }
70
71 VTeletextView::VTeletextView(TeletextDecoderVBIEBU* TTdecoder,Boxx* playerview)
72 {   
73     ttdecoder=TTdecoder;
74     pv=playerview;
75     subtitlemode=false;
76     initpol_tables();
77     
78     
79     if (Video::getInstance()->getFormat() == Video::PAL)
80     { 
81         //setSize(680, 550);
82         setSize(680,22); //Only first line
83         setPosition(40, 26);
84     }
85     else
86     {
87         setPosition(40, 30);
88         //setSize(680, 450);
89         setSize(680,18);//only first line
90     }
91     createBuffer();
92     keyindigit=1;
93     page=0x100;
94     
95 }
96
97 VTeletextView::~VTeletextView ()
98 {
99     // Make sure the timer is deleted
100   pv->draw();
101   BoxStack::getInstance()->update(pv);
102   Timers::getInstance()->cancelTimer(this, 1);
103   ttdecoder->unRegisterTeletextView(this);
104     
105 }
106
107 void VTeletextView::draw(bool completedraw, bool onlyfirstline)
108 {
109     Boxx::draw();
110     int x,y;
111     
112     for (y=0;y<25;y++) {
113         for (x=0;x<40;x++) {
114             if (ttdecoder->isDirty(x,y) || completedraw) {
115                 cTeletextChar c=ttdecoder->getChar(x,y);
116                 c.SetDirty(false);
117                 //Skip Blinking and conceal
118                 drawChar(x,y,c);
119                 ttdecoder->setChar(x,y,c);
120             }
121         }
122         if (onlyfirstline) break;
123     }
124    
125     
126 }
127
128 Colour VTeletextView::enumTeletextColorToCoulour(enumTeletextColor ttcol)
129 {
130     switch (ttcol) {
131         case ttcBlack:
132             return Colour(0,0,0);
133         case ttcRed:
134             return Colour(255,0,0);
135         case ttcGreen:
136             return Colour(0,255,0);
137         case ttcYellow:
138             return Colour(255,255,0);
139         case ttcBlue:
140             return Colour(0,0,255);
141         case ttcMagenta:
142             return Colour(255,0,255);
143         case ttcCyan:
144             return Colour(0,255,255);
145         case ttcWhite:
146             return Colour(255,255,255);
147         case ttcTransparent:
148             return Colour(0,0,0,0);
149         case ttcHalfRed:
150             return Colour(127,0,0);
151         case ttcHalfGreen:
152             return Colour(0,127,0);
153         case ttcHalfYellow:
154             return Colour(127,127,0);
155         case ttcHalfBlue:
156             return Colour(0,0,127);
157         case ttcHalfMagenta:
158             return Colour(127,0,127);
159         case ttcHalfCyan:
160             return Colour(0,127,127);
161         case ttcGrey:
162             return Colour(127,127,127);
163         default:
164             return Colour(0,0,0);
165     };
166 }
167
168 //Next function inspired by osdteletext plugin
169 void VTeletextView::drawChar(int x, int y, cTeletextChar c)
170 {
171     unsigned int buffer [10];
172     unsigned int * charmap=GetFontChar(c,buffer);
173     if (!charmap) { //invalid char
174         memset(&buffer,0,10);
175         charmap=buffer;
176     } 
177     enumTeletextColor ttforegcolour=c.GetFGColor();
178     enumTeletextColor ttbackgcolour=c.GetBGColor();
179     if (c.GetBoxedOut()) {
180         ttforegcolour=ttcTransparent;
181         ttbackgcolour=ttcTransparent;
182     }
183     int charsizex;
184     int charsizey;
185     charsizex=16;
186     bool firstline=false;
187     if (y==0) firstline=true;
188     if (Video::getInstance()->getFormat() == Video::PAL)
189     { 
190         charsizey=22;
191     } else {
192         charsizey=18;
193     }
194     int ttcharsizex=12;
195     int ttcharsizey=10;
196     int screenposx=charsizex*x; //12*40= 480 250
197     int screenposy=y*charsizey;
198     Boxx* drawtarget=this;
199     if (!firstline) {
200   
201         drawtarget=pv;
202         screenposy+=this->getScreenY();
203         screenposx+=this->getScreenX();
204
205     }
206
207     Colour fgcharcl=enumTeletextColorToCoulour(ttforegcolour);
208     Colour bgcharcl=enumTeletextColorToCoulour(ttbackgcolour);
209
210     drawtarget->startFastDraw();
211     for (int py=0;py<charsizey;py++) {
212         int upperbitline=charmap[interpol_upline[py]];
213         int lowerbitline=charmap[interpol_lowline[py]];
214         for (int px=0;px<charsizex;px++) {
215             int upperbit= interpol_upbit[px];
216             int lowerbit= interpol_lowbit[px];
217             Colour uuc=( upperbitline &(0x8000>>upperbit)) ? fgcharcl: bgcharcl;
218             Colour ulc=( upperbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl;
219             Colour luc=( lowerbitline &(0x8000>>upperbit)) ? fgcharcl: bgcharcl;
220             Colour llc=( lowerbitline &(0x8000>>lowerbit)) ? fgcharcl: bgcharcl;
221             unsigned int fac1,fac2,fac3,fac4;
222             fac1=interpol_table_fac1[px][py];
223             fac2=interpol_table_fac2[px][py];
224             fac3=interpol_table_fac3[px][py];
225             fac4=interpol_table_fac4[px][py];
226          
227             Colour res((uuc.red*fac1+ulc.red*fac2+luc.red*fac3+llc.red*fac4)/256,
228                 (uuc.green*fac1+ulc.green*fac2+luc.green*fac3+llc.green*fac4)/256,
229                 (uuc.blue*fac1+ulc.blue*fac2+luc.blue*fac3+llc.blue*fac4)/256,
230                 (uuc.alpha*fac1+ulc.alpha*fac2+luc.alpha*fac3+llc.alpha*fac4)/256); //if this is too slow make a table
231             drawtarget->drawPixelAlpha(screenposx+px,screenposy+py,res, true);
232         }
233     }
234
235    
236     drawtarget->endFastDraw();
237
238
239 }
240
241 int VTeletextView::handleCommand(int command) {
242     if (subtitlemode) return 0; //Ok we are in  subtitle mode, we are a slave of the player
243     switch (command) {
244     case Remote::OK:
245         return 2;
246     case Remote::BACK:
247         return 4;
248      case Remote::ZERO:
249     case Remote::ONE:
250     case Remote::TWO:
251     case Remote::THREE:
252     case Remote::FOUR:
253     case Remote::FIVE:
254     case Remote::SIX:
255     case Remote::SEVEN:
256     case Remote::EIGHT:
257     case Remote::NINE:
258     {
259       // key in teletext page
260       doKey(command);
261       return 2;
262     }
263     };
264
265     return 0;
266     
267 }
268
269 void VTeletextView::doKey(int command)
270 {
271     char pagenums[3];
272     if (keyindigit==1){
273         if (command==9) return; //not allowed
274         page=command<<8;
275         pagenums[0]=command+ 48;
276         pagenums[1]='-';
277         pagenums[2]='-';
278         keyindigit++;
279     } else if (keyindigit==2) {
280         page|=command<<4;
281         pagenums[0]=48+((page &0xF00)>>8);
282         pagenums[1]=command+ 48;
283         pagenums[2]='-';
284         keyindigit++;
285     } else if (keyindigit==3) {
286         page|=command;
287         pagenums[0]=48+((page &0xF00)>>8);
288         pagenums[1]=48+((page &0x0F0)>>4);
289         pagenums[2]=48+command;
290         keyindigit=1;
291         ttdecoder->setPage(page);
292     }
293     ttdecoder->setKeyinDigits(pagenums,true);
294     Region toupdate;
295     toupdate.w=16*40;
296     if (Video::getInstance()->getFormat() == Video::PAL) {
297         toupdate.h=22;
298         
299      } else {
300         toupdate.h=18;
301         
302       }
303      toupdate.x=0;
304      toupdate.y=0;
305             
306      draw(false,true);
307      BoxStack::getInstance()->update(this,&toupdate);
308
309 }
310
311 void VTeletextView::timercall(int clientReference)
312 {
313     
314 }
315
316 void VTeletextView::processMessage(Message* m)
317 {
318     if (m->message == Message::TELETEXTUPDATE)
319     {
320         draw(false,false);
321         BoxStack::getInstance()->update(this);
322         BoxStack::getInstance()->update(pv);
323
324     } else if (m->message == Message::TELETEXTUPDATEFIRSTLINE) 
325     {
326         Region toupdate;
327         toupdate.w=16*40;
328         if (Video::getInstance()->getFormat() == Video::PAL) {
329             toupdate.h=22;
330             
331         } else {
332             toupdate.h=18;
333             
334         }
335         toupdate.x=0;
336         toupdate.y=0;
337
338
339             
340         draw(false,true);
341         BoxStack::getInstance()->update(this,&toupdate);
342
343     }
344 }
345
346