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