From a96f84c4571151396e84628349bde457758d89a0 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Thu, 20 Feb 2020 23:29:36 +0000 Subject: [PATCH] Rewrite timers class using std::thread/mutex/cond/chrono --- CREDITS | 1 + audioplayer.cc | 7 +- audioplayer.h | 6 +- command.cc | 1 - main.cc | 2 +- playermedia.cc | 1 - playermedia.h | 2 +- timers.cc | 492 +++++++++++++++++++++------------------------- timers.h | 148 +++++--------- vchannelselect.cc | 9 +- vchannelselect.h | 2 +- vdr.cc | 6 +- vepg.cc | 4 +- vepg.h | 7 +- vmedialist.h | 1 - vmediaview.cc | 1 - vmediaview.h | 9 +- vmute.cc | 5 +- vmute.h | 5 +- vradiorec.cc | 10 +- vradiorec.h | 10 +- vsleeptimer.cc | 1 - vsleeptimer.h | 2 +- vteletextview.cc | 304 ++++++++++++++-------------- vteletextview.h | 43 ++-- vtimeredit.cc | 1 - vtimerlist.cc | 1 - vtimerlist.h | 2 +- vvideolivetv.cc | 6 +- vvideolivetv.h | 2 +- vvideomedia.cc | 1 - vvideomedia.h | 3 +- vvideorec.cc | 10 +- vvideorec.h | 11 +- vvolume.cc | 1 - vvolume.h | 2 +- vwelcome.cc | 5 +- vwelcome.h | 2 +- 38 files changed, 490 insertions(+), 636 deletions(-) diff --git a/CREDITS b/CREDITS index 9de0c99..4fc8470 100644 --- a/CREDITS +++ b/CREDITS @@ -43,6 +43,7 @@ Marten Richter Reporting of many bugs Audio channel selection VDR 1.7 compatibility + Raspberry Pi port Andreas Vogel Media player diff --git a/audioplayer.cc b/audioplayer.cc index e6001e7..9f3f9a3 100644 --- a/audioplayer.cc +++ b/audioplayer.cc @@ -14,13 +14,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ -#include "audioplayer.h" #include "demuxeraudio.h" -#include "timers.h" #include "video.h" #include "messagequeue.h" #include "i18n.h" @@ -29,6 +26,8 @@ #include "media.h" #include "mediaplayer.h" +#include "audioplayer.h" + //how often do we retry if there is no data in stream #define MAXTRY 50 diff --git a/audioplayer.h b/audioplayer.h index 08af3d9..f39df37 100644 --- a/audioplayer.h +++ b/audioplayer.h @@ -14,8 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #ifndef AUDIOPLAYER_H @@ -36,7 +35,7 @@ #include "messagequeue.h" #include "thread.h" #include "afeed.h" -#include "timerreceiver.h" +#include "timers.h" #ifdef WIN32 #include "threadwin.h" @@ -45,7 +44,6 @@ #endif - class Boxx; class DemuxerAudio; class MediaURI; diff --git a/command.cc b/command.cc index e5c767b..b38569d 100644 --- a/command.cc +++ b/command.cc @@ -41,7 +41,6 @@ #include "colour.h" #include "osd.h" #include "i18n.h" -#include "timerreceiver.h" #include "timers.h" #include "wol.h" #include "vconnect.h" diff --git a/main.cc b/main.cc index 924d9a7..b727db3 100644 --- a/main.cc +++ b/main.cc @@ -141,7 +141,7 @@ int main(int argc, char** argv) wol = new Wol(); sleeptimer = new Sleeptimer(); - if (!logger || !inputMan || !led || !osd || !video || !audio || !boxstack || !command || !wol || !sleeptimer) + if (!logger || !timers || !inputMan || !led || !osd || !video || !audio || !boxstack || !command || !wol || !sleeptimer) { printf("Could not create objects. Memory problems?\n"); shutdown(1); diff --git a/playermedia.cc b/playermedia.cc index 692dd20..ecaad25 100644 --- a/playermedia.cc +++ b/playermedia.cc @@ -20,7 +20,6 @@ #include "playermedia.h" //we most probably need a new demux... #include "demuxermedia.h" -#include "timers.h" #include "video.h" #include "messagequeue.h" #include "i18n.h" diff --git a/playermedia.h b/playermedia.h index d97e17b..6012c66 100644 --- a/playermedia.h +++ b/playermedia.h @@ -37,7 +37,7 @@ #include "thread.h" #include "afeed.h" #include "vfeed.h" -#include "timerreceiver.h" +#include "timers.h" #include "video.h" #ifdef WIN32 diff --git a/timers.cc b/timers.cc index 115cacb..f1f73da 100644 --- a/timers.cc +++ b/timers.cc @@ -1,5 +1,5 @@ /* - Copyright 2004-2007 Chris Tallon + Copyright 2004-2020 Chris Tallon This file is part of VOMP. @@ -14,15 +14,12 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ -#include "timers.h" - #include "log.h" -#include "command.h" -#include "timerreceiver.h" + +#include "timers.h" Timers* Timers::instance = NULL; @@ -30,7 +27,6 @@ Timers::Timers() { if (instance) return; instance = this; - initted = false; } Timers::~Timers() @@ -45,87 +41,106 @@ Timers* Timers::getInstance() int Timers::init() { - if (initted) return 0; - initted = true; + if (initted) return false; logger = Log::getInstance(); - if (!threadStart()) - { - shutdown(); - return 0; - } - - return 1; + timersMutex.lock(); // Start thread with mutex locked + recalc = true; + timersThread = std::thread([this] { masterLoop(); }); + logger->log("Timers", Log::DEBUG, "Timers started"); + initted = true; + return true; } -int Timers::shutdown() +void Timers::shutdown() { - if (!initted) return 0; - initted = false; + if (!initted) return; + + std::unique_lock lockWrapper(timersMutex); // lock the mutex + // main loop is in cond.wait/_until - logger->log("Timers", Log::DEBUG, "Timers shutdown start"); + // stop the main thread + quitThread = true; // main loop effectively dead, but join it later - threadStop(); + // Remove any future timer events from the list + for(auto i = timerList.begin(); i != timerList.end(); ) + { + TimerEvent* te = *i; - TimerEvent* timerEvent = NULL; - TimerReceiver* client = NULL; - int clientReference = 0; + if (!te->running) + { + delete te; + i = timerList.erase(i); + } + else + ++i; + } + // Now wait for all timer event threads to end while(timerList.size()) { - threadLock(); - timerEvent = timerList.front(); - client = timerEvent->client; - clientReference = timerEvent->clientReference; - threadUnlock(); - - cancelTimer(client, clientReference); + timersCond.wait(lockWrapper); // unlocks in wait. waiting for reap signals + // locked + // Assume there has been a reap signal. Could be spurious but no harm done + reap(); + timersCond.notify_all(); // In case of waiting cancelTimers } - logger->log("Timers", Log::DEBUG, "Timers shutdown end"); + timersCond.notify_one(); // In case there were no TimerEvents to reap, wake the masterLoop thread + lockWrapper.unlock(); // main loop exits if it hasn't already + timersThread.join(); +} - return 1; +bool Timers::setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs) +{ + std::chrono::system_clock::time_point fireTime = std::chrono::system_clock::now(); + fireTime += std::chrono::seconds(requestedSecs); + fireTime += std::chrono::nanoseconds(requestedNSecs); + + return setTimerC(client, clientReference, fireTime); +} + +bool Timers::setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSecs) +{ + std::chrono::system_clock::time_point fireTime = std::chrono::system_clock::from_time_t(requestedTime); + fireTime += std::chrono::nanoseconds(requestedTimeNSecs); + + return setTimerC(client, clientReference, fireTime); } -bool Timers::setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC) +bool Timers::setTimerC(TimerReceiver* client, int clientReference, std::chrono::system_clock::time_point& fireTime) { if (!initted) return 0; - logger->log("Timers", Log::DEBUG, "Starting set timer 1"); + logger->log("Timers", Log::DEBUG, "Starting set timer chrono"); - //logger->log("Timers", Log::DEBUG, "Waiting for LOCK -TIMERS- MUTEX 2"); - threadLock(); + std::lock_guard lock(timersMutex); // Check that this timer is not already in the list - TimerList::iterator i; - TimerEvent* currentTimerEvent = NULL; - for(i = timerList.begin(); i != timerList.end(); i++) + for(auto foundTimerEvent : timerList) { - currentTimerEvent = *i; - - if ((currentTimerEvent->client == client) && (currentTimerEvent->clientReference == clientReference)) + if ((foundTimerEvent->client == client) && (foundTimerEvent->clientReference == clientReference)) { // Timer exists already, either waiting or running - // Update the clocks - currentTimerEvent->requestedTime.tv_sec = requestedTime; - currentTimerEvent->requestedTime.tv_nsec = requestedTimeNSEC; + // Update requestedTime + foundTimerEvent->requestedTime = fireTime; - if (currentTimerEvent->running) + if (foundTimerEvent->running) { // If this timerEvent is currently running, update the clocks and set the restart flag. // Instead of being deleted in timerEventFinished it will be restarted - currentTimerEvent->restartAfterFinish = true; + foundTimerEvent->restartAfterFinish = true; // Don't need to resetThreadFlag because this timer isn't re-live yet - threadUnlock(); - return true; + return true; // unlock } else { + logger->log("Timers", Log::DEBUG, "Editing existing timer"); + // A waiting timer has been edited - resetThreadFlag = true; - threadSignalNoLock(); - threadUnlock(); - return true; + recalc = true; + timersCond.notify_all(); + return true; // unlock } } } @@ -135,40 +150,132 @@ bool Timers::setTimerT(TimerReceiver* client, int clientReference, long int requ TimerEvent* t = new TimerEvent(); t->client = client; t->clientReference = clientReference; - t->requestedTime.tv_sec = requestedTime; - t->requestedTime.tv_nsec = requestedTimeNSEC; + t->requestedTime = fireTime; - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 2"); timerList.push_back(t); - resetThreadFlag = true; - threadSignalNoLock(); - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX 2"); - threadUnlock(); - + recalc = true; + timersCond.notify_all(); logger->log("Timers", Log::DEBUG, "Timer set for %p ref %i", client, clientReference); - - return true; + return true; // unlock } -bool Timers::setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs) +void Timers::masterLoop() { - struct timespec currentTime; + // mutex is locked already + std::unique_lock lockWrapper(timersMutex, std::defer_lock); - getClockRealTime(¤tTime); + TimerEvent* nextTimer = NULL; + + while(1) + { + if (recalc) + { + // work out the next fire time + nextTimer = NULL; - long int requestedTime; - long int requestedTimeNSEC; + for(TimerEvent* thisTimer : timerList) + { + if (thisTimer->running) continue; // has already been timercall'd - requestedTime = currentTime.tv_sec + requestedSecs; - requestedTimeNSEC = currentTime.tv_nsec + requestedNSecs; - if (requestedTimeNSEC > 999999999) + if (!nextTimer) + { + nextTimer = thisTimer; + } + else + { + if (thisTimer->requestedTime < nextTimer->requestedTime) + { + nextTimer = thisTimer; + } + } + } + + recalc = false; + } + + std::cv_status cvs; + if (nextTimer) + { + // wait for signal timed + cvs = timersCond.wait_until(lockWrapper, nextTimer->requestedTime); //unlocks in wait + } + else + { + // wait for signal + timersCond.wait(lockWrapper); //unlocks in wait + } + + // and we're back - we've been signalled (quit, recalc, reap) or the time ran out, or spurious. mutex locked. + + // quit? -> quit + if (quitThread) return; // unlocks motex + + if (doReap) + { + reap(); + timersCond.notify_all(); // in case of waiting cancelTimers + } + + // recalc? -> restart loop + if (recalc) continue; + + // time ran out? -> fire a timer + if (nextTimer && (cvs == std::cv_status::timeout)) + { + nextTimer->run(); + recalc = true; + } +// else +// { + // not quit, not recalc, and either: + // 1. there is no next timer + // 2. there is a next timer but the timeout didn't expire + // therefore, this is a spurious wakeup. Leave recalc == false, go around, and do wait/wait_until again. +// continue; +// } + } + + // If you want to do any cleanup after the main loop, change the quitthread return to break and put cleanup here. mutex will be locked +} + +void Timers::reap() // Master timers thread, mutex locked (or shutdown, mutex locked) +{ + for(auto i = timerList.begin(); i != timerList.end(); ) { - ++requestedTime; - requestedTimeNSEC -= 1000000000; - logger->log("Timers", Log::DEBUG, "Second rollover - CHECK FIXME"); + TimerEvent* te = *i; + + if (te->completed) + { + te->timerThread.join(); + + if (te->restartAfterFinish) + { + logger->log("Timers", Log::DEBUG, "timerEventFinished RESTART for %p %i", te->client, te->clientReference); + te->restartAfterFinish = false; + te->running = false; + te->completed = false; + recalc = true; + ++i; + } + else + { + delete te; + i = timerList.erase(i); + } + } + else + ++i; } +} - return setTimerT(client, clientReference, requestedTime, requestedTimeNSEC); +void Timers::reapTimerEvent(TimerEvent* te) // Called by a TimerEvent thread +{ + std::lock_guard lock(timersMutex); + te->completed = true; + doReap = true; + timersCond.notify_all(); // Would be notify_one, but in the case of shutdown the thread within shutdown() will be + // handling the reaping. The notify that goes to the masterLoop will cause it to return from wait and sit waiting + // for the lock so it can examine quitThread and return. Doesn't matter which thread is unblocked first } bool Timers::cancelTimer(TimerReceiver* client, int clientReference) @@ -176,7 +283,7 @@ bool Timers::cancelTimer(TimerReceiver* client, int clientReference) /* This method locks the timers mutex Then one of three things can happen: 1. The TimerEvent is found, running = false. This means it hasn't started yet. - Delete the timer normally, set resetFlag + Delete the timer normally, set recalc 2. The TimerEvent is found, running = true. This means the timer is currently firing, timercall on the client is being called. a. Thread calling cancelTimer is an external thread: In this case, this thread @@ -199,225 +306,80 @@ bool Timers::cancelTimer(TimerReceiver* client, int clientReference) logger->log("Timers", Log::DEBUG, "Starting cancel timer %p %i, list size = %i", client, clientReference, timerList.size()); + std::unique_lock lockWrapper(timersMutex); // lock + while(1) { - threadLock(); - + TimerEvent* foundTimerEvent = NULL; TimerList::iterator i; - TimerEvent* currentTimerEvent = NULL; for(i = timerList.begin(); i != timerList.end(); i++) { - currentTimerEvent = *i; - if ((currentTimerEvent->client == client) && (currentTimerEvent->clientReference == clientReference)) + if (((*i)->client == client) && ((*i)->clientReference == clientReference)) { + foundTimerEvent = *i; break; } } - if (i == timerList.end()) + if (!foundTimerEvent) { // Case 3, no timer found - threadUnlock(); - return true; + return true; // unlock } - else - { - // Timer found, Case 1 or 2 - if (currentTimerEvent->running == false) - { - // Case 1. Just delete the timer and reset the thread. - timerList.erase(i); - delete currentTimerEvent; - logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference); - resetThreadFlag = true; - threadSignalNoLock(); - threadUnlock(); - return true; - } - else - { - if (Thread_TYPE::thisThreadID() == currentTimerEvent->getThreadID()) - { - // Case 2 b. - // The thread requesting cancelTimer is the timer thread itself, the timer has already fired. - logger->log("Timers", Log::DEBUG, "%p ref %i cancelTimer itself calling - ignore", client, clientReference); - currentTimerEvent->restartAfterFinish = false; // in case a restart had already been set. - threadUnlock(); - return true; - } - - // Case 2 a. For now, use polling with a 50ms delay. - // Don't delete a running timer. - // FIXME upgrade me to signalling - - logger->log("Timers", Log::DEBUG, "%p ref %i cancelTimer WAITING", client, clientReference); - - threadUnlock(); - MILLISLEEP(50); - } - } - } // end of the big while loop -} + // Timer found, case 1 or 2 -void Timers::timerEventFinished(TimerEvent* timerEvent) -{ - // This function takes out the already timercall'd TimerEvent from the list - // Or resets it if restart flag is true - - - if (!initted) return; - threadLock(); - - logger->log("Timers", Log::DEBUG, "timerEventFinished for %p", timerEvent->client); - - for(TimerList::iterator i = timerList.begin(); i != timerList.end(); i++) - { - if (timerEvent != *i) continue; - - if (timerEvent->restartAfterFinish) + if (!foundTimerEvent->running) { - logger->log("Timers", Log::DEBUG, "timerEventFinished RESTART for %p", timerEvent->client); + // Case 1. Timer was just waiting. Delete and set recalc. - timerEvent->restartAfterFinish = false; - timerEvent->running = false; - resetThreadFlag = true; - threadSignalNoLock(); - } - else - { - // The removal of a called and non-restart TimerEvent doesn't need the threadMethod to be reset timerList.erase(i); - logger->log("Timers", Log::DEBUG, "timerEventFinished for %p %i - remove done", timerEvent->client, timerEvent->clientReference); - delete timerEvent; + delete foundTimerEvent; + logger->log("Timers", Log::DEBUG, "Removed timer for %p ref %i", client, clientReference); + recalc = true; + timersCond.notify_all(); // shutdown could be being called? notify_all guarantees we wake masterLoop + return true; // unlock } - break; - } - // FIXME At this point, this should signal all threads waiting on cancelTimer - threadUnlock(); - - // Kill this thread, as it's the one started for the timer event - Thread_TYPE::threadSuicide(); -} - -void Timers::threadMethod() -{ - struct timespec nextTime; - TimerEvent* nextTimer = NULL; - resetThreadFlag = true; - - threadLock(); - - while(1) - { - if (resetThreadFlag) + if (std::this_thread::get_id() == foundTimerEvent->timerThread.get_id()) { - resetThreadFlag = false; - - // Work out the next Timer - - nextTime.tv_sec = 0; - nextTime.tv_nsec = 0; - nextTimer = NULL; - - TimerList::iterator i; - TimerEvent* currentTimer = NULL; - for(i = timerList.begin(); i != timerList.end(); i++) - { - currentTimer = *i; - if (currentTimer->running) continue; // has already been timercall'd - - if (!nextTimer) - { - nextTime.tv_sec = currentTimer->requestedTime.tv_sec; - nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; - nextTimer = currentTimer; - } - else - { - if (currentTimer->requestedTime.tv_sec < nextTime.tv_sec) - { - nextTime.tv_sec = currentTimer->requestedTime.tv_sec; - nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; - nextTimer = currentTimer; - } - else if (currentTimer->requestedTime.tv_sec == nextTime.tv_sec) - { - if (currentTimer->requestedTime.tv_nsec < nextTime.tv_nsec) - { - nextTime.tv_sec = currentTimer->requestedTime.tv_sec; - nextTime.tv_nsec = currentTimer->requestedTime.tv_nsec; - nextTimer = currentTimer; - } - } - } - } - } - - if (nextTimer) - { -//## logger->log("Timers", Log::DEBUG, "List size: %i. nextTimerClient: %p/%i. nextTime.tv_sec: %li. nextTime.tv_nsec: %li", timerList.size(), nextTimer->client, nextTimer->clientReference, nextTime.tv_sec, nextTime.tv_nsec); - - - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (1)"); - threadWaitForSignalTimed(&nextTime); - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 5"); - - // unlocks in the wait - } - else - { - //logger->log("Timers", Log::DEBUG, "about to un-LOCK -TIMERS- MUTEX (2)"); - threadWaitForSignal(); - //logger->log("Timers", Log::DEBUG, "LOCKED -TIMERS- MUTEX 6"); - // unlocks in the wait + // Case 2 b. + // The thread requesting cancelTimer is the timer thread itself, the timer has already fired. + logger->log("Timers", Log::DEBUG, "%p ref %i cancelTimer itself calling - ignore", client, clientReference); + foundTimerEvent->restartAfterFinish = false; // in case a restart had already been set. + return true; // unlock } - // Mutex locked again here by exit of wait or timedwait above - - // ok. we have been signalled or the time has run out - // This only gets signalled if it is to reset or die - - // First check for die.. - threadCheckExit(); // exiting thread with mutex locked - - // Check for reset.. - // This can be caused by an addition or deletion to the list - if (resetThreadFlag || (nextTimer == NULL)) continue; + // Case 2 a. An external thread is calling cancelTimer for a timer which has already fired and is still running. + // Want to block here until we know the thread has completed. - // timer ran out + // A broadcast notify goes out after each reap (whether in main loop or shutdown) + // So, wait on the cond and go around each time we wake. One of them will have been after the timerThread finished, + // which turns it into a case 3. - Log::getInstance()->log("Timers", Log::DEBUG, "Timer firing for client %p ref %i", nextTimer->client, nextTimer->clientReference); + logger->log("Timers", Log::DEBUG, "%p ref %i cancelTimer WAITING", client, clientReference); + timersCond.wait(lockWrapper); //unlocks in wait + // locked + logger->log("Timers", Log::DEBUG, "%p ref %i cancelTimer go-around", client, clientReference); - nextTimer->run(); // sets timerevent to running and starts it - resetThreadFlag = true; // find a new timer to wait on - } + } // end of the big while loop } - // Class TimerEvent -TimerEvent::TimerEvent() -{ - running = false; - restartAfterFinish = false; - client = NULL; - clientReference = 0; - requestedTime.tv_sec = 0; - requestedTime.tv_nsec = 0; -} - -void TimerEvent::threadMethod() -{ - Log::getInstance()->log("Timers", Log::DEBUG, "sending timer to %p with parameter %u", client, clientReference); - client->timercall(clientReference); - Timers::getInstance()->timerEventFinished(this); // does not return -} - void TimerEvent::run() { running = true; - threadStart(); + threadStartProtect.lock(); + timerThread = std::thread([this] + { + threadStartProtect.lock(); + threadStartProtect.unlock(); + + Log::getInstance()->log("Timers", Log::DEBUG, "sending timer to %p with parameter %u", client, clientReference); + client->timercall(clientReference); + Timers::getInstance()->reapTimerEvent(this); + }); + threadStartProtect.unlock(); // Ensures timerThread is valid before run() returns } diff --git a/timers.h b/timers.h index d15ef30..bf746b9 100644 --- a/timers.h +++ b/timers.h @@ -1,60 +1,5 @@ - - - - - - - - - -/* - - -FYI - -Fixed: - -The main problem was that timers only seemed to launch messages which went into The Big Mutex. -This has been fixed a different way by implementing locking in BoxStack - meaning timercalls -can now draw and update their displays without locking The Big Mutex. Problem solved. I think -the whole program might move more towards classes keeping more mutexes and rely less on The -Big Mutex. - - - -> Timers ... deprecated. Maybe. - -> This whole thing will be replaced with a timed-message idea. It will be possible -> to send yourself (or whoever) a message with a delay, or delivery time. The message -> will be handed to Command as usual, but command will do the right thing. The messages -> will be delivered to the recipient _with the gui mutex locked_, meaning updates can -> be done there and then in the message handler. - -> Good points: -> * Cuts down on code lines -> * Most (all?) timercall()s eventually send a message to command in order to -> do something within The Big Mutex. This makes it easier and simpler code wise -> * Gets rid of Timers. - -> Bad points: -> * Timers become gui only features. Solve this with a MessageReceiver interface and -> have command deliver messages straight to the recipients rather than through BoxStack. -> * Timer delivery accuracy becomes dependant on everything that uses The Big Mutex. -> It will become more important to not block The Big Mutex. -> * Cancelling timers... hmm - -> If you have any comments about the new design, like, "It's just as flawed as the old one", -> then I'd appreciate hearing it before I start writing it all :) - - -*/ - - - - - /* - Copyright 2004-2005 Chris Tallon + Copyright 2004-2020 Chris Tallon This file is part of VOMP. @@ -69,30 +14,15 @@ Big Mutex. GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ -#ifndef TIMERS_H -#define TIMERS_H - -#include -#include - -#include "threadsystem.h" - -#include "defines.h" - - -class Log; -class TimerReceiver; - /* Timers documentation Call setTimer to set a timer.... cancelTimer to delete a running timer. -Derive your object from TimerReceiver (timerreceiver.h), implement timercall() in your class +Derive your object from TimerReceiver, implement timercall() in your class and supply your 'this' pointer to setTimer. Once a timer has fired it does not exist anymore, you have to keep creating them if you want @@ -103,36 +33,52 @@ so you can identify which timer has fired if you have more than one. You can reset a timer by calling setTimer again. This will not create 2 timers, it will overwrite the first one. -You must not allow a timer to fire on an object that has been deleted already, unless you want -segfaulty hell. - -?? +You must not allow a timer to fire on an object that has been deleted already. You must call cancelTimer before deleting object. cancelTimer guarantees that timercall will not be called again. */ -class TimerEvent : public Thread_TYPE -{ - public: - TimerEvent(); +#ifndef TIMERS_H +#define TIMERS_H - virtual void run(); - virtual void threadMethod(); +#include +#include +#include +#include +#include - TimerReceiver* client; - int clientReference; - struct timespec requestedTime; +#include "defines.h" - bool running; - bool restartAfterFinish; +class TimerReceiver +{ + public: + virtual ~TimerReceiver() {} + virtual void timercall(int clientReference)=0; }; +class TimerEvent +{ + friend class Timers; + public: + private: + TimerReceiver* client{}; + int clientReference{}; + std::chrono::system_clock::time_point requestedTime; + bool running{}; + bool completed{}; + bool restartAfterFinish{}; + std::thread timerThread; + std::mutex threadStartProtect; + + void run(); +}; +class Log; typedef std::list TimerList; -class Timers : public Thread_TYPE +class Timers { public: Timers(); @@ -140,23 +86,29 @@ class Timers : public Thread_TYPE static Timers* getInstance(); int init(); - int shutdown(); + void shutdown(); bool setTimerT(TimerReceiver* client, int clientReference, long int requestedTime, long int requestedTimeNSEC=0); bool setTimerD(TimerReceiver* client, int clientReference, long int requestedSecs, long int requestedNSecs=0); + bool setTimerC(TimerReceiver* client, int clientReference, std::chrono::system_clock::time_point& requestedTime); bool cancelTimer(TimerReceiver* client, int clientReference); - // Thread stuff - virtual void threadMethod(); - - void timerEventFinished(TimerEvent* timerEvent); // internal use only, does not return - + void reapTimerEvent(TimerEvent*); // Internal only private: static Timers* instance; - Log* logger; - bool initted; + Log* logger{}; + bool initted{}; + bool quitThread{}; + bool recalc{}; + bool doReap{}; TimerList timerList; - bool resetThreadFlag; + + std::thread timersThread; + std::mutex timersMutex; + std::condition_variable timersCond; + + void masterLoop(); + void reap(); }; #endif diff --git a/vchannelselect.cc b/vchannelselect.cc index bc6c492..d53d4aa 100644 --- a/vchannelselect.cc +++ b/vchannelselect.cc @@ -17,17 +17,17 @@ along with VOMP. If not, see . */ -#include "vchannelselect.h" #include "input.h" #include "message.h" #include "boxstack.h" #include "colour.h" #include "log.h" -#include "timers.h" #include "vdr.h" #include "messagequeue.h" +#include "vchannelselect.h" + // this class only works as it does because the remote command // values for the numbers are the numbers themselves ! @@ -37,7 +37,7 @@ VChannelSelect::VChannelSelect(Boxx* v) numGot = 0; ignoreTimer = false; - numWidth = (int)VDR::getInstance()->getChannelNumberWidth(); + numWidth = static_cast(VDR::getInstance()->getChannelNumberWidth()); if (numWidth > 10) numWidth = 10; for (int i = 0; i < numWidth; i++) input[i] = -1; @@ -54,7 +54,6 @@ VChannelSelect::~VChannelSelect() void VChannelSelect::timercall(int /*clientReference*/) { - Log::getInstance()->log("VChannelSelect", Log::DEBUG, "Timer call"); if (ignoreTimer) return; changeChannel(); } @@ -112,7 +111,7 @@ void VChannelSelect::changeChannel() for(i = numGot - 1; i >= 0; i--) { - m->parameter += input[i] * (ULONG)pow(10., i); + m->parameter += input[i] * static_cast(pow(10., i)); } MessageQueue::getInstance()->postMessage(m); diff --git a/vchannelselect.h b/vchannelselect.h index ab22182..00b84a6 100644 --- a/vchannelselect.h +++ b/vchannelselect.h @@ -24,7 +24,7 @@ #include #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" class VChannelSelect : public Boxx, public TimerReceiver { diff --git a/vdr.cc b/vdr.cc index 3f218b7..c54e8f4 100644 --- a/vdr.cc +++ b/vdr.cc @@ -598,12 +598,12 @@ VDR_ResponsePacket* VDR::RequestResponse(VDR_RequestPacket* vrp) } // Sleep and block this thread. The sleep unlocks the mutex - logger->log("VDR", Log::DEBUG, "RR sleep - opcode %lu", vrp->getOpcode()); +// logger->log("VDR", Log::DEBUG, "RR sleep - opcode %lu", vrp->getOpcode()); edSleepThisReceiver(&vdrpr); - logger->log("VDR", Log::DEBUG, "RR unsleep"); +// logger->log("VDR", Log::DEBUG, "RR unsleep"); // Woken because a response packet has arrived, mutex will be locked - logger->log("VDR", Log::DEBUG, "Packet delivered to me, requestID: %lu", vdrpr.save_vresp->getRequestID()); +// logger->log("VDR", Log::DEBUG, "Packet delivered to me, requestID: %lu", vdrpr.save_vresp->getRequestID()); edUnlock(); return vdrpr.save_vresp; diff --git a/vepg.cc b/vepg.cc index 4069109..62705b3 100644 --- a/vepg.cc +++ b/vepg.cc @@ -30,14 +30,11 @@ The video stream currently being viewed is shown as quarter screen in the top right. */ -#include "vepg.h" - #include "input.h" #include "vchannellist.h" #include "messagequeue.h" #include "video.h" #include "vepgsettimer.h" -#include "timers.h" #include "wsymbol.h" #include "message.h" #include "colour.h" @@ -46,6 +43,7 @@ #include "i18n.h" #include "log.h" +#include "vepg.h" VEpg* VEpg::instance = NULL; diff --git a/vepg.h b/vepg.h index adc6f7e..098e5d5 100644 --- a/vepg.h +++ b/vepg.h @@ -14,20 +14,17 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #ifndef VEPG_H #define VEPG_H -#include -#include #include #include "boxx.h" #include "defines.h" -#include "timerreceiver.h" +#include "timers.h" #include "wtextbox.h" #include "vdr.h" #include "wselectlist.h" diff --git a/vmedialist.h b/vmedialist.h index 4cda3cd..0707547 100644 --- a/vmedialist.h +++ b/vmedialist.h @@ -28,7 +28,6 @@ #include "tbboxx.h" #include "wselectlist.h" #include "timers.h" -#include "timerreceiver.h" class DirList; class Message; diff --git a/vmediaview.cc b/vmediaview.cc index 403c68d..87e0f10 100644 --- a/vmediaview.cc +++ b/vmediaview.cc @@ -24,7 +24,6 @@ #include "vpicturebanner.h" #include "vcolourtuner.h" #include "audioplayer.h" -#include "timers.h" #include "boxx.h" #include "wselectlist.h" #include "input.h" diff --git a/vmediaview.h b/vmediaview.h index 7e6d10a..7d0bf63 100644 --- a/vmediaview.h +++ b/vmediaview.h @@ -14,19 +14,14 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #ifndef VMEDIAVIEW_H #define VMEDIAVIEW_H -#include -#include -#include - #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" #include "vmedialist.h" #include "colour.h" #include "wjpeg.h" diff --git a/vmute.cc b/vmute.cc index b2fd4df..9a8ccdc 100644 --- a/vmute.cc +++ b/vmute.cc @@ -17,17 +17,16 @@ along with VOMP. If not, see . */ -#include "vmute.h" - #include "input.h" #include "audio.h" #include "video.h" #include "wsymbol.h" #include "colour.h" -#include "timers.h" #include "boxstack.h" #include "messagequeue.h" +#include "vmute.h" + VMute::VMute() { isMuted = Audio::getInstance()->toggleUserMute(); diff --git a/vmute.h b/vmute.h index 850dbb9..ebeb242 100644 --- a/vmute.h +++ b/vmute.h @@ -14,8 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #ifndef VMUTE_H @@ -24,7 +23,7 @@ #include #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" class VMute : public Boxx, public TimerReceiver { diff --git a/vradiorec.cc b/vradiorec.cc index 416a1e3..d53b7fa 100644 --- a/vradiorec.cc +++ b/vradiorec.cc @@ -1,5 +1,5 @@ /* - Copyright 2004-2019 Chris Tallon + Copyright 2004-2020 Chris Tallon This file is part of VOMP. @@ -14,12 +14,9 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ -#include "vradiorec.h" - #include "command.h" #include "osd.h" #include "player.h" @@ -29,7 +26,6 @@ #include "message.h" #include "vdr.h" #include "video.h" -#include "timers.h" #include "playerradio.h" #include "boxstack.h" #include "input.h" @@ -38,6 +34,8 @@ #include "log.h" #include "messagequeue.h" +#include "vradiorec.h" + VRadioRec::VRadioRec(Recording* rec) { boxstack = BoxStack::getInstance(); diff --git a/vradiorec.h b/vradiorec.h index a552901..dfff16d 100644 --- a/vradiorec.h +++ b/vradiorec.h @@ -1,5 +1,5 @@ /* - Copyright 2004-2006 Chris Tallon + Copyright 2004-2020 Chris Tallon This file is part of VOMP. @@ -14,17 +14,14 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #ifndef VRADIOREC_H #define VRADIOREC_H -#include - #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" #include "defines.h" #include "colour.h" #include "region.h" @@ -34,7 +31,6 @@ class Message; class VDR; class Video; class PlayerRadio; -class Timers; class BoxStack; class VRadioRec : public Boxx, public TimerReceiver diff --git a/vsleeptimer.cc b/vsleeptimer.cc index 45136a8..9ba949f 100644 --- a/vsleeptimer.cc +++ b/vsleeptimer.cc @@ -23,7 +23,6 @@ #include "wsymbol.h" #include "colour.h" #include "video.h" -#include "timers.h" #include "boxstack.h" #include "command.h" #include "messagequeue.h" diff --git a/vsleeptimer.h b/vsleeptimer.h index 3ca76f0..bf0785e 100644 --- a/vsleeptimer.h +++ b/vsleeptimer.h @@ -23,7 +23,7 @@ #include #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" #include "threadsystem.h" diff --git a/vteletextview.cc b/vteletextview.cc index 5e47bc4..15a1ce6 100644 --- a/vteletextview.cc +++ b/vteletextview.cc @@ -1,5 +1,5 @@ /* - Copyright 2005-2008 Chris Tallon, Marten Richter + Copyright 2005-2020 Chris Tallon, Marten Richter This file is part of VOMP. @@ -14,200 +14,192 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ + #include -#include "vteletextview.h" + #include "video.h" -#include "timers.h" #include "boxstack.h" #include "input.h" #include "playerlivetv.h" +#include "vteletextview.h" -VTeletextView::VTeletextView(TeletextDecoderVBIEBU* TTdecoder,Boxx* playerview, PlayerLiveTV* playerObj) +VTeletextView::VTeletextView(TeletextDecoderVBIEBU* TTdecoder, Boxx* playerview, PlayerLiveTV* playerObj) { - ttdecoder=TTdecoder; - pv=playerview; - player=playerObj; - subtitlemode=false; - - - - if (Video::getInstance()->getFormat() == Video::PAL) - { - //setSize(680, 550); - setSize(680,22); //Only first line - setPosition(40, 26); - } - else - { - setPosition(40, 30); - //setSize(680, 450); - setSize(680,18);//only first line - } - createBuffer(); - keyindigit=1; - page=0x100; - + ttdecoder = TTdecoder; + pv = playerview; + player = playerObj; + + if (Video::getInstance()->getFormat() == Video::PAL) + { + //setSize(680, 550); + setSize(680,22); //Only first line + setPosition(40, 26); + } + else + { + setPosition(40, 30); + //setSize(680, 450); + setSize(680,18);//only first line + } + + createBuffer(); + keyindigit = 1; + page = 0x100; } -VTeletextView::~VTeletextView () +VTeletextView::~VTeletextView() { - // Make sure the timer is deleted - Log::getInstance()->log("VTeletextView", Log::DEBUG, "VTeletextView destruct"); + Log::getInstance()->log("VTeletextView", Log::DEBUG, "VTeletextView destruct"); pv->draw(); BoxStack::getInstance()->update(pv); - Timers::getInstance()->cancelTimer(this, 1); ttdecoder->unRegisterTeletextView(this); - } void VTeletextView::draw(bool completedraw, bool onlyfirstline) { - //Log::getInstance()->log("VTeletextView", Log::ERR, "Start draw"); - Boxx::draw(); - int x,y; + //Log::getInstance()->log("VTeletextView", Log::ERR, "Start draw"); + Boxx::draw(); + int x, y; - Boxx *drawtarget=NULL; - int ox,oy; - for (y=0;y<25;y++) { - if (y==0) { - drawtarget=this; - ox=0; - oy=0; - } else { - drawtarget=pv; - ox=this->getScreenX(); - oy=this->getScreenY(); - } - - for (x=0;x<40;x++) { - if (ttdecoder->isDirty(x,y) || completedraw) { - cTeletextChar c=ttdecoder->getChar(x,y); - c.SetDirty(false); - //Skip Blinking and conceal - drawtarget->drawTTChar(ox,oy,x,y,c); - ttdecoder->setChar(x,y,c); - } - } - // Log::getInstance()->log("VTeletextView", Log::ERR, "Line %d",y); - if (onlyfirstline) break; + Boxx* drawtarget = NULL; + int ox, oy; + for (y = 0; y < 25; y++) + { + if (y == 0) + { + drawtarget = this; + ox = 0; + oy = 0; + } + else + { + drawtarget = pv; + ox = this->getScreenX(); + oy = this->getScreenY(); + } + + for (x = 0; x < 40; x++) + { + if (ttdecoder->isDirty(x, y) || completedraw) + { + cTeletextChar c = ttdecoder->getChar(x, y); + c.SetDirty(false); + //Skip Blinking and conceal + drawtarget->drawTTChar(ox, oy, x, y, c); + ttdecoder->setChar(x, y, c); + } } +// Log::getInstance()->log("VTeletextView", Log::ERR, "Line %d",y); + if (onlyfirstline) break; + } // Log::getInstance()->log("VTeletextView", Log::ERR, "Start end"); - - } - - - - -int VTeletextView::handleCommand(int command) { - if (subtitlemode) return 0; //Ok we are in subtitle mode, we are a slave of the player - switch (command) { - case Input::OK: +int VTeletextView::handleCommand(int command) +{ + if (subtitlemode) return 0; //Ok we are in subtitle mode, we are a slave of the player + switch (command) + { + case Input::OK: return 2; - case Input::BACK: + case Input::BACK: if(player) player->tellSubtitlesOSDVisible(false); // Only on liveTV return 4; - case Input::ZERO: - case Input::ONE: - case Input::TWO: - case Input::THREE: - case Input::FOUR: - case Input::FIVE: - case Input::SIX: - case Input::SEVEN: - case Input::EIGHT: - case Input::NINE: - { - // key in teletext page - doKey(command); - return 2; + case Input::ZERO: + case Input::ONE: + case Input::TWO: + case Input::THREE: + case Input::FOUR: + case Input::FIVE: + case Input::SIX: + case Input::SEVEN: + case Input::EIGHT: + case Input::NINE: + { + // key in teletext page + doKey(command); + return 2; + } } - }; return 0; - } void VTeletextView::doKey(int command) { - char pagenums[3]; - if (keyindigit==1){ - if (command==9) return; //not allowed - page=command<<8; - pagenums[0]=command+ 48; - pagenums[1]='-'; - pagenums[2]='-'; - keyindigit++; - } else if (keyindigit==2) { - page|=command<<4; - pagenums[0]=48+((page &0xF00)>>8); - pagenums[1]=command+ 48; - pagenums[2]='-'; - keyindigit++; - } else if (keyindigit==3) { - page|=command; - pagenums[0]=48+((page &0xF00)>>8); - pagenums[1]=48+((page &0x0F0)>>4); - pagenums[2]=48+command; - keyindigit=1; - ttdecoder->setPage(page); - } - ttdecoder->setKeyinDigits(pagenums,true); - Region toupdate; - toupdate.w=16*40; - if (Video::getInstance()->getFormat() == Video::PAL) { - toupdate.h=22; - - } else { - toupdate.h=18; - - } - toupdate.x=0; - toupdate.y=0; - - draw(false,true); - BoxStack::getInstance()->update(this,&toupdate); - -} - -void VTeletextView::timercall(int /* clientReference */) -{ - + char pagenums[3]; + if (keyindigit == 1) + { + if (command == 9) return; //not allowed + page = command << 8; + pagenums[0] = static_cast(command + 48); + pagenums[1] = '-'; + pagenums[2] = '-'; + keyindigit++; + } + else if (keyindigit == 2) + { + page |= command << 4; + pagenums[0] = static_cast(48 + ((page & 0xF00) >> 8)); + pagenums[1] = static_cast(command + 48); + pagenums[2] = '-'; + keyindigit++; + } + else if (keyindigit == 3) + { + page |= command; + pagenums[0] = static_cast(48 + ((page & 0xF00) >> 8)); + pagenums[1] = static_cast(48 + ((page & 0x0F0) >> 4)); + pagenums[2] = static_cast(48 + command); + keyindigit = 1; + ttdecoder->setPage(page); + } + + ttdecoder->setKeyinDigits(pagenums, true); + Region toupdate; + toupdate.w = 16 * 40; + if (Video::getInstance()->getFormat() == Video::PAL) + { + toupdate.h = 22; + } + else + { + toupdate.h = 18; + } + toupdate.x = 0; + toupdate.y = 0; + + draw(false, true); + BoxStack::getInstance()->update(this, &toupdate); } void VTeletextView::processMessage(Message* m) { - if (m->message == Message::TELETEXTUPDATE) + if (m->message == Message::TELETEXTUPDATE) + { + draw(false, false); + BoxStack::getInstance()->update(this); + BoxStack::getInstance()->update(pv); + } + else if (m->message == Message::TELETEXTUPDATEFIRSTLINE) + { + Region toupdate; + toupdate.w = 16 * 40; + if (Video::getInstance()->getFormat() == Video::PAL) { - draw(false,false); - BoxStack::getInstance()->update(this); - BoxStack::getInstance()->update(pv); - - } else if (m->message == Message::TELETEXTUPDATEFIRSTLINE) + toupdate.h = 22; + } + else { - Region toupdate; - toupdate.w=16*40; - if (Video::getInstance()->getFormat() == Video::PAL) { - toupdate.h=22; - - } else { - toupdate.h=18; - - } - toupdate.x=0; - toupdate.y=0; - - - - draw(false,true); - BoxStack::getInstance()->update(this,&toupdate); - + toupdate.h = 18; } -} - + toupdate.x = 0; + toupdate.y = 0; + draw(false, true); + BoxStack::getInstance()->update(this, &toupdate); + } +} diff --git a/vteletextview.h b/vteletextview.h index d3d1f35..5e7ac45 100644 --- a/vteletextview.h +++ b/vteletextview.h @@ -14,55 +14,42 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with VOMP; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + along with VOMP. If not, see . */ #ifndef VTELETEXTVIEW_H #define VTELETEXTVIEW_H -#include - #include "boxx.h" -#include "timerreceiver.h" + #include "teletextdecodervbiebu.h" class PlayerLiveTV; -class VTeletextView : public Boxx, public TimerReceiver +class VTeletextView : public Boxx { public: - VTeletextView (TeletextDecoderVBIEBU* TTdecoder, Boxx* playerview, - PlayerLiveTV* palyerObj); - ~VTeletextView (); + VTeletextView(TeletextDecoderVBIEBU* TTdecoder, Boxx* playerview, PlayerLiveTV* palyerObj); + ~VTeletextView(); void draw(bool completedraw, bool onlyfirstline); - void draw() {draw(true,false);}; - - - - + void draw() { draw(true, false); } void processMessage(Message* m); - void setSubtitleMode(bool mode) {subtitlemode=mode;}; - bool isInSubtitleMode() {return subtitlemode;}; + void setSubtitleMode(bool mode) { subtitlemode = mode; } + bool isInSubtitleMode() { return subtitlemode; } int handleCommand(int command); - void timercall(int clientReference); - private: - void doKey(int command); - + void doKey(int command); protected: - TeletextDecoderVBIEBU* ttdecoder; - int keyindigit; - int page; - bool subtitlemode; - Boxx* pv; - PlayerLiveTV* player; - - + TeletextDecoderVBIEBU* ttdecoder; + int keyindigit; + int page; + bool subtitlemode{}; + Boxx* pv; + PlayerLiveTV* player; }; #endif diff --git a/vtimeredit.cc b/vtimeredit.cc index 0d2f97b..a66aca0 100644 --- a/vtimeredit.cc +++ b/vtimeredit.cc @@ -27,7 +27,6 @@ #include "colour.h" #include "video.h" #include "i18n.h" -#include "timers.h" #include "vquestion.h" #include "messagequeue.h" #include "staticartwork.h" diff --git a/vtimerlist.cc b/vtimerlist.cc index c96c8b0..59bdd21 100644 --- a/vtimerlist.cc +++ b/vtimerlist.cc @@ -28,7 +28,6 @@ #include "colour.h" #include "video.h" #include "i18n.h" -#include "timers.h" #include "vtimeredit.h" #include "command.h" #include "boxstack.h" diff --git a/vtimerlist.h b/vtimerlist.h index 21219bf..966ac37 100644 --- a/vtimerlist.h +++ b/vtimerlist.h @@ -22,7 +22,7 @@ #include "vdr.h" #include "tbboxx.h" -#include "timerreceiver.h" +#include "timers.h" #include "wselectlist.h" #include "region.h" diff --git a/vvideolivetv.cc b/vvideolivetv.cc index bce617f..c09a0ba 100644 --- a/vvideolivetv.cc +++ b/vvideolivetv.cc @@ -17,7 +17,7 @@ along with VOMP. If not, see . */ -#include "vvideolivetv.h" +#include #include "vchannellist.h" #include "video.h" @@ -37,7 +37,6 @@ #include "vaudioselector.h" #include "colour.h" #include "event.h" -#include "timers.h" #include "vepg.h" #include "bitmap.h" #include "log.h" @@ -48,7 +47,8 @@ #include "demuxer.h" #include "messagequeue.h" -#include +#include "vvideolivetv.h" + VVideoLiveTV::VVideoLiveTV(ChannelList* tchanList, ULONG initialChannelNumber, VChannelList* tvchannelList) { diff --git a/vvideolivetv.h b/vvideolivetv.h index 22077df..7d083c2 100644 --- a/vvideolivetv.h +++ b/vvideolivetv.h @@ -30,7 +30,7 @@ #include "vdr.h" #include "wtextbox.h" #include "wselectlist.h" -#include "timerreceiver.h" +#include "timers.h" #include "wsymbol.h" #include "wprogressbar.h" #include "osdreceiver.h" diff --git a/vvideomedia.cc b/vvideomedia.cc index efb2bdc..b2f26c8 100644 --- a/vvideomedia.cc +++ b/vvideomedia.cc @@ -27,7 +27,6 @@ #include "wsymbol.h" #include "audio.h" #include "video.h" -#include "timers.h" #include "playermedia.h" #include "recording.h" #include "vaudioselector.h" diff --git a/vvideomedia.h b/vvideomedia.h index f45c222..da51337 100644 --- a/vvideomedia.h +++ b/vvideomedia.h @@ -24,13 +24,12 @@ #include #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" #include "wwss.h" #include "region.h" #include "colour.h" #include "recinfo.h" -class Timers; class PlayerMedia; class Recording; class VAudioSelector; diff --git a/vvideorec.cc b/vvideorec.cc index 478f8a0..f212b94 100644 --- a/vvideorec.cc +++ b/vvideorec.cc @@ -25,7 +25,6 @@ #include "audio.h" #include "vdr.h" #include "video.h" -#include "timers.h" #include "player.h" #include "recording.h" #include "vaudioselector.h" @@ -40,6 +39,7 @@ #include "channel.h" #include "vteletextview.h" #include "messagequeue.h" + #include "vvideorec.h" VVideoRec::VVideoRec(Recording* rec, bool ish264) @@ -59,10 +59,6 @@ VVideoRec::VVideoRec(Recording* rec, bool ish264) player = new Player(Command::getInstance(), this, this); player->init(myRec->IsPesRecording,myRec->recInfo->fps); - playing = false; - - startMargin = 0; - endMargin = 0; char* cstartMargin = vdr->configLoad("Timers", "Start margin"); char* cendMargin = vdr->configLoad("Timers", "End margin"); if (!cstartMargin) @@ -95,7 +91,7 @@ VVideoRec::VVideoRec(Recording* rec, bool ish264) OsdVector* osdv=dynamic_cast(Osd::getInstance()); if (osdv) { - osdv->updateBackgroundColor(DrawStyle::BLACK); + osdv->updateBackgroundColor(DrawStyle::BLACK); } barRegion.x = 0; @@ -121,8 +117,6 @@ VVideoRec::VVideoRec(Recording* rec, bool ish264) vdisplay.y=0; vdisplay.width=0; vdisplay.height=0; - - lastbar = -1; } void VVideoRec::preDelete() diff --git a/vvideorec.h b/vvideorec.h index 6c2823c..9dfa4fd 100644 --- a/vvideorec.h +++ b/vvideorec.h @@ -23,7 +23,7 @@ #include #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" #include "region.h" #include "colour.h" #include "osdreceiver.h" @@ -31,7 +31,6 @@ #include "video.h" class VDR; -class Timers; class Player; class Recording; class VAudioSelector; @@ -77,7 +76,7 @@ class VVideoRec : public Boxx, public TimerReceiver, public OSDReceiver UCHAR videoMode; void toggleChopSides(); - bool playing; + bool playing{}; bool barShowing; bool barGenHold; @@ -94,10 +93,10 @@ class VVideoRec : public Boxx, public TimerReceiver, public OSDReceiver Region barRegion; Region clocksRegion; - UINT startMargin; - UINT endMargin; + UINT startMargin{}; + UINT endMargin{}; - int lastbar; + int lastbar{-1}; VInfo* vsummary; }; diff --git a/vvolume.cc b/vvolume.cc index 3728a54..c0fc58a 100644 --- a/vvolume.cc +++ b/vvolume.cc @@ -24,7 +24,6 @@ #include "wsymbol.h" #include "colour.h" #include "video.h" -#include "timers.h" #include "boxstack.h" #include "messagequeue.h" diff --git a/vvolume.h b/vvolume.h index a1a670b..400cd8c 100644 --- a/vvolume.h +++ b/vvolume.h @@ -24,7 +24,7 @@ #include #include "boxx.h" -#include "timerreceiver.h" +#include "timers.h" class VVolume : public Boxx, public TimerReceiver { diff --git a/vwelcome.cc b/vwelcome.cc index bb8b070..efc1d2b 100644 --- a/vwelcome.cc +++ b/vwelcome.cc @@ -17,8 +17,8 @@ along with VOMP. If not, see . */ -#include "vwelcome.h" +#include "log.h" #include "input.h" #include "vdr.h" #include "vchannellist.h" @@ -30,14 +30,13 @@ #include "colour.h" #include "video.h" #include "i18n.h" -#include "timers.h" #include "vscreensaver.h" #include "vmedialist.h" #include "boxstack.h" #include "vopts.h" #include "staticartwork.h" -#include "log.h" +#include "vwelcome.h" VWelcome::VWelcome() { diff --git a/vwelcome.h b/vwelcome.h index fd70295..a0dfecc 100644 --- a/vwelcome.h +++ b/vwelcome.h @@ -25,7 +25,7 @@ #include #include "tbboxx.h" -#include "timerreceiver.h" +#include "timers.h" #include "wselectlist.h" #ifndef GRADIENT_DRAWING #include "wjpeg.h" -- 2.39.5