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"
47 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
48 : osdBack(0, 0, 0, 128)
50 vdr = VDR::getInstance();
51 boxstack = BoxStack::getInstance();
52 video = Video::getInstance();
57 vchannelList = tvchannelList;
58 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
60 currentChannelIndex = 0;
61 previousChannelIndex = 0;
68 // Convert channel number to index
70 for(i = 0; i < chanList->size(); i++)
72 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
74 currentChannelIndex = i;
82 videoMode = video->getMode();
84 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
86 streamType = VDR::VIDEO;
87 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
91 streamType = VDR::RADIO;
92 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
96 setSize(video->getScreenWidth(), video->getScreenHeight());
98 DrawStyle transparent(0, 0, 0, 0);
99 setBackgroundColour(transparent);
102 char* optionWSS = vdr->configLoad("General", "WSS");
105 if (strstr(optionWSS, "Yes")) dowss = true;
108 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
112 wss.setFormat(video->getFormat());
118 wssRegion.w = video->getScreenWidth();
122 // This variable is set to true if the user pressed OK to bring the OSD on screen
123 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
124 okTriggeredOSD = false;
126 osdposterbanner.setPosition(20,20);
127 osdposterbanner.setBackgroundColour(osdBack);
128 osdposterbanner.setSize(video->getScreenWidth()*4/10,video->getScreenHeight()*4/10);
129 osdposterbanner.setVisible(false);
130 add(&osdposterbanner);
133 osd.setBackgroundColour(osdBack);
134 osd.setPosition(0, video->getScreenHeight() - 150);
135 osd.setSize(video->getScreenWidth(), 150);
136 osd.setVisible(false);
140 clock.setBackgroundColour(osdBack);
141 clock.setPosition(osd.getWidth() - 100, 4);
142 clock.setSize(90, 30);
145 osdChanNum.setBackgroundColour(osdBack);
146 osdChanNum.setPosition(50, 4);
147 osdChanNum.setSize((numberWidth*10) + 22, 30); // 10 px = width of number chars in font
148 osd.add(&osdChanNum);
150 osdChanName.setBackgroundColour(osdBack);
151 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
152 osdChanName.setSize(300, 30);
153 osd.add(&osdChanName);
155 boxRed.setBackgroundColour(DrawStyle::RED);
156 boxRed.setPosition(54, 104);
157 boxRed.setSize(18, 16);
160 boxGreen.setBackgroundColour(DrawStyle::GREEN);
161 boxGreen.setPosition(220, 104);
162 boxGreen.setSize(18, 16);
165 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
166 boxYellow.setPosition(390, 104);
167 boxYellow.setSize(18, 16);
170 boxBlue.setBackgroundColour(DrawStyle::BLUE);
171 boxBlue.setPosition(560, 104);
172 boxBlue.setSize(18, 16);
175 textRed.setBackgroundColour(osdBack);
176 textRed.setPosition(boxRed.getX2(), 98);
177 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
178 textRed.setText(tr("Summary"));
181 if (streamType == VDR::VIDEO)
183 textGreen.setBackgroundColour(osdBack);
184 textGreen.setPosition(boxGreen.getX2(), 98);
185 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
186 textGreen.setText(tr("Audio"));
190 textYellow.setBackgroundColour(osdBack);
191 textYellow.setPosition(boxYellow.getX2(), 98);
192 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
193 textYellow.setText(tr("Teletext"));
194 osd.add(&textYellow);
196 textBlue.setBackgroundColour(osdBack);
197 textBlue.setPosition(boxBlue.getX2(), 98);
198 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
199 textBlue.setText(tr("EPG"));
202 sl.setBackgroundColour(osdBack);
203 sl.setPosition(70, 36);
209 summary.setBackgroundColour(osdBack);
210 summary.setPosition(0, video->getScreenHeight() - 300);
211 summary.setSize(video->getScreenWidth(), 150);
212 summary.setVisible(false);
215 textSummary.setBackgroundColour(osdBack);
216 textSummary.setPosition(40, 10);
217 textSummary.setSize(video->getScreenWidth() - 80, 130);
218 textSummary.setParaMode(true);
219 summary.add(&textSummary);
221 summaryBlackLine.setBackgroundColour(DrawStyle::BLACK);
222 summaryBlackLine.setPosition(0, summary.getHeight() - 4);
223 summaryBlackLine.setSize(summary.getWidth(), 4);
224 summary.add(&summaryBlackLine);
226 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
227 sAspectRatio.nextColour = DrawStyle::SELECTHIGHLIGHT;
228 sAspectRatio.setVisible(false);
229 osd.add(&sAspectRatio);
231 bufferBar.setPosition(osd.getWidth() - 90, 70);
232 bufferBar.setSize(40, 20);
233 bufferBar.setVisible(true);
236 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
237 sAudioChannels.nextColour = DrawStyle::SELECTHIGHLIGHT;
238 sAudioChannels.setVisible(false);
239 osd.add(&sAudioChannels);
241 textUnavailable.setBackgroundColour(osdBack);
242 textUnavailable.setPosition(60, 30);
243 textUnavailable.setSize(osd.getWidth() - 120, 30);
244 textUnavailable.setText(tr("Channel Unavailable"));
245 textUnavailable.setVisible(false);
246 add(&textUnavailable);
249 Region r1 = summary.getRegionR();
250 Region r2 = osd.getRegionR();
251 osdSummaryRegion = r1 + r2;
254 void VVideoLiveTV::preDelete()
259 VVideoLiveTV::~VVideoLiveTV()
262 video->setDefaultAspect();
266 void VVideoLiveTV::delData()
270 int eventListSize = eventList->size();
271 for(int i = 0; i < eventListSize; i++)
273 delete (*eventList)[i];
282 int VVideoLiveTV::handleCommand(int command)
288 if (osd.getVisible() && !textUnavailable.getVisible())
293 // else drop through to stop
298 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
302 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
305 if (Remote::getInstance()->mayHaveFewButtons()) {
306 if (okTriggeredOSD) doUpDown(false);
307 else doChanUpDown(UP);
315 if (Remote::getInstance()->mayHaveFewButtons()) {
316 if (okTriggeredOSD) doUpDown(true);
317 else doChanUpDown(DOWN);
333 // Continue new remote only...
334 case Remote::CHANNELUP:
339 case Remote::CHANNELDOWN:
345 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
347 // DF_LEFT and DF_RIGHT never get here because they are stolen
348 // by command as vol- and vol+
350 // Old remote. Decide what to do based on whether
351 // OK was pressed - osd shown manually, use up/down for epg nav
352 // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
356 // Old remote, decide what to do based on okTriggeredOSD
357 if (okTriggeredOSD) doUpDown(false);
358 else doChanUpDown(UP);
361 case Remote::DF_DOWN:
363 // Old remote, decide what to do based on okTriggeredOSD
364 if (okTriggeredOSD) doUpDown(true);
365 else doChanUpDown(DOWN);
369 // END NEW/OLD REMOTE STUFF
371 case Remote::PREVCHANNEL:
373 channelChange(PREVIOUS, 0);
374 osdChannelIndex = currentChannelIndex;
407 // key in channel number
414 if (streamType == VDR::VIDEO) doAudioSelector();
419 if (streamType ==VDR::VIDEO)
421 doTeletext(); //TODO: Add a selector for subtitles or teletext
432 if (streamType == VDR::VIDEO)
433 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
440 void VVideoLiveTV::go()
444 boxstack->update(this);
449 player->go(currentChannelIndex);
452 void VVideoLiveTV::stop()
454 Timers::getInstance()->cancelTimer(this, 1);
455 Timers::getInstance()->cancelTimer(this, 2);
460 void VVideoLiveTV::doLeftRight(bool right)
462 if (osd.getVisible())
464 if (right) osdChannelIndex = upChannel(osdChannelIndex);
465 else osdChannelIndex = downChannel(osdChannelIndex);
469 osdChannelIndex = currentChannelIndex;
474 void VVideoLiveTV::doUpDown(bool down)
476 if (osd.getVisible())
490 void VVideoLiveTV::doChanUpDown(int which)
492 channelChange(OFFSET, which);
493 osdChannelIndex = currentChannelIndex;
497 void VVideoLiveTV::doOK()
499 if (osd.getVisible())
504 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
506 channelChange(NUMBER, newChannel);
507 osdChannelIndex = currentChannelIndex;
510 else if (osdChannelIndex == currentChannelIndex)
516 channelChange(INDEX, osdChannelIndex);
522 osdChannelIndex = currentChannelIndex;
524 okTriggeredOSD = true;
528 void VVideoLiveTV::doSummary()
531 Channel* currentChannel = (*chanList)[osdChannelIndex];
532 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
537 sort(eventList->begin(), eventList->end(), EventSorter());
539 if (eventList->size() < 1) return;
540 Event* event = (*eventList)[0];
541 event->loadinfos(currentChannel->number);
543 VEpgSummary* vr = new VEpgSummary(event,currentChannel);
546 boxstack->update(vr);
548 if (summary.getVisible())
550 summary.setVisible(false);
552 boxstack->update(this, summary.getRegion());
553 Timers::getInstance()->setTimerD(this, 1, 8); // Restart a timer to get rid of osd
557 summary.setVisible(true);
559 if (osd.getVisible())
561 Timers::getInstance()->cancelTimer(this, 1);
570 void VVideoLiveTV::doKey(int command)
572 if (!osd.getVisible()) // First key. prep the data
575 updatePosterBanner();
580 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
581 keyingInput[0] = command;
584 char* keyingString = new char[numberWidth + 1];
585 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
586 keyingString[numberWidth] = '\0';
588 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
590 if (keying == numberWidth)
593 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
595 channelChange(NUMBER, newChannel);
596 osdChannelIndex = currentChannelIndex;
597 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
598 displayOSD(true); // this will put one back if required
602 osdChanNum.setText(keyingString);
604 if (!osd.getVisible())
606 osd.setVisible(true);
613 boxstack->update(this, osd.getRegion());
614 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
616 delete[] keyingString;
619 void VVideoLiveTV::doTeletext(bool subtitlemode)
621 if (streamType !=VDR::VIDEO) return;
622 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
629 // and reset the display - this is a copy from setNowNextData
630 char formatChanNum[20];
631 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
632 osdChanNum.setText(formatChanNum);
633 osdChanName.setText((*chanList)[osdChannelIndex]->name);
635 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
636 if (osd.getVisible()) clearScreen();
638 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
640 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this, (PlayerLiveTV*)player);
641 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
644 vtxv->setSubtitleMode(subtitlemode);
649 BoxStack::getInstance()->add(vtxv);
651 BoxStack::getInstance()->update(this);
652 BoxStack::getInstance()->update(vtxv);
655 void VVideoLiveTV::doAudioSelector()
657 // If the osd is already visisble there might be a timer for it
658 Timers::getInstance()->cancelTimer(this, 1);
659 //This causes a deadlock with the timertrhread itself is locked
666 // and reset the display - this is a copy from setNowNextData
667 char formatChanNum[20];
668 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
669 osdChanNum.setText(formatChanNum);
670 osdChanName.setText((*chanList)[osdChannelIndex]->name);
672 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
673 int subtitleType=0x10;
674 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
675 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
676 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
678 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
682 subtitleType=0xFF; //turnedOff
688 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
689 subtitleType,subtitleChannel,NULL);
691 vas->setBackgroundColour(osdBack);
692 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
695 // make vas != null and displayOSD will not set a timer or do any boxstack update
696 summary.setVisible(false);
697 if (osd.getVisible()) displayOSD(false);
698 else displayOSD(true);
701 BoxStack::getInstance()->add(vas);
702 BoxStack::getInstance()->update(this);
703 BoxStack::getInstance()->update(vas);
706 void VVideoLiveTV::doEPG()
708 if (osd.getVisible()) clearScreen();
710 video->setMode(Video::QUARTER);
711 video->setPosition(170, 5); //TODO need to deal with 4:3 switching
713 VEpg* vepg = new VEpg(this, currentChannelIndex, streamType);
716 boxstack->update(vepg);
719 void VVideoLiveTV::setNowNextData()
723 Channel* currentChannel = (*chanList)[osdChannelIndex];
725 char formatChanNum[20];
726 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
727 osdChanNum.setText(formatChanNum);
728 osdChanName.setText(currentChannel->name);
730 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
734 sl.addOption(tr("No channel data available"), 0, 1);
738 sort(eventList->begin(), eventList->end(), EventSorter());
740 char tempString[300];
741 char tempString2[300];
744 int eventListSize = eventList->size();
745 for(int i = 0; i < eventListSize; i++)
747 event = (*eventList)[i];
749 //btime = localtime((time_t*)&event->time);
750 time_t etime = event->time;
751 btime = localtime(&etime);
753 strftime(tempString2, 299, "%0H:%0M ", btime);
755 strftime(tempString2, 299, "%H:%M ", btime);
757 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
759 sl.addOption(tempString, (ULONG)event, (i==0));
764 void VVideoLiveTV::setSummaryData()
766 // If osd is not being displayed, sl will be filled with now, current channel
767 // If the display was already on, sl will have programme to show summary for, not necessarily current channel and now
768 Event* selectedEvent = (Event*)sl.getCurrentOptionData();
772 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "No summary");
773 textSummary.setText(tr("No summary available"));
777 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Summary: %s", selectedEvent->description);
778 textSummary.setText(selectedEvent->description);
782 void VVideoLiveTV::displayOSD(bool newNowNextData)
784 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(true);
785 osd.setVisible(true);
789 updatePosterBanner();
793 if (osdposterbanner.getVisible()) osdposterbanner.draw();
797 if (summary.getVisible())
801 toupdate=osdSummaryRegion;
805 toupdate=*osd.getRegion();
808 if (osdposterbanner.getVisible()) {
809 boxstack->update(this);
811 boxstack->update(this, &toupdate);
814 bool setTimer = true;
815 if (vas) setTimer = false;
816 if (summary.getVisible()) setTimer = false;
817 if (textUnavailable.getVisible()) setTimer = false;
819 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
822 void VVideoLiveTV::clearScreen()
824 if (!summary.getVisible()) Timers::getInstance()->cancelTimer(this, 1);
826 textUnavailable.setVisible(false);
827 osd.setVisible(false);
828 summary.setVisible(false);
829 osdposterbanner.setVisible(false);
831 okTriggeredOSD = false;
834 boxstack->update(this);
836 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(false);
839 void VVideoLiveTV::showUnavailable()
841 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
842 textUnavailable.setVisible(true);
843 textUnavailable.draw();
845 if (!osd.getVisible()) displayOSD(true);
847 boxstack->update(this, textUnavailable.getRegion());
850 void VVideoLiveTV::setClock()
855 struct tm* tms = localtime(&t);
856 strftime(timeString, 19, "%H:%M", tms);
857 clock.setText(timeString);
859 time_t dt = 60 - (t % 60); // seconds to the next minute
860 if (dt == 0) dt = 60; // advance a whole minute if necessary
861 dt += t; // get a time_t value for it rather than using duration
862 // (so it will occur at the actual second and not second and a half)
864 Timers::getInstance()->setTimerT(this, 2, dt);
867 void VVideoLiveTV::timercall(int ref)
873 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
875 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
877 Message* m = new Message();
878 m->message = Message::CHANNEL_CHANGE;
880 m->parameter = newChannel;
881 m->tag = 1; // signal to call displayOSD();
882 Command::getInstance()->postMessageFromOuterSpace(m);
883 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
887 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
888 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
889 if (preBuffering < 100)
891 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
892 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
895 bool osdpbvisible=osdposterbanner.getVisible();
896 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
897 osd.setVisible(false);
898 osdposterbanner.setVisible(false);
899 okTriggeredOSD = false;
900 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
902 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
903 if (osdpbvisible) boxstack->update(this);
904 else boxstack->update(this, osd.getRegion());
906 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
907 (static_cast<PlayerLiveTV*>(player))->tellSubtitlesOSDVisible(false);
908 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
913 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
915 if (osd.getVisible())
918 boxstack->update(this, osd.getRegion());
920 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
924 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
927 if (streamType ==VDR::VIDEO) {
928 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
930 BoxStack::getInstance()->remove(vtxt);
934 if (changeType == INDEX)
936 newChannel = newData;
938 else if (changeType == NUMBER)
941 for(i = 0; i < chanList->size(); i++)
943 if ((*chanList)[i]->number == (UINT)newData)
950 if (i == chanList->size())
956 else if (changeType == OFFSET)
958 if (newData == UP) newChannel = upChannel(currentChannelIndex);
959 else newChannel = downChannel(currentChannelIndex);
961 else if (changeType == PREVIOUS)
963 newChannel = previousChannelIndex;
967 return false; // bad input
970 if (newChannel == currentChannelIndex) return true;
972 previousChannelIndex = currentChannelIndex;
973 currentChannelIndex = newChannel;
977 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
978 player->setChannel(currentChannelIndex);
979 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
981 // Blank out the symbols
982 sAspectRatio.setVisible(false);
983 bufferBar.setPercent(0);
984 sAudioChannels.setVisible(false);
986 // Remove other stuff
987 if (textUnavailable.getVisible())
989 textUnavailable.setVisible(false);
994 BoxStack::getInstance()->update(this);
999 void VVideoLiveTV::processMessage(Message* m)
1001 if (m->message == Message::MOUSE_LBDOWN)
1003 //check if press is outside this view! then simulate cancel
1004 int x=(m->parameter>>16)-osd.getScreenX();
1005 int y=(m->parameter&0xFFFF)-osd.getScreenY();
1006 if (osd.getVisible()) {
1008 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
1009 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y )) {
1010 BoxStack::getInstance()->handleCommand(Remote::RED);
1011 } else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
1012 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y)){
1013 BoxStack::getInstance()->handleCommand(Remote::GREEN);
1014 } else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
1015 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
1016 BoxStack::getInstance()->handleCommand(Remote::YELLOW);
1017 } else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
1018 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y )){
1019 BoxStack::getInstance()->handleCommand(Remote::BLUE);
1021 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1025 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
1028 else if (m->message == Message::CHANNEL_CHANGE)
1030 channelChange(NUMBER, m->parameter);
1031 osdChannelIndex = currentChannelIndex;
1032 if (m->tag == 1) displayOSD(true);
1034 else if (m->message == Message::EPG_CLOSE)
1036 video->setMode(videoMode);
1038 else if (m->message == Message::CHILD_CLOSE)
1046 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
1048 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %x", m->parameter);
1049 player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16,(m->parameter & 0xFF000000)>>24);
1051 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
1053 if (streamType !=VDR::VIDEO) return;
1054 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %x", m->parameter);
1055 int type=((m->parameter & 0xFF0000)>>16);
1057 case 0x10: { //dvbsubtitle
1058 if (streamType == VDR::VIDEO){
1059 player->setSubtitleChannel((m->parameter & 0xFFFF));
1060 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1061 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1062 if (vtxt && vtxt->isInSubtitleMode()) {
1063 BoxStack::getInstance()->remove(vtxt);
1067 case 0xFF: { //nosubtitles
1068 if (streamType == VDR::VIDEO){
1069 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1070 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1071 if (vtxt && vtxt->isInSubtitleMode()) {
1072 BoxStack::getInstance()->remove(vtxt);
1076 case 0x11: { //videotext
1077 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1079 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1083 BoxStack::getInstance()->update(vas);
1084 //BoxStack::getInstance()->update(&osd); //eveil error
1086 BoxStack::getInstance()->update(this, osd.getRegion());
1090 else if (m->message == Message::PLAYER_EVENT)
1092 switch(m->parameter)
1094 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1096 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1097 Command::getInstance()->connectionLost();
1101 case PlayerLiveTV::STREAM_END:
1103 // Message comes from playerlivetv through master mutex, so can do anything here
1108 case PlayerLiveTV::ASPECT43:
1111 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1113 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
1116 BoxStack::getInstance()->update(this, &wssRegion);
1120 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
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::ASPECT169:
1134 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1136 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
1139 BoxStack::getInstance()->update(this, &wssRegion);
1143 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1144 sAspectRatio.setVisible(true);
1146 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1149 BoxStack::getInstance()->update(this, osd.getRegion());
1154 case PlayerLiveTV::PREBUFFERING:
1156 preBuffering = m->tag;
1157 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1158 bufferBar.setPercent(preBuffering);
1160 if (osd.getVisible())
1162 bufferBar.setVisible(true);
1165 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1166 BoxStack::getInstance()->update(this, &r);
1168 if (preBuffering == 100)
1170 doAudioChannelSymbol();
1178 void VVideoLiveTV::doAudioChannelSymbol()
1181 Channel* currentChannel = (*chanList)[osdChannelIndex];
1183 bool multiAudio = false;
1184 if (Audio::getInstance()->supportsAc3()) {
1185 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
1187 if (currentChannel->numAPids > 1) multiAudio = true;
1191 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1192 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1193 sAudioChannels.setVisible(true);
1195 if (osd.getVisible())
1197 sAudioChannels.draw();
1199 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1203 BoxStack::getInstance()->update(this, &r);
1207 UINT VVideoLiveTV::upChannel(UINT index)
1209 if (index == (chanList->size() - 1)) // at the end
1210 return 0; // so go to start
1215 UINT VVideoLiveTV::downChannel(UINT index)
1217 if (index == 0) // at the start
1218 return chanList->size() - 1; // so go to end
1223 void VVideoLiveTV::toggleChopSides()
1225 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1227 if (videoMode == Video::NORMAL)
1229 videoMode = Video::LETTERBOX;
1230 video->setMode(Video::LETTERBOX);
1234 videoMode = Video::NORMAL;
1235 video->setMode(Video::NORMAL);
1239 void VVideoLiveTV::updatePosterBanner()
1241 OsdVector *osdv=dynamic_cast<OsdVector*>(Osd::getInstance());
1243 osdposterbanner.setVisible(false);
1246 Event* toShow = NULL;
1247 if (eventList && eventList->size()) {
1248 toShow = (*eventList)[0];
1249 Channel* currentChannel = (*chanList)[osdChannelIndex];
1250 toShow->loadinfos(currentChannel->number);
1257 bool posterscale=true;
1258 if (toShow->movieInfo) {
1259 poster=toShow->movieInfo->poster;
1261 if (toShow->seriesInfo) {
1262 if (toShow->seriesInfo->banners.size()) {
1263 poster=toShow->seriesInfo->banners[0];
1265 } else if (toShow->seriesInfo->seasonposter.height) {
1266 poster=toShow->seriesInfo->seasonposter;
1267 } else if (toShow->seriesInfo->posters.size()) {
1268 poster=toShow->seriesInfo->posters[0];
1271 if (poster.height) {
1272 osdposterbanner.setTVMedia(poster.info, posterscale ? WTVMedia::ZoomVertical : WTVMedia::ZoomHorizontal);
1273 osdposterbanner.setVisible(true);
1275 osdposterbanner.setVisible(false);
1278 osdposterbanner.setVisible(false);
1284 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm, const DisplayRegion& region)
1286 drawBitmap(posX, posY, bm,region);
1288 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1289 boxstack->update(this, &r);
1292 void VVideoLiveTV::clearOSD()
1294 rectangle(area, DrawStyle(0,0,0,0));
1295 boxstack->update(this, &area);
1298 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height, const DisplayRegion& region)
1301 r.x = posX+region.windowx; r.y = posY+region.windowy; r.w = width; r.h = height;
1302 //now convert to our display
1303 float scalex=720.f/((float) (region.framewidth+1));
1304 float scaley=576.f/((float) (region.frameheight+1));
1305 r.x=floor(scalex*((float)r.x));
1306 r.y=floor(scaley*((float)r.y));
1307 r.w=ceil(scalex*((float)r.w))+1.f;
1308 r.h=ceil(scaley*((float)r.h))+1.f;
1309 rectangle(r, DrawStyle(0,0,0,0));
1310 boxstack->update(this, &r);