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"
50 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
52 vdr = VDR::getInstance();
53 boxstack = BoxStack::getInstance();
54 video = Video::getInstance();
59 vchannelList = tvchannelList;
60 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
62 currentChannelIndex = 0;
63 previousChannelIndex = 0;
70 // Convert channel number to index
72 for(i = 0; i < chanList->size(); i++)
74 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
76 currentChannelIndex = i;
84 videoMode = video->getMode();
86 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
88 streamType = VDR::VIDEO;
89 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
93 streamType = VDR::RADIO;
94 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
98 setSize(video->getScreenWidth(), video->getScreenHeight());
100 DrawStyle transparent(0, 0, 0, 0);
101 setBackgroundColour(transparent);
104 char* optionWSS = vdr->configLoad("General", "WSS");
107 if (strstr(optionWSS, "Yes")) dowss = true;
110 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
114 wss.setFormat(video->getFormat());
120 wssRegion.w = video->getScreenWidth();
124 // This variable is set to true if the user pressed OK to bring the OSD on screen
125 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
126 okTriggeredOSD = false;
129 info.setChannelLogo(initialChannelNumber);
130 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
132 if (osdv && streamType == VDR::RADIO) {
133 radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
134 radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
135 radioChannelLogo.setVisible(true);
136 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
137 add(&radioChannelLogo);
140 osdposterbanner.setPosition(20,20);
141 osdposterbanner.setBackgroundColour(DrawStyle::OSDBACKGROUND);
142 osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
143 osdposterbanner.setVisible(false);
144 add(&osdposterbanner);
148 osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
149 osd.setPosition(0, video->getScreenHeight() - 150);
150 osd.setSize(video->getScreenWidth(), 150);
151 osd.setVisible(false);
154 int channellogomove=0;
156 osdChannelLogo.setBackgroundColour(DrawStyle::OSDBACKGROUND);
157 osdChannelLogo.setPosition(30,5);
158 osdChannelLogo.setSize(60,60);
159 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
160 osd.add(&osdChannelLogo);
161 channellogomove=30-5;
164 clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
165 clock.setPosition(osd.getWidth() - 100, 4);
166 clock.setSize(90, 30);
169 osdChanNum.setBackgroundColour(DrawStyle::OSDBACKGROUND);
170 osdChanNum.setPosition(60+channellogomove, 4);
171 osdChanNum.setSize((numberWidth*10) + 22, getFontHeight()+5); // 10 px = width of number chars in font
172 osd.add(&osdChanNum);
174 osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
175 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
176 osdChanName.setSize(300, 30);
177 osd.add(&osdChanName);
179 boxRed.setBackgroundColour(DrawStyle::RED);
180 boxRed.setPosition(54, 104);
181 boxRed.setSize(18, 16);
184 boxGreen.setBackgroundColour(DrawStyle::GREEN);
185 boxGreen.setPosition(220, 104);
186 boxGreen.setSize(18, 16);
189 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
190 boxYellow.setPosition(390, 104);
191 boxYellow.setSize(18, 16);
194 boxBlue.setBackgroundColour(DrawStyle::BLUE);
195 boxBlue.setPosition(560, 104);
196 boxBlue.setSize(18, 16);
199 textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
200 textRed.setPosition(boxRed.getX2(), 98);
201 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
202 textRed.setText(tr("Summary"));
205 if (streamType == VDR::VIDEO)
207 textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
208 textGreen.setPosition(boxGreen.getX2(), 98);
209 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
210 textGreen.setText(tr("Audio"));
214 textYellow.setBackgroundColour(DrawStyle::OSDBACKGROUND);
215 textYellow.setPosition(boxYellow.getX2(), 98);
216 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
217 textYellow.setText(tr("Teletext"));
218 osd.add(&textYellow);
220 textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
221 textBlue.setPosition(boxBlue.getX2(), 98);
222 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
223 textBlue.setText(tr("EPG"));
226 sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
227 sl.setPosition(90, 36);
232 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
233 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
234 sAspectRatio.setVisible(false);
235 osd.add(&sAspectRatio);
237 bufferBar.setPosition(osd.getWidth() - 90, 70);
238 bufferBar.setSize(40, 20);
239 bufferBar.setVisible(true);
242 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
243 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
244 sAudioChannels.setVisible(false);
245 osd.add(&sAudioChannels);
247 textUnavailable.setBackgroundColour(DrawStyle::OSDBACKGROUND);
248 textUnavailable.setPosition(60, 30);
249 textUnavailable.setSize(osd.getWidth() - 120, 30);
250 textUnavailable.setText(tr("Channel Unavailable"));
251 textUnavailable.setVisible(false);
252 add(&textUnavailable);
255 vdisplay.mode=Fullscreen;
256 vdisplay.fallbackMode=Fullscreen;
263 void VVideoLiveTV::preDelete()
268 VVideoLiveTV::~VVideoLiveTV()
271 video->setDefaultAspect();
275 void VVideoLiveTV::delData()
279 int eventListSize = eventList->size();
280 for(int i = 0; i < eventListSize; i++)
282 delete (*eventList)[i];
290 int VVideoLiveTV::handleCommand(int command)
296 if (osd.getVisible() && !textUnavailable.getVisible())
301 // else drop through to stop
306 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
310 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
313 if (Remote::getInstance()->mayHaveFewButtons()) {
314 if (okTriggeredOSD) doUpDown(false);
315 else doChanUpDown(UP);
323 if (Remote::getInstance()->mayHaveFewButtons()) {
324 if (okTriggeredOSD) doUpDown(true);
325 else doChanUpDown(DOWN);
341 // Continue new remote only...
342 case Remote::CHANNELUP:
347 case Remote::CHANNELDOWN:
353 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
355 // DF_LEFT and DF_RIGHT never get here because they are stolen
356 // by command as vol- and vol+
358 // Old remote. Decide what to do based on whether
359 // OK was pressed - osd shown manually, use up/down for epg nav
360 // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
364 // Old remote, decide what to do based on okTriggeredOSD
365 if (okTriggeredOSD) doUpDown(false);
366 else doChanUpDown(UP);
369 case Remote::DF_DOWN:
371 // Old remote, decide what to do based on okTriggeredOSD
372 if (okTriggeredOSD) doUpDown(true);
373 else doChanUpDown(DOWN);
377 // END NEW/OLD REMOTE STUFF
379 case Remote::PREVCHANNEL:
381 channelChange(PREVIOUS, 0);
382 osdChannelIndex = currentChannelIndex;
415 // key in channel number
422 if (streamType == VDR::VIDEO) doAudioSelector();
427 if (streamType ==VDR::VIDEO)
429 doTeletext(); //TODO: Add a selector for subtitles or teletext
440 if (streamType == VDR::VIDEO)
441 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
448 void VVideoLiveTV::go()
452 boxstack->update(this);
457 player->go(currentChannelIndex);
460 void VVideoLiveTV::stop()
462 Timers::getInstance()->cancelTimer(this, 1);
463 Timers::getInstance()->cancelTimer(this, 2);
468 void VVideoLiveTV::doLeftRight(bool right)
470 if (osd.getVisible())
472 if (right) osdChannelIndex = upChannel(osdChannelIndex);
473 else osdChannelIndex = downChannel(osdChannelIndex);
477 osdChannelIndex = currentChannelIndex;
482 void VVideoLiveTV::doUpDown(bool down)
484 if (osd.getVisible())
496 void VVideoLiveTV::doChanUpDown(int which)
498 channelChange(OFFSET, which);
499 osdChannelIndex = currentChannelIndex;
503 void VVideoLiveTV::doOK()
505 if (osd.getVisible())
510 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
512 channelChange(NUMBER, newChannel);
513 osdChannelIndex = currentChannelIndex;
516 else if (osdChannelIndex == currentChannelIndex)
522 channelChange(INDEX, osdChannelIndex);
528 osdChannelIndex = currentChannelIndex;
530 okTriggeredOSD = true;
534 void VVideoLiveTV::doSummary()
537 Channel* currentChannel = (*chanList)[osdChannelIndex];
538 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
543 sort(eventList->begin(), eventList->end(), EventSorter());
545 if (eventList->size() < 1) return;
546 Event* event = (*eventList)[0];
547 event->loadinfos(currentChannel->number);
549 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
552 boxstack->update(vr);
556 void VVideoLiveTV::doKey(int command)
558 if (!osd.getVisible()) // First key. prep the data
561 updatePosterBanner();
566 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
567 keyingInput[0] = command;
570 char* keyingString = new char[numberWidth + 1];
571 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
572 keyingString[numberWidth] = '\0';
574 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
576 if (keying == numberWidth)
579 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
581 channelChange(NUMBER, newChannel);
582 osdChannelIndex = currentChannelIndex;
583 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
584 displayOSD(true); // this will put one back if required
588 osdChanNum.setText(keyingString);
590 if (!osd.getVisible())
592 osd.setVisible(true);
599 boxstack->update(this, osd.getRegion());
600 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
602 delete[] keyingString;
605 void VVideoLiveTV::doTeletext(bool subtitlemode)
607 if (streamType !=VDR::VIDEO) return;
608 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
615 // and reset the display - this is a copy from setNowNextData
616 char formatChanNum[20];
617 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
618 osdChanNum.setText(formatChanNum);
619 osdChanName.setText((*chanList)[osdChannelIndex]->name);
621 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
622 if (osd.getVisible()) clearScreen();
624 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
626 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
627 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
630 vtxv->setSubtitleMode(subtitlemode);
635 BoxStack::getInstance()->add(vtxv);
637 BoxStack::getInstance()->update(this);
638 BoxStack::getInstance()->update(vtxv);
641 void VVideoLiveTV::doAudioSelector()
643 // If the osd is already visisble there might be a timer for it
644 Timers::getInstance()->cancelTimer(this, 1);
645 //This causes a deadlock with the timertrhread itself is locked
652 // and reset the display - this is a copy from setNowNextData
653 char formatChanNum[20];
654 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
655 osdChanNum.setText(formatChanNum);
656 osdChanName.setText((*chanList)[osdChannelIndex]->name);
658 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
659 int subtitleType=0x10;
660 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
661 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
662 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
664 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
668 subtitleType=0xFF; //turnedOff
674 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
675 subtitleType,subtitleChannel,NULL);
677 vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
678 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
681 // make vas != null and displayOSD will not set a timer or do any boxstack update
682 if (osd.getVisible()) displayOSD(false);
683 else displayOSD(true);
686 BoxStack::getInstance()->add(vas);
687 BoxStack::getInstance()->update(this);
688 BoxStack::getInstance()->update(vas);
691 void VVideoLiveTV::doEPG()
693 if (osd.getVisible()) clearScreen();
695 if (!Command::getInstance()->advMenues()) {
697 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
700 boxstack->update(vepg);
702 Channel* currentChannel = (*chanList)[osdChannelIndex];
703 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
706 boxstack->update(vepg);
710 void VVideoLiveTV::setNowNextData()
714 Channel* currentChannel = (*chanList)[osdChannelIndex];
716 char formatChanNum[20];
717 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
718 osdChanNum.setText(formatChanNum);
719 osdChanName.setText(currentChannel->name);
721 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
725 sl.setText(tr("No channel data available"));
729 sort(eventList->begin(), eventList->end(), EventSorter());
731 char tempString[300];
732 char tempString2[300];
735 int eventListSize = eventList->size();
736 std::stringstream string;
737 for(int i = 0; i < eventListSize; i++)
739 event = (*eventList)[i];
741 //btime = localtime((time_t*)&event->time);
742 time_t etime = event->time;
743 btime = localtime(&etime);
745 strftime(tempString2, 299, "%0H:%0M ", btime);
747 strftime(tempString2, 299, "%H:%M ", btime);
749 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
750 string << tempString << "\n";
752 sl.setText(string.str().c_str());
758 void VVideoLiveTV::displayOSD(bool newNowNextData)
760 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
761 osd.setVisible(true);
765 updatePosterBanner();
769 if (osdposterbanner.getVisible()) osdposterbanner.draw();
774 toupdate=*osd.getRegion();
777 if (osdposterbanner.getVisible()) {
778 boxstack->update(this);
780 boxstack->update(this, &toupdate);
783 bool setTimer = true;
784 if (vas) setTimer = false;
785 if (textUnavailable.getVisible()) setTimer = false;
787 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
790 void VVideoLiveTV::clearScreen()
792 Timers::getInstance()->cancelTimer(this, 1);
794 textUnavailable.setVisible(false);
795 osd.setVisible(false);
796 osdposterbanner.setVisible(false);
798 okTriggeredOSD = false;
801 boxstack->update(this);
803 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(false);
806 void VVideoLiveTV::showUnavailable()
808 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
809 textUnavailable.setVisible(true);
810 textUnavailable.draw();
812 if (!osd.getVisible()) displayOSD(true);
814 boxstack->update(this, textUnavailable.getRegion());
817 void VVideoLiveTV::setClock()
822 struct tm* tms = localtime(&t);
823 strftime(timeString, 19, "%H:%M", tms);
824 clock.setText(timeString);
826 time_t dt = 60 - (t % 60); // seconds to the next minute
827 if (dt == 0) dt = 60; // advance a whole minute if necessary
828 dt += t; // get a time_t value for it rather than using duration
829 // (so it will occur at the actual second and not second and a half)
831 Timers::getInstance()->setTimerT(this, 2, dt);
834 void VVideoLiveTV::timercall(int ref)
840 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
842 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
844 Message* m = new Message();
845 m->message = Message::CHANNEL_CHANGE;
847 m->parameter = newChannel;
848 m->tag = 1; // signal to call displayOSD();
849 Command::getInstance()->postMessageFromOuterSpace(m);
850 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
854 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
855 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
856 if (preBuffering < 100)
858 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
859 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
862 bool osdpbvisible=osdposterbanner.getVisible();
863 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
864 osd.setVisible(false);
865 osdposterbanner.setVisible(false);
866 okTriggeredOSD = false;
867 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
869 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
870 if (osdpbvisible) boxstack->update(this);
871 else boxstack->update(this, osd.getRegion());
873 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
874 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(false);
875 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
880 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
882 if (osd.getVisible())
885 boxstack->update(this, osd.getRegion());
887 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
891 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
894 if (streamType ==VDR::VIDEO) {
895 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
897 BoxStack::getInstance()->remove(vtxt);
901 if (changeType == INDEX)
903 newChannel = newData;
905 else if (changeType == NUMBER)
908 for(i = 0; i < chanList->size(); i++)
910 if ((*chanList)[i]->number == (UINT)newData)
917 if (i == chanList->size())
923 else if (changeType == OFFSET)
925 if (newData == UP) newChannel = upChannel(currentChannelIndex);
926 else newChannel = downChannel(currentChannelIndex);
928 else if (changeType == PREVIOUS)
930 newChannel = previousChannelIndex;
934 return false; // bad input
937 if (newChannel == currentChannelIndex) return true;
939 previousChannelIndex = currentChannelIndex;
940 currentChannelIndex = newChannel;
944 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
945 player->setChannel(currentChannelIndex);
946 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
948 // Blank out the symbols
949 sAspectRatio.setVisible(false);
950 bufferBar.setPercent(0);
951 sAudioChannels.setVisible(false);
953 // Remove other stuff
954 if (textUnavailable.getVisible())
956 textUnavailable.setVisible(false);
959 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
962 Channel* currentChannel = (*chanList)[currentChannelIndex];
963 if (currentChannel) {
964 info.setChannelLogo(currentChannel->number);
965 if (streamType == VDR::RADIO) {
966 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
967 radioChannelLogo.setVisible(true);
969 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
975 BoxStack::getInstance()->update(this);
980 void VVideoLiveTV::processMessage(Message* m)
982 if (m->message == Message::MOUSE_LBDOWN)
984 //check if press is outside this view! then simulate cancel
985 int x=(m->parameter>>16)-osd.getScreenX();
986 int y=(m->parameter&0xFFFF)-osd.getScreenY();
987 if (osd.getVisible()) {
989 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
990 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y )) {
991 BoxStack::getInstance()->handleCommand(Remote::RED);
992 } else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
993 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y)){
994 BoxStack::getInstance()->handleCommand(Remote::GREEN);
995 } else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
996 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
997 BoxStack::getInstance()->handleCommand(Remote::YELLOW);
998 } else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
999 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y )){
1000 BoxStack::getInstance()->handleCommand(Remote::BLUE);
1002 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1006 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1009 else if (m->message == Message::CHANNEL_CHANGE)
1011 channelChange(NUMBER, m->parameter);
1012 osdChannelIndex = currentChannelIndex;
1013 if (m->tag == 1) displayOSD(true);
1015 else if (m->message == Message::CHILD_CLOSE)
1023 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1025 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter);
1026 player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16,(m->parameter & 0xFF000000)>>24);
1028 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1030 if (streamType !=VDR::VIDEO) return;
1031 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter);
1032 int type=((m->parameter & 0xFF0000)>>16);
1034 case 0x10: { //dvbsubtitle
1035 if (streamType == VDR::VIDEO){
1036 player->setSubtitleChannel((m->parameter & 0xFFFF));
1037 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1038 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1039 if (vtxt && vtxt->isInSubtitleMode()) {
1040 BoxStack::getInstance()->remove(vtxt);
1044 case 0xFF: { //nosubtitles
1045 if (streamType == VDR::VIDEO){
1046 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1047 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1048 if (vtxt && vtxt->isInSubtitleMode()) {
1049 BoxStack::getInstance()->remove(vtxt);
1053 case 0x11: { //videotext
1054 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1056 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1060 BoxStack::getInstance()->update(vas);
1061 //BoxStack::getInstance()->update(&osd); //eveil error
1063 BoxStack::getInstance()->update(this, osd.getRegion());
1067 else if (m->message == Message::PLAYER_EVENT)
1069 switch(m->parameter)
1071 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1073 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1074 Command::getInstance()->connectionLost();
1078 case PlayerLiveTV::STREAM_END:
1080 // Message comes from playerlivetv through master mutex, so can do anything here
1085 case PlayerLiveTV::ASPECT43:
1088 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1090 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
1093 BoxStack::getInstance()->update(this, &wssRegion);
1097 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1098 sAspectRatio.setVisible(true);
1100 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1103 BoxStack::getInstance()->update(this, osd.getRegion());
1108 case PlayerLiveTV::ASPECT169:
1111 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1113 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
1116 BoxStack::getInstance()->update(this, &wssRegion);
1120 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1121 sAspectRatio.setVisible(true);
1123 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1126 BoxStack::getInstance()->update(this, osd.getRegion());
1131 case PlayerLiveTV::PREBUFFERING:
1133 preBuffering = m->tag;
1134 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1135 bufferBar.setPercent(preBuffering);
1137 if (osd.getVisible())
1139 bufferBar.setVisible(true);
1142 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1143 BoxStack::getInstance()->update(this, &r);
1145 if (preBuffering == 100)
1147 doAudioChannelSymbol();
1155 void VVideoLiveTV::doAudioChannelSymbol()
1158 Channel* currentChannel = (*chanList)[osdChannelIndex];
1160 bool multiAudio = false;
1161 if (Audio::getInstance()->supportsAc3()) {
1162 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1164 if (currentChannel->numAPids > 1) multiAudio = true;
1168 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1169 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1170 sAudioChannels.setVisible(true);
1172 if (osd.getVisible())
1174 sAudioChannels.draw();
1176 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1180 BoxStack::getInstance()->update(this, &r);
1184 UINT VVideoLiveTV::upChannel(UINT index)
1186 if (index == (chanList->size() - 1)) // at the end
1187 return 0; // so go to start
1192 UINT VVideoLiveTV::downChannel(UINT index)
1194 if (index == 0) // at the start
1195 return chanList->size() - 1; // so go to end
1200 void VVideoLiveTV::toggleChopSides()
1202 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1204 if (videoMode == Video::NORMAL)
1206 videoMode = Video::LETTERBOX;
1207 video->setMode(Video::LETTERBOX);
1211 videoMode = Video::NORMAL;
1212 video->setMode(Video::NORMAL);
1216 void VVideoLiveTV::updatePosterBanner()
1218 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1220 osdposterbanner.setVisible(false);
1223 Event* toShow = NULL;
1224 if (eventList && eventList->size()) {
1225 toShow = (*eventList)[0];
1226 Channel* currentChannel = (*chanList)[osdChannelIndex];
1227 toShow->loadinfos(currentChannel->number);
1234 bool posterscale=true;
1235 if (toShow->movieInfo) {
1236 poster=toShow->movieInfo->poster;
1238 if (toShow->seriesInfo) {
1239 if (toShow->seriesInfo->banners.size()) {
1240 poster=toShow->seriesInfo->banners[0];
1242 } else if (toShow->seriesInfo->seasonposter.height) {
1243 poster=toShow->seriesInfo->seasonposter;
1244 } else if (toShow->seriesInfo->posters.size()) {
1245 poster=toShow->seriesInfo->posters[0];
1248 if (poster.height) {
1249 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1250 osdposterbanner.setVisible(true);
1252 osdposterbanner.setVisible(false);
1255 osdposterbanner.setVisible(false);
1261 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1263 drawBitmap(posX, posY, bm,region);
1265 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1266 boxstack->update(this, &r);
1269 void VVideoLiveTV::clearOSD()
1271 rectangle(area, DrawStyle(0,0,0,0));
1272 boxstack->update(this, &area);
1275 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1278 r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1279 //now convert to our display
1280 float scalex=720.f/((float) (region.framewidth+1));
1281 float scaley=576.f/((float) (region.frameheight+1));
1282 r.x=floor(scalex*((float)r.x));
1283 r.y=floor(scaley*((float)r.y));
1284 r.w=ceil(scalex*((float)r.w))+1.f;
1285 r.h=ceil(scaley*((float)r.h))+1.f;
1286 rectangle(r, DrawStyle(0,0,0,0));
1287 boxstack->update(this, &r);