]> git.vomp.tv Git - vompclient.git/blob - vvideolive.cc
Connection failure detection
[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(), 0, 1);
42   else                          player = new Player(Command::getInstance(), 0, 0);
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::PLAY:
72     {
73       if (!unavailable) player->play(); // do resync
74       return 2;
75     }
76     case Remote::PAUSE:
77     {
78       if (!unavailable) player->resyncAudio(); // do resync2
79       return 2;
80     }
81
82     case Remote::STOP:
83     case Remote::BACK:
84     case Remote::MENU:
85     {
86       if (unavailable) showUnavailable(0);
87       else stop();
88
89       vchannelList->highlightChannel((*chanList)[currentChannel]);
90       return 4;
91     }
92     // Take up and down from new remote and do live banner
93     case Remote::UP:
94     case Remote::DOWN:
95     {
96       doBanner(true);
97       return 2;
98     }
99     case Remote::DF_UP:
100     case Remote::CHANNELUP:
101     {
102       if (unavailable) showUnavailable(0);
103       else stop();
104       channelChange(OFFSET, UP);
105       return 2;
106     }
107     case Remote::DF_DOWN:
108     case Remote::CHANNELDOWN:
109     {
110       if (unavailable) showUnavailable(0);
111       else stop();
112       channelChange(OFFSET, DOWN);
113       return 2;
114     }
115     case Remote::PREVCHANNEL:
116     {
117       if (unavailable) showUnavailable(0);
118       else stop();
119       channelChange(PREVIOUS, 0);
120       return 2;
121     }
122     case Remote::OK:
123     {
124       doBanner(true);
125       return 2;
126     }
127     case Remote::GUIDE:
128     case Remote::RED:
129     {
130       showEPG();
131       return 2;
132     }
133     case Remote::FULL:
134     case Remote::TV:
135     {
136       toggleChopSides();
137       return 2;
138     }
139
140     case Remote::ZERO ... Remote::NINE:
141     {
142       VChannelSelect* v = new VChannelSelect(this, command);
143       v->draw();
144       viewman->add(v);
145       viewman->updateView(v);
146       return 2;
147     }
148   }
149
150   return 1;
151 }
152
153 void VVideoLive::channelChange(UCHAR changeType, UINT newData)
154 {
155   UINT newChannel = 0;
156
157   if (changeType == INDEX)
158   {
159     newChannel = newData;
160   }
161   else if (changeType == NUMBER)
162   {
163     UINT i;
164     for(i = 0; i < chanList->size(); i++)
165     {
166       if ((*chanList)[i]->number == (UINT)newData)
167       {
168         newChannel = i;
169         break;
170       }
171     }
172
173     if (i == chanList->size())
174     {
175       doNoSuchChannel();
176       return;
177     }
178   }
179   else if (changeType == OFFSET)
180   {
181     if (newData == UP) newChannel = upChannel();
182     else newChannel = downChannel();
183   }
184   else if (changeType == PREVIOUS)
185   {
186     newChannel = previousChannel;
187   }
188   else
189   {
190     return; // bad input!
191   }
192
193   previousChannel = currentChannel;
194   currentChannel = newChannel;
195
196   if (unavailable) showUnavailable(0);
197   else stop(1);
198
199   VEpg* vepg = VEpg::getInstance();
200   if(vepg) vepg->setCurrentChannel((*chanList)[currentChannel]->name);
201
202   VLiveBanner* vlb = VLiveBanner::getInstance();
203   if (vlb)
204   {
205     vlb->setChannel((*chanList)[currentChannel]);
206     vlb->draw();
207     viewman->updateView(vlb);
208   }
209
210   play();
211 }
212
213 void VVideoLive::streamEnd()
214 {
215   Log::getInstance()->log("VVideoLive", Log::DEBUG, "streamEnd");
216   stop(1);
217   showUnavailable(1);
218 }
219
220 void VVideoLive::processMessage(Message* m)
221 {
222   if (m->message == Message::CHANNEL_CHANGE)
223   {
224     channelChange(NUMBER, m->parameter);
225   }
226   else if (m->message == Message::EPG)
227   {
228     Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG requested from live banner");
229     showEPG();
230   }
231   else if (m->message == Message::EPG_CLOSE)
232   {
233     video->setMode(videoMode);
234     if (saveUnavailable) showUnavailable(1);
235   }
236 }
237
238 void VVideoLive::doBanner(bool bannerTakesCommands)
239 {
240   if (VEpg::getInstance()) return;
241
242   if (VLiveBanner::getInstance()) return; // there already is one
243
244   VLiveBanner* vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
245
246   vlb->draw();
247   viewman->add(vlb);
248   viewman->updateView(vlb);
249 }
250
251 void VVideoLive::doNoSuchChannel()
252 {
253   Log::getInstance()->log("VVideoLive", Log::ERR, "No such channel");
254   // FIXME do gui for this
255 }
256
257 void VVideoLive::showUnavailable(int active)
258 {
259   if (active == unavailable) return;
260
261   if (active)
262   {
263     unavailable = 1;
264
265     unavailableView = new VInfo();
266     unavailableView->create(400, 200);
267     if (video->getFormat() == Video::PAL)
268     {
269       unavailableView->setScreenPos(170, 200);
270     }
271     else
272     {
273       unavailableView->setScreenPos(160, 150);
274     }
275     unavailableView->setTitleText((*chanList)[currentChannel]->name);
276     unavailableView->setOneLiner(tr("Channel unavailable"));
277     unavailableView->setDropThrough();
278     unavailableView->draw();
279     viewman->add(unavailableView);
280     viewman->updateView(unavailableView);
281   }
282   else
283   {
284     unavailable = 0;
285     viewman->removeView(unavailableView);
286     unavailableView = NULL;
287   }
288 }
289
290 void VVideoLive::play(int noShowVLB)
291 {
292   showUnavailable(0);
293
294   int available = vdr->streamChannel((*chanList)[currentChannel]->number);
295
296   if (!available)
297   {
298     if (!noShowVLB) doBanner(false);
299     showUnavailable(1);
300     if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
301   }
302   else
303   {
304     if (!noShowVLB) doBanner(false);
305     player->play();
306   }
307 }
308
309 void VVideoLive::stop(int noRemoveVLB)
310 {
311   if (unavailable) return;
312   if (!noRemoveVLB && VLiveBanner::getInstance()) viewman->removeView(VLiveBanner::getInstance()); // if live banner is present, remove it. won't cause damage if its not present
313
314   player->stop();
315   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay starts here due to time taken by plugin to stop");
316   vdr->stopStreaming();
317   if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
318   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay ends here due to time taken by plugin to stop");
319 }
320
321 UINT VVideoLive::upChannel()
322 {
323   if (currentChannel == (chanList->size() - 1)) // at the end
324     return 0; // so go to start
325   else
326     return currentChannel + 1;
327 }
328
329 UINT VVideoLive::downChannel()
330 {
331   if (currentChannel == 0) // at the start
332     return chanList->size() - 1; // so go to end
333   else
334     return currentChannel - 1;
335 }
336
337 void VVideoLive::showEPG()
338 {
339   saveUnavailable = unavailable;
340   if (unavailable) showUnavailable(0);
341
342   if (VEpg::getInstance()) return; // already showing!
343
344   video->setMode(Video::QUARTER);
345   video->setPosition(170, 5); //TODO need to deal with 4:3 switching
346
347   VEpg* vepg = new VEpg(this, currentChannel);
348   vepg->draw();
349
350   viewman->add(vepg);
351   viewman->updateView(vepg);
352 }
353
354 void VVideoLive::toggleChopSides()
355 {
356   if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
357
358   if (videoMode == Video::NORMAL)
359   {
360     videoMode = Video::LETTERBOX;
361     video->setMode(Video::LETTERBOX);
362   }
363   else
364   {
365     videoMode = Video::NORMAL;
366     video->setMode(Video::NORMAL);
367   }
368 }