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