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