2 Copyright 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "vvideolivetv.h"
23 #include "vchannellist.h"
25 //#include "playerlivetv.h"
34 #include "vaudioselector.h"
40 VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList)
42 vdr = VDR::getInstance();
43 boxstack = BoxStack::getInstance();
44 video = Video::getInstance();
47 vchannelList = tvchannelList;
48 numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
50 currentChannelIndex = 0;
51 previousChannelIndex = 0;
57 // Convert channel number to index
59 for(i = 0; i < chanList->size(); i++)
61 if ((*chanList)[i]->number == (UINT)initialChannelNumber)
63 currentChannelIndex = i;
71 videoMode = video->getMode();
72 // player = new PlayerLiveTV(Command::getInstance(), this);
73 // player->init(chanList);
75 setSize(video->getScreenWidth(), video->getScreenHeight());
77 Colour transparent(0, 0, 0, 0);
78 setBackgroundColour(transparent);
81 char* optionWSS = vdr->configLoad("General", "WSS");
84 if (strstr(optionWSS, "Yes")) dowss = true;
87 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Do WSS: %u", dowss);
91 wss.setFormat(video->getFormat());
97 wssRegion.w = video->getScreenWidth();
101 Colour osdBack = Colour(50, 50, 50);
103 osd.setBackgroundColour(osdBack);
104 osd.setPosition(0, video->getScreenHeight() - 150);
105 osd.setSize(video->getScreenWidth(), 150);
106 osd.setVisible(false);
109 clock.setBackgroundColour(Colour::BLACK);
110 clock.setPosition(osd.getWidth() - 100, 4);
111 clock.setSize(90, 30);
114 osdChanNum.setBackgroundColour(Colour::BLACK);
115 osdChanNum.setPosition(40, 4);
116 osdChanNum.setSize((numberWidth*10) + 22, 30); // 10 px = width of number chars in font
117 osd.add(&osdChanNum);
119 osdChanName.setBackgroundColour(Colour::BLACK);
120 osdChanName.setPosition(osdChanNum.getX2() + 10, 4);
121 osdChanName.setSize(300, 30);
122 osd.add(&osdChanName);
124 boxRed.setBackgroundColour(Colour::RED);
125 boxRed.setPosition(50, 104);
126 boxRed.setSize(18, 16);
129 boxGreen.setBackgroundColour(Colour::GREEN);
130 boxGreen.setPosition(220, 104);
131 boxGreen.setSize(18, 16);
134 boxYellow.setBackgroundColour(Colour::YELLOW);
135 boxYellow.setPosition(390, 104);
136 boxYellow.setSize(18, 16);
139 boxBlue.setBackgroundColour(Colour::BLUE);
140 boxBlue.setPosition(560, 104);
141 boxBlue.setSize(18, 16);
144 textRed.setBackgroundColour(Colour::BLACK);
145 textRed.setPosition(boxRed.getX()+18, 98);
146 textRed.setSize(120, 30);
147 textRed.setText("Summary");
150 textGreen.setBackgroundColour(Colour::BLACK);
151 textGreen.setPosition(boxGreen.getX()+18, 98);
152 textGreen.setSize(120, 30);
153 textGreen.setText("Audio");
156 textYellow.setBackgroundColour(Colour::BLACK);
157 textYellow.setPosition(boxYellow.getX()+18, 98);
158 textYellow.setSize(120, 30);
159 textYellow.setText("");
160 osd.add(&textYellow);
162 textBlue.setBackgroundColour(Colour::BLACK);
163 textBlue.setPosition(boxBlue.getX()+18, 98);
164 textBlue.setSize(90, 30);
165 textBlue.setText("EPG");
168 sl.setPosition(70, 36);
174 VVideoLiveTV::~VVideoLiveTV()
179 video->setDefaultAspect();
182 int VVideoLiveTV::handleCommand(int command)
188 if (osd.getVisible())
193 // else drop through to stop
199 vchannelList->highlightChannel((*chanList)[currentChannelIndex]);
231 case Remote::CHANNELUP:
236 case Remote::DF_DOWN:
237 case Remote::CHANNELDOWN:
242 case Remote::PREVCHANNEL:
244 channelChange(PREVIOUS, 0);
274 // key in channel number
282 VAudioSelector* vas = new VAudioSelector(this, (*chanList)[currentChannelIndex], ((Player*)player)->getCurrentAudioChannel());
283 vas->setBackgroundColour(Colour::VIEWBACKGROUND);
284 vas->setPosition(0, getHeight()-200);
286 BoxStack::getInstance()->add(vas);
287 BoxStack::getInstance()->update(vas);
305 void VVideoLiveTV::go()
309 boxstack->update(this);
317 void VVideoLiveTV::stop()
319 Timers::getInstance()->cancelTimer(this, 1);
320 Timers::getInstance()->cancelTimer(this, 2);
324 void VVideoLiveTV::doNowNext()
329 Channel* currentChannel = (*chanList)[osdChannelIndex];
331 char formatChanNum[20];
332 SNPRINTF(formatChanNum, 19, "%0*lu", numberWidth, currentChannel->number);
333 osdChanNum.setText(formatChanNum);
334 osdChanName.setText(currentChannel->name);
336 eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
340 sl.addOption(tr("No channel data available"), 0, 1);
344 sort(eventList->begin(), eventList->end(), EventSorter());
346 char tempString[300];
347 char tempString2[300];
350 int eventListSize = eventList->size();
351 for(int i = 0; i < eventListSize; i++)
353 event = (*eventList)[i];
355 //btime = localtime((time_t*)&event->time);
356 time_t etime = event->time;
357 btime = localtime(&etime);
359 strftime(tempString2, 299, "%0H:%0M ", btime);
361 strftime(tempString2, 299, "%H:%M ", btime);
363 SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
364 sl.addOption(tempString, (ULONG)event, (i==0));
369 void VVideoLiveTV::delData()
373 int eventListSize = eventList->size();
374 for(int i = 0; i < eventListSize; i++)
376 delete (*eventList)[i];
385 void VVideoLiveTV::doOK()
387 if (osd.getVisible())
392 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10, i);
394 channelChange(NUMBER, newChannel);
395 osdChannelIndex = currentChannelIndex;
398 else if (osdChannelIndex == currentChannelIndex)
404 channelChange(INDEX, osdChannelIndex);
410 osdChannelIndex = currentChannelIndex;
415 void VVideoLiveTV::doLeft()
417 if (osd.getVisible())
418 osdChannelIndex = downChannel(osdChannelIndex);
420 osdChannelIndex = currentChannelIndex;
425 void VVideoLiveTV::doRight()
427 if (osd.getVisible())
428 osdChannelIndex = upChannel(osdChannelIndex);
430 osdChannelIndex = currentChannelIndex;
435 void VVideoLiveTV::doUp()
437 if (osd.getVisible())
441 boxstack->update(this, osd.getRegion());
442 Timers::getInstance()->setTimerD(this, 1, 8); // arrows pressed, go to 8s timer
450 void VVideoLiveTV::doDown()
452 if (osd.getVisible())
456 boxstack->update(this, osd.getRegion());
457 Timers::getInstance()->setTimerD(this, 1, 8); // arrows pressed, go to 8s timer
465 void VVideoLiveTV::doChanUp()
467 channelChange(OFFSET, UP);
468 osdChannelIndex = currentChannelIndex;
473 void VVideoLiveTV::doChanDown()
475 channelChange(OFFSET, DOWN);
476 osdChannelIndex = currentChannelIndex;
481 void VVideoLiveTV::doKey(int command)
483 if (!osd.getVisible()) // First key. prep the data
489 for (i = keying - 1; i >= 0; i--) keyingInput[i+1] = keyingInput[i];
490 keyingInput[0] = command;
493 char keyingString[numberWidth+1];
494 for (i = 0; i < numberWidth; i++) keyingString[i] = '_';
495 keyingString[numberWidth] = '\0';
497 for (i = 0; i < keying; i++) keyingString[i] = keyingInput[keying - 1 - i] + 48;
499 if (keying == numberWidth)
502 for(i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10, i);
504 channelChange(NUMBER, newChannel);
505 osdChannelIndex = currentChannelIndex;
510 // Special, modified displayOSD
511 if (!osd.getVisible())
513 osd.setVisible(true);
514 osdChanNum.setText(keyingString);
519 osdChanNum.setText(keyingString);
522 boxstack->update(this, osd.getRegion());
523 Timers::getInstance()->setTimerD(this, 1, 3); // 3s for keying input
527 void VVideoLiveTV::displayOSD()
529 osd.setVisible(true);
532 boxstack->update(this, osd.getRegion());
533 Timers::getInstance()->setTimerD(this, 1, 4);
536 void VVideoLiveTV::removeOSD()
538 Timers::getInstance()->cancelTimer(this, 1);
539 osd.setVisible(false);
541 boxstack->update(this, osd.getRegion());
544 void VVideoLiveTV::setClock()
549 struct tm* tms = localtime(&t);
550 strftime(timeString, 19, "%H:%M", tms);
551 clock.setText(timeString);
553 time_t dt = 60 - (t % 60); // seconds to the next minute
554 if (dt == 0) dt = 60; // advance a whole minute if necessary
555 dt += t; // get a time_t value for it rather than using duration
556 // (so it will occur at the actual second and not second and a half)
558 Timers::getInstance()->setTimerT(this, 2, dt);
561 void VVideoLiveTV::doEPG()
563 if (osd.getVisible()) removeOSD();
565 video->setMode(Video::QUARTER);
566 video->setPosition(170, 5); //TODO need to deal with 4:3 switching
568 VEpg* vepg = new VEpg(NULL, currentChannelIndex, VDR::VIDEO);
571 boxstack->update(vepg);
574 void VVideoLiveTV::timercall(int ref)
580 // Really, now that cancelTimer basically protects us from deletion, why can't we execute gui stuff here?
583 for(int i = keying - 1; i >= 0; i--) newChannel += keyingInput[i] * (ULONG)pow(10, i);
585 Message* m = new Message();
586 m->message = Message::CHANNEL_CHANGE;
588 m->parameter = newChannel;
589 Command::getInstance()->postMessageFromOuterSpace(m); // FIXME cjt yeah you know what.
593 osd.setVisible(false);
595 Message* m = new Message();
596 m->message = Message::REDRAW;
597 m->to = BoxStack::getInstance();
599 m->parameter = (ULONG)osd.getRegion();
600 Command::getInstance()->postMessageFromOuterSpace(m); // FIXME cjt yeah you know what.
606 if (osd.getVisible())
609 Message* m = new Message();
610 m->message = Message::REDRAW;
611 m->to = BoxStack::getInstance();
613 m->parameter = (ULONG)osd.getRegion();
614 Command::getInstance()->postMessageFromOuterSpace(m); // FIXME cjt yeah you know what.
619 bool VVideoLiveTV::channelChange(UCHAR changeType, UINT newData)
623 if (changeType == INDEX)
625 newChannel = newData;
627 else if (changeType == NUMBER)
630 for(i = 0; i < chanList->size(); i++)
632 if ((*chanList)[i]->number == (UINT)newData)
639 if (i == chanList->size())
645 else if (changeType == OFFSET)
647 if (newData == UP) newChannel = upChannel(currentChannelIndex);
648 else newChannel = downChannel(currentChannelIndex);
650 else if (changeType == PREVIOUS)
652 newChannel = previousChannelIndex;
656 return false; // bad input
659 if (newChannel == currentChannelIndex) return true;
661 previousChannelIndex = currentChannelIndex;
662 currentChannelIndex = newChannel;
664 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Set player to channel %u", currentChannelIndex);
667 // player->setChannel(currentChannelIndex);
670 void VVideoLiveTV::processMessage(Message* m)
672 if (m->message == Message::MOUSE_LBDOWN)
674 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
676 else if (m->message == Message::CHANNEL_CHANGE)
678 channelChange(NUMBER, m->parameter);
679 osdChannelIndex = currentChannelIndex;
682 else if (m->message == Message::EPG_CLOSE)
684 video->setMode(videoMode);
686 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
688 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received change audio channel to %i", m->parameter);
689 // ((Player*)player)->setAudioChannel(m->parameter);
691 else if (m->message == Message::PLAYER_EVENT)
696 case Player::CONNECTION_LOST: // connection lost detected
698 Log::getInstance()->log("VVideoLiveTV", Log::DEBUG, "Received connection lost from player");
699 // I can't handle this, send it to command
700 Message* m2 = new Message();
701 m2->to = Command::getInstance();
702 m2->message = Message::CONNECTION_LOST;
703 Command::getInstance()->postMessageNoLock(m2);
706 case Player::STREAM_END:
708 // I can't handle this, send it to command - improve this
709 Message* m2 = new Message(); // Must be done after this thread finishes, and must break into master mutex
710 m2->to = Command::getInstance();
711 m2->message = Message::STREAM_END;
712 Command::getInstance()->postMessageNoLock(m2);
715 case Player::ASPECT43:
719 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
722 BoxStack::getInstance()->update(this, &wssRegion);
726 case Player::ASPECT169:
730 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
733 BoxStack::getInstance()->update(this, &wssRegion);
742 UINT VVideoLiveTV::upChannel(UINT index)
744 if (index == (chanList->size() - 1)) // at the end
745 return 0; // so go to start
750 UINT VVideoLiveTV::downChannel(UINT index)
752 if (index == 0) // at the start
753 return chanList->size() - 1; // so go to end
758 void VVideoLiveTV::toggleChopSides()
760 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
762 if (videoMode == Video::NORMAL)
764 videoMode = Video::LETTERBOX;
765 video->setMode(Video::LETTERBOX);
769 videoMode = Video::NORMAL;
770 video->setMode(Video::NORMAL);