]> git.vomp.tv Git - vompclient.git/blob - vepglistadvanced.cc
Fix leak in picture handling of osdvector, add static fallback pictures, some default...
[vompclient.git] / vepglistadvanced.cc
1 /*
2     Copyright 2004-2007 Chris Tallon, 2014 Marten Richter
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 "vepglistadvanced.h"
22
23 #include "boxstack.h"
24 #include "remote.h"
25 #include "wsymbol.h"
26 #include "boxstack.h"
27 #include "vdr.h"
28 #include "colour.h"
29 #include "video.h"
30 #include "i18n.h"
31 #include "command.h"
32 #include "log.h"
33 #include "movieinfo.h"
34 #include "seriesinfo.h"
35 #include "event.h"
36 #include "channel.h"
37 #include "vepgsummary.h"
38 #include "vepgsettimer.h"
39 #include "vepg.h"
40 #include "staticartwork.h"
41
42 #include <sstream>
43
44
45 VEpgListAdvanced::VEpgListAdvanced(VVideoLiveTV *tvideolive, ChannelList* tchanList,ULONG initialChannelNumber)
46 {
47         channelNumber = initialChannelNumber;
48         chanList = tchanList;
49         videolive = tvideolive;
50         boxstack = BoxStack::getInstance();
51
52         mode = OneChannel;
53
54         setSize(640+40, 500+40); //old   setSize(570, 420);
55         createBuffer();
56
57         setPosition(20, 20);
58
59         setTitleBarOn(1);
60         setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
61         TVMediaInfo *info= new TVMediaInfo();
62         info->setChannelLogo(channelNumber);
63         info->setStaticFallback(sa_tv);
64         setTitleBarIcon(info);
65
66         sl.setPosition(10, 30 + 5);
67         sl.setSize(area.w*42/100 - 20, area.h - 30 - 15 - 30);
68         sl.setLinesPerOption(2.4f);
69         add(&sl);
70
71         Region slarea=sl.getRegionR();
72
73         epg.setParaMode(true);
74         epg.setPosition(slarea.x  +slarea.w+10 ,30+5);
75         epg.setSize(area.w -slarea.x -slarea.w -10, area.h - 30 - 15 - 30);
76         add(&epg);
77         epg.setText("");
78         epg.setVideoBackground();
79         epg.setBackgroundColour(DrawStyle::VIEWTRANSPARENTBACKGROUND);
80
81         epgTVmedia.setPosition(epg.getRegionR().w-100-10,10);
82         epgTVmedia.setSize(100,150/Osd::getInstance()->getPixelAspect());
83         epg.add(&epgTVmedia);
84
85         boxRed.setBackgroundColour(DrawStyle::RED);
86         boxRed.setPosition(165 /*54*/, sl.getY2()+8);
87         boxRed.setSize(18, 16);
88         add(&boxRed);
89
90         textRed.setPosition(boxRed.getX2(), sl.getY2()+4);
91         textRed.setSize(116, 30);
92
93         add(&textRed);
94
95         boxGreen.setBackgroundColour(DrawStyle::GREEN);
96         boxGreen.setPosition(165 +1*110, sl.getY2()+8);
97         boxGreen.setSize(18, 16);
98         add(&boxGreen);
99
100         textGreen.setPosition(boxGreen.getX2(), sl.getY2()+4);
101         textGreen.setSize(116, 30);
102         add(&textGreen);
103
104         boxYellow.setBackgroundColour(DrawStyle::YELLOW);
105         boxYellow.setPosition(165 +2*110, sl.getY2()+8);
106         boxYellow.setSize(18, 16);
107         add(&boxYellow);
108
109         textYellow.setPosition(boxYellow.getX2(), sl.getY2()+4);
110         textYellow.setSize(116, 30);
111         add(&textYellow);
112
113         boxBlue.setBackgroundColour(DrawStyle::BLUE);
114         boxBlue.setPosition(165 +3*110, sl.getY2()+8);
115         boxBlue.setSize(18, 16);
116         add(&boxBlue);
117
118         textBlue.setPosition(boxBlue.getX2(), sl.getY2()+4);
119         textBlue.setSize(116, 30);
120         add(&textBlue);
121
122         setButtonText();
123
124
125         updateEpgDataChannel();
126 }
127
128 VEpgListAdvanced::~VEpgListAdvanced()
129 {
130         clearEventList();
131 }
132
133
134 void VEpgListAdvanced::setButtonText()
135 {
136         switch (mode)
137         {
138         case OneChannel: {
139                 textRed.setText(tr("Record"));
140                 textGreen.setText(tr("Now"));
141                 textYellow.setText(tr("Next"));
142                 textBlue.setText(tr("Guide"));
143
144         } break;
145         case Now: {
146                 textRed.setText(tr("Record"));
147                 textGreen.setText(tr("Next"));
148                 textYellow.setText(tr("Schedule"));
149                 textBlue.setText(tr("Switch"));
150         } break;
151         case Next: {
152                 textRed.setText(tr("Record"));
153                 textGreen.setText(tr("Now"));
154                 textYellow.setText(tr("Schedule"));
155                 textBlue.setText(tr("Switch"));
156         } break;
157
158         };
159 }
160
161 void VEpgListAdvanced::doRed()
162 {
163         doRecord();
164 }
165
166 void VEpgListAdvanced::doGreen()
167 {
168         switch (mode)
169         {
170         case Now: {
171                 doNext();
172         } break;
173         case OneChannel:
174         case Next: {
175                 doNow();
176         } break;
177         };
178 }
179
180 void VEpgListAdvanced::doYellow()
181 {
182         switch (mode)
183         {
184         case OneChannel: {
185                 doNext();
186         } break;
187         case Next:
188         case Now: {
189                 doProgramm();
190         } break;
191         };
192 }
193
194 void VEpgListAdvanced::doBlue()
195 {
196         switch (mode)
197         {
198         case OneChannel: {
199                 doGrid();
200         } break;
201         case Next:
202         case Now: {
203                 doSwitch();
204         } break;
205         };
206 }
207
208 void VEpgListAdvanced::doNext()
209 {
210         Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doNext");
211         if (mode!=OneChannel) {
212                 Channel * chan=(*chanList)[ sl.getCurrentOptionData()];
213                 channelNumber = chan->number;
214         }
215         mode=Next;
216         updateEpgDataNowNext(true);
217         setButtonText();
218         TVMediaInfo *info= new TVMediaInfo();
219         info->setStaticArtwork(sa_tv);
220         setTitleBarIcon(info);
221         draw(true);
222         boxstack->update(this);
223 }
224 void VEpgListAdvanced::doNow()
225 {
226         Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doNow");
227         if (mode!=OneChannel) {
228                 Channel * chan=(*chanList)[ sl.getCurrentOptionData()];
229                 channelNumber = chan->number;
230         }
231         mode=Now;
232         updateEpgDataNowNext(true);
233         setButtonText();
234         TVMediaInfo *info= new TVMediaInfo();
235         info->setStaticArtwork(sa_tv);
236         setTitleBarIcon(info);
237         draw(true);
238         boxstack->update(this);
239 }
240
241 void VEpgListAdvanced::doProgramm()
242 {
243         Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doProgram");
244         mode=OneChannel;
245
246         Channel * chan=(*chanList)[ sl.getCurrentOptionData()];
247         channelNumber = chan->number;
248         updateEpgDataChannel();
249         setButtonText();
250         TVMediaInfo *info= new TVMediaInfo();
251         info->setChannelLogo(channelNumber);
252         info->setStaticFallback(sa_tv);
253         setTitleBarIcon(info);
254         draw(true);
255         boxstack->update(this);
256 }
257
258 void VEpgListAdvanced::doSwitch()
259 {
260
261         if (videolive)
262         {
263                 if (mode!=OneChannel) {
264                         Channel * chan=(*chanList)[ sl.getCurrentOptionData()];
265                         channelNumber = chan->number;
266                 }
267                 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doSwitch %d", channelNumber);
268                 Message* m = new Message(); // Must be done after this view deleted
269                 m->from = this;
270                 m->to = videolive;
271                 m->message = Message::CHANNEL_CHANGE;
272                 m->parameter = channelNumber;
273                 m->tag = 0;
274                 Command::getInstance()->postMessageNoLock(m);
275         }
276 }
277
278 void VEpgListAdvanced::doRecord()
279 {
280         int channel;
281         Event* current = getCurrentOptionEvent(channel);
282         if (current)
283         {
284                 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "Found the option you pointed at. %s %d", current->title, current->id);
285                 unsigned int chanlistsize=chanList->size();
286                 Channel * chan;
287                 UINT listIndex;
288                 for(listIndex = 0; listIndex < chanlistsize; listIndex++)
289                 {
290                         chan = (*chanList)[listIndex];
291                         if (chan->number == channel) break;
292                 }
293
294                 Log::getInstance()->log("VEpgSummary", Log::DEBUG, "ID %lu TIME %lu DURATION %lu TITLE %s", current->id, current->time,
295                                 current->duration, current->title);
296                 VEpgSetTimer* vs = new VEpgSetTimer(current, chan);
297                 vs->draw();
298                 boxstack->add(vs);
299                 boxstack->update(vs);
300         }
301
302 }
303
304 void VEpgListAdvanced::doGrid()
305 {
306
307         if (mode!=OneChannel) {
308                 Channel * chan=(*chanList)[ sl.getCurrentOptionData()];
309                 channelNumber = chan->number;
310         }
311         UINT listIndex;
312         unsigned int chanlistsize=chanList->size();
313         Channel *chan;
314         for(listIndex = 0; listIndex < chanlistsize; listIndex++)
315         {
316                 chan = (*chanList)[listIndex];
317                 if (chan->number == channelNumber) break;
318         }
319
320         VEpg* vepg = new VEpg(videolive, listIndex, chanList);
321         vepg->draw();
322         boxstack->add(vepg);
323         boxstack->update(vepg);
324
325 }
326
327 void VEpgListAdvanced::clearEventList()
328 {
329         std::vector<EventList*>::iterator itty = eventLista.begin();
330         while (itty!= eventLista.end()) {
331                 if (*itty) {
332                         (*itty)->clear();
333                         delete (*itty);
334                 }
335                 itty++;
336         }
337         eventLista.clear();
338
339 }
340
341
342 /* Prototype
343  *
344  *   if (!chanList) return;
345   Channel* chan;
346   for(UINT listIndex = 0; listIndex < gridRows; listIndex++)
347   {
348     if(listTop + listIndex >= UINT(chanListbox.getBottomOption()))
349       continue;
350     chan = (*chanList)[listTop + listIndex];
351     eventLista[listIndex] = VDR::getInstance()->getChannelSchedule(chan->number, ltime - 1, window_width * 60 + 2); // ltime - 1 to get prog before window (allows cursor left past ltime). + 2 to get prog after window
352   }
353
354  */
355
356 void VEpgListAdvanced::updateEpgData()
357 {
358         switch (mode)
359         {
360         case OneChannel: {
361                 //updateEpgDataChannel();
362         } break;
363         case Next:
364         case Now: {
365                 updateEpgDataNowNext(false);
366         } break;
367         };
368
369 }
370
371 void VEpgListAdvanced::updateEpgDataNowNext(bool changeState)
372 {
373         int startupdate=0;
374         int endupdate=0;
375
376         unsigned int chanlistsize=chanList->size();
377         if (changeState) {
378                 clearEventList();
379                 eventLista.resize(chanList->size());
380                 Channel* chan;
381                 for(UINT listIndex = 0; listIndex < chanlistsize; listIndex++)
382                 {
383                         if (listIndex < 0) continue;
384                         if (listIndex >= chanlistsize) continue;
385                         chan = (*chanList)[listIndex];
386                         if (chan->number == channelNumber) {
387                                 startupdate = listIndex-sl.getNumOptionsDisplayable()-2;
388                                 endupdate = listIndex+sl.getNumOptionsDisplayable()+2;
389                                 break;
390                         }
391                 }
392         } else {
393                 startupdate=sl.getTopOption()-2;
394                 endupdate=sl.getBottomOption()+1;
395         }
396
397         time_t now;
398         time(&now);
399
400         Channel* chan;
401         for(int listIndex = startupdate; listIndex < endupdate; listIndex++)
402         {
403                 if (listIndex < 0) continue;
404                 if (listIndex >= chanlistsize) continue;
405
406             chan = (*chanList)[listIndex];
407                 if (!eventLista[listIndex]) eventLista[listIndex] = VDR::getInstance()->getChannelSchedule(chan->number, now, 4 * 60 *60);
408
409         }
410
411 }
412
413 void VEpgListAdvanced::updateEpgDataChannel()
414 {
415         clearEventList();
416         eventLista.resize(1);
417         time_t now;
418         time(&now);
419         eventLista[0] = VDR::getInstance()->getChannelSchedule(channelNumber, now, 24 * 60 *60 *30); // one month
420         Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "Eventlist %x %d", eventLista[0],channelNumber);
421
422 }
423
424 void VEpgListAdvanced::drawData(bool doIndexPop)
425 {
426         switch (mode)
427         {
428         case OneChannel: {
429                 drawDataChannel(doIndexPop);
430         } break;
431         case Next: {
432                 drawDataNowNext(true, doIndexPop);
433         } break;
434         case Now: {
435                 drawDataNowNext(false, doIndexPop);
436         } break;
437         };
438
439 }
440
441 void VEpgListAdvanced::drawDataChannel(bool doIndexPop)
442 {
443   int saveIndex = sl.getCurrentOption();
444   int saveTop = sl.getTopOption();
445   sl.clear();
446   sl.addColumn(0);
447   sl.addColumn(25 );
448   sl.addColumn(25 + 7);
449   sl.addColumn(25 + 7+ 7);
450   //sl.addColumn(118);
451
452   int first = 1;
453
454   char tempA[300]; // FIXME  this is guesswork!
455   char tempB[300]; // FIXME
456   char tempC[300]; // FIXME
457   struct tm* btime;
458
459
460
461   Event* currentEvent;
462   EventList::iterator j;
463   EventList* eventList = eventLista[0];
464   if (eventList) {
465           for (j = eventList->begin(); j != eventList->end(); j++)
466           {
467                   currentEvent = *j;
468                   time_t eventStartTime = (time_t)currentEvent->time;
469                   time_t eventEndTime = (time_t)(currentEvent->time + currentEvent->duration);
470
471                   btime = localtime(&eventStartTime);
472                   strftime(tempA, 299, "%d/%m/%y %H:%M ", btime);
473                   btime = localtime(&eventEndTime);
474                   strftime(tempB, 299, "- %H:%M ", btime);
475                   //#endif
476                   sprintf(tempC, "\t %s\n \t \t%s%s", currentEvent->title,tempA,tempB);
477                   // New TVMedia stuff
478                   TVMediaInfo *info= new TVMediaInfo();
479                   info->setPosterThumb(channelNumber, currentEvent->id);
480                   info->setStaticFallback(sa_defposter);
481                   currentEvent->index = sl.addOption(tempC, currentEvent->id, first, info);
482                   first = 0;
483           }
484   }
485
486   if (doIndexPop)
487   {
488     sl.hintSetCurrent(0);
489   }
490   else
491   {
492     sl.hintSetCurrent(saveIndex);
493     sl.hintSetTop(saveTop);
494   }
495   updateSelection();
496
497 }
498
499 void VEpgListAdvanced::drawDataNowNext(bool next, bool doIndexPop)
500 {
501   int saveIndex = sl.getCurrentOption();
502   int saveTop = sl.getTopOption();
503   sl.clear();
504   sl.addColumn(0);
505   sl.addColumn(42 );
506   sl.addColumn(160);
507
508   int first = 1;
509
510   char tempA[300]; // FIXME  this is guesswork!
511   char tempB[300]; // FIXME
512   char tempC[300]; // FIXME
513   struct tm* btime;
514
515
516
517   Event* currentEvent;
518   EventList::iterator j;
519   int minevents=1;
520   if (next) minevents++;
521   int setcurrenthelper =0;
522
523   unsigned int chanlistsize=chanList->size();
524   for(UINT listIndex = 0; listIndex < chanlistsize; listIndex++)
525   {
526           Channel* chan;
527           chan = (*chanList)[listIndex];
528
529           EventList* eventList = eventLista[listIndex];
530           if (eventList && eventList->size()>=minevents) {
531                   j = eventList->begin();
532
533                   currentEvent = j[minevents-1];
534                   time_t eventStartTime = (time_t)currentEvent->time;
535                   time_t eventEndTime = (time_t)(currentEvent->time + currentEvent->duration);
536
537                   btime = localtime(&eventStartTime);
538                   strftime(tempA, 299, "%H:%M ", btime);
539                   btime = localtime(&eventEndTime);
540                   strftime(tempB, 299, "- %H:%M ", btime);
541                   //#endif
542                   sprintf(tempC, "%s\n%s\t %s%s", currentEvent->title, chan->name,tempA,tempB);
543
544           } else {
545                   sprintf(tempC, "\n%s", chan->name);
546
547           }
548           TVMediaInfo *info= new TVMediaInfo();
549           if ((*chanList)[listIndex]->number == channelNumber) {
550                   first = 1;
551                   setcurrenthelper = listIndex;
552           }
553           info->setChannelLogo((*chanList)[listIndex]->number);
554           info->setStaticFallback(sa_tv);
555           currentEvent->index = sl.addOption(tempC, listIndex, first, info);
556           first = 0;
557   }
558
559   if (doIndexPop)
560   {
561     sl.hintSetCurrent(setcurrenthelper);
562   }
563   else
564   {
565     sl.hintSetCurrent(saveIndex);
566     sl.hintSetTop(saveTop);
567   }
568   updateSelection();
569 }
570
571 void VEpgListAdvanced::draw(bool doIndexPop)
572 {
573
574         // Single channel mode
575         switch (mode) {
576         case OneChannel: {
577                 char tempA[300];
578                  unsigned int chanlistsize=chanList->size();
579                  Channel * chan;
580                  UINT listIndex;
581                  for(listIndex = 0; listIndex < chanlistsize; listIndex++)
582                  {
583                          chan = (*chanList)[listIndex];
584                          if (chan->number == channelNumber) break;
585                  }
586                 sprintf(tempA, tr("Schedule - %s"), (*chanList)[listIndex]->name);
587                 setTitleText(tempA);
588         } break;
589         case Now: {
590                 setTitleText(tr("Now"));
591         } break;
592         case Next: {
593                 setTitleText(tr("Next"));
594         } break;
595         };
596
597
598
599         drawData(doIndexPop);
600
601         TBBoxx::draw();
602
603
604
605
606
607
608
609         char freeSpace[50];
610         struct tm* btime;
611         time_t now;
612         time(&now);
613         btime = localtime(&now);
614         strftime(freeSpace, 299, "%d/%m/%y", btime);
615
616         drawTextRJ(freeSpace, getWidth(), 5, DrawStyle::LIGHTTEXT);
617
618         // Symbols
619
620         WSymbol w;
621         TEMPADD(&w);
622         w.nextSymbol = WSymbol::UP;
623         w.setPosition(20, area.h-35);
624         w.draw();
625         w.nextSymbol = WSymbol::DOWN;
626         w.setPosition(50, area.h-35);
627         w.draw();
628         w.nextSymbol = WSymbol::SKIPBACK;
629         w.setPosition(85, area.h-35);
630         w.draw();
631         w.nextSymbol = WSymbol::SKIPFORWARD;
632         w.setPosition(115, area.h-35);
633         w.draw();
634
635         drawTextRJ(tr("[ok] = info"), 560+70, 385+80, DrawStyle::LIGHTTEXT);
636
637         // All static stuff done
638
639
640 }
641
642 Event* VEpgListAdvanced::getCurrentOptionEvent(int& channel)
643 {
644         // version for channel
645         Event* currentEvent = NULL;
646         EventList::iterator j;
647         EventList* eventList = NULL;
648         switch (mode)
649         {
650         case OneChannel: {
651                 eventList = eventLista[0];
652                 if (eventList) {
653                         channel = channelNumber;
654                         for (j = eventList->begin(); j != eventList->end(); j++)
655                         {
656                                 currentEvent = *j;
657                                 if (currentEvent->index == sl.getCurrentOption()) return currentEvent;
658                         }
659
660
661                 } break;
662         case Next: {
663                 eventList = eventLista[sl.getCurrentOptionData()];
664                 channel = (*chanList)[sl.getCurrentOptionData()]->number;
665
666
667                 if (eventList && eventList->size()>1) {
668                         j = eventList->begin();
669                         currentEvent = j[1];
670                 } else {
671                         currentEvent = NULL;
672                 }
673         } break;
674         case Now: {
675                 eventList = eventLista[sl.getCurrentOptionData()];
676                 channel = (*chanList)[sl.getCurrentOptionData()]->number;
677
678                 if (eventList && eventList->size()>0) {
679                         j = eventList->begin();
680                         currentEvent = j[0];
681                 } else {
682                         currentEvent = NULL;
683                 }
684         } break;
685         };
686
687
688   }
689   return currentEvent;
690 }
691
692
693
694 void VEpgListAdvanced::updateSelection()
695 {
696         updateEpgData();
697         int channel=0;
698         if (mode==OneChannel) {
699                 TVMediaInfo *info= new TVMediaInfo();
700                 info->setChannelLogo(channelNumber);
701                 info->setStaticFallback(sa_tv);
702                 setTitleBarIcon(info);
703         }
704         Event* toShow = getCurrentOptionEvent(channel);
705         if (toShow)
706         {
707                 toShow->loadinfos(channel);
708                 std::stringstream description;
709
710                 description << "\n"<< toShow->title  << "\n\n";
711                 description << toShow->subtitle <<"\n";
712                 description << toShow->description;
713
714                 TVMedia poster;
715                 poster.height=0;
716                 if (toShow->movieInfo) {
717                         poster=toShow->movieInfo->poster;
718                 }
719                 if (toShow->seriesInfo) {
720                         if (toShow->seriesInfo->seasonposter.height) {
721                                 poster=toShow->seriesInfo->seasonposter;
722                         }
723                         else if (toShow->seriesInfo->posters.size()) {
724                                 poster=toShow->seriesInfo->posters[0];
725                         }
726                 }
727                 if (poster.height) {
728                         epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
729                         epgTVmedia.setVisible(true);
730                 } else {
731                         if (toShow->epgImage)
732                         {
733                                 TVMediaInfo info;
734                                 info.setPosterThumb(channel,toShow->id);
735                                 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
736                                 epgTVmedia.setVisible(true);
737                         }else if (mode!=OneChannel) {
738                                 TVMediaInfo info;
739                                 info.setChannelLogo(channel);
740                                 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
741                                 epgTVmedia.setVisible(true);
742                         } else {
743                                 epgTVmedia.setVisible(false);
744                         }
745                 }
746
747                 epg.setText(description.str().c_str());
748         } else {
749                 epg.setText("");
750                 if (mode!=OneChannel) {
751                         TVMediaInfo info;
752                         info.setChannelLogo(channel);
753                         epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
754                         epgTVmedia.setVisible(true);
755                 } else {
756                         epgTVmedia.setVisible(false);
757                 }
758         }
759
760 }
761
762 int VEpgListAdvanced::handleCommand(int command)
763 {
764   switch(command)
765   {
766     case Remote::DF_UP:
767     case Remote::UP:
768     {
769       sl.up();
770       quickUpdate();
771
772       boxstack->update(this);
773       return 2;
774     }
775     case Remote::DF_DOWN:
776     case Remote::DOWN:
777     {
778       sl.down();
779       quickUpdate();
780
781       boxstack->update(this);
782       return 2;
783     }
784     case Remote::SKIPBACK:
785     {
786       sl.pageUp();
787       quickUpdate();
788
789       boxstack->update(this);
790       return 2;
791     }
792     case Remote::SKIPFORWARD:
793     {
794       sl.pageDown();
795       quickUpdate();
796
797       boxstack->update(this);
798       return 2;
799     }
800     case Remote::RED:
801     {
802         doRed();
803         return 2;
804     }
805     case Remote::GREEN:
806     {
807         doGreen();
808         return 2;
809     }
810     case Remote::YELLOW:
811     {
812         doYellow();
813         return 2;
814     }
815     case Remote::BLUE:
816     {
817         doBlue();
818         return 2;
819     }
820     case Remote::OK:
821     {
822       if (sl.getNumOptions() == 0) return 2;
823
824
825       int channel;
826       Event* current = getCurrentOptionEvent(channel);
827       if (current)
828       {
829           Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "Found the option you pointed at. %s %d", current->title, current->id);
830           unsigned int chanlistsize=chanList->size();
831           Channel * chan;
832           UINT listIndex;
833           for(listIndex = 0; listIndex < chanlistsize; listIndex++)
834           {
835                   chan = (*chanList)[listIndex];
836                   if (chan->number == channel) break;
837           }
838
839           VEpgSummary* vr = new VEpgSummary(current, (*chanList)[listIndex]);
840           vr->draw();
841           boxstack->add(vr);
842           boxstack->update(vr);
843
844           return 2;
845       }
846       // should not get to here
847       return 1;
848     }
849     case Remote::BACK:
850     {
851         return 4;
852     }
853   }
854   // stop command getting to any more views
855   return 1;
856 }
857
858 void VEpgListAdvanced::processMessage(Message* m)
859 {
860   Log::getInstance()->log("VEpgListAdvanced", Log::DEBUG, "Got message value %lu", m->message);
861
862   if (m->message == Message::MOUSE_MOVE)
863   {
864     if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
865     {
866       quickUpdate();
867       boxstack->update(this);
868     }
869   }
870   else if (m->message == Message::MOUSE_LBDOWN)
871   {
872     if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
873     {
874       boxstack->handleCommand(Remote::OK); //simulate OK press
875     }
876     else
877     {
878       //check if press is outside this view! then simulate cancel
879       int x=(m->parameter>>16)-getScreenX();
880       int y=(m->parameter&0xFFFF)-getScreenY();
881       if (x<0 || y <0 || x>(int)getWidth() || y>(int)getHeight())
882       {
883         boxstack->handleCommand(Remote::BACK); //simulate cancel press
884       }
885     }
886   }
887 }
888
889
890
891 void VEpgListAdvanced::quickUpdate() { //only quick for plattform that need it!
892         updateSelection();
893 #ifdef GRADIENT_DRAWING
894       draw();
895 #else
896       sl.draw();
897       epg.draw();
898 #endif
899 }