]> git.vomp.tv Git - vompclient-marten.git/blob - vvideolive.cc
Minor cleanup changes
[vompclient-marten.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     player = (void*)new PlayerRadio(Command::getInstance(), this, false);
45     ((PlayerRadio*)player)->init(0, 0);
46   }
47   else
48   {
49     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::MOUSE_LBDOWN)
265   {
266     ViewMan::getInstance()->handleCommand(Remote::OK); //simulate rok press
267   }
268   else if (m->message == Message::CHANNEL_CHANGE)
269   {
270     channelChange(NUMBER, m->parameter);
271   }
272   else if (m->message == Message::EPG)
273   {
274     Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG requested from live banner");
275     showEPG();
276   }
277   else if (m->message == Message::EPG_CLOSE)
278   {
279     video->setMode(videoMode);
280     if (saveUnavailable) showUnavailable(1);
281   }
282   else if (m->message == Message::PLAYER_EVENT)
283   {
284     switch(m->parameter)
285     {
286       case Player::CONNECTION_LOST: // connection lost detected
287       {
288         Log::getInstance()->log("VVideoLive", Log::DEBUG, "Received connection lost from player");
289         // I can't handle this, send it to command
290         Message* m = new Message();
291         m->to = Command::getInstance();
292         m->message = Message::CONNECTION_LOST;
293         Command::getInstance()->postMessageNoLock(m);
294         break;
295       }
296       case Player::STREAM_END:
297       {
298         // I can't handle this, send it to command - improve this
299         Message* m = new Message(); // Must be done after this thread finishes, and must break into master mutex
300         m->to = Command::getInstance();
301         m->message = Message::STREAM_END;
302         Command::getInstance()->postMessageNoLock(m);
303         break;
304       }
305       case Player::ASPECT43:
306       {
307         if (dowss)
308         {
309           Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 43");
310           wss.setWide(false);
311           wss.draw();
312           ViewMan::getInstance()->updateView(this, &wssRegion);
313         }
314         break;
315       }
316       case Player::ASPECT169:
317       {
318         if (dowss)
319         {
320           Log::getInstance()->log("VVideoRec", Log::DEBUG, "Received do WSS 169");
321           wss.setWide(true);
322           wss.draw();
323           ViewMan::getInstance()->updateView(this, &wssRegion);
324         }
325         break;
326       }
327     }
328   }
329 }
330
331 void VVideoLive::doBanner(bool bannerTakesCommands)
332 {
333   if (VEpg::getInstance()) return;
334
335   if (VLiveBanner::getInstance()) return; // there already is one
336
337   VLiveBanner* vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
338
339   vlb->draw();
340   viewman->add(vlb);
341   viewman->updateView(vlb);
342 }
343
344 void VVideoLive::doNoSuchChannel()
345 {
346   Log::getInstance()->log("VVideoLive", Log::ERR, "No such channel");
347   // FIXME do gui for this
348 }
349
350 void VVideoLive::showUnavailable(int active)
351 {
352   if (active == unavailable) return;
353
354   if (active)
355   {
356     unavailable = 1;
357
358     unavailableView = new VInfo();
359     unavailableView->create(400, 200);
360     if (video->getFormat() == Video::PAL)
361     {
362       unavailableView->setScreenPos(170, 200);
363     }
364     else
365     {
366       unavailableView->setScreenPos(160, 150);
367     }
368     unavailableView->setTitleText((*chanList)[currentChannel]->name);
369     unavailableView->setOneLiner(tr("Channel unavailable"));
370     unavailableView->setDropThrough();
371     unavailableView->draw();
372     viewman->add(unavailableView);
373     viewman->updateView(unavailableView);
374   }
375   else
376   {
377     unavailable = 0;
378     viewman->removeView(unavailableView);
379     unavailableView = NULL;
380   }
381 }
382
383 void VVideoLive::play(int noShowVLB)
384 {
385   showUnavailable(0);
386
387   int available = vdr->streamChannel((*chanList)[currentChannel]->number);
388
389   if (!available)
390   {
391     if (!noShowVLB) doBanner(false);
392     showUnavailable(1);
393     if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
394   }
395   else
396   {
397     if (!noShowVLB) doBanner(false);
398
399     // FIXME - change this streamType thingy to the new system using getPids
400     // FIXME - upgrade PlayerRadio to new getPids
401
402     Channel* toPlay = (*chanList)[currentChannel];
403     toPlay->loadPids();
404
405     if (streamType == VDR::RADIO)
406     {
407       ((PlayerRadio*)player)->play(toPlay->apids[0].pid);
408     }
409     else
410     {
411       ((Player*)player)->play(toPlay->vpid, toPlay->apids[0].pid);
412     }
413   }
414 }
415
416 void VVideoLive::stop(int noRemoveVLB)
417 {
418   if (unavailable) return;
419   if (!noRemoveVLB && VLiveBanner::getInstance()) viewman->removeView(VLiveBanner::getInstance()); // if live banner is present, remove it. won't cause damage if its not present
420
421   if (streamType == VDR::RADIO)
422   {
423     ((PlayerRadio*)player)->stop();
424   }
425   else
426   {
427     ((Player*)player)->stop();
428   }
429
430   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay starts here due to time taken by plugin to stop");
431   vdr->stopStreaming();
432   if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
433   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay ends here due to time taken by plugin to stop");
434 }
435
436 UINT VVideoLive::upChannel()
437 {
438   if (currentChannel == (chanList->size() - 1)) // at the end
439     return 0; // so go to start
440   else
441     return currentChannel + 1;
442 }
443
444 UINT VVideoLive::downChannel()
445 {
446   if (currentChannel == 0) // at the start
447     return chanList->size() - 1; // so go to end
448   else
449     return currentChannel - 1;
450 }
451
452 void VVideoLive::showEPG()
453 {
454   saveUnavailable = unavailable;
455   if (unavailable) showUnavailable(0);
456
457   if (VEpg::getInstance()) return; // already showing!
458
459   video->setMode(Video::QUARTER);
460   video->setPosition(170, 5); //TODO need to deal with 4:3 switching
461
462   VEpg* vepg = new VEpg(this, currentChannel);
463   vepg->draw();
464
465   viewman->add(vepg);
466   viewman->updateView(vepg);
467 }
468
469 void VVideoLive::toggleChopSides()
470 {
471   if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
472
473   if (videoMode == Video::NORMAL)
474   {
475     videoMode = Video::LETTERBOX;
476     video->setMode(Video::LETTERBOX);
477   }
478   else
479   {
480     videoMode = Video::NORMAL;
481     video->setMode(Video::NORMAL);
482   }
483 }