2 Copyright 2007-2008 Chris Tallon
4 This file is part of VOMP.
6 VOMP is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 VOMP is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with VOMP. If not, see <https://www.gnu.org/licenses/>.
22 #include "vchannellist.h"
25 #include "playerlive.h"
26 #include "playerlivetv.h"
27 #include "playerliveradio.h"
37 #include "vaudioselector.h"
43 #include "vteletextview.h"
44 #include "vepgsummary.h"
45 #include "vepglistadvanced.h"
46 #include "staticartwork.h"
48 #include "messagequeue.h"
50 #include "vvideolivetv.h"
53 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
55 vdr = VDR::getInstance();
56 boxstack = BoxStack::getInstance();
57 video = Video::getInstance();
62 vchannelList = tvchannelList;
63 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
65 currentChannelIndex = 0;
66 previousChannelIndex = 0;
73 // Convert channel number to index
75 for(i = 0; i < chanList->size(); i++)
77 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
79 currentChannelIndex = i;
87 videoMode = video->getMode();
89 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
91 streamType = VDR::VIDEO;
92 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
96 streamType = VDR::RADIO;
97 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
101 setSize(video->getScreenWidth(), video->getScreenHeight());
103 DrawStyle transparent(0, 0, 0, 0);
104 setBackgroundColour(transparent);
106 // This variable is set to true if the user pressed OK to bring the OSD on screen
107 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
108 okTriggeredOSD = false;
111 info.setChannelLogo(initialChannelNumber);
112 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
114 if (osdv && streamType == VDR::RADIO) {
115 radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
116 radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
117 radioChannelLogo.setVisible(true);
118 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
119 add(&radioChannelLogo);
122 osdposterbanner.setPosition(20,20);
123 //osdposterbanner.setBackgroundColour(DrawStyle::OSDBACKGROUND);
124 osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
125 osdposterbanner.setVisible(false);
126 add(&osdposterbanner);
128 osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
129 osd.setPosition(0, video->getScreenHeight() - 150);
130 osd.setSize(video->getScreenWidth(), 150);
131 osd.setVisible(false);
134 int channellogomove=0;
138 //osdChannelLogo.setBackgroundColour(DrawStyle::OSDBACKGROUND);
139 osdChannelLogo.setPosition(30,5);
140 osdChannelLogo.setSize(60,60);
141 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
142 osd.add(&osdChannelLogo);
143 channellogomove = 30-5;
147 //clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
148 clock.setPosition(osd.getWidth() - 100, 4);
149 clock.setSize(90, 30);
152 //osdChanNum.setBackgroundColour(DrawStyle::OSDBACKGROUND);
153 osdChanNum.setPosition(60 + channellogomove, 4);
154 osdChanNum.setSize((numberWidth * 10) + 22, getFontHeight() + 5); // 10 px = width of number chars in font
155 osd.add(&osdChanNum);
157 //osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
158 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
159 osdChanName.setSize(300, 30);
160 osd.add(&osdChanName);
162 boxRed.setBackgroundColour(DrawStyle::RED);
163 boxRed.setPosition(54+0*boxdiff, 104);
164 boxRed.setSize(18, 16);
167 boxGreen.setBackgroundColour(DrawStyle::GREEN);
168 boxGreen.setPosition(54+1*boxdiff, 104);
169 boxGreen.setSize(18, 16);
172 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
173 boxYellow.setPosition(54+2*boxdiff, 104);
174 boxYellow.setSize(18, 16);
177 boxBlue.setBackgroundColour(DrawStyle::BLUE);
178 boxBlue.setPosition(54+3*boxdiff, 104);
179 boxBlue.setSize(18, 16);
182 //textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
183 textRed.setPosition(boxRed.getX2(), 98);
184 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
185 textRed.setText(tr("Summary"));
188 if (streamType == VDR::VIDEO)
190 //textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
191 textGreen.setPosition(boxGreen.getX2(), 98);
192 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
193 textGreen.setText(tr("Audio"));
197 //textYellow.setBackgroundColour(DrawStyle::OSDBACKGROUND);
198 textYellow.setPosition(boxYellow.getX2(), 98);
199 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
200 textYellow.setText(tr("Teletext"));
201 osd.add(&textYellow);
203 //textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
204 textBlue.setPosition(boxBlue.getX2(), 98);
205 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
206 textBlue.setText(tr("EPG"));
209 //sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
210 sl.setPosition(90, 36);
214 bufferBar.setPosition(osd.getWidth() - 90, 70);
215 bufferBar.setSize(40, 20);
216 bufferBar.setVisible(true);
221 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
222 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
223 sAspectRatio.setVisible(false);
224 osd.add(&sAspectRatio);
226 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
227 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
228 sAudioChannels.setVisible(false);
229 osd.add(&sAudioChannels);
235 ninfo.setStaticArtwork(sa_txtoff);
236 txtlogo.setPosition(54+4*boxdiff,104);
237 txtlogo.setSize(22,20);
238 txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
241 ninfo.setStaticArtwork(sa_dolbyoff);
242 dolbylogo.setPosition(54+4*boxdiff+15,104);
243 dolbylogo.setSize(22,20);
244 dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
247 ninfo.setStaticArtwork(sa_sd576i);
248 reslogo.setPosition(54+4*boxdiff+30,104);
249 reslogo.setSize(22,20);
250 reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
253 reslogo.setVisible(false);
254 dolbylogo.setVisible(false);
255 txtlogo.setVisible(false);
258 //textUnavailable.setBackgroundColour(DrawStyle::OSDBACKGROUND);
259 textUnavailable.setPosition(60, 30);
260 textUnavailable.setSize(osd.getWidth() - 120, 30);
261 textUnavailable.setText(tr("Channel Unavailable"));
262 textUnavailable.setVisible(false);
263 add(&textUnavailable);
265 vdisplay.mode = Fullscreen;
266 vdisplay.fallbackMode = Fullscreen;
273 void VVideoLiveTV::preDelete()
278 VVideoLiveTV::~VVideoLiveTV()
281 video->setDefaultAspect();
283 OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
286 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
290 void VVideoLiveTV::delData()
294 int eventListSize = eventList->size();
295 for(int i = 0; i < eventListSize; i++)
297 delete (*eventList)[i];
304 int VVideoLiveTV::handleCommand(int command)
310 if (osd.getVisible() && !textUnavailable.getVisible())
315 // else drop through to stop
321 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
325 // navigate EPG, bring it onscreen if it's not there
328 if (InputMan::getInstance()->mayHaveFewButtons())
330 if (okTriggeredOSD) doUpDown(false);
331 else doChanUpDown(UP);
341 if (InputMan::getInstance()->mayHaveFewButtons())
343 if (okTriggeredOSD) doUpDown(true);
344 else doChanUpDown(DOWN);
362 case Input::CHANNELUP:
367 case Input::CHANNELDOWN:
372 case Input::PREVCHANNEL:
374 channelChange(PREVIOUS, 0);
375 osdChannelIndex = currentChannelIndex;
408 // key in channel number
415 if (streamType == VDR::VIDEO) doAudioSelector();
420 if (streamType ==VDR::VIDEO)
422 doTeletext(); //TODO: Add a selector for subtitles or teletext
433 if (streamType == VDR::VIDEO)
434 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
441 void VVideoLiveTV::go()
445 boxstack->update(this);
450 player->go(currentChannelIndex);
453 void VVideoLiveTV::stop()
455 Timers::getInstance()->cancelTimer(this, 1);
456 Timers::getInstance()->cancelTimer(this, 2);
461 void VVideoLiveTV::doLeftRight(bool right)
463 if (osd.getVisible())
465 if (right) osdChannelIndex = upChannel(osdChannelIndex);
466 else osdChannelIndex = downChannel(osdChannelIndex);
470 osdChannelIndex = currentChannelIndex;
475 void VVideoLiveTV::doUpDown(bool down)
477 if (osd.getVisible())
489 void VVideoLiveTV::doChanUpDown(int which)
491 channelChange(OFFSET, which);
492 osdChannelIndex = currentChannelIndex;
496 void VVideoLiveTV::doOK()
498 if (osd.getVisible())
503 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
505 channelChange(NUMBER, newChannel);
506 osdChannelIndex = currentChannelIndex;
509 else if (osdChannelIndex == currentChannelIndex)
515 channelChange(INDEX, osdChannelIndex);
521 osdChannelIndex = currentChannelIndex;
523 okTriggeredOSD = true;
527 void VVideoLiveTV::doSummary()
530 Channel* currentChannel = (*chanList)[osdChannelIndex];
531 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
536 sort(eventList->begin(), eventList->end(), EventSorter());
538 if (eventList->size() < 1) return;
539 Event* event = (*eventList)[0];
540 event->loadinfos(currentChannel->number);
542 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
545 boxstack->update(vr);
548 void VVideoLiveTV::doKey(int command)
550 if (!osd.getVisible()) // First key. prep the data
553 updatePosterBanner();
558 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
559 keyingInput[0] = command;
562 char* keyingString = new char[numberWidth + 1];
563 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
564 keyingString[numberWidth] = '\0';
566 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
568 if (keying == numberWidth)
571 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
573 channelChange(NUMBER, newChannel);
574 osdChannelIndex = currentChannelIndex;
575 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
576 displayOSD(true); // this will put one back if required
580 osdChanNum.setText(keyingString);
582 if (!osd.getVisible())
584 osd.setVisible(true);
591 boxstack->update(this, osd.getRegion());
592 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
594 delete[] keyingString;
597 void VVideoLiveTV::doTeletext(bool subtitlemode)
599 if (streamType !=VDR::VIDEO) return;
600 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
607 // and reset the display - this is a copy from setNowNextData
608 char formatChanNum[20];
609 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
610 osdChanNum.setText(formatChanNum);
611 osdChanName.setText((*chanList)[osdChannelIndex]->name);
613 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
614 if (osd.getVisible()) clearScreen();
616 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
619 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
620 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
624 vtxv->setSubtitleMode(subtitlemode);
630 BoxStack::getInstance()->add(vtxv);
633 BoxStack::getInstance()->update(this);
634 BoxStack::getInstance()->update(vtxv);
637 void VVideoLiveTV::doAudioSelector()
639 // If the osd is already visisble there might be a timer for it
640 Timers::getInstance()->cancelTimer(this, 1);
641 //This causes a deadlock with the timertrhread itself is locked
647 // and reset the display - this is a copy from setNowNextData
648 char formatChanNum[20];
649 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
650 osdChanNum.setText(formatChanNum);
651 osdChanName.setText((*chanList)[osdChannelIndex]->name);
653 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
654 int subtitleType=0x10;
655 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
656 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
657 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
659 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
663 subtitleType=0xFF; //turnedOff
669 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
670 subtitleType,subtitleChannel,NULL);
672 vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
673 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
676 // make vas != null and displayOSD will not set a timer or do any boxstack update
677 if (osd.getVisible()) displayOSD(false);
678 else displayOSD(true);
681 BoxStack::getInstance()->add(vas);
682 BoxStack::getInstance()->update(this);
683 BoxStack::getInstance()->update(vas);
686 void VVideoLiveTV::doEPG()
688 if (osd.getVisible()) clearScreen();
690 if (!Command::getInstance()->isAdvMenus())
692 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
695 boxstack->update(vepg);
699 Channel* currentChannel = (*chanList)[osdChannelIndex];
700 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
703 boxstack->update(vepg);
707 void VVideoLiveTV::setNowNextData()
711 Channel* currentChannel = (*chanList)[osdChannelIndex];
713 char formatChanNum[20];
714 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
715 osdChanNum.setText(formatChanNum);
716 osdChanName.setText(currentChannel->name);
718 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
722 sl.setText(tr("No channel data available"));
726 sort(eventList->begin(), eventList->end(), EventSorter());
728 char tempString[300];
729 char tempString2[300];
732 int eventListSize = eventList->size();
733 std::stringstream string;
734 for(int i = 0; i < eventListSize; i++)
736 event = (*eventList)[i];
738 time_t etime = event->time;
739 LOCALTIME_R(&etime, &btime);
741 strftime(tempString2, 299, "%0H:%0M ", &btime);
743 strftime(tempString2, 299, "%H:%M ", &btime);
745 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
746 string << tempString << "\n";
748 sl.setText(string.str().c_str());
754 void VVideoLiveTV::displayOSD(bool newNowNextData)
756 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
757 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(true);
758 osd.setVisible(true);
762 updatePosterBanner();
766 if (osdposterbanner.getVisible()) osdposterbanner.draw();
771 toupdate=*osd.getRegion();
774 if (osdposterbanner.getVisible())
776 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 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
804 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
807 void VVideoLiveTV::showUnavailable()
809 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
810 textUnavailable.setVisible(true);
811 textUnavailable.draw();
813 if (!osd.getVisible()) displayOSD(true);
815 boxstack->update(this, textUnavailable.getRegion());
818 void VVideoLiveTV::setClock()
824 LOCALTIME_R(&t, &tms);
825 strftime(timeString, 19, "%H:%M", &tms);
826 clock.setText(timeString);
828 time_t dt = 60 - (t % 60); // seconds to the next minute
829 if (dt == 0) dt = 60; // advance a whole minute if necessary
830 dt += t; // get a time_t value for it rather than using duration
831 // (so it will occur at the actual second and not second and a half)
833 Timers::getInstance()->setTimerT(this, 2, dt);
836 void VVideoLiveTV::timercall(int ref)
842 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
844 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
846 Message* m = new Message();
847 m->message = Message::CHANNEL_CHANGE;
849 m->parameter = newChannel;
850 m->tag = 1; // signal to call displayOSD();
851 MessageQueue::getInstance()->postMessage(m);
852 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
856 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
857 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
858 if (preBuffering < 100)
860 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
861 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
864 bool osdpbvisible=osdposterbanner.getVisible();
865 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
866 osd.setVisible(false);
867 osdposterbanner.setVisible(false);
868 okTriggeredOSD = false;
869 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
871 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
872 if (osdpbvisible) boxstack->update(this);
873 else boxstack->update(this, osd.getRegion());
875 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
876 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
877 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
878 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
883 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
885 if (osd.getVisible())
888 boxstack->update(this, osd.getRegion());
890 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
894 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
897 if (streamType == VDR::VIDEO)
899 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
902 BoxStack::getInstance()->remove(vtxt);
905 if (changeType == INDEX)
907 newChannel = newData;
909 else if (changeType == NUMBER)
912 for(i = 0; i < chanList->size(); i++)
914 if ((*chanList)[i]->number == (UINT)newData)
921 if (i == chanList->size())
927 else if (changeType == OFFSET)
929 if (newData == UP) newChannel = upChannel(currentChannelIndex);
930 else newChannel = downChannel(currentChannelIndex);
932 else if (changeType == PREVIOUS)
934 newChannel = previousChannelIndex;
938 return false; // bad input
941 if (newChannel == currentChannelIndex) return true;
943 previousChannelIndex = currentChannelIndex;
944 currentChannelIndex = newChannel;
948 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
949 player->setChannel(currentChannelIndex);
950 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
952 // Blank out the symbols
953 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
955 bufferBar.setPercent(0);
959 sAudioChannels.setVisible(false);
960 sAspectRatio.setVisible(false);
964 reslogo.setVisible(false);
965 dolbylogo.setVisible(false);
966 txtlogo.setVisible(false);
969 // Remove other stuff
970 if (textUnavailable.getVisible())
972 textUnavailable.setVisible(false);
978 Channel* currentChannel = (*chanList)[currentChannelIndex];
981 info.setChannelLogo(currentChannel->number);
982 if (streamType == VDR::RADIO)
984 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
985 radioChannelLogo.setVisible(true);
987 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
992 BoxStack::getInstance()->update(this);
997 void VVideoLiveTV::processMessage(Message* m)
999 if (m->message == Message::MOUSE_LBDOWN)
1001 //check if press is outside this view! then simulate cancel
1002 int x = (m->parameter >> 16) - osd.getScreenX();
1003 int y = (m->parameter & 0xFFFF) - osd.getScreenY();
1004 if (osd.getVisible())
1006 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
1007 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y ))
1009 BoxStack::getInstance()->handleCommand(Input::RED);
1011 else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
1012 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y))
1014 BoxStack::getInstance()->handleCommand(Input::GREEN);
1016 else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
1017 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
1018 BoxStack::getInstance()->handleCommand(Input::YELLOW);
1020 else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
1021 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y ))
1023 BoxStack::getInstance()->handleCommand(Input::BLUE);
1027 BoxStack::getInstance()->handleCommand(Input::OK); //simulate rok press
1032 BoxStack::getInstance()->handleCommand(Input::OK); //simulate rok press
1035 else if (m->message == Message::CHANNEL_CHANGE)
1037 channelChange(NUMBER, m->parameter);
1038 osdChannelIndex = currentChannelIndex;
1039 if (m->tag == 1) displayOSD(true);
1041 else if (m->message == Message::CHILD_CLOSE)
1049 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1051 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter);
1052 player->setAudioChannel((m->parameter & 0xFFFF), (m->parameter & 0xFF0000) >> 16, (m->parameter & 0xFF000000) >> 24);
1054 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1056 if (streamType != VDR::VIDEO) return;
1057 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter);
1058 int type = (m->parameter & 0xFF0000) >> 16;
1064 if (streamType == VDR::VIDEO)
1066 player->setSubtitleChannel((m->parameter & 0xFFFF));
1067 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1068 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1069 if (vtxt && vtxt->isInSubtitleMode())
1071 BoxStack::getInstance()->remove(vtxt);
1077 if (streamType == VDR::VIDEO){
1078 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1079 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1080 if (vtxt && vtxt->isInSubtitleMode()) {
1081 BoxStack::getInstance()->remove(vtxt);
1088 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1090 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1096 BoxStack::getInstance()->update(vas);
1097 //BoxStack::getInstance()->update(&osd); //eveil error
1099 BoxStack::getInstance()->update(this, osd.getRegion());
1101 else if (m->message == Message::PLAYER_EVENT)
1103 switch (m->parameter)
1105 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1107 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1108 Command::getInstance()->connectionLost();
1112 case PlayerLiveTV::STREAM_END:
1114 // Message comes from playerlivetv through master mutex, so can do anything here
1119 case PlayerLiveTV::ASPECT43:
1121 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1124 osdv->updateBackgroundColor(DrawStyle::BLACK);
1127 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1128 sAspectRatio.setVisible(true);
1130 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1133 BoxStack::getInstance()->update(this, osd.getRegion());
1138 case PlayerLiveTV::ASPECT169:
1140 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1141 sAspectRatio.setVisible(true);
1143 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1146 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
1150 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1153 BoxStack::getInstance()->update(this, osd.getRegion());
1158 case PlayerLiveTV::PREBUFFERING:
1160 preBuffering = m->tag;
1161 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1162 bufferBar.setPercent(preBuffering);
1164 if (osd.getVisible())
1166 bufferBar.setVisible(true);
1169 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1170 BoxStack::getInstance()->update(this, &r);
1172 if (preBuffering == 100)
1174 doAudioChannelSymbol();
1182 void VVideoLiveTV::doAudioChannelSymbol()
1184 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1186 Channel* currentChannel = (*chanList)[osdChannelIndex];
1188 bool multiAudio = false;
1189 if (Audio::getInstance()->supportsAc3()) {
1190 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1192 if (currentChannel->numAPids > 1) multiAudio = true;
1196 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1197 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1198 sAudioChannels.setVisible(true);
1202 dolbylogo.setVisible(true);
1203 txtlogo.setVisible(true);
1205 if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
1206 else info.setStaticArtwork(sa_txtoff);
1207 txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
1210 if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
1211 info.setStaticArtwork(sa_dolbyon);
1212 else info.setStaticArtwork(sa_dolbyoff);
1213 dolbylogo.setTVMedia(info, WTVMedia::ZoomVertical);
1215 Demuxer* demux=Demuxer::getInstance();
1217 int vertical_size=demux->getVerticalSize();
1218 Log::getInstance()->log("VVideoRec", Log::DEBUG, "TVMedia vertical size %d", vertical_size);
1219 reslogo.setVisible(true);
1220 switch (vertical_size) {
1222 info.setStaticArtwork(sa_sd576i);
1223 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1225 info.setStaticArtwork(sa_hd720p);
1226 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1228 info.setStaticArtwork(sa_hd1080i);
1229 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1230 default: // we assume sd
1231 reslogo.setVisible(false);
1235 reslogo.setVisible(false);
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 = (UINT)floor(scalex*((float)r.x));
1352 r.y = (UINT)floor(scaley*((float)r.y));
1353 r.w = (UINT)(ceil(scalex*((float)r.w))+1.f);
1354 r.h = (UINT)(ceil(scaley*((float)r.h))+1.f);
1355 rectangle(r, DrawStyle(0,0,0,0));
1356 boxstack->update(this, &r);