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 "playervideolive.h"
27 #include "playerradiolive.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 = VDR::getInstance()->getChannelNumberWidth();
65 currentChannelIndex = 0;
66 previousChannelIndex = 0;
73 // Convert channel number to index
74 for(UINT i = 0; i < chanList->size(); i++)
76 if ((*chanList)[i]->number == initialChannelNumber)
78 currentChannelIndex = i;
86 videoMode = video->getMode();
88 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
90 streamType = VDR::VIDEO;
91 player = new PlayerVideoLive(Control::getInstance(), this, this, chanList);
95 streamType = VDR::RADIO;
96 player = new PlayerRadioLive(Control::getInstance(), this, chanList);
100 setSize(video->getScreenWidth(), video->getScreenHeight());
102 setBackgroundColour(DrawStyle::TRANSPARENT);
104 OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
107 osdv->updateBackgroundColor(DrawStyle::BLACK);
110 // This variable is set to true if the user pressed OK to bring the OSD on screen
111 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
112 okTriggeredOSD = false;
115 info.setChannelLogo(initialChannelNumber);
117 if (osdv && streamType == VDR::RADIO) {
118 radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
119 radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
120 radioChannelLogo.setVisible(true);
121 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
122 add(&radioChannelLogo);
125 osdposterbanner.setPosition(20,20);
126 //osdposterbanner.setBackgroundColour(DrawStyle::OSDBACKGROUND);
127 osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
128 osdposterbanner.setVisible(false);
129 add(&osdposterbanner);
131 osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
132 osd.setPosition(0, video->getScreenHeight() - 150);
133 osd.setSize(video->getScreenWidth(), 150);
134 osd.setVisible(false);
137 int channellogomove=0;
141 //osdChannelLogo.setBackgroundColour(DrawStyle::OSDBACKGROUND);
142 osdChannelLogo.setPosition(30,5);
143 osdChannelLogo.setSize(60,60);
144 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
145 osd.add(&osdChannelLogo);
146 channellogomove = 30-5;
150 //clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
151 clock.setPosition(osd.getWidth() - 100, 4);
152 clock.setSize(90, 30);
155 //osdChanNum.setBackgroundColour(DrawStyle::OSDBACKGROUND);
156 osdChanNum.setPosition(60 + channellogomove, 4);
157 osdChanNum.setSize((numberWidth * 10) + 22, getFontHeight() + 5); // 10 px = width of number chars in font
158 osd.add(&osdChanNum);
160 //osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
161 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
162 osdChanName.setSize(300, 30);
163 osd.add(&osdChanName);
165 boxRed.setBackgroundColour(DrawStyle::RED);
166 boxRed.setPosition(54+0*boxdiff, 104);
167 boxRed.setSize(18, 16);
170 boxGreen.setBackgroundColour(DrawStyle::GREEN);
171 boxGreen.setPosition(54+1*boxdiff, 104);
172 boxGreen.setSize(18, 16);
175 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
176 boxYellow.setPosition(54+2*boxdiff, 104);
177 boxYellow.setSize(18, 16);
180 boxBlue.setBackgroundColour(DrawStyle::BLUE);
181 boxBlue.setPosition(54+3*boxdiff, 104);
182 boxBlue.setSize(18, 16);
185 //textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
186 textRed.setPosition(boxRed.getX2(), 98);
187 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
188 textRed.setText(tr("Summary"));
191 if (streamType == VDR::VIDEO)
193 //textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
194 textGreen.setPosition(boxGreen.getX2(), 98);
195 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
196 textGreen.setText(tr("Audio"));
200 //textYellow.setBackgroundColour(DrawStyle::OSDBACKGROUND);
201 textYellow.setPosition(boxYellow.getX2(), 98);
202 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
203 textYellow.setText(tr("Teletext"));
204 osd.add(&textYellow);
206 //textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
207 textBlue.setPosition(boxBlue.getX2(), 98);
208 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
209 textBlue.setText(tr("EPG"));
212 //sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
213 sl.setPosition(90, 36);
217 bufferBar.setPosition(osd.getWidth() - 90, 70);
218 bufferBar.setSize(40, 20);
219 bufferBar.setVisible(true);
224 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
225 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
226 sAspectRatio.setVisible(false);
227 osd.add(&sAspectRatio);
229 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
230 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
231 sAudioChannels.setVisible(false);
232 osd.add(&sAudioChannels);
238 ninfo.setStaticArtwork(sa_txtoff);
239 txtlogo.setPosition(54+4*boxdiff,104);
240 txtlogo.setSize(22,20);
241 txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
244 ninfo.setStaticArtwork(sa_dolbyoff);
245 dolbylogo.setPosition(54+4*boxdiff+15,104);
246 dolbylogo.setSize(22,20);
247 dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
250 ninfo.setStaticArtwork(sa_sd576i);
251 reslogo.setPosition(54+4*boxdiff+30,104);
252 reslogo.setSize(22,20);
253 reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
256 reslogo.setVisible(false);
257 dolbylogo.setVisible(false);
258 txtlogo.setVisible(false);
261 //textUnavailable.setBackgroundColour(DrawStyle::OSDBACKGROUND);
262 textUnavailable.setPosition(60, 30);
263 textUnavailable.setSize(osd.getWidth() - 120, 30);
264 textUnavailable.setText(tr("Channel Unavailable"));
265 textUnavailable.setVisible(false);
266 add(&textUnavailable);
268 vdisplay.mode = Fullscreen;
269 vdisplay.fallbackMode = Fullscreen;
276 void VVideoLiveTV::preDelete()
281 VVideoLiveTV::~VVideoLiveTV()
284 video->setDefaultAspect();
286 OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
289 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
293 void VVideoLiveTV::delData()
297 int eventListSize = eventList->size();
298 for(int i = 0; i < eventListSize; i++)
300 delete (*eventList)[i];
307 int VVideoLiveTV::handleCommand(int command)
313 if (osd.getVisible() && !textUnavailable.getVisible())
318 // else drop through to stop
324 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
328 // navigate EPG, bring it onscreen if it's not there
331 if (InputMan::getInstance()->mayHaveFewButtons())
333 if (okTriggeredOSD) doUpDown(false);
334 else doChanUpDown(UP);
344 if (InputMan::getInstance()->mayHaveFewButtons())
346 if (okTriggeredOSD) doUpDown(true);
347 else doChanUpDown(DOWN);
365 case Input::CHANNELUP:
370 case Input::CHANNELDOWN:
375 case Input::PREVCHANNEL:
377 channelChange(PREVIOUS, 0);
378 osdChannelIndex = currentChannelIndex;
411 // key in channel number
418 if (streamType == VDR::VIDEO) doAudioSelector();
423 if (streamType ==VDR::VIDEO)
425 doTeletext(); //TODO: Add a selector for subtitles or teletext
436 if (streamType == VDR::VIDEO)
437 (static_cast<PlayerVideoLive*>(player))->toggleSubtitles();
444 void VVideoLiveTV::go()
448 boxstack->update(this);
453 player->go(currentChannelIndex);
456 void VVideoLiveTV::stop()
458 Timers::getInstance()->cancelTimer(this, 1);
459 Timers::getInstance()->cancelTimer(this, 2);
464 void VVideoLiveTV::doLeftRight(bool right)
466 if (osd.getVisible())
468 if (right) osdChannelIndex = upChannel(osdChannelIndex);
469 else osdChannelIndex = downChannel(osdChannelIndex);
473 osdChannelIndex = currentChannelIndex;
478 void VVideoLiveTV::doUpDown(bool /* down */)
480 if (osd.getVisible())
492 void VVideoLiveTV::doChanUpDown(int which)
494 channelChange(OFFSET, which);
495 osdChannelIndex = currentChannelIndex;
499 void VVideoLiveTV::doOK()
501 if (osd.getVisible())
506 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * static_cast<int>(pow(10.f, i));
508 channelChange(NUMBER, newChannel);
509 osdChannelIndex = currentChannelIndex;
512 else if (osdChannelIndex == currentChannelIndex)
518 channelChange(INDEX, osdChannelIndex);
524 osdChannelIndex = currentChannelIndex;
526 okTriggeredOSD = true;
530 void VVideoLiveTV::doSummary()
533 Channel* currentChannel = (*chanList)[osdChannelIndex];
534 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
539 sort(eventList->begin(), eventList->end(), EventSorter());
541 if (eventList->size() < 1) return;
542 Event* event = (*eventList)[0];
543 event->loadinfos(currentChannel->number);
545 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
548 boxstack->update(vr);
551 void VVideoLiveTV::doKey(int command)
553 if (!osd.getVisible()) // First key. prep the data
556 updatePosterBanner();
561 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
562 keyingInput[0] = command;
565 char* keyingString = new char[numberWidth + 1];
566 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
567 keyingString[numberWidth] = '\0';
569 for (i = 0; i < keying; i++) keyingString[i] = static_cast<char>(keyingInput[keying - 1 - i] + 48);
571 if (keying == numberWidth)
574 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * static_cast<int>(pow(10.f, i));
576 channelChange(NUMBER, newChannel);
577 osdChannelIndex = currentChannelIndex;
578 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
579 displayOSD(true); // this will put one back if required
583 osdChanNum.setText(keyingString);
585 if (!osd.getVisible())
587 osd.setVisible(true);
594 boxstack->update(this, osd.getRegion());
595 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
597 delete[] keyingString;
600 void VVideoLiveTV::doTeletext(bool subtitlemode)
602 if (streamType != VDR::VIDEO) return;
604 PlayerVideoLive* playervl = static_cast<PlayerVideoLive*>(player);
606 playervl->tellSubtitlesOSDVisible(true);
613 // and reset the display - this is a copy from setNowNextData
614 char formatChanNum[20];
615 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
616 osdChanNum.setText(formatChanNum);
617 osdChanName.setText((*chanList)[osdChannelIndex]->name);
619 playervl->tellSubtitlesOSDVisible(true);
620 if (osd.getVisible()) clearScreen();
622 VTeletextView* vtxv = playervl->getTeletextDecoder()->getTeletxtView();
625 vtxv = new VTeletextView(playervl->getTeletextDecoder(), this, playervl);
626 playervl->getTeletextDecoder()->registerTeletextView(vtxv);
630 vtxv->setSubtitleMode(subtitlemode);
636 BoxStack::getInstance()->add(vtxv);
639 BoxStack::getInstance()->update(this);
640 BoxStack::getInstance()->update(vtxv);
643 void VVideoLiveTV::doAudioSelector()
645 // Only called if streamtype == VDR::VIDEO
646 PlayerVideoLive* playervl = static_cast<PlayerVideoLive*>(player);
648 // If the osd is already visisble there might be a timer for it
649 Timers::getInstance()->cancelTimer(this, 1);
650 //This causes a deadlock with the timertrhread itself is locked
656 // and reset the display - this is a copy from setNowNextData
657 char formatChanNum[20];
658 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
659 osdChanNum.setText(formatChanNum);
660 osdChanName.setText((*chanList)[osdChannelIndex]->name);
662 int subtitleChannel = playervl->getCurrentSubtitleChannel();
663 int subtitleType = 0x10;
664 if (!playervl->isSubtitlesOn())
666 if (playervl->getTeletextDecoder()->getTeletxtView() &&
667 playervl->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode())
669 subtitleChannel = playervl->getTeletextDecoder()->getPage();
674 subtitleType = 0xFF; //turnedOff
680 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], playervl->getCurrentAudioChannel(),
681 subtitleType,subtitleChannel,NULL);
683 vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
684 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
687 // make vas != null and displayOSD will not set a timer or do any boxstack update
688 if (osd.getVisible()) displayOSD(false);
689 else displayOSD(true);
692 BoxStack::getInstance()->add(vas);
693 BoxStack::getInstance()->update(this);
694 BoxStack::getInstance()->update(vas);
697 void VVideoLiveTV::doEPG()
699 if (osd.getVisible()) clearScreen();
701 if (!Control::getInstance()->isAdvMenus())
703 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
706 boxstack->update(vepg);
710 Channel* currentChannel = (*chanList)[osdChannelIndex];
711 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
714 boxstack->update(vepg);
718 void VVideoLiveTV::setNowNextData()
722 Channel* currentChannel = (*chanList)[osdChannelIndex];
724 char formatChanNum[20];
725 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
726 osdChanNum.setText(formatChanNum);
727 osdChanName.setText(currentChannel->name);
729 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
733 sl.setText(tr("No channel data available"));
737 sort(eventList->begin(), eventList->end(), EventSorter());
739 char tempString[300];
742 int eventListSize = eventList->size();
743 std::stringstream ss;
744 for(int i = 0; i < eventListSize; i++)
746 event = (*eventList)[i];
748 time_t etime = event->time;
749 LOCALTIME_R(&etime, &btime);
750 // FIXME convert following to std::strftime
752 strftime(tempString, 299, "%0H:%0M ", &btime);
754 strftime(tempString, 299, "%H:%M ", &btime);
756 ss << tempString << " " << event->title << "\n";
758 sl.setText(ss.str().c_str());
764 void VVideoLiveTV::displayOSD(bool newNowNextData)
766 PlayerVideoLive* playerlivetv = dynamic_cast<PlayerVideoLive*>(player);
767 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(true);
768 osd.setVisible(true);
772 updatePosterBanner();
776 if (osdposterbanner.getVisible()) osdposterbanner.draw();
781 toupdate=*osd.getRegion();
784 if (osdposterbanner.getVisible())
786 boxstack->update(this);
790 boxstack->update(this, &toupdate);
793 bool setTimer = true;
794 if (vas) setTimer = false;
795 if (textUnavailable.getVisible()) setTimer = false;
797 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
800 void VVideoLiveTV::clearScreen()
802 Timers::getInstance()->cancelTimer(this, 1);
804 textUnavailable.setVisible(false);
805 osd.setVisible(false);
806 osdposterbanner.setVisible(false);
808 okTriggeredOSD = false;
811 boxstack->update(this);
813 PlayerVideoLive* playerlivetv = dynamic_cast<PlayerVideoLive*>(player);
814 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
817 void VVideoLiveTV::showUnavailable()
819 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
820 textUnavailable.setVisible(true);
821 textUnavailable.draw();
823 if (!osd.getVisible()) displayOSD(true);
825 boxstack->update(this, textUnavailable.getRegion());
828 void VVideoLiveTV::setClock()
834 LOCALTIME_R(&t, &tms);
835 strftime(timeString, 19, "%H:%M", &tms);
836 clock.setText(timeString);
838 time_t dt = 60 - (t % 60); // seconds to the next minute
839 if (dt == 0) dt = 60; // advance a whole minute if necessary
840 dt += t; // get a time_t value for it rather than using duration
841 // (so it will occur at the actual second and not second and a half)
843 Timers::getInstance()->setTimerT(this, 2, dt);
846 void VVideoLiveTV::timercall(int ref)
852 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
854 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * static_cast<int>(pow(10.f, i));
856 Message* m = new Message();
857 m->message = Message::CHANNEL_CHANGE;
859 m->parameter = newChannel;
860 m->tag = 1; // signal to call displayOSD();
861 MessageQueue::getInstance()->postMessage(m);
862 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
866 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
867 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
868 if (preBuffering < 100)
870 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
871 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
874 bool osdpbvisible=osdposterbanner.getVisible();
875 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
876 osd.setVisible(false);
877 osdposterbanner.setVisible(false);
878 okTriggeredOSD = false;
879 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
881 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
882 if (osdpbvisible) boxstack->update(this);
883 else boxstack->update(this, osd.getRegion());
885 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
886 PlayerVideoLive* playerlivetv = dynamic_cast<PlayerVideoLive*>(player);
887 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
888 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
893 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
895 if (osd.getVisible())
898 boxstack->update(this, osd.getRegion());
900 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
904 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
907 if (streamType == VDR::VIDEO)
909 VTeletextView* vtxt = static_cast<PlayerVideoLive*>(player)->getTeletextDecoder()->getTeletxtView();
912 BoxStack::getInstance()->remove(vtxt);
915 if (changeType == INDEX)
917 newChannel = newData;
919 else if (changeType == NUMBER)
922 for(i = 0; i < chanList->size(); i++)
924 if ((*chanList)[i]->number == newData)
931 if (i == chanList->size())
937 else if (changeType == OFFSET)
939 if (newData == UP) newChannel = upChannel(currentChannelIndex);
940 else newChannel = downChannel(currentChannelIndex);
942 else if (changeType == PREVIOUS)
944 newChannel = previousChannelIndex;
948 return false; // bad input
951 if (newChannel == currentChannelIndex) return true;
953 previousChannelIndex = currentChannelIndex;
954 currentChannelIndex = newChannel;
958 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
959 player->setChannel(currentChannelIndex);
960 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
962 // Blank out the symbols
963 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
965 bufferBar.setPercent(0);
969 sAudioChannels.setVisible(false);
970 sAspectRatio.setVisible(false);
974 reslogo.setVisible(false);
975 dolbylogo.setVisible(false);
976 txtlogo.setVisible(false);
979 // Remove other stuff
980 if (textUnavailable.getVisible())
982 textUnavailable.setVisible(false);
988 Channel* currentChannel = (*chanList)[currentChannelIndex];
991 info.setChannelLogo(currentChannel->number);
992 if (streamType == VDR::RADIO)
994 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
995 radioChannelLogo.setVisible(true);
997 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1002 BoxStack::getInstance()->update(this);
1007 void VVideoLiveTV::processMessage(Message* m)
1009 if (m->message == Message::MOUSE_LBDOWN)
1011 //check if press is outside this view! then simulate cancel
1012 int x = m->parameter - osd.getScreenX();
1013 int y = m->tag - osd.getScreenY();
1014 if (osd.getVisible())
1016 if ((boxRed.getX() <= x) && (boxRed.getX() + static_cast<int>(boxRed.getWidth()) >= x) &&
1017 (boxRed.getY() <= y) && (boxRed.getY() + static_cast<int>(boxRed.getHeight()) >= y))
1019 BoxStack::getInstance()->handleCommand(Input::RED);
1021 else if ((boxGreen.getX() <= x) && (boxGreen.getX() + static_cast<int>(boxGreen.getWidth()) >= x) &&
1022 (boxGreen.getY() <= y) && (boxGreen.getY() + static_cast<int>(boxGreen.getHeight()) >= y))
1024 BoxStack::getInstance()->handleCommand(Input::GREEN);
1026 else if ((boxYellow.getX() <= x) && (boxYellow.getX() + static_cast<int>(boxYellow.getWidth()) >= x) &&
1027 (boxYellow.getY() <= y) && (boxYellow.getY() + static_cast<int>(boxYellow.getHeight()) >= y))
1029 BoxStack::getInstance()->handleCommand(Input::YELLOW);
1031 else if ((boxBlue.getX() <= x) && (boxBlue.getX() + static_cast<int>(boxBlue.getWidth()) >= x) &&
1032 (boxBlue.getY() <= y) && (boxBlue.getY() + static_cast<int>(boxBlue.getHeight()) >= y))
1034 BoxStack::getInstance()->handleCommand(Input::BLUE);
1038 BoxStack::getInstance()->handleCommand(Input::OK); //simulate rok press
1043 BoxStack::getInstance()->handleCommand(Input::OK); //simulate rok press
1046 else if (m->message == Message::CHANNEL_CHANGE)
1048 channelChange(NUMBER, m->parameter);
1049 osdChannelIndex = currentChannelIndex;
1050 if (m->tag == 1) displayOSD(true);
1052 else if (m->message == Message::CHILD_CLOSE)
1060 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1062 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter);
1063 player->setAudioChannel((m->parameter & 0xFFFF), (m->parameter & 0xFF0000) >> 16, (m->parameter & 0xFF000000) >> 24);
1065 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1067 if (streamType != VDR::VIDEO) return;
1069 PlayerVideoLive* playervl = static_cast<PlayerVideoLive*>(player);
1071 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter);
1072 int type = (m->parameter & 0xFF0000) >> 16;
1078 playervl->setSubtitleChannel((m->parameter & 0xFFFF));
1079 playervl->turnSubtitlesOn(true);
1080 VTeletextView* vtxt = playervl->getTeletextDecoder()->getTeletxtView();
1081 if (vtxt && vtxt->isInSubtitleMode())
1083 BoxStack::getInstance()->remove(vtxt);
1090 playervl->turnSubtitlesOn(false);
1091 VTeletextView* vtxt = playervl->getTeletextDecoder()->getTeletxtView();
1092 if (vtxt && vtxt->isInSubtitleMode())
1094 BoxStack::getInstance()->remove(vtxt);
1101 playervl->turnSubtitlesOn(false);
1103 playervl->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1110 BoxStack::getInstance()->update(vas);
1111 //BoxStack::getInstance()->update(&osd); //eveil error
1113 BoxStack::getInstance()->update(this, osd.getRegion());
1115 else if (m->message == Message::PLAYER_EVENT)
1117 switch (m->parameter)
1119 case PlayerVideoLive::CONNECTION_LOST: // connection lost detected
1121 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1122 Control::getInstance()->connectionLost();
1126 case PlayerVideoLive::STREAM_END:
1128 // Message comes from playerlivetv through master mutex, so can do anything here
1133 case PlayerVideoLive::ASPECT43:
1135 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1138 osdv->updateBackgroundColor(DrawStyle::BLACK);
1141 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1142 sAspectRatio.setVisible(true);
1144 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1147 BoxStack::getInstance()->update(this, osd.getRegion());
1152 case PlayerVideoLive::ASPECT169:
1154 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1155 sAspectRatio.setVisible(true);
1157 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1160 osdv->updateBackgroundColor(DrawStyle::BLACK);
1164 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1167 BoxStack::getInstance()->update(this, osd.getRegion());
1172 case PlayerVideoLive::PREBUFFERING:
1174 preBuffering = m->tag;
1175 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1176 bufferBar.setPercent(preBuffering);
1178 if (osd.getVisible())
1180 bufferBar.setVisible(true);
1183 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1184 BoxStack::getInstance()->update(this, &r);
1186 if (preBuffering == 100)
1188 doAudioChannelSymbol();
1196 void VVideoLiveTV::doAudioChannelSymbol()
1198 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1200 Channel* currentChannel = (*chanList)[osdChannelIndex];
1202 bool multiAudio = false;
1203 if (Audio::getInstance()->supportsAc3()) {
1204 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1206 if (currentChannel->numAPids > 1) multiAudio = true;
1210 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1211 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1212 sAudioChannels.setVisible(true);
1216 dolbylogo.setVisible(true);
1217 txtlogo.setVisible(true);
1219 if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
1220 else info.setStaticArtwork(sa_txtoff);
1221 txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
1224 if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
1225 info.setStaticArtwork(sa_dolbyon);
1226 else info.setStaticArtwork(sa_dolbyoff);
1227 dolbylogo.setTVMedia(info, WTVMedia::ZoomVertical);
1229 Demuxer* demux=Demuxer::getInstance();
1231 int vertical_size=demux->getVerticalSize();
1232 Log::getInstance()->log("VVideoRec", Log::DEBUG, "TVMedia vertical size %d", vertical_size);
1233 reslogo.setVisible(true);
1234 switch (vertical_size) {
1236 info.setStaticArtwork(sa_sd576i);
1237 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1239 info.setStaticArtwork(sa_hd720p);
1240 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1242 info.setStaticArtwork(sa_hd1080i);
1243 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1244 default: // we assume sd
1245 reslogo.setVisible(false);
1249 reslogo.setVisible(false);
1255 if (osd.getVisible())
1257 sAudioChannels.draw();
1259 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1263 BoxStack::getInstance()->update(this, &r);
1267 UINT VVideoLiveTV::upChannel(UINT index)
1269 if (index == (chanList->size() - 1)) // at the end
1270 return 0; // so go to start
1275 UINT VVideoLiveTV::downChannel(UINT index)
1277 if (index == 0) // at the start
1278 return chanList->size() - 1; // so go to end
1283 void VVideoLiveTV::toggleChopSides()
1285 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1287 if (videoMode == Video::NORMAL)
1289 videoMode = Video::LETTERBOX;
1290 video->setMode(Video::LETTERBOX);
1294 videoMode = Video::NORMAL;
1295 video->setMode(Video::NORMAL);
1299 void VVideoLiveTV::updatePosterBanner()
1301 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1303 osdposterbanner.setVisible(false);
1306 Event* toShow = NULL;
1307 if (eventList && eventList->size()) {
1308 toShow = (*eventList)[0];
1309 Channel* currentChannel = (*chanList)[osdChannelIndex];
1310 toShow->loadinfos(currentChannel->number);
1317 bool posterscale=true;
1318 if (toShow->movieInfo) {
1319 poster=toShow->movieInfo->poster;
1321 if (toShow->seriesInfo) {
1322 if (toShow->seriesInfo->banners.size()) {
1323 poster=toShow->seriesInfo->banners[0];
1325 } else if (toShow->seriesInfo->seasonposter.height) {
1326 poster=toShow->seriesInfo->seasonposter;
1327 } else if (toShow->seriesInfo->posters.size()) {
1328 poster=toShow->seriesInfo->posters[0];
1331 if (poster.height) {
1332 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1333 osdposterbanner.setVisible(true);
1335 osdposterbanner.setVisible(false);
1338 osdposterbanner.setVisible(false);
1344 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1346 drawBitmap(posX, posY, bm,region);
1348 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1349 boxstack->update(this, &r);
1352 void VVideoLiveTV::clearOSD()
1354 rectangle(area, DrawStyle::TRANSPARENT);
1355 boxstack->update(this, &area);
1358 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1361 r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1362 //now convert to our display
1363 float scalex = 720.f / static_cast<float>(region.framewidth + 1);
1364 float scaley = 576.f / static_cast<float>(region.frameheight + 1);
1365 r.x = static_cast<UINT>(floor(scalex * static_cast<float>(r.x)));
1366 r.y = static_cast<UINT>(floor(scaley * static_cast<float>(r.y)));
1367 r.w = static_cast<UINT>(ceil(scalex * static_cast<float>(r.w)) + 1.f);
1368 r.h = static_cast<UINT>(ceil(scaley * static_cast<float>(r.h)) + 1.f);
1369 rectangle(r, DrawStyle::TRANSPARENT);
1370 boxstack->update(this, &r);