2 Copyright 2007-2008 Chris Tallon
4 This file is part of VOMP.
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.
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.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
22 #include "vchannellist.h"
25 #include "playerlive.h"
26 #include "playervideolive.h"
27 #include "playerliveradio.h"
37 #include "vaudioselector.h"
43 #include "vteletextview.h"
44 #include "vepgsummary.h"
45 #include "vepglistadvanced.h"
46 #include "staticartwork.h"
48 #include "messagequeue.h"
50 #include "vvideolivetv.h"
53 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
55 vdr = VDR::getInstance();
56 boxstack = BoxStack::getInstance();
57 video = Video::getInstance();
62 vchannelList = tvchannelList;
63 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
65 currentChannelIndex = 0;
66 previousChannelIndex = 0;
73 // Convert channel number to index
75 for(i = 0; i < chanList->size(); i++)
77 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
79 currentChannelIndex = i;
87 videoMode = video->getMode();
89 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
91 streamType = VDR::VIDEO;
92 player = new PlayerVideoLive(Command::getInstance(), this, this, chanList);
96 streamType = VDR::RADIO;
97 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
101 setSize(video->getScreenWidth(), video->getScreenHeight());
103 DrawStyle transparent(0, 0, 0, 0);
104 setBackgroundColour(transparent);
106 OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
109 osdv->updateBackgroundColor(DrawStyle::BLACK);
112 // This variable is set to true if the user pressed OK to bring the OSD on screen
113 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
114 okTriggeredOSD = false;
117 info.setChannelLogo(initialChannelNumber);
119 if (osdv && streamType == VDR::RADIO) {
120 radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
121 radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
122 radioChannelLogo.setVisible(true);
123 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
124 add(&radioChannelLogo);
127 osdposterbanner.setPosition(20,20);
128 //osdposterbanner.setBackgroundColour(DrawStyle::OSDBACKGROUND);
129 osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
130 osdposterbanner.setVisible(false);
131 add(&osdposterbanner);
133 osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
134 osd.setPosition(0, video->getScreenHeight() - 150);
135 osd.setSize(video->getScreenWidth(), 150);
136 osd.setVisible(false);
139 int channellogomove=0;
143 //osdChannelLogo.setBackgroundColour(DrawStyle::OSDBACKGROUND);
144 osdChannelLogo.setPosition(30,5);
145 osdChannelLogo.setSize(60,60);
146 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
147 osd.add(&osdChannelLogo);
148 channellogomove = 30-5;
152 //clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
153 clock.setPosition(osd.getWidth() - 100, 4);
154 clock.setSize(90, 30);
157 //osdChanNum.setBackgroundColour(DrawStyle::OSDBACKGROUND);
158 osdChanNum.setPosition(60 + channellogomove, 4);
159 osdChanNum.setSize((numberWidth * 10) + 22, getFontHeight() + 5); // 10 px = width of number chars in font
160 osd.add(&osdChanNum);
162 //osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
163 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
164 osdChanName.setSize(300, 30);
165 osd.add(&osdChanName);
167 boxRed.setBackgroundColour(DrawStyle::RED);
168 boxRed.setPosition(54+0*boxdiff, 104);
169 boxRed.setSize(18, 16);
172 boxGreen.setBackgroundColour(DrawStyle::GREEN);
173 boxGreen.setPosition(54+1*boxdiff, 104);
174 boxGreen.setSize(18, 16);
177 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
178 boxYellow.setPosition(54+2*boxdiff, 104);
179 boxYellow.setSize(18, 16);
182 boxBlue.setBackgroundColour(DrawStyle::BLUE);
183 boxBlue.setPosition(54+3*boxdiff, 104);
184 boxBlue.setSize(18, 16);
187 //textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
188 textRed.setPosition(boxRed.getX2(), 98);
189 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
190 textRed.setText(tr("Summary"));
193 if (streamType == VDR::VIDEO)
195 //textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
196 textGreen.setPosition(boxGreen.getX2(), 98);
197 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
198 textGreen.setText(tr("Audio"));
202 //textYellow.setBackgroundColour(DrawStyle::OSDBACKGROUND);
203 textYellow.setPosition(boxYellow.getX2(), 98);
204 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
205 textYellow.setText(tr("Teletext"));
206 osd.add(&textYellow);
208 //textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
209 textBlue.setPosition(boxBlue.getX2(), 98);
210 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
211 textBlue.setText(tr("EPG"));
214 //sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
215 sl.setPosition(90, 36);
219 bufferBar.setPosition(osd.getWidth() - 90, 70);
220 bufferBar.setSize(40, 20);
221 bufferBar.setVisible(true);
226 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
227 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
228 sAspectRatio.setVisible(false);
229 osd.add(&sAspectRatio);
231 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
232 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
233 sAudioChannels.setVisible(false);
234 osd.add(&sAudioChannels);
240 ninfo.setStaticArtwork(sa_txtoff);
241 txtlogo.setPosition(54+4*boxdiff,104);
242 txtlogo.setSize(22,20);
243 txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
246 ninfo.setStaticArtwork(sa_dolbyoff);
247 dolbylogo.setPosition(54+4*boxdiff+15,104);
248 dolbylogo.setSize(22,20);
249 dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
252 ninfo.setStaticArtwork(sa_sd576i);
253 reslogo.setPosition(54+4*boxdiff+30,104);
254 reslogo.setSize(22,20);
255 reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
258 reslogo.setVisible(false);
259 dolbylogo.setVisible(false);
260 txtlogo.setVisible(false);
263 //textUnavailable.setBackgroundColour(DrawStyle::OSDBACKGROUND);
264 textUnavailable.setPosition(60, 30);
265 textUnavailable.setSize(osd.getWidth() - 120, 30);
266 textUnavailable.setText(tr("Channel Unavailable"));
267 textUnavailable.setVisible(false);
268 add(&textUnavailable);
270 vdisplay.mode = Fullscreen;
271 vdisplay.fallbackMode = Fullscreen;
278 void VVideoLiveTV::preDelete()
283 VVideoLiveTV::~VVideoLiveTV()
286 video->setDefaultAspect();
288 OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
291 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
295 void VVideoLiveTV::delData()
299 int eventListSize = eventList->size();
300 for(int i = 0; i < eventListSize; i++)
302 delete (*eventList)[i];
309 int VVideoLiveTV::handleCommand(int command)
315 if (osd.getVisible() && !textUnavailable.getVisible())
320 // else drop through to stop
326 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
330 // navigate EPG, bring it onscreen if it's not there
333 if (InputMan::getInstance()->mayHaveFewButtons())
335 if (okTriggeredOSD) doUpDown(false);
336 else doChanUpDown(UP);
346 if (InputMan::getInstance()->mayHaveFewButtons())
348 if (okTriggeredOSD) doUpDown(true);
349 else doChanUpDown(DOWN);
367 case Input::CHANNELUP:
372 case Input::CHANNELDOWN:
377 case Input::PREVCHANNEL:
379 channelChange(PREVIOUS, 0);
380 osdChannelIndex = currentChannelIndex;
413 // key in channel number
420 if (streamType == VDR::VIDEO) doAudioSelector();
425 if (streamType ==VDR::VIDEO)
427 doTeletext(); //TODO: Add a selector for subtitles or teletext
438 if (streamType == VDR::VIDEO)
439 (static_cast<PlayerVideoLive*>(player))->toggleSubtitles();
446 void VVideoLiveTV::go()
450 boxstack->update(this);
455 player->go(currentChannelIndex);
458 void VVideoLiveTV::stop()
460 Timers::getInstance()->cancelTimer(this, 1);
461 Timers::getInstance()->cancelTimer(this, 2);
466 void VVideoLiveTV::doLeftRight(bool right)
468 if (osd.getVisible())
470 if (right) osdChannelIndex = upChannel(osdChannelIndex);
471 else osdChannelIndex = downChannel(osdChannelIndex);
475 osdChannelIndex = currentChannelIndex;
480 void VVideoLiveTV::doUpDown(bool down)
482 if (osd.getVisible())
494 void VVideoLiveTV::doChanUpDown(int which)
496 channelChange(OFFSET, which);
497 osdChannelIndex = currentChannelIndex;
501 void VVideoLiveTV::doOK()
503 if (osd.getVisible())
508 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
510 channelChange(NUMBER, newChannel);
511 osdChannelIndex = currentChannelIndex;
514 else if (osdChannelIndex == currentChannelIndex)
520 channelChange(INDEX, osdChannelIndex);
526 osdChannelIndex = currentChannelIndex;
528 okTriggeredOSD = true;
532 void VVideoLiveTV::doSummary()
535 Channel* currentChannel = (*chanList)[osdChannelIndex];
536 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
541 sort(eventList->begin(), eventList->end(), EventSorter());
543 if (eventList->size() < 1) return;
544 Event* event = (*eventList)[0];
545 event->loadinfos(currentChannel->number);
547 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
550 boxstack->update(vr);
553 void VVideoLiveTV::doKey(int command)
555 if (!osd.getVisible()) // First key. prep the data
558 updatePosterBanner();
563 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
564 keyingInput[0] = command;
567 char* keyingString = new char[numberWidth + 1];
568 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
569 keyingString[numberWidth] = '\0';
571 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
573 if (keying == numberWidth)
576 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
578 channelChange(NUMBER, newChannel);
579 osdChannelIndex = currentChannelIndex;
580 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
581 displayOSD(true); // this will put one back if required
585 osdChanNum.setText(keyingString);
587 if (!osd.getVisible())
589 osd.setVisible(true);
596 boxstack->update(this, osd.getRegion());
597 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
599 delete[] keyingString;
602 void VVideoLiveTV::doTeletext(bool subtitlemode)
604 if (streamType !=VDR::VIDEO) return;
605 (static_cast<PlayerVideoLive*>(player))->tellSubtitlesOSDVisible(true);
612 // and reset the display - this is a copy from setNowNextData
613 char formatChanNum[20];
614 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
615 osdChanNum.setText(formatChanNum);
616 osdChanName.setText((*chanList)[osdChannelIndex]->name);
618 (static_cast<PlayerVideoLive*>(player))->tellSubtitlesOSDVisible(true);
619 if (osd.getVisible()) clearScreen();
621 VTeletextView *vtxv=((PlayerVideoLive*)player)->getTeletextDecoder()->getTeletxtView();
624 vtxv= new VTeletextView(((PlayerVideoLive*)player)->getTeletextDecoder(),this, (PlayerVideoLive*)player);
625 ((PlayerVideoLive*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
629 vtxv->setSubtitleMode(subtitlemode);
635 BoxStack::getInstance()->add(vtxv);
638 BoxStack::getInstance()->update(this);
639 BoxStack::getInstance()->update(vtxv);
642 void VVideoLiveTV::doAudioSelector()
644 // If the osd is already visisble there might be a timer for it
645 Timers::getInstance()->cancelTimer(this, 1);
646 //This causes a deadlock with the timertrhread itself is locked
652 // and reset the display - this is a copy from setNowNextData
653 char formatChanNum[20];
654 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
655 osdChanNum.setText(formatChanNum);
656 osdChanName.setText((*chanList)[osdChannelIndex]->name);
658 int subtitleChannel=((PlayerVideoLive*)player)->getCurrentSubtitleChannel();
659 int subtitleType=0x10;
660 if (!(static_cast<PlayerVideoLive*>(player))->isSubtitlesOn()) {
661 if (((PlayerVideoLive*)player)->getTeletextDecoder()->getTeletxtView() &&
662 ((PlayerVideoLive*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
664 subtitleChannel=((PlayerVideoLive*)player)->getTeletextDecoder()->getPage();
668 subtitleType=0xFF; //turnedOff
674 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerVideoLive*)player)->getCurrentAudioChannel(),
675 subtitleType,subtitleChannel,NULL);
677 vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
678 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
681 // make vas != null and displayOSD will not set a timer or do any boxstack update
682 if (osd.getVisible()) displayOSD(false);
683 else displayOSD(true);
686 BoxStack::getInstance()->add(vas);
687 BoxStack::getInstance()->update(this);
688 BoxStack::getInstance()->update(vas);
691 void VVideoLiveTV::doEPG()
693 if (osd.getVisible()) clearScreen();
695 if (!Command::getInstance()->isAdvMenus())
697 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
700 boxstack->update(vepg);
704 Channel* currentChannel = (*chanList)[osdChannelIndex];
705 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
708 boxstack->update(vepg);
712 void VVideoLiveTV::setNowNextData()
716 Channel* currentChannel = (*chanList)[osdChannelIndex];
718 char formatChanNum[20];
719 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
720 osdChanNum.setText(formatChanNum);
721 osdChanName.setText(currentChannel->name);
723 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
727 sl.setText(tr("No channel data available"));
731 sort(eventList->begin(), eventList->end(), EventSorter());
733 char tempString[300];
734 char tempString2[300];
737 int eventListSize = eventList->size();
738 std::stringstream string;
739 for(int i = 0; i < eventListSize; i++)
741 event = (*eventList)[i];
743 time_t etime = event->time;
744 LOCALTIME_R(&etime, &btime);
746 strftime(tempString2, 299, "%0H:%0M ", &btime);
748 strftime(tempString2, 299, "%H:%M ", &btime);
750 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
751 string << tempString << "\n";
753 sl.setText(string.str().c_str());
759 void VVideoLiveTV::displayOSD(bool newNowNextData)
761 PlayerVideoLive* playerlivetv = dynamic_cast<PlayerVideoLive*>(player);
762 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(true);
763 osd.setVisible(true);
767 updatePosterBanner();
771 if (osdposterbanner.getVisible()) osdposterbanner.draw();
776 toupdate=*osd.getRegion();
779 if (osdposterbanner.getVisible())
781 boxstack->update(this);
785 boxstack->update(this, &toupdate);
788 bool setTimer = true;
789 if (vas) setTimer = false;
790 if (textUnavailable.getVisible()) setTimer = false;
792 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
795 void VVideoLiveTV::clearScreen()
797 Timers::getInstance()->cancelTimer(this, 1);
799 textUnavailable.setVisible(false);
800 osd.setVisible(false);
801 osdposterbanner.setVisible(false);
803 okTriggeredOSD = false;
806 boxstack->update(this);
808 PlayerVideoLive* playerlivetv = dynamic_cast<PlayerVideoLive*>(player);
809 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
812 void VVideoLiveTV::showUnavailable()
814 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
815 textUnavailable.setVisible(true);
816 textUnavailable.draw();
818 if (!osd.getVisible()) displayOSD(true);
820 boxstack->update(this, textUnavailable.getRegion());
823 void VVideoLiveTV::setClock()
829 LOCALTIME_R(&t, &tms);
830 strftime(timeString, 19, "%H:%M", &tms);
831 clock.setText(timeString);
833 time_t dt = 60 - (t % 60); // seconds to the next minute
834 if (dt == 0) dt = 60; // advance a whole minute if necessary
835 dt += t; // get a time_t value for it rather than using duration
836 // (so it will occur at the actual second and not second and a half)
838 Timers::getInstance()->setTimerT(this, 2, dt);
841 void VVideoLiveTV::timercall(int ref)
847 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
849 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
851 Message* m = new Message();
852 m->message = Message::CHANNEL_CHANGE;
854 m->parameter = newChannel;
855 m->tag = 1; // signal to call displayOSD();
856 MessageQueue::getInstance()->postMessage(m);
857 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
861 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
862 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
863 if (preBuffering < 100)
865 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
866 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
869 bool osdpbvisible=osdposterbanner.getVisible();
870 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
871 osd.setVisible(false);
872 osdposterbanner.setVisible(false);
873 okTriggeredOSD = false;
874 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
876 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
877 if (osdpbvisible) boxstack->update(this);
878 else boxstack->update(this, osd.getRegion());
880 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
881 PlayerVideoLive* playerlivetv = dynamic_cast<PlayerVideoLive*>(player);
882 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
883 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
888 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
890 if (osd.getVisible())
893 boxstack->update(this, osd.getRegion());
895 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
899 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
902 if (streamType == VDR::VIDEO)
904 VTeletextView *vtxt=((PlayerVideoLive*)player)->getTeletextDecoder()->getTeletxtView();
907 BoxStack::getInstance()->remove(vtxt);
910 if (changeType == INDEX)
912 newChannel = newData;
914 else if (changeType == NUMBER)
917 for(i = 0; i < chanList->size(); i++)
919 if ((*chanList)[i]->number == (UINT)newData)
926 if (i == chanList->size())
932 else if (changeType == OFFSET)
934 if (newData == UP) newChannel = upChannel(currentChannelIndex);
935 else newChannel = downChannel(currentChannelIndex);
937 else if (changeType == PREVIOUS)
939 newChannel = previousChannelIndex;
943 return false; // bad input
946 if (newChannel == currentChannelIndex) return true;
948 previousChannelIndex = currentChannelIndex;
949 currentChannelIndex = newChannel;
953 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
954 player->setChannel(currentChannelIndex);
955 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
957 // Blank out the symbols
958 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
960 bufferBar.setPercent(0);
964 sAudioChannels.setVisible(false);
965 sAspectRatio.setVisible(false);
969 reslogo.setVisible(false);
970 dolbylogo.setVisible(false);
971 txtlogo.setVisible(false);
974 // Remove other stuff
975 if (textUnavailable.getVisible())
977 textUnavailable.setVisible(false);
983 Channel* currentChannel = (*chanList)[currentChannelIndex];
986 info.setChannelLogo(currentChannel->number);
987 if (streamType == VDR::RADIO)
989 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
990 radioChannelLogo.setVisible(true);
992 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
997 BoxStack::getInstance()->update(this);
1002 void VVideoLiveTV::processMessage(Message* m)
1004 if (m->message == Message::MOUSE_LBDOWN)
1006 //check if press is outside this view! then simulate cancel
1007 int x = (m->parameter >> 16) - osd.getScreenX();
1008 int y = (m->parameter & 0xFFFF) - osd.getScreenY();
1009 if (osd.getVisible())
1011 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
1012 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y ))
1014 BoxStack::getInstance()->handleCommand(Input::RED);
1016 else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
1017 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y))
1019 BoxStack::getInstance()->handleCommand(Input::GREEN);
1021 else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
1022 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
1023 BoxStack::getInstance()->handleCommand(Input::YELLOW);
1025 else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
1026 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y ))
1028 BoxStack::getInstance()->handleCommand(Input::BLUE);
1032 BoxStack::getInstance()->handleCommand(Input::OK); //simulate rok press
1037 BoxStack::getInstance()->handleCommand(Input::OK); //simulate rok press
1040 else if (m->message == Message::CHANNEL_CHANGE)
1042 channelChange(NUMBER, m->parameter);
1043 osdChannelIndex = currentChannelIndex;
1044 if (m->tag == 1) displayOSD(true);
1046 else if (m->message == Message::CHILD_CLOSE)
1054 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1056 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter);
1057 player->setAudioChannel((m->parameter & 0xFFFF), (m->parameter & 0xFF0000) >> 16, (m->parameter & 0xFF000000) >> 24);
1059 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1061 if (streamType != VDR::VIDEO) return;
1062 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter);
1063 int type = (m->parameter & 0xFF0000) >> 16;
1069 if (streamType == VDR::VIDEO)
1071 player->setSubtitleChannel((m->parameter & 0xFFFF));
1072 (static_cast<PlayerVideoLive*>(player))->turnSubtitlesOn(true);
1073 VTeletextView *vtxt=((PlayerVideoLive*)player)->getTeletextDecoder()->getTeletxtView();
1074 if (vtxt && vtxt->isInSubtitleMode())
1076 BoxStack::getInstance()->remove(vtxt);
1082 if (streamType == VDR::VIDEO){
1083 (static_cast<PlayerVideoLive*>(player))->turnSubtitlesOn(false);
1084 VTeletextView *vtxt=((PlayerVideoLive*)player)->getTeletextDecoder()->getTeletxtView();
1085 if (vtxt && vtxt->isInSubtitleMode()) {
1086 BoxStack::getInstance()->remove(vtxt);
1093 (static_cast<PlayerVideoLive*>(player))->turnSubtitlesOn(false);
1095 ((PlayerVideoLive*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1101 BoxStack::getInstance()->update(vas);
1102 //BoxStack::getInstance()->update(&osd); //eveil error
1104 BoxStack::getInstance()->update(this, osd.getRegion());
1106 else if (m->message == Message::PLAYER_EVENT)
1108 switch (m->parameter)
1110 case PlayerVideoLive::CONNECTION_LOST: // connection lost detected
1112 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1113 Command::getInstance()->connectionLost();
1117 case PlayerVideoLive::STREAM_END:
1119 // Message comes from playerlivetv through master mutex, so can do anything here
1124 case PlayerVideoLive::ASPECT43:
1126 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1129 osdv->updateBackgroundColor(DrawStyle::BLACK);
1132 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1133 sAspectRatio.setVisible(true);
1135 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1138 BoxStack::getInstance()->update(this, osd.getRegion());
1143 case PlayerVideoLive::ASPECT169:
1145 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1146 sAspectRatio.setVisible(true);
1148 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1151 osdv->updateBackgroundColor(DrawStyle::BLACK);
1155 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1158 BoxStack::getInstance()->update(this, osd.getRegion());
1163 case PlayerVideoLive::PREBUFFERING:
1165 preBuffering = m->tag;
1166 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1167 bufferBar.setPercent(preBuffering);
1169 if (osd.getVisible())
1171 bufferBar.setVisible(true);
1174 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1175 BoxStack::getInstance()->update(this, &r);
1177 if (preBuffering == 100)
1179 doAudioChannelSymbol();
1187 void VVideoLiveTV::doAudioChannelSymbol()
1189 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1191 Channel* currentChannel = (*chanList)[osdChannelIndex];
1193 bool multiAudio = false;
1194 if (Audio::getInstance()->supportsAc3()) {
1195 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1197 if (currentChannel->numAPids > 1) multiAudio = true;
1201 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1202 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1203 sAudioChannels.setVisible(true);
1207 dolbylogo.setVisible(true);
1208 txtlogo.setVisible(true);
1210 if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
1211 else info.setStaticArtwork(sa_txtoff);
1212 txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
1215 if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
1216 info.setStaticArtwork(sa_dolbyon);
1217 else info.setStaticArtwork(sa_dolbyoff);
1218 dolbylogo.setTVMedia(info, WTVMedia::ZoomVertical);
1220 Demuxer* demux=Demuxer::getInstance();
1222 int vertical_size=demux->getVerticalSize();
1223 Log::getInstance()->log("VVideoRec", Log::DEBUG, "TVMedia vertical size %d", vertical_size);
1224 reslogo.setVisible(true);
1225 switch (vertical_size) {
1227 info.setStaticArtwork(sa_sd576i);
1228 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1230 info.setStaticArtwork(sa_hd720p);
1231 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1233 info.setStaticArtwork(sa_hd1080i);
1234 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1235 default: // we assume sd
1236 reslogo.setVisible(false);
1240 reslogo.setVisible(false);
1246 if (osd.getVisible())
1248 sAudioChannels.draw();
1250 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1254 BoxStack::getInstance()->update(this, &r);
1258 UINT VVideoLiveTV::upChannel(UINT index)
1260 if (index == (chanList->size() - 1)) // at the end
1261 return 0; // so go to start
1266 UINT VVideoLiveTV::downChannel(UINT index)
1268 if (index == 0) // at the start
1269 return chanList->size() - 1; // so go to end
1274 void VVideoLiveTV::toggleChopSides()
1276 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1278 if (videoMode == Video::NORMAL)
1280 videoMode = Video::LETTERBOX;
1281 video->setMode(Video::LETTERBOX);
1285 videoMode = Video::NORMAL;
1286 video->setMode(Video::NORMAL);
1290 void VVideoLiveTV::updatePosterBanner()
1292 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1294 osdposterbanner.setVisible(false);
1297 Event* toShow = NULL;
1298 if (eventList && eventList->size()) {
1299 toShow = (*eventList)[0];
1300 Channel* currentChannel = (*chanList)[osdChannelIndex];
1301 toShow->loadinfos(currentChannel->number);
1308 bool posterscale=true;
1309 if (toShow->movieInfo) {
1310 poster=toShow->movieInfo->poster;
1312 if (toShow->seriesInfo) {
1313 if (toShow->seriesInfo->banners.size()) {
1314 poster=toShow->seriesInfo->banners[0];
1316 } else if (toShow->seriesInfo->seasonposter.height) {
1317 poster=toShow->seriesInfo->seasonposter;
1318 } else if (toShow->seriesInfo->posters.size()) {
1319 poster=toShow->seriesInfo->posters[0];
1322 if (poster.height) {
1323 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1324 osdposterbanner.setVisible(true);
1326 osdposterbanner.setVisible(false);
1329 osdposterbanner.setVisible(false);
1335 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1337 drawBitmap(posX, posY, bm,region);
1339 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1340 boxstack->update(this, &r);
1343 void VVideoLiveTV::clearOSD()
1345 rectangle(area, DrawStyle(0,0,0,0));
1346 boxstack->update(this, &area);
1349 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1352 r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1353 //now convert to our display
1354 float scalex=720.f/((float) (region.framewidth+1));
1355 float scaley=576.f/((float) (region.frameheight+1));
1356 r.x = (UINT)floor(scalex*((float)r.x));
1357 r.y = (UINT)floor(scaley*((float)r.y));
1358 r.w = (UINT)(ceil(scalex*((float)r.w))+1.f);
1359 r.h = (UINT)(ceil(scaley*((float)r.h))+1.f);
1360 rectangle(r, DrawStyle(0,0,0,0));
1361 boxstack->update(this, &r);