2 Copyright 2004-2007 Chris Tallon, 2014 Marten Richter
4 This file is part of VOMP.
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.
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.
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/>.
20 #include "vepglistadvanced.h"
30 #include "messagequeue.h"
32 #include "movieinfo.h"
33 #include "seriesinfo.h"
36 #include "vepgsummary.h"
37 #include "vepgsettimer.h"
39 #include "staticartwork.h"
44 VEpgListAdvanced::VEpgListAdvanced(VVideoLiveTV *tvideolive, ChannelList* tchanList,ULONG initialChannelNumber)
46 channelNumber = initialChannelNumber;
48 videolive = tvideolive;
49 boxstack = BoxStack::getInstance();
53 setSize(640+40, 500+40); //old setSize(570, 420);
59 setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
60 TVMediaInfo *info= new TVMediaInfo();
61 info->setChannelLogo(channelNumber);
62 info->setStaticFallback(sa_tv);
63 setTitleBarIcon(info);
65 sl.setPosition(10, 30 + 5);
66 sl.setSize(area.w*42/100 - 20, area.h - 30 - 15 - 30);
67 sl.setLinesPerOption(2.4f);
70 Region slarea=sl.getRegionR();
72 epg.setParaMode(true);
73 epg.setPosition(slarea.x +slarea.w+10 ,30+5);
74 epg.setSize(area.w -slarea.x -slarea.w -10, area.h - 30 - 15 - 30);
77 epg.setVideoBackground();
78 epg.setBackgroundColour(DrawStyle::VIEWTRANSPARENTBACKGROUND);
80 epgTVmedia.setPosition(epg.getRegionR().w-100-10,10);
81 epgTVmedia.setSize(100,(UINT)(150/Osd::getInstance()->getPixelAspect()));
84 boxRed.setBackgroundColour(DrawStyle::RED);
85 boxRed.setPosition(165 /*54*/, sl.getY2()+8);
86 boxRed.setSize(18, 16);
89 textRed.setPosition(boxRed.getX2(), sl.getY2()+4);
90 textRed.setSize(116, 30);
94 boxGreen.setBackgroundColour(DrawStyle::GREEN);
95 boxGreen.setPosition(165 +1*110, sl.getY2()+8);
96 boxGreen.setSize(18, 16);
99 textGreen.setPosition(boxGreen.getX2(), sl.getY2()+4);
100 textGreen.setSize(116, 30);
103 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
104 boxYellow.setPosition(165 +2*110, sl.getY2()+8);
105 boxYellow.setSize(18, 16);
108 textYellow.setPosition(boxYellow.getX2(), sl.getY2()+4);
109 textYellow.setSize(116, 30);
112 boxBlue.setBackgroundColour(DrawStyle::BLUE);
113 boxBlue.setPosition(165 +3*110, sl.getY2()+8);
114 boxBlue.setSize(18, 16);
117 textBlue.setPosition(boxBlue.getX2(), sl.getY2()+4);
118 textBlue.setSize(116, 30);
124 updateEpgDataChannel();
127 VEpgListAdvanced::~VEpgListAdvanced()
133 void VEpgListAdvanced::setButtonText()
138 textRed.setText(tr("Record"));
139 textGreen.setText(tr("Now"));
140 textYellow.setText(tr("Next"));
141 textBlue.setText(tr("Guide"));
145 textRed.setText(tr("Record"));
146 textGreen.setText(tr("Next"));
147 textYellow.setText(tr("Schedule"));
148 textBlue.setText(tr("Switch"));
151 textRed.setText(tr("Record"));
152 textGreen.setText(tr("Now"));
153 textYellow.setText(tr("Schedule"));
154 textBlue.setText(tr("Switch"));
160 void VEpgListAdvanced::doRed()
165 void VEpgListAdvanced::doGreen()
179 void VEpgListAdvanced::doYellow()
193 void VEpgListAdvanced::doBlue()
207 void VEpgListAdvanced::doNext()
209 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doNext");
210 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
211 if (mode!=OneChannel) {
212 Channel * chan=(*chanList)[slCurrentOption];
213 channelNumber = chan->number;
216 updateEpgDataNowNext(true);
218 TVMediaInfo *info= new TVMediaInfo();
219 info->setStaticArtwork(sa_tv);
220 setTitleBarIcon(info);
222 boxstack->update(this);
224 void VEpgListAdvanced::doNow()
226 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doNow");
227 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
228 if (mode!=OneChannel) {
229 Channel * chan=(*chanList)[slCurrentOption];
230 channelNumber = chan->number;
233 updateEpgDataNowNext(true);
235 TVMediaInfo *info= new TVMediaInfo();
236 info->setStaticArtwork(sa_tv);
237 setTitleBarIcon(info);
239 boxstack->update(this);
242 void VEpgListAdvanced::doProgramm()
244 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doProgram");
246 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
247 Channel * chan=(*chanList)[slCurrentOption];
248 channelNumber = chan->number;
249 updateEpgDataChannel();
251 TVMediaInfo *info= new TVMediaInfo();
252 info->setChannelLogo(channelNumber);
253 info->setStaticFallback(sa_tv);
254 setTitleBarIcon(info);
256 boxstack->update(this);
259 void VEpgListAdvanced::doSwitch()
264 if (mode!=OneChannel) {
265 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
266 Channel * chan=(*chanList)[slCurrentOption];
267 channelNumber = chan->number;
269 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doSwitch %d", channelNumber);
270 Message* m = new Message(); // Must be done after this view deleted
273 m->message = Message::CHANNEL_CHANGE;
274 m->parameter = channelNumber;
276 MessageQueue::getInstance()->postMessage(m);
282 #pragma warning(disable : 4703)
285 void VEpgListAdvanced::doRecord()
288 Event* current = getCurrentOptionEvent(channel);
291 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "Found the option you pointed at. %s %d", current->title, current->id);
292 unsigned int chanlistsize=chanList->size();
295 for(listIndex = 0; listIndex < chanlistsize; listIndex++)
297 chan = (*chanList)[listIndex];
298 if ((int)chan->number == channel) break;
301 Log::getInstance()->log("VEpgSummary", Log::DEBUG, "ID %lu TIME %lu DURATION %lu TITLE %s", current->id, current->time,
302 current->duration, current->title);
303 VEpgSetTimer* vs = new VEpgSetTimer(current, chan);
306 boxstack->update(vs);
311 void VEpgListAdvanced::doGrid()
314 if (mode!=OneChannel) {
315 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
316 Channel * chan=(*chanList)[slCurrentOption];
317 channelNumber = chan->number;
320 unsigned int chanlistsize=chanList->size();
322 for(listIndex = 0; listIndex < chanlistsize; listIndex++)
324 chan = (*chanList)[listIndex];
325 if (chan->number == channelNumber) break;
328 VEpg* vepg = new VEpg(videolive, listIndex, chanList);
331 boxstack->update(vepg);
335 void VEpgListAdvanced::clearEventList()
337 std::vector<EventList*>::iterator itty = eventLista.begin();
338 while (itty!= eventLista.end()) {
352 * if (!chanList) return;
354 for(UINT listIndex = 0; listIndex < gridRows; listIndex++)
356 if(listTop + listIndex >= UINT(chanListbox.getBottomOption()))
358 chan = (*chanList)[listTop + listIndex];
359 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
364 void VEpgListAdvanced::updateEpgData()
369 //updateEpgDataChannel();
373 updateEpgDataNowNext(false);
379 void VEpgListAdvanced::updateEpgDataNowNext(bool changeState)
384 unsigned int chanlistsize=chanList->size();
387 eventLista.resize(chanList->size());
389 for(UINT listIndex = 0; listIndex < chanlistsize; listIndex++)
391 if (listIndex < 0) continue;
392 if (listIndex >= chanlistsize) continue;
393 chan = (*chanList)[listIndex];
394 if (chan->number == channelNumber) {
395 startupdate = listIndex-sl.getNumOptionsDisplayable()-2;
396 endupdate = listIndex+sl.getNumOptionsDisplayable()+2;
401 startupdate=sl.getTopOption()-2;
402 endupdate=sl.getBottomOption()+1;
409 for(int listIndex = startupdate; listIndex < endupdate; listIndex++)
411 if (listIndex < 0) continue;
412 if (listIndex >= (int)chanlistsize) continue;
414 chan = (*chanList)[listIndex];
415 if (!eventLista[listIndex]) eventLista[listIndex] = VDR::getInstance()->getChannelSchedule(chan->number, now, 4 * 60 *60);
421 void VEpgListAdvanced::updateEpgDataChannel()
424 eventLista.resize(1);
427 eventLista[0] = VDR::getInstance()->getChannelSchedule(channelNumber, now, 24 * 60 *60 *30); // one month
428 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "Eventlist %x %d", eventLista[0],channelNumber);
432 void VEpgListAdvanced::drawData(bool doIndexPop)
437 drawDataChannel(doIndexPop);
440 drawDataNowNext(true, doIndexPop);
443 drawDataNowNext(false, doIndexPop);
449 void VEpgListAdvanced::drawDataChannel(bool doIndexPop)
451 int saveIndex = sl.getCurrentOption();
452 int saveTop = sl.getTopOption();
456 sl.addColumn(25 + 7);
457 sl.addColumn(25 + 7+ 7);
462 char tempA[300]; // FIXME this is guesswork!
463 char tempB[300]; // FIXME
464 char tempC[300]; // FIXME
470 Event* currentEvent = NULL;
471 EventList::iterator j;
472 EventList* eventList = eventLista[0];
474 for (j = eventList->begin(); j != eventList->end(); j++)
477 time_t eventStartTime = (time_t)currentEvent->time;
478 time_t eventEndTime = (time_t)(currentEvent->time + currentEvent->duration);
480 LOCALTIME_R(&eventStartTime, &btime);
481 strftime(tempA, 300, "%d/%m/%y %H:%M ", &btime);
482 LOCALTIME_R(&eventEndTime, &btime);
483 strftime(tempB, 300, "- %H:%M ", &btime);
484 int check = SNPRINTF(tempC, 300, "\t %s\n \t \t%s%s", currentEvent->title,tempA,tempB);
485 if ((check < 0) || (check > 299)) Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "String too big");
487 TVMediaInfo *info= new TVMediaInfo();
488 info->setPosterThumb(channelNumber, currentEvent->id);
489 info->setStaticFallback(sa_defposter);
490 currentEvent->index = sl.addOption(tempC, reinterpret_cast<void*>(currentEvent->id), first, info);
497 sl.hintSetCurrent(0);
501 sl.hintSetCurrent(saveIndex);
502 sl.hintSetTop(saveTop);
508 void VEpgListAdvanced::drawDataNowNext(bool next, bool doIndexPop)
510 int saveIndex = sl.getCurrentOption();
511 int saveTop = sl.getTopOption();
519 char tempA[300]; // FIXME this is guesswork!
520 char tempB[300]; // FIXME
521 char tempC[300]; // FIXME
527 Event* currentEvent = NULL;
528 EventList::iterator j;
530 if (next) minevents++;
531 int setcurrenthelper =0;
533 unsigned int chanlistsize=chanList->size();
534 for(UINT listIndex = 0; listIndex < chanlistsize; listIndex++)
537 chan = (*chanList)[listIndex];
539 EventList* eventList = eventLista[listIndex];
540 if (eventList && ((int)eventList->size() >= minevents)) {
541 j = eventList->begin();
543 currentEvent = j[minevents-1];
544 time_t eventStartTime = (time_t)currentEvent->time;
545 time_t eventEndTime = (time_t)(currentEvent->time + currentEvent->duration);
547 LOCALTIME_R(&eventStartTime, &btime);
548 strftime(tempA, 300, "%H:%M ", &btime);
549 LOCALTIME_R(&eventEndTime, &btime);
550 strftime(tempB, 300, "- %H:%M ", &btime);
551 int check = SNPRINTF(tempC, 300, "%s\n%s\t %s%s", currentEvent->title, chan->name,tempA,tempB);
552 if ((check < 0) || (check > 299)) Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "String too big");
554 sprintf(tempC, "\n%s", chan->name);
557 TVMediaInfo *info= new TVMediaInfo();
558 if ((*chanList)[listIndex]->number == channelNumber) {
560 setcurrenthelper = listIndex;
562 info->setChannelLogo((*chanList)[listIndex]->number);
563 info->setStaticFallback(sa_tv);
564 int index = sl.addOption(tempC, reinterpret_cast<void*>(listIndex), first, info);
565 if (currentEvent) currentEvent->index = index;
571 sl.hintSetCurrent(setcurrenthelper);
575 sl.hintSetCurrent(saveIndex);
576 sl.hintSetTop(saveTop);
581 void VEpgListAdvanced::draw(bool doIndexPop)
584 // Single channel mode
588 unsigned int chanlistsize=chanList->size();
591 for(listIndex = 0; listIndex < chanlistsize; listIndex++)
593 chan = (*chanList)[listIndex];
594 if (chan->number == channelNumber) break;
596 sprintf(tempA, tr("Schedule - %s"), (*chanList)[listIndex]->name);
600 setTitleText(tr("Now"));
603 setTitleText(tr("Next"));
609 drawData(doIndexPop);
623 LOCALTIME_R(&now, &btime);
624 strftime(freeSpace, 299, "%d/%m/%y", &btime);
626 drawTextRJ(freeSpace, getWidth(), 5, DrawStyle::LIGHTTEXT);
632 w.nextSymbol = WSymbol::UP;
633 w.setPosition(20, area.h-35);
635 w.nextSymbol = WSymbol::DOWN;
636 w.setPosition(50, area.h-35);
638 w.nextSymbol = WSymbol::SKIPBACK;
639 w.setPosition(85, area.h-35);
641 w.nextSymbol = WSymbol::SKIPFORWARD;
642 w.setPosition(115, area.h-35);
645 drawTextRJ(tr("[ok] = info"), 560+70, sl.getY2()+4, DrawStyle::LIGHTTEXT);
647 // All static stuff done
652 Event* VEpgListAdvanced::getCurrentOptionEvent(int& channel)
654 // version for channel
655 Event* currentEvent = NULL;
656 EventList::iterator j;
657 EventList* eventList = NULL;
658 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
663 eventList = eventLista[0];
665 channel = channelNumber;
666 for (j = eventList->begin(); j != eventList->end(); j++)
669 if (currentEvent->index == slCurrentOption) return currentEvent;
675 eventList = eventLista[slCurrentOption];
676 channel = (*chanList)[slCurrentOption]->number;
679 if (eventList && eventList->size()>1) {
680 j = eventList->begin();
687 eventList = eventLista[slCurrentOption];
688 channel = (*chanList)[slCurrentOption]->number;
690 if (eventList && eventList->size()>0) {
691 j = eventList->begin();
706 void VEpgListAdvanced::updateSelection()
709 if (mode==OneChannel) {
710 TVMediaInfo *info= new TVMediaInfo();
711 info->setChannelLogo(channelNumber);
712 info->setStaticFallback(sa_tv);
713 setTitleBarIcon(info);
715 Event* toShow = getCurrentOptionEvent(channel);
718 toShow->loadinfos(channel);
719 std::stringstream description;
721 description << "\n"<< toShow->title << "\n\n";
722 description << toShow->subtitle <<"\n";
723 description << toShow->description;
727 if (toShow->movieInfo) {
728 poster=toShow->movieInfo->poster;
730 if (toShow->seriesInfo) {
731 if (toShow->seriesInfo->seasonposter.height) {
732 poster=toShow->seriesInfo->seasonposter;
734 else if (toShow->seriesInfo->posters.size()) {
735 poster=toShow->seriesInfo->posters[0];
739 epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
740 epgTVmedia.setVisible(true);
742 if (toShow->epgImage)
745 info.setPosterThumb(channel,toShow->id);
746 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
747 epgTVmedia.setVisible(true);
748 }else if (mode!=OneChannel) {
750 info.setChannelLogo(channel);
751 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
752 epgTVmedia.setVisible(true);
754 epgTVmedia.setVisible(false);
758 epg.setText(description.str().c_str());
761 if (mode!=OneChannel) {
763 info.setChannelLogo(channel);
764 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
765 epgTVmedia.setVisible(true);
767 epgTVmedia.setVisible(false);
773 int VEpgListAdvanced::handleCommand(int command)
782 boxstack->update(this);
790 boxstack->update(this);
793 case Input::SKIPBACK:
798 boxstack->update(this);
801 case Input::SKIPFORWARD:
806 boxstack->update(this);
831 if (sl.getNumOptions() == 0) return 2;
835 Event* current = getCurrentOptionEvent(channel);
838 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "Found the option you pointed at. %s %d", current->title, current->id);
839 unsigned int chanlistsize=chanList->size();
842 for(listIndex = 0; listIndex < chanlistsize; listIndex++)
844 chan = (*chanList)[listIndex];
845 if ((int)chan->number == channel) break;
848 VEpgSummary* vr = new VEpgSummary(current, (*chanList)[listIndex]);
851 boxstack->update(vr);
855 // should not get to here
863 // stop command getting to any more views
867 void VEpgListAdvanced::processMessage(Message* m)
869 Log::getInstance()->log("VEpgListAdvanced", Log::DEBUG, "Got message value %lu", m->message);
871 if (m->message == Message::MOUSE_MOVE)
873 if (sl.mouseMove((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
876 boxstack->update(this);
879 else if (m->message == Message::MOUSE_LBDOWN)
881 if (sl.mouseLBDOWN((m->parameter>>16)-getScreenX(),(m->parameter&0xFFFF)-getScreenY()))
883 boxstack->handleCommand(Input::OK); //simulate OK press
885 else if (boxRed.mouseLBDOWN((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
887 boxstack->handleCommand(Input::RED);
889 else if (boxGreen.mouseLBDOWN((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
891 boxstack->handleCommand(Input::GREEN);
893 else if (boxYellow.mouseLBDOWN((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
895 boxstack->handleCommand(Input::GREEN);
897 else if (boxBlue.mouseLBDOWN((m->parameter >> 16) - getScreenX(), (m->parameter & 0xFFFF) - getScreenY()))
899 boxstack->handleCommand(Input::GREEN);
903 if (coordsOutsideBox(m))
905 boxstack->handleCommand(Input::BACK); //simulate cancel press
913 void VEpgListAdvanced::quickUpdate() { //only quick for plattform that need it!
916 #ifdef GRADIENT_DRAWING