2 Copyright 2007-2008 Chris Tallon
\r
4 This file is part of VOMP.
\r
6 VOMP is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 VOMP is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with VOMP; if not, write to the Free Software
\r
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
\r
21 #include "vvideolivetv.h"
\r
23 #include "vchannellist.h"
\r
26 #include "playerlive.h"
\r
27 #include "playerlivetv.h"
\r
28 #include "playerliveradio.h"
\r
29 #include "channel.h"
\r
30 #include "boxstack.h"
\r
33 #include "command.h"
\r
35 #include "wtextbox.h"
\r
37 #include "vaudioselector.h"
\r
44 #include "vteletextview.h"
\r
46 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
\r
48 vdr = VDR::getInstance();
\r
49 boxstack = BoxStack::getInstance();
\r
50 video = Video::getInstance();
\r
54 chanList = tchanList;
\r
55 vchannelList = tvchannelList;
\r
56 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
\r
58 currentChannelIndex = 0;
\r
59 previousChannelIndex = 0;
\r
60 osdChannelIndex = 0;
\r
66 // Convert channel number to index
\r
68 for(i = 0; i < chanList->size(); i++)
\r
70 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
\r
72 currentChannelIndex = i;
\r
73 osdChannelIndex = i;
\r
80 videoMode = video->getMode();
\r
82 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
\r
84 streamType = VDR::VIDEO;
\r
85 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
\r
89 streamType = VDR::RADIO;
\r
90 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
\r
94 setSize(video->getScreenWidth(), video->getScreenHeight());
\r
96 Colour transparent(0, 0, 0, 0);
\r
97 setBackgroundColour(transparent);
\r
100 char* optionWSS = vdr->configLoad("General", "WSS");
\r
103 if (strstr(optionWSS, "Yes")) dowss = true;
\r
104 delete[] optionWSS;
\r
106 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
\r
110 wss.setFormat(video->getFormat());
\r
116 wssRegion.w = video->getScreenWidth();
\r
120 // This variable is set to true if the user pressed OK to bring the OSD on screen
\r
121 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
\r
122 okTriggeredOSD = false;
\r
124 Colour osdBack = Colour(0, 0, 0, 128);
\r
126 osd.setBackgroundColour(osdBack);
\r
127 osd.setPosition(0, video->getScreenHeight() - 150);
\r
128 osd.setSize(video->getScreenWidth(), 150);
\r
129 osd.setVisible(false);
\r
132 clock.setBackgroundColour(osdBack);
\r
133 clock.setPosition(osd.getWidth() - 100, 4);
\r
134 clock.setSize(90, 30);
\r
137 osdChanNum.setBackgroundColour(osdBack);
\r
138 osdChanNum.setPosition(50, 4);
\r
139 osdChanNum.setSize((numberWidth*10) + 22, 30); // 10 px = width of number chars in font
\r
140 osd.add(&osdChanNum);
\r
142 osdChanName.setBackgroundColour(osdBack);
\r
143 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
\r
144 osdChanName.setSize(300, 30);
\r
145 osd.add(&osdChanName);
\r
147 boxRed.setBackgroundColour(Colour::RED);
\r
148 boxRed.setPosition(54, 104);
\r
149 boxRed.setSize(18, 16);
\r
152 boxGreen.setBackgroundColour(Colour::GREEN);
\r
153 boxGreen.setPosition(220, 104);
\r
154 boxGreen.setSize(18, 16);
\r
155 osd.add(&boxGreen);
\r
157 boxYellow.setBackgroundColour(Colour::YELLOW);
\r
158 boxYellow.setPosition(390, 104);
\r
159 boxYellow.setSize(18, 16);
\r
160 osd.add(&boxYellow);
\r
162 boxBlue.setBackgroundColour(Colour::BLUE);
\r
163 boxBlue.setPosition(560, 104);
\r
164 boxBlue.setSize(18, 16);
\r
165 osd.add(&boxBlue);
\r
167 textRed.setBackgroundColour(osdBack);
\r
168 textRed.setPosition(boxRed.getX2(), 98);
\r
169 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
\r
170 textRed.setText(tr("Summary"));
\r
171 osd.add(&textRed);
\r
173 if (streamType == VDR::VIDEO)
\r
175 textGreen.setBackgroundColour(osdBack);
\r
176 textGreen.setPosition(boxGreen.getX2(), 98);
\r
177 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
\r
178 textGreen.setText(tr("Audio"));
\r
179 osd.add(&textGreen);
\r
182 textYellow.setBackgroundColour(osdBack);
\r
183 textYellow.setPosition(boxYellow.getX2(), 98);
\r
184 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
\r
185 textYellow.setText(tr("Teletext"));
\r
186 osd.add(&textYellow);
\r
188 textBlue.setBackgroundColour(osdBack);
\r
189 textBlue.setPosition(boxBlue.getX2(), 98);
\r
190 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
\r
191 textBlue.setText(tr("EPG"));
\r
192 osd.add(&textBlue);
\r
194 sl.setBackgroundColour(osdBack);
\r
195 sl.setPosition(70, 36);
\r
196 sl.setSize(500, 58);
\r
201 summary.setBackgroundColour(osdBack);
\r
202 summary.setPosition(0, video->getScreenHeight() - 300);
\r
203 summary.setSize(video->getScreenWidth(), 150);
\r
204 summary.setVisible(false);
\r
207 textSummary.setBackgroundColour(osdBack);
\r
208 textSummary.setPosition(40, 10);
\r
209 textSummary.setSize(video->getScreenWidth() - 80, 130);
\r
210 textSummary.setParaMode(true);
\r
211 summary.add(&textSummary);
\r
213 summaryBlackLine.setBackgroundColour(Colour::BLACK);
\r
214 summaryBlackLine.setPosition(0, summary.getHeight() - 4);
\r
215 summaryBlackLine.setSize(summary.getWidth(), 4);
\r
216 summary.add(&summaryBlackLine);
\r
218 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
\r
219 sAspectRatio.nextColour = Colour::SELECTHIGHLIGHT;
\r
220 sAspectRatio.setVisible(false);
\r
221 osd.add(&sAspectRatio);
\r
223 bufferBar.setPosition(osd.getWidth() - 90, 70);
\r
224 bufferBar.setSize(40, 20);
\r
225 bufferBar.setVisible(true);
\r
226 osd.add(&bufferBar);
\r
228 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
\r
229 sAudioChannels.nextColour = Colour::SELECTHIGHLIGHT;
\r
230 sAudioChannels.setVisible(false);
\r
231 osd.add(&sAudioChannels);
\r
233 textUnavailable.setBackgroundColour(osdBack);
\r
234 textUnavailable.setPosition(60, 30);
\r
235 textUnavailable.setSize(osd.getWidth() - 120, 30);
\r
236 textUnavailable.setText(tr("Channel Unavailable"));
\r
237 textUnavailable.setVisible(false);
\r
238 add(&textUnavailable);
\r
241 Region r1 = summary.getRegionR();
\r
242 Region r2 = osd.getRegionR();
\r
243 osdSummaryRegion = r1 + r2;
\r
246 void VVideoLiveTV::preDelete()
\r
248 if (playing) stop();
\r
251 VVideoLiveTV::~VVideoLiveTV()
\r
254 video->setDefaultAspect();
\r
258 void VVideoLiveTV::delData()
\r
262 int eventListSize = eventList->size();
\r
263 for(int i = 0; i < eventListSize; i++)
\r
265 delete (*eventList)[i];
\r
267 eventList->clear();
\r
274 int VVideoLiveTV::handleCommand(int command)
\r
280 if (osd.getVisible() && !textUnavailable.getVisible())
\r
285 // else drop through to stop
\r
290 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
\r
294 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
\r
307 doLeftRight(false);
\r
310 case Remote::RIGHT:
\r
315 // Continue new remote only...
\r
316 case Remote::CHANNELUP:
\r
321 case Remote::CHANNELDOWN:
\r
323 doChanUpDown(DOWN);
\r
327 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
\r
329 // DF_LEFT and DF_RIGHT never get here because they are stolen
\r
330 // by command as vol- and vol+
\r
332 // Old remote. Decide what to do based on whether
\r
333 // OK was pressed - osd shown manually, use up/down for epg nav
\r
334 // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
\r
336 case Remote::DF_UP:
\r
338 // Old remote, decide what to do based on okTriggeredOSD
\r
339 if (okTriggeredOSD) doUpDown(false);
\r
340 else doChanUpDown(UP);
\r
343 case Remote::DF_DOWN:
\r
345 // Old remote, decide what to do based on okTriggeredOSD
\r
346 if (okTriggeredOSD) doUpDown(true);
\r
347 else doChanUpDown(DOWN);
\r
351 // END NEW/OLD REMOTE STUFF
\r
353 case Remote::PREVCHANNEL:
\r
355 channelChange(PREVIOUS, 0);
\r
356 osdChannelIndex = currentChannelIndex;
\r
381 case Remote::THREE:
\r
385 case Remote::SEVEN:
\r
386 case Remote::EIGHT:
\r
389 // key in channel number
\r
394 case Remote::GREEN:
\r
396 if (streamType == VDR::VIDEO) doAudioSelector();
\r
399 case Remote::YELLOW:
\r
401 if (streamType ==VDR::VIDEO) doTeletext(); //TODO: Add a selector for subtitles or teletext
\r
404 case Remote::GUIDE:
\r
410 case Remote::RECORD:
\r
411 if (streamType == VDR::VIDEO)
\r
412 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
\r
419 void VVideoLiveTV::go()
\r
423 boxstack->update(this);
\r
428 player->go(currentChannelIndex);
\r
431 void VVideoLiveTV::stop()
\r
433 Timers::getInstance()->cancelTimer(this, 1);
\r
434 Timers::getInstance()->cancelTimer(this, 2);
\r
439 void VVideoLiveTV::doLeftRight(bool right)
\r
441 if (osd.getVisible())
\r
443 if (right) osdChannelIndex = upChannel(osdChannelIndex);
\r
444 else osdChannelIndex = downChannel(osdChannelIndex);
\r
448 osdChannelIndex = currentChannelIndex;
\r
453 void VVideoLiveTV::doUpDown(bool down)
\r
455 if (osd.getVisible())
\r
457 if (down) sl.down();
\r
469 void VVideoLiveTV::doChanUpDown(int which)
\r
471 channelChange(OFFSET, which);
\r
472 osdChannelIndex = currentChannelIndex;
\r
476 void VVideoLiveTV::doOK()
\r
478 if (osd.getVisible())
\r
482 UINT newChannel = 0;
\r
483 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
\r
485 channelChange(NUMBER, newChannel);
\r
486 osdChannelIndex = currentChannelIndex;
\r
489 else if (osdChannelIndex == currentChannelIndex)
\r
495 channelChange(INDEX, osdChannelIndex);
\r
501 osdChannelIndex = currentChannelIndex;
\r
503 okTriggeredOSD = true;
\r
507 void VVideoLiveTV::doSummary()
\r
509 if (summary.getVisible())
\r
511 summary.setVisible(false);
\r
513 boxstack->update(this, summary.getRegion());
\r
514 Timers::getInstance()->setTimerD(this, 1, 8); // Restart a timer to get rid of osd
\r
518 summary.setVisible(true);
\r
520 if (osd.getVisible())
\r
522 Timers::getInstance()->cancelTimer(this, 1);
\r
531 void VVideoLiveTV::doKey(int command)
\r
533 if (!osd.getVisible()) // First key. prep the data
\r
540 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
\r
541 keyingInput[0] = command;
\r
544 char* keyingString = new char[numberWidth + 1];
\r
545 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
\r
546 keyingString[numberWidth] = '\0';
\r
548 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
\r
550 if (keying == numberWidth)
\r
552 UINT newChannel = 0;
\r
553 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
\r
555 channelChange(NUMBER, newChannel);
\r
556 osdChannelIndex = currentChannelIndex;
\r
557 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
\r
558 displayOSD(true); // this will put one back if required
\r
562 osdChanNum.setText(keyingString);
\r
564 if (!osd.getVisible())
\r
566 osd.setVisible(true);
\r
573 boxstack->update(this, osd.getRegion());
\r
574 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
\r
576 delete[] keyingString;
\r
579 void VVideoLiveTV::doTeletext(bool subtitlemode)
\r
581 if (streamType !=VDR::VIDEO) return;
\r
588 // and reset the display - this is a copy from setNowNextData
\r
589 char formatChanNum[20];
\r
590 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
\r
591 osdChanNum.setText(formatChanNum);
\r
592 osdChanName.setText((*chanList)[osdChannelIndex]->name);
\r
594 if (osd.getVisible()) clearScreen();
\r
595 // Draw the teletxt
\r
596 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
\r
598 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this);
\r
599 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
\r
602 vtxv->setSubtitleMode(subtitlemode);
\r
607 BoxStack::getInstance()->add(vtxv);
\r
609 BoxStack::getInstance()->update(this);
\r
610 BoxStack::getInstance()->update(vtxv);
\r
613 void VVideoLiveTV::doAudioSelector()
\r
615 // If the osd is already visisble there might be a timer for it
\r
616 Timers::getInstance()->cancelTimer(this, 1);
\r
617 //This causes a deadlock with the timertrhread itself is locked
\r
624 // and reset the display - this is a copy from setNowNextData
\r
625 char formatChanNum[20];
\r
626 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
\r
627 osdChanNum.setText(formatChanNum);
\r
628 osdChanName.setText((*chanList)[osdChannelIndex]->name);
\r
630 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
\r
631 int subtitleType=0x10;
\r
632 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
\r
633 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
\r
634 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
\r
636 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
\r
640 subtitleType=0xFF; //turnedOff
\r
645 // Draw the selector
\r
646 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
\r
647 subtitleType,subtitleChannel,NULL);
\r
648 Colour osdBack = Colour(0, 0, 0, 128);
\r
649 vas->setBackgroundColour(osdBack);
\r
650 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
\r
653 // make vas != null and displayOSD will not set a timer or do any boxstack update
\r
654 summary.setVisible(false);
\r
655 if (osd.getVisible()) displayOSD(false);
\r
656 else displayOSD(true);
\r
659 BoxStack::getInstance()->add(vas);
\r
660 BoxStack::getInstance()->update(this);
\r
661 BoxStack::getInstance()->update(vas);
\r
664 void VVideoLiveTV::doEPG()
\r
666 if (osd.getVisible()) clearScreen();
\r
668 video->setMode(Video::QUARTER);
\r
669 video->setPosition(170, 5); //TODO need to deal with 4:3 switching
\r
671 VEpg* vepg = new VEpg(this, currentChannelIndex, streamType);
\r
673 boxstack->add(vepg);
\r
674 boxstack->update(vepg);
\r
677 void VVideoLiveTV::setNowNextData()
\r
681 Channel* currentChannel = (*chanList)[osdChannelIndex];
\r
683 char formatChanNum[20];
\r
684 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
\r
685 osdChanNum.setText(formatChanNum);
\r
686 osdChanName.setText(currentChannel->name);
\r
688 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
\r
692 sl.addOption(tr("No channel data available"), 0, 1);
\r
696 sort(eventList->begin(), eventList->end(), EventSorter());
\r
698 char tempString[300];
\r
699 char tempString2[300];
\r
702 int eventListSize = eventList->size();
\r
703 for(int i = 0; i < eventListSize; i++)
\r
705 event = (*eventList)[i];
\r
707 //btime = localtime((time_t*)&event->time);
\r
708 time_t etime = event->time;
\r
709 btime = localtime(&etime);
\r
711 strftime(tempString2, 299, "%0H:%0M ", btime);
\r
713 strftime(tempString2, 299, "%H:%M ", btime);
\r
715 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
\r
717 sl.addOption(tempString, (ULONG)event, (i==0));
\r
722 void VVideoLiveTV::setSummaryData()
\r
724 // If osd is not being displayed, sl will be filled with now, current channel
\r
725 // If the display was already on, sl will have programme to show summary for, not necessarily current channel and now
\r
726 Event* selectedEvent = (Event*)sl.getCurrentOptionData();
\r
728 if (!selectedEvent)
\r
730 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "No summary");
\r
731 textSummary.setText(tr("No summary available"));
\r
735 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Summary: %s", selectedEvent->description);
\r
736 textSummary.setText(selectedEvent->description);
\r
740 void VVideoLiveTV::displayOSD(bool newNowNextData)
\r
742 osd.setVisible(true);
\r
743 if (newNowNextData)
\r
750 if (summary.getVisible())
\r
754 boxstack->update(this, &osdSummaryRegion);
\r
758 boxstack->update(this, osd.getRegion());
\r
761 bool setTimer = true;
\r
762 if (vas) setTimer = false;
\r
763 if (summary.getVisible()) setTimer = false;
\r
764 if (textUnavailable.getVisible()) setTimer = false;
\r
766 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
\r
769 void VVideoLiveTV::clearScreen()
\r
771 if (!summary.getVisible()) Timers::getInstance()->cancelTimer(this, 1);
\r
773 textUnavailable.setVisible(false);
\r
774 osd.setVisible(false);
\r
775 summary.setVisible(false);
\r
777 okTriggeredOSD = false;
\r
780 boxstack->update(this);
\r
783 void VVideoLiveTV::showUnavailable()
\r
785 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
\r
786 textUnavailable.setVisible(true);
\r
787 textUnavailable.draw();
\r
789 if (!osd.getVisible()) displayOSD(true);
\r
791 boxstack->update(this, textUnavailable.getRegion());
\r
794 void VVideoLiveTV::setClock()
\r
796 char timeString[20];
\r
799 struct tm* tms = localtime(&t);
\r
800 strftime(timeString, 19, "%H:%M", tms);
\r
801 clock.setText(timeString);
\r
803 time_t dt = 60 - (t % 60); // seconds to the next minute
\r
804 if (dt == 0) dt = 60; // advance a whole minute if necessary
\r
805 dt += t; // get a time_t value for it rather than using duration
\r
806 // (so it will occur at the actual second and not second and a half)
\r
808 Timers::getInstance()->setTimerT(this, 2, dt);
\r
811 void VVideoLiveTV::timercall(int ref)
\r
817 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
\r
818 UINT newChannel = 0;
\r
819 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
\r
821 Message* m = new Message();
\r
822 m->message = Message::CHANNEL_CHANGE;
\r
824 m->parameter = newChannel;
\r
825 m->tag = 1; // signal to call displayOSD();
\r
826 Command::getInstance()->postMessageFromOuterSpace(m);
\r
827 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
\r
831 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
\r
832 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
\r
833 if (preBuffering < 100)
\r
835 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
\r
836 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
\r
839 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
\r
840 osd.setVisible(false);
\r
841 okTriggeredOSD = false;
\r
842 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
\r
844 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
\r
845 boxstack->update(this, osd.getRegion());
\r
847 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
\r
848 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
\r
853 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
\r
855 if (osd.getVisible())
\r
858 boxstack->update(this, osd.getRegion());
\r
860 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
\r
864 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
\r
866 UINT newChannel = 0;
\r
867 if (streamType ==VDR::VIDEO) {
\r
868 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
\r
870 BoxStack::getInstance()->remove(vtxt);
\r
874 if (changeType == INDEX)
\r
876 newChannel = newData;
\r
878 else if (changeType == NUMBER)
\r
881 for(i = 0; i < chanList->size(); i++)
\r
883 if ((*chanList)[i]->number == (UINT)newData)
\r
890 if (i == chanList->size())
\r
896 else if (changeType == OFFSET)
\r
898 if (newData == UP) newChannel = upChannel(currentChannelIndex);
\r
899 else newChannel = downChannel(currentChannelIndex);
\r
901 else if (changeType == PREVIOUS)
\r
903 newChannel = previousChannelIndex;
\r
907 return false; // bad input
\r
910 if (newChannel == currentChannelIndex) return true;
\r
912 previousChannelIndex = currentChannelIndex;
\r
913 currentChannelIndex = newChannel;
\r
917 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
\r
918 player->setChannel(currentChannelIndex);
\r
919 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
\r
921 // Blank out the symbols
\r
922 sAspectRatio.setVisible(false);
\r
923 bufferBar.setPercent(0);
\r
924 sAudioChannels.setVisible(false);
\r
926 // Remove other stuff
\r
927 if (textUnavailable.getVisible())
\r
929 textUnavailable.setVisible(false);
\r
934 BoxStack::getInstance()->update(this);
\r
939 void VVideoLiveTV::processMessage(Message* m)
\r
941 if (m->message == Message::MOUSE_LBDOWN)
\r
943 //check if press is outside this view! then simulate cancel
\r
944 int x=(m->parameter>>16)-osd.getScreenX();
\r
945 int y=(m->parameter&0xFFFF)-osd.getScreenY();
\r
946 if (osd.getVisible()) {
\r
948 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
\r
949 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y )) {
\r
950 BoxStack::getInstance()->handleCommand(Remote::RED);
\r
951 } else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
\r
952 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y)){
\r
953 BoxStack::getInstance()->handleCommand(Remote::GREEN);
\r
954 } else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
\r
955 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
\r
956 BoxStack::getInstance()->handleCommand(Remote::YELLOW);
\r
957 } else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
\r
958 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y )){
\r
959 BoxStack::getInstance()->handleCommand(Remote::BLUE);
\r
961 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
\r
965 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
\r
968 else if (m->message == Message::CHANNEL_CHANGE)
\r
970 channelChange(NUMBER, m->parameter);
\r
971 osdChannelIndex = currentChannelIndex;
\r
972 if (m->tag == 1) displayOSD(true);
\r
974 else if (m->message == Message::EPG_CLOSE)
\r
976 video->setMode(videoMode);
\r
978 else if (m->message == Message::CHILD_CLOSE)
\r
980 if (m->from == vas)
\r
986 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
\r
988 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %i", m->parameter);
\r
989 player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16);
\r
991 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
\r
993 if (streamType !=VDR::VIDEO) return;
\r
994 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %i", m->parameter);
\r
995 int type=((m->parameter & 0xFF0000)>>16);
\r
997 case 0x10: { //dvbsubtitle
\r
998 if (streamType == VDR::VIDEO){
\r
999 player->setSubtitleChannel((m->parameter & 0xFFFF));
\r
1000 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
\r
1001 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
\r
1002 if (vtxt && vtxt->isInSubtitleMode()) {
\r
1003 BoxStack::getInstance()->remove(vtxt);
\r
1007 case 0xFF: { //nosubtitles
\r
1008 if (streamType == VDR::VIDEO){
\r
1009 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
\r
1010 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
\r
1011 if (vtxt && vtxt->isInSubtitleMode()) {
\r
1012 BoxStack::getInstance()->remove(vtxt);
\r
1016 case 0x11: { //videotext
\r
1017 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
\r
1019 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
\r
1023 BoxStack::getInstance()->update(vas);
\r
1024 //BoxStack::getInstance()->update(&osd); //eveil error
\r
1026 BoxStack::getInstance()->update(this, osd.getRegion());
\r
1030 else if (m->message == Message::PLAYER_EVENT)
\r
1032 switch(m->parameter)
\r
1034 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
\r
1036 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
\r
1037 Command::getInstance()->connectionLost();
\r
1041 case PlayerLiveTV::STREAM_END:
\r
1043 // Message comes from playerlivetv through master mutex, so can do anything here
\r
1044 showUnavailable();
\r
1048 case PlayerLiveTV::ASPECT43:
\r
1050 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
\r
1052 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
\r
1053 wss.setWide(false);
\r
1055 BoxStack::getInstance()->update(this, &wssRegion);
\r
1058 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
\r
1059 sAspectRatio.setVisible(true);
\r
1061 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
\r
1064 BoxStack::getInstance()->update(this, osd.getRegion());
\r
1069 case PlayerLiveTV::ASPECT169:
\r
1071 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
\r
1073 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
\r
1074 wss.setWide(true);
\r
1076 BoxStack::getInstance()->update(this, &wssRegion);
\r
1079 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
\r
1080 sAspectRatio.setVisible(true);
\r
1082 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
\r
1085 BoxStack::getInstance()->update(this, osd.getRegion());
\r
1090 case PlayerLiveTV::PREBUFFERING:
\r
1092 preBuffering = m->tag;
\r
1093 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
\r
1094 bufferBar.setPercent(preBuffering);
\r
1096 if (osd.getVisible())
\r
1098 bufferBar.setVisible(true);
\r
1101 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
\r
1102 BoxStack::getInstance()->update(this, &r);
\r
1104 if (preBuffering == 100)
\r
1106 doAudioChannelSymbol();
\r
1114 void VVideoLiveTV::doAudioChannelSymbol()
\r
1116 // get the doobery
\r
1117 Channel* currentChannel = (*chanList)[osdChannelIndex];
\r
1119 bool multiAudio = false;
\r
1120 if (Audio::getInstance()->supportsAc3()) {
\r
1121 if ((currentChannel->numDPids+currentChannel->numAPids) > 1) multiAudio = true;
\r
1123 if (currentChannel->numAPids > 1) multiAudio = true;
\r
1125 // draw the doobery
\r
1127 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
\r
1128 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
\r
1129 sAudioChannels.setVisible(true);
\r
1131 if (osd.getVisible())
\r
1133 sAudioChannels.draw();
\r
1135 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
\r
1136 // Fix this n'all.
\r
1139 BoxStack::getInstance()->update(this, &r);
\r
1143 UINT VVideoLiveTV::upChannel(UINT index)
\r
1145 if (index == (chanList->size() - 1)) // at the end
\r
1146 return 0; // so go to start
\r
1151 UINT VVideoLiveTV::downChannel(UINT index)
\r
1153 if (index == 0) // at the start
\r
1154 return chanList->size() - 1; // so go to end
\r
1159 void VVideoLiveTV::toggleChopSides()
\r
1161 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
\r
1163 if (videoMode == Video::NORMAL)
\r
1165 videoMode = Video::LETTERBOX;
\r
1166 video->setMode(Video::LETTERBOX);
\r
1170 videoMode = Video::NORMAL;
\r
1171 video->setMode(Video::NORMAL);
\r
1175 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm)
\r
1177 drawBitmap(posX, posY, bm);
\r
1179 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
\r
1180 boxstack->update(this, &r);
\r
1183 void VVideoLiveTV::clearOSD()
\r
1185 rectangle(area, Colour(0,0,0,0));
\r
1186 boxstack->update(this, &area);
\r
1189 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height)
\r
1192 r.x = posX; r.y = posY; r.w = width; r.h = height;
\r
1193 rectangle(r, Colour(0,0,0,0));
\r
1194 boxstack->update(this, &r);
\r