2 Copyright 2004-2005 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 "vvideolive.h"
23 #include "vchannellist.h"
26 #include "playerradio.h"
28 #include "vlivebanner.h"
30 #include "vchannelselect.h"
39 #include "vaudioselector.h"
41 VVideoLive* VVideoLive::instance = NULL;
43 VVideoLive::VVideoLive(ChannelList* tchanList, ULONG tstreamType, VChannelList* tvchannelList)
46 vdr = VDR::getInstance();
47 boxstack = BoxStack::getInstance();
48 video = Video::getInstance();
51 vchannelList = tvchannelList;
56 unavailableView = NULL;
57 streamType = tstreamType;
58 videoMode = video->getMode();
60 if (streamType == VDR::RADIO)
62 player = (void*)new PlayerRadio(Command::getInstance(), this, false);
63 ((PlayerRadio*)player)->init(0, 0);
67 player = (void*)new Player(Command::getInstance(), this, false);
68 ((Player*)player)->init();
71 setSize(video->getScreenWidth(), video->getScreenHeight());
73 Colour transparent(0, 0, 0, 0);
74 fillColour(transparent);
77 char* optionWSS = vdr->configLoad("General", "WSS");
80 if (strstr(optionWSS, "Yes")) dowss = true;
83 Log::getInstance()->log("VVideoLive", Log::DEBUG, "Do WSS: %u", dowss);
87 wss.setFormat(video->getFormat());
93 wssRegion.w = video->getScreenWidth();
98 VVideoLive::~VVideoLive()
100 if (streamType == VDR::RADIO)
102 delete (PlayerRadio*)player;
106 delete (Player*)player;
110 video->setDefaultAspect();
113 VVideoLive* VVideoLive::getInstance()
118 int VVideoLive::handleCommand(int command)
126 if (unavailable) showUnavailable(0);
129 vchannelList->highlightChannel((*chanList)[currentChannel]);
132 // Take up and down from new remote and do live banner
140 case Remote::CHANNELUP:
142 if (unavailable) showUnavailable(0);
144 channelChange(OFFSET, UP);
147 case Remote::DF_DOWN:
148 case Remote::CHANNELDOWN:
150 if (unavailable) showUnavailable(0);
152 channelChange(OFFSET, DOWN);
155 case Remote::PREVCHANNEL:
157 if (unavailable) showUnavailable(0);
159 channelChange(PREVIOUS, 0);
191 VChannelSelect* v = new VChannelSelect(this);
196 v->handleCommand(command);
202 if (streamType == VDR::VIDEO)
204 VAudioSelector* vas = new VAudioSelector(this, (*chanList)[currentChannel], ((Player*)player)->getCurrentAudioChannel());
205 vas->setBackgroundColour(Colour::VIEWBACKGROUND);
206 vas->setPosition(0, getHeight()-200);
208 BoxStack::getInstance()->add(vas);
209 BoxStack::getInstance()->update(vas);
225 void VVideoLive::channelChange(UCHAR changeType, UINT newData)
229 if (changeType == INDEX)
231 newChannel = newData;
233 else if (changeType == NUMBER)
236 for(i = 0; i < chanList->size(); i++)
238 if ((*chanList)[i]->number == (UINT)newData)
245 if (i == chanList->size())
251 else if (changeType == OFFSET)
253 if (newData == UP) newChannel = upChannel();
254 else newChannel = downChannel();
256 else if (changeType == PREVIOUS)
258 newChannel = previousChannel;
262 return; // bad input!
265 previousChannel = currentChannel;
266 currentChannel = newChannel;
268 if (unavailable) showUnavailable(0);
271 // VEpg* vepg = VEpg::getInstance();
272 // if(vepg) vepg->setCurrentChannel((*chanList)[currentChannel]->name);
274 VLiveBanner* vlb = VLiveBanner::getInstance();
277 vlb->setChannel((*chanList)[currentChannel]);
279 boxstack->update(vlb);
285 void VVideoLive::streamEnd()
287 Log::getInstance()->log("VVideoLive", Log::DEBUG, "streamEnd");
292 void VVideoLive::processMessage(Message* m)
294 if (m->message == Message::MOUSE_LBDOWN)
296 BoxStack::getInstance()->handleCommand(Remote::OK); //simulate rok press
298 else if (m->message == Message::CHANNEL_CHANGE)
300 channelChange(NUMBER, m->parameter);
302 else if (m->message == Message::EPG)
304 Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG requested from live banner");
307 else if (m->message == Message::EPG_CLOSE)
309 video->setMode(videoMode);
310 if (saveUnavailable) showUnavailable(1);
312 else if (m->message == Message::AUDIO_CHANGE_CHANNEL)
314 Log::getInstance()->log("VVideoLive", Log::DEBUG, "Received change audio channel to %i", m->parameter);
315 ((Player*)player)->setAudioChannel(m->parameter&0xFFFF,(m->parameter&0xFF0000)>>16);
317 else if (m->message == Message::PLAYER_EVENT)
321 case Player::CONNECTION_LOST: // connection lost detected
323 Log::getInstance()->log("VVideoLive", Log::DEBUG, "Received connection lost from player");
324 // I can't handle this, send it to command
325 Message* m2 = new Message();
326 m2->to = Command::getInstance();
327 m2->message = Message::CONNECTION_LOST;
328 Command::getInstance()->postMessageNoLock(m2);
331 case Player::STREAM_END:
333 // I can't handle this, send it to command - improve this
334 Message* m2 = new Message(); // Must be done after this thread finishes, and must break into master mutex
335 m2->to = Command::getInstance();
336 m2->message = Message::STREAM_END;
337 Command::getInstance()->postMessageNoLock(m2);
340 case Player::ASPECT43:
344 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
347 BoxStack::getInstance()->update(this, &wssRegion);
351 case Player::ASPECT169:
355 Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
358 BoxStack::getInstance()->update(this, &wssRegion);
366 void VVideoLive::doBanner(bool bannerTakesCommands)
368 if (VEpg::getInstance()) return;
370 if (VLiveBanner::getInstance()) return; // there already is one
372 VLiveBanner* vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
376 boxstack->update(vlb);
379 void VVideoLive::doNoSuchChannel()
381 Log::getInstance()->log("VVideoLive", Log::ERR, "No such channel");
382 // FIXME do gui for this
385 void VVideoLive::showUnavailable(int active)
387 if (active == unavailable) return;
393 unavailableView = new VInfo();
394 unavailableView->setSize(400, 200);
395 unavailableView->createBuffer();
396 if (video->getFormat() == Video::PAL)
398 unavailableView->setPosition(170, 200);
402 unavailableView->setPosition(160, 150);
404 unavailableView->setTitleText((*chanList)[currentChannel]->name);
405 unavailableView->setOneLiner(tr("Channel unavailable"));
406 unavailableView->setDropThrough();
407 unavailableView->draw();
408 boxstack->add(unavailableView);
409 boxstack->update(unavailableView);
414 boxstack->remove(unavailableView);
415 unavailableView = NULL;
419 void VVideoLive::play(int noShowVLB)
423 int available = vdr->streamChannel((*chanList)[currentChannel]->number);
427 if (!noShowVLB) doBanner(false);
429 if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
433 if (!noShowVLB) doBanner(false);
435 // FIXME - change this streamType thingy to the new system using getPids
436 // FIXME - upgrade PlayerRadio to new getPids
438 Channel* toPlay = (*chanList)[currentChannel];
441 if (streamType == VDR::RADIO)
443 ((PlayerRadio*)player)->play(toPlay->apids[0].pid);
447 ((Player*)player)->play(toPlay->vpid, toPlay->apids[0].pid);
452 void VVideoLive::stop(int noRemoveVLB)
454 if (unavailable) return;
455 if (!noRemoveVLB && VLiveBanner::getInstance()) boxstack->remove(VLiveBanner::getInstance()); // if live banner is present, remove it. won't cause damage if its not present
457 if (streamType == VDR::RADIO)
459 ((PlayerRadio*)player)->stop();
463 ((Player*)player)->stop();
466 Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay starts here due to time taken by plugin to stop");
467 vdr->stopStreaming();
468 if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
469 Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay ends here due to time taken by plugin to stop");
472 UINT VVideoLive::upChannel()
474 if (currentChannel == (chanList->size() - 1)) // at the end
475 return 0; // so go to start
477 return currentChannel + 1;
480 UINT VVideoLive::downChannel()
482 if (currentChannel == 0) // at the start
483 return chanList->size() - 1; // so go to end
485 return currentChannel - 1;
488 void VVideoLive::showEPG()
490 saveUnavailable = unavailable;
491 if (unavailable) showUnavailable(0);
493 if (VEpg::getInstance()) return; // already showing!
495 video->setMode(Video::QUARTER);
496 video->setPosition(170, 5); //TODO need to deal with 4:3 switching
498 VEpg* vepg = new VEpg(this, currentChannel, streamType);
501 Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG draw finished");
504 boxstack->update(vepg);
506 Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG blttd to screen");
509 void VVideoLive::toggleChopSides()
511 if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
513 if (videoMode == Video::NORMAL)
515 videoMode = Video::LETTERBOX;
516 video->setMode(Video::LETTERBOX);
520 videoMode = Video::NORMAL;
521 video->setMode(Video::NORMAL);