]> git.vomp.tv Git - vompclient.git/blob - vvideolive.cc
Bug fix 2 for duplicating epg rows
[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:
141     case Remote::ONE:
142     case Remote::TWO:
143     case Remote::THREE:
144     case Remote::FOUR:
145     case Remote::FIVE:
146     case Remote::SIX:
147     case Remote::SEVEN:
148     case Remote::EIGHT:
149     case Remote::NINE:
150     {
151       VChannelSelect* v = new VChannelSelect(this, command);
152       v->draw();
153       viewman->add(v);
154       viewman->updateView(v);
155       return 2;
156     }
157   }
158
159   return 1;
160 }
161
162 void VVideoLive::channelChange(UCHAR changeType, UINT newData)
163 {
164   UINT newChannel = 0;
165
166   if (changeType == INDEX)
167   {
168     newChannel = newData;
169   }
170   else if (changeType == NUMBER)
171   {
172     UINT i;
173     for(i = 0; i < chanList->size(); i++)
174     {
175       if ((*chanList)[i]->number == (UINT)newData)
176       {
177         newChannel = i;
178         break;
179       }
180     }
181
182     if (i == chanList->size())
183     {
184       doNoSuchChannel();
185       return;
186     }
187   }
188   else if (changeType == OFFSET)
189   {
190     if (newData == UP) newChannel = upChannel();
191     else newChannel = downChannel();
192   }
193   else if (changeType == PREVIOUS)
194   {
195     newChannel = previousChannel;
196   }
197   else
198   {
199     return; // bad input!
200   }
201
202   previousChannel = currentChannel;
203   currentChannel = newChannel;
204
205   if (unavailable) showUnavailable(0);
206   else stop(1);
207
208   VEpg* vepg = VEpg::getInstance();
209   if(vepg) vepg->setCurrentChannel((*chanList)[currentChannel]->name);
210
211   VLiveBanner* vlb = VLiveBanner::getInstance();
212   if (vlb)
213   {
214     vlb->setChannel((*chanList)[currentChannel]);
215     vlb->draw();
216     viewman->updateView(vlb);
217   }
218
219   play();
220 }
221
222 void VVideoLive::streamEnd()
223 {
224   Log::getInstance()->log("VVideoLive", Log::DEBUG, "streamEnd");
225   stop(1);
226   showUnavailable(1);
227 }
228
229 void VVideoLive::processMessage(Message* m)
230 {
231   if (m->message == Message::CHANNEL_CHANGE)
232   {
233     channelChange(NUMBER, m->parameter);
234   }
235   else if (m->message == Message::EPG)
236   {
237     Log::getInstance()->log("VVideoLive", Log::DEBUG, "EPG requested from live banner");
238     showEPG();
239   }
240   else if (m->message == Message::EPG_CLOSE)
241   {
242     video->setMode(videoMode);
243     if (saveUnavailable) showUnavailable(1);
244   }
245 }
246
247 void VVideoLive::doBanner(bool bannerTakesCommands)
248 {
249   if (VEpg::getInstance()) return;
250
251   if (VLiveBanner::getInstance()) return; // there already is one
252
253   VLiveBanner* vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
254
255   vlb->draw();
256   viewman->add(vlb);
257   viewman->updateView(vlb);
258 }
259
260 void VVideoLive::doNoSuchChannel()
261 {
262   Log::getInstance()->log("VVideoLive", Log::ERR, "No such channel");
263   // FIXME do gui for this
264 }
265
266 void VVideoLive::showUnavailable(int active)
267 {
268   if (active == unavailable) return;
269
270   if (active)
271   {
272     unavailable = 1;
273
274     unavailableView = new VInfo();
275     unavailableView->create(400, 200);
276     if (video->getFormat() == Video::PAL)
277     {
278       unavailableView->setScreenPos(170, 200);
279     }
280     else
281     {
282       unavailableView->setScreenPos(160, 150);
283     }
284     unavailableView->setTitleText((*chanList)[currentChannel]->name);
285     unavailableView->setOneLiner(tr("Channel unavailable"));
286     unavailableView->setDropThrough();
287     unavailableView->draw();
288     viewman->add(unavailableView);
289     viewman->updateView(unavailableView);
290   }
291   else
292   {
293     unavailable = 0;
294     viewman->removeView(unavailableView);
295     unavailableView = NULL;
296   }
297 }
298
299 void VVideoLive::play(int noShowVLB)
300 {
301   showUnavailable(0);
302
303   int available = vdr->streamChannel((*chanList)[currentChannel]->number);
304
305   if (!available)
306   {
307     if (!noShowVLB) doBanner(false);
308     showUnavailable(1);
309     if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
310   }
311   else
312   {
313     if (!noShowVLB) doBanner(false);
314     player->play();
315   }
316 }
317
318 void VVideoLive::stop(int noRemoveVLB)
319 {
320   if (unavailable) return;
321   if (!noRemoveVLB && VLiveBanner::getInstance()) viewman->removeView(VLiveBanner::getInstance()); // if live banner is present, remove it. won't cause damage if its not present
322
323   player->stop();
324   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay starts here due to time taken by plugin to stop");
325   vdr->stopStreaming();
326   if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
327   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay ends here due to time taken by plugin to stop");
328 }
329
330 UINT VVideoLive::upChannel()
331 {
332   if (currentChannel == (chanList->size() - 1)) // at the end
333     return 0; // so go to start
334   else
335     return currentChannel + 1;
336 }
337
338 UINT VVideoLive::downChannel()
339 {
340   if (currentChannel == 0) // at the start
341     return chanList->size() - 1; // so go to end
342   else
343     return currentChannel - 1;
344 }
345
346 void VVideoLive::showEPG()
347 {
348   saveUnavailable = unavailable;
349   if (unavailable) showUnavailable(0);
350
351   if (VEpg::getInstance()) return; // already showing!
352
353   video->setMode(Video::QUARTER);
354   video->setPosition(170, 5); //TODO need to deal with 4:3 switching
355
356   VEpg* vepg = new VEpg(this, currentChannel);
357   vepg->draw();
358
359   viewman->add(vepg);
360   viewman->updateView(vepg);
361 }
362
363 void VVideoLive::toggleChopSides()
364 {
365   if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
366
367   if (videoMode == Video::NORMAL)
368   {
369     videoMode = Video::LETTERBOX;
370     video->setMode(Video::LETTERBOX);
371   }
372   else
373   {
374     videoMode = Video::NORMAL;
375     video->setMode(Video::NORMAL);
376   }
377 }