]> git.vomp.tv Git - vompclient.git/blob - vvideolive.cc
Fixes (1) for new frame number navigation
[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(), false, true);
42   else                          player = new Player(Command::getInstance(), 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 }
247
248 void VVideoLive::doBanner(bool bannerTakesCommands)
249 {
250   if (VEpg::getInstance()) return;
251
252   if (VLiveBanner::getInstance()) return; // there already is one
253
254   VLiveBanner* vlb = new VLiveBanner(this, (*chanList)[currentChannel], bannerTakesCommands);
255
256   vlb->draw();
257   viewman->add(vlb);
258   viewman->updateView(vlb);
259 }
260
261 void VVideoLive::doNoSuchChannel()
262 {
263   Log::getInstance()->log("VVideoLive", Log::ERR, "No such channel");
264   // FIXME do gui for this
265 }
266
267 void VVideoLive::showUnavailable(int active)
268 {
269   if (active == unavailable) return;
270
271   if (active)
272   {
273     unavailable = 1;
274
275     unavailableView = new VInfo();
276     unavailableView->create(400, 200);
277     if (video->getFormat() == Video::PAL)
278     {
279       unavailableView->setScreenPos(170, 200);
280     }
281     else
282     {
283       unavailableView->setScreenPos(160, 150);
284     }
285     unavailableView->setTitleText((*chanList)[currentChannel]->name);
286     unavailableView->setOneLiner(tr("Channel unavailable"));
287     unavailableView->setDropThrough();
288     unavailableView->draw();
289     viewman->add(unavailableView);
290     viewman->updateView(unavailableView);
291   }
292   else
293   {
294     unavailable = 0;
295     viewman->removeView(unavailableView);
296     unavailableView = NULL;
297   }
298 }
299
300 void VVideoLive::play(int noShowVLB)
301 {
302   showUnavailable(0);
303
304   int available = vdr->streamChannel((*chanList)[currentChannel]->number);
305
306   if (!available)
307   {
308     if (!noShowVLB) doBanner(false);
309     showUnavailable(1);
310     if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
311   }
312   else
313   {
314     if (!noShowVLB) doBanner(false);
315     player->play();
316   }
317 }
318
319 void VVideoLive::stop(int noRemoveVLB)
320 {
321   if (unavailable) return;
322   if (!noRemoveVLB && VLiveBanner::getInstance()) viewman->removeView(VLiveBanner::getInstance()); // if live banner is present, remove it. won't cause damage if its not present
323
324   player->stop();
325   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay starts here due to time taken by plugin to stop");
326   vdr->stopStreaming();
327   if (!vdr->isConnected()) { Command::getInstance()->connectionLost(); return; }
328   Log::getInstance()->log("VVideoLive", Log::DEBUG, "Delay ends here due to time taken by plugin to stop");
329 }
330
331 UINT VVideoLive::upChannel()
332 {
333   if (currentChannel == (chanList->size() - 1)) // at the end
334     return 0; // so go to start
335   else
336     return currentChannel + 1;
337 }
338
339 UINT VVideoLive::downChannel()
340 {
341   if (currentChannel == 0) // at the start
342     return chanList->size() - 1; // so go to end
343   else
344     return currentChannel - 1;
345 }
346
347 void VVideoLive::showEPG()
348 {
349   saveUnavailable = unavailable;
350   if (unavailable) showUnavailable(0);
351
352   if (VEpg::getInstance()) return; // already showing!
353
354   video->setMode(Video::QUARTER);
355   video->setPosition(170, 5); //TODO need to deal with 4:3 switching
356
357   VEpg* vepg = new VEpg(this, currentChannel);
358   vepg->draw();
359
360   viewman->add(vepg);
361   viewman->updateView(vepg);
362 }
363
364 void VVideoLive::toggleChopSides()
365 {
366   if (video->getTVsize() == Video::ASPECT16X9) return; // Means nothing for 16:9 TVs
367
368   if (videoMode == Video::NORMAL)
369   {
370     videoMode = Video::LETTERBOX;
371     video->setMode(Video::LETTERBOX);
372   }
373   else
374   {
375     videoMode = Video::NORMAL;
376     video->setMode(Video::NORMAL);
377   }
378 }