eOSState cMenuEpgTimers::Delete(void) { // Check if this timer is active: cTimer *ti = CurrentTimer(); if (ti) { if (Interface->Confirm(tr("Delete timer?"))) { if (ti->Recording()) { if (Interface->Confirm(tr("Timer still recording - really delete?"))) { ti->Skip(); cRecordControls::Process(time(NULL)); } else return osContinue; } isyslog("deleting timer %s", *ti->ToDescr()); if(!Timers.Del(ti)) Skins.Message(mtError, trVDR("Could not delete timer")); //cOsdMenu::Del(Current()); Timers.SetModified(); //Display(); } } else { cMenuSwitchTimerItem *item = dynamic_cast<cMenuSwitchTimerItem*> (Get(Current())); if (item && item->switchTimer && Interface->Confirm(tr("Delete switchtimer?"))) { cMutexLock SwitchTimersLock(&SwitchTimers); SwitchTimers.Del(item->switchTimer); SwitchTimers.Save(); Del(Current()); } } return osContinue; }
eOSState cMenuEditSwitchTimer::ProcessKey(eKeys Key) { int iOldMinsBefore = data.switchMinsBefore; eOSState state = cOsdMenu::ProcessKey(Key); if (iOldMinsBefore != data.switchMinsBefore) { time_t now = time(NULL); if (data.event->StartTime() - 60 * data.switchMinsBefore < now) data.switchMinsBefore = iOldMinsBefore; Set(); Display(); } if (state == osUnknown) { switch (Key) { case kOk: { if (switchTimer) { *switchTimer = data; cMutexLock SwitchTimersLock(&SwitchTimers); if (addIfConfirmed) SwitchTimers.Add(switchTimer); SwitchTimers.Save(); } addIfConfirmed = false; return osBack; break; } default: break; } } return state; }
eOSState cMenuSwitchTimers::DeleteAll(void) { if (Interface->Confirm(tr("Edit$Delete all entries?"))) { cMutexLock SwitchTimersLock(&SwitchTimers); while (SwitchTimers.First()) SwitchTimers.Del(SwitchTimers.First()); SwitchTimers.Save(); Set(); } return osContinue; }
eOSState cMenuSwitchTimers::Delete(void) { cSwitchTimer *curSwitchTimer = CurrentSwitchTimer(); if (curSwitchTimer) { if (Interface->Confirm(tr("Edit$Delete entry?"))) { cMutexLock SwitchTimersLock(&SwitchTimers); SwitchTimers.Del(curSwitchTimer); SwitchTimers.Save(); cOsdMenu::Del(Current()); Display(); } } return osContinue; }
void cMenuSwitchTimers::Set() { Clear(); cMutexLock SwitchTimersLock(&SwitchTimers); cSwitchTimer* switchTimer = SwitchTimers.First(); while (switchTimer) { if (switchTimer->event) Add(new cMenuSwitchTimerItem(switchTimer)); switchTimer = SwitchTimers.Next(switchTimer); } Display(); SetHelp(trVDR("Button$Edit"), tr("Button$Delete all"), trVDR("Button$Delete"), NULL); Sort(); }
eOSState cMenuSwitchTimers::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: state = Summary(); break; case kGreen: state = DeleteAll(); break; case kYellow: state = Delete(); break; case kRed: if (HasSubMenu()) return osContinue; if (CurrentSwitchTimer()) state = AddSubMenu(new cMenuEditSwitchTimer(CurrentSwitchTimer())); else state = osContinue; break; case k0: if (CurrentSwitchTimer()) { cSwitchTimer* switchTimer = CurrentSwitchTimer(); switchTimer->announceOnly = 1 - switchTimer->announceOnly; cMutexLock SwitchTimersLock(&SwitchTimers); SwitchTimers.Save(); RefreshCurrent(); Display(); } break; default: break; } } return state; }
bool cPluginEpgsearch::Service(const char *Id, void *Data) { if (strcmp(Id, "MainMenuHooksPatch-v1.0::osSchedule") == 0 && EPGSearchConfig.ReplaceOrgSchedule!=0) { if (Data == NULL) return true; cOsdMenu **menu = (cOsdMenu**) Data; if (menu) *menu = (cOsdMenu*) MainMenuAction(); return true; } if (strcmp(Id, "Epgsearch-search-v1.0") == 0) { if (Data == NULL) return true; cSearchExt* SearchExt = new cSearchExt; Epgsearch_search_v1_0* searchData = (Epgsearch_search_v1_0*) Data; searchData->pResultMenu = NULL; strn0cpy(SearchExt->search,searchData->query, sizeof(SearchExt->search)); if (searchData->channelNr > 0) { #if VDRVERSNUM > 20300 LOCK_CHANNELS_READ; const cChannels *vdrchannels = Channels; #else cChannels *vdrchannels = &Channels; #endif SearchExt->useChannel = true; SearchExt->channelMin = vdrchannels->GetByNumber(searchData->channelNr); SearchExt->channelMax = vdrchannels->GetByNumber(searchData->channelNr); } SearchExt->mode = searchData->mode; SearchExt->useTitle = searchData->useTitle; SearchExt->useSubtitle = searchData->useSubTitle; SearchExt->useDescription = searchData->useDescription; searchData->pResultMenu = new cMenuSearchResultsForSearch(SearchExt, cTemplFile::GetTemplateByName("MenuSearchResults")); return true; } if (strcmp(Id, "Epgsearch-exttimeredit-v1.0") == 0 && !EPGSearchConfig.useVDRTimerEditMenu) { if (Data == NULL) return true; Epgsearch_exttimeredit_v1_0* serviceData = (Epgsearch_exttimeredit_v1_0*) Data; serviceData->pTimerMenu = new cMenuMyEditTimer(serviceData->timer, serviceData->bNew, serviceData->event); return true; } if (strcmp(Id, "Epgsearch-enablesearchtimers-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_enablesearchtimers_v1_0* serviceData = (Epgsearch_enablesearchtimers_v1_0*) Data; if (serviceData->enable && cSearchTimerThread::m_Instance == NULL) cSearchTimerThread::Init(this); else if (!serviceData->enable && cSearchTimerThread::m_Instance != NULL) cSearchTimerThread::Exit(); } return true; } if (strcmp(Id, "Epgsearch-updatesearchtimers-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_updatesearchtimers_v1_0* serviceData = (Epgsearch_updatesearchtimers_v1_0*) Data; if (!EPGSearchConfig.useSearchTimers) // enable search timer thread if necessary cSearchTimerThread::Init((cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"), true); updateForced = serviceData->showMessage?3:1; } return true; } if (strcmp(Id, "Epgsearch-osdmessage-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_osdmessage_v1_0* serviceData = (Epgsearch_osdmessage_v1_0*) Data; Skins.Message(serviceData->type, serviceData->message,5); } return true; } if (strcmp(Id, "Epgsearch-searchmenu-v1.0") == 0) { if (Data == NULL) return true; EpgSearchMenu_v1_0* serviceData = (EpgSearchMenu_v1_0*) Data; serviceData->Menu = new cMenuEPGSearchExt(); return true; } if (strcmp(Id, "Epgsearch-conflictmenu-v1.0") == 0) { if (Data == NULL) return true; EpgSearchMenu_v1_0* serviceData = (EpgSearchMenu_v1_0*) Data; serviceData->Menu = new cMenuConflictCheck(); return true; } if (strcmp(Id, "Epgsearch-lastconflictinfo-v1.0") == 0) { if (Data == NULL) return true; Epgsearch_lastconflictinfo_v1_0* serviceData = (Epgsearch_lastconflictinfo_v1_0*) Data; serviceData->nextConflict = cConflictCheckThread::m_cacheNextConflict; serviceData->relevantConflicts = cConflictCheckThread::m_cacheRelevantConflicts; serviceData->totalConflicts = cConflictCheckThread::m_cacheTotalConflicts; return true; } if (strcmp(Id, "Epgsearch-searchresults-v1.0") == 0) { if (Data == NULL) return true; cSearchExt* SearchExt = new cSearchExt; Epgsearch_searchresults_v1_0* searchData = (Epgsearch_searchresults_v1_0*) Data; searchData->pResultList = NULL; strn0cpy(SearchExt->search,searchData->query, sizeof(SearchExt->search)); if (searchData->channelNr > 0) { #if VDRVERSNUM > 20300 LOCK_CHANNELS_READ; const cChannels *vdrchannels = Channels; #else cChannels *vdrchannels = &Channels; #endif SearchExt->useChannel = true; SearchExt->channelMin = vdrchannels->GetByNumber(searchData->channelNr); SearchExt->channelMax = vdrchannels->GetByNumber(searchData->channelNr); } SearchExt->mode = searchData->mode; SearchExt->useTitle = searchData->useTitle; SearchExt->useSubtitle = searchData->useSubTitle; SearchExt->useDescription = searchData->useDescription; cSearchResults* results = SearchExt->Run(); // transfer to result list if (results) { results->SortBy(CompareEventTime); searchData->pResultList = new cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>; cSearchResult *result = results->First(); while (result) { searchData->pResultList->Add(new Epgsearch_searchresults_v1_0::cServiceSearchResult(result->event)); result = results->Next(result); } } return true; } if (strcmp(Id, "Epgsearch-switchtimer-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_switchtimer_v1_0* serviceData = (Epgsearch_switchtimer_v1_0*) Data; if (!serviceData->event) return false; switch(serviceData->mode){ case 0: {// query existence cSwitchTimer *lTimer = SwitchTimers.InSwitchList(serviceData->event); if (lTimer) { serviceData->switchMinsBefore = lTimer->switchMinsBefore; serviceData->announceOnly = lTimer->mode; } // if serviceData->success=lTimer!=NULL; break; } // 0 case 1: { // add/modify cSwitchTimer *lTimer = SwitchTimers.InSwitchList(serviceData->event); if (lTimer) { lTimer->switchMinsBefore = serviceData->switchMinsBefore; lTimer->mode = serviceData->announceOnly; } else { cMutexLock SwitchTimersLock(&SwitchTimers); SwitchTimers.Add(new cSwitchTimer(serviceData->event,serviceData->switchMinsBefore,serviceData->announceOnly)); SwitchTimers.Save(); cSwitchTimerThread::Init(); } // if serviceData->success=true; break; } // 1 case 2: {// delete cSwitchTimer *lTimer = SwitchTimers.InSwitchList(serviceData->event); serviceData->success=lTimer!=NULL; if (lTimer) { cMutexLock SwitchTimersLock(&SwitchTimers); SwitchTimers.Del(lTimer); SwitchTimers.Save(); } // if break; } // 2 default: serviceData->success=false; break; } // switch } // if return true; } // if if (strcmp(Id, "Epgsearch-quicksearch-v1.0") == 0) { if (Data == NULL) return true; EpgSearchMenu_v1_0* serviceData = (EpgSearchMenu_v1_0*) Data; serviceData->Menu = new cMenuQuickSearch(new cSearchExt); return true; } if (strcmp(Id, "Epgsearch-services-v1.0") == 0) { if (Data == NULL) return true; Epgsearch_services_v1_0* serviceData = (Epgsearch_services_v1_0*) Data; std::auto_ptr<cEpgsearchServiceHandler> autoHandler(new cEpgsearchServiceHandler); serviceData->handler = autoHandler; return true; } if (strcmp(Id, "Epgsearch-services-v1.1") == 0) { if (Data == NULL) return true; Epgsearch_services_v1_1* serviceData = (Epgsearch_services_v1_1*) Data; std::auto_ptr<cEpgsearchServiceHandler> autoHandler(new cEpgsearchServiceHandler); serviceData->handler = autoHandler; return true; } return false; }
void cSearchTimerThread::Action(void) { if (EPGSearchConfig.useExternalSVDRP && !cSVDRPClient::SVDRPSendCmd) { LogFile.eSysLog("ERROR - SVDRPSend script not specified or does not exist (use -f option)"); return; } SetPriority(SEARCHTIMER_NICE); m_Active = true; // let VDR do its startup if (!cPluginEpgsearch::VDR_readyafterStartup) LogFile.Log(2, "SearchTimerThread: waiting for VDR to become ready..."); while(Running() && m_Active && !cPluginEpgsearch::VDR_readyafterStartup) Wait.Wait(1000); time_t nextUpdate = time(NULL); while (m_Active && Running()) { time_t now = time(NULL); bool needUpdate = NeedUpdate(); if (now >= nextUpdate || needUpdate) { justRunning = true; if (updateForced & UPDS_WITH_EPGSCAN) { LogFile.Log(1,"starting EPG scan before search timer update"); EITScanner.ForceScan(); do { Wait.Wait(1000); } while(EITScanner.Active() && m_Active && Running()); LogFile.Log(1,"EPG scan finished"); } if (Timers.BeingEdited()) { Wait.Wait(1000); continue; } LogFile.iSysLog("search timer update started"); UserVars.ResetCache(); // reset internal cache of user vars cTimerObjList* pOutdatedTimers = NULL; // for thread safeness we work with a copy of the current searches, // because SVDRP would not work if the main thread would be locked cSearchExts* localSearchExts = SearchExts.Clone(); localSearchExts->SortBy(CompareSearchExtPrioDescTerm); cSearchExt *searchExt = localSearchExts->First(); // reset announcelist announceList.Clear(); while (searchExt && m_Active && Running()) { if (!searchExt->IsActiveAt(now)) { searchExt = localSearchExts->Next(searchExt); continue; } pOutdatedTimers = searchExt->GetTimerList(pOutdatedTimers); cSearchResults* pSearchResults = searchExt->Run(-1, true); if (!pSearchResults) { searchExt = localSearchExts->Next(searchExt); continue; } pSearchResults->SortBy(CompareEventTime); if (searchExt->pauseOnNrRecordings > 0) searchExt->CheckExistingRecordings(pSearchResults); for (cSearchResult* pResultObj = pSearchResults->First(); pResultObj; pResultObj = pSearchResults->Next(pResultObj)) { if (!Running()) break; const cEvent* pEvent = pResultObj->event; if (!pEvent) continue; cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true); if (!channel) continue; int index = 0; cTimer *timer = new cTimer(pEvent); // create the file char* file = NULL; if ((file = searchExt->BuildFile(pEvent)) != NULL) { while(strstr(file, "!^pipe^!")) file = strreplace(file, "!^pipe^!", "|"); // revert the translation of '|' in BuildFile if (strstr(file, "!^invalid^!") || strlen(file) == 0) { LogFile.eSysLog("Skipping timer due to invalid or empty filename"); if (time(NULL) <= timer->StopTime()) pOutdatedTimers->DelTimer(timer); delete timer; free(file); continue; } timer->SetFile(file); free(file); } int Priority = searchExt->Priority; int Lifetime = searchExt->Lifetime; // search for an already existing timer bool bTimesMatchExactly = false; cTimer *t = GetTimer(searchExt, pEvent, bTimesMatchExactly); char* Summary = NULL; uint timerMod = tmNoChange; if (t) { // already exists pOutdatedTimers->DelTimer(t); if (!t->HasFlags(tfActive)) { // do not update inactive timers LogFile.Log(2,"timer for '%s~%s' (%s - %s, channel %d) not active - won't be touched", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); delete timer; continue; } int triggerID = TriggeredFromSearchTimerID(t); if (!pResultObj->needsTimer && !t->Recording()) // not needed { if (triggerID == searchExt->ID) { LogFile.Log(1,"delete timer for '%s~%s' (%s - %s, channel %d)", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); RemoveTimer(t, pEvent); } else if (triggerID == -1) //manual timer { LogFile.Log(2,"keep obsolete timer for '%s~%s' (%s - %s, channel %d) - was manually created", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); } delete timer; continue; } if (TimerWasModified(t)) // don't touch timer modified by user { LogFile.Log(2,"timer for '%s~%s' (%s - %s, channel %d) modified by user - won't be touched", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); delete timer; continue; } if (triggerID > -1 && triggerID != searchExt->ID) { LogFile.Log(2,"timer for '%s~%s' (%s - %s, channel %d) already created by search id %d - won't be touched", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), triggerID); delete timer; continue; } char* pFile = NULL; // File is prepared for svdrp, so prepare t->File for comparision too msprintf(&pFile, "%s", t->File()); pFile = strreplace(pFile, ':', '|'); pFile = strreplace(pFile, " ~", "~"); pFile = strreplace(pFile, "~ ", "~"); Summary = SummaryExtended(searchExt, t, pEvent); if (bTimesMatchExactly && strcmp(pFile, timer->File()) == 0 && (t->Aux() != NULL && strcmp(t->Aux(), Summary) == 0) ) { // dir, title, episode name and summary have not changed if (Summary) free(Summary); delete timer; free(pFile); continue; } else { if (!bTimesMatchExactly) timerMod = (uint)timerMod | tmStartStop; if (strcmp(pFile, timer->File()) != 0) timerMod |= tmFile; if (t->Aux() != NULL && strcmp(t->Aux(), Summary) != 0) { char* oldEventID = GetAuxValue(t, "eventid"); char* newEventID = GetAuxValue(Summary, "eventid"); if (oldEventID && newEventID && strcmp(oldEventID, newEventID) != 0) timerMod |= tmAuxEventID; free(oldEventID); free(newEventID); } if (LogFile.Level() >= 3) // output reasons for a timer modification { if (timerMod & tmStartStop) LogFile.Log(3,"timer for '%s~%s' (%s - %s, channel %d) : start/stop has changed", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); if (timerMod & tmFile) LogFile.Log(3,"timer for '%s~%s' (%s - %s, channel %d) : title and/or episdode has changed (old: %s, new: %s", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), timer?timer->File():"", pFile); if (timerMod & tmAuxEventID) LogFile.Log(3,"timer for '%s~%s' (%s - %s, channel %d) : aux info for event id has changed", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); } index = t->Index()+1; Priority = t->Priority(); Lifetime = t->Lifetime(); } free(pFile); if (t->Recording() && t->StopTime() == timer->StopTime()) { // only update recording timers if stop time has changed, since all other settings can't be modified LogFile.Log(2,"timer for '%s~%s' (%s - %s, channel %d) already recording - no changes possible", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); delete timer; continue; } } else { if (!pResultObj->needsTimer) { delete timer; continue; } } if (searchExt->action == searchTimerActionAnnounceViaOSD) { if (t || // timer already exists or NoAnnounces.InList(pEvent) || // announcement not wanted anymore or (EPGSearchConfig.noAnnounceWhileReplay && cDevice::PrimaryDevice()->Replaying() && !(updateForced & UPDS_WITH_OSD)) // no announce while replay within automatic updates ) { if (Summary) free(Summary); delete timer; continue; } if (!announceList.Lookup(pEvent)) announceList.Add(new cSearchResult(pEvent, searchExt->ID)); if (Summary) free(Summary); delete timer; continue; } if (searchExt->action == searchTimerActionAnnounceViaMail) { if (t || // timer already exists or NoAnnounces.InList(pEvent) || pEvent->StartTime() < time(NULL)) // already started? { if (Summary) free(Summary); delete timer; continue; } mailNotifier.AddAnnounceEventNotification(pEvent->EventID(), pEvent->ChannelID(), searchExt->ID); if (Summary) free(Summary); delete timer; continue; } if (searchExt->action == searchTimerActionSwitchOnly || searchExt->action == searchTimerActionAnnounceAndSwitch) // add to switch list { time_t now = time(NULL); if (now < pEvent->StartTime()) { if (!SwitchTimers.InSwitchList(pEvent)) { cMutexLock SwitchTimersLock(&SwitchTimers); int mode = 0; if (searchExt->action == searchTimerActionAnnounceAndSwitch) mode = 2; LogFile.Log(3,"adding switch timer event for '%s~%s' (%s - %s); search timer: '%s'", pEvent->Title(), pEvent->ShortText()?pEvent->ShortText():"", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), searchExt->search); SwitchTimers.Add(new cSwitchTimer(pEvent, searchExt->switchMinsBefore, mode, searchExt->unmuteSoundOnSwitch)); SwitchTimers.Save(); cSwitchTimerThread::Init(); } } if (Summary) free(Summary); delete timer; continue; } if (AddModTimer(timer, index, searchExt, pEvent, Priority, Lifetime, Summary, timerMod)) { if (index == 0) LogFile.Log(1,"added timer for '%s~%s' (%s - %s); search timer: '%s'", pEvent->Title(), pEvent->ShortText()?pEvent->ShortText():"", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), searchExt->search); else LogFile.Log(1,"modified timer %d for '%s~%s' (%s - %s); search timer: '%s'", index, pEvent->Title(), pEvent->ShortText()?pEvent->ShortText():"", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), searchExt->search); } if (Summary) free(Summary); delete timer; } delete pSearchResults; searchExt = localSearchExts->Next(searchExt); } if (localSearchExts) delete localSearchExts; if (pOutdatedTimers) { if (pOutdatedTimers->Count() > 0) { LogFile.Log(1,"removing outdated timers"); for(cTimerObj *tObj = pOutdatedTimers->First(); tObj; tObj = pOutdatedTimers->Next(tObj)) { cTimer* t = tObj->timer; // timer could have been deleted meanwhile, so check if its still there bool found = false; for(cTimer* checkT = Timers.First(); checkT; checkT = Timers.Next(checkT)) if (checkT == t) { found = true; break; } if (!found) continue; if (TimerWasModified(t)) continue; if (!t->Event()) continue; // if there is no event, we keep the timer, since EPG could have been cleared if (time(NULL) > t->StopTime()) continue; // if this timer has (just) finished, let VDR do the cleanup if (t->Recording()) continue; // do not remove recording timers LogFile.Log(1,"delete timer for '%s' (%s, channel %s)", t->File(), DAYDATETIME(t->StartTime()), CHANNELNAME(t->Channel())); RemoveTimer(t, t->Event()); } LogFile.Log(1,"removing outdated timers - done"); } delete pOutdatedTimers; } TimersDone.ClearOutdated(); TimersDone.Save(); if (announceList.Count() > 0) { cString msgfmt = cString::sprintf(tr("%d new broadcast(s) found! Show them?"), announceList.Count()); if (SendMsg(msgfmt, true,7) == kOk) { m_plugin->showAnnounces = true; cRemote::CallPlugin("epgsearch"); } } CheckEPGHours(); LogFile.iSysLog("search timer update finished"); // check for conflicts if (EPGSearchConfig.checkTimerConflictsAfterUpdate && m_Active && Running()) { LogFile.iSysLog("check for timer conflicts"); cConflictCheck conflictCheck; conflictCheck.Check(); if (conflictCheck.relevantConflicts > 0) { if (EPGSearchConfig.sendMailOnConflicts) { cMailConflictNotifier mailNotifier; mailNotifier.SendConflictNotifications(conflictCheck); } conflictCheck.EvaluateConflCheckCmd(); cString msgfmt = cString::sprintf(tr("%d timer conflict(s)! First at %s. Show them?"), conflictCheck.relevantConflicts, *DateTime(conflictCheck.nextRelevantConflictDate)); bool doMessage = EPGSearchConfig.noConflMsgWhileReplay == 0 || !cDevice::PrimaryDevice()->Replaying() || conflictCheck.nextRelevantConflictDate - now < 2*60*60 || (updateForced & UPDS_WITH_OSD); if (doMessage && SendMsg(msgfmt, true,7) == kOk) { m_plugin->showConflicts = true; cRemote::CallPlugin("epgsearch"); } } LogFile.iSysLog("check for timer conflicts - done"); } // delete expired recordings CheckExpiredRecs(); // check for updates for manual timers CheckManualTimers(); if (m_Active) mailNotifier.SendUpdateNotifications(); if ((updateForced & UPDS_WITH_OSD) && m_Active) SendMsg(tr("Search timer update done!")); // reset service call flag updateForced = 0; m_lastUpdate = time(NULL); nextUpdate = long(m_lastUpdate/60)*60 + (EPGSearchConfig.UpdateIntervall * 60); justRunning = false; } if (m_Active && Running()) Wait.Wait(2000); // to avoid high system load if time%30==0 while (Running() && m_Active && !NeedUpdate() && time(NULL)%30 != 0) // sync heart beat to a multiple of 5secs Wait.Wait(1000); }; LogFile.iSysLog("Leaving search timer thread"); }