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);
133 #ifndef VOMP_PLATTFORM_MVP
135 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
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);
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);
154 osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
155 osd.setPosition(0, video->getScreenHeight() - 150);
156 osd.setSize(video->getScreenWidth(), 150);
157 osd.setVisible(false);
160 int channellogomove=0;
163 #ifndef VOMP_PLATTFORM_MVP
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;
176 //clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
177 clock.setPosition(osd.getWidth() - 100, 4);
178 clock.setSize(90, 30);
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);
186 //osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
187 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
188 osdChanName.setSize(300, 30);
189 osd.add(&osdChanName);
191 boxRed.setBackgroundColour(DrawStyle::RED);
192 boxRed.setPosition(54+0*boxdiff, 104);
193 boxRed.setSize(18, 16);
196 boxGreen.setBackgroundColour(DrawStyle::GREEN);
197 boxGreen.setPosition(54+1*boxdiff, 104);
198 boxGreen.setSize(18, 16);
201 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
202 boxYellow.setPosition(54+2*boxdiff, 104);
203 boxYellow.setSize(18, 16);
206 boxBlue.setBackgroundColour(DrawStyle::BLUE);
207 boxBlue.setPosition(54+3*boxdiff, 104);
208 boxBlue.setSize(18, 16);
211 //textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
212 textRed.setPosition(boxRed.getX2(), 98);
213 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
214 textRed.setText(tr("Summary"));
217 if (streamType == VDR::VIDEO)
219 //textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
220 textGreen.setPosition(boxGreen.getX2(), 98);
221 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
222 textGreen.setText(tr("Audio"));
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);
232 //textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
233 textBlue.setPosition(boxBlue.getX2(), 98);
234 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
235 textBlue.setText(tr("EPG"));
238 //sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
239 sl.setPosition(90, 36);
245 bufferBar.setPosition(osd.getWidth() - 90, 70);
246 bufferBar.setSize(40, 20);
247 bufferBar.setVisible(true);
250 #ifndef VOMP_PLATTFORM_MVP
254 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
255 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
256 sAspectRatio.setVisible(false);
257 osd.add(&sAspectRatio);
259 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
260 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
261 sAudioChannels.setVisible(false);
262 osd.add(&sAudioChannels);
267 ninfo.setStaticArtwork(sa_txtoff);
268 txtlogo.setPosition(54+4*boxdiff,104);
269 txtlogo.setSize(22,20);
270 txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
273 ninfo.setStaticArtwork(sa_dolbyoff);
274 dolbylogo.setPosition(54+4*boxdiff+15,104);
275 dolbylogo.setSize(22,20);
276 dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
279 ninfo.setStaticArtwork(sa_sd576i);
280 reslogo.setPosition(54+4*boxdiff+30,104);
281 reslogo.setSize(22,20);
282 reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
285 reslogo.setVisible(false);
286 dolbylogo.setVisible(false);
287 txtlogo.setVisible(false);
290 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
291 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
292 sAspectRatio.setVisible(false);
293 osd.add(&sAspectRatio);
295 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
296 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
297 sAudioChannels.setVisible(false);
298 osd.add(&sAudioChannels);
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);
310 vdisplay.mode=Fullscreen;
311 vdisplay.fallbackMode=Fullscreen;
319 void VVideoLiveTV::preDelete()
324 VVideoLiveTV::~VVideoLiveTV()
327 video->setDefaultAspect();
331 #ifndef VOMP_PLATTFORM_MVP
334 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
337 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
343 void VVideoLiveTV::delData()
347 int eventListSize = eventList->size();
348 for(int i = 0; i < eventListSize; i++)
350 delete (*eventList)[i];
358 int VVideoLiveTV::handleCommand(int command)
364 if (osd.getVisible() && !textUnavailable.getVisible())
369 // else drop through to stop
374 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
378 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
381 if (Remote::getInstance()->mayHaveFewButtons()) {
382 if (okTriggeredOSD) doUpDown(false);
383 else doChanUpDown(UP);
391 if (Remote::getInstance()->mayHaveFewButtons()) {
392 if (okTriggeredOSD) doUpDown(true);
393 else doChanUpDown(DOWN);
409 // Continue new remote only...
410 case Remote::CHANNELUP:
415 case Remote::CHANNELDOWN:
421 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
423 // DF_LEFT and DF_RIGHT never get here because they are stolen
424 // by command as vol- and vol+
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-
432 // Old remote, decide what to do based on okTriggeredOSD
433 if (okTriggeredOSD) doUpDown(false);
434 else doChanUpDown(UP);
437 case Remote::DF_DOWN:
439 // Old remote, decide what to do based on okTriggeredOSD
440 if (okTriggeredOSD) doUpDown(true);
441 else doChanUpDown(DOWN);
445 // END NEW/OLD REMOTE STUFF
447 case Remote::PREVCHANNEL:
449 channelChange(PREVIOUS, 0);
450 osdChannelIndex = currentChannelIndex;
483 // key in channel number
490 if (streamType == VDR::VIDEO) doAudioSelector();
495 if (streamType ==VDR::VIDEO)
497 doTeletext(); //TODO: Add a selector for subtitles or teletext
508 if (streamType == VDR::VIDEO)
509 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
516 void VVideoLiveTV::go()
520 boxstack->update(this);
525 player->go(currentChannelIndex);
528 void VVideoLiveTV::stop()
530 Timers::getInstance()->cancelTimer(this, 1);
531 Timers::getInstance()->cancelTimer(this, 2);
536 void VVideoLiveTV::doLeftRight(bool right)
538 if (osd.getVisible())
540 if (right) osdChannelIndex = upChannel(osdChannelIndex);
541 else osdChannelIndex = downChannel(osdChannelIndex);
545 osdChannelIndex = currentChannelIndex;
550 void VVideoLiveTV::doUpDown(bool down)
552 if (osd.getVisible())
564 void VVideoLiveTV::doChanUpDown(int which)
566 channelChange(OFFSET, which);
567 osdChannelIndex = currentChannelIndex;
571 void VVideoLiveTV::doOK()
573 if (osd.getVisible())
578 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
580 channelChange(NUMBER, newChannel);
581 osdChannelIndex = currentChannelIndex;
584 else if (osdChannelIndex == currentChannelIndex)
590 channelChange(INDEX, osdChannelIndex);
596 osdChannelIndex = currentChannelIndex;
598 okTriggeredOSD = true;
602 void VVideoLiveTV::doSummary()
605 Channel* currentChannel = (*chanList)[osdChannelIndex];
606 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
611 sort(eventList->begin(), eventList->end(), EventSorter());
613 if (eventList->size() < 1) return;
614 Event* event = (*eventList)[0];
615 event->loadinfos(currentChannel->number);
617 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
620 boxstack->update(vr);
624 void VVideoLiveTV::doKey(int command)
626 if (!osd.getVisible()) // First key. prep the data
629 updatePosterBanner();
634 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
635 keyingInput[0] = command;
638 char* keyingString = new char[numberWidth + 1];
639 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
640 keyingString[numberWidth] = '\0';
642 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
644 if (keying == numberWidth)
647 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
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
656 osdChanNum.setText(keyingString);
658 if (!osd.getVisible())
660 osd.setVisible(true);
667 boxstack->update(this, osd.getRegion());
668 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
670 delete[] keyingString;
673 void VVideoLiveTV::doTeletext(bool subtitlemode)
675 if (streamType !=VDR::VIDEO) return;
676 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
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);
689 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
690 if (osd.getVisible()) clearScreen();
692 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
694 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
695 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
698 vtxv->setSubtitleMode(subtitlemode);
703 BoxStack::getInstance()->add(vtxv);
705 BoxStack::getInstance()->update(this);
706 BoxStack::getInstance()->update(vtxv);
709 void VVideoLiveTV::doAudioSelector()
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
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);
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()
732 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
736 subtitleType=0xFF; //turnedOff
742 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
743 subtitleType,subtitleChannel,NULL);
745 vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
746 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
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);
754 BoxStack::getInstance()->add(vas);
755 BoxStack::getInstance()->update(this);
756 BoxStack::getInstance()->update(vas);
759 void VVideoLiveTV::doEPG()
761 if (osd.getVisible()) clearScreen();
763 if (!Command::getInstance()->advMenues()) {
765 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
768 boxstack->update(vepg);
770 Channel* currentChannel = (*chanList)[osdChannelIndex];
771 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
774 boxstack->update(vepg);
778 void VVideoLiveTV::setNowNextData()
782 Channel* currentChannel = (*chanList)[osdChannelIndex];
784 char formatChanNum[20];
785 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
786 osdChanNum.setText(formatChanNum);
787 osdChanName.setText(currentChannel->name);
789 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
793 sl.setText(tr("No channel data available"));
797 sort(eventList->begin(), eventList->end(), EventSorter());
799 char tempString[300];
800 char tempString2[300];
803 int eventListSize = eventList->size();
804 std::stringstream string;
805 for(int i = 0; i < eventListSize; i++)
807 event = (*eventList)[i];
809 time_t etime = event->time;
810 localtime_r(&etime, &btime);
812 strftime(tempString2, 299, "%0H:%0M ", &btime);
814 strftime(tempString2, 299, "%H:%M ", &btime);
816 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
817 string << tempString << "\n";
819 sl.setText(string.str().c_str());
825 void VVideoLiveTV::displayOSD(bool newNowNextData)
827 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
828 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(true);
829 osd.setVisible(true);
833 updatePosterBanner();
837 if (osdposterbanner.getVisible()) osdposterbanner.draw();
842 toupdate=*osd.getRegion();
845 if (osdposterbanner.getVisible()) {
846 boxstack->update(this);
848 boxstack->update(this, &toupdate);
851 bool setTimer = true;
852 if (vas) setTimer = false;
853 if (textUnavailable.getVisible()) setTimer = false;
855 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
858 void VVideoLiveTV::clearScreen()
860 Timers::getInstance()->cancelTimer(this, 1);
862 textUnavailable.setVisible(false);
863 osd.setVisible(false);
864 osdposterbanner.setVisible(false);
866 okTriggeredOSD = false;
869 boxstack->update(this);
871 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
872 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
875 void VVideoLiveTV::showUnavailable()
877 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
878 textUnavailable.setVisible(true);
879 textUnavailable.draw();
881 if (!osd.getVisible()) displayOSD(true);
883 boxstack->update(this, textUnavailable.getRegion());
886 void VVideoLiveTV::setClock()
892 localtime_r(&t, &tms);
893 strftime(timeString, 19, "%H:%M", &tms);
894 clock.setText(timeString);
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)
901 Timers::getInstance()->setTimerT(this, 2, dt);
904 void VVideoLiveTV::timercall(int ref)
910 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
912 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
914 Message* m = new Message();
915 m->message = Message::CHANNEL_CHANGE;
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.");
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)
928 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
929 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
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.");
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());
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.");
951 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
953 if (osd.getVisible())
956 boxstack->update(this, osd.getRegion());
958 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
962 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
965 if (streamType ==VDR::VIDEO) {
966 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
968 BoxStack::getInstance()->remove(vtxt);
972 if (changeType == INDEX)
974 newChannel = newData;
976 else if (changeType == NUMBER)
979 for(i = 0; i < chanList->size(); i++)
981 if ((*chanList)[i]->number == (UINT)newData)
988 if (i == chanList->size())
994 else if (changeType == OFFSET)
996 if (newData == UP) newChannel = upChannel(currentChannelIndex);
997 else newChannel = downChannel(currentChannelIndex);
999 else if (changeType == PREVIOUS)
1001 newChannel = previousChannelIndex;
1005 return false; // bad input
1008 if (newChannel == currentChannelIndex) return true;
1010 previousChannelIndex = currentChannelIndex;
1011 currentChannelIndex = newChannel;
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);
1019 bufferBar.setPercent(0);
1021 #ifndef VOMP_PLATTFORM_MVP
1024 // Blank out the symbols
1025 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1029 sAudioChannels.setVisible(false);
1030 sAspectRatio.setVisible(false);
1032 reslogo.setVisible(false);
1033 dolbylogo.setVisible(false);
1034 txtlogo.setVisible(false);
1038 sAudioChannels.setVisible(false);
1039 sAspectRatio.setVisible(false);
1044 // Remove other stuff
1045 if (textUnavailable.getVisible())
1047 textUnavailable.setVisible(false);
1051 #ifndef VOMP_PLATTFORM_MVP
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);
1063 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1070 BoxStack::getInstance()->update(this);
1075 void VVideoLiveTV::processMessage(Message* m)
1077 if (m->message == Message::MOUSE_LBDOWN)
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()) {
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);
1097 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1101 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1104 else if (m->message == Message::CHANNEL_CHANGE)
1106 channelChange(NUMBER, m->parameter.num);
1107 osdChannelIndex = currentChannelIndex;
1108 if (m->tag == 1) displayOSD(true);
1110 else if (m->message == Message::CHILD_CLOSE)
1118 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
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);
1123 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
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);
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);
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);
1148 case 0x11: { //videotext
1149 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1151 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter.num & 0xFFFF));
1155 BoxStack::getInstance()->update(vas);
1156 //BoxStack::getInstance()->update(&osd); //eveil error
1158 BoxStack::getInstance()->update(this, osd.getRegion());
1162 else if (m->message == Message::PLAYER_EVENT)
1164 switch (m->parameter.num)
1166 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1168 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1169 Command::getInstance()->connectionLost();
1173 case PlayerLiveTV::STREAM_END:
1175 // Message comes from playerlivetv through master mutex, so can do anything here
1180 case PlayerLiveTV::ASPECT43:
1183 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1185 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
1188 BoxStack::getInstance()->update(this, &wssRegion);
1192 #ifndef VOMP_PLATTFORM_MVP
1194 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1197 osdv->updateBackgroundColor(DrawStyle::BLACK);
1201 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1202 sAspectRatio.setVisible(true);
1204 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1207 BoxStack::getInstance()->update(this, osd.getRegion());
1212 case PlayerLiveTV::ASPECT169:
1215 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1217 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
1220 BoxStack::getInstance()->update(this, &wssRegion);
1224 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1225 sAspectRatio.setVisible(true);
1227 #ifndef VOMP_PLATTFORM_MVP
1229 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1232 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
1236 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1239 BoxStack::getInstance()->update(this, osd.getRegion());
1244 case PlayerLiveTV::PREBUFFERING:
1246 preBuffering = m->tag;
1247 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1248 bufferBar.setPercent(preBuffering);
1250 if (osd.getVisible())
1252 bufferBar.setVisible(true);
1255 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1256 BoxStack::getInstance()->update(this, &r);
1258 if (preBuffering == 100)
1260 doAudioChannelSymbol();
1268 void VVideoLiveTV::doAudioChannelSymbol()
1271 Channel* currentChannel = (*chanList)[osdChannelIndex];
1273 bool multiAudio = false;
1274 if (Audio::getInstance()->supportsAc3()) {
1275 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1277 if (currentChannel->numAPids > 1) multiAudio = true;
1279 #ifndef VOMP_PLATTFORM_MVP
1282 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1285 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1286 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1287 sAudioChannels.setVisible(true);
1291 dolbylogo.setVisible(true);
1292 txtlogo.setVisible(true);
1294 if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
1295 else info.setStaticArtwork(sa_txtoff);
1296 txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
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);
1304 Demuxer* demux=Demuxer::getInstance();
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) {
1311 info.setStaticArtwork(sa_sd576i);
1312 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1314 info.setStaticArtwork(sa_hd720p);
1315 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1317 info.setStaticArtwork(sa_hd1080i);
1318 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1319 default: // we assume sd
1320 reslogo.setVisible(false);
1324 reslogo.setVisible(false);
1328 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1329 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1330 sAudioChannels.setVisible(true);
1333 if (osd.getVisible())
1335 sAudioChannels.draw();
1337 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1341 BoxStack::getInstance()->update(this, &r);
1345 UINT VVideoLiveTV::upChannel(UINT index)
1347 if (index == (chanList->size() - 1)) // at the end
1348 return 0; // so go to start
1353 UINT VVideoLiveTV::downChannel(UINT index)
1355 if (index == 0) // at the start
1356 return chanList->size() - 1; // so go to end
1361 void VVideoLiveTV::toggleChopSides()
1363 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1365 if (videoMode == Video::NORMAL)
1367 videoMode = Video::LETTERBOX;
1368 video->setMode(Video::LETTERBOX);
1372 videoMode = Video::NORMAL;
1373 video->setMode(Video::NORMAL);
1377 void VVideoLiveTV::updatePosterBanner()
1379 #ifndef VOMP_PLATTFORM_MVP
1381 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1383 osdposterbanner.setVisible(false);
1389 Event* toShow = NULL;
1390 if (eventList && eventList->size()) {
1391 toShow = (*eventList)[0];
1392 Channel* currentChannel = (*chanList)[osdChannelIndex];
1393 toShow->loadinfos(currentChannel->number);
1400 bool posterscale=true;
1401 if (toShow->movieInfo) {
1402 poster=toShow->movieInfo->poster;
1404 if (toShow->seriesInfo) {
1405 if (toShow->seriesInfo->banners.size()) {
1406 poster=toShow->seriesInfo->banners[0];
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];
1414 if (poster.height) {
1415 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1416 osdposterbanner.setVisible(true);
1418 osdposterbanner.setVisible(false);
1421 osdposterbanner.setVisible(false);
1427 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1429 drawBitmap(posX, posY, bm,region);
1431 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1432 boxstack->update(this, &r);
1435 void VVideoLiveTV::clearOSD()
1437 rectangle(area, DrawStyle(0,0,0,0));
1438 boxstack->update(this, &area);
1441 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
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);