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/>.
20 #include "vvideolivetv.h"
22 #include "vchannellist.h"
25 #include "playerlive.h"
26 #include "playerlivetv.h"
27 #include "playerliveradio.h"
36 #include "vaudioselector.h"
43 #include "vteletextview.h"
44 #include "vepgsummary.h"
45 #include "vepglistadvanced.h"
46 #include "staticartwork.h"
48 #include "messagequeue.h"
52 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
54 vdr = VDR::getInstance();
55 boxstack = BoxStack::getInstance();
56 video = Video::getInstance();
61 vchannelList = tvchannelList;
62 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
64 currentChannelIndex = 0;
65 previousChannelIndex = 0;
72 // Convert channel number to index
74 for(i = 0; i < chanList->size(); i++)
76 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
78 currentChannelIndex = i;
86 videoMode = video->getMode();
88 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
90 streamType = VDR::VIDEO;
91 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
95 streamType = VDR::RADIO;
96 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
100 setSize(video->getScreenWidth(), video->getScreenHeight());
102 DrawStyle transparent(0, 0, 0, 0);
103 setBackgroundColour(transparent);
105 // This variable is set to true if the user pressed OK to bring the OSD on screen
106 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
107 okTriggeredOSD = false;
110 info.setChannelLogo(initialChannelNumber);
111 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
113 if (osdv && streamType == VDR::RADIO) {
114 radioChannelLogo.setPosition(video->getScreenWidth()/4,video->getScreenHeight()/4);
115 radioChannelLogo.setSize(video->getScreenWidth()/2,video->getScreenHeight()/2);
116 radioChannelLogo.setVisible(true);
117 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
118 add(&radioChannelLogo);
121 osdposterbanner.setPosition(20,20);
122 //osdposterbanner.setBackgroundColour(DrawStyle::OSDBACKGROUND);
123 osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
124 osdposterbanner.setVisible(false);
125 add(&osdposterbanner);
127 osd.setBackgroundColour(DrawStyle::OSDBACKGROUND);
128 osd.setPosition(0, video->getScreenHeight() - 150);
129 osd.setSize(video->getScreenWidth(), 150);
130 osd.setVisible(false);
133 int channellogomove=0;
137 //osdChannelLogo.setBackgroundColour(DrawStyle::OSDBACKGROUND);
138 osdChannelLogo.setPosition(30,5);
139 osdChannelLogo.setSize(60,60);
140 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
141 osd.add(&osdChannelLogo);
142 channellogomove = 30-5;
146 //clock.setBackgroundColour(DrawStyle::OSDBACKGROUND);
147 clock.setPosition(osd.getWidth() - 100, 4);
148 clock.setSize(90, 30);
151 //osdChanNum.setBackgroundColour(DrawStyle::OSDBACKGROUND);
152 osdChanNum.setPosition(60 + channellogomove, 4);
153 osdChanNum.setSize((numberWidth * 10) + 22, getFontHeight() + 5); // 10 px = width of number chars in font
154 osd.add(&osdChanNum);
156 //osdChanName.setBackgroundColour(DrawStyle::OSDBACKGROUND);
157 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
158 osdChanName.setSize(300, 30);
159 osd.add(&osdChanName);
161 boxRed.setBackgroundColour(DrawStyle::RED);
162 boxRed.setPosition(54+0*boxdiff, 104);
163 boxRed.setSize(18, 16);
166 boxGreen.setBackgroundColour(DrawStyle::GREEN);
167 boxGreen.setPosition(54+1*boxdiff, 104);
168 boxGreen.setSize(18, 16);
171 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
172 boxYellow.setPosition(54+2*boxdiff, 104);
173 boxYellow.setSize(18, 16);
176 boxBlue.setBackgroundColour(DrawStyle::BLUE);
177 boxBlue.setPosition(54+3*boxdiff, 104);
178 boxBlue.setSize(18, 16);
181 //textRed.setBackgroundColour(DrawStyle::OSDBACKGROUND);
182 textRed.setPosition(boxRed.getX2(), 98);
183 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
184 textRed.setText(tr("Summary"));
187 if (streamType == VDR::VIDEO)
189 //textGreen.setBackgroundColour(DrawStyle::OSDBACKGROUND);
190 textGreen.setPosition(boxGreen.getX2(), 98);
191 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
192 textGreen.setText(tr("Audio"));
196 //textYellow.setBackgroundColour(DrawStyle::OSDBACKGROUND);
197 textYellow.setPosition(boxYellow.getX2(), 98);
198 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
199 textYellow.setText(tr("Teletext"));
200 osd.add(&textYellow);
202 //textBlue.setBackgroundColour(DrawStyle::OSDBACKGROUND);
203 textBlue.setPosition(boxBlue.getX2(), 98);
204 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
205 textBlue.setText(tr("EPG"));
208 //sl.setBackgroundColour(DrawStyle::OSDBACKGROUND);
209 sl.setPosition(90, 36);
213 bufferBar.setPosition(osd.getWidth() - 90, 70);
214 bufferBar.setSize(40, 20);
215 bufferBar.setVisible(true);
220 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
221 sAspectRatio.nextColour = DrawStyle::LIVETVSYMBOLS;
222 sAspectRatio.setVisible(false);
223 osd.add(&sAspectRatio);
225 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
226 sAudioChannels.nextColour = DrawStyle::LIVETVSYMBOLS;
227 sAudioChannels.setVisible(false);
228 osd.add(&sAudioChannels);
234 ninfo.setStaticArtwork(sa_txtoff);
235 txtlogo.setPosition(54+4*boxdiff,104);
236 txtlogo.setSize(22,20);
237 txtlogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
240 ninfo.setStaticArtwork(sa_dolbyoff);
241 dolbylogo.setPosition(54+4*boxdiff+15,104);
242 dolbylogo.setSize(22,20);
243 dolbylogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
246 ninfo.setStaticArtwork(sa_sd576i);
247 reslogo.setPosition(54+4*boxdiff+30,104);
248 reslogo.setSize(22,20);
249 reslogo.setTVMedia(ninfo, WTVMedia::ZoomVertical);
252 reslogo.setVisible(false);
253 dolbylogo.setVisible(false);
254 txtlogo.setVisible(false);
257 //textUnavailable.setBackgroundColour(DrawStyle::OSDBACKGROUND);
258 textUnavailable.setPosition(60, 30);
259 textUnavailable.setSize(osd.getWidth() - 120, 30);
260 textUnavailable.setText(tr("Channel Unavailable"));
261 textUnavailable.setVisible(false);
262 add(&textUnavailable);
264 vdisplay.mode = Fullscreen;
265 vdisplay.fallbackMode = Fullscreen;
272 void VVideoLiveTV::preDelete()
277 VVideoLiveTV::~VVideoLiveTV()
280 video->setDefaultAspect();
282 OsdVector* osdv = dynamic_cast<OsdVector*>(Osd::getInstance());
285 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
289 void VVideoLiveTV::delData()
293 int eventListSize = eventList->size();
294 for(int i = 0; i < eventListSize; i++)
296 delete (*eventList)[i];
303 int VVideoLiveTV::handleCommand(int command)
309 if (osd.getVisible() && !textUnavailable.getVisible())
314 // else drop through to stop
319 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
323 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
326 if (Remote::getInstance()->mayHaveFewButtons())
328 if (okTriggeredOSD) doUpDown(false);
329 else doChanUpDown(UP);
339 if (Remote::getInstance()->mayHaveFewButtons())
341 if (okTriggeredOSD) doUpDown(true);
342 else doChanUpDown(DOWN);
360 // Continue new remote only...
361 case Remote::CHANNELUP:
366 case Remote::CHANNELDOWN:
372 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
374 // DF_LEFT and DF_RIGHT never get here because they are stolen
375 // by command as vol- and vol+
377 // Old remote. Decide what to do based on whether
378 // OK was pressed - osd shown manually, use up/down for epg nav
379 // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
383 // Old remote, decide what to do based on okTriggeredOSD
384 if (okTriggeredOSD) doUpDown(false);
385 else doChanUpDown(UP);
388 case Remote::DF_DOWN:
390 // Old remote, decide what to do based on okTriggeredOSD
391 if (okTriggeredOSD) doUpDown(true);
392 else doChanUpDown(DOWN);
396 // END NEW/OLD REMOTE STUFF
398 case Remote::PREVCHANNEL:
400 channelChange(PREVIOUS, 0);
401 osdChannelIndex = currentChannelIndex;
434 // key in channel number
441 if (streamType == VDR::VIDEO) doAudioSelector();
446 if (streamType ==VDR::VIDEO)
448 doTeletext(); //TODO: Add a selector for subtitles or teletext
459 if (streamType == VDR::VIDEO)
460 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
467 void VVideoLiveTV::go()
471 boxstack->update(this);
476 player->go(currentChannelIndex);
479 void VVideoLiveTV::stop()
481 Timers::getInstance()->cancelTimer(this, 1);
482 Timers::getInstance()->cancelTimer(this, 2);
487 void VVideoLiveTV::doLeftRight(bool right)
489 if (osd.getVisible())
491 if (right) osdChannelIndex = upChannel(osdChannelIndex);
492 else osdChannelIndex = downChannel(osdChannelIndex);
496 osdChannelIndex = currentChannelIndex;
501 void VVideoLiveTV::doUpDown(bool down)
503 if (osd.getVisible())
515 void VVideoLiveTV::doChanUpDown(int which)
517 channelChange(OFFSET, which);
518 osdChannelIndex = currentChannelIndex;
522 void VVideoLiveTV::doOK()
524 if (osd.getVisible())
529 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
531 channelChange(NUMBER, newChannel);
532 osdChannelIndex = currentChannelIndex;
535 else if (osdChannelIndex == currentChannelIndex)
541 channelChange(INDEX, osdChannelIndex);
547 osdChannelIndex = currentChannelIndex;
549 okTriggeredOSD = true;
553 void VVideoLiveTV::doSummary()
556 Channel* currentChannel = (*chanList)[osdChannelIndex];
557 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
562 sort(eventList->begin(), eventList->end(), EventSorter());
564 if (eventList->size() < 1) return;
565 Event* event = (*eventList)[0];
566 event->loadinfos(currentChannel->number);
568 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
571 boxstack->update(vr);
574 void VVideoLiveTV::doKey(int command)
576 if (!osd.getVisible()) // First key. prep the data
579 updatePosterBanner();
584 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
585 keyingInput[0] = command;
588 char* keyingString = new char[numberWidth + 1];
589 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
590 keyingString[numberWidth] = '\0';
592 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
594 if (keying == numberWidth)
597 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
599 channelChange(NUMBER, newChannel);
600 osdChannelIndex = currentChannelIndex;
601 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
602 displayOSD(true); // this will put one back if required
606 osdChanNum.setText(keyingString);
608 if (!osd.getVisible())
610 osd.setVisible(true);
617 boxstack->update(this, osd.getRegion());
618 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
620 delete[] keyingString;
623 void VVideoLiveTV::doTeletext(bool subtitlemode)
625 if (streamType !=VDR::VIDEO) return;
626 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
633 // and reset the display - this is a copy from setNowNextData
634 char formatChanNum[20];
635 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
636 osdChanNum.setText(formatChanNum);
637 osdChanName.setText((*chanList)[osdChannelIndex]->name);
639 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
640 if (osd.getVisible()) clearScreen();
642 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
645 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
646 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
650 vtxv->setSubtitleMode(subtitlemode);
656 BoxStack::getInstance()->add(vtxv);
659 BoxStack::getInstance()->update(this);
660 BoxStack::getInstance()->update(vtxv);
663 void VVideoLiveTV::doAudioSelector()
665 // If the osd is already visisble there might be a timer for it
666 Timers::getInstance()->cancelTimer(this, 1);
667 //This causes a deadlock with the timertrhread itself is locked
673 // and reset the display - this is a copy from setNowNextData
674 char formatChanNum[20];
675 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
676 osdChanNum.setText(formatChanNum);
677 osdChanName.setText((*chanList)[osdChannelIndex]->name);
679 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
680 int subtitleType=0x10;
681 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
682 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
683 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
685 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
689 subtitleType=0xFF; //turnedOff
695 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
696 subtitleType,subtitleChannel,NULL);
698 vas->setBackgroundColour(DrawStyle::OSDBACKGROUND);
699 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
702 // make vas != null and displayOSD will not set a timer or do any boxstack update
703 if (osd.getVisible()) displayOSD(false);
704 else displayOSD(true);
707 BoxStack::getInstance()->add(vas);
708 BoxStack::getInstance()->update(this);
709 BoxStack::getInstance()->update(vas);
712 void VVideoLiveTV::doEPG()
714 if (osd.getVisible()) clearScreen();
716 if (!Command::getInstance()->isAdvMenus())
718 VEpg* vepg = new VEpg(this, currentChannelIndex, chanList);
721 boxstack->update(vepg);
725 Channel* currentChannel = (*chanList)[osdChannelIndex];
726 VEpgListAdvanced *vepg= new VEpgListAdvanced(this, chanList, currentChannel->number);
729 boxstack->update(vepg);
733 void VVideoLiveTV::setNowNextData()
737 Channel* currentChannel = (*chanList)[osdChannelIndex];
739 char formatChanNum[20];
740 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
741 osdChanNum.setText(formatChanNum);
742 osdChanName.setText(currentChannel->name);
744 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
748 sl.setText(tr("No channel data available"));
752 sort(eventList->begin(), eventList->end(), EventSorter());
754 char tempString[300];
755 char tempString2[300];
758 int eventListSize = eventList->size();
759 std::stringstream string;
760 for(int i = 0; i < eventListSize; i++)
762 event = (*eventList)[i];
764 time_t etime = event->time;
765 LOCALTIME_R(&etime, &btime);
767 strftime(tempString2, 299, "%0H:%0M ", &btime);
769 strftime(tempString2, 299, "%H:%M ", &btime);
771 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
772 string << tempString << "\n";
774 sl.setText(string.str().c_str());
780 void VVideoLiveTV::displayOSD(bool newNowNextData)
782 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
783 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(true);
784 osd.setVisible(true);
788 updatePosterBanner();
792 if (osdposterbanner.getVisible()) osdposterbanner.draw();
797 toupdate=*osd.getRegion();
800 if (osdposterbanner.getVisible())
802 boxstack->update(this);
806 boxstack->update(this, &toupdate);
809 bool setTimer = true;
810 if (vas) setTimer = false;
811 if (textUnavailable.getVisible()) setTimer = false;
813 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
816 void VVideoLiveTV::clearScreen()
818 Timers::getInstance()->cancelTimer(this, 1);
820 textUnavailable.setVisible(false);
821 osd.setVisible(false);
822 osdposterbanner.setVisible(false);
824 okTriggeredOSD = false;
827 boxstack->update(this);
829 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
830 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
833 void VVideoLiveTV::showUnavailable()
835 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
836 textUnavailable.setVisible(true);
837 textUnavailable.draw();
839 if (!osd.getVisible()) displayOSD(true);
841 boxstack->update(this, textUnavailable.getRegion());
844 void VVideoLiveTV::setClock()
850 LOCALTIME_R(&t, &tms);
851 strftime(timeString, 19, "%H:%M", &tms);
852 clock.setText(timeString);
854 time_t dt = 60 - (t % 60); // seconds to the next minute
855 if (dt == 0) dt = 60; // advance a whole minute if necessary
856 dt += t; // get a time_t value for it rather than using duration
857 // (so it will occur at the actual second and not second and a half)
859 Timers::getInstance()->setTimerT(this, 2, dt);
862 void VVideoLiveTV::timercall(int ref)
868 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
870 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
872 Message* m = new Message();
873 m->message = Message::CHANNEL_CHANGE;
875 m->parameter = newChannel;
876 m->tag = 1; // signal to call displayOSD();
877 MessageQueue::getInstance()->postMessageFromOuterSpace(m);
878 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
882 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
883 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
884 if (preBuffering < 100)
886 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
887 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
890 bool osdpbvisible=osdposterbanner.getVisible();
891 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
892 osd.setVisible(false);
893 osdposterbanner.setVisible(false);
894 okTriggeredOSD = false;
895 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
897 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
898 if (osdpbvisible) boxstack->update(this);
899 else boxstack->update(this, osd.getRegion());
901 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
902 PlayerLiveTV* playerlivetv = dynamic_cast<PlayerLiveTV*>(player);
903 if (playerlivetv) playerlivetv->tellSubtitlesOSDVisible(false);
904 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
909 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
911 if (osd.getVisible())
914 boxstack->update(this, osd.getRegion());
916 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
920 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
923 if (streamType == VDR::VIDEO)
925 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
928 BoxStack::getInstance()->remove(vtxt);
931 if (changeType == INDEX)
933 newChannel = newData;
935 else if (changeType == NUMBER)
938 for(i = 0; i < chanList->size(); i++)
940 if ((*chanList)[i]->number == (UINT)newData)
947 if (i == chanList->size())
953 else if (changeType == OFFSET)
955 if (newData == UP) newChannel = upChannel(currentChannelIndex);
956 else newChannel = downChannel(currentChannelIndex);
958 else if (changeType == PREVIOUS)
960 newChannel = previousChannelIndex;
964 return false; // bad input
967 if (newChannel == currentChannelIndex) return true;
969 previousChannelIndex = currentChannelIndex;
970 currentChannelIndex = newChannel;
974 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
975 player->setChannel(currentChannelIndex);
976 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
978 // Blank out the symbols
979 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
981 bufferBar.setPercent(0);
985 sAudioChannels.setVisible(false);
986 sAspectRatio.setVisible(false);
990 reslogo.setVisible(false);
991 dolbylogo.setVisible(false);
992 txtlogo.setVisible(false);
995 // Remove other stuff
996 if (textUnavailable.getVisible())
998 textUnavailable.setVisible(false);
1004 Channel* currentChannel = (*chanList)[currentChannelIndex];
1007 info.setChannelLogo(currentChannel->number);
1008 if (streamType == VDR::RADIO)
1010 radioChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1011 radioChannelLogo.setVisible(true);
1013 osdChannelLogo.setTVMedia(info, WTVMedia::ZoomVertical);
1018 BoxStack::getInstance()->update(this);
1023 void VVideoLiveTV::processMessage(Message* m)
1025 if (m->message == Message::MOUSE_LBDOWN)
1027 //check if press is outside this view! then simulate cancel
1028 int x = (m->parameter >> 16) - osd.getScreenX();
1029 int y = (m->parameter & 0xFFFF) - osd.getScreenY();
1030 if (osd.getVisible())
1032 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
1033 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y ))
1035 BoxStack::getInstance()->handleCommand(Remote::RED);
1037 else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
1038 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y))
1040 BoxStack::getInstance()->handleCommand(Remote::GREEN);
1042 else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
1043 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
1044 BoxStack::getInstance()->handleCommand(Remote::YELLOW);
1046 else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
1047 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y ))
1049 BoxStack::getInstance()->handleCommand(Remote::BLUE);
1053 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1058 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1061 else if (m->message == Message::CHANNEL_CHANGE)
1063 channelChange(NUMBER, m->parameter);
1064 osdChannelIndex = currentChannelIndex;
1065 if (m->tag == 1) displayOSD(true);
1067 else if (m->message == Message::CHILD_CLOSE)
1075 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1077 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter);
1078 player->setAudioChannel((m->parameter & 0xFFFF), (m->parameter & 0xFF0000) >> 16, (m->parameter & 0xFF000000) >> 24);
1080 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1082 if (streamType != VDR::VIDEO) return;
1083 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter);
1084 int type = (m->parameter & 0xFF0000) >> 16;
1090 if (streamType == VDR::VIDEO)
1092 player->setSubtitleChannel((m->parameter & 0xFFFF));
1093 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1094 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1095 if (vtxt && vtxt->isInSubtitleMode())
1097 BoxStack::getInstance()->remove(vtxt);
1103 if (streamType == VDR::VIDEO){
1104 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1105 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1106 if (vtxt && vtxt->isInSubtitleMode()) {
1107 BoxStack::getInstance()->remove(vtxt);
1114 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1116 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1122 BoxStack::getInstance()->update(vas);
1123 //BoxStack::getInstance()->update(&osd); //eveil error
1125 BoxStack::getInstance()->update(this, osd.getRegion());
1127 else if (m->message == Message::PLAYER_EVENT)
1129 switch (m->parameter)
1131 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1133 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1134 Command::getInstance()->connectionLost();
1138 case PlayerLiveTV::STREAM_END:
1140 // Message comes from playerlivetv through master mutex, so can do anything here
1145 case PlayerLiveTV::ASPECT43:
1147 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1150 osdv->updateBackgroundColor(DrawStyle::BLACK);
1153 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1154 sAspectRatio.setVisible(true);
1156 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1159 BoxStack::getInstance()->update(this, osd.getRegion());
1164 case PlayerLiveTV::ASPECT169:
1166 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1167 sAspectRatio.setVisible(true);
1169 OsdVector* osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1172 osdv->updateBackgroundColor(DrawStyle::WALLPAPER);
1176 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1179 BoxStack::getInstance()->update(this, osd.getRegion());
1184 case PlayerLiveTV::PREBUFFERING:
1186 preBuffering = m->tag;
1187 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1188 bufferBar.setPercent(preBuffering);
1190 if (osd.getVisible())
1192 bufferBar.setVisible(true);
1195 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1196 BoxStack::getInstance()->update(this, &r);
1198 if (preBuffering == 100)
1200 doAudioChannelSymbol();
1208 void VVideoLiveTV::doAudioChannelSymbol()
1210 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1212 Channel* currentChannel = (*chanList)[osdChannelIndex];
1214 bool multiAudio = false;
1215 if (Audio::getInstance()->supportsAc3()) {
1216 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1218 if (currentChannel->numAPids > 1) multiAudio = true;
1222 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1223 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1224 sAudioChannels.setVisible(true);
1228 dolbylogo.setVisible(true);
1229 txtlogo.setVisible(true);
1231 if (currentChannel->tpid!=0) info.setStaticArtwork(sa_txton);
1232 else info.setStaticArtwork(sa_txtoff);
1233 txtlogo.setTVMedia(info, WTVMedia::ZoomVertical);
1236 if (Audio::getInstance()->supportsAc3() && currentChannel->numDPids>1)
1237 info.setStaticArtwork(sa_dolbyon);
1238 else info.setStaticArtwork(sa_dolbyoff);
1239 dolbylogo.setTVMedia(info, WTVMedia::ZoomVertical);
1241 Demuxer* demux=Demuxer::getInstance();
1243 int vertical_size=demux->getVerticalSize();
1244 Log::getInstance()->log("VVideoRec", Log::DEBUG, "TVMedia vertical size %d", vertical_size);
1245 reslogo.setVisible(true);
1246 switch (vertical_size) {
1248 info.setStaticArtwork(sa_sd576i);
1249 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1251 info.setStaticArtwork(sa_hd720p);
1252 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1254 info.setStaticArtwork(sa_hd1080i);
1255 reslogo.setTVMedia(info, WTVMedia::ZoomVertical);break;
1256 default: // we assume sd
1257 reslogo.setVisible(false);
1261 reslogo.setVisible(false);
1267 if (osd.getVisible())
1269 sAudioChannels.draw();
1271 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1275 BoxStack::getInstance()->update(this, &r);
1279 UINT VVideoLiveTV::upChannel(UINT index)
1281 if (index == (chanList->size() - 1)) // at the end
1282 return 0; // so go to start
1287 UINT VVideoLiveTV::downChannel(UINT index)
1289 if (index == 0) // at the start
1290 return chanList->size() - 1; // so go to end
1295 void VVideoLiveTV::toggleChopSides()
1297 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1299 if (videoMode == Video::NORMAL)
1301 videoMode = Video::LETTERBOX;
1302 video->setMode(Video::LETTERBOX);
1306 videoMode = Video::NORMAL;
1307 video->setMode(Video::NORMAL);
1311 void VVideoLiveTV::updatePosterBanner()
1313 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1315 osdposterbanner.setVisible(false);
1318 Event* toShow = NULL;
1319 if (eventList && eventList->size()) {
1320 toShow = (*eventList)[0];
1321 Channel* currentChannel = (*chanList)[osdChannelIndex];
1322 toShow->loadinfos(currentChannel->number);
1329 bool posterscale=true;
1330 if (toShow->movieInfo) {
1331 poster=toShow->movieInfo->poster;
1333 if (toShow->seriesInfo) {
1334 if (toShow->seriesInfo->banners.size()) {
1335 poster=toShow->seriesInfo->banners[0];
1337 } else if (toShow->seriesInfo->seasonposter.height) {
1338 poster=toShow->seriesInfo->seasonposter;
1339 } else if (toShow->seriesInfo->posters.size()) {
1340 poster=toShow->seriesInfo->posters[0];
1343 if (poster.height) {
1344 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1345 osdposterbanner.setVisible(true);
1347 osdposterbanner.setVisible(false);
1350 osdposterbanner.setVisible(false);
1356 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1358 drawBitmap(posX, posY, bm,region);
1360 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1361 boxstack->update(this, &r);
1364 void VVideoLiveTV::clearOSD()
1366 rectangle(area, DrawStyle(0,0,0,0));
1367 boxstack->update(this, &area);
1370 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1373 r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1374 //now convert to our display
1375 float scalex=720.f/((float) (region.framewidth+1));
1376 float scaley=576.f/((float) (region.frameheight+1));
1377 r.x = (UINT)floor(scalex*((float)r.x));
1378 r.y = (UINT)floor(scaley*((float)r.y));
1379 r.w = (UINT)(ceil(scalex*((float)r.w))+1.f);
1380 r.h = (UINT)(ceil(scaley*((float)r.h))+1.f);
1381 rectangle(r, DrawStyle(0,0,0,0));
1382 boxstack->update(this, &r);