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"
25 #include "playerlive.h"
26 #include "playerlivetv.h"
27 #include "playerliveradio.h"
36 #include "vaudioselector.h"
43 #include "vteletextview.h"
45 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
47 vdr = VDR::getInstance();
48 boxstack = BoxStack::getInstance();
49 video = Video::getInstance();
54 vchannelList = tvchannelList;
55 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
57 currentChannelIndex = 0;
58 previousChannelIndex = 0;
65 // Convert channel number to index
67 for(i = 0; i < chanList->size(); i++)
69 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
71 currentChannelIndex = i;
79 videoMode = video->getMode();
81 if ((*chanList)[currentChannelIndex]->type == VDR::VIDEO)
83 streamType = VDR::VIDEO;
84 player = new PlayerLiveTV(Command::getInstance(), this, this, chanList);
88 streamType = VDR::RADIO;
89 player = new PlayerLiveRadio(Command::getInstance(), this, chanList);
93 setSize(video->getScreenWidth(), video->getScreenHeight());
95 Colour transparent(0, 0, 0, 0);
96 setBackgroundColour(transparent);
99 char* optionWSS = vdr->configLoad("General", "WSS");
102 if (strstr(optionWSS, "Yes")) dowss = true;
105 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
109 wss.setFormat(video->getFormat());
115 wssRegion.w = video->getScreenWidth();
119 // This variable is set to true if the user pressed OK to bring the OSD on screen
120 // This is only used on old remotes to stop up/down buttons being used for osd-epg scrolling
121 okTriggeredOSD = false;
123 Colour osdBack = Colour(0, 0, 0, 128);
125 osd.setBackgroundColour(osdBack);
126 osd.setPosition(0, video->getScreenHeight() - 150);
127 osd.setSize(video->getScreenWidth(), 150);
128 osd.setVisible(false);
131 clock.setBackgroundColour(osdBack);
132 clock.setPosition(osd.getWidth() - 100, 4);
133 clock.setSize(90, 30);
136 osdChanNum.setBackgroundColour(osdBack);
137 osdChanNum.setPosition(50, 4);
138 osdChanNum.setSize((numberWidth*10) + 22, 30); // 10 px = width of number chars in font
139 osd.add(&osdChanNum);
141 osdChanName.setBackgroundColour(osdBack);
142 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
143 osdChanName.setSize(300, 30);
144 osd.add(&osdChanName);
146 boxRed.setBackgroundColour(Colour::RED);
147 boxRed.setPosition(54, 104);
148 boxRed.setSize(18, 16);
151 boxGreen.setBackgroundColour(Colour::GREEN);
152 boxGreen.setPosition(220, 104);
153 boxGreen.setSize(18, 16);
156 boxYellow.setBackgroundColour(Colour::YELLOW);
157 boxYellow.setPosition(390, 104);
158 boxYellow.setSize(18, 16);
161 boxBlue.setBackgroundColour(Colour::BLUE);
162 boxBlue.setPosition(560, 104);
163 boxBlue.setSize(18, 16);
166 textRed.setBackgroundColour(osdBack);
167 textRed.setPosition(boxRed.getX2(), 98);
168 textRed.setSize(boxGreen.getX() - boxRed.getX2(), 30);
169 textRed.setText(tr("Summary"));
172 if (streamType == VDR::VIDEO)
174 textGreen.setBackgroundColour(osdBack);
175 textGreen.setPosition(boxGreen.getX2(), 98);
176 textGreen.setSize(boxYellow.getX() - boxGreen.getX2(), 30);
177 textGreen.setText(tr("Audio"));
181 textYellow.setBackgroundColour(osdBack);
182 textYellow.setPosition(boxYellow.getX2(), 98);
183 textYellow.setSize(boxBlue.getX() - boxYellow.getX2(), 30);
184 textYellow.setText("Teletext");
185 osd.add(&textYellow);
187 textBlue.setBackgroundColour(osdBack);
188 textBlue.setPosition(boxBlue.getX2(), 98);
189 textBlue.setSize(osd.getX2() - boxBlue.getX2(), 30);
190 textBlue.setText(tr("EPG"));
193 sl.setBackgroundColour(osdBack);
194 sl.setPosition(70, 36);
200 summary.setBackgroundColour(osdBack);
201 summary.setPosition(0, video->getScreenHeight() - 300);
202 summary.setSize(video->getScreenWidth(), 150);
203 summary.setVisible(false);
206 textSummary.setBackgroundColour(osdBack);
207 textSummary.setPosition(40, 10);
208 textSummary.setSize(video->getScreenWidth() - 80, 130);
209 textSummary.setParaMode(true);
210 summary.add(&textSummary);
212 summaryBlackLine.setBackgroundColour(Colour::BLACK);
213 summaryBlackLine.setPosition(0, summary.getHeight() - 4);
214 summaryBlackLine.setSize(summary.getWidth(), 4);
215 summary.add(&summaryBlackLine);
217 sAspectRatio.setPosition(osd.getWidth() - 90, 40);
218 sAspectRatio.nextColour = Colour::SELECTHIGHLIGHT;
219 sAspectRatio.setVisible(false);
220 osd.add(&sAspectRatio);
222 bufferBar.setPosition(osd.getWidth() - 90, 70);
223 bufferBar.setSize(40, 20);
224 bufferBar.setVisible(true);
227 sAudioChannels.setPosition(osd.getWidth() - 130, 40);
228 sAudioChannels.nextColour = Colour::SELECTHIGHLIGHT;
229 sAudioChannels.setVisible(false);
230 osd.add(&sAudioChannels);
232 textUnavailable.setBackgroundColour(osdBack);
233 textUnavailable.setPosition(60, 30);
234 textUnavailable.setSize(osd.getWidth() - 120, 30);
235 textUnavailable.setText(tr("Channel Unavailable"));
236 textUnavailable.setVisible(false);
237 add(&textUnavailable);
240 Region r1 = summary.getRegionR();
241 Region r2 = osd.getRegionR();
242 osdSummaryRegion = r1 + r2;
245 void VVideoLiveTV::preDelete()
250 VVideoLiveTV::~VVideoLiveTV()
253 video->setDefaultAspect();
257 void VVideoLiveTV::delData()
261 int eventListSize = eventList->size();
262 for(int i = 0; i < eventListSize; i++)
264 delete (*eventList)[i];
273 int VVideoLiveTV::handleCommand(int command)
279 if (osd.getVisible() && !textUnavailable.getVisible())
284 // else drop through to stop
289 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
293 // NEW REMOTE ONLY - navigate EPG, bring it onscreen if it's not there
314 // Continue new remote only...
315 case Remote::CHANNELUP:
320 case Remote::CHANNELDOWN:
326 // END NEW REMOTE ONLY, START OLD REMOTE ONLY
328 // DF_LEFT and DF_RIGHT never get here because they are stolen
329 // by command as vol- and vol+
331 // Old remote. Decide what to do based on whether
332 // OK was pressed - osd shown manually, use up/down for epg nav
333 // UP/DOWN was pressed to change channel, osd was shown auto, use up/down for ch+/ch-
337 // Old remote, decide what to do based on okTriggeredOSD
338 if (okTriggeredOSD) doUpDown(false);
339 else doChanUpDown(UP);
342 case Remote::DF_DOWN:
344 // Old remote, decide what to do based on okTriggeredOSD
345 if (okTriggeredOSD) doUpDown(true);
346 else doChanUpDown(DOWN);
350 // END NEW/OLD REMOTE STUFF
352 case Remote::PREVCHANNEL:
354 channelChange(PREVIOUS, 0);
355 osdChannelIndex = currentChannelIndex;
388 // key in channel number
395 if (streamType == VDR::VIDEO) doAudioSelector();
400 if (streamType ==VDR::VIDEO) doTeletext(); //TODO: Add a selector for subtitles or teletext
410 if (streamType = VDR::VIDEO)
411 (static_cast<PlayerLiveTV*>(player))->toggleSubtitles();
418 void VVideoLiveTV::go()
422 boxstack->update(this);
427 player->go(currentChannelIndex);
430 void VVideoLiveTV::stop()
432 Timers::getInstance()->cancelTimer(this, 1);
433 Timers::getInstance()->cancelTimer(this, 2);
438 void VVideoLiveTV::doLeftRight(bool right)
440 if (osd.getVisible())
442 if (right) osdChannelIndex = upChannel(osdChannelIndex);
443 else osdChannelIndex = downChannel(osdChannelIndex);
447 osdChannelIndex = currentChannelIndex;
452 void VVideoLiveTV::doUpDown(bool down)
454 if (osd.getVisible())
468 void VVideoLiveTV::doChanUpDown(int which)
470 channelChange(OFFSET, which);
471 osdChannelIndex = currentChannelIndex;
475 void VVideoLiveTV::doOK()
477 if (osd.getVisible())
482 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
484 channelChange(NUMBER, newChannel);
485 osdChannelIndex = currentChannelIndex;
488 else if (osdChannelIndex == currentChannelIndex)
494 channelChange(INDEX, osdChannelIndex);
500 osdChannelIndex = currentChannelIndex;
502 okTriggeredOSD = true;
506 void VVideoLiveTV::doSummary()
508 if (summary.getVisible())
510 summary.setVisible(false);
512 boxstack->update(this, summary.getRegion());
513 Timers::getInstance()->setTimerD(this, 1, 8); // Restart a timer to get rid of osd
517 summary.setVisible(true);
519 if (osd.getVisible())
521 Timers::getInstance()->cancelTimer(this, 1);
530 void VVideoLiveTV::doKey(int command)
532 if (!osd.getVisible()) // First key. prep the data
539 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
540 keyingInput[0] = command;
543 char* keyingString = new char[numberWidth + 1];
544 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
545 keyingString[numberWidth] = '\0';
547 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
549 if (keying == numberWidth)
552 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
554 channelChange(NUMBER, newChannel);
555 osdChannelIndex = currentChannelIndex;
556 Timers::getInstance()->cancelTimer(this, 1); // cancel the timer to react to keying input,
557 displayOSD(true); // this will put one back if required
561 osdChanNum.setText(keyingString);
563 if (!osd.getVisible())
565 osd.setVisible(true);
572 boxstack->update(this, osd.getRegion());
573 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
575 delete[] keyingString;
578 void VVideoLiveTV::doTeletext(bool subtitlemode)
580 if (streamType !=VDR::VIDEO) return;
587 // and reset the display - this is a copy from setNowNextData
588 char formatChanNum[20];
589 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
590 osdChanNum.setText(formatChanNum);
591 osdChanName.setText((*chanList)[osdChannelIndex]->name);
593 if (osd.getVisible()) clearScreen();
595 VTeletextView *vtxv=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
597 vtxv= new VTeletextView(((PlayerLiveTV*)player)->getTeletextDecoder(),this);
598 ((PlayerLiveTV*)player)->getTeletextDecoder()->registerTeletextView(vtxv);
601 vtxv->setSubtitleMode(subtitlemode);
606 BoxStack::getInstance()->add(vtxv);
608 BoxStack::getInstance()->update(this);
609 BoxStack::getInstance()->update(vtxv);
612 void VVideoLiveTV::doAudioSelector()
614 // If the osd is already visisble there might be a timer for it
615 Timers::getInstance()->cancelTimer(this, 1);
616 //This causes a deadlock with the timertrhread itself is locked
623 // and reset the display - this is a copy from setNowNextData
624 char formatChanNum[20];
625 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, (*chanList)[osdChannelIndex]->number);
626 osdChanNum.setText(formatChanNum);
627 osdChanName.setText((*chanList)[osdChannelIndex]->name);
629 int subtitleChannel=((PlayerLiveTV*)player)->getCurrentSubtitleChannel();
630 int subtitleType=0x10;
631 if (!(static_cast<PlayerLiveTV*>(player))->isSubtitlesOn()) {
632 if (((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView() &&
633 ((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView()->isInSubtitleMode()
635 subtitleChannel=((PlayerLiveTV*)player)->getTeletextDecoder()->getPage();
639 subtitleType=0xFF; //turnedOff
645 vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((PlayerLiveTV*)player)->getCurrentAudioChannel(),
646 subtitleType,subtitleChannel,NULL);
647 Colour osdBack = Colour(0, 0, 0, 128);
648 vas->setBackgroundColour(osdBack);
649 vas->setPosition(0, osd.getScreenY() - vas->getHeight());
652 // make vas != null and displayOSD will not set a timer or do any boxstack update
653 summary.setVisible(false);
654 if (osd.getVisible()) displayOSD(false);
655 else displayOSD(true);
658 BoxStack::getInstance()->add(vas);
659 BoxStack::getInstance()->update(this);
660 BoxStack::getInstance()->update(vas);
663 void VVideoLiveTV::doEPG()
665 if (osd.getVisible()) clearScreen();
667 video->setMode(Video::QUARTER);
668 video->setPosition(170, 5); //TODO need to deal with 4:3 switching
670 VEpg* vepg = new VEpg(this, currentChannelIndex, streamType);
673 boxstack->update(vepg);
676 void VVideoLiveTV::setNowNextData()
680 Channel* currentChannel = (*chanList)[osdChannelIndex];
682 char formatChanNum[20];
683 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
684 osdChanNum.setText(formatChanNum);
685 osdChanName.setText(currentChannel->name);
687 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
691 sl.addOption(tr("No channel data available"), 0, 1);
695 sort(eventList->begin(), eventList->end(), EventSorter());
697 char tempString[300];
698 char tempString2[300];
701 int eventListSize = eventList->size();
702 for(int i = 0; i < eventListSize; i++)
704 event = (*eventList)[i];
706 //btime = localtime((time_t*)&event->time);
707 time_t etime = event->time;
708 btime = localtime(&etime);
710 strftime(tempString2, 299, "%0H:%0M ", btime);
712 strftime(tempString2, 299, "%H:%M ", btime);
714 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
716 sl.addOption(tempString, (ULONG)event, (i==0));
721 void VVideoLiveTV::setSummaryData()
723 // If osd is not being displayed, sl will be filled with now, current channel
724 // If the display was already on, sl will have programme to show summary for, not necessarily current channel and now
725 Event* selectedEvent = (Event*)sl.getCurrentOptionData();
729 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "No summary");
730 textSummary.setText(tr("No summary available"));
734 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Summary: %s", selectedEvent->description);
735 textSummary.setText(selectedEvent->description);
739 void VVideoLiveTV::displayOSD(bool newNowNextData)
741 osd.setVisible(true);
749 if (summary.getVisible())
753 boxstack->update(this, &osdSummaryRegion);
757 boxstack->update(this, osd.getRegion());
760 bool setTimer = true;
761 if (vas) setTimer = false;
762 if (summary.getVisible()) setTimer = false;
763 if (textUnavailable.getVisible()) setTimer = false;
765 if (setTimer) Timers::getInstance()->setTimerD(this, 1, 4);
768 void VVideoLiveTV::clearScreen()
770 if (!summary.getVisible()) Timers::getInstance()->cancelTimer(this, 1);
772 textUnavailable.setVisible(false);
773 osd.setVisible(false);
774 summary.setVisible(false);
776 okTriggeredOSD = false;
779 boxstack->update(this);
782 void VVideoLiveTV::showUnavailable()
784 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Show unavailable called");
785 textUnavailable.setVisible(true);
786 textUnavailable.draw();
788 if (!osd.getVisible()) displayOSD(true);
790 boxstack->update(this, textUnavailable.getRegion());
793 void VVideoLiveTV::setClock()
798 struct tm* tms = localtime(&t);
799 strftime(timeString, 19, "%H:%M", tms);
800 clock.setText(timeString);
802 time_t dt = 60 - (t % 60); // seconds to the next minute
803 if (dt == 0) dt = 60; // advance a whole minute if necessary
804 dt += t; // get a time_t value for it rather than using duration
805 // (so it will occur at the actual second and not second and a half)
807 Timers::getInstance()->setTimerT(this, 2, dt);
810 void VVideoLiveTV::timercall(int ref)
816 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key start.");
818 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10., i);
820 Message* m = new Message();
821 m->message = Message::CHANNEL_CHANGE;
823 m->parameter = newChannel;
824 m->tag = 1; // signal to call displayOSD();
825 Command::getInstance()->postMessageFromOuterSpace(m);
826 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 key end.");
830 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 not key start.");
831 // We have received a timer, we are not keying. If still prebuffering, don't remove the bar
832 if (preBuffering < 100)
834 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Still prebuffering, not removing osd...");
835 Timers::getInstance()->setTimerD(this, 1, 2); // reset timer for another 2s
838 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 1.");
839 osd.setVisible(false);
840 okTriggeredOSD = false;
841 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 2.");
843 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 4.");
844 boxstack->update(this, osd.getRegion());
846 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey 3.");
847 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 1 notkey end.");
852 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 start.");
854 if (osd.getVisible())
857 boxstack->update(this, osd.getRegion());
859 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Timer Call 2 end.");
863 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
866 if (streamType ==VDR::VIDEO) {
867 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
869 BoxStack::getInstance()->remove(vtxt);
873 if (changeType == INDEX)
875 newChannel = newData;
877 else if (changeType == NUMBER)
880 for(i = 0; i < chanList->size(); i++)
882 if ((*chanList)[i]->number == (UINT)newData)
889 if (i == chanList->size())
895 else if (changeType == OFFSET)
897 if (newData == UP) newChannel = upChannel(currentChannelIndex);
898 else newChannel = downChannel(currentChannelIndex);
900 else if (changeType == PREVIOUS)
902 newChannel = previousChannelIndex;
906 return false; // bad input
909 if (newChannel == currentChannelIndex) return true;
911 previousChannelIndex = currentChannelIndex;
912 currentChannelIndex = newChannel;
916 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
917 player->setChannel(currentChannelIndex);
918 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Done Set player to channel %u", currentChannelIndex);
920 // Blank out the symbols
921 sAspectRatio.setVisible(false);
922 bufferBar.setPercent(0);
923 sAudioChannels.setVisible(false);
925 // Remove other stuff
926 if (textUnavailable.getVisible())
928 textUnavailable.setVisible(false);
933 BoxStack::getInstance()->update(this);
938 void VVideoLiveTV::processMessage(Message* m)
940 if (m->message == Message::MOUSE_LBDOWN)
942 //check if press is outside this view! then simulate cancel
943 int x=(m->parameter>>16)-osd.getScreenX();
944 int y=(m->parameter&0xFFFF)-osd.getScreenY();
945 if (osd.getVisible()) {
947 if ((boxRed.getX()<=x) && (boxRed.getX()+(int)boxRed.getWidth()>=x ) &&
948 (boxRed.getY()<=y) && (boxRed.getY()+(int)boxRed.getHeight()>=y )) {
949 BoxStack::getInstance()->handleCommand(Remote::RED);
950 } else if ((boxGreen.getX()<=x) && (boxGreen.getX()+(int)boxGreen.getWidth()>=x ) &&
951 (boxGreen.getY()<=y) && (boxGreen.getY()+(int)boxGreen.getHeight()>=y)){
952 BoxStack::getInstance()->handleCommand(Remote::GREEN);
953 } else if ((boxYellow.getX()<=x) && (boxYellow.getX()+(int)boxYellow.getWidth()>=x ) &&
954 (boxYellow.getY()<=y) && (boxYellow.getY()+(int)boxYellow.getHeight()>=y )){
955 BoxStack::getInstance()->handleCommand(Remote::YELLOW);
956 } else if ((boxBlue.getX()<=x) && (boxBlue.getX()+(int)boxBlue.getWidth()>=x ) &&
957 (boxBlue.getY()<=y) && (boxBlue.getY()+(int)boxBlue.getHeight()>=y )){
958 BoxStack::getInstance()->handleCommand(Remote::BLUE);
960 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
964 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
967 else if (m->message == Message::CHANNEL_CHANGE)
969 channelChange(NUMBER, m->parameter);
970 osdChannelIndex = currentChannelIndex;
971 if (m->tag == 1) displayOSD(true);
973 else if (m->message == Message::EPG_CLOSE)
975 video->setMode(videoMode);
977 else if (m->message == Message::CHILD_CLOSE)
985 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
987 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %i", m->parameter);
988 player->setAudioChannel((m->parameter & 0xFFFF),(m->parameter & 0xFF0000)>>16);
990 else if (m->message == Message::SUBTITLE_CHANGE_CHANNEL)
992 if (streamType !=VDR::VIDEO) return;
993 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change subtitle channel to %i", m->parameter);
994 int type=((m->parameter & 0xFF0000)>>16);
996 case 0x10: { //dvbsubtitle
997 if (streamType = VDR::VIDEO){
998 player->setSubtitleChannel((m->parameter & 0xFFFF));
999 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(true);
1000 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1001 if (vtxt && vtxt->isInSubtitleMode()) {
1002 BoxStack::getInstance()->remove(vtxt);
1006 case 0xFF: { //nosubtitles
1007 if (streamType = VDR::VIDEO){
1008 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1009 VTeletextView *vtxt=((PlayerLiveTV*)player)->getTeletextDecoder()->getTeletxtView();
1010 if (vtxt && vtxt->isInSubtitleMode()) {
1011 BoxStack::getInstance()->remove(vtxt);
1015 case 0x11: { //videotext
1016 (static_cast<PlayerLiveTV*>(player))->turnSubtitlesOn(false);
1018 ((PlayerLiveTV*)player)->getTeletextDecoder()->setPage((m->parameter & 0xFFFF));
1022 BoxStack::getInstance()->update(vas);
1023 //BoxStack::getInstance()->update(&osd); //eveil error
1025 BoxStack::getInstance()->update(this, osd.getRegion());
1029 else if (m->message == Message::PLAYER_EVENT)
1031 switch(m->parameter)
1033 case PlayerLiveTV::CONNECTION_LOST: // connection lost detected
1035 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
1036 Command::getInstance()->connectionLost();
1040 case PlayerLiveTV::STREAM_END:
1042 // Message comes from playerlivetv through master mutex, so can do anything here
1047 case PlayerLiveTV::ASPECT43:
1049 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1051 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
1054 BoxStack::getInstance()->update(this, &wssRegion);
1057 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT43;
1058 sAspectRatio.setVisible(true);
1060 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1063 BoxStack::getInstance()->update(this, osd.getRegion());
1068 case PlayerLiveTV::ASPECT169:
1070 if ((video->getTVsize() == Video::ASPECT16X9) && dowss)
1072 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
1075 BoxStack::getInstance()->update(this, &wssRegion);
1078 sAspectRatio.nextSymbol = WSymbol::VIDEOASPECT169;
1079 sAspectRatio.setVisible(true);
1081 if (osd.getVisible()) // don't wake up the whole osd just for a aspect change
1084 BoxStack::getInstance()->update(this, osd.getRegion());
1089 case PlayerLiveTV::PREBUFFERING:
1091 preBuffering = m->tag;
1092 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Prebuffering - %u", preBuffering);
1093 bufferBar.setPercent(preBuffering);
1095 if (osd.getVisible())
1097 bufferBar.setVisible(true);
1100 bufferBar.getRootBoxRegion(&r); ///////// FIXME !!!
1101 BoxStack::getInstance()->update(this, &r);
1103 if (preBuffering == 100)
1105 doAudioChannelSymbol();
1113 void VVideoLiveTV::doAudioChannelSymbol()
1116 Channel* currentChannel = (*chanList)[osdChannelIndex];
1118 bool multiAudio = false;
1120 if (currentChannel->numDPids > 1) multiAudio = true;
1122 if (currentChannel->numAPids > 1) multiAudio = true;
1126 if (multiAudio) sAudioChannels.nextSymbol = WSymbol::MULTIAUDIO;
1127 else sAudioChannels.nextSymbol = WSymbol::SINGLEAUDIO;
1128 sAudioChannels.setVisible(true);
1130 if (osd.getVisible())
1132 sAudioChannels.draw();
1134 sAudioChannels.getRootBoxRegion(&r); ///////// FIXME !!!
1138 BoxStack::getInstance()->update(this, &r);
1142 UINT VVideoLiveTV::upChannel(UINT index)
1144 if (index == (chanList->size() - 1)) // at the end
1145 return 0; // so go to start
1150 UINT VVideoLiveTV::downChannel(UINT index)
1152 if (index == 0) // at the start
1153 return chanList->size() - 1; // so go to end
1158 void VVideoLiveTV::toggleChopSides()
1160 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
1162 if (videoMode == Video::NORMAL)
1164 videoMode = Video::LETTERBOX;
1165 video->setMode(Video::LETTERBOX);
1169 videoMode = Video::NORMAL;
1170 video->setMode(Video::NORMAL);
1174 void VVideoLiveTV::drawOSDBitmap(UINT posX, UINT posY, const Bitmap& bm)
1176 drawBitmap(posX, posY, bm);
1178 r.x = posX; r.y = posY; r.w = bm.getWidth(); r.h = bm.getHeight();
1179 boxstack->update(this, &r);
1182 void VVideoLiveTV::clearOSD()
1184 rectangle(area, Colour(0,0,0,0));
1185 boxstack->update(this, &area);
1188 void VVideoLiveTV::clearOSDArea(UINT posX, UINT posY, UINT width, UINT height)
1191 r.x = posX; r.y = posY; r.w = width; r.h = height;
1192 rectangle(r, Colour(0,0,0,0));
1193 boxstack->update(this, &r);