From 2bf0e6c3a91f92cad86dabfcdcdb0e95e99c4738 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Thu, 7 May 2020 15:48:08 +0100 Subject: [PATCH] Rework SleepTimer Remove thread and use Timers instead Reuse same Boxxes when displaying Move all logic to SleepTimer class from display classes Use i18n --- control.cc | 23 ++-- control.h | 4 +- objects.mk | 2 +- sleeptimer.cc | 316 +++++++++++++++++++++++++++++++++++++++++++++++++ sleeptimer.h | 93 +++++++++++++++ vsleeptimer.cc | 303 ----------------------------------------------- vsleeptimer.h | 69 ----------- 7 files changed, 423 insertions(+), 387 deletions(-) create mode 100644 sleeptimer.cc create mode 100644 sleeptimer.h delete mode 100644 vsleeptimer.cc delete mode 100644 vsleeptimer.h diff --git a/control.cc b/control.cc index 998a426..31c6b35 100644 --- a/control.cc +++ b/control.cc @@ -56,7 +56,7 @@ #include "boxx.h" #include "boxstack.h" #include "log.h" -#include "vsleeptimer.h" +#include "sleeptimer.h" #include "wjpeg.h" #include "osdvector.h" @@ -133,7 +133,7 @@ bool Control::init(bool tcrashed) boxstack = new BoxStack(); if (!boxstack) throw 70; if (!boxstack->init()) throw 71; - sleeptimer = new Sleeptimer(); if (!sleeptimer) throw 80; + sleepTimer = new SleepTimer(); if (!sleepTimer) throw 80; wol = new Wol(); if (!wol) throw 90; @@ -173,8 +173,8 @@ bool Control::init(bool tcrashed) wol = NULL; FALLTHROUGH case 90: - delete sleeptimer; - sleeptimer = NULL; + delete sleepTimer; + sleepTimer = NULL; FALLTHROUGH case 80: boxstack->shutdown(); @@ -256,11 +256,11 @@ void Control::shutdown() logger->log("Control", Log::NOTICE, "WOL module shut down"); } - if (sleeptimer) + if (sleepTimer) { - delete sleeptimer; - sleeptimer = NULL; - logger->log("Control", Log::NOTICE, "Sleeptimer module shut down"); + delete sleepTimer; + sleepTimer = NULL; + logger->log("Control", Log::NOTICE, "SleepTimer module shut down"); } if (boxstack) @@ -616,9 +616,8 @@ void Control::handleCommand(int button) } case Input::GO: { - VSleeptimer* sleep = new VSleeptimer(); - boxstack->add(sleep); - sleep->handleCommand(button); // this will draw+show + logger->log("Control", Log::DEBUG, "Handling sleeptimer go"); + sleepTimer->go(); return; } } @@ -679,7 +678,7 @@ void Control::doPowerOff() Led::getInstance()->off(); InputMan::getInstance()->changePowerState(false); isStandby = true; - Sleeptimer::getInstance()->shutdown(); + sleepTimer->shutdown(); } } diff --git a/control.h b/control.h index 0271d0f..6524cee 100644 --- a/control.h +++ b/control.h @@ -35,7 +35,7 @@ class BoxStack; class Log; class VInfo; class WJpeg; -class Sleeptimer; +class SleepTimer; class Wol; class Audio; class Video; @@ -82,7 +82,7 @@ class Control : public MessageQueue Audio* audio{}; VDR* vdr{}; BoxStack* boxstack{}; - Sleeptimer* sleeptimer{}; + SleepTimer* sleepTimer{}; Wol* wol{}; InputMan* inputMan{}; diff --git a/objects.mk b/objects.mk index 63c17a0..30d496e 100644 --- a/objects.mk +++ b/objects.mk @@ -14,7 +14,7 @@ OBJ_COMMON = util.o control.o thread.o timers.o i18n.o udp4.o udp6.o vdpc.o tcp. woptionpane.o woptionbox.o wremoteconfig.o wtabbar.o led.o \ inputman.o input.o inputudp.o inputlirc.o vpicturebanner.o \ abstractoption.o eventdispatcher.o vdrrequestpacket.o \ - vdrresponsepacket.o vvideolivetv.o vsleeptimer.o \ + vdrresponsepacket.o vvideolivetv.o sleeptimer.o \ wprogressbar.o bitmap.o dvbsubtitles.o tfeed.o vteletextview.o \ teletextdecodervbiebu.o teletxt/txtfont.o movieinfo.o seriesinfo.o \ wmovieview.o wseriesview.o tvmedia.o wtvmedia.o wpictureview.o \ diff --git a/sleeptimer.cc b/sleeptimer.cc new file mode 100644 index 0000000..4a49f78 --- /dev/null +++ b/sleeptimer.cc @@ -0,0 +1,316 @@ +/* + Copyright 2008 Thomas Steger + Copyright 2020 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP. If not, see . +*/ + +#include "defines.h" +#include "log.h" +#include "input.h" +#include "wsymbol.h" +#include "colour.h" +#include "video.h" +#include "boxstack.h" +#include "message.h" +#include "messagequeue.h" +#include "util.h" +#include "i18n.h" + +#include "sleeptimer.h" + +SleepTimer::SleepTimer() +{ + logger = Log::getInstance(); + boxstack = BoxStack::getInstance(); + timers = Timers::getInstance(); +} + +// --- Input Functions ---- + +void SleepTimer::go() // User presses GO, from Control +{ + std::lock_guard lg(stateLock); + + if (state == 0) // inactive + { + calcNewTime(); + + vsleeptimer = new VSleepTimer(); + vsleeptimer->setTime(timerText); + vsleeptimer->draw(); + boxstack->add(vsleeptimer); + boxstack->update(vsleeptimer); + + timers->setTimerD(this, 1, 3); // 3s remove vsleeptimer timer + timers->setTimerD(this, 2, sec - 31); // logic timer 31s before end + + state = 2; + } + else if (state == 1) // counting, no displays - display current running time + { + calcCurrentSec(); + + vsleeptimer = new VSleepTimer(); + vsleeptimer->setTime(liveText); + vsleeptimer->draw(); + boxstack->add(vsleeptimer); + boxstack->update(vsleeptimer); + + timers->setTimerD(this, 1, 3); // 3s remove vsleeptimer timer + state = 2; + } + else if (state == 2) // counting, modify display showing already. + { + calcNewTime(); + + vsleeptimer->setTime(timerText); + vsleeptimer->draw(); + boxstack->update(vsleeptimer); + + timers->setTimerD(this, 1, 3); // update existing remove vsleeptimer timer + if (sec == -1) + { + timers->cancelTimer(this, 2); + state = 4; // user went beyond 2h, turning it off + } + else + { + timers->setTimerD(this, 2, sec - 31); // reset the logic timer 31s before end + } + } + else if (state == 3) // counting, countdown display showing. turn it off + { + timers->cancelTimer(this, 2); + + vsleeptimer = new VSleepTimer(); // Show a new VSleepTimer OFF dialogue + vsleeptimer->setTime(tr("OFF")); + vsleeptimer->draw(); + boxstack->add(vsleeptimer); + boxstack->update(vsleeptimer); + + boxstack->remove(vcountdown); // this deletes vcountdown as well + vcountdown = NULL; + + timers->setTimerD(this, 1, 3); // 3s remove vsleeptimer timer + state = 4; + } + else if (state == 4) // not counting, OFF dialogue showing + { + boxstack->remove(vsleeptimer); + vsleeptimer = NULL; + state = 0; + } +} + +void SleepTimer::timercall(int clientReference) +{ + std::lock_guard lg(stateLock); + + if (clientReference == 1) // Remove the VSleepTimer + { + if (state == 2 || state == 4) // modify display showing, counting or not + { + boxstack->remove(vsleeptimer); + vsleeptimer = NULL; + if (state == 2) state = 1; + else if (state == 4) state = 0; + } + } + else if (clientReference == 2) // sleep timer logic + { + if (state == 0) // inactive + { + logger->log("SleepTimer", Log::ERR, "Received timercall when state 0"); + } + else if (state == 1 || state == 2) // counting (either with or without modify display showing) + { + if (state == 2) // counting, modify display showing + { + // User has very recently pressed the sleeptimer button and the modify display / livetext is showing + // But now the logic timer has fired for the first time in the countdown. + // Delete the vsleeptimer before going on + + boxstack->remove(vsleeptimer); + vsleeptimer = NULL; + state = 1; + } + + // To receive a timer now means we are starting the countdown + calcCurrentSec(); + + vcountdown = new VCountdown(); // Show a new VCountdown dialogue + vcountdown->setTime(sec); + vcountdown->draw(); + boxstack->add(vcountdown); + boxstack->update(vcountdown); + + timers->setTimerD(this, 2, 1); // logic timer every 1s + state = 3; + } + else if (state == 3) // counting, countdown display showing + { + calcCurrentSec(); + + if (sec > -1) // update countdown + { + vcountdown->setTime(sec); + vcountdown->draw(); + boxstack->update(vcountdown); + timers->setTimerD(this, 2, 1); // logic timer every 1s + } + else // end of countdown + { + boxstack->remove(vcountdown); + vcountdown = NULL; + state = 0; + + Message* m = new Message(); + m->message = Message::INPUT_EVENT; + m->p_to = Message::CONTROL; + m->from = this; + m->parameter = Input::POWER; + MessageQueue::getInstance()->postMessage(m); + } + } + else if (state == 4) // not counting, off dialogue showing + { + logger->log("SleepTimer", Log::ERR, "Received timercall when state 4"); + } + } +} + +void SleepTimer::shutdown() +{ + std::lock_guard lg(stateLock); + + // Cancel any logic timer + if (state == 1 || state == 2 || state == 3) + timers->cancelTimer(this, 2); + + // Cancel any remove-vsleeptimer counter + if (state > 1) timers->cancelTimer(this, 1); + + if (vsleeptimer) + { + boxstack->remove(vsleeptimer); + vsleeptimer = NULL; + } + + if (vcountdown) + { + boxstack->remove(vcountdown); + vcountdown = NULL; + } + + state = 0; + sec = -1; +} + +// ------------------------ + +void SleepTimer::calcNewTime() +{ + if (sec < 890) { timerText = "0:15"; sec = 900; } + else if (sec < 1790) { timerText = "0:30"; sec = 1800; } + else if (sec < 2690) { timerText = "0:45"; sec = 2700; } + else if (sec < 3590) { timerText = "1:00"; sec = 3600; } + else if (sec < 4490) { timerText = "1:15"; sec = 4500; } + else if (sec < 5390) { timerText = "1:30"; sec = 5400; } + else if (sec < 6290) { timerText = "1:45"; sec = 6300; } + else if (sec < 7190) { timerText = "2:00"; sec = 7200; } + else { timerText = tr("OFF"); sec = -1; } + + endTime = std::chrono::system_clock::now() + std::chrono::seconds(sec); +} + +void SleepTimer::calcCurrentSec() +{ + auto remainingTime = endTime - std::chrono::system_clock::now(); + auto remainingTimeS = std::chrono::duration_cast(remainingTime); + sec = static_cast(remainingTimeS.count()); // I think this chrono stuff is a bit too ... wordy ......... + SNPRINTF(liveText, 10, "0:%02d", sec / 60); +} + +// ------------ VSleepTimer class + +VSleepTimer::VSleepTimer() +{ + setSize(100, 28); + createBuffer(); + if (Video::getInstance()->getFormat() == Video::PAL) + { + setPosition(100, 499); + } + else + { + setPosition(90, 400); + } + + setBackgroundColour(DrawStyle::VIEWBACKGROUND); + + wsClock.nextSymbol = WSymbol::CLOCK; + wsClock.setPosition(3, 0); + add(&wsClock); +} + +void VSleepTimer::setTime(const char* text) +{ + displaySleeptimer = text; +} + +void VSleepTimer::draw() +{ + Boxx::draw(); + drawText(displaySleeptimer, 50, 2, DrawStyle::LIGHTTEXT); +} + +// ------------ VCountdown class + +VCountdown::VCountdown() +{ + setSize(100, 28); + createBuffer(); + if (Video::getInstance()->getFormat() == Video::PAL) + { + setPosition(100, 499); + } + else + { + setPosition(90, 400); + } + + setBackgroundColour(DrawStyle::VIEWBACKGROUND); + + wsClock.nextSymbol = WSymbol::CLOCK; + wsClock.nextColour = DrawStyle::RED; + wsClock.setPosition(3, 0); + add(&wsClock); +} + +void VCountdown::setTime(int tsec) +{ + sec = tsec; +} + +void VCountdown::draw() +{ + Boxx::draw(); + + char temp[10]; + SNPRINTF(temp, 10, "0:%02d", sec); + drawText(temp, 50, 2, DrawStyle::RED); +} diff --git a/sleeptimer.h b/sleeptimer.h new file mode 100644 index 0000000..f548545 --- /dev/null +++ b/sleeptimer.h @@ -0,0 +1,93 @@ +/* + Copyright 2008 Thomas Steger + Copyright 2020 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP. If not, see . +*/ + +#ifndef SLEEPTIMER_H +#define SLEEPTIMER_H + +#include +#include "defines.h" +#include "boxx.h" +#include "wsymbol.h" +#include "timers.h" + +class Log; +class BoxStack; +class VSleepTimer; +class VCountdown; + +class SleepTimer : public TimerReceiver +{ + public: + SleepTimer(); + void go(); + void timercall(int clientReference); + void shutdown(); + + private: + Log* logger{}; + BoxStack* boxstack{}; + Timers* timers{}; + + void calcNewTime(); + void calcCurrentSec(); + + int sec{-1}; + const char* timerText; + char liveText[10]; + std::chrono::system_clock::time_point endTime; + + std::mutex stateLock; + UINT state{0}; + /* 0 = inactive + * 1 = counting - no displays + * 2 = counting - modify display showing + * 3 = counting - countdown display showing + * 4 - not counting - OFF dialogue showing + */ + + VSleepTimer* vsleeptimer{}; + VCountdown* vcountdown{}; +}; + +class VSleepTimer : public Boxx +{ + public: + VSleepTimer(); + void setTime(const char* text); + void draw(); + + private: + WSymbol wsClock; + const char* displaySleeptimer; +}; + +class VCountdown : public Boxx +{ + public: + VCountdown(); + void setTime(int sec); + void draw(); + + private: + WSymbol wsClock; + int sec; +}; + +#endif diff --git a/vsleeptimer.cc b/vsleeptimer.cc deleted file mode 100644 index 8db2d3c..0000000 --- a/vsleeptimer.cc +++ /dev/null @@ -1,303 +0,0 @@ -/* - Copyright 2008 Thomas Steger - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP. If not, see . -*/ - - -#include "input.h" -#include "wsymbol.h" -#include "colour.h" -#include "video.h" -#include "boxstack.h" -#include "message.h" -#include "messagequeue.h" -#include "util.h" - -#include "vsleeptimer.h" - -Sleeptimer* Sleeptimer::instance = NULL; - -Sleeptimer::Sleeptimer() -{ - if (instance) return; - instance = this; -} - -Sleeptimer::~Sleeptimer() -{ - instance = NULL; -} - -const char* Sleeptimer::SetTime() -{ - if (sec < 890) - { - sec = 900; - if (active == false) - { - active = true; - threadStart(); - } - - return "0:15"; - } - else if (sec <1790) - { - sec = 1800; - if (active == false) - { - active = true; - threadStart(); - } - - return "0:30"; - } - else if (sec < 2690) - { - sec = 2700; - if (active==false) - { - active = true; - threadStart(); - } - - return "0:45"; - } - else if (sec < 3590) - { - sec = 3600; - if (active==false) - { - active = true; - threadStart(); - } - - return "1:00"; - } - else if (sec < 4490) - { - sec = 4500; - if (active==false) - { - active = true; - threadStart(); - } - - return "1:15"; - } - else if (sec < 5390) - { - sec = 5400; - if (active==false) - { - active = true; - threadStart(); - } - - return "1:30"; - } - else if (sec < 6290) - { - sec = 6300; - if (active==false) - { - active = true; - threadStart(); - } - - return "1:45"; - } - else if (sec < 7190) - { - sec = 7200; - if (active==false) - { - active = true; - threadStart(); - } - - return "2:00"; - - } - else - { - sec = -1; - if (active==true) - shutdown(); - return "AUS"; - } -} - -Sleeptimer* Sleeptimer::getInstance() -{ - return instance; -} - -void Sleeptimer::threadMethod() -{ - while (sec>-1 && active==true) - { - sec--; - if (sec<31 && sec>-1) - { - VCountdown* count = new VCountdown(); - char temp[20]; - sprintf(temp, "0:%02d", sec); - count->drawClock(temp); - - Message* m1 = new Message(); - m1->message = Message::ADD_VIEW; - m1->p_to = Message::BOXSTACK; - m1->data = reinterpret_cast(count); - MessageQueue::getInstance()->postMessage(m1); - } - MILLISLEEP(1000); - - if (sec == -1) - { - Message* m2 = new Message(); - m2->message = Message::INPUT_EVENT; - m2->p_to = Message::CONTROL; - m2->from = this; - m2->parameter = Input::POWER; - MessageQueue::getInstance()->postMessage(m2); - shutdown(); - } - } -} - -void Sleeptimer::shutdown() -{ - if (active) - { - sec = -1; - threadCancel(); - active = false; - } -} - - -VSleeptimer::VSleeptimer() -{ - setSize(100, 28); - createBuffer(); - if (Video::getInstance()->getFormat() == Video::PAL) - { - setPosition(100, 499); - } - else - { - setPosition(90, 400); - } -} - -VSleeptimer::~VSleeptimer() -{ - // Make sure the timer is deleted - Timers::getInstance()->cancelTimer(this, 1); -} - -void VSleeptimer::draw() -{ - fillColour(DrawStyle::VIEWBACKGROUND); - WSymbol w; - TEMPADD(&w); - w.nextSymbol = WSymbol::CLOCK; - w.setPosition(3, 0); - w.draw(); - - Boxx::draw(); - drawText(displaySleeptimer,50,2,DrawStyle::LIGHTTEXT); - Timers::getInstance()->setTimerD(this, 1, 2); -} - -void VSleeptimer::timercall(int /* clientReference */) -{ - // delete me! - Message* m = new Message(); // Delete self - m->message = Message::CLOSE_ME; - m->p_to = Message::BOXSTACK; - m->from = this; - MessageQueue::getInstance()->postMessage(m); -} - -int VSleeptimer::handleCommand(int command) -{ - switch(command) - { - case Input::GO: - { - displaySleeptimer = Sleeptimer::getInstance()->SetTime(); - draw(); - BoxStack::getInstance()->update(this); - // handled - return 2; - } - } - - // allow command to drop through to other views - return 0; -} - - - - -VCountdown::VCountdown() -{ - - setSize(100, 28); - createBuffer(); - if (Video::getInstance()->getFormat() == Video::PAL) - { - setPosition(100, 499); - } - else - { - setPosition(90, 400); - } -} - -VCountdown::~VCountdown() -{ - // Make sure the timer is deleted - Timers::getInstance()->cancelTimer(this, 1); -} - -void VCountdown::drawClock(const char* sec) -{ - fillColour(DrawStyle::VIEWBACKGROUND); - WSymbol w; - TEMPADD(&w); - w.nextSymbol = WSymbol::CLOCK; - w.nextColour = DrawStyle::RED; - w.setPosition(3, 0); - w.draw(); - - Boxx::draw(); - drawText(sec, 50, 2, DrawStyle::RED); - Timers::getInstance()->setTimerD(this, 1, 1); -} - -void VCountdown::timercall(int /* clientReference */) -{ - // delete me! - Message* m = new Message(); // Delete self - m->message = Message::CLOSE_ME; - m->p_to = Message::BOXSTACK; - m->from = this; - MessageQueue::getInstance()->postMessage(m); -} diff --git a/vsleeptimer.h b/vsleeptimer.h deleted file mode 100644 index bf0785e..0000000 --- a/vsleeptimer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright 2008 Thomas Steger - - This file is part of VOMP. - - VOMP is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - VOMP is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with VOMP. If not, see . -*/ - -#ifndef VSLEEPTIMER_H -#define VSLEEPTIMER_H - -#include - -#include "boxx.h" -#include "timers.h" - -#include "threadsystem.h" - -class Sleeptimer : public Thread_TYPE -{ - public: - Sleeptimer(); - virtual ~Sleeptimer(); - static Sleeptimer* getInstance(); - const char* SetTime(); - void shutdown(); - virtual void threadMethod(); - - private: - int sec{-1}; - bool active{}; - static Sleeptimer* instance; -}; - - -class VSleeptimer : public Boxx, public TimerReceiver -{ - public: - VSleeptimer(); - ~VSleeptimer(); - void draw(); - int handleCommand(int command); - void timercall(int clientReference); - - private: - const char* displaySleeptimer; -}; - -class VCountdown : public Boxx, public TimerReceiver -{ - public: - VCountdown(); - ~VCountdown(); - void drawClock(const char* sec); - void timercall(int clientReference); -}; - -#endif -- 2.39.2