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"
48 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
49 : osdBack(0, 0, 0, 128)
51 vdr = VDR::getInstance();
52 boxstack = BoxStack::getInstance();
53 video = Video::getInstance();
58 vchannelList = tvchannelList;
59 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
61 currentChannelIndex = 0;
62 previousChannelIndex = 0;
69 // Convert channel number to index
71 for(i = 0; i < chanList->size(); i++)
73 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
75 currentChannelIndex = i;
83 videoMode = video->getMode();
85 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
87 streamType = VDR::VIDEO;
88 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
92 streamType = VDR::RADIO;
93 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
97 setSize(video->getScreenWidth(), video->getScreenHeight());
99 DrawStyle transparent(0, 0, 0, 0);
100 setBackgroundColour(transparent);
103 char* optionWSS = vdr->configLoad("General", "WSS");
106 if (strstr(optionWSS, "Yes")) dowss = true;
109 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
113 wss.setFormat(video->getFormat());
119 wssRegion.w = video->getScreenWidth();
123 // This variable is set to true if the user pressed OK to bring the OSD on screen
124 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
125 okTriggeredOSD = false;
128 info.setChannelLogo(initialChannelNumber);
129 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
131 if (osdv && streamType == VDR::RADIO) {
132 radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
133 radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
134 radioChannelLogo.setVisible(true);
135 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
136 add(&radioChannelLogo);
139 osdposterbanner.setPosition(20,20);
140 osdposterbanner.setBackgroundColour(osdBack);
141 osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
142 osdposterbanner.setVisible(false);
143 add(&osdposterbanner);
147 osd.setBackgroundColour(osdBack);
148 osd.setPosition(0, video->getScreenHeight() - 150);
149 osd.setSize(video->getScreenWidth(), 150);
150 osd.setVisible(false);
153 int channellogomove=0;
155 osdChannelLogo.setBackgroundColour(osdBack);
156 osdChannelLogo.setPosition(30,5);
157 osdChannelLogo.setSize(60,60);
158 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
159 osd.add(&osdChannelLogo);
160 channellogomove=30-5;
163 clock.setBackgroundColour(osdBack);
164 clock.setPosition(osd.getWidth() - 100, 4);
165 clock.setSize(90, 30);
168 osdChanNum.setBackgroundColour(osdBack);
169 osdChanNum.setPosition(60+channellogomove, 4);
170 osdChanNum.setSize((numberWidth*10) + 22, getFontHeight()+5); // 10 px = width of number chars in font
171 osd.add(&osdChanNum);
173 osdChanName.setBackgroundColour(osdBack);
174 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
175 osdChanName.setSize(300, 30);
176 osd.add(&osdChanName);
178 boxRed.setBackgroundColour(DrawStyle::RED);
179 boxRed.setPosition(54, 104);
180 boxRed.setSize(18, 16);
183 boxGreen.setBackgroundColour(DrawStyle::GREEN);
184 boxGreen.setPosition(220, 104);
185 boxGreen.setSize(18, 16);
188 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
189 boxYellow.setPosition(390, 104);
190 boxYellow.setSize(18, 16);
193 boxBlue.setBackgroundColour(DrawStyle::BLUE);
194 boxBlue.setPosition(560, 104);
195 boxBlue.setSize(18, 16);
198 textRed.setBackgroundColour(osdBack);
199 textRed.setPosition(boxRed.getX2(), 98);
200 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
201 textRed.setText(tr("Summary"));
204 if (streamType == VDR::VIDEO)
206 textGreen.setBackgroundColour(osdBack);
207 textGreen.setPosition(boxGreen.getX2(), 98);
208 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
209 textGreen.setText(tr("Audio"));
213 textYellow.setBackgroundColour(osdBack);
214 textYellow.setPosition(boxYellow.getX2(), 98);
215 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
216 textYellow.setText(tr("Teletext"));
217 osd.add(&textYellow);
219 textBlue.setBackgroundColour(osdBack);
220 textBlue.setPosition(boxBlue.getX2(), 98);
221 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
222 textBlue.setText(tr("EPG"));
225 sl.setBackgroundColour(osdBack);
226 sl.setPosition(90, 36);
232 summary.setBackgroundColour(osdBack);
233 summary.setPosition(0, video->getScreenHeight() - 300);
234 summary.setSize(video->getScreenWidth(), 150);
235 summary.setVisible(false);
238 textSummary.setBackgroundColour(osdBack);
239 textSummary.setPosition(40, 10);
240 textSummary.setSize(video->getScreenWidth() - 80, 130);
241 textSummary.setParaMode(true);
242 summary.add(&textSummary);
244 summaryBlackLine.setBackgroundColour(DrawStyle::BLACK);
245 summaryBlackLine.setPosition(0, summary.getHeight() - 4);
246 summaryBlackLine.setSize(summary.getWidth(), 4);
247 summary.add(&summaryBlackLine);
249 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
250 sAspectRatio.nextColour = DrawStyle::SELECTHIGHLIGHT;
251 sAspectRatio.setVisible(false);
252 osd.add(&sAspectRatio);
254 bufferBar.setPosition(osd.getWidth() - 90, 70);
255 bufferBar.setSize(40, 20);
256 bufferBar.setVisible(true);
259 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
260 sAudioChannels.nextColour = DrawStyle::SELECTHIGHLIGHT;
261 sAudioChannels.setVisible(false);
262 osd.add(&sAudioChannels);
264 textUnavailable.setBackgroundColour(osdBack);
265 textUnavailable.setPosition(60, 30);
266 textUnavailable.setSize(osd.getWidth() - 120, 30);
267 textUnavailable.setText(tr("Channel Unavailable"));
268 textUnavailable.setVisible(false);
269 add(&textUnavailable);
272 Region r1 = summary.getRegionR();
273 Region r2 = osd.getRegionR();
274 osdSummaryRegion = r1 + r2;
276 vdisplay.mode=Fullscreen;
277 vdisplay.fallbackMode=Fullscreen;
284 void VVideoLiveTV::preDelete()
289 VVideoLiveTV::~VVideoLiveTV()
292 video->setDefaultAspect();
296 void VVideoLiveTV::delData()
300 int eventListSize = eventList->size();
301 for(int i = 0; i < eventListSize; i++)
303 delete (*eventList)[i];
312 int VVideoLiveTV::handleCommand(int command)
318 if (osd.getVisible() && !textUnavailable.getVisible())
323 // else drop through to stop
328 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
332 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
335 if (Remote::getInstance()->mayHaveFewButtons()) {
336 if (okTriggeredOSD) doUpDown(false);
337 else doChanUpDown(UP);
345 if (Remote::getInstance()->mayHaveFewButtons()) {
346 if (okTriggeredOSD) doUpDown(true);
347 else doChanUpDown(DOWN);
363 // Continue new remote only...
364 case Remote::CHANNELUP:
369 case Remote::CHANNELDOWN:
375 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
377 // DF_LEFT and DF_RIGHT never get here because they are stolen
378 // by command as vol- and vol+
380 // Old remote. Decide what to do based on whether
381 // OK was pressed - osd shown manually, use up/down for epg nav
382 // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
386 // Old remote, decide what to do based on okTriggeredOSD
387 if (okTriggeredOSD) doUpDown(false);
388 else doChanUpDown(UP);
391 case Remote::DF_DOWN:
393 // Old remote, decide what to do based on okTriggeredOSD
394 if (okTriggeredOSD) doUpDown(true);
395 else doChanUpDown(DOWN);
399 // END NEW/OLD REMOTE STUFF
401 case Remote::PREVCHANNEL:
403 channelChange(PREVIOUS, 0);
404 osdChannelIndex = currentChannelIndex;
437 // key in channel number
444 if (streamType == VDR::VIDEO) doAudioSelector();
449 if (streamType ==VDR::VIDEO)
451 doTeletext(); //TODO: Add a selector for subtitles or teletext
462 if (streamType == VDR::VIDEO)
463 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
470 void VVideoLiveTV::go()
474 boxstack->update(this);
479 player->go(currentChannelIndex);
482 void VVideoLiveTV::stop()
484 Timers::getInstance()->cancelTimer(this, 1);
485 Timers::getInstance()->cancelTimer(this, 2);
490 void VVideoLiveTV::doLeftRight(bool right)
492 if (osd.getVisible())
494 if (right) osdChannelIndex = upChannel(osdChannelIndex);
495 else osdChannelIndex = downChannel(osdChannelIndex);
499 osdChannelIndex = currentChannelIndex;
504 void VVideoLiveTV::doUpDown(bool down)
506 if (osd.getVisible())
520 void VVideoLiveTV::doChanUpDown(int which)
522 channelChange(OFFSET, which);
523 osdChannelIndex = currentChannelIndex;
527 void VVideoLiveTV::doOK()
529 if (osd.getVisible())
534 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
536 channelChange(NUMBER, newChannel);
537 osdChannelIndex = currentChannelIndex;
540 else if (osdChannelIndex == currentChannelIndex)
546 channelChange(INDEX, osdChannelIndex);
552 osdChannelIndex = currentChannelIndex;
554 okTriggeredOSD = true;
558 void VVideoLiveTV::doSummary()
561 Channel* currentChannel = (*chanList)[osdChannelIndex];
562 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
567 sort(eventList->begin(), eventList->end(), EventSorter());
569 if (eventList->size() < 1) return;
570 Event* event = (*eventList)[0];
571 event->loadinfos(currentChannel->number);
573 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
576 boxstack->update(vr);
578 if (summary.getVisible())
580 summary.setVisible(false);
582 boxstack->update(this, summary.getRegion());
583 Timers::getInstance()->setTimerD(this, 1, 8); // Restart a timer to get rid of osd
587 summary.setVisible(true);
589 if (osd.getVisible())
591 Timers::getInstance()->cancelTimer(this, 1);
600 void VVideoLiveTV::doKey(int command)
602 if (!osd.getVisible()) // First key. prep the data
605 updatePosterBanner();
610 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
611 keyingInput[0] = command;
614 char* keyingString = new char[numberWidth + 1];
615 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
616 keyingString[numberWidth] = '\0';
618 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
620 if (keying == numberWidth)
623 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
625 channelChange(NUMBER, newChannel);
626 osdChannelIndex = currentChannelIndex;
627 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
628 displayOSD(true); // this will put one back if required
632 osdChanNum.setText(keyingString);
634 if (!osd.getVisible())
636 osd.setVisible(true);
643 boxstack->update(this, osd.getRegion());
644 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
646 delete[] keyingString;
649 void VVideoLiveTV::doTeletext(bool subtitlemode)
651 if (streamType !=VDR::VIDEO) return;
652 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
659 // and reset the display - this is a copy from setNowNextData
660 char formatChanNum[20];
661 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
662 osdChanNum.setText(formatChanNum);
663 osdChanName.setText((*chanList)[osdChannelIndex]->name);
665 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
666 if (osd.getVisible()) clearScreen();
668 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
670 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
671 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
674 vtxv->setSubtitleMode(subtitlemode);
679 BoxStack::getInstance()->add(vtxv);
681 BoxStack::getInstance()->update(this);
682 BoxStack::getInstance()->update(vtxv);
685 void VVideoLiveTV::doAudioSelector()
687 // If the osd is already visisble there might be a timer for it
688 Timers::getInstance()->cancelTimer(this, 1);
689 //This causes a deadlock with the timertrhread itself is locked
696 // and reset the display - this is a copy from setNowNextData
697 char formatChanNum[20];
698 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
699 osdChanNum.setText(formatChanNum);
700 osdChanName.setText((*chanList)[osdChannelIndex]->name);
702 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
703 int subtitleType=0x10;
704 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
705 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
706 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
708 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
712 subtitleType=0xFF; //turnedOff
718 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
719 subtitleType,subtitleChannel,NULL);
721 vas->setBackgroundColour(osdBack);
722 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
725 // make vas != null and displayOSD will not set a timer or do any boxstack update
726 summary.setVisible(false);
727 if (osd.getVisible()) displayOSD(false);
728 else displayOSD(true);
731 BoxStack::getInstance()->add(vas);
732 BoxStack::getInstance()->update(this);
733 BoxStack::getInstance()->update(vas);
736 void VVideoLiveTV::doEPG()
738 if (osd.getVisible()) clearScreen();
740 if (!Command::getInstance()->advMenues()) {
742 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
745 boxstack->update(vepg);
747 Channel* currentChannel = (*chanList)[osdChannelIndex];
748 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
751 boxstack->update(vepg);
755 void VVideoLiveTV::setNowNextData()
759 Channel* currentChannel = (*chanList)[osdChannelIndex];
761 char formatChanNum[20];
762 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
763 osdChanNum.setText(formatChanNum);
764 osdChanName.setText(currentChannel->name);
766 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
770 sl.addOption(tr("No channel data available"), 0, 1);
774 sort(eventList->begin(), eventList->end(), EventSorter());
776 char tempString[300];
777 char tempString2[300];
780 int eventListSize = eventList->size();
781 for(int i = 0; i < eventListSize; i++)
783 event = (*eventList)[i];
785 //btime = localtime((time_t*)&event->time);
786 time_t etime = event->time;
787 btime = localtime(&etime);
789 strftime(tempString2, 299, "%0H:%0M ", btime);
791 strftime(tempString2, 299, "%H:%M ", btime);
793 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
795 sl.addOption(tempString, (ULONG)event, (i==0));
800 void VVideoLiveTV::setSummaryData()
802 // If osd is not being displayed, sl will be filled with now, current channel
803 // If the display was already on, sl will have programme to show summary for, not necessarily current channel and now
804 Event* selectedEvent = (Event*)sl.getCurrentOptionData();
808 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "No summary");
809 textSummary.setText(tr("No summary available"));
813 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Summary: %s", selectedEvent->description);
814 textSummary.setText(selectedEvent->description);
818 void VVideoLiveTV::displayOSD(bool newNowNextData)
820 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
821 osd.setVisible(true);
825 updatePosterBanner();
829 if (osdposterbanner.getVisible()) osdposterbanner.draw();
833 if (summary.getVisible())
837 toupdate=osdSummaryRegion;
841 toupdate=*osd.getRegion();
844 if (osdposterbanner.getVisible()) {
845 boxstack->update(this);
847 boxstack->update(this, &toupdate);
850 bool setTimer = true;
851 if (vas) setTimer = false;
852 if (summary.getVisible()) setTimer = false;
853 if (textUnavailable.getVisible()) setTimer = false;
855 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
858 void VVideoLiveTV::clearScreen()
860 if (!summary.getVisible()) Timers::getInstance()->cancelTimer(this, 1);
862 textUnavailable.setVisible(false);
863 osd.setVisible(false);
864 summary.setVisible(false);
865 osdposterbanner.setVisible(false);
867 okTriggeredOSD = false;
870 boxstack->update(this);
872 (static_cast<PlayerLiveTV*>(player))->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()
891 struct tm* tms = localtime(&t);
892 strftime(timeString, 19, "%H:%M", tms);
893 clock.setText(timeString);
895 time_t dt = 60 - (t % 60); // seconds to the next minute
896 if (dt == 0) dt = 60; // advance a whole minute if necessary
897 dt += t; // get a time_t value for it rather than using duration
898 // (so it will occur at the actual second and not second and a half)
900 Timers::getInstance()->setTimerT(this, 2, dt);
903 void VVideoLiveTV::timercall(int ref)
909 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
911 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
913 Message* m = new Message();
914 m->message = Message::CHANNEL_CHANGE;
916 m->parameter = newChannel;
917 m->tag = 1; // signal to call displayOSD();
918 Command::getInstance()->postMessageFromOuterSpace(m);
919 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
923 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
924 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
925 if (preBuffering < 100)
927 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
928 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
931 bool osdpbvisible=osdposterbanner.getVisible();
932 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
933 osd.setVisible(false);
934 osdposterbanner.setVisible(false);
935 okTriggeredOSD = false;
936 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
938 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
939 if (osdpbvisible) boxstack->update(this);
940 else boxstack->update(this, osd.getRegion());
942 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
943 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(false);
944 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
949 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
951 if (osd.getVisible())
954 boxstack->update(this, osd.getRegion());
956 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
960 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
963 if (streamType ==VDR::VIDEO) {
964 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
966 BoxStack::getInstance()->remove(vtxt);
970 if (changeType == INDEX)
972 newChannel = newData;
974 else if (changeType == NUMBER)
977 for(i = 0; i < chanList->size(); i++)
979 if ((*chanList)[i]->number == (UINT)newData)
986 if (i == chanList->size())
992 else if (changeType == OFFSET)
994 if (newData == UP) newChannel = upChannel(currentChannelIndex);
995 else newChannel = downChannel(currentChannelIndex);
997 else if (changeType == PREVIOUS)
999 newChannel = previousChannelIndex;
1003 return false; // bad input
1006 if (newChannel == currentChannelIndex) return true;
1008 previousChannelIndex = currentChannelIndex;
1009 currentChannelIndex = newChannel;
1013 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
1014 player->setChannel(currentChannelIndex);
1015 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
1017 // Blank out the symbols
1018 sAspectRatio.setVisible(false);
1019 bufferBar.setPercent(0);
1020 sAudioChannels.setVisible(false);
1022 // Remove other stuff
1023 if (textUnavailable.getVisible())
1025 textUnavailable.setVisible(false);
1028 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1031 Channel* currentChannel = (*chanList)[currentChannelIndex];
1032 if (currentChannel) {
1033 info.setChannelLogo(currentChannel->number);
1034 if (streamType == VDR::RADIO) {
1035 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1036 radioChannelLogo.setVisible(true);
1038 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1044 BoxStack::getInstance()->update(this);
1049 void VVideoLiveTV::processMessage(Message* m)
1051 if (m->message == Message::MOUSE_LBDOWN)
1053 //check if press is outside this view! then simulate cancel
1054 int x=(m->parameter>>16)-osd.getScreenX();
1055 int y=(m->parameter&0xFFFF)-osd.getScreenY();
1056 if (osd.getVisible()) {
1058 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
1059 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y )) {
1060 BoxStack::getInstance()->handleCommand(Remote::RED);
1061 } else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
1062 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y)){
1063 BoxStack::getInstance()->handleCommand(Remote::GREEN);
1064 } else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
1065 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
1066 BoxStack::getInstance()->handleCommand(Remote::YELLOW);
1067 } else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
1068 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y )){
1069 BoxStack::getInstance()->handleCommand(Remote::BLUE);
1071 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1075 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1078 else if (m->message == Message::CHANNEL_CHANGE)
1080 channelChange(NUMBER, m->parameter);
1081 osdChannelIndex = currentChannelIndex;
1082 if (m->tag == 1) displayOSD(true);
1084 else if (m->message == Message::CHILD_CLOSE)
1092 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1094 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter);
1095 player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16,(m->parameter & 0xFF000000)>>24);
1097 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1099 if (streamType !=VDR::VIDEO) return;
1100 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter);
1101 int type=((m->parameter & 0xFF0000)>>16);
1103 case 0x10: { //dvbsubtitle
1104 if (streamType == VDR::VIDEO){
1105 player->setSubtitleChannel((m->parameter & 0xFFFF));
1106 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1107 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1108 if (vtxt && vtxt->isInSubtitleMode()) {
1109 BoxStack::getInstance()->remove(vtxt);
1113 case 0xFF: { //nosubtitles
1114 if (streamType == VDR::VIDEO){
1115 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1116 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1117 if (vtxt && vtxt->isInSubtitleMode()) {
1118 BoxStack::getInstance()->remove(vtxt);
1122 case 0x11: { //videotext
1123 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1125 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1129 BoxStack::getInstance()->update(vas);
1130 //BoxStack::getInstance()->update(&osd); //eveil error
1132 BoxStack::getInstance()->update(this, osd.getRegion());
1136 else if (m->message == Message::PLAYER_EVENT)
1138 switch(m->parameter)
1140 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1142 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1143 Command::getInstance()->connectionLost();
1147 case PlayerLiveTV::STREAM_END:
1149 // Message comes from playerlivetv through master mutex, so can do anything here
1154 case PlayerLiveTV::ASPECT43:
1157 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1159 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
1162 BoxStack::getInstance()->update(this, &wssRegion);
1166 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1167 sAspectRatio.setVisible(true);
1169 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1172 BoxStack::getInstance()->update(this, osd.getRegion());
1177 case PlayerLiveTV::ASPECT169:
1180 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1182 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
1185 BoxStack::getInstance()->update(this, &wssRegion);
1189 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1190 sAspectRatio.setVisible(true);
1192 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1195 BoxStack::getInstance()->update(this, osd.getRegion());
1200 case PlayerLiveTV::PREBUFFERING:
1202 preBuffering = m->tag;
1203 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1204 bufferBar.setPercent(preBuffering);
1206 if (osd.getVisible())
1208 bufferBar.setVisible(true);
1211 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1212 BoxStack::getInstance()->update(this, &r);
1214 if (preBuffering == 100)
1216 doAudioChannelSymbol();
1224 void VVideoLiveTV::doAudioChannelSymbol()
1227 Channel* currentChannel = (*chanList)[osdChannelIndex];
1229 bool multiAudio = false;
1230 if (Audio::getInstance()->supportsAc3()) {
1231 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1233 if (currentChannel->numAPids > 1) multiAudio = true;
1237 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1238 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1239 sAudioChannels.setVisible(true);
1241 if (osd.getVisible())
1243 sAudioChannels.draw();
1245 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1249 BoxStack::getInstance()->update(this, &r);
1253 UINT VVideoLiveTV::upChannel(UINT index)
1255 if (index == (chanList->size() - 1)) // at the end
1256 return 0; // so go to start
1261 UINT VVideoLiveTV::downChannel(UINT index)
1263 if (index == 0) // at the start
1264 return chanList->size() - 1; // so go to end
1269 void VVideoLiveTV::toggleChopSides()
1271 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1273 if (videoMode == Video::NORMAL)
1275 videoMode = Video::LETTERBOX;
1276 video->setMode(Video::LETTERBOX);
1280 videoMode = Video::NORMAL;
1281 video->setMode(Video::NORMAL);
1285 void VVideoLiveTV::updatePosterBanner()
1287 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1289 osdposterbanner.setVisible(false);
1292 Event* toShow = NULL;
1293 if (eventList && eventList->size()) {
1294 toShow = (*eventList)[0];
1295 Channel* currentChannel = (*chanList)[osdChannelIndex];
1296 toShow->loadinfos(currentChannel->number);
1303 bool posterscale=true;
1304 if (toShow->movieInfo) {
1305 poster=toShow->movieInfo->poster;
1307 if (toShow->seriesInfo) {
1308 if (toShow->seriesInfo->banners.size()) {
1309 poster=toShow->seriesInfo->banners[0];
1311 } else if (toShow->seriesInfo->seasonposter.height) {
1312 poster=toShow->seriesInfo->seasonposter;
1313 } else if (toShow->seriesInfo->posters.size()) {
1314 poster=toShow->seriesInfo->posters[0];
1317 if (poster.height) {
1318 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1319 osdposterbanner.setVisible(true);
1321 osdposterbanner.setVisible(false);
1324 osdposterbanner.setVisible(false);
1330 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1332 drawBitmap(posX, posY, bm,region);
1334 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1335 boxstack->update(this, &r);
1338 void VVideoLiveTV::clearOSD()
1340 rectangle(area, DrawStyle(0,0,0,0));
1341 boxstack->update(this, &area);
1344 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1347 r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1348 //now convert to our display
1349 float scalex=720.f/((float) (region.framewidth+1));
1350 float scaley=576.f/((float) (region.frameheight+1));
1351 r.x=floor(scalex*((float)r.x));
1352 r.y=floor(scaley*((float)r.y));
1353 r.w=ceil(scalex*((float)r.w))+1.f;
1354 r.h=ceil(scaley*((float)r.h))+1.f;
1355 rectangle(r, DrawStyle(0,0,0,0));
1356 boxstack->update(this, &r);