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