#define __STL_CONFIG_H #include #include #include #include #include #include "services/remotetimers.h" #include "tools.h" #include "switchtimer.h" #include "timerconflict.h" #include #include "recmanager.h" static int CompareRecording(const void *p1, const void *p2) { return (int)((*(cRecording **)p1)->Start() - (*(cRecording **)p2)->Start()); } cRecManager::cRecManager(void) { epgSearchPlugin = NULL; epgSearchAvailable = false; } cRecManager::~cRecManager(void) { } void cRecManager::SetEPGSearchPlugin(void) { epgSearchPlugin = cPluginManager::GetPlugin("epgsearch"); if (epgSearchPlugin) { epgSearchAvailable = true; } } bool cRecManager::RefreshRemoteTimers(void) { cString errorMsg; if (!pRemoteTimers->Service("RemoteTimers::RefreshTimers-v1.0", &errorMsg)) { esyslog("tvguide: %s", *errorMsg); return false; } return true; } bool cRecManager::CheckEventForTimer(const cEvent *event) { bool hasTimer = false; if (config.useRemoteTimers && pRemoteTimers) { RemoteTimers_GetMatch_v1_0 rtMatch; rtMatch.event = event; pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); if (rtMatch.timerMatch == tmFull) hasTimer = true; } else { #if VDRVERSNUM >= 20301 eTimerMatch TimerMatch = tmNone; LOCK_TIMERS_READ; const cTimers *timers = Timers; if (timers->GetMatch(event, &TimerMatch) && (TimerMatch == tmFull)) hasTimer = true; #else hasTimer = event->HasTimer(); #endif } return hasTimer; } const cTimer *cRecManager::GetTimerForEvent(const cEvent *event) { const cTimer *timer = NULL; if (config.useRemoteTimers && pRemoteTimers) { RemoteTimers_GetMatch_v1_0 rtMatch; rtMatch.event = event; pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); timer = rtMatch.timer; return timer; } #if VDRVERSNUM >= 20301 LOCK_TIMERS_READ; timer = Timers->GetMatch(event); #else timer = Timers.GetMatch(event); #endif return timer; } cTimer *cRecManager::createTimer(const cEvent *event, std::string path) { cTimer *timer = NULL; if (config.useRemoteTimers && pRemoteTimers) { timer = createRemoteTimer(event, path); } else { timer = createLocalTimer(event, path); } return timer; } cTimer *cRecManager::createLocalTimer(const cEvent *event, std::string path) { cTimer *timer = new cTimer(event); #if VDRVERSNUM >= 20301 LOCK_TIMERS_WRITE; cTimers* timers = Timers; timers->SetExplicitModify(); if (Setup.SVDRPPeering && *Setup.SVDRPDefaultHost) timer->SetRemote(Setup.SVDRPDefaultHost); #else cTimers* timers = &Timers; #endif cTimer *t = timers->GetTimer(timer); if (t) { t->OnOff(); #if VDRVERSNUM >= 20301 t->SetEvent(event); #else t->SetEventFromSchedule(); #endif delete timer; timer = t; isyslog("timer %s reactivated", *t->ToDescr()); } else { SetTimerPath(timer, event, path); timers->Add(timer); timers->SetModified(); #if VDRVERSNUM >= 20301 if (!HandleRemoteTimerModifications(timer)) { timers->Del(timer); esyslog(tr("tvguide: RemoteTimerModifications failed")); } else { isyslog("timer %s added (active)", *timer->ToDescr()); } #else isyslog("timer %s added (active)", *timer->ToDescr()); #endif } return timers->GetTimer(timer); } cTimer *cRecManager::createRemoteTimer(const cEvent *event, std::string path) { cTimer *t = new cTimer(event); SetTimerPath(t, event, path); RemoteTimers_Timer_v1_0 rt; rt.timer = t; pRemoteTimers->Service("RemoteTimers::GetTimer-v1.0", &rt.timer); if (rt.timer) { rt.timer->OnOff(); if (!pRemoteTimers->Service("RemoteTimers::ModTimer-v1.0", &rt)) rt.timer = NULL; } else { rt.timer = t; if (!pRemoteTimers->Service("RemoteTimers::NewTimer-v1.0", &rt)) isyslog("%s", *rt.errorMsg); } RefreshRemoteTimers(); return rt.timer; } void cRecManager::SetTimerPath(cTimer *timer, const cEvent *event, std::string path) { if (config.instRecFolderMode == eFolderFixed) { Epgsearch_services_v1_2 *epgSearch = new Epgsearch_services_v1_2; std::string recDir = config.instRecFixedFolder; std::replace(recDir.begin(), recDir.end(), '/', '~'); if (strchr(recDir.c_str(), '%') != NULL) { if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::string newFileName = epgSearch->handler->Evaluate(recDir, event); if (strchr(newFileName.c_str(), '%') == NULL) // only set directory to new value if all categories could have been replaced timer->SetFile(newFileName.c_str()); else esyslog("tvguide: timer path not set because replacing variable was not successfull: %s", newFileName.c_str()); } } else { cString newFileName; if (recDir.size() > 0) { newFileName = cString::sprintf("%s~%s", recDir.c_str(), timer->File()); timer->SetFile(*newFileName); } } return; } //Set choosen path bool addSubtitle = false; if (!isempty(event->ShortText())) { // add subtitle if present addSubtitle = (config.addSubtitleToTimer != addSubtitleNever); if (config.addSubtitleToTimer == addSubtitleSmart) if (event->Duration() > 80 * 60) addSubtitle = false; } cString newFileName; if (path.size() > 0) { std::replace(path.begin(), path.end(), '/', '~'); if (addSubtitle) newFileName = cString::sprintf("%s~%s~%s", path.c_str(), event->Title(), event->ShortText()); else newFileName = cString::sprintf("%s~%s", path.c_str(), timer->File()); } else { if (addSubtitle) newFileName = cString::sprintf("%s~%s", event->Title(), event->ShortText()); else newFileName = event->Title(); } timer->SetFile(*newFileName); } void cRecManager::DeleteTimer(const cEvent *event) { if (!event) return; if (config.useRemoteTimers && pRemoteTimers) { DeleteRemoteTimer(event); } else { DeleteLocalTimer(event); } } void cRecManager::DeleteLocalTimer(const cEvent *event) { const cTimer *t; #if VDRVERSNUM >= 20301 { LOCK_TIMERS_READ; t = Timers->GetMatch(event); } #else t = Timers.GetMatch(event); #endif if (!t) return; DeleteTimer(t); } void cRecManager::DeleteTimer(const cTimer *timer) { #if VDRVERSNUM >= 20301 LOCK_TIMERS_WRITE; cTimers* timers = Timers; if (timer && timer->Remote() && !timer->Recording()) { if (HandleRemoteTimerModifications(NULL, (cTimer*)timer)) { timers->Del((cTimer*)timer); } timers->SetModified(); } cTimer* t = timers->GetTimer(timer); #else cTimers* timers = &Timers; cTimer* t = timers->GetTimer((cTimer*)timer); #endif if (!t) return; if (t->Recording()) { t->Skip(); #if VDRVERSNUM >= 20301 cRecordControls::Process(timers, time(NULL)); #else cRecordControls::Process(time(NULL)); #endif } isyslog("timer %s deleted", *t->ToDescr()); timers->Del(t, true); timers->SetModified(); } void cRecManager::DeleteRemoteTimer(const cEvent *event) { RemoteTimers_GetMatch_v1_0 rtMatch; rtMatch.event = event; pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch); if (rtMatch.timer) { RemoteTimers_Timer_v1_0 rt; rt.timer = rtMatch.timer; isyslog("remotetimer %s deleted", *rt.timer->ToDescr()); if (!pRemoteTimers->Service("RemoteTimers::DelTimer-v1.0", &rt)) isyslog("remotetimer error"); RefreshRemoteTimers(); } } void cRecManager::OnOffTimer(const cEvent *event) { const cTimer *t; #if VDRVERSNUM >= 20301 { LOCK_TIMERS_READ; t = Timers->GetMatch(event); } #else t = Timers.GetMatch(event); #endif if (!t) return; SaveTimer(t); } void cRecManager::SaveTimer(const cTimer *t, cTimer *newTimerSettings) { if (!t) return; #if VDRVERSNUM >= 20301 LOCK_TIMERS_WRITE; cTimers* timers = Timers; timers->SetExplicitModify(); if (t && t->Remote()) { if (!HandleRemoteTimerModifications(newTimerSettings, (cTimer *)t)) { esyslog(tr("tvguide: RemoteTimerModifications failed")); } } cTimer *timer = timers->GetTimer(t); #else cTimers* timers = &Timers; cTimer *timer = timers->GetTimer((cTimer *)t); #endif if (!timer) { return; } bool active = true; if (newTimerSettings) { int prio = newTimerSettings->Priority(); int lifetime = newTimerSettings->Lifetime(); time_t day = newTimerSettings->Day(); int start = newTimerSettings->Start(); int stop = newTimerSettings->Stop(); std::string fileName = newTimerSettings->File(); timer->SetDay(day); timer->SetStart(start); timer->SetStop(stop); timer->SetPriority(prio); timer->SetLifetime(lifetime); timer->SetFile(fileName.c_str()); active = newTimerSettings->HasFlags(tfActive); } else active = !timer->HasFlags(tfActive); if (active) timer->SetFlags(tfActive); else timer->ClrFlags(tfActive); #if VDRVERSNUM < 20300 timer->SetEventFromSchedule(); #endif if (config.useRemoteTimers && pRemoteTimers) { RemoteTimers_Timer_v1_0 rt; rt.timer = timer; if (!pRemoteTimers->Service("RemoteTimers::ModTimer-v1.0", &rt)) rt.timer = NULL; RefreshRemoteTimers(); } else { timers->SetModified(); } } bool cRecManager::IsRecorded(const cEvent *event) { #if VDRVERSNUM >= 20301 LOCK_TIMERS_WRITE; cTimer *timer = Timers->GetMatch(event); #else cTimer *timer = Timers.GetMatch(event); #endif if (!timer) return false; return timer->Recording(); } cTVGuideTimerConflicts *cRecManager::CheckTimerConflict(void) { cTVGuideTimerConflicts *conflictList = new cTVGuideTimerConflicts(); if (!epgSearchAvailable) return conflictList; Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::list conflicts = epgSearch->handler->TimerConflictList(); int numConflicts = conflicts.size(); if (numConflicts == 0) return conflictList; for (std::list::iterator it=conflicts.begin(); it != conflicts.end(); ++it) { conflictList->AddConflict(*it); } } delete epgSearch; conflictList->CalculateConflicts(); return conflictList; } void cRecManager::CreateSeriesTimer(cTimer *seriesTimer) { #if VDRVERSNUM < 20300 seriesTimer->SetEventFromSchedule(); #endif if (config.useRemoteTimers && pRemoteTimers) { RemoteTimers_Timer_v1_0 rt; rt.timer = seriesTimer; if (!pRemoteTimers->Service("RemoteTimers::NewTimer-v1.0", &rt)) isyslog("%s", *rt.errorMsg); RefreshRemoteTimers(); } else { #if VDRVERSNUM >= 20301 LOCK_TIMERS_WRITE; cTimers* timers = Timers; #else cTimers* timers = &Timers; #endif timers->Add(seriesTimer); timers->SetModified(); } } void cRecManager::ReadEPGSearchTemplates(std::vector *epgTemplates) { cString ConfigDir = cPlugin::ConfigDirectory("epgsearch"); cString epgsearchConf = "epgsearchtemplates.conf"; cString fileName = AddDirectory(*ConfigDir, *epgsearchConf); if (access(fileName, F_OK) == 0) { FILE *f = fopen(fileName, "r"); if (f) { char *s; cReadLine ReadLine; while ((s = ReadLine.Read(f)) != NULL) { char *p = strchr(s, '#'); if (p) *p = 0; stripspace(s); try { if (!isempty(s)) { std::string templ = s; int posID = templ.find_first_of(":"); int posName = templ.find_first_of(":", posID+1); std::string name = templ.substr(posID+1, posName - posID - 1); std::string templValue = templ.substr(posName); TVGuideEPGSearchTemplate tmp; tmp.name = name; tmp.templValue = templValue; epgTemplates->push_back(tmp); } } catch (...){} } } } } const cEvent **cRecManager::PerformSearchTimerSearch(std::string epgSearchString, int &numResults) { if (!epgSearchAvailable) return NULL; const cEvent **searchResults = NULL; Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::list results = epgSearch->handler->QuerySearch(epgSearchString); numResults = results.size(); if (numResults > 0) { searchResults = new const cEvent *[numResults]; const cSchedules *schedules; #if VDRVERSNUM >= 20301 { LOCK_SCHEDULES_READ; schedules = Schedules; } #else cSchedulesLock schedulesLock; schedules = cSchedules::Schedules(schedulesLock); #endif const cEvent *event = NULL; int index=0; for (std::list::iterator it=results.begin(); it != results.end(); ++it) { try { splitstring s(it->c_str()); std::vector flds = s.split(':', 1); int eventID = atoi(flds[1].c_str()); std::string channelID = flds[7]; tChannelID chanID = tChannelID::FromString(channelID.c_str()); const cChannel *channel; #if VDRVERSNUM >= 20301 { LOCK_CHANNELS_READ; channel = Channels->GetByChannelID(chanID); } #else channel = Channels.GetByChannelID(chanID); #endif if (channel) { const cSchedule *Schedule = NULL; Schedule = schedules->GetSchedule(channel); event = Schedule->GetEvent(eventID); if (event) { searchResults[index] = event; } else return NULL; } else return NULL; index++; } catch (...){} } } } return searchResults; } const cEvent **cRecManager::PerformSearch(Epgsearch_searchresults_v1_0 data, int &numResults) { if (epgSearchAvailable) { if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) { cList *list = data.pResultList; if (!list) return NULL; int numElements = list->Count(); const cEvent **searchResults = NULL; if (numElements > 0) { searchResults = new const cEvent *[numElements]; numResults = numElements; int index = 0; for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r ; r = list->Next(r)) { searchResults[index] = r->event; index++; } } delete list; return searchResults; } } return NULL; } void cRecManager::GetSearchTimers(std::vector *searchTimer) { if (!epgSearchAvailable) { return; } Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::list searchTimerList; searchTimerList = epgSearch->handler->SearchTimerList(); for(std::list::iterator it = searchTimerList.begin(); it != searchTimerList.end(); it++) { cTVGuideSearchTimer timer; timer.SetEPGSearchString(it->c_str()); if (timer.Parse()) searchTimer->push_back(timer); } } std::sort(searchTimer->begin(), searchTimer->end()); } void cRecManager::GetSearchExtCats(std::vector *searchExtCats) { if (!epgSearchAvailable) { return; } Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::list list; list = epgSearch->handler->ExtEPGInfoList(); for (std::list::iterator it = list.begin(); it != list.end(); it++) { searchExtCats->push_back(*it); } } } void cRecManager::GetChannelGroups(std::vector *channelGroups) { if (!epgSearchAvailable) { return; } Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::list list; list = epgSearch->handler->ChanGrpList(); for (std::list::iterator it = list.begin(); it != list.end(); it++) { channelGroups->push_back(*it); } } std::sort(channelGroups->begin(), channelGroups->end()); } void cRecManager::GetBlacklists(std::vector *blacklists) { if (!epgSearchAvailable) { return; } Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::list list; list = epgSearch->handler->BlackList(); for (std::list::iterator it = list.begin(); it != list.end(); it++) { blacklists->push_back(*it); } } } int cRecManager::CreateSearchTimer(std::string epgSearchString) { int timerID = -1; if (!epgSearchAvailable) return timerID; Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { timerID = epgSearch->handler->AddSearchTimer(epgSearchString); } return timerID; } bool cRecManager::SaveSearchTimer(cTVGuideSearchTimer *searchTimer) { if (!epgSearchAvailable) return false; Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (searchTimer->GetID() > -1) { if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { bool success = epgSearch->handler->ModSearchTimer(searchTimer->BuildSearchString()); if (success) { esyslog("tvguide: search timer with id %d sucessfully modified", searchTimer->GetID()); return true; } else { esyslog("tvguide: error modifying search timer with id %d, build string %s", searchTimer->GetID(), searchTimer->BuildSearchString().c_str()); return false; } } } else { if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { int timerID = epgSearch->handler->AddSearchTimer(searchTimer->BuildSearchString()); if (timerID >=0) { esyslog("tvguide: search timer with id %d sucessfully created", timerID); return true; } else { esyslog("tvguide: error creating search timer, build string %s", searchTimer->BuildSearchString().c_str()); return false; } } } return false; } void cRecManager::DeleteSearchTimer(cTVGuideSearchTimer *searchTimer, bool delTimers) { if (!epgSearchAvailable) return; int searchTimerID = searchTimer->GetID(); if (delTimers) { cTimers* timers; #if VDRVERSNUM >= 20301 { LOCK_TIMERS_WRITE; timers = Timers; } #else timers = &Timers; #endif cTimer *timer = timers->First(); while (timer) { if (!timer->Recording()) { char* searchID = GetAuxValue(timer, "s-id"); if (searchID) { if (searchTimerID == atoi(searchID)) { cTimer* timerNext = timers->Next(timer); DeleteTimer(timer); timer = timerNext; } else { timer = timers->Next(timer); } free(searchID); } else { timer = timers->Next(timer); } } else { timer = timers->Next(timer); } } } Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { bool success = epgSearch->handler->DelSearchTimer(searchTimerID); if (success) { esyslog("tvguide: search timer \"%s\" sucessfully deleted", searchTimer->GetSearchString().c_str()); } else { esyslog("tvguide: error deleting search timer \"%s\"", searchTimer->GetSearchString().c_str()); } } } void cRecManager::UpdateSearchTimers(void) { if (epgSearchAvailable) { Epgsearch_updatesearchtimers_v1_0 data; data.showMessage = false; epgSearchPlugin->Service("Epgsearch-updatesearchtimers-v1.0", &data); } } // switchMode: 0 = switch, 1 = announce only, 2 = ask for switch bool cRecManager::CreateSwitchTimer(const cEvent *event, cSwitchTimer switchTimer) { if (epgSearchAvailable && event) { Epgsearch_switchtimer_v1_0 data; data.event = event; data.mode = 1; data.switchMinsBefore = switchTimer.switchMinsBefore; data.announceOnly = switchTimer.switchMode; data.success = false; epgSearchPlugin->Service("Epgsearch-switchtimer-v1.0", &data); cSwitchTimer *t = new cSwitchTimer(event); SwitchTimers.Add(t); return data.success; } return false; } void cRecManager::DeleteSwitchTimer(const cEvent *event) { SwitchTimers.DeleteSwitchTimer(event); if (epgSearchAvailable) { Epgsearch_switchtimer_v1_0 data; data.event = event; data.mode = 2; data.switchMinsBefore = 0; data.announceOnly = 0; data.success = false; epgSearchPlugin->Service("Epgsearch-switchtimer-v1.0", &data); } } const cRecording **cRecManager::SearchForRecordings(std::string searchString, int &numResults) { const cRecording **matchingRecordings = NULL; int num = 0; numResults = 0; #if VDRVERSNUM >= 20301 LOCK_RECORDINGS_READ; const cRecordings* recordings = Recordings; #else const cRecordings* recordings = &Recordings; #endif for (const cRecording *recording = recordings->First(); recording; recording = recordings->Next(recording)) { std::string s1 = recording->Name(); std::string s2 = searchString; if (s1.empty() || s2.empty()) continue; // tolerance for fuzzy searching: 90% of the shorter text length, but at least 1 int tolerance = std::max(1, (int)std::min(s1.size(), s2.size()) / 10); bool match = FindIgnoreCase(s1, s2) >= 0 || FindIgnoreCase(s2, s1) >= 0; if (!match) { AFUZZY af = { NULL, NULL, NULL, NULL, NULL, NULL, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 }; if (s1.size() > 32) s1 = s1.substr(0, 32); afuzzy_init(s1.c_str(), tolerance, 0, &af); /* Checking substring */ int res = afuzzy_checkSUB(s2.c_str(), &af); afuzzy_free(&af); match = (res > 0); } if (!match) { AFUZZY af = { NULL, NULL, NULL, NULL, NULL, NULL, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 }; if (s2.size() > 32) s2 = s2.substr(0, 32); afuzzy_init(s2.c_str(), tolerance, 0, &af); /* Checking substring */ int res = afuzzy_checkSUB(s1.c_str(), &af); afuzzy_free(&af); match = (res > 0); } if (match) { matchingRecordings = (const cRecording **)realloc(matchingRecordings, (num + 1) * sizeof(cRecording *)); matchingRecordings[num++] = recording; } } if (num > 0) { qsort(matchingRecordings, num, sizeof(cRecording *), CompareRecording); numResults = num; return matchingRecordings; } return NULL; } const cEvent **cRecManager::LoadReruns(const cEvent *event, int &numResults) { if (epgSearchAvailable && !isempty(event->Title())) { Epgsearch_searchresults_v1_0 data; std::string strQuery = event->Title(); if (config.useSubtitleRerun > 0) { if (config.useSubtitleRerun == 2 || !isempty(event->ShortText())) strQuery += "~"; if (!isempty(event->ShortText())) strQuery += event->ShortText(); data.useSubTitle = true; } else { data.useSubTitle = false; } data.query = (char *)strQuery.c_str(); data.mode = 0; data.channelNr = 0; data.useTitle = true; data.useDescription = false; if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) { cList* list = data.pResultList; if (!list) return NULL; const cEvent **searchResults = NULL; int numElements = list->Count(); if (numElements > 0) { searchResults = new const cEvent *[numElements]; int index = 0; for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r; r = list->Next(r)) { if ((event->ChannelID() == r->event->ChannelID()) && (event->StartTime() == r->event->StartTime())) continue; searchResults[index] = r->event; index++; } delete list; numResults = index; return searchResults; } } } return NULL; } void cRecManager::GetFavorites(std::vector *favorites) { if (!epgSearchAvailable) { return; } Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1; if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) { std::list searchTimerList; searchTimerList = epgSearch->handler->SearchTimerList(); for(std::list::iterator it = searchTimerList.begin(); it != searchTimerList.end(); it++) { cTVGuideSearchTimer timer; timer.SetEPGSearchString(it->c_str()); if (timer.Parse()) { if (timer.UseInFavorites()) favorites->push_back(timer); } } } } const cEvent **cRecManager::WhatsOnNow(bool nowOrNext, int &numResults) { std::vector tmpResults; #if VDRVERSNUM >= 20301 LOCK_CHANNELS_READ; const cChannels* channels = Channels; LOCK_SCHEDULES_READ; const cSchedules* schedules = Schedules; #else cChannels* channels = &Channels; cSchedulesLock schedulesLock; const cSchedules *schedules = cSchedules::Schedules(schedulesLock); #endif const cChannel *startChannel = NULL, *stopChannel = NULL; if (config.favLimitChannels) { startChannel = channels->GetByNumber(config.favStartChannel); stopChannel = channels->GetByNumber(config.favStopChannel); } if (!startChannel) startChannel = channels->First(); for (const cChannel *channel = startChannel; channel; channel = channels->Next(channel)) { if (channel->GroupSep()) continue; const cSchedule *Schedule = schedules->GetSchedule(channel); if (!Schedule) continue; const cEvent *event = NULL; if (nowOrNext) event = Schedule->GetPresentEvent(); else event = Schedule->GetFollowingEvent(); if (event) { tmpResults.push_back(event); } if (stopChannel && (stopChannel->Number() <= channel->Number())) break; } numResults = tmpResults.size(); const cEvent **results = new const cEvent *[numResults]; for (int i=0; i tmpResults; int favTime = 0; if (userTime == 1) { favTime = config.favTime1; } else if (userTime == 2) { favTime = config.favTime2; } else if (userTime == 3) { favTime = config.favTime3; } else if (userTime == 4) { favTime = config.favTime4; } time_t now = time(0); tm *midn = localtime(&now); midn->tm_sec = 0; midn->tm_min = 0; midn->tm_hour = 0; time_t midnight = mktime(midn); int hours = favTime/100; int mins = favTime - hours * 100; time_t searchTime = midnight + hours*60*60 + mins*60; if (searchTime < now) searchTime += 24*60*60; #if VDRVERSNUM >= 20301 LOCK_CHANNELS_READ; const cChannels* channels = Channels; LOCK_SCHEDULES_READ; const cSchedules* schedules = Schedules; #else cChannels* channels = &Channels; cSchedulesLock schedulesLock; const cSchedules *schedules = cSchedules::Schedules(schedulesLock); #endif const cChannel *startChannel = NULL, *stopChannel = NULL; if (config.favLimitChannels) { startChannel = channels->GetByNumber(config.favStartChannel); stopChannel = channels->GetByNumber(config.favStopChannel); } if (!startChannel) startChannel = channels->First(); for (const cChannel *channel = startChannel; channel; channel = channels->Next(channel)) { if (channel->GroupSep()) continue; const cSchedule *Schedule = schedules->GetSchedule(channel); if (!Schedule) continue; const cEvent *event = Schedule->GetEventAround(searchTime); if (!event) continue; //if event is more or less over (only 15mns left), take next if ((event->EndTime() - searchTime) < 15*60) { event = Schedule->Events()->Next(event); } if (event) tmpResults.push_back(event); if (stopChannel && (stopChannel->Number() <= channel->Number())) break; } numResults = tmpResults.size(); const cEvent **results = new const cEvent *[numResults]; for (int i=0; i