]> git.vomp.tv Git - vompclient.git/blob - vvideolive.cc
More EPG tweaks, fix a freeze changing to a non-transmitting channel
[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)
26 {
27   instance = this;
28   vdr = VDR::getInstance();
29   viewman = ViewMan::getInstance();
30   chanList = tchanList;
31   currentChannel = 0;
32   previousChannel = 0;
33   unavailable = 0;
34   unavailableView = NULL;
35   streamType = tstreamType;
36   epgmode=false;
37   videoMode = Video::getInstance()->getMode();
38   if (streamType == VDR::RADIO) player = new PlayerVideo(Command::getInstance(), 0, 1);
39   else                          player = new PlayerVideo(Command::getInstance(), 0, 0);
40
41   player->init();
42
43   Video* video = Video::getInstance();
44   create(video->getScreenWidth(), video->getScreenHeight());
45   Colour transparent(0, 0, 0, 0);
46   setBackgroundColour(transparent);
47 }
48
49 VVideoLive::~VVideoLive()
50 {
51   delete player;
52   instance = NULL;
53   Video::getInstance()->setDefaultAspect();
54 }
55
56 VVideoLive* VVideoLive::getInstance()
57 {
58   return instance;
59 }
60
61 void VVideoLive::draw()
62 {
63   View::draw();
64 }
65
66 int VVideoLive::handleCommand(int command)
67 {
68   switch(command)
69   {
70     case Remote::PLAY:
71     {
72       if (!unavailable) player->play(); // do resync
73       return 2;
74     }
75     case Remote::PAUSE:
76     {
77       if (!unavailable) player->resyncAudio(); // do resync2
78       return 2;
79     }
80
81     case Remote::STOP:
82     case Remote::BACK:
83     case Remote::MENU:
84     {
85       if (unavailable) showUnavailable(0);
86       else stop();
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       if (!epgmode)
128       {
129         showEPG();
130       }
131       epgmode=!epgmode;
132       return 2;
133     }
134
135     case Remote::ZERO ... Remote::NINE:
136     {
137       VChannelSelect* v = new VChannelSelect(this, command);
138       v->draw();
139       viewman->add(v);
140       viewman->updateView(v);
141     }
142   }
143
144   return 1;
145 }
146
147 void VVideoLive::channelChange(UCHAR changeType, UINT newData)
148 {
149   UINT newChannel = 0;
150
151   if (changeType == INDEX)
152   {
153     newChannel = newData;
154   }
155   else if (changeType == NUMBER)
156   {
157     newChannel = channelIndexFromNumber(newData);
158   }
159   else if (changeType == OFFSET)
160   {
161     if (newData == UP) newChannel = upChannel();
162     else newChannel = downChannel();
163   }
164   else if (changeType == PREVIOUS)
165   {
166     newChannel = previousChannel;
167   }
168   else
169   {
170     return; // bad input!
171   }
172
173   previousChannel = currentChannel;
174   currentChannel = newChannel;
175
176   if (unavailable) showUnavailable(0);
177   else stop(1);
178   if(epgmode)
179     if(vepg)
180       vepg->setCurrentChannel((*chanList)[currentChannel]->name);
181   play();
182 }
183
184 void VVideoLive::processMessage(Message* m)
185 {
186   if (m->message == Message::CHANNEL_CHANGE)
187   {
188     channelChange(NUMBER, m->parameter);
189   }
190   else if (m->message == Message::CHANNEL_UP)
191   {
192     // this message is from vlivebanner
193     channelChange(OFFSET, UP);
194     if(!epgmode)
195     {
196       VLiveBanner* vlb = VLiveBanner::getInstance(); // guaranteed to be one
197       vlb->setChannel((*chanList)[currentChannel]);
198       vlb->draw();
199       viewman->updateView(vlb);
200     }
201   }
202   else if (m->message == Message::CHANNEL_DOWN)
203   {
204     // this message is from vlivebanner
205     channelChange(OFFSET, DOWN);
206     if(!epgmode)
207     {
208       VLiveBanner* vlb = VLiveBanner::getInstance(); // guaranteed to be one
209       vlb->setChannel((*chanList)[currentChannel]);
210       vlb->draw();
211       viewman->updateView(vlb);
212     }
213   }
214   else if (m->message == Message::STREAM_END)
215   {
216     Log::getInstance()->log("VVideoLive", Log::DEBUG, "streamEnd");
217     stop();
218     showUnavailable(1);
219   }
220   else if (m->message == Message::EPG)
221   {
222     Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG requested from live banner");
223
224     if (!epgmode)
225     {
226       showEPG();
227       epgmode=!epgmode; // shouldn't this be within the braces? // same for above in handleCommand, ask Brian FIXME
228     }
229   }
230 }
231
232 void VVideoLive::doBanner(bool bannerTakesCommands)
233 {
234   if(epgmode)
235     return;
236
237   if (VLiveBanner::getInstance()) return; // there already is one
238
239   VLiveBanner* vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
240
241   Message* m = new Message();
242   m->from = this;
243   m->to = viewman;
244   m->message = Message::ADD_VIEW;
245   m->parameter = (ULONG)vlb;
246
247   viewman->postMessage(m);
248 }
249
250 void VVideoLive::showUnavailable(int active)
251 {
252   if (active == unavailable) return;
253
254   if (active)
255   {
256     unavailable = 1;
257
258     unavailableView = new VInfo();
259     unavailableView->create(400, 200);
260     if (Video::getInstance()->getFormat() == Video::PAL)
261     {
262       unavailableView->setScreenPos(170, 200);
263     }
264     else
265     {
266       unavailableView->setScreenPos(160, 150);
267     }
268     unavailableView->setTitleText((*chanList)[currentChannel]->name);
269     unavailableView->setOneLiner(tr("Channel unavailable"));
270     unavailableView->setDropThrough();
271
272     Message* m = new Message();
273     m->from = this;
274     m->to = viewman;
275     m->message = Message::ADD_VIEW;
276     m->parameter = (ULONG)unavailableView;
277
278     viewman->postMessage(m);
279   }
280   else
281   {
282     unavailable = 0;
283     viewman->removeView(unavailableView);
284     unavailableView = NULL;
285   }
286 }
287
288 void VVideoLive::play(int noShowVLB)
289 {
290   showUnavailable(0);
291
292   int available = vdr->streamChannel((*chanList)[currentChannel]->number);
293
294   if (!available)
295   {
296     showUnavailable(1);
297     if (!noShowVLB) doBanner(false);
298   }
299   else
300   {
301     if (!noShowVLB) doBanner(false);
302     player->play();
303   }
304 }
305
306 void VVideoLive::stop(int noRemoveVLB)
307 {
308   if (unavailable) return;
309   if (!noRemoveVLB && VLiveBanner::getInstance()) viewman->removeView(VLiveBanner::getInstance()); // if live banner is present, remove it. won't cause damage if its not present
310
311   player->stop();
312   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay starts here due to time taken by plugin to stop");
313   vdr->stopStreaming();
314   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay ends here due to time taken by plugin to stop");
315 }
316
317 UINT VVideoLive::upChannel()
318 {
319   if (currentChannel == (chanList->size() - 1)) // at the end
320     return 0; // so go to start
321   else
322     return currentChannel + 1;
323 }
324
325 UINT VVideoLive::downChannel()
326 {
327   if (currentChannel == 0) // at the start
328     return chanList->size() - 1; // so go to end
329   else
330     return currentChannel - 1;
331 }
332
333 UINT VVideoLive::channelIndexFromNumber(int number)
334 {
335   for(UINT i = 0; i < chanList->size(); i++)
336   {
337     if ((*chanList)[i]->number == (UINT)number) return i;
338   }
339   return 0;
340 }
341
342 UINT VVideoLive::getCurrentChannelIndex()
343 {
344   return channelIndexFromNumber(currentChannel);
345 }
346
347 void VVideoLive::showEPG()
348 {
349   if (unavailable) showUnavailable(0);
350
351   Video::getInstance()->setMode(Video::QUARTER);
352   Video::getInstance()->setPosition(170, 5); //TODO need to deal with 4:3 switching
353
354   vepg = new VEpg(this, currentChannel);
355   vepg->draw();
356
357   viewman->add(vepg);
358   viewman->updateView(vepg);
359 }
360
361 void VVideoLive::setEpgMode(bool mode)
362 {
363   epgmode = mode;
364
365   // Ok so we do need this function
366   // but FIXME improve this, integrate with live mode switching from remote
367   if (mode == FALSE)
368   {
369     Video::getInstance()->setMode(videoMode);
370   }
371 }