2 Copyright 2004-2020 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/>.
30 #include "messagequeue.h"
32 #include "movieinfo.h"
33 #include "seriesinfo.h"
36 #include "vepgsummary.h"
37 #include "vepgsettimer.h"
39 #include "staticartwork.h"
41 #include "vepglistadvanced.h"
43 VEpgListAdvanced::VEpgListAdvanced(VVideoLiveTV* tvideolive, ChannelList* tchanList, ULONG initialChannelNumber)
45 channelNumber = initialChannelNumber;
47 videolive = tvideolive;
48 boxstack = BoxStack::getInstance();
52 setSize(640 + 40, 500 + 40); //old setSize(570, 420);
58 setTitleBarColour(DrawStyle::TITLEBARBACKGROUND);
59 TVMediaInfo* info = new TVMediaInfo();
60 info->setChannelLogo(channelNumber);
61 info->setStaticFallback(sa_tv);
62 setTitleBarIcon(info);
64 sl.setPosition(10, 30 + 5);
65 sl.setSize(area.w * 42 / 100 - 20, area.h - 30 - 15 - 30);
66 sl.setLinesPerOption(2.4f);
69 Region slarea = sl.getRegionR();
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);
76 epg.setVideoBackground();
77 epg.setBackgroundColour(DrawStyle::VIEWTRANSPARENTBACKGROUND);
79 epgTVmedia.setPosition(epg.getRegionR().w - 100 - 10, 10);
80 epgTVmedia.setSize(100, static_cast<UINT>(150 / Osd::getInstance()->getPixelAspect()));
83 boxRed.setBackgroundColour(DrawStyle::RED);
84 boxRed.setPosition(165 /*54*/, sl.getY2() + 8);
85 boxRed.setSize(18, 16);
88 textRed.setPosition(boxRed.getX2(), sl.getY2() + 4);
89 textRed.setSize(116, 30);
93 boxGreen.setBackgroundColour(DrawStyle::GREEN);
94 boxGreen.setPosition(165 + 1 * 110, sl.getY2() + 8);
95 boxGreen.setSize(18, 16);
98 textGreen.setPosition(boxGreen.getX2(), sl.getY2() + 4);
99 textGreen.setSize(116, 30);
102 boxYellow.setBackgroundColour(DrawStyle::YELLOW);
103 boxYellow.setPosition(165 + 2 * 110, sl.getY2() + 8);
104 boxYellow.setSize(18, 16);
107 textYellow.setPosition(boxYellow.getX2(), sl.getY2() + 4);
108 textYellow.setSize(116, 30);
111 boxBlue.setBackgroundColour(DrawStyle::BLUE);
112 boxBlue.setPosition(165 + 3 * 110, sl.getY2() + 8);
113 boxBlue.setSize(18, 16);
116 textBlue.setPosition(boxBlue.getX2(), sl.getY2() + 4);
117 textBlue.setSize(116, 30);
122 updateEpgDataChannel();
125 VEpgListAdvanced::~VEpgListAdvanced()
130 void VEpgListAdvanced::setButtonText()
136 textRed.setText(tr("Record"));
137 textGreen.setText(tr("Now"));
138 textYellow.setText(tr("Next"));
139 textBlue.setText(tr("Guide"));
144 textRed.setText(tr("Record"));
145 textGreen.setText(tr("Next"));
146 textYellow.setText(tr("Schedule"));
147 textBlue.setText(tr("Switch"));
152 textRed.setText(tr("Record"));
153 textGreen.setText(tr("Now"));
154 textYellow.setText(tr("Schedule"));
155 textBlue.setText(tr("Switch"));
161 void VEpgListAdvanced::doRed()
166 void VEpgListAdvanced::doGreen()
184 void VEpgListAdvanced::doYellow()
202 void VEpgListAdvanced::doBlue()
220 void VEpgListAdvanced::doNext()
222 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doNext");
223 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
225 if (mode != OneChannel)
227 Channel* chan = (*chanList)[slCurrentOption];
228 channelNumber = chan->number;
232 updateEpgDataNowNext(true);
234 TVMediaInfo* info = new TVMediaInfo();
235 info->setStaticArtwork(sa_tv);
236 setTitleBarIcon(info);
238 boxstack->update(this);
241 void VEpgListAdvanced::doNow()
243 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doNow");
244 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
246 if (mode != OneChannel)
248 Channel* chan = (*chanList)[slCurrentOption];
249 channelNumber = chan->number;
253 updateEpgDataNowNext(true);
255 TVMediaInfo* info = new TVMediaInfo();
256 info->setStaticArtwork(sa_tv);
257 setTitleBarIcon(info);
259 boxstack->update(this);
262 void VEpgListAdvanced::doProgramm()
264 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doProgram");
266 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
267 Channel* chan = (*chanList)[slCurrentOption];
268 channelNumber = chan->number;
269 updateEpgDataChannel();
271 TVMediaInfo* info = new TVMediaInfo();
272 info->setChannelLogo(channelNumber);
273 info->setStaticFallback(sa_tv);
274 setTitleBarIcon(info);
276 boxstack->update(this);
279 void VEpgListAdvanced::doSwitch()
283 if (mode != OneChannel)
285 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
286 Channel* chan = (*chanList)[slCurrentOption];
287 channelNumber = chan->number;
290 Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "doSwitch %d", channelNumber);
291 Message* m = new Message(); // Must be done after this view deleted
294 m->message = Message::CHANNEL_CHANGE;
295 m->parameter = channelNumber;
297 MessageQueue::getInstance()->postMessage(m);
303 #pragma warning(disable : 4703)
306 void VEpgListAdvanced::doRecord()
309 Event* current = getCurrentOptionEvent(channel);
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();
318 for (listIndex = 0; listIndex < chanlistsize; listIndex++)
320 chan = (*chanList)[listIndex];
322 if (chan->number == channel) break;
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);
330 boxstack->update(vs);
334 void VEpgListAdvanced::doGrid()
336 if (mode != OneChannel)
338 ULONG slCurrentOption = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
339 Channel* chan = (*chanList)[slCurrentOption];
340 channelNumber = chan->number;
344 unsigned int chanlistsize = chanList->size();
347 for (listIndex = 0; listIndex < chanlistsize; listIndex++)
349 chan = (*chanList)[listIndex];
350 if (chan->number == channelNumber) break;
353 VEpg* vepg = new VEpg(videolive, listIndex, chanList);
356 boxstack->update(vepg);
359 void VEpgListAdvanced::clearEventList()
361 std::vector<EventList*>::iterator itty = eventLista.begin();
363 while (itty != eventLista.end())
379 * if (!chanList) return;
381 for(UINT listIndex = 0; listIndex < gridRows; listIndex++)
383 if(listTop + listIndex >= UINT(chanListbox.getBottomOption()))
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
391 void VEpgListAdvanced::updateEpgData()
397 //updateEpgDataChannel();
403 updateEpgDataNowNext(false);
409 void VEpgListAdvanced::updateEpgDataNowNext(bool changeState)
414 UINT chanlistsize = chanList->size();
419 eventLista.resize(chanList->size());
422 for (UINT listIndex = 0; listIndex < chanlistsize; listIndex++)
424 if (listIndex >= chanlistsize) continue;
426 chan = (*chanList)[listIndex];
428 if (chan->number == channelNumber)
430 startupdate = listIndex - sl.getNumOptionsDisplayable() - 2;
431 endupdate = listIndex + sl.getNumOptionsDisplayable() + 2;
438 startupdate = sl.getTopOption() - 2;
439 endupdate = sl.getBottomOption() + 1;
447 for (int listIndex = startupdate; listIndex < endupdate; listIndex++)
449 if (listIndex < 0) continue;
450 if (listIndex >= static_cast<int>(chanlistsize)) continue;
452 chan = (*chanList)[listIndex];
454 if (!eventLista[listIndex]) eventLista[listIndex] = VDR::getInstance()->getChannelSchedule(chan->number, now, 4 * 60 * 60);
458 void VEpgListAdvanced::updateEpgDataChannel()
461 eventLista.resize(1);
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);
468 void VEpgListAdvanced::drawData(bool doIndexPop)
470 if (mode == OneChannel) drawDataChannel(doIndexPop);
471 else if (mode == Next) drawDataNowNext(true, doIndexPop);
472 else if (mode == Now) drawDataNowNext(false, doIndexPop);
475 void VEpgListAdvanced::drawDataChannel(bool doIndexPop)
477 int saveIndex = sl.getCurrentOption();
478 int saveTop = sl.getTopOption();
482 sl.addColumn(25 + 7);
483 sl.addColumn(25 + 7 + 7);
488 char tempA[300]; // FIXME this is guesswork!
489 char tempB[300]; // FIXME
490 char tempC[300]; // FIXME
493 Event* currentEvent = NULL;
494 EventList::iterator j;
495 EventList* eventList = eventLista[0];
499 for (j = eventList->begin(); j != eventList->end(); j++)
502 time_t eventStartTime = static_cast<time_t>(currentEvent->time);
503 time_t eventEndTime = static_cast<time_t>(currentEvent->time + currentEvent->duration);
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);
511 if ((check < 0) || (check > 299)) Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "String too big");
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);
524 sl.hintSetCurrent(0);
528 sl.hintSetCurrent(saveIndex);
529 sl.hintSetTop(saveTop);
535 void VEpgListAdvanced::drawDataNowNext(bool next, bool doIndexPop)
537 int saveIndex = sl.getCurrentOption();
538 int saveTop = sl.getTopOption();
546 char tempA[300]; // FIXME this is guesswork!
547 char tempB[300]; // FIXME
548 char tempC[300]; // FIXME
551 Event* currentEvent = NULL;
552 EventList::iterator j;
555 if (next) minevents++;
557 int setcurrenthelper = 0;
559 unsigned int chanlistsize = chanList->size();
561 for (UINT listIndex = 0; listIndex < chanlistsize; listIndex++)
564 chan = (*chanList)[listIndex];
566 EventList* eventList = eventLista[listIndex];
568 if (eventList && (eventList->size() >= minevents))
570 j = eventList->begin();
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);
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);
582 if ((check < 0) || (check > 299)) Log::getInstance()->log("VEventListAdvanced", Log::DEBUG, "String too big");
586 sprintf(tempC, "\n%s", chan->name);
589 TVMediaInfo* info = new TVMediaInfo();
591 if ((*chanList)[listIndex]->number == channelNumber)
594 setcurrenthelper = listIndex;
597 info->setChannelLogo((*chanList)[listIndex]->number);
598 info->setStaticFallback(sa_tv);
599 int index = sl.addOption(tempC, reinterpret_cast<void*>(listIndex), first, info);
601 if (currentEvent) currentEvent->index = index;
608 sl.hintSetCurrent(setcurrenthelper);
612 sl.hintSetCurrent(saveIndex);
613 sl.hintSetTop(saveTop);
619 void VEpgListAdvanced::draw(bool doIndexPop)
621 // Single channel mode
627 unsigned int chanlistsize = chanList->size();
631 for (listIndex = 0; listIndex < chanlistsize; listIndex++)
633 chan = (*chanList)[listIndex];
635 if (chan->number == channelNumber) break;
638 sprintf(tempA, tr("Schedule - %s"), (*chanList)[listIndex]->name);
644 setTitleText(tr("Now"));
649 setTitleText(tr("Next"));
654 drawData(doIndexPop);
664 LOCALTIME_R(&now, &btime);
665 strftime(freeSpace, 299, "%d/%m/%y", &btime);
666 drawTextRJ(freeSpace, getWidth(), 5, DrawStyle::LIGHTTEXT);
673 w.nextSymbol = WSymbol::UP;
674 w.setPosition(20, area.h - 35);
677 w.nextSymbol = WSymbol::DOWN;
678 w.setPosition(50, area.h - 35);
681 w.nextSymbol = WSymbol::SKIPBACK;
682 w.setPosition(85, area.h - 35);
685 w.nextSymbol = WSymbol::SKIPFORWARD;
686 w.setPosition(115, area.h - 35);
689 drawTextRJ(tr("[ok] = info"), 560 + 70, sl.getY2() + 4, DrawStyle::LIGHTTEXT);
691 // All static stuff done
694 Event* VEpgListAdvanced::getCurrentOptionEvent(ULONG& channel)
696 if (mode == OneChannel)
698 channel = channelNumber;
700 EventList* eventList = eventLista[0];
701 if (!eventList) return NULL;
703 for (Event* currentEvent : *eventList)
705 if (currentEvent->index == sl.getCurrentOption()) return currentEvent;
708 else if ((mode == Now) || (mode == Next))
710 ULONG slCurrentOptionData = reinterpret_cast<ULONG>(sl.getCurrentOptionData());
711 EventList* eventList = eventLista[slCurrentOptionData];
712 if (!eventList) return NULL;
713 channel = (*chanList)[slCurrentOptionData]->number;
715 if ((mode == Now) && (eventList->size() > 0)) return (*eventList)[0];
716 else if ((mode == Next) && (eventList->size() > 1)) return (*eventList)[1];
722 void VEpgListAdvanced::updateSelection()
726 if (mode == OneChannel)
728 TVMediaInfo* info = new TVMediaInfo();
729 info->setChannelLogo(channelNumber);
730 info->setStaticFallback(sa_tv);
731 setTitleBarIcon(info);
734 Event* toShow = getCurrentOptionEvent(channel);
738 toShow->loadinfos(channel);
739 std::stringstream description;
741 description << "\n" << toShow->title << "\n\n";
742 description << toShow->subtitle << "\n";
743 description << toShow->description;
748 if (toShow->movieInfo)
750 poster = toShow->movieInfo->poster;
753 if (toShow->seriesInfo)
755 if (toShow->seriesInfo->seasonposter.height)
757 poster = toShow->seriesInfo->seasonposter;
759 else if (toShow->seriesInfo->posters.size())
761 poster = toShow->seriesInfo->posters[0];
767 epgTVmedia.setTVMedia(poster.info, WTVMedia::ZoomHorizontal);
768 epgTVmedia.setVisible(true);
772 if (toShow->epgImage)
775 info.setPosterThumb(channel, toShow->id);
776 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
777 epgTVmedia.setVisible(true);
779 else if (mode != OneChannel)
782 info.setChannelLogo(channel);
783 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
784 epgTVmedia.setVisible(true);
788 epgTVmedia.setVisible(false);
792 epg.setText(description.str().c_str());
798 if (mode != OneChannel)
801 info.setChannelLogo(channel);
802 epgTVmedia.setTVMedia(info, WTVMedia::ZoomHorizontal);
803 epgTVmedia.setVisible(true);
807 epgTVmedia.setVisible(false);
812 int VEpgListAdvanced::handleCommand(int command)
821 boxstack->update(this);
830 boxstack->update(this);
834 case Input::SKIPBACK:
839 boxstack->update(this);
843 case Input::SKIPFORWARD:
848 boxstack->update(this);
878 if (sl.getNumOptions() == 0) return 2;
881 Event* current = getCurrentOptionEvent(channel);
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();
890 for (listIndex = 0; listIndex < chanlistsize; listIndex++)
892 chan = (*chanList)[listIndex];
893 if (chan->number == channel) break;
896 VEpgSummary* vr = new VEpgSummary(current, (*chanList)[listIndex]);
899 boxstack->update(vr);
904 // should not get to here
914 // stop command getting to any more views
918 void VEpgListAdvanced::processMessage(Message* m)
920 Log::getInstance()->log("VEpgListAdvanced", Log::DEBUG, "Got message value %lu", m->message);
922 if (m->message == Message::MOUSE_MOVE)
924 if (sl.mouseMove(m->parameter - getScreenX(), m->tag - getScreenY()))
927 boxstack->update(this);
930 else if (m->message == Message::MOUSE_LBDOWN)
932 int x = m->parameter - getScreenX();
933 int y = m->tag - getScreenY();
934 if (sl.mouseLBDOWN(x, y))
936 boxstack->handleCommand(Input::OK); //simulate OK press
938 else if (boxRed.mouseLBDOWN(x, y))
940 boxstack->handleCommand(Input::RED);
942 else if (boxGreen.mouseLBDOWN(x, y))
944 boxstack->handleCommand(Input::GREEN); // FIXME all these green? is this right?
946 else if (boxYellow.mouseLBDOWN(x, y))
948 boxstack->handleCommand(Input::GREEN);
950 else if (boxBlue.mouseLBDOWN(x, y))
952 boxstack->handleCommand(Input::GREEN);
956 if (coordsOutsideBox(m))
958 boxstack->handleCommand(Input::BACK); //simulate cancel press
964 void VEpgListAdvanced::quickUpdate() //only quick for plattform that need it!
968 #ifdef GRADIENT_DRAWING