]> git.vomp.tv Git - vompclient.git/blob - vvideolive.cc
WSS files added, and now working on live tv as well
[vompclient.git] / vvideolive.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
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.
10
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.
15
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
19 */
20
21 #include "vvideolive.h"
22
23 VVideoLive* VVideoLive::instance = NULL;
24
25 VVideoLive::VVideoLive(ChannelList* tchanList, ULONG tstreamType, VChannelList* tvchannelList)
26 {
27   instance = this;
28   vdr = VDR::getInstance();
29   viewman = ViewMan::getInstance();
30   video = Video::getInstance();
31
32   chanList = tchanList;
33   vchannelList = tvchannelList;
34
35   currentChannel = 0;
36   previousChannel = 0;
37   unavailable = 0;
38   unavailableView = NULL;
39   streamType = tstreamType;
40   videoMode = video->getMode();
41   if (streamType == VDR::RADIO) player = new Player(Command::getInstance(), this, false, true);
42   else                          player = new Player(Command::getInstance(), this, false, false);
43
44   player->init();
45   create(video->getScreenWidth(), video->getScreenHeight());
46   Colour transparent(0, 0, 0, 0);
47   setBackgroundColour(transparent);
48
49   wss.setSurface(surface);
50   wss.setWide(true);
51
52   wssRegion.x = 0;
53   wssRegion.y = 6;
54   wssRegion.w = video->getScreenWidth();
55   wssRegion.h = 2;
56 }
57
58 VVideoLive::~VVideoLive()
59 {
60   delete player;
61   instance = NULL;
62   video->setDefaultAspect();
63 }
64
65 VVideoLive* VVideoLive::getInstance()
66 {
67   return instance;
68 }
69
70 void VVideoLive::draw()
71 {
72   View::draw();
73 }
74
75 int VVideoLive::handleCommand(int command)
76 {
77   switch(command)
78   {
79     case Remote::STOP:
80     case Remote::BACK:
81     case Remote::MENU:
82     {
83       if (unavailable) showUnavailable(0);
84       else stop();
85
86       vchannelList->highlightChannel((*chanList)[currentChannel]);
87       return 4;
88     }
89     // Take up and down from new remote and do live banner
90     case Remote::UP:
91     case Remote::DOWN:
92     {
93       doBanner(true);
94       return 2;
95     }
96     case Remote::DF_UP:
97     case Remote::CHANNELUP:
98     {
99       if (unavailable) showUnavailable(0);
100       else stop();
101       channelChange(OFFSET, UP);
102       return 2;
103     }
104     case Remote::DF_DOWN:
105     case Remote::CHANNELDOWN:
106     {
107       if (unavailable) showUnavailable(0);
108       else stop();
109       channelChange(OFFSET, DOWN);
110       return 2;
111     }
112     case Remote::PREVCHANNEL:
113     {
114       if (unavailable) showUnavailable(0);
115       else stop();
116       channelChange(PREVIOUS, 0);
117       return 2;
118     }
119     case Remote::OK:
120     {
121       doBanner(true);
122       return 2;
123     }
124     case Remote::GUIDE:
125     case Remote::RED:
126     {
127       showEPG();
128       return 2;
129     }
130     case Remote::FULL:
131     case Remote::TV:
132     {
133       toggleChopSides();
134       return 2;
135     }
136
137     case Remote::ZERO:
138     case Remote::ONE:
139     case Remote::TWO:
140     case Remote::THREE:
141     case Remote::FOUR:
142     case Remote::FIVE:
143     case Remote::SIX:
144     case Remote::SEVEN:
145     case Remote::EIGHT:
146     case Remote::NINE:
147     {
148       VChannelSelect* v = new VChannelSelect(this, command);
149       v->draw();
150       viewman->add(v);
151       viewman->updateView(v);
152       return 2;
153     }
154 #ifdef DEV
155     case Remote::YELLOW:
156     {
157       player->test1();
158       break;
159     }
160     case Remote::BLUE:
161     {
162       player->test2();
163       break;
164     }
165 #endif
166   }
167
168   return 1;
169 }
170
171 void VVideoLive::channelChange(UCHAR changeType, UINT newData)
172 {
173   UINT newChannel = 0;
174
175   if (changeType == INDEX)
176   {
177     newChannel = newData;
178   }
179   else if (changeType == NUMBER)
180   {
181     UINT i;
182     for(i = 0; i < chanList->size(); i++)
183     {
184       if ((*chanList)[i]->number == (UINT)newData)
185       {
186         newChannel = i;
187         break;
188       }
189     }
190
191     if (i == chanList->size())
192     {
193       doNoSuchChannel();
194       return;
195     }
196   }
197   else if (changeType == OFFSET)
198   {
199     if (newData == UP) newChannel = upChannel();
200     else newChannel = downChannel();
201   }
202   else if (changeType == PREVIOUS)
203   {
204     newChannel = previousChannel;
205   }
206   else
207   {
208     return; // bad input!
209   }
210
211   previousChannel = currentChannel;
212   currentChannel = newChannel;
213
214   if (unavailable) showUnavailable(0);
215   else stop(1);
216
217   VEpg* vepg = VEpg::getInstance();
218   if(vepg) vepg->setCurrentChannel((*chanList)[currentChannel]->name);
219
220   VLiveBanner* vlb = VLiveBanner::getInstance();
221   if (vlb)
222   {
223     vlb->setChannel((*chanList)[currentChannel]);
224     vlb->draw();
225     viewman->updateView(vlb);
226   }
227
228   play();
229 }
230
231 void VVideoLive::streamEnd()
232 {
233   Log::getInstance()->log("VVideoLive", Log::DEBUG, "streamEnd");
234   stop(1);
235   showUnavailable(1);
236 }
237
238 void VVideoLive::processMessage(Message* m)
239 {
240   if (m->message == Message::CHANNEL_CHANGE)
241   {
242     channelChange(NUMBER, m->parameter);
243   }
244   else if (m->message == Message::EPG)
245   {
246     Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG requested from live banner");
247     showEPG();
248   }
249   else if (m->message == Message::EPG_CLOSE)
250   {
251     video->setMode(videoMode);
252     if (saveUnavailable) showUnavailable(1);
253   }
254   else if (m->message == Message::PLAYER_EVENT)
255   {
256     switch(m->parameter)
257     {
258       case Player::CONNECTION_LOST: // connection lost detected
259       {
260         Log::getInstance()->log("VVideoLive", Log::DEBUG, "Received connection lost from player");
261         // I can't handle this, send it to command
262         Message* m = new Message();
263         m->to = Command::getInstance();
264         m->message = Message::CONNECTION_LOST;
265         Command::getInstance()->postMessageNoLock(m);
266         break;
267       }
268       case Player::STREAM_END:
269       {
270         // I can't handle this, send it to command - improve this
271         Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
272         m->to = Command::getInstance();
273         m->message = Message::STREAM_END;
274         Command::getInstance()->postMessageNoLock(m);
275         break;
276       }
277       case Player::ASPECT43:
278       {
279         Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
280         wss.setWide(false);
281         wss.draw();
282         ViewMan::getInstance()->updateView(this, &wssRegion);
283         break;
284       }
285       case Player::ASPECT169:
286       {
287         Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
288         wss.setWide(true);
289         wss.draw();
290         ViewMan::getInstance()->updateView(this, &wssRegion);
291         break;
292       }
293     }
294   }
295 }
296
297 void VVideoLive::doBanner(bool bannerTakesCommands)
298 {
299   if (VEpg::getInstance()) return;
300
301   if (VLiveBanner::getInstance()) return; // there already is one
302
303   VLiveBanner* vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
304
305   vlb->draw();
306   viewman->add(vlb);
307   viewman->updateView(vlb);
308 }
309
310 void VVideoLive::doNoSuchChannel()
311 {
312   Log::getInstance()->log("VVideoLive", Log::ERR, "No such channel");
313   // FIXME do gui for this
314 }
315
316 void VVideoLive::showUnavailable(int active)
317 {
318   if (active == unavailable) return;
319
320   if (active)
321   {
322     unavailable = 1;
323
324     unavailableView = new VInfo();
325     unavailableView->create(400, 200);
326     if (video->getFormat() == Video::PAL)
327     {
328       unavailableView->setScreenPos(170, 200);
329     }
330     else
331     {
332       unavailableView->setScreenPos(160, 150);
333     }
334     unavailableView->setTitleText((*chanList)[currentChannel]->name);
335     unavailableView->setOneLiner(tr("Channel unavailable"));
336     unavailableView->setDropThrough();
337     unavailableView->draw();
338     viewman->add(unavailableView);
339     viewman->updateView(unavailableView);
340   }
341   else
342   {
343     unavailable = 0;
344     viewman->removeView(unavailableView);
345     unavailableView = NULL;
346   }
347 }
348
349 void VVideoLive::play(int noShowVLB)
350 {
351   showUnavailable(0);
352
353   int available = vdr->streamChannel((*chanList)[currentChannel]->number);
354
355   if (!available)
356   {
357     if (!noShowVLB) doBanner(false);
358     showUnavailable(1);
359     if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
360   }
361   else
362   {
363     if (!noShowVLB) doBanner(false);
364     player->play();
365   }
366 }
367
368 void VVideoLive::stop(int noRemoveVLB)
369 {
370   if (unavailable) return;
371   if (!noRemoveVLB && VLiveBanner::getInstance()) viewman->removeView(VLiveBanner::getInstance()); // if live banner is present, remove it. won't cause damage if its not present
372
373   player->stop();
374   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay starts here due to time taken by plugin to stop");
375   vdr->stopStreaming();
376   if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
377   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay ends here due to time taken by plugin to stop");
378 }
379
380 UINT VVideoLive::upChannel()
381 {
382   if (currentChannel == (chanList->size() - 1)) // at the end
383     return 0; // so go to start
384   else
385     return currentChannel + 1;
386 }
387
388 UINT VVideoLive::downChannel()
389 {
390   if (currentChannel == 0) // at the start
391     return chanList->size() - 1; // so go to end
392   else
393     return currentChannel - 1;
394 }
395
396 void VVideoLive::showEPG()
397 {
398   saveUnavailable = unavailable;
399   if (unavailable) showUnavailable(0);
400
401   if (VEpg::getInstance()) return; // already showing!
402
403   video->setMode(Video::QUARTER);
404   video->setPosition(170, 5); //TODO need to deal with 4:3 switching
405
406   VEpg* vepg = new VEpg(this, currentChannel);
407   vepg->draw();
408
409   viewman->add(vepg);
410   viewman->updateView(vepg);
411 }
412
413 void VVideoLive::toggleChopSides()
414 {
415   if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
416
417   if (videoMode == Video::NORMAL)
418   {
419     videoMode = Video::LETTERBOX;
420     video->setMode(Video::LETTERBOX);
421   }
422   else
423   {
424     videoMode = Video::NORMAL;
425     video->setMode(Video::NORMAL);
426   }
427 }