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