]> git.vomp.tv Git - vompclient.git/blob - vvideolivetv.cc
Fix text corruption on channel list when returning from live TV
[vompclient.git] / vvideolivetv.cc
1 /*
2     Copyright 2007-2008 Chris Tallon
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
21 #include "vvideolivetv.h"
22
23 #include "vchannellist.h"
24 #include "video.h"
25 #include "audio.h"
26 #include "playerlive.h"
27 #include "playerlivetv.h"
28 #include "playerliveradio.h"
29 #include "channel.h"
30 #include "boxstack.h"
31 #include "colour.h"
32 #include "osd.h"
33 #include "command.h"
34 #include "i18n.h"
35 #include "wtextbox.h"
36 #include "remote.h"
37 #include "vaudioselector.h"
38 #include "colour.h"
39 #include "event.h"
40 #include "timers.h"
41 #include "vepg.h"
42 #include "bitmap.h"
43 #include "log.h"
44 #include "vteletextview.h"
45 #include "vepgsummary.h"
46 #include "vepglistadvanced.h"
47 #include "staticartwork.h"
48 #include "demuxer.h"
49
50 #include <sstream>
51
52 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
53 {
54   vdr = VDR::getInstance();
55   boxstack = BoxStack::getInstance();
56   video = Video::getInstance();
57   
58   vas = NULL;
59
60   chanList = tchanList;
61   vchannelList = tvchannelList;
62   numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
63
64   currentChannelIndex = 0;
65   previousChannelIndex = 0;
66   osdChannelIndex = 0;
67   keying = 0;
68   preBuffering = 0;
69
70   playing = false;
71
72   // Convert channel number to index
73   UINT i;
74   for(i = 0; i < chanList->size(); i++)
75   {
76     if ((*chanList)[i]->number == (UINT)initialChannelNumber)
77     {
78       currentChannelIndex = i;
79       osdChannelIndex = i;
80       break;
81     }
82   }
83
84   eventList = NULL;
85
86   videoMode = video->getMode();
87   
88   if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
89   {
90     streamType = VDR::VIDEO;
91     player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
92   }
93   else
94   {
95     streamType = VDR::RADIO;
96     player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
97   }
98   player->init();
99
100   setSize(video->getScreenWidth(), video->getScreenHeight());
101   createBuffer();
102   DrawStyle transparent(0, 0, 0, 0);
103   setBackgroundColour(transparent);
104 #ifdef PAL_WSS
105   dowss = false;
106   char* optionWSS = vdr->configLoad("General", "WSS");
107   if (optionWSS)
108   {
109     if (strstr(optionWSS, "Yes")) dowss = true;
110     delete[] optionWSS;
111   }
112   Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
113
114   if (dowss)
115   {
116     wss.setFormat(video->getFormat());
117     wss.setWide(true);
118     add(&wss);
119     
120     wssRegion.x = 0;
121     wssRegion.y = 6;
122     wssRegion.w = video->getScreenWidth();
123     wssRegion.h = 2;
124   }
125 #endif
126   // This variable is set to true if the user pressed OK to bring the OSD on screen
127   // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
128   okTriggeredOSD = false;
129
130   TVMediaInfo info;
131   info.setChannelLogo(initialChannelNumber);
132   OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
133
134   if (osdv && streamType == VDR::RADIO) {
135           radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
136           radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
137           radioChannelLogo.setVisible(true);
138           radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
139           add(&radioChannelLogo);
140   }
141
142   osdposterbanner.setPosition(20,20);
143   //osdposterbanner.setBackgroundColour(DrawStyle::OSDBACKGROUND);
144   osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
145   osdposterbanner.setVisible(false);
146   add(&osdposterbanner);
147
148
149
150   osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
151   osd.setPosition(0, video->getScreenHeight() - 150);
152   osd.setSize(video->getScreenWidth(), 150);
153   osd.setVisible(false);
154   add(&osd);
155   
156   int channellogomove=0;
157   int boxdiff=166;
158   if (osdv) {
159           //osdChannelLogo.setBackgroundColour(DrawStyle::OSDBACKGROUND);
160           osdChannelLogo.setPosition(30,5);
161           osdChannelLogo.setSize(60,60);
162           osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
163           osd.add(&osdChannelLogo);
164           channellogomove=30-5;
165           boxdiff=145;
166   }
167
168
169   //clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
170   clock.setPosition(osd.getWidth() - 100, 4);
171   clock.setSize(90, 30);
172   osd.add(&clock);
173
174   //osdChanNum.setBackgroundColour(DrawStyle::OSDBACKGROUND);
175   osdChanNum.setPosition(60+channellogomove, 4);
176   osdChanNum.setSize((numberWidth*10) + 22, getFontHeight()+5); // 10 px = width of number chars in font
177   osd.add(&osdChanNum);  
178
179   //osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
180   osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
181   osdChanName.setSize(300, 30);
182   osd.add(&osdChanName);
183   
184   boxRed.setBackgroundColour(DrawStyle::RED);
185   boxRed.setPosition(54+0*boxdiff, 104);
186   boxRed.setSize(18, 16);
187   osd.add(&boxRed);
188
189   boxGreen.setBackgroundColour(DrawStyle::GREEN);
190   boxGreen.setPosition(54+1*boxdiff, 104);
191   boxGreen.setSize(18, 16);
192   osd.add(&boxGreen);
193
194   boxYellow.setBackgroundColour(DrawStyle::YELLOW);
195   boxYellow.setPosition(54+2*boxdiff, 104);
196   boxYellow.setSize(18, 16);
197   osd.add(&boxYellow);
198
199   boxBlue.setBackgroundColour(DrawStyle::BLUE);
200   boxBlue.setPosition(54+3*boxdiff, 104);
201   boxBlue.setSize(18, 16);
202   osd.add(&boxBlue);  
203   
204   //textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
205   textRed.setPosition(boxRed.getX2(), 98);
206   textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
207   textRed.setText(tr("Summary"));
208   osd.add(&textRed);  
209     
210   if (streamType == VDR::VIDEO)
211   {
212     //textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
213     textGreen.setPosition(boxGreen.getX2(), 98);
214     textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
215     textGreen.setText(tr("Audio"));
216     osd.add(&textGreen);  
217   }
218     
219   //textYellow.setBackgroundColour(DrawStyle::OSDBACKGROUND);
220   textYellow.setPosition(boxYellow.getX2(), 98);
221   textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
222   textYellow.setText(tr("Teletext"));
223   osd.add(&textYellow);  
224     
225   //textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
226   textBlue.setPosition(boxBlue.getX2(), 98);
227   textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
228   textBlue.setText(tr("EPG"));
229   osd.add(&textBlue);  
230     
231   //sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
232   sl.setPosition(90, 36);
233   sl.setSize(480, 58);
234   osd.add(&sl);
235   
236   
237
238   bufferBar.setPosition(osd.getWidth() - 90, 70);
239   bufferBar.setSize(40, 20);
240   bufferBar.setVisible(true);
241   osd.add(&bufferBar);
242
243   if (!osdv) {
244           sAspectRatio.setPosition(osd.getWidth() - 90, 40);
245           sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
246           sAspectRatio.setVisible(false);
247           osd.add(&sAspectRatio);
248   
249           sAudioChannels.setPosition(osd.getWidth() - 130, 40);
250           sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
251           sAudioChannels.setVisible(false);
252           osd.add(&sAudioChannels);
253   }
254   
255   if (osdv) {
256           TVMediaInfo ninfo;
257           ninfo.setStaticArtwork(sa_txtoff);
258           txtlogo.setPosition(54+4*boxdiff,104);
259           txtlogo.setSize(22,20);
260           txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
261           osd.add(&txtlogo);
262
263           ninfo.setStaticArtwork(sa_dolbyoff);
264           dolbylogo.setPosition(54+4*boxdiff+15,104);
265           dolbylogo.setSize(22,20);
266           dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
267           osd.add(&dolbylogo);
268
269           ninfo.setStaticArtwork(sa_sd576i);
270           reslogo.setPosition(54+4*boxdiff+30,104);
271           reslogo.setSize(22,20);
272           reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
273           osd.add(&reslogo);
274
275           reslogo.setVisible(false);
276           dolbylogo.setVisible(false);
277           txtlogo.setVisible(false);
278   }
279
280
281   //textUnavailable.setBackgroundColour(DrawStyle::OSDBACKGROUND);
282   textUnavailable.setPosition(60, 30);
283   textUnavailable.setSize(osd.getWidth() - 120, 30);
284   textUnavailable.setText(tr("Channel Unavailable"));
285   textUnavailable.setVisible(false);
286   add(&textUnavailable);
287   
288
289   vdisplay.mode=Fullscreen;
290   vdisplay.fallbackMode=Fullscreen;
291   vdisplay.x=0;
292   vdisplay.y=0;
293   vdisplay.width=0;
294   vdisplay.height=0;
295
296 }
297
298 void VVideoLiveTV::preDelete()
299 {
300   if (playing) stop();
301 }
302
303 VVideoLiveTV::~VVideoLiveTV()
304 {
305   delete player;
306   video->setDefaultAspect();
307   delData();
308   OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
309   if (osdv)
310   {
311           osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
312   }
313 }
314
315 void VVideoLiveTV::delData()
316 {
317   if (eventList)
318   {
319     int eventListSize = eventList->size();
320     for(int i = 0; i < eventListSize; i++)
321     {
322       delete (*eventList)[i];
323     }
324     eventList->clear();
325     delete eventList;
326
327   }
328 }
329
330 int VVideoLiveTV::handleCommand(int command)
331 {
332   switch(command)
333   {
334     case Remote::BACK:
335     {
336       if (osd.getVisible() && !textUnavailable.getVisible())
337       {
338         clearScreen();
339         return 2;
340       }
341       // else drop through to stop
342     }
343     case Remote::STOP:
344     {
345       stop();
346       vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
347       return 4;
348     }
349     
350     // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
351     case Remote::UP:
352     {
353         if (Remote::getInstance()->mayHaveFewButtons()) {
354               if (okTriggeredOSD) doUpDown(false);
355               else doChanUpDown(UP);
356         } else {
357                 doUpDown(false);
358         }
359       return 2;
360     }
361     case Remote::DOWN:
362     {
363       if (Remote::getInstance()->mayHaveFewButtons()) {
364           if (okTriggeredOSD) doUpDown(true);
365           else doChanUpDown(DOWN);
366       } else {
367           doUpDown(true);
368       }
369       return 2;
370     }
371     case Remote::LEFT:
372     {
373       doLeftRight(false);
374       return 2;
375     }
376     case Remote::RIGHT:
377     {
378       doLeftRight(true);
379       return 2;
380     }
381     // Continue new remote only...
382     case Remote::CHANNELUP:
383     {
384       doChanUpDown(UP);
385       return 2;
386     }
387     case Remote::CHANNELDOWN:
388     {
389       doChanUpDown(DOWN);
390       return 2;
391     }
392
393     // END NEW REMOTE ONLY, START OLD REMOTE ONLY
394     
395     // DF_LEFT and DF_RIGHT never get here because they are stolen
396     // by command as vol- and vol+
397     
398     // Old remote. Decide what to do based on whether
399     // OK was pressed - osd shown manually, use up/down for epg nav
400     // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
401     
402     case Remote::DF_UP:
403     {
404       // Old remote, decide what to do based on okTriggeredOSD
405       if (okTriggeredOSD) doUpDown(false);
406       else doChanUpDown(UP);
407       return 2;
408     }
409     case Remote::DF_DOWN:
410     {
411       // Old remote, decide what to do based on okTriggeredOSD
412       if (okTriggeredOSD) doUpDown(true);
413       else doChanUpDown(DOWN);
414       return 2;
415     }
416
417     // END NEW/OLD REMOTE STUFF
418
419     case Remote::PREVCHANNEL:
420     {
421       channelChange(PREVIOUS, 0);
422       osdChannelIndex = currentChannelIndex;
423       displayOSD(true);
424       return 2;
425     }
426     case Remote::OK:
427     {
428       doOK();
429       return 2;
430     }
431     case Remote::RED:
432     case Remote::MENU:
433     {
434       doSummary();
435       return 2;
436     }
437     case Remote::FULL:
438     case Remote::TV:
439     {
440       toggleChopSides();
441       return 2;
442     }
443
444     case Remote::ZERO:
445     case Remote::ONE:
446     case Remote::TWO:
447     case Remote::THREE:
448     case Remote::FOUR:
449     case Remote::FIVE:
450     case Remote::SIX:
451     case Remote::SEVEN:
452     case Remote::EIGHT:
453     case Remote::NINE:
454     {
455       // key in channel number
456       doKey(command);
457       return 2;
458     }
459
460     case Remote::GREEN:
461     {
462       if (streamType == VDR::VIDEO) doAudioSelector();
463       return 2;   
464     }
465     case Remote::YELLOW:
466     {
467       if (streamType ==VDR::VIDEO) 
468       {
469         doTeletext(); //TODO: Add a selector for subtitles or teletext
470       }
471       return 2;
472     }
473     case Remote::GUIDE:
474     case Remote::BLUE:
475     {
476       doEPG();
477       return 2;
478     }
479     case Remote::RECORD:
480       if (streamType == VDR::VIDEO)
481         (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
482       return 2;
483   }
484
485   return 1;
486 }
487
488 void VVideoLiveTV::go()
489 {
490   playing = true;
491   draw();
492   boxstack->update(this);
493
494   setClock();
495   displayOSD(true);
496   
497   player->go(currentChannelIndex);
498 }
499
500 void VVideoLiveTV::stop()
501 {
502   Timers::getInstance()->cancelTimer(this, 1);
503   Timers::getInstance()->cancelTimer(this, 2);
504   player->stop();
505   playing = false;
506 }
507
508 void VVideoLiveTV::doLeftRight(bool right)
509 {
510   if (osd.getVisible())
511   {
512     if (right) osdChannelIndex = upChannel(osdChannelIndex);
513     else       osdChannelIndex = downChannel(osdChannelIndex);
514   }
515   else
516   {
517     osdChannelIndex = currentChannelIndex;
518   }
519   displayOSD(true);
520 }
521
522 void VVideoLiveTV::doUpDown(bool down)
523 {
524   if (osd.getVisible())
525   {
526     sl.draw();
527     
528     displayOSD(false);
529   }
530   else
531   {
532     displayOSD(true);
533   }
534 }
535
536 void VVideoLiveTV::doChanUpDown(int which)
537 {
538   channelChange(OFFSET, which);
539   osdChannelIndex = currentChannelIndex;
540   displayOSD(true);
541 }
542
543 void VVideoLiveTV::doOK()
544 {
545   if (osd.getVisible())
546   {
547     if (keying)
548     {
549       UINT newChannel = 0;
550       for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
551       
552       channelChange(NUMBER, newChannel);
553       osdChannelIndex = currentChannelIndex;
554       displayOSD(true);
555     }
556     else if (osdChannelIndex == currentChannelIndex)
557     {
558       clearScreen();
559     }
560     else
561     {
562       channelChange(INDEX, osdChannelIndex);
563       displayOSD(true);
564     }
565   }
566   else
567   {
568     osdChannelIndex = currentChannelIndex;
569     displayOSD(true);
570     okTriggeredOSD = true;
571   }
572 }
573
574 void VVideoLiveTV::doSummary()
575 {
576         displayOSD(false);
577         Channel* currentChannel = (*chanList)[osdChannelIndex];
578         eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
579         if (!eventList)
580         {
581                 return;
582         }
583         sort(eventList->begin(), eventList->end(), EventSorter());
584
585         if (eventList->size() < 1) return;
586         Event* event = (*eventList)[0];
587         event->loadinfos(currentChannel->number);
588
589         VEpgSummary* vr = new VEpgSummary(event,currentChannel);
590         vr->draw();
591         boxstack->add(vr);
592         boxstack->update(vr);
593
594 }
595
596 void VVideoLiveTV::doKey(int command)
597 {
598   if (!osd.getVisible()) // First key. prep the data
599   {
600     setNowNextData();
601     updatePosterBanner();
602     keying = 0;    
603   }
604
605   int i;
606   for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
607   keyingInput[0] = command;
608   keying++;
609
610   char* keyingString = new char[numberWidth + 1];
611   for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
612   keyingString[numberWidth] = '\0';
613
614   for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
615   
616   if (keying == numberWidth)
617   {
618     UINT newChannel = 0;
619     for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
620     
621     channelChange(NUMBER, newChannel);
622     osdChannelIndex = currentChannelIndex;
623     Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
624     displayOSD(true); // this will put one back if required
625   }
626   else
627   {
628     osdChanNum.setText(keyingString);
629
630     if (!osd.getVisible())
631     {
632       osd.setVisible(true);
633       draw();
634     }
635     else
636     {
637       osdChanNum.draw();
638     }
639     boxstack->update(this, osd.getRegion());
640     Timers::getInstance()->setTimerD(this, 1, 3);  // 3s for keying input
641   }
642   delete[] keyingString;
643 }
644
645 void VVideoLiveTV::doTeletext(bool subtitlemode)
646 {
647   if (streamType !=VDR::VIDEO) return;
648   (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
649   bool exists=true;
650
651   // Cancel keying
652   if (keying)
653   {
654     keying = 0;
655     // and reset the display - this is a copy from setNowNextData
656     char formatChanNum[20];
657     SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
658     osdChanNum.setText(formatChanNum);
659     osdChanName.setText((*chanList)[osdChannelIndex]->name);
660   }
661   (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
662   if (osd.getVisible()) clearScreen();
663   // Draw the teletxt
664   VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
665   if (vtxv==NULL) {
666        vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
667       ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
668       exists=false;
669   }
670   vtxv->setSubtitleMode(subtitlemode);
671   vtxv->draw();
672   draw();
673   
674   if (!exists) {
675       BoxStack::getInstance()->add(vtxv);
676   }
677   BoxStack::getInstance()->update(this);
678   BoxStack::getInstance()->update(vtxv); 
679 }
680
681 void VVideoLiveTV::doAudioSelector()
682 {
683   // If the osd is already visisble there might be a timer for it
684   Timers::getInstance()->cancelTimer(this, 1);
685   //This causes a deadlock with the timertrhread itself is locked
686
687
688   // Cancel keying
689   if (keying)
690   {
691     keying = 0;
692     // and reset the display - this is a copy from setNowNextData
693     char formatChanNum[20];
694     SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
695     osdChanNum.setText(formatChanNum);
696     osdChanName.setText((*chanList)[osdChannelIndex]->name);
697   }
698   int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
699   int subtitleType=0x10;
700   if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
701       if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
702           ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode() 
703           ) {
704               subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
705               subtitleType=0x11;
706           
707       } else {
708           subtitleType=0xFF; //turnedOff
709           subtitleChannel=0;
710       }
711   }
712
713   // Draw the selector
714   vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
715       subtitleType,subtitleChannel,NULL);
716
717   vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
718   vas->setPosition(0, osd.getScreenY() - vas->getHeight());
719   vas->draw();
720
721   // make vas != null and displayOSD will not set a timer or do any boxstack update
722   if (osd.getVisible()) displayOSD(false);
723   else displayOSD(true);
724   draw();
725
726   BoxStack::getInstance()->add(vas);
727   BoxStack::getInstance()->update(this);        
728   BoxStack::getInstance()->update(vas);     
729 }      
730       
731 void VVideoLiveTV::doEPG()
732 {
733   if (osd.getVisible()) clearScreen();
734
735   if (!Command::getInstance()->advMenues()) {
736
737           VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
738           vepg->draw();
739           boxstack->add(vepg);
740           boxstack->update(vepg);
741   } else {
742           Channel* currentChannel = (*chanList)[osdChannelIndex];
743           VEpgListAdvanced  *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
744           vepg->draw();
745           boxstack->add(vepg);
746           boxstack->update(vepg);
747   }
748 }
749
750 void VVideoLiveTV::setNowNextData()
751 {
752   delData();
753   
754   Channel* currentChannel = (*chanList)[osdChannelIndex];
755
756   char formatChanNum[20];
757   SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
758   osdChanNum.setText(formatChanNum);
759   osdChanName.setText(currentChannel->name);
760
761   eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
762
763   if (!eventList)
764   {
765     sl.setText(tr("No channel data available"));
766   }
767   else
768   {
769     sort(eventList->begin(), eventList->end(), EventSorter());
770
771     char tempString[300];
772     char tempString2[300];
773     struct tm btime;
774     Event* event;
775     int eventListSize = eventList->size();
776     std::stringstream string;
777     for(int i = 0; i < eventListSize; i++)
778     {
779       event = (*eventList)[i];
780
781       time_t etime = event->time;
782       LOCALTIME_R(&etime, &btime);
783 #ifndef _MSC_VER
784       strftime(tempString2, 299, "%0H:%0M ", &btime);
785 #else
786       strftime(tempString2, 299, "%H:%M ", &btime);
787 #endif
788       SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
789       string << tempString << "\n";
790     }
791     sl.setText(string.str().c_str());
792   }
793 }
794
795
796
797 void VVideoLiveTV::displayOSD(bool newNowNextData)
798 {
799   PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
800   if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(true);
801   osd.setVisible(true);
802   if (newNowNextData)
803   {
804     setNowNextData();
805     updatePosterBanner();
806     keying = 0;
807   }
808   osd.draw();
809   if (osdposterbanner.getVisible()) osdposterbanner.draw();
810   
811
812   Region  toupdate;
813
814   toupdate=*osd.getRegion();
815
816
817   if (osdposterbanner.getVisible()) {
818           boxstack->update(this);
819   } else {
820           boxstack->update(this, &toupdate);
821   }
822   
823   bool setTimer = true;
824   if (vas) setTimer = false;
825   if (textUnavailable.getVisible()) setTimer = false;
826
827   if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
828 }
829
830 void VVideoLiveTV::clearScreen()
831 {  
832   Timers::getInstance()->cancelTimer(this, 1);
833
834   textUnavailable.setVisible(false);
835   osd.setVisible(false);
836   osdposterbanner.setVisible(false);
837
838   okTriggeredOSD = false;
839
840   draw();
841   boxstack->update(this);
842
843   PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
844   if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
845 }
846
847 void VVideoLiveTV::showUnavailable()
848 {
849   Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");  
850   textUnavailable.setVisible(true);
851   textUnavailable.draw();
852   
853   if (!osd.getVisible()) displayOSD(true);
854
855   boxstack->update(this, textUnavailable.getRegion());  
856 }
857
858 void VVideoLiveTV::setClock()
859 {
860   char timeString[20];
861   time_t t;
862   time(&t);
863   struct tm tms;
864   LOCALTIME_R(&t, &tms);
865   strftime(timeString, 19, "%H:%M", &tms);
866   clock.setText(timeString);
867
868   time_t dt = 60 - (t % 60);  // seconds to the next minute
869   if (dt == 0) dt = 60; // advance a whole minute if necessary
870   dt += t;  // get a time_t value for it rather than using duration
871   // (so it will occur at the actual second and not second and a half)
872
873   Timers::getInstance()->setTimerT(this, 2, dt);
874 }
875
876 void VVideoLiveTV::timercall(int ref)
877 {
878   if (ref == 1)
879   {
880     if (keying)
881     {
882          Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start."); 
883       UINT newChannel = 0;
884       for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
885       
886       Message* m = new Message();
887       m->message = Message::CHANNEL_CHANGE;
888       m->to = this;
889           m->parameter.num = newChannel;
890       m->tag = 1; // signal to call displayOSD();
891       Command::getInstance()->postMessageFromOuterSpace(m);
892       Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end."); 
893     }
894     else
895     {
896         Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start."); 
897       // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
898       if (preBuffering < 100)
899       {
900         Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");  
901         Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
902         return;
903       }
904       bool osdpbvisible=osdposterbanner.getVisible();
905       Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1."); 
906       osd.setVisible(false);
907       osdposterbanner.setVisible(false);
908       okTriggeredOSD = false;
909       Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2."); 
910       draw();
911       Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4."); 
912       if (osdpbvisible) boxstack->update(this);
913       else  boxstack->update(this, osd.getRegion());
914
915       Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3."); 
916           PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
917           if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
918       Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end."); 
919     }
920   }
921   else if (ref == 2)
922   {
923       Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2  start."); 
924     setClock();
925     if (osd.getVisible())
926     {
927       clock.draw();
928       boxstack->update(this, osd.getRegion());
929     }
930     Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end."); 
931   }
932 }
933
934 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
935 {
936   UINT newChannel = 0;
937   if (streamType ==VDR::VIDEO) {
938           VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
939           if (vtxt ) {
940                   BoxStack::getInstance()->remove(vtxt);
941
942           }
943   }
944   if (changeType == INDEX)
945   {
946     newChannel = newData;
947   }
948   else if (changeType == NUMBER)
949   {
950     UINT i;
951     for(i = 0; i < chanList->size(); i++)
952     {
953       if ((*chanList)[i]->number == (UINT)newData)
954       {
955         newChannel = i;
956         break;
957       }
958     }
959
960     if (i == chanList->size())
961     {
962       // no such channel
963       return false;
964     }
965   }
966   else if (changeType == OFFSET)
967   {
968     if (newData == UP) newChannel = upChannel(currentChannelIndex);
969     else newChannel = downChannel(currentChannelIndex);
970   }
971   else if (changeType == PREVIOUS)
972   {
973     newChannel = previousChannelIndex;
974   }
975   else
976   {
977     return false; // bad input
978   }
979
980   if (newChannel == currentChannelIndex) return true;
981
982   previousChannelIndex = currentChannelIndex;
983   currentChannelIndex = newChannel;
984   
985   preBuffering = 0;
986   
987   Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
988   player->setChannel(currentChannelIndex);
989   Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
990
991   // Blank out the symbols
992   OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
993
994   bufferBar.setPercent(0);
995   
996   if (!osdv) {
997           sAudioChannels.setVisible(false);
998           sAspectRatio.setVisible(false);
999   } else {
1000           reslogo.setVisible(false);
1001           dolbylogo.setVisible(false);
1002           txtlogo.setVisible(false);
1003   }
1004
1005   // Remove other stuff
1006   if (textUnavailable.getVisible())
1007   {
1008     textUnavailable.setVisible(false);
1009     
1010   }
1011
1012   if (osdv) {
1013           TVMediaInfo info;
1014           Channel* currentChannel = (*chanList)[currentChannelIndex];
1015           if (currentChannel) {
1016                   info.setChannelLogo(currentChannel->number);
1017                   if (streamType == VDR::RADIO) {
1018                           radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1019                           radioChannelLogo.setVisible(true);
1020                   }
1021                   osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1022
1023           }
1024   }
1025
1026   draw();
1027   BoxStack::getInstance()->update(this);
1028   
1029   return true;
1030 }
1031
1032 void VVideoLiveTV::processMessage(Message* m)
1033 {
1034   if (m->message == Message::MOUSE_LBDOWN)
1035   {
1036     //check if press is outside this view! then simulate cancel
1037         int x = (m->parameter.num >> 16) - osd.getScreenX();
1038         int y = (m->parameter.num & 0xFFFF) - osd.getScreenY();
1039     if (osd.getVisible()) {
1040     
1041         if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
1042             (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y )) {
1043             BoxStack::getInstance()->handleCommand(Remote::RED);
1044         } else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
1045             (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y)){
1046             BoxStack::getInstance()->handleCommand(Remote::GREEN);
1047         } else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
1048             (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
1049             BoxStack::getInstance()->handleCommand(Remote::YELLOW);
1050         } else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
1051             (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y )){
1052             BoxStack::getInstance()->handleCommand(Remote::BLUE);
1053         } else {
1054             BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1055         }
1056
1057     } else {
1058         BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1059     }
1060   }
1061   else if (m->message == Message::CHANNEL_CHANGE)
1062   {
1063         channelChange(NUMBER, m->parameter.num);
1064     osdChannelIndex = currentChannelIndex;
1065     if (m->tag == 1) displayOSD(true);
1066   }
1067   else if (m->message == Message::CHILD_CLOSE)
1068   {
1069     if (m->from == vas)
1070     {
1071       vas = NULL;
1072       displayOSD(false);
1073     }
1074   }
1075   else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1076   {
1077         Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter.num);
1078         player->setAudioChannel((m->parameter.num & 0xFFFF), (m->parameter.num & 0xFF0000) >> 16, (m->parameter.num & 0xFF000000) >> 24);
1079   } 
1080   else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1081   {
1082     if (streamType !=VDR::VIDEO) return;
1083           Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter.num);
1084       int type=((m->parameter.num & 0xFF0000)>>16);
1085       switch (type) {
1086       case 0x10: { //dvbsubtitle
1087           if (streamType == VDR::VIDEO){
1088               player->setSubtitleChannel((m->parameter.num & 0xFFFF));
1089               (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1090               VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1091               if (vtxt && vtxt->isInSubtitleMode()) {
1092                   BoxStack::getInstance()->remove(vtxt);
1093               }
1094           }
1095                  } break;
1096       case 0xFF: { //nosubtitles
1097           if (streamType == VDR::VIDEO){
1098               (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1099               VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1100               if (vtxt && vtxt->isInSubtitleMode()) {
1101                   BoxStack::getInstance()->remove(vtxt);
1102               }  
1103           }
1104                  } break;
1105       case 0x11: { //videotext
1106           (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1107           doTeletext(true);
1108           ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter.num & 0xFFFF));
1109                  } break;
1110       };
1111       if (vas) {
1112         BoxStack::getInstance()->update(vas);
1113         //BoxStack::getInstance()->update(&osd); //eveil error
1114       }
1115       BoxStack::getInstance()->update(this, osd.getRegion());
1116
1117       
1118   }
1119   else if (m->message == Message::PLAYER_EVENT)
1120   {
1121         switch (m->parameter.num)
1122     {
1123       case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1124       {
1125         Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1126         Command::getInstance()->connectionLost();
1127         break;
1128       }
1129       
1130       case PlayerLiveTV::STREAM_END:
1131       {
1132         // Message comes from playerlivetv through master mutex, so can do anything here
1133         showUnavailable();        
1134         break;
1135       }
1136       
1137       case PlayerLiveTV::ASPECT43:
1138       {
1139 #ifdef PAL_WSS
1140         if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1141         {
1142           Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
1143           wss.setWide(false);
1144           wss.draw();
1145           BoxStack::getInstance()->update(this, &wssRegion);
1146         }
1147 #endif
1148         
1149         OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1150         if (osdv)
1151         {
1152           osdv->updateBackgroundColor(DrawStyle::BLACK);
1153         }
1154
1155         sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1156         sAspectRatio.setVisible(true);
1157         
1158         if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1159         {
1160           osd.draw();
1161           BoxStack::getInstance()->update(this, osd.getRegion());
1162         }
1163         
1164         break;
1165       }
1166       case PlayerLiveTV::ASPECT169:
1167       {
1168 #ifdef PAL_WSS
1169         if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1170         {
1171           Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
1172           wss.setWide(true);
1173           wss.draw();
1174           BoxStack::getInstance()->update(this, &wssRegion);
1175         }
1176 #endif
1177         
1178         sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1179         sAspectRatio.setVisible(true);
1180
1181         OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1182         if (osdv)
1183         {
1184           osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
1185         }
1186
1187
1188         if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1189         {
1190           osd.draw();
1191           BoxStack::getInstance()->update(this, osd.getRegion());
1192         }
1193                 
1194         break;
1195       }
1196       case PlayerLiveTV::PREBUFFERING:
1197       {
1198         preBuffering = m->tag;
1199         Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1200         bufferBar.setPercent(preBuffering);
1201
1202         if (osd.getVisible())
1203         {
1204           bufferBar.setVisible(true);
1205           bufferBar.draw();
1206           Region r;
1207           bufferBar.getRootBoxRegion(&r);                       ///////// FIXME !!!
1208           BoxStack::getInstance()->update(this, &r);
1209
1210           if (preBuffering == 100)
1211           {
1212             doAudioChannelSymbol();
1213           }
1214         }
1215       }
1216     }
1217   }
1218 #ifdef VOMP_PLATTFORM_MVP
1219 // See vepg.cc ~ line 480
1220   else if (m->message == Message::HACK_MVP_RETURN_FROM_QUARTER)
1221   {
1222     video->setMode(videoMode);
1223   }
1224 #endif
1225 }
1226
1227 void VVideoLiveTV::doAudioChannelSymbol()
1228 {
1229   OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1230   // get the doobery
1231   Channel* currentChannel = (*chanList)[osdChannelIndex];
1232     
1233   bool multiAudio = false;
1234   if (Audio::getInstance()->supportsAc3()) {
1235           if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1236   }
1237   if (currentChannel->numAPids > 1) multiAudio = true;
1238   
1239   // draw the doobery
1240   if (!osdv) {
1241           if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1242           else            sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1243           sAudioChannels.setVisible(true);
1244   }
1245   if (osdv)
1246   {
1247           dolbylogo.setVisible(true);
1248           txtlogo.setVisible(true);
1249           TVMediaInfo info;
1250           if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
1251           else info.setStaticArtwork(sa_txtoff);
1252           txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
1253
1254
1255           if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
1256                   info.setStaticArtwork(sa_dolbyon);
1257           else info.setStaticArtwork(sa_dolbyoff);
1258           dolbylogo.setTVMedia(info, WTVMedia::ZoomVertical);
1259
1260          Demuxer* demux=Demuxer::getInstance();
1261          if (demux) {
1262                  int vertical_size=demux->getVerticalSize();
1263                  Log::getInstance()->log("VVideoRec", Log::DEBUG, "TVMedia vertical size %d", vertical_size);
1264                  reslogo.setVisible(true);
1265                  switch (vertical_size) {
1266                  case 576:
1267                          info.setStaticArtwork(sa_sd576i);
1268                          reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1269                  case 720:
1270                          info.setStaticArtwork(sa_hd720p);
1271                          reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1272                  case 1080:
1273                          info.setStaticArtwork(sa_hd1080i);
1274                          reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1275                  default: // we assume sd
1276                          reslogo.setVisible(false);
1277                  };
1278
1279          } else {
1280                  reslogo.setVisible(false);
1281          }
1282
1283
1284   }
1285   
1286   if (osd.getVisible())
1287   {
1288     sAudioChannels.draw();
1289     Region r;
1290     sAudioChannels.getRootBoxRegion(&r);                       ///////// FIXME !!!
1291     // Fix this n'all.
1292     r.w = 32;
1293     r.h = 16;
1294     BoxStack::getInstance()->update(this, &r);
1295   }
1296 }
1297
1298 UINT VVideoLiveTV::upChannel(UINT index)
1299 {
1300   if (index == (chanList->size() - 1)) // at the end
1301     return 0; // so go to start
1302   else
1303     return index + 1;
1304 }
1305
1306 UINT VVideoLiveTV::downChannel(UINT index)
1307 {
1308   if (index == 0) // at the start
1309     return chanList->size() - 1; // so go to end
1310   else
1311     return index - 1;
1312 }
1313
1314 void VVideoLiveTV::toggleChopSides()
1315 {
1316   if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1317
1318   if (videoMode == Video::NORMAL)
1319   {
1320     videoMode = Video::LETTERBOX;
1321     video->setMode(Video::LETTERBOX);
1322   }
1323   else
1324   {
1325     videoMode = Video::NORMAL;
1326     video->setMode(Video::NORMAL);
1327   }
1328 }
1329
1330 void VVideoLiveTV::updatePosterBanner()
1331 {
1332         OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1333         if (!osdv) {
1334                 osdposterbanner.setVisible(false);
1335                 return;
1336         }
1337         Event* toShow = NULL;
1338         if (eventList && eventList->size()) {
1339                 toShow = (*eventList)[0];
1340                 Channel* currentChannel = (*chanList)[osdChannelIndex];
1341                 toShow->loadinfos(currentChannel->number);
1342         }
1343
1344         if (toShow)
1345         {
1346                 TVMedia poster;
1347                 poster.height=0;
1348                 bool posterscale=true;
1349                 if (toShow->movieInfo) {
1350                         poster=toShow->movieInfo->poster;
1351                 }
1352                 if (toShow->seriesInfo) {
1353                         if (toShow->seriesInfo->banners.size()) {
1354                                 poster=toShow->seriesInfo->banners[0];
1355                                 posterscale=false;
1356                         } else if (toShow->seriesInfo->seasonposter.height) {
1357                                 poster=toShow->seriesInfo->seasonposter;
1358                         } else if (toShow->seriesInfo->posters.size()) {
1359                                 poster=toShow->seriesInfo->posters[0];
1360                         }
1361                 }
1362                 if (poster.height) {
1363                         osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1364                         osdposterbanner.setVisible(true);
1365                 } else {
1366                         osdposterbanner.setVisible(false);
1367                 }
1368         } else {
1369                 osdposterbanner.setVisible(false);
1370         }
1371
1372 }
1373
1374
1375 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1376 {
1377   drawBitmap(posX, posY, bm,region);
1378   Region r;
1379   r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1380   boxstack->update(this, &r);
1381 }
1382
1383 void VVideoLiveTV::clearOSD()
1384 {
1385   rectangle(area, DrawStyle(0,0,0,0));
1386   boxstack->update(this, &area);
1387 }
1388
1389 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1390 {
1391   Region r;
1392   r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1393   //now convert to our display
1394   float scalex=720.f/((float) (region.framewidth+1));
1395   float scaley=576.f/((float) (region.frameheight+1));
1396   r.x = (UINT)floor(scalex*((float)r.x));
1397   r.y = (UINT)floor(scaley*((float)r.y));
1398   r.w = (UINT)(ceil(scalex*((float)r.w))+1.f);
1399   r.h = (UINT)(ceil(scaley*((float)r.h))+1.f);
1400   rectangle(r, DrawStyle(0,0,0,0));
1401   boxstack->update(this, &r);
1402 }