/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "conflictcheck_thread.h" #include "epgsearchcfg.h" #include "mail.h" #include "epgsearch.h" #define CONFLICTCHECK_NICE 19 cConflictCheckThread *cConflictCheckThread::m_Instance = NULL; time_t cConflictCheckThread::m_cacheNextConflict = 0; int cConflictCheckThread::m_cacheRelevantConflicts = 0; int cConflictCheckThread::m_cacheTotalConflicts = 0; bool cConflictCheckThread::m_runOnce = false; bool cConflictCheckThread::m_forceUpdate = false; cConflictCheckThread::cConflictCheckThread(cPluginEpgsearch* thePlugin) : cThread("EPGSearch: conflictcheck") { m_plugin = thePlugin; m_Active = false; m_lastUpdate = time(NULL); m_runOnce = false; m_forceUpdate = false; } cConflictCheckThread::~cConflictCheckThread() { if (m_Active) Stop(); } void cConflictCheckThread::Init(cPluginEpgsearch* thePlugin, bool runOnce) { if (EPGSearchConfig.checkTimerConflictsAfterUpdate || EPGSearchConfig.conflictCheckIntervall == 0) { if (!runOnce) return; m_runOnce = true; } if (m_Instance == NULL) { m_Instance = new cConflictCheckThread(thePlugin); m_Instance->Start(); } else if (runOnce) m_forceUpdate = true; // force an update, because thread is already running } void cConflictCheckThread::Exit(void) { if (m_Instance != NULL) { m_Instance->Stop(); DELETENULL(m_Instance); } } void cConflictCheckThread::Stop(void) { m_Active = false; Wait.Signal(); Cancel(6); } void cConflictCheckThread::Action(void) { SetPriority(CONFLICTCHECK_NICE); m_Active = true; // let VDR do its startup if (!m_runOnce) { if (!cPluginEpgsearch::VDR_readyafterStartup) LogFile.Log(2, "ConflictCheckThread: waiting for VDR to become ready..."); while(m_Active && !cPluginEpgsearch::VDR_readyafterStartup) Wait.Wait(1000); } time_t nextUpdate = time(NULL); while (m_Active && Running()) { time_t now = time(NULL); if (now >= nextUpdate || m_forceUpdate) { m_forceUpdate = false; { LOCK_TIMERS_WRITE; Timers->SetExplicitModify(); } LogFile.iSysLog("timer conflict check started"); cConflictCheck conflictCheck; conflictCheck.Check(); time_t nextConflict = 0; if (conflictCheck.relevantConflicts > 0) { cString msgfmt = ""; if (conflictCheck.relevantConflicts == 1) msgfmt = cString::sprintf(tr("timer conflict at %s! Show it?"), *DateTime(conflictCheck.nextRelevantConflictDate)); else msgfmt = cString::sprintf(tr("%d timer conflicts! First at %s. Show them?"), conflictCheck.relevantConflicts, *DateTime(conflictCheck.nextRelevantConflictDate)); bool doMessage = EPGSearchConfig.noConflMsgWhileReplay == 0 || !cDevice::PrimaryDevice()->Replaying() || conflictCheck.nextRelevantConflictDate - now < 2*60*60; if (doMessage && SendMsg(msgfmt, true,7, mtWarning) == kOk) { m_plugin->showConflicts = true; cRemote::CallPlugin("epgsearch"); } if (EPGSearchConfig.sendMailOnConflicts) { cMailConflictNotifier mailNotifier; mailNotifier.SendConflictNotifications(conflictCheck); } conflictCheck.EvaluateConflCheckCmd(); } // store for external access cConflictCheckThread::m_cacheNextConflict = conflictCheck.nextRelevantConflictDate; cConflictCheckThread::m_cacheRelevantConflicts = conflictCheck.relevantConflicts; cConflictCheckThread::m_cacheTotalConflicts = conflictCheck.numConflicts; LogFile.iSysLog("timer conflict check finished"); m_lastUpdate = time(NULL); int Intervall = EPGSearchConfig.conflictCheckIntervall; if (nextConflict > 0 && EPGSearchConfig.conflictCheckWithinLimit > 0 && nextConflict - time(NULL) < EPGSearchConfig.conflictCheckWithinLimit * 60) Intervall = EPGSearchConfig.conflictCheckIntervall2; nextUpdate = long(m_lastUpdate/60)*60 + (Intervall * 60); } if (m_Active && Running()) Wait.Wait(2000); // to avoid high system load if time%30==0 ????????????????????? // no waiting in the while loop if m_runOnce is true while (Running() && m_Active && time(NULL)%30 != 0 && !m_runOnce) // sync heart beat to a multiple of 5secs Wait.Wait(1000); }; m_Active = false; // always false at this point LogFile.iSysLog("Leaving conflict check thread"); }