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, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "vvideolivetv.h"
23 #include "vchannellist.h"
26 #include "playerlive.h"
27 #include "playerlivetv.h"
28 #include "playerliveradio.h"
37 #include "vaudioselector.h"
44 #include "vteletextview.h"
45 #include "vepgsummary.h"
46 #include "vepglistadvanced.h"
47 #include "staticartwork.h"
52 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
54 vdr = VDR::getInstance();
55 boxstack = BoxStack::getInstance();
56 video = Video::getInstance();
61 vchannelList = tvchannelList;
62 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
64 currentChannelIndex = 0;
65 previousChannelIndex = 0;
72 // Convert channel number to index
74 for(i = 0; i < chanList->size(); i++)
76 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
78 currentChannelIndex = i;
86 videoMode = video->getMode();
88 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
90 streamType = VDR::VIDEO;
91 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
95 streamType = VDR::RADIO;
96 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
100 setSize(video->getScreenWidth(), video->getScreenHeight());
102 DrawStyle transparent(0, 0, 0, 0);
103 setBackgroundColour(transparent);
106 char* optionWSS = vdr->configLoad("General", "WSS");
109 if (strstr(optionWSS, "Yes")) dowss = true;
112 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
116 wss.setFormat(video->getFormat());
122 wssRegion.w = video->getScreenWidth();
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;
131 info.setChannelLogo(initialChannelNumber);
132 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
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);
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);
150 osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
151 osd.setPosition(0, video->getScreenHeight() - 150);
152 osd.setSize(video->getScreenWidth(), 150);
153 osd.setVisible(false);
156 int channellogomove=0;
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;
169 //clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
170 clock.setPosition(osd.getWidth() - 100, 4);
171 clock.setSize(90, 30);
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);
179 //osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
180 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
181 osdChanName.setSize(300, 30);
182 osd.add(&osdChanName);
184 boxRed.setBackgroundColour(DrawStyle::RED);
185 boxRed.setPosition(54+0*boxdiff, 104);
186 boxRed.setSize(18, 16);
189 boxGreen.setBackgroundColour(DrawStyle::GREEN);
190 boxGreen.setPosition(54+1*boxdiff, 104);
191 boxGreen.setSize(18, 16);
194 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
195 boxYellow.setPosition(54+2*boxdiff, 104);
196 boxYellow.setSize(18, 16);
199 boxBlue.setBackgroundColour(DrawStyle::BLUE);
200 boxBlue.setPosition(54+3*boxdiff, 104);
201 boxBlue.setSize(18, 16);
204 //textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
205 textRed.setPosition(boxRed.getX2(), 98);
206 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
207 textRed.setText(tr("Summary"));
210 if (streamType == VDR::VIDEO)
212 //textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
213 textGreen.setPosition(boxGreen.getX2(), 98);
214 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
215 textGreen.setText(tr("Audio"));
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);
225 //textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
226 textBlue.setPosition(boxBlue.getX2(), 98);
227 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
228 textBlue.setText(tr("EPG"));
231 //sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
232 sl.setPosition(90, 36);
238 bufferBar.setPosition(osd.getWidth() - 90, 70);
239 bufferBar.setSize(40, 20);
240 bufferBar.setVisible(true);
244 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
245 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
246 sAspectRatio.setVisible(false);
247 osd.add(&sAspectRatio);
249 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
250 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
251 sAudioChannels.setVisible(false);
252 osd.add(&sAudioChannels);
257 ninfo.setStaticArtwork(sa_txtoff);
258 txtlogo.setPosition(54+4*boxdiff,104);
259 txtlogo.setSize(22,20);
260 txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
263 ninfo.setStaticArtwork(sa_dolbyoff);
264 dolbylogo.setPosition(54+4*boxdiff+15,104);
265 dolbylogo.setSize(22,20);
266 dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
269 ninfo.setStaticArtwork(sa_sd576i);
270 reslogo.setPosition(54+4*boxdiff+30,104);
271 reslogo.setSize(22,20);
272 reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
275 reslogo.setVisible(false);
276 dolbylogo.setVisible(false);
277 txtlogo.setVisible(false);
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);
289 vdisplay.mode=Fullscreen;
290 vdisplay.fallbackMode=Fullscreen;
298 void VVideoLiveTV::preDelete()
303 VVideoLiveTV::~VVideoLiveTV()
306 video->setDefaultAspect();
308 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
311 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
315 void VVideoLiveTV::delData()
319 int eventListSize = eventList->size();
320 for(int i = 0; i < eventListSize; i++)
322 delete (*eventList)[i];
330 int VVideoLiveTV::handleCommand(int command)
336 if (osd.getVisible() && !textUnavailable.getVisible())
341 // else drop through to stop
346 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
350 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
353 if (Remote::getInstance()->mayHaveFewButtons()) {
354 if (okTriggeredOSD) doUpDown(false);
355 else doChanUpDown(UP);
363 if (Remote::getInstance()->mayHaveFewButtons()) {
364 if (okTriggeredOSD) doUpDown(true);
365 else doChanUpDown(DOWN);
381 // Continue new remote only...
382 case Remote::CHANNELUP:
387 case Remote::CHANNELDOWN:
393 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
395 // DF_LEFT and DF_RIGHT never get here because they are stolen
396 // by command as vol- and vol+
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-
404 // Old remote, decide what to do based on okTriggeredOSD
405 if (okTriggeredOSD) doUpDown(false);
406 else doChanUpDown(UP);
409 case Remote::DF_DOWN:
411 // Old remote, decide what to do based on okTriggeredOSD
412 if (okTriggeredOSD) doUpDown(true);
413 else doChanUpDown(DOWN);
417 // END NEW/OLD REMOTE STUFF
419 case Remote::PREVCHANNEL:
421 channelChange(PREVIOUS, 0);
422 osdChannelIndex = currentChannelIndex;
455 // key in channel number
462 if (streamType == VDR::VIDEO) doAudioSelector();
467 if (streamType ==VDR::VIDEO)
469 doTeletext(); //TODO: Add a selector for subtitles or teletext
480 if (streamType == VDR::VIDEO)
481 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
488 void VVideoLiveTV::go()
492 boxstack->update(this);
497 player->go(currentChannelIndex);
500 void VVideoLiveTV::stop()
502 Timers::getInstance()->cancelTimer(this, 1);
503 Timers::getInstance()->cancelTimer(this, 2);
508 void VVideoLiveTV::doLeftRight(bool right)
510 if (osd.getVisible())
512 if (right) osdChannelIndex = upChannel(osdChannelIndex);
513 else osdChannelIndex = downChannel(osdChannelIndex);
517 osdChannelIndex = currentChannelIndex;
522 void VVideoLiveTV::doUpDown(bool down)
524 if (osd.getVisible())
536 void VVideoLiveTV::doChanUpDown(int which)
538 channelChange(OFFSET, which);
539 osdChannelIndex = currentChannelIndex;
543 void VVideoLiveTV::doOK()
545 if (osd.getVisible())
550 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
552 channelChange(NUMBER, newChannel);
553 osdChannelIndex = currentChannelIndex;
556 else if (osdChannelIndex == currentChannelIndex)
562 channelChange(INDEX, osdChannelIndex);
568 osdChannelIndex = currentChannelIndex;
570 okTriggeredOSD = true;
574 void VVideoLiveTV::doSummary()
577 Channel* currentChannel = (*chanList)[osdChannelIndex];
578 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
583 sort(eventList->begin(), eventList->end(), EventSorter());
585 if (eventList->size() < 1) return;
586 Event* event = (*eventList)[0];
587 event->loadinfos(currentChannel->number);
589 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
592 boxstack->update(vr);
596 void VVideoLiveTV::doKey(int command)
598 if (!osd.getVisible()) // First key. prep the data
601 updatePosterBanner();
606 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
607 keyingInput[0] = command;
610 char* keyingString = new char[numberWidth + 1];
611 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
612 keyingString[numberWidth] = '\0';
614 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
616 if (keying == numberWidth)
619 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
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
628 osdChanNum.setText(keyingString);
630 if (!osd.getVisible())
632 osd.setVisible(true);
637 osdChanNum.fillColour(DrawStyle::VIEWBACKGROUND);
640 boxstack->update(this, osd.getRegion());
641 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
643 delete[] keyingString;
646 void VVideoLiveTV::doTeletext(bool subtitlemode)
648 if (streamType !=VDR::VIDEO) return;
649 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
656 // and reset the display - this is a copy from setNowNextData
657 char formatChanNum[20];
658 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
659 osdChanNum.setText(formatChanNum);
660 osdChanName.setText((*chanList)[osdChannelIndex]->name);
662 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
663 if (osd.getVisible()) clearScreen();
665 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
667 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
668 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
671 vtxv->setSubtitleMode(subtitlemode);
676 BoxStack::getInstance()->add(vtxv);
678 BoxStack::getInstance()->update(this);
679 BoxStack::getInstance()->update(vtxv);
682 void VVideoLiveTV::doAudioSelector()
684 // If the osd is already visisble there might be a timer for it
685 Timers::getInstance()->cancelTimer(this, 1);
686 //This causes a deadlock with the timertrhread itself is locked
693 // and reset the display - this is a copy from setNowNextData
694 char formatChanNum[20];
695 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
696 osdChanNum.setText(formatChanNum);
697 osdChanName.setText((*chanList)[osdChannelIndex]->name);
699 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
700 int subtitleType=0x10;
701 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
702 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
703 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
705 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
709 subtitleType=0xFF; //turnedOff
715 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
716 subtitleType,subtitleChannel,NULL);
718 vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
719 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
722 // make vas != null and displayOSD will not set a timer or do any boxstack update
723 if (osd.getVisible()) displayOSD(false);
724 else displayOSD(true);
727 BoxStack::getInstance()->add(vas);
728 BoxStack::getInstance()->update(this);
729 BoxStack::getInstance()->update(vas);
732 void VVideoLiveTV::doEPG()
734 if (osd.getVisible()) clearScreen();
736 if (!Command::getInstance()->advMenues()) {
738 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
741 boxstack->update(vepg);
743 Channel* currentChannel = (*chanList)[osdChannelIndex];
744 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
747 boxstack->update(vepg);
751 void VVideoLiveTV::setNowNextData()
755 Channel* currentChannel = (*chanList)[osdChannelIndex];
757 char formatChanNum[20];
758 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
759 osdChanNum.setText(formatChanNum);
760 osdChanName.setText(currentChannel->name);
762 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
766 sl.setText(tr("No channel data available"));
770 sort(eventList->begin(), eventList->end(), EventSorter());
772 char tempString[300];
773 char tempString2[300];
776 int eventListSize = eventList->size();
777 std::stringstream string;
778 for(int i = 0; i < eventListSize; i++)
780 event = (*eventList)[i];
782 time_t etime = event->time;
783 LOCALTIME_R(&etime, &btime);
785 strftime(tempString2, 299, "%0H:%0M ", &btime);
787 strftime(tempString2, 299, "%H:%M ", &btime);
789 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
790 string << tempString << "\n";
792 sl.setText(string.str().c_str());
798 void VVideoLiveTV::displayOSD(bool newNowNextData)
800 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
801 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(true);
802 osd.setVisible(true);
806 updatePosterBanner();
810 if (osdposterbanner.getVisible()) osdposterbanner.draw();
815 toupdate=*osd.getRegion();
818 if (osdposterbanner.getVisible()) {
819 boxstack->update(this);
821 boxstack->update(this, &toupdate);
824 bool setTimer = true;
825 if (vas) setTimer = false;
826 if (textUnavailable.getVisible()) setTimer = false;
828 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
831 void VVideoLiveTV::clearScreen()
833 Timers::getInstance()->cancelTimer(this, 1);
835 textUnavailable.setVisible(false);
836 osd.setVisible(false);
837 osdposterbanner.setVisible(false);
839 okTriggeredOSD = false;
842 boxstack->update(this);
844 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
845 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
848 void VVideoLiveTV::showUnavailable()
850 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
851 textUnavailable.setVisible(true);
852 textUnavailable.draw();
854 if (!osd.getVisible()) displayOSD(true);
856 boxstack->update(this, textUnavailable.getRegion());
859 void VVideoLiveTV::setClock()
865 LOCALTIME_R(&t, &tms);
866 strftime(timeString, 19, "%H:%M", &tms);
867 clock.setText(timeString);
869 time_t dt = 60 - (t % 60); // seconds to the next minute
870 if (dt == 0) dt = 60; // advance a whole minute if necessary
871 dt += t; // get a time_t value for it rather than using duration
872 // (so it will occur at the actual second and not second and a half)
874 Timers::getInstance()->setTimerT(this, 2, dt);
877 void VVideoLiveTV::timercall(int ref)
883 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
885 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
887 Message* m = new Message();
888 m->message = Message::CHANNEL_CHANGE;
890 m->parameter.num = newChannel;
891 m->tag = 1; // signal to call displayOSD();
892 Command::getInstance()->postMessageFromOuterSpace(m);
893 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
897 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
898 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
899 if (preBuffering < 100)
901 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
902 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
905 bool osdpbvisible=osdposterbanner.getVisible();
906 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
907 osd.setVisible(false);
908 osdposterbanner.setVisible(false);
909 okTriggeredOSD = false;
910 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
912 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
913 if (osdpbvisible) boxstack->update(this);
914 else boxstack->update(this, osd.getRegion());
916 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
917 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
918 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
919 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
924 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
926 if (osd.getVisible())
929 boxstack->update(this, osd.getRegion());
931 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
935 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
938 if (streamType ==VDR::VIDEO) {
939 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
941 BoxStack::getInstance()->remove(vtxt);
945 if (changeType == INDEX)
947 newChannel = newData;
949 else if (changeType == NUMBER)
952 for(i = 0; i < chanList->size(); i++)
954 if ((*chanList)[i]->number == (UINT)newData)
961 if (i == chanList->size())
967 else if (changeType == OFFSET)
969 if (newData == UP) newChannel = upChannel(currentChannelIndex);
970 else newChannel = downChannel(currentChannelIndex);
972 else if (changeType == PREVIOUS)
974 newChannel = previousChannelIndex;
978 return false; // bad input
981 if (newChannel == currentChannelIndex) return true;
983 previousChannelIndex = currentChannelIndex;
984 currentChannelIndex = newChannel;
988 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
989 player->setChannel(currentChannelIndex);
990 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
992 // Blank out the symbols
993 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
995 bufferBar.setPercent(0);
998 sAudioChannels.setVisible(false);
999 sAspectRatio.setVisible(false);
1001 reslogo.setVisible(false);
1002 dolbylogo.setVisible(false);
1003 txtlogo.setVisible(false);
1006 // Remove other stuff
1007 if (textUnavailable.getVisible())
1009 textUnavailable.setVisible(false);
1015 Channel* currentChannel = (*chanList)[currentChannelIndex];
1016 if (currentChannel) {
1017 info.setChannelLogo(currentChannel->number);
1018 if (streamType == VDR::RADIO) {
1019 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1020 radioChannelLogo.setVisible(true);
1022 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1028 BoxStack::getInstance()->update(this);
1033 void VVideoLiveTV::processMessage(Message* m)
1035 if (m->message == Message::MOUSE_LBDOWN)
1037 //check if press is outside this view! then simulate cancel
1038 int x = (m->parameter.num >> 16) - osd.getScreenX();
1039 int y = (m->parameter.num & 0xFFFF) - osd.getScreenY();
1040 if (osd.getVisible()) {
1042 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
1043 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y )) {
1044 BoxStack::getInstance()->handleCommand(Remote::RED);
1045 } else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
1046 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y)){
1047 BoxStack::getInstance()->handleCommand(Remote::GREEN);
1048 } else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
1049 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
1050 BoxStack::getInstance()->handleCommand(Remote::YELLOW);
1051 } else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
1052 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y )){
1053 BoxStack::getInstance()->handleCommand(Remote::BLUE);
1055 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1059 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1062 else if (m->message == Message::CHANNEL_CHANGE)
1064 channelChange(NUMBER, m->parameter.num);
1065 osdChannelIndex = currentChannelIndex;
1066 if (m->tag == 1) displayOSD(true);
1068 else if (m->message == Message::CHILD_CLOSE)
1076 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1078 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter.num);
1079 player->setAudioChannel((m->parameter.num & 0xFFFF), (m->parameter.num & 0xFF0000) >> 16, (m->parameter.num & 0xFF000000) >> 24);
1081 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1083 if (streamType !=VDR::VIDEO) return;
1084 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter.num);
1085 int type=((m->parameter.num & 0xFF0000)>>16);
1087 case 0x10: { //dvbsubtitle
1088 if (streamType == VDR::VIDEO){
1089 player->setSubtitleChannel((m->parameter.num & 0xFFFF));
1090 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1091 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1092 if (vtxt && vtxt->isInSubtitleMode()) {
1093 BoxStack::getInstance()->remove(vtxt);
1097 case 0xFF: { //nosubtitles
1098 if (streamType == VDR::VIDEO){
1099 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1100 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1101 if (vtxt && vtxt->isInSubtitleMode()) {
1102 BoxStack::getInstance()->remove(vtxt);
1106 case 0x11: { //videotext
1107 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1109 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter.num & 0xFFFF));
1113 BoxStack::getInstance()->update(vas);
1114 //BoxStack::getInstance()->update(&osd); //eveil error
1116 BoxStack::getInstance()->update(this, osd.getRegion());
1120 else if (m->message == Message::PLAYER_EVENT)
1122 switch (m->parameter.num)
1124 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1126 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1127 Command::getInstance()->connectionLost();
1131 case PlayerLiveTV::STREAM_END:
1133 // Message comes from playerlivetv through master mutex, so can do anything here
1138 case PlayerLiveTV::ASPECT43:
1141 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1143 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
1146 BoxStack::getInstance()->update(this, &wssRegion);
1150 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1153 osdv->updateBackgroundColor(DrawStyle::BLACK);
1156 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1157 sAspectRatio.setVisible(true);
1159 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1162 BoxStack::getInstance()->update(this, osd.getRegion());
1167 case PlayerLiveTV::ASPECT169:
1170 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1172 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
1175 BoxStack::getInstance()->update(this, &wssRegion);
1179 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1180 sAspectRatio.setVisible(true);
1182 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1185 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
1189 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1192 BoxStack::getInstance()->update(this, osd.getRegion());
1197 case PlayerLiveTV::PREBUFFERING:
1199 preBuffering = m->tag;
1200 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1201 bufferBar.setPercent(preBuffering);
1203 if (osd.getVisible())
1205 bufferBar.setVisible(true);
1208 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1209 BoxStack::getInstance()->update(this, &r);
1211 if (preBuffering == 100)
1213 doAudioChannelSymbol();
1219 #ifdef VOMP_PLATTFORM_MVP
1220 // See vepg.cc ~ line 480
1221 else if (m->message == Message::HACK_MVP_RETURN_FROM_QUARTER)
1223 video->setMode(videoMode);
1228 void VVideoLiveTV::doAudioChannelSymbol()
1230 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1232 Channel* currentChannel = (*chanList)[osdChannelIndex];
1234 bool multiAudio = false;
1235 if (Audio::getInstance()->supportsAc3()) {
1236 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1238 if (currentChannel->numAPids > 1) multiAudio = true;
1242 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1243 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1244 sAudioChannels.setVisible(true);
1248 dolbylogo.setVisible(true);
1249 txtlogo.setVisible(true);
1251 if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
1252 else info.setStaticArtwork(sa_txtoff);
1253 txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
1256 if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
1257 info.setStaticArtwork(sa_dolbyon);
1258 else info.setStaticArtwork(sa_dolbyoff);
1259 dolbylogo.setTVMedia(info, WTVMedia::ZoomVertical);
1261 Demuxer* demux=Demuxer::getInstance();
1263 int vertical_size=demux->getVerticalSize();
1264 Log::getInstance()->log("VVideoRec", Log::DEBUG, "TVMedia vertical size %d", vertical_size);
1265 reslogo.setVisible(true);
1266 switch (vertical_size) {
1268 info.setStaticArtwork(sa_sd576i);
1269 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1271 info.setStaticArtwork(sa_hd720p);
1272 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1274 info.setStaticArtwork(sa_hd1080i);
1275 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1276 default: // we assume sd
1277 reslogo.setVisible(false);
1281 reslogo.setVisible(false);
1287 if (osd.getVisible())
1289 sAudioChannels.draw();
1291 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1295 BoxStack::getInstance()->update(this, &r);
1299 UINT VVideoLiveTV::upChannel(UINT index)
1301 if (index == (chanList->size() - 1)) // at the end
1302 return 0; // so go to start
1307 UINT VVideoLiveTV::downChannel(UINT index)
1309 if (index == 0) // at the start
1310 return chanList->size() - 1; // so go to end
1315 void VVideoLiveTV::toggleChopSides()
1317 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1319 if (videoMode == Video::NORMAL)
1321 videoMode = Video::LETTERBOX;
1322 video->setMode(Video::LETTERBOX);
1326 videoMode = Video::NORMAL;
1327 video->setMode(Video::NORMAL);
1331 void VVideoLiveTV::updatePosterBanner()
1333 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1335 osdposterbanner.setVisible(false);
1338 Event* toShow = NULL;
1339 if (eventList && eventList->size()) {
1340 toShow = (*eventList)[0];
1341 Channel* currentChannel = (*chanList)[osdChannelIndex];
1342 toShow->loadinfos(currentChannel->number);
1349 bool posterscale=true;
1350 if (toShow->movieInfo) {
1351 poster=toShow->movieInfo->poster;
1353 if (toShow->seriesInfo) {
1354 if (toShow->seriesInfo->banners.size()) {
1355 poster=toShow->seriesInfo->banners[0];
1357 } else if (toShow->seriesInfo->seasonposter.height) {
1358 poster=toShow->seriesInfo->seasonposter;
1359 } else if (toShow->seriesInfo->posters.size()) {
1360 poster=toShow->seriesInfo->posters[0];
1363 if (poster.height) {
1364 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1365 osdposterbanner.setVisible(true);
1367 osdposterbanner.setVisible(false);
1370 osdposterbanner.setVisible(false);
1376 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1378 drawBitmap(posX, posY, bm,region);
1380 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1381 boxstack->update(this, &r);
1384 void VVideoLiveTV::clearOSD()
1386 rectangle(area, DrawStyle(0,0,0,0));
1387 boxstack->update(this, &area);
1390 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1393 r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1394 //now convert to our display
1395 float scalex=720.f/((float) (region.framewidth+1));
1396 float scaley=576.f/((float) (region.frameheight+1));
1397 r.x = (UINT)floor(scalex*((float)r.x));
1398 r.y = (UINT)floor(scaley*((float)r.y));
1399 r.w = (UINT)(ceil(scalex*((float)r.w))+1.f);
1400 r.h = (UINT)(ceil(scaley*((float)r.h))+1.f);
1401 rectangle(r, DrawStyle(0,0,0,0));
1402 boxstack->update(this, &r);