]> git.vomp.tv Git - vompclient-marten.git/blob - vlivebanner.cc
Prev channel and prebuffering osd fixes
[vompclient-marten.git] / vlivebanner.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "vlivebanner.h"
22
23 #include "vvideolive.h"
24 #include "remote.h"
25 #include "colour.h"
26 #include "video.h"
27 #include "event.h"
28 #include "vinfo.h"
29 #include "boxstack.h"
30 #include "i18n.h"
31 #include "timers.h"
32 #include "channel.h"
33 #include "command.h"
34
35 VLiveBanner* VLiveBanner::instance = NULL;
36
37 VLiveBanner::VLiveBanner(VVideoLive* tvvideoLive, Channel* channel, bool bannerTakesCommands)
38 {
39   instance = this;
40   eventList = NULL;
41   vvideoLive = tvvideoLive;
42   takeCommands = bannerTakesCommands;
43
44   clockRegion.x = 440;
45   clockRegion.y = 0;
46   clockRegion.w = 60;
47   clockRegion.h = 30;
48
49   setSize(500, 120);
50   createBuffer();
51   if (Video::getInstance()->getFormat() == Video::PAL)
52   {
53     setPosition(124, 410);
54   }
55   else
56   {
57     setPosition(114, 320);
58   }
59
60
61   setTitleBarOn(1);
62   setTitleBarColour(Colour::TITLEBARBACKGROUND);
63
64   sl.setPosition(0, 30);
65   sl.setSize(area.w, area.h - 60);
66   sl.setNoLoop();
67   add(&sl);
68
69   setChannel(channel);
70 }
71
72 VLiveBanner::~VLiveBanner()
73 {
74   instance = NULL;
75   Timers::getInstance()->cancelTimer(this, 1);
76   Timers::getInstance()->cancelTimer(this, 2);
77   delData();
78 }
79
80 VLiveBanner* VLiveBanner::getInstance()
81 {
82   return instance;
83 }
84
85 void VLiveBanner::delData()
86 {
87   if (eventList)
88   {
89     int eventListSize = eventList->size();
90     for(int i = 0; i < eventListSize; i++)
91     {
92       delete (*eventList)[i];
93     }
94     eventList->clear();
95     delete eventList;
96
97   }
98   sl.clear();
99 }
100
101 void VLiveBanner::setChannel(Channel* tChannel)
102 {
103   delData();
104   currentChannel = tChannel;
105   // get the data
106
107   int numberWidth = (int)VDR::getInstance()->getChannelNumberWidth();
108
109   char ttitleText[100];
110   SNPRINTF(ttitleText, 99, "%0*lu - %s", numberWidth, currentChannel->number, currentChannel->name);
111
112   setTitleText(ttitleText);
113   eventList = VDR::getInstance()->getChannelSchedule(currentChannel->number);
114
115   if (!eventList)
116   {
117     sl.addOption(tr("No channel data available"), 0, 1);
118   }
119   else
120   {
121     sort(eventList->begin(), eventList->end(), EventSorter());
122
123     char tempString[300];
124     char tempString2[300];
125     struct tm* btime;
126     Event* event;
127     int first = 1;
128     int eventListSize = eventList->size();
129     for(int i = 0; i < eventListSize; i++)
130     {
131       event = (*eventList)[i];
132
133       //btime = localtime((time_t*)&event->time);
134       time_t etime = event->time;
135       btime = localtime(&etime);
136 #ifndef _MSC_VER
137       strftime(tempString2, 299, "%0H:%0M ", btime);
138 #else
139       strftime(tempString2, 299, "%H:%M ", btime);
140 #endif
141       SNPRINTF(tempString, 299, "%s %s", tempString2, event->title);
142       sl.addOption(tempString, (ULONG)event, first);
143       first = 0;
144     }
145   }
146
147   // Reset the timer as it probably took 1-2 seconds to change the channel
148   Timers::getInstance()->setTimerD(this, 1, 4);
149 }
150
151 void VLiveBanner::draw()
152 {
153   TBBoxx::draw();
154   rectangle(0, area.h - 30, area.w, 30, titleBarColour);
155
156   rectangle(7, area.h - 24, 18, 16, Colour::RED);
157   drawText(tr("EPG"), 32, area.h - 25, Colour::LIGHTTEXT);
158
159   rectangle(110, area.h - 24, 18, 16, Colour::GREEN);
160   drawText(tr("info"), 135, area.h - 25, Colour::LIGHTTEXT);
161
162   drawClock();
163 }
164
165 int VLiveBanner::handleCommand(int command)
166 {
167   switch (command)
168   {
169     case Remote::OK:
170     case Remote::BACK:
171     {
172       Timers::getInstance()->cancelTimer(this, 1); // if it exists
173       return 4;
174     }
175     case Remote::DF_UP:
176     {
177       if (!takeCommands) return 0; // banner was auto, old remote
178     } // else drop through
179     case Remote::UP:
180     {
181       sl.up();
182       sl.draw();
183
184       BoxStack::getInstance()->update(this);
185
186       // Arrows pressed, go to an 8s timer
187       Timers::getInstance()->setTimerD(this, 1, 8);
188
189       return 2;
190     }
191     case Remote::DF_DOWN:
192     {
193       if (!takeCommands) return 0; // banner was auto, old remote
194     } // else drop through
195     case Remote::DOWN:
196     {
197       sl.down();
198       sl.draw();
199
200       BoxStack::getInstance()->update(this);
201
202       // Arrows pressed, go to an 8s timer
203       Timers::getInstance()->setTimerD(this, 1, 8);
204
205       return 2;
206     }
207     case Remote::CHANNELUP:
208     {
209       // cancel timer so this view is still here later
210       Timers::getInstance()->cancelTimer(this, 1); // if it exists
211       vvideoLive->channelChange(VVideoLive::OFFSET, VVideoLive::UP);
212       return 2;
213     }
214     case Remote::CHANNELDOWN:
215     {
216       // cancel timer so this view is still here later
217       Timers::getInstance()->cancelTimer(this, 1); // if it exists
218       vvideoLive->channelChange(VVideoLive::OFFSET, VVideoLive::DOWN);
219       return 2;
220     }
221     case Remote::GREEN:
222     case Remote::MENU:
223     {
224       if (!eventList) return 2;
225       Event* event = (Event*)sl.getCurrentOptionData();
226       Log::getInstance()->log("VLiveBanner", Log::DEBUG, "Found the option you pointed at. %s", event->title);
227       // First, cancel my delete timer
228       Timers::getInstance()->cancelTimer(this, 1); // if it exists
229
230       VInfo* vi = new VInfo();
231       vi->setTitleText(event->title);
232       vi->setBorderOn(1);
233       vi->setExitable();
234       if (event->description) vi->setMainText(event->description);
235       else vi->setMainText(tr("Summary unavailable"));
236       if (Video::getInstance()->getFormat() == Video::PAL)
237       {
238         vi->setPosition(120, 130);
239       }
240       else
241       {
242         vi->setPosition(110, 90);
243       }
244       vi->setSize(510, 270);
245       vi->createBuffer();
246       vi->draw();
247
248       BoxStack::getInstance()->add(vi);
249       BoxStack::getInstance()->update(vi);
250
251       return 2;
252     }
253     case Remote::GUIDE:
254     case Remote::RED:
255     {
256       // full epg
257       Timers::getInstance()->cancelTimer(this, 1); // if it exists
258       Message* m = new Message(); // Must be done after this view deleted
259       m->message = Message::EPG;
260       m->to = vvideoLive;
261       m->from = this;
262       Command::getInstance()->postMessageNoLock(m);
263       return 4;
264     }
265   }
266
267   return 1;
268 }
269
270 void VLiveBanner::timercall(int clientReference)
271 {
272   if (clientReference == 1)
273   {
274     // delete me!
275     Message* m = new Message();  // Delete self
276     m->message = Message::CLOSE_ME;
277     m->to = BoxStack::getInstance();
278     m->from = this;
279     Command::getInstance()->postMessageFromOuterSpace(m);
280   }
281   else if (clientReference == 2)
282   {
283     // redraw clock
284     drawClock();
285     Message* m = new Message();
286     m->message = Message::REDRAW;
287     m->to = BoxStack::getInstance();
288     m->from = this;
289     m->parameter = (ULONG)&clockRegion;
290     Command::getInstance()->postMessageFromOuterSpace(m);
291   }
292 }
293
294 void VLiveBanner::drawClock()
295 {
296   // Blank the area first
297   rectangle(area.w - 60, 0, 60, 30, titleBarColour);
298
299   char timeString[20];
300   time_t t;
301   time(&t);
302   struct tm* tms = localtime(&t);
303   strftime(timeString, 19, "%H:%M", tms);
304   drawTextRJ(timeString, 490, 5, Colour::LIGHTTEXT);
305
306   time_t dt = 60 - (t % 60);  // seconds to the next minute
307   if (dt == 0) dt = 60; // advance a whole minute if necessary
308   dt += t;  // get a time_t value for it rather than using duration
309   // (so it will occur at the actual second and not second and a half)
310
311   Timers::getInstance()->setTimerT(this, 2, dt);
312 }
313
314 void VLiveBanner::processMessage(Message* m)
315 {
316   if (m->message == Message::MOUSE_MOVE)
317   {
318     if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
319     {
320       sl.draw();
321       BoxStack::getInstance()->update(this);
322     }
323   }
324   else if (m->message == Message::MOUSE_LBDOWN)
325   {
326     //check if press is outside this view! then simulate cancel
327     int x=(m->parameter>>16)-getScreenX();
328     int y=(m->parameter&0xFFFF)-getScreenY();
329     if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
330     {
331       BoxStack::getInstance()->handleCommand(Remote::BACK); //simulate cancel press
332     }
333     else if (y>=(int)area.h-24 && y<=(int)area.h-6)
334     {
335       //y coordinate is right!
336       if (x>=7 &&x<=25)
337       {
338         BoxStack::getInstance()->handleCommand(Remote::RED); //simulate red press
339       }
340       else if (x>=110 &&x<=128)
341       {
342         BoxStack::getInstance()->handleCommand(Remote::GREEN); //simulate red press
343       }
344     }
345   }
346 }