diff options
-rw-r--r-- | HISTORY.h | 7 | ||||
-rw-r--r-- | lib/common.c | 48 | ||||
-rw-r--r-- | lib/common.h | 28 | ||||
-rw-r--r-- | menu.c | 2 | ||||
-rw-r--r-- | timer.c | 18 | ||||
-rw-r--r-- | update.c | 55 | ||||
-rw-r--r-- | update.h | 13 |
7 files changed, 166 insertions, 5 deletions
@@ -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 @@ -414,6 +414,34 @@ class LogDuration }; //*************************************************************************** +// 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 //*************************************************************************** @@ -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", @@ -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(); @@ -93,6 +93,7 @@ cUpdate::cUpdate(cPluginEPG2VDR* aPlugin) manualTrigger = no; videoBasePath = 0; dbReconnectTriggered = no; + switchTimerTrigger = no; fullreload = no; epgdBusy = yes; @@ -830,6 +831,20 @@ int cUpdate::exitDb() } //*************************************************************************** +// 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 @@ -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<cRunningRecording> runningRecordings; cMutex runningRecMutex; @@ -300,6 +308,11 @@ class cUpdate : public cThread, public cStatus, public cParameters std::queue<std::string> pendingNewRecordings; // recordings to store details (obsolete if pendingRecordingActions implemented finally) std::queue<RecordingAction> pendingRecordingActions; // recordings actions (start/stop) std::map<long,SwitchTimer> switchTimers; + std::queue<int> eventHook; + cMutex eventHookMutex; + + std::list<cTimerThread*> timerThreads; + static void sendEvent(int event, void* userData); static const char* auxFields[]; }; |