From fb6de12636c538ab4ddaae0cc32089eac9584ed9 Mon Sep 17 00:00:00 2001 From: horchi Date: Sat, 24 Feb 2018 17:29:07 +0100 Subject: 2018-02-23 version 1.1.89 (horchi)\n - change: Improved switch timer 'timing'\n\n --- HISTORY.h | 7 +++++-- lib/common.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ lib/common.h | 28 ++++++++++++++++++++++++++++ menu.c | 2 ++ timer.c | 18 ++++++++++++++++-- update.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- update.h | 13 +++++++++++++ 7 files changed, 166 insertions(+), 5 deletions(-) diff --git a/HISTORY.h b/HISTORY.h index 037acba..1b3f6e8 100644 --- a/HISTORY.h +++ b/HISTORY.h @@ -5,8 +5,8 @@ * */ -#define _VERSION "1.1.88" -#define VERSION_DATE "22.02.2018" +#define _VERSION "1.1.89" +#define VERSION_DATE "24.02.2018" #define DB_API 6 @@ -19,6 +19,9 @@ /* * ------------------------------------ +2018-02-23 version 1.1.89 (horchi) + - change: Improved switch timer 'timing' + 2018-02-22 version 1.1.88 (horchi) - added: Optional switch timer notification message diff --git a/lib/common.c b/lib/common.c index 413b9f5..cf68ffa 100644 --- a/lib/common.c +++ b/lib/common.c @@ -1919,3 +1919,51 @@ int urlUnescape(char* dst, const char* src, int normalize) return (dst - org_dst) - 1; } + +//*************************************************************************** +//*************************************************************************** +// Timer Thread +//*************************************************************************** + +cTimerThread::cTimerThread(sendEventFct fct, int aEvent, time_t aTime, void* aUserData, bool aSelfDistroy) +{ + sendEvent = fct; + event = aEvent; + theTime = aTime; + userData = aUserData; + selfdetroy = aSelfDistroy; + active = no; + + Start(); +} + +//*************************************************************************** +// Action +//*************************************************************************** + +void cTimerThread::Action() +{ + cMutex mutex; + + active = yes; + + mutex.Lock(); + tell(1, "Info: Started timer thread, event (%d) scheduled for '%s'", event, l2pTime(theTime).c_str()); + + while (time(0) < theTime && Running() && active) + { + // loop every 10 seconds + + waitCondition.TimedWait(mutex, (theTime - time(0)) * 1000); + } + + if (time(0) >= theTime && sendEvent) + sendEvent(event, userData); + + tell(3, "Info: Finished timer thread"); + + active = no; + + // if (selfdetroy) + // delete this; // :o :o ;) +} diff --git a/lib/common.h b/lib/common.h index 28536ec..3d0aa95 100644 --- a/lib/common.h +++ b/lib/common.h @@ -413,6 +413,34 @@ class LogDuration int logLevel; }; +//*************************************************************************** +// Timer Thread +//*************************************************************************** + +class cTimerThread : public cThread +{ + public: + + typedef void (*sendEventFct)(int event, void* userData); + + cTimerThread(sendEventFct fct, int aEvent, time_t aTime, void* aUserData = 0, bool aSelfDistroy = no); + + int isActive() { return active; } + + protected: + + virtual void Action(); + + int event; + time_t theTime; + void* userData; + bool selfdetroy; + cCondVar waitCondition; + int active; + + sendEventFct sendEvent; +}; + //*************************************************************************** // Semaphore //*************************************************************************** diff --git a/menu.c b/menu.c index 1673884..d563009 100644 --- a/menu.c +++ b/menu.c @@ -736,6 +736,8 @@ int cMenuDb::createSwitchTimer(const cEvent* event) return done; cDbRow* timerRow = newTimerRowFromEvent(event); + + timerRow->setValue("STARTTIME", l2hhmm(timerRow->getIntValue("_STARTTIME"))); createTimer(timerRow, Epg2VdrConfig.uuid, ttView); tell(0, "Switch timer for '%s' at '%s' created", diff --git a/timer.c b/timer.c index 80cdbba..a0d6aab 100644 --- a/timer.c +++ b/timer.c @@ -31,7 +31,7 @@ int cUpdate::checkSwitchTimer() { char* buf; asprintf(&buf, "Switching in %ld seconds to '%s'", swTimer->start-time(0), swTimer->channelId.c_str()); - Skins.Message(mtInfo, buf); + Skins.QueueMessage(mtInfo, buf); free(buf); swTimer->notified = yes; } @@ -86,6 +86,8 @@ int cUpdate::checkSwitchTimer() it = switchTimers.erase(it); } + switchTimerTrigger = no; + return done; } @@ -513,9 +515,21 @@ int cUpdate::takeSwitchTimer() switchTimers[timerid].eventId = timerDb->getIntValue("EVENTID"); switchTimers[timerid].channelId = timerDb->getStrValue("CHANNELID"); - switchTimers[timerid].start = timerDb->getIntValue("_STARTTIME"); + switchTimers[timerid].start = (timerDb->getIntValue("_STARTTIME") / 60) * 60; // cut seconds switchTimers[timerid].notified = no; + // and register timer for it + + timerThreads.push_back(new cTimerThread(&sendEvent, evtSwitchTimer, + switchTimers[timerid].start, this)); + + if (Epg2VdrConfig.switchTimerNotifyTime) + timerThreads.push_back(new cTimerThread(&sendEvent, evtSwitchTimer, + switchTimers[timerid].start - Epg2VdrConfig.switchTimerNotifyTime, + this)); + + // at last confirm it + timerDb->setCharValue("ACTION", taAssumed); timerDb->setCharValue("STATE", tsPending); timerDb->store(); diff --git a/update.c b/update.c index 1a39a1d..ae51fe8 100644 --- a/update.c +++ b/update.c @@ -93,6 +93,7 @@ cUpdate::cUpdate(cPluginEPG2VDR* aPlugin) manualTrigger = no; videoBasePath = 0; dbReconnectTriggered = no; + switchTimerTrigger = no; fullreload = no; epgdBusy = yes; @@ -829,6 +830,20 @@ int cUpdate::exitDb() return done; } +//*************************************************************************** +// Send Event +//*************************************************************************** + +void cUpdate::sendEvent(int event, void* userData) +{ + cUpdate* update = (cUpdate*)userData; + cMutexLock lock(&update->eventHookMutex); + + update->eventHook.push(event); + tell(3, "sendEvent(%d)", event); + update->waitCondition.Broadcast(); +} + //*************************************************************************** // Check Connection //*************************************************************************** @@ -1239,6 +1254,39 @@ void cUpdate::Stop() Cancel(10); // wait up to 10 seconds for thread was stopping } +void cUpdate::processEvents() +{ + cMutexLock lock(&eventHookMutex); + + while (!eventHook.empty()) + { + int event = eventHook.front(); + eventHook.pop(); + + switch (event) + { + case evtSwitchTimer: + { + switchTimerTrigger = yes; + break; + } + } + } + + for (auto it = timerThreads.begin(); it != timerThreads.end(); ) + { + if (!(*it)->isActive()) + { + delete *it; + it = timerThreads.erase(it); + } + else + { + it++; + } + } +} + //*************************************************************************** // Action //*************************************************************************** @@ -1265,6 +1313,10 @@ void cUpdate::Action() waitCondition.TimedWait(mutex, 60*1000); + // first process events + + processEvents(); + // we pass here at least once per minute ... if (checkConnection(reconnectTimeout) != success) @@ -1272,7 +1324,8 @@ void cUpdate::Action() // switch timer - checkSwitchTimer(); + if (switchTimerTrigger) + checkSwitchTimer(); // recording stuff diff --git a/update.h b/update.h index 92ebe35..eace297 100644 --- a/update.h +++ b/update.h @@ -115,6 +115,12 @@ class cUpdate : public cThread, public cStatus, public cParameters mmCount }; + enum Event + { + evtUnknown = na, + evtSwitchTimer, + }; + cUpdate(cPluginEPG2VDR* aPlugin); ~cUpdate(); @@ -168,6 +174,7 @@ class cUpdate : public cThread, public cStatus, public cParameters int exitDb(); void Action(void); + void processEvents(); int isHandlerMaster(); void updateVdrData(); int updateRecFolderOption(); @@ -239,6 +246,7 @@ class cUpdate : public cThread, public cStatus, public cParameters int recordingFullReloadTrigger; int storeAllRecordingInfoFilesTrigger; int updateRecFolderOptionTrigger; + int switchTimerTrigger; cList runningRecordings; cMutex runningRecMutex; @@ -300,6 +308,11 @@ class cUpdate : public cThread, public cStatus, public cParameters std::queue pendingNewRecordings; // recordings to store details (obsolete if pendingRecordingActions implemented finally) std::queue pendingRecordingActions; // recordings actions (start/stop) std::map switchTimers; + std::queue eventHook; + cMutex eventHookMutex; + + std::list timerThreads; + static void sendEvent(int event, void* userData); static const char* auxFields[]; }; -- cgit v1.2.3