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