diff options
author | Frank Neumann <fnu@yavdr.org> | 2017-05-01 11:02:21 +0200 |
---|---|---|
committer | Frank Neumann <fnu@yavdr.org> | 2017-05-01 11:02:21 +0200 |
commit | a46c7161bddc00b5b11bda0f8a14066b5f837302 (patch) | |
tree | 48e50b78f0efb1120b39bfb07f3612aabb1541e6 | |
parent | 0b09f90f361454d1d422cc750ee84359f11bd378 (diff) | |
download | vdr-plugin-epgsearch-a46c7161bddc00b5b11bda0f8a14066b5f837302.tar.gz vdr-plugin-epgsearch-a46c7161bddc00b5b11bda0f8a14066b5f837302.tar.bz2 |
Add compatibility for VDR 2.3.2+ (thx kamel5, mini73 & TomJoad)
53 files changed, 1662 insertions, 317 deletions
@@ -132,7 +132,7 @@ ifeq ($(WITHOUT_QUICKSEARCH), 0) ALL += libvdr-$(PLUGIN4).so endif -OBJS = afuzzy.o blacklist.o changrp.o confdloader.o conflictcheck.o conflictcheck_thread.o distance.o $(PLUGIN).o epgsearchcats.o epgsearchcfg.o epgsearchext.o epgsearchsetup.o epgsearchsvdrp.o epgsearchtools.o mail.o md5.o menu_announcelist.o menu_blacklistedit.o menu_blacklists.o menu_commands.o menu_conflictcheck.o menu_deftimercheckmethod.o menu_dirselect.o menu_event.o menu_favorites.o menu_main.o menu_myedittimer.o menu_quicksearch.o menu_recsdone.o menu_search.o menu_searchactions.o menu_searchedit.o menu_searchresults.o menu_searchtemplate.o menu_switchtimers.o menu_templateedit.o menu_timersdone.o menu_whatson.o noannounce.o pending_notifications.o rcfile.o recdone.o recstatus.o searchtimer_thread.o services.o switchtimer.o switchtimer_thread.o templatefile.o timer_thread.o timerdone.o timerstatus.o uservars.o varparser.o +OBJS = afuzzy.o blacklist.o changrp.o confdloader.o conflictcheck.o conflictcheck_thread.o distance.o $(PLUGIN).o epgsearchcats.o epgsearchcfg.o epgsearchext.o epgsearchsetup.o epgsearchsvdrp.o epgsearchtools.o mail.o md5.o menu_announcelist.o menu_blacklistedit.o menu_blacklists.o menu_commands.o menu_conflictcheck.o menu_deftimercheckmethod.o menu_dirselect.o menu_event.o menu_favorites.o menu_main.o menu_myedittimer.o menu_quicksearch.o menu_recsdone.o menu_search.o menu_searchactions.o menu_searchedit.o menu_searchresults.o menu_searchtemplate.o menu_switchtimers.o menu_templateedit.o menu_timersdone.o menu_whatson.o noannounce.o pending_notifications.o rcfile.o recdone.o recstatus.o searchtimer_thread.o services.o switchtimer.o switchtimer_thread.o templatefile.o timer_thread.o timerdone.o timerstatus.o uservars.o varparser.o status_thread.o ifeq ($(REGEXLIB), pcre) LIBS += $(shell pcre-config --libs-posix) diff --git a/blacklist.c b/blacklist.c index f6fd471..9f77155 100644 --- a/blacklist.c +++ b/blacklist.c @@ -47,8 +47,14 @@ cBlacklist::cBlacklist(void) startTime = 0000; stopTime = 2359; useChannel = false; - channelMin = Channels.GetByNumber(cDevice::CurrentChannel()); - channelMax = Channels.GetByNumber(cDevice::CurrentChannel()); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + channelMin = vdrchannels->GetByNumber(cDevice::CurrentChannel()); + channelMax = vdrchannels->GetByNumber(cDevice::CurrentChannel()); channelGroup = NULL; useCase = false; mode = 0; @@ -331,7 +337,13 @@ bool cBlacklist::Parse(const char *s) char *channelMaxbuffer = NULL; int channels = sscanf(value, "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer); #endif - channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + channelMin = vdrchannels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); if (!channelMin) { LogFile.eSysLog("ERROR: channel %s not defined", channelMinbuffer); @@ -342,7 +354,7 @@ bool cBlacklist::Parse(const char *s) channelMax = channelMin; else { - channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); + channelMax = vdrchannels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); if (!channelMax) { LogFile.eSysLog("ERROR: channel %s not defined", channelMaxbuffer); @@ -512,10 +524,10 @@ bool cBlacklist::Save(FILE *f) return fprintf(f, "%s\n", ToText()) > 0; } -cEvent * cBlacklist::GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop) +const cEvent * cBlacklist::GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop) { - cEvent *pe = NULL; - cEvent *p1 = NULL; + const cEvent *pe = NULL; + const cEvent *p1 = NULL; if (Start) p1 = schedules->Events()->Next(Start); @@ -545,7 +557,7 @@ cEvent * cBlacklist::GetEventByBlacklist(const cSchedule *schedules, const cEven maxSearchDuration = maxDuration/100*60 + maxDuration%100; } - for (cEvent *p = p1; p; p = schedules->Events()->Next(p)) + for (const cEvent *p = p1; p; p = schedules->Events()->Next(p)) { if(!p) { @@ -633,9 +645,14 @@ cSearchResults* cBlacklist::Run(cSearchResults* pSearchResults, int MarginStop) { LogFile.Log(3,"start search for blacklist '%s'", search); - cSchedulesLock schedulesLock; const cSchedules *schedules; +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + schedules = Schedules; +#else + cSchedulesLock schedulesLock; schedules = cSchedules::Schedules(schedulesLock); +#endif if(!schedules) { LogFile.Log(1,"schedules are currently locked! try again later."); return NULL; @@ -644,7 +661,13 @@ cSearchResults* cBlacklist::Run(cSearchResults* pSearchResults, int MarginStop) const cSchedule *Schedule = schedules->First(); while (Schedule) { - cChannel* channel = Channels.GetByChannelID(Schedule->ChannelID(),true,true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->GetByChannelID(Schedule->ChannelID(),true,true); if (!channel) { Schedule = (const cSchedule *)schedules->Next(Schedule); @@ -682,7 +705,13 @@ cSearchResults* cBlacklist::Run(cSearchResults* pSearchResults, int MarginStop) do { const cEvent* event = GetEventByBlacklist(Schedule, pPrevEvent, MarginStop); pPrevEvent = event; - if (event && Channels.GetByChannelID(event->ChannelID(),true,true)) +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + if (event && vdrchannels->GetByChannelID(event->ChannelID(),true,true)) { if (!pSearchResults) pSearchResults = new cSearchResults; pSearchResults->Add(new cSearchResult(event, this)); diff --git a/blacklist.h b/blacklist.h index c38ea60..183b940 100644 --- a/blacklist.h +++ b/blacklist.h @@ -39,8 +39,8 @@ public: int startTime; int stopTime; int useChannel; - cChannel *channelMin; - cChannel *channelMax; + const cChannel *channelMin; + const cChannel *channelMax; char* channelGroup; int useCase; int mode; @@ -70,9 +70,9 @@ public: int StartTime(void) { return startTime; } int StopTime(void) { return stopTime; } int UseChannel(void) { return useChannel; } - cChannel *ChannelMin(void) { return channelMin; } - cChannel *ChannelMax(void) { return channelMax; } - cEvent * GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop = 0); + const cChannel *ChannelMin(void) { return channelMin; } + const cChannel *ChannelMax(void) { return channelMax; } + const cEvent * GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop = 0); bool MatchesExtEPGInfo(const cEvent* e); const char *ToText(void); bool Parse(const char *s); @@ -82,7 +82,13 @@ bool cChannelGroup::Parse(const char *s) #endif if (numChannels == 1) { - cChannel* channel = Channels.GetByChannelID(tChannelID::FromString(channelbuffer), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->GetByChannelID(tChannelID::FromString(channelbuffer), true, true); if (channel) { cChannelGroupItem* channelitem = new cChannelGroupItem(channel); @@ -110,7 +116,7 @@ const char *cChannelGroup::ToText(void) int index = 0; while (ChannelGroupItem) { - cChannel* channel = ChannelGroupItem->channel; + const cChannel* channel = ChannelGroupItem->channel; if (index++ == 0) channelbuffer = strdup(CHANNELSTRING(channel)); else @@ -129,14 +135,20 @@ const char *cChannelGroup::ToText(void) int* cChannelGroup::CreateChannelSel() { - int* channelSel = (int*) malloc(Channels.Count() * sizeof(int)); - cChannel* channel = Channels.First(); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + int* channelSel = (int*) malloc(vdrchannels->Count() * sizeof(int)); + const cChannel* channel = vdrchannels->First(); int index = 0; while (channel) { if (channel->GroupSep()) { - channel = Channels.Next(channel); + channel = vdrchannels->Next(channel); continue; } channelSel[index] = 0; @@ -151,7 +163,7 @@ int* cChannelGroup::CreateChannelSel() channelInGroup = channels.Next(channelInGroup); } index++; - channel = Channels.Next(channel); + channel = vdrchannels->Next(channel); } return channelSel; } @@ -159,7 +171,13 @@ int* cChannelGroup::CreateChannelSel() void cChannelGroup::CreateChannelList(int* channelSel) { channels.Clear(); - cChannel* channel = Channels.First(); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->First(); int index = 0; while (channel) { @@ -169,7 +187,7 @@ void cChannelGroup::CreateChannelList(int* channelSel) channels.Add(new cChannelGroupItem(channel)); index++; } - channel = Channels.Next(channel); + channel = vdrchannels->Next(channel); } } @@ -178,7 +196,7 @@ bool cChannelGroup::Save(FILE *f) return fprintf(f, "%s\n", ToText()) > 0; } -bool cChannelGroup::ChannelInGroup(cChannel* channel) +bool cChannelGroup::ChannelInGroup(const cChannel* channel) { cChannelGroupItem* channelInGroup = channels.First(); while (channelInGroup) @@ -432,17 +450,23 @@ void cMenuEditChannelGroup::Set() Clear(); Add(new cMenuEditStrItem( tr("Group name"), name, sizeof(group->name), trVDR(FileNameChars))); - cChannel* channel = Channels.First(); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->First(); int index = 0; while (channel) { if (channel->GroupSep()) { - channel = Channels.Next(channel); + channel = vdrchannels->Next(channel); continue; } Add(new cMenuEditBoolItem( CHANNELNAME(channel), &channelSel[index++], trVDR("no"), trVDR("yes"))); - channel = Channels.Next(channel); + channel = vdrchannels->Next(channel); } SetCurrent(Get(current)); @@ -507,19 +531,25 @@ eOSState cMenuEditChannelGroup::ProcessKey(eKeys Key) case kGreen: case kYellow: { - cChannel* channel = Channels.First(); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->First(); int index = 0; while (channel) { if (channel->GroupSep()) { - channel = Channels.Next(channel); + channel = vdrchannels->Next(channel); continue; } channelSel[index] = (Key == kGreen?1:(Key == kRed?1-channelSel[index]:0)); index++; - channel = Channels.Next(channel); + channel = vdrchannels->Next(channel); } Set(); Display(); @@ -33,9 +33,9 @@ class cSearchExt; // --- cChannelGroupItem -------------------------------------------------------- class cChannelGroupItem : public cListObject { public: - cChannel* channel; + const cChannel* channel; public: - cChannelGroupItem(cChannel* ch) : channel(ch) {} + cChannelGroupItem(const cChannel* ch) : channel(ch) {} }; // --- cChannelGroup -------------------------------------------------------- @@ -52,7 +52,7 @@ public: bool Save(FILE *f); int* CreateChannelSel(); void CreateChannelList(int*); - bool ChannelInGroup(cChannel*); + bool ChannelInGroup(const cChannel*); }; // --- cChannelGroups -------------------------------------------------------- diff --git a/conflictcheck.c b/conflictcheck.c index eb7fa57..9202df8 100644 --- a/conflictcheck.c +++ b/conflictcheck.c @@ -73,12 +73,17 @@ const cEvent* cConflictCheckTimerObj::Event() const cEvent* cConflictCheckTimerObj::SetEventFromSchedule() { +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + const cSchedules *schedules = Schedules; +#else cSchedulesLock SchedulesLock; - const cSchedules* Schedules = NULL; - if (!(Schedules = cSchedules::Schedules(SchedulesLock))) + const cSchedules* schedules = cSchedules::Schedules(SchedulesLock); +#endif + if (!schedules) return NULL; - const cSchedule *Schedule = Schedules->GetSchedule(timer->Channel()); + const cSchedule *Schedule = schedules->GetSchedule(timer->Channel()); if (Schedule && Schedule->Events()->First()) { const cEvent *Event = NULL; @@ -230,15 +235,27 @@ void cConflictCheck::BondDevices(const char *Bondings) #endif } +#if VDRVERSNUM > 20300 +void cConflictCheck::Check(const cTimers* vdrtimers) +{ + Check_(vdrtimers); +} +#endif void cConflictCheck::Check() { + const cTimers* vdrtimers = NULL; + Check_(vdrtimers); +} + +void cConflictCheck::Check_(const cTimers* vdrtimers) +{ if (evaltimeList) DELETENULL(evaltimeList); if (timerList) DELETENULL(timerList); - timerList = CreateCurrentTimerList(); + timerList = CreateCurrentTimerList(vdrtimers); if (timerList) evaltimeList = CreateEvaluationTimeList(timerList); if (evaltimeList) failedList = CreateConflictList(evaltimeList, timerList); if (failedList) @@ -255,15 +272,23 @@ void cConflictCheck::Check() gl_timerStatusMonitor->SetConflictCheckAdvised(); } -cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList() +cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList(const cTimers* vdrtimers) { LogFile.Log(3,"current timer list creation started"); cList<cConflictCheckTimerObj>* CurrentTimerList = NULL; // collect single event timers time_t tMax = 0; - cTimer* ti = NULL; - for (ti = Timers.First(); ti; ti = Timers.Next(ti)) +#if VDRVERSNUM > 20300 + if (!vdrtimers) { + LOCK_TIMERS_READ; + vdrtimers = Timers; + } +#else + vdrtimers = &Timers; +#endif + const cTimer* ti = NULL; + for (ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti)) { tMax = max(tMax, ti->StartTime()); if (!ti->IsSingleEvent()) continue; @@ -291,7 +316,7 @@ cList<cConflictCheckTimerObj>* cConflictCheck::CreateCurrentTimerList() // collect repeating timers from now until the date of the timer with tMax time_t maxCheck = time(NULL) + min(14,EPGSearchConfig.checkMaxDays) * SECSINDAY; tMax = max(tMax, maxCheck); - for (ti = Timers.First(); ti; ti = Timers.Next(ti)) + for (ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti)) { if (ti->IsSingleEvent()) continue; time_t day = time(NULL); @@ -669,7 +694,7 @@ void cConflictCheck::AddConflict(cConflictCheckTimerObj* TimerObj, cConflictChec LogFile.Log(3,"conflict found for timer '%s' (%s, channel %s)", TimerObj->timer->File(), DAYDATETIME(TimerObj->start), CHANNELNAME(TimerObj->timer->Channel())); } -bool cConflictCheck::TimerInConflict(cTimer* timer) +bool cConflictCheck::TimerInConflict(const cTimers* vdrtimers, const cTimer* timer) { for(cConflictCheckTime* checkTime = failedList->First(); checkTime; checkTime = failedList->Next(checkTime)) { @@ -683,7 +708,7 @@ bool cConflictCheck::TimerInConflict(cTimer* timer) { for (it2 = (*it)->concurrentTimers->begin(); it2 != (*it)->concurrentTimers->end(); ++it2) { - if ((*it2)->OrigTimer() == timer) + if ((*it2)->OrigTimer(vdrtimers) == timer) return true; } } @@ -706,7 +731,13 @@ void cConflictCheck::EvaluateConflCheckCmd() if ((*it) && !(*it)->ignore) { string result = EPGSearchConfig.conflCheckCmd; - if (!(*it)->OrigTimer()) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + if (!(*it)->OrigTimer(vdrtimers)) { LogFile.Log(3,"timer has disappeared meanwhile"); continue; diff --git a/conflictcheck.h b/conflictcheck.h index 089c367..75e82e2 100644 --- a/conflictcheck.h +++ b/conflictcheck.h @@ -59,7 +59,20 @@ class cConflictCheckTimerObj : public cTimerObj const cEvent* Event(); const cEvent* SetEventFromSchedule(); int Matches(const cEvent *Event, int *Overlap) const; - cTimer* OrigTimer() {return Timers.GetTimer(timer); } + const cTimer* OrigTimer(const cTimers* timers) const + { + // http://www.vdr-portal.de/board1-news/board2-vdr-news/p1255344-/#post1255344 + // if patch is accepted, change to + //return timers->GetTimer(timer); + return ((cTimers*)timers)->GetTimer((cTimer*)timer); + } + cTimer* OrigTimer(cTimers* timers) + { + // http://www.vdr-portal.de/board1-news/board2-vdr-news/p1255344-/#post1255344 + // if patch is accepted, change to + //return timers->GetTimer(timer); + return timers->GetTimer((cTimer*)timer); + } }; class TimerObjSort @@ -262,6 +275,8 @@ class cConflictCheck int numDevices; time_t maxCheck; std::vector<eModuleStatus> camSlotStatusArray; + private: + void Check_(const cTimers* vdrtimers); public: int relevantConflicts; int numConflicts; @@ -271,8 +286,11 @@ class cConflictCheck ~cConflictCheck(); void InitDevicesInfo(); void Check(); +#if VDRVERSNUM > 20300 + void Check(const cTimers* vdrtimers); +#endif void BondDevices(const char* bondings); - cList<cConflictCheckTimerObj>* CreateCurrentTimerList(); + cList<cConflictCheckTimerObj>* CreateCurrentTimerList(const cTimers* vdrtimers); cList<cConflictCheckTime>* CreateEvaluationTimeList(cList<cConflictCheckTimerObj>*); cList<cConflictCheckTime>* CreateConflictList(cList<cConflictCheckTime>*, cList<cConflictCheckTimerObj>* timerList); int GetDevice(cConflictCheckTimerObj* TimerObj, bool *NeedsDetachReceivers); @@ -280,7 +298,7 @@ class cConflictCheck cList<cConflictCheckTimerObj>* GetTimers() { return timerList; } void AddConflict(cConflictCheckTimerObj* TimerObj, cConflictCheckTime* Checktime, std::set<cConflictCheckTimerObj*>& pendingTimers); int ProcessCheckTime(cConflictCheckTime* checkTime); - bool TimerInConflict(cTimer*); + bool TimerInConflict(const cTimers* vdrtimers, const cTimer*); void EvaluateConflCheckCmd(); eModuleStatus CamSlotModuleStatus(cCamSlot *CamSlot); }; diff --git a/conflictcheck_thread.c b/conflictcheck_thread.c index d224ccf..8c52d85 100644 --- a/conflictcheck_thread.c +++ b/conflictcheck_thread.c @@ -102,11 +102,17 @@ void cConflictCheckThread::Action(void) if (now >= nextUpdate || m_forceUpdate) { m_forceUpdate = false; +#if VDRVERSNUM > 20300 + { + LOCK_TIMERS_READ; + } +#else if (Timers.BeingEdited()) { Wait.Wait(1000); continue; } +#endif LogFile.iSysLog("timer conflict check started"); cConflictCheck conflictCheck; diff --git a/epgsearch.c b/epgsearch.c index 83a12b6..08c5d1f 100644 --- a/epgsearch.c +++ b/epgsearch.c @@ -156,9 +156,15 @@ bool cPluginEpgsearch::ProcessArgs(int argc, char *argv[]) strn0cpy(SearchExt->search,argv[2], sizeof(SearchExt->search)); if (atoi(argv[3]) > 0) { +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif SearchExt->useChannel = true; - SearchExt->channelMin = Channels.GetByNumber(atoi(argv[3])); - SearchExt->channelMax = Channels.GetByNumber(atoi(argv[3])); + SearchExt->channelMin = vdrchannels->GetByNumber(atoi(argv[3])); + SearchExt->channelMax = vdrchannels->GetByNumber(atoi(argv[3])); } SearchExt->mode = atoi(argv[4]); SearchExt->useTitle = atoi(argv[5]); @@ -237,9 +243,15 @@ bool cPluginEpgsearch::Service(const char *Id, void *Data) 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 = Channels.GetByNumber(searchData->channelNr); - SearchExt->channelMax = Channels.GetByNumber(searchData->channelNr); + SearchExt->channelMin = vdrchannels->GetByNumber(searchData->channelNr); + SearchExt->channelMax = vdrchannels->GetByNumber(searchData->channelNr); } SearchExt->mode = searchData->mode; SearchExt->useTitle = searchData->useTitle; @@ -332,9 +344,15 @@ bool cPluginEpgsearch::Service(const char *Id, void *Data) 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 = Channels.GetByNumber(searchData->channelNr); - SearchExt->channelMax = Channels.GetByNumber(searchData->channelNr); + SearchExt->channelMin = vdrchannels->GetByNumber(searchData->channelNr); + SearchExt->channelMax = vdrchannels->GetByNumber(searchData->channelNr); } SearchExt->mode = searchData->mode; SearchExt->useTitle = searchData->useTitle; @@ -510,9 +528,15 @@ cOsdObject *cPluginEpgsearch::DoInitialSearch(char* rcFilename) strn0cpy(SearchExt->search,rcFile.Search, sizeof(SearchExt->search)); if (rcFile.ChannelNr != -1) { +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif SearchExt->useChannel = true; - SearchExt->channelMin = Channels.GetByNumber(rcFile.ChannelNr); - SearchExt->channelMax = Channels.GetByNumber(rcFile.ChannelNr); + SearchExt->channelMin = vdrchannels->GetByNumber(rcFile.ChannelNr); + SearchExt->channelMax = vdrchannels->GetByNumber(rcFile.ChannelNr); } SearchExt->mode = rcFile.SearchMode; SearchExt->useTitle = rcFile.UseTitle; diff --git a/epgsearchext.c b/epgsearchext.c index 9d11c3b..9b793f6 100644 --- a/epgsearchext.c +++ b/epgsearchext.c @@ -58,8 +58,14 @@ cSearchExt::cSearchExt(void) startTime = 0000; stopTime = 2359; useChannel = false; - channelMin = Channels.GetByNumber(cDevice::CurrentChannel()); - channelMax = Channels.GetByNumber(cDevice::CurrentChannel()); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + channelMin = vdrchannels->GetByNumber(cDevice::CurrentChannel()); + channelMax = vdrchannels->GetByNumber(cDevice::CurrentChannel()); channelGroup = NULL; useCase = false; mode = 0; @@ -228,7 +234,7 @@ cSearchExt& cSearchExt::operator= (const cSearchExt &SearchExt) recordingsKeep = templ->recordingsKeep; blacklistMode = templ->blacklistMode; blacklists.Clear(); - cBlacklistObject* blacklistObj = templ->blacklists.First(); + const cBlacklistObject* blacklistObj = templ->blacklists.First(); while(blacklistObj) { blacklists.Add(new cBlacklistObject(blacklistObj->blacklist)); @@ -480,7 +486,13 @@ bool cSearchExt::Parse(const char *s) char *channelMaxbuffer = NULL; int channels = sscanf(value, "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer); #endif - channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + channelMin = vdrchannels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); if (!channelMin) { LogFile.eSysLog("ERROR: channel '%s' not defined", channelMinbuffer); @@ -492,7 +504,7 @@ bool cSearchExt::Parse(const char *s) channelMax = channelMin; else { - channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); + channelMax = vdrchannels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); if (!channelMax) { LogFile.eSysLog("ERROR: channel '%s' not defined", channelMaxbuffer); @@ -858,12 +870,12 @@ bool cSearchExt::Save(FILE *f) return fprintf(f, "%s\n", ToText()) > 0; } -cEvent * cSearchExt::GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin) +const cEvent * cSearchExt::GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin) { if (!schedules) return NULL; - cEvent *pe = NULL; - cEvent *p1 = NULL; + const cEvent *pe = NULL; + const cEvent *p1 = NULL; const cList<cEvent>* Events = schedules->Events(); if (Start) @@ -893,7 +905,7 @@ cEvent * cSearchExt::GetEventBySearchExt(const cSchedule *schedules, const cEven if (!useCase) ToLower(searchText); - for (cEvent *p = p1; p; p = Events->Next(p)) + for (const cEvent *p = p1; p; p = Events->Next(p)) { if(!p) { @@ -1011,9 +1023,14 @@ cSearchResults* cSearchExt::Run(int PayTVMode, bool inspectTimerMargin, int eval { LogFile.Log(3,"start search for search timer '%s'", search); - cSchedulesLock schedulesLock; const cSchedules *schedules; +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + schedules = Schedules; +#else + cSchedulesLock schedulesLock; schedules = cSchedules::Schedules(schedulesLock); +#endif if(!schedules) { LogFile.Log(1,"schedules are currently locked! try again later."); return NULL; @@ -1031,8 +1048,14 @@ cSearchResults* cSearchExt::Run(int PayTVMode, bool inspectTimerMargin, int eval cSearchResults* pBlacklistResults = GetBlacklistEvents(inspectTimerMargin?MarginStop:0); int counter = 0; +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif while (Schedule) { - cChannel* channel = Channels.GetByChannelID(Schedule->ChannelID(),true,true); + const cChannel* channel = vdrchannels->GetByChannelID(Schedule->ChannelID(),true,true); if (!channel) { Schedule = (const cSchedule *)schedules->Next(Schedule); @@ -1084,7 +1107,7 @@ cSearchResults* cSearchExt::Run(int PayTVMode, bool inspectTimerMargin, int eval if (tNow + evalLimitMins*60 <= event->EndTime()) break; } - if (event && Channels.GetByChannelID(event->ChannelID(),true,true)) + if (event && vdrchannels->GetByChannelID(event->ChannelID(),true,true)) { if (pBlacklistResults && pBlacklistResults->Lookup(event)) { @@ -1165,6 +1188,12 @@ void cSearchExt::CheckRepeatTimers(cSearchResults* pResults) } cSearchResult* pResultObj = NULL; +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers* vdrtimers = Timers; +#else + cTimers* vdrtimers = &Timers; +#endif for (pResultObj = pResults->First(); pResultObj; pResultObj = pResults->Next(pResultObj)) { if (action != searchTimerActionRecord) // only announce if there is no timer for the event @@ -1253,7 +1282,7 @@ void cSearchExt::CheckRepeatTimers(cSearchResults* pResults) } } bool dummy; - cTimer* timer = cSearchTimerThread::GetTimer(this, pEvent, dummy); + const cTimer* timer = cSearchTimerThread::GetTimer(vdrtimers, this, pEvent, dummy); if (timer && !timer->HasFlags(tfActive)) { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d), existing timer disabled", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); @@ -1278,7 +1307,8 @@ void cSearchExt::CheckExistingRecordings(cSearchResults* pResults) LogFile.Log(3,"analysing existing recordings for search timer '%s'...", search); // how many recordings do we already have? - int num = GetCountRecordings(); + cRecordings *vdrrecordings = NULL; + int num = GetCountRecordings(vdrrecordings); cSearchResult* pResultObj = NULL; int remain = pauseOnNrRecordings - num; @@ -1337,39 +1367,54 @@ bool cSearchExt::MatchesExtEPGInfo(const cEvent* e) void cSearchExt::OnOffTimers(bool bOn) { - for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + for (cTimer *ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti)) { if (((!bOn && ti->HasFlags(tfActive)) || (bOn && !ti->HasFlags(tfActive))) && TriggeredFromSearchTimerID(ti) == ID) ti->OnOff(); } +#if VDRVERSNUM < 20300 Timers.SetModified(); +#endif } void cSearchExt::DeleteAllTimers() { cList<cTimerObj> DelTimers; - cTimer *ti = Timers.First(); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + cTimer *ti = vdrtimers->First(); while(ti) { if (!ti->Recording() && TriggeredFromSearchTimerID(ti) == ID) { - cTimer* tiNext = Timers.Next(ti); + cTimer* tiNext = vdrtimers->Next(ti); LogFile.iSysLog("deleting timer %s", *ti->ToDescr()); - Timers.Del(ti); - Timers.SetModified(); + vdrtimers->Del(ti); + vdrtimers->SetModified(); ti = tiNext; } else - ti = Timers.Next(ti); + ti = vdrtimers->Next(ti); }; } -cTimerObjList* cSearchExt::GetTimerList(cTimerObjList* timerList) +cTimerObjList* cSearchExt::GetTimerList(const cTimers* vdrtimers, cTimerObjList* timerList) { if (!timerList) timerList = new cTimerObjList; - for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) + for (const cTimer *ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti)) { if (TriggeredFromSearchTimerID(ti) == ID) { @@ -1391,11 +1436,19 @@ cTimerObjList* cSearchExt::GetTimerList(cTimerObjList* timerList) } // counts the currently existent recordings triggered by this search timer -int cSearchExt::GetCountRecordings() +int cSearchExt::GetCountRecordings(cRecordings *vdrrecordings) { int countRecs = 0; - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) +#if VDRVERSNUM > 20300 + if (!vdrrecordings) { + LOCK_RECORDINGS_READ; + vdrrecordings = (cRecordings *)Recordings; + } +#else + vdrrecordings = &Recordings; +#endif + for (const cRecording *recording = vdrrecordings->First(); recording; recording = vdrrecordings->Next(recording)) { if (recording->IsEdited()) continue; // ignore recordings edited if (!recording->Info()) continue; diff --git a/epgsearchext.h b/epgsearchext.h index eee3cf4..3e6148e 100644 --- a/epgsearchext.h +++ b/epgsearchext.h @@ -140,8 +140,8 @@ public: std::string contentsFilter; int useExtEPGInfo; char** catvalues; - cChannel *channelMin; - cChannel *channelMax; + const cChannel *channelMin; + const cChannel *channelMax; char* channelGroup; int avoidRepeats; int compareTitle; @@ -181,9 +181,9 @@ public: int StartTime(void) { return startTime; } int StopTime(void) { return stopTime; } int UseChannel(void) { return useChannel; } - cChannel *ChannelMin(void) { return channelMin; } - cChannel *ChannelMax(void) { return channelMax; } - cEvent * GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin = false); + const cChannel *ChannelMin(void) { return channelMin; } + const cChannel *ChannelMax(void) { return channelMax; } + const cEvent * GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin = false); bool MatchesExtEPGInfo(const cEvent* e); const char *ToText(); bool Parse(const char *s); @@ -199,8 +199,8 @@ public: cSearchResults* GetBlacklistEvents(int MarginStop = 0); void OnOffTimers(bool); void DeleteAllTimers(); - cTimerObjList* GetTimerList(cTimerObjList* timerList); - int GetCountRecordings(); + cTimerObjList* GetTimerList(const cTimers* vdrtimers, cTimerObjList* timerList); + int GetCountRecordings(cRecordings *vdrrecordings); bool IsActiveAt(time_t t); bool HasContent(int contentID); void SetContentFilter(int* contentStringsFlags); diff --git a/epgsearchsvdrp.c b/epgsearchsvdrp.c index f181013..6b3c039 100644 --- a/epgsearchsvdrp.c +++ b/epgsearchsvdrp.c @@ -232,8 +232,12 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option, { LogFile.Log(1,"search '%s' deleted via SVDRP", search->search); cMutexLock SearchExtsLock(&SearchExts); - if (delTimers && !Timers.BeingEdited()) - search->DeleteAllTimers(); + if (delTimers +#if VDRVERSNUM < 20300 + && !Timers.BeingEdited() +#endif + ) + search->DeleteAllTimers(); SearchExts.Del(search); SearchExts.Save(); RecsDone.RemoveSearchID(SID); @@ -562,13 +566,25 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option, eTimerMatch timerMatch; bool hasTimer = false; - if (Timers.GetMatch(pEvent, &timerMatch)) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + if (vdrtimers->GetMatch(pEvent, &timerMatch)) hasTimer = (timerMatch == tmFull); if (!result->search->useAsSearchTimer) result->needsTimer = false; - cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true,true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true,true); int timerMode = hasTimer?1:(result->needsTimer?2:0); string title = pEvent->Title()?ReplaceAll(pEvent->Title(), "|", "!^pipe!^"):""; @@ -1043,7 +1059,13 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option, ReplyCode = 901; return cString::sprintf("invalid channel id"); } - cChannel *ch = Channels.GetByChannelID(chID,true,true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *ch = vdrchannels->GetByChannelID(chID,true,true); if (!ch) { ReplyCode = 901; @@ -1053,12 +1075,18 @@ cString cPluginEpgsearch::SVDRPCommand(const char *Command, const char *Option, } else { +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif string sBuffer; - for (int i = 0; i < Channels.Count(); i++) + for (int i = 0; i < vdrchannels->Count(); i++) { - cChannel* ch = Channels.Get(i); + const cChannel* ch = vdrchannels->Get(i); if (ch && !ch->GroupSep()) - sBuffer += string(*ch->GetChannelID().ToString()) + string(": ") + NumToString(DefTimerCheckModes.GetMode(ch)) + string((i<Channels.Count()-1)?"\n":""); + sBuffer += string(*ch->GetChannelID().ToString()) + string(": ") + NumToString(DefTimerCheckModes.GetMode(ch)) + string((i<vdrchannels->Count()-1)?"\n":""); } return sBuffer.c_str(); } diff --git a/epgsearchtools.c b/epgsearchtools.c index 6f7485a..09ad7b3 100644 --- a/epgsearchtools.c +++ b/epgsearchtools.c @@ -519,7 +519,7 @@ bool DescriptionMatches(const char* eDescr, const char* rDescr, int matchLimit) return false; } -const cEvent* GetEvent(cTimer* timer) +const cEvent* GetEvent(const cTimer* timer) { const cEvent* event = NULL; const cChannel *channel = timer->Channel(); @@ -527,10 +527,15 @@ const cEvent* GetEvent(cTimer* timer) for (int seconds = 0; seconds <= 3; seconds++) { { +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + const cSchedules *schedules = Schedules; +#else cSchedulesLock SchedulesLock; - const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock); - if (Schedules) { - const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); + const cSchedules *schedules = cSchedules::Schedules(SchedulesLock); +#endif + if (schedules) { + const cSchedule *Schedule = schedules->GetSchedule(channel->GetChannelID()); if (Schedule) { event = Schedule->GetEventAround(Time); if (event) return event; @@ -709,7 +714,13 @@ int ChannelNrFromEvent(const cEvent* pEvent) { if (!pEvent) return -1; - cChannel* channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true); if (!channel) return -1; else diff --git a/epgsearchtools.h b/epgsearchtools.h index dc68f8b..7227970 100644 --- a/epgsearchtools.h +++ b/epgsearchtools.h @@ -70,7 +70,7 @@ using std::string; #undef CONFIGDIR #define CONFIGDIR (!ConfigDir?cPlugin::ConfigDirectory():ConfigDir) -#define CHNUMWIDTH (numdigits(Channels.MaxNumber()) + 2) +#define CHNUMWIDTH (numdigits(vdrchannels->MaxNumber()) + 2) #define SHORTTEXT(EVENT) \ (EVENT && EPGSearchConfig.showShortText && !isempty((EVENT)->ShortText()))?" ~ ":"", \ @@ -157,7 +157,7 @@ cSearchExt* TriggeredFromSearchTimer(const cTimer* timer); int TriggeredFromSearchTimerID(const cTimer* timer); double FuzzyMatch(const char* s1, const char* s2, int maxLength); bool DescriptionMatches(const char* eDescr, const char* rDescr, int matchLimit = 90); -const cEvent* GetEvent(cTimer* timer); +const cEvent* GetEvent(const cTimer* timer); char* GetRawDescription(const char* descr); void PrepareTimerFile(const cEvent* event, cTimer* timer); int CompareEventTime(const void *p1, const void *p2); @@ -188,15 +188,15 @@ long getAddrFromString(const char* hostnameOrIp, struct sockaddr_in* addr); // --- cTimerObj -------------------------------------------------------- class cTimerObj : public cListObject { public: - cTimer* timer; - cTimerObj(cTimer* Timer) : timer(Timer) {} + const cTimer* timer; + cTimerObj(const cTimer* Timer) : timer(Timer) {} virtual ~cTimerObj() { timer = NULL; } // do not delete anything! }; // --- cTimerObjList -------------------------------------------------------- class cTimerObjList : public cList<cTimerObj> { public: - void DelTimer(cTimer* t) + void DelTimer(const cTimer* t) { for (cTimerObj* pTObj = First(); pTObj; pTObj = Next(pTObj)) if (pTObj->timer == t) @@ -50,7 +50,13 @@ string cMailTimerNotification::Format(const string& templ) const if (!pEvent) return ""; eTimerMatch TimerMatch = tmNone; - cTimer* pTimer = Timers.GetMatch(pEvent, &TimerMatch); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + const cTimer* pTimer = vdrtimers->GetMatch(pEvent, &TimerMatch); if (!pTimer) return ""; string result = templ; @@ -70,8 +76,13 @@ string cMailTimerNotification::Format(const string& templ) const const cEvent* cMailTimerNotification::GetEvent() const { +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + const cSchedules *schedules = Schedules; +#else cSchedulesLock schedulesLock; const cSchedules *schedules = cSchedules::Schedules(schedulesLock); +#endif if (!schedules) return NULL; const cSchedule *schedule = schedules->GetSchedule(channelID); if (!schedule) return NULL; @@ -80,8 +91,14 @@ const cEvent* cMailTimerNotification::GetEvent() const bool cMailTimerNotification::operator< (const cMailTimerNotification &N) const { - const cChannel* channel = Channels.GetByChannelID(channelID,true,true); - const cChannel* channelOther = Channels.GetByChannelID(N.channelID,true,true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->GetByChannelID(channelID,true,true); + const cChannel* channelOther = vdrchannels->GetByChannelID(N.channelID,true,true); if (!channel || !channelOther) return false; const cEvent* event = GetEvent(); @@ -98,7 +115,7 @@ bool cMailTimerNotification::operator< (const cMailTimerNotification &N) const // ------------------------- // cMailDelTimerNotification -cMailDelTimerNotification::cMailDelTimerNotification(cTimer* pTimer, const cEvent* pEvent, const string& templ) +cMailDelTimerNotification::cMailDelTimerNotification(const cTimer* pTimer, const cEvent* pEvent, const string& templ) { if (!pTimer || !pTimer->Channel()) return; @@ -121,8 +138,14 @@ cMailDelTimerNotification::cMailDelTimerNotification(const string& Formatted, tC bool cMailDelTimerNotification::operator< (const cMailDelTimerNotification &N) const { - const cChannel* channel = Channels.GetByChannelID(channelID,true,true); - const cChannel* channelOther = Channels.GetByChannelID(N.channelID,true,true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->GetByChannelID(channelID,true,true); + const cChannel* channelOther = vdrchannels->GetByChannelID(N.channelID,true,true); if (!channel || !channelOther) return false; if (channel != channelOther) @@ -338,7 +361,7 @@ void cMailUpdateNotifier::AddModTimerNotification(tEventID EventID, tChannelID C modTimers.insert(N); } -void cMailUpdateNotifier::AddRemoveTimerNotification(cTimer* t, const cEvent* e) +void cMailUpdateNotifier::AddRemoveTimerNotification(const cTimer* t, const cEvent* e) { string templTimer = GetTemplValue(mailTemplate, "timer"); cMailDelTimerNotification N(t, e, templTimer); @@ -82,7 +82,7 @@ class cMailDelTimerNotification public: string formatted; - cMailDelTimerNotification(cTimer* t, const cEvent* pEvent, const string& templ); + cMailDelTimerNotification(const cTimer* t, const cEvent* pEvent, const string& templ); cMailDelTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start); bool operator< (const cMailDelTimerNotification &N) const; string Format(const string& templ) const { return formatted; } @@ -110,7 +110,7 @@ class cMailUpdateNotifier : public cMailNotifier cMailUpdateNotifier(); void AddNewTimerNotification(tEventID EventID, tChannelID ChannelID); void AddModTimerNotification(tEventID EventID, tChannelID ChannelID, uint timerMod = tmNoChange); - void AddRemoveTimerNotification(cTimer* t, const cEvent* e = NULL); + void AddRemoveTimerNotification(const cTimer* t, const cEvent* e = NULL); void AddRemoveTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start); void AddAnnounceEventNotification(tEventID EventID, tChannelID ChannelID, int SearchExtID); void SendUpdateNotifications(); diff --git a/menu_blacklistedit.c b/menu_blacklistedit.c index 4173cdb..ef5a1c3 100644 --- a/menu_blacklistedit.c +++ b/menu_blacklistedit.c @@ -351,7 +351,13 @@ eOSState cMenuBlacklistEdit::ProcessKey(eKeys Key) case kOk: if (data.useChannel==1) { - cChannel *ch = Channels.GetByNumber(channelMin); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *ch = vdrchannels->GetByNumber(channelMin); if (ch) data.channelMin = ch; else @@ -359,7 +365,7 @@ eOSState cMenuBlacklistEdit::ProcessKey(eKeys Key) ERROR(tr("*** Invalid Channel ***")); break; } - ch = Channels.GetByNumber(channelMax); + ch = vdrchannels->GetByNumber(channelMax); if (ch) data.channelMax = ch; else diff --git a/menu_commands.c b/menu_commands.c index 174cf7f..f3194e9 100644 --- a/menu_commands.c +++ b/menu_commands.c @@ -40,6 +40,10 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #include <vdr/menu.h> #include "menu_deftimercheckmethod.h" +#if VDRVERSNUM > 20300 +extern bool HandleRemoteModifications(cTimer* NewTimer, cTimer* OldTimer); +#endif + // --- cMenuSearchCommands --------------------------------------------------------- cMenuSearchCommands::cMenuSearchCommands(const char *Title, const cEvent* Event, bool DirectCall, cSearchExt* Search) @@ -102,7 +106,13 @@ void cMenuSearchCommands::LoadCommands() eOSState cMenuSearchCommands::Switch(void) { - cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(event->ChannelID(), true, true); if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true)) return osEnd; else @@ -122,7 +132,14 @@ eOSState cMenuSearchCommands::Record(void) if (!event) return osContinue; eTimerMatch timerMatch = tmNone; - cTimer* timer = Timers.GetMatch(event, &timerMatch); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + cTimer* timer = vdrtimers->GetMatch(event, &timerMatch); if (timerMatch == tmFull) { if (EPGSearchConfig.useVDRTimerEditMenu) @@ -133,7 +150,7 @@ eOSState cMenuSearchCommands::Record(void) timer = new cTimer(event); PrepareTimerFile(event, timer); - cTimer *t = Timers.GetTimer(timer); + cTimer *t = vdrtimers->GetTimer(timer); if (EPGSearchConfig.onePressTimerCreation == 0 || t || (!t && event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL))) { @@ -170,11 +187,21 @@ eOSState cMenuSearchCommands::Record(void) #endif SetAux(timer, fullaux); - Timers.Add(timer); +#if VDRVERSNUM > 20300 + if (*Setup.SVDRPDefaultHost) + timer->SetRemote(Setup.SVDRPDefaultHost); +#endif + vdrtimers->Add(timer); timer->Matches(); - Timers.SetModified(); - + vdrtimers->SetModified(); +#if VDRVERSNUM > 20300 + if (!HandleRemoteModifications(timer,NULL)) { + vdrtimers->Del(timer); + delete timer; + } +#else LogFile.iSysLog("timer %s added (active)", *timer->ToDescr()); +#endif return osBack; } return osContinue; @@ -232,7 +259,13 @@ eOSState cMenuSearchCommands::CreateSearchTimer(void) cSearchExt* pNew = new cSearchExt; strcpy(pNew->search, event->Title()); - pNew->channelMin = pNew->channelMax = Channels.GetByChannelID(event->ChannelID()); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + pNew->channelMin = pNew->channelMax = vdrchannels->GetByChannelID(event->ChannelID()); return AddSubMenu(new cMenuEditSearchExt(pNew, true, false, true)); } @@ -280,12 +313,18 @@ eOSState cMenuSearchCommands::Execute(void) buffer = cString::sprintf("%s...", command->Title()); Skins.Message(mtStatus, buffer); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif buffer = cString::sprintf("'%s' %ld %ld %d '%s' '%s'", EscapeString(event->Title()).c_str(), event->StartTime(), event->EndTime(), ChannelNrFromEvent(event), - EscapeString(Channels.GetByChannelID(event->ChannelID(), true, true)->Name()).c_str(), + EscapeString(vdrchannels->GetByChannelID(event->ChannelID(), true, true)->Name()).c_str(), EscapeString(event->ShortText()?event->ShortText():"").c_str()); const char *Result = command->Execute(buffer); Skins.Message(mtStatus, NULL); diff --git a/menu_conflictcheck.c b/menu_conflictcheck.c index 562842e..6f0ab61 100644 --- a/menu_conflictcheck.c +++ b/menu_conflictcheck.c @@ -50,7 +50,7 @@ cMenuConflictCheckItem::cMenuConflictCheckItem(cConflictCheckTime* Ct, cConflict } else { - cTimer* t = timerObj->timer; + const cTimer* t = timerObj->timer; int recPart = timerObj->recDuration * 100 / (timerObj->stop - timerObj->start); buffer = cString::sprintf("%d\t%s\t%d\t%2d%%\t%s", t->Channel()->Number(), t->Channel()->ShortName(true), t->Priority(), recPart, t->File()); } @@ -165,17 +165,23 @@ eOSState cMenuConflictCheck::ProcessKey(eKeys Key) cMenuConflictCheckDetailsItem::cMenuConflictCheckDetailsItem(cConflictCheckTimerObj* TimerObj) { timerObj = TimerObj; - hasTimer = timerObj->OrigTimer()?timerObj->OrigTimer()->HasFlags(tfActive):false; - Update(true); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + hasTimer = timerObj->OrigTimer(vdrtimers)?timerObj->OrigTimer(vdrtimers)->HasFlags(tfActive):false; + Update(vdrtimers, true); } -bool cMenuConflictCheckDetailsItem::Update(bool Force) +bool cMenuConflictCheckDetailsItem::Update(const cTimers* vdrtimers, bool Force) { bool oldhasTimer = hasTimer; - hasTimer = timerObj->OrigTimer()?timerObj->OrigTimer()->HasFlags(tfActive):false; + hasTimer = timerObj->OrigTimer(vdrtimers)?timerObj->OrigTimer(vdrtimers)->HasFlags(tfActive):false; if (Force || hasTimer != oldhasTimer) { - cTimer* timer = timerObj->timer; + const cTimer* timer = timerObj->timer; char device[2]=""; if (hasTimer) { @@ -266,19 +272,27 @@ eOSState cMenuConflictCheckDetails::Commands(eKeys Key) eOSState cMenuConflictCheckDetails::ToggleTimer(cConflictCheckTimerObj* TimerObj) { - if (!TimerObj || !TimerObj->OrigTimer()) return osContinue; - TimerObj->OrigTimer()->OnOff(); - Timers.SetModified(); - Update(); + cTimers *vdrtimers; +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + vdrtimers = Timers; +#else + vdrtimers = &Timers; +#endif + if (!TimerObj || !TimerObj->OrigTimer(vdrtimers)) return osContinue; + TimerObj->OrigTimer(vdrtimers)->OnOff(); // Toggles Timer Flag + vdrtimers->SetModified(); + Update(vdrtimers); Display(); return osContinue; } -bool cMenuConflictCheckDetails::Update(bool Force) +bool cMenuConflictCheckDetails::Update(const cTimers* vdrtimers, bool Force) { bool result = false; for (cOsdItem *item = First(); item; item = Next(item)) { - if (item->Selectable() && ((cMenuConflictCheckDetailsItem *)item)->Update(Force)) + if (item->Selectable() && ((cMenuConflictCheckDetailsItem *)item)->Update(vdrtimers, Force)) result = true; } return result; @@ -286,22 +300,33 @@ bool cMenuConflictCheckDetails::Update(bool Force) eOSState cMenuConflictCheckDetails::DeleteTimer(cConflictCheckTimerObj* TimerObj) { - cTimer* timer = TimerObj->OrigTimer(); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + cTimer* timer = TimerObj->OrigTimer(vdrtimers); // Check if this timer is active: if (timer) { if (Interface->Confirm(trVDR("Delete timer?"))) { if (timer->Recording()) { if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) { timer->Skip(); +#if VDRVERSNUM > 20300 + cRecordControls::Process(vdrtimers, time(NULL)); +#else cRecordControls::Process(time(NULL)); +#endif } else return osContinue; } LogFile.iSysLog("deleting timer %s", *timer->ToDescr()); - Timers.Del(timer); + vdrtimers->Del(timer); cOsdMenu::Del(Current()); - Timers.SetModified(); + vdrtimers->SetModified(); Display(); return osBack; } @@ -319,7 +344,13 @@ eOSState cMenuConflictCheckDetails::ShowSummary() const cEvent *ei = curTimerObj->Event(); if (ei) { - cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(ei->ChannelID(), true, true); if (channel) return AddSubMenu(new cMenuEventSearchSimple(ei, eventObjects)); } @@ -408,10 +439,16 @@ eOSState cMenuConflictCheckDetails::ProcessKey(eKeys Key) for (it = timerObj->concurrentTimers->begin(); it != timerObj->concurrentTimers->end(); ++it) { bool found = false; - for(cTimer* checkT = Timers.First(); checkT; checkT = Timers.Next(checkT)) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + for(cTimer* checkT = vdrtimers->First(); checkT; checkT = vdrtimers->Next(checkT)) { checkT->Matches(); - if (checkT == (*it)->OrigTimer()) // ok -> found, check for changes + if (checkT == (*it)->OrigTimer(vdrtimers)) // ok -> found, check for changes { if (checkT->IsSingleEvent()) { @@ -444,7 +481,13 @@ eOSState cMenuConflictCheckDetails::ProcessKey(eKeys Key) if (Key != kNone) SetHelpKeys(); - if ((HadSubMenu || gl_TimerProgged) && Update(true)) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers, true)) { if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP { diff --git a/menu_conflictcheck.h b/menu_conflictcheck.h index e8d48d0..e7a858e 100644 --- a/menu_conflictcheck.h +++ b/menu_conflictcheck.h @@ -56,7 +56,7 @@ class cMenuConflictCheckDetailsItem : public cOsdItem { public: cConflictCheckTimerObj* timerObj; cMenuConflictCheckDetailsItem(cConflictCheckTimerObj* TimerObj = NULL); - bool Update(bool Force = false); + bool Update(const cTimers *vdrtimers, bool Force = false); }; // --- cMenuConflictCheckDetails ------------------------------------------------------ @@ -73,7 +73,7 @@ private: void SetHelpKeys(); eOSState ToggleTimer(cConflictCheckTimerObj* TimerObj); eOSState DeleteTimer(cConflictCheckTimerObj* TimerObj); - bool Update(bool Force = false); + bool Update(const cTimers* vdrtimers, bool Force = false); bool BuildList(); eOSState ShowSummary(); void UpdateCurrent(); diff --git a/menu_deftimercheckmethod.c b/menu_deftimercheckmethod.c index 0476211..c776c43 100644 --- a/menu_deftimercheckmethod.c +++ b/menu_deftimercheckmethod.c @@ -142,9 +142,15 @@ void cMenuDefTimerCheckMethod::Set() Clear(); delete modes; - modes = new int[Channels.Count()]; +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + modes = new int[vdrchannels->Count()]; int i=0; - for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel), i++) + for (const cChannel *channel = vdrchannels->First(); channel; channel = vdrchannels->Next(channel), i++) { if (!channel->GroupSep() && *channel->Name()) { @@ -164,7 +170,13 @@ eOSState cMenuDefTimerCheckMethod::ProcessKey(eKeys Key) case kOk: { int i=0; - for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel), i++) +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + for (const cChannel *channel = vdrchannels->First(); channel; channel = vdrchannels->Next(channel), i++) if (!channel->GroupSep() && *channel->Name()) DefTimerCheckModes.SetMode(channel, modes[i]); DefTimerCheckModes.Save(); diff --git a/menu_dirselect.c b/menu_dirselect.c index 2fc24a8..3064c09 100644 --- a/menu_dirselect.c +++ b/menu_dirselect.c @@ -132,9 +132,15 @@ void cMenuDirSelect::CreateDirSet(bool extraDirs) directorySet.clear(); // add distinct directories from current recordings +#if VDRVERSNUM > 20300 + LOCK_RECORDINGS_READ; + const cRecordings *vdrrecordings = Recordings; +#else + cRecordings *vdrrecordings = &Recordings; if (Recordings.Count() == 0) Recordings.Load(); - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) +#endif + for (const cRecording *recording = vdrrecordings->First(); recording; recording = vdrrecordings->Next(recording)) { if (recording->HierarchyLevels() > 0) { @@ -156,7 +162,13 @@ void cMenuDirSelect::CreateDirSet(bool extraDirs) } } // add distinct directories from current timers - for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + const cTimers *vdrtimers = &Timers; +#endif + for (const cTimer *timer = vdrtimers->First(); timer; timer = vdrtimers->Next(timer)) { char* dir = strdup(timer->File()); // strip the trailing name dir diff --git a/menu_event.c b/menu_event.c index 77a03a6..7c29114 100644 --- a/menu_event.c +++ b/menu_event.c @@ -84,7 +84,13 @@ void cMenuEventSearch::Set() if (event) { - cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(event->ChannelID(), true, true); bool canSwitch = false; if (channel) { @@ -96,7 +102,13 @@ void cMenuEventSearch::Set() cEventObj* eventObjNext = GetNext(event); eTimerMatch timerMatch = tmNone; - Timers.GetMatch(event, &timerMatch); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + vdrtimers->GetMatch(event, &timerMatch); const char* szRed = trVDR("Button$Record"); if (timerMatch == tmFull) szRed = trVDR("Button$Timer"); @@ -112,9 +124,9 @@ void cMenuEventSearch::Set() else if (surfMode == SurfModeChannel) { if (eventObjPrev && eventObjPrev->Event()) - szGreen = strdup(CHANNELNAME(Channels.GetByChannelID(eventObjPrev->Event()->ChannelID(), true, true))); + szGreen = strdup(CHANNELNAME(vdrchannels->GetByChannelID(eventObjPrev->Event()->ChannelID(), true, true))); if (eventObjNext && eventObjNext->Event()) - szYellow = strdup(CHANNELNAME(Channels.GetByChannelID(eventObjNext->Event()->ChannelID(), true, true))); + szYellow = strdup(CHANNELNAME(vdrchannels->GetByChannelID(eventObjNext->Event()->ChannelID(), true, true))); SetHelp(szRed, szGreen, szYellow, canSwitch ? trVDR("Button$Switch") : NULL); } } @@ -236,7 +248,13 @@ void cMenuEventSearchSimple::Set() if (event) { - cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(event->ChannelID(), true, true); if (channel) { SetTitle(channel->Name()); diff --git a/menu_favorites.c b/menu_favorites.c index d2dce45..f04aea2 100644 --- a/menu_favorites.c +++ b/menu_favorites.c @@ -122,7 +122,13 @@ eOSState cMenuFavorites::OnYellow() cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current()); if (item && item->event) { - cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(item->event->ChannelID(), true, true); cMenuWhatsOnSearch::scheduleChannel = channel; cMenuWhatsOnSearch::currentShowMode = showNow; } diff --git a/menu_main.c b/menu_main.c index 5203e35..c528918 100644 --- a/menu_main.c +++ b/menu_main.c @@ -42,6 +42,9 @@ The project's page is at http://winni.vdr-developer.org/epgsearch int toggleKeys=0; int exitToMainMenu = 0; extern int gl_InfoConflict; +#if VDRVERSNUM > 20300 +extern bool HandleRemoteModifications(cTimer* NewTimer, cTimer* OldTimer); +#endif int cMenuSearchMain::forceMenu = 0; // 1 = now, 2 = schedule, 3 = summary @@ -58,8 +61,19 @@ cMenuSearchMain::cMenuSearchMain(void) shiftTime = 0; InWhatsOnMenu = false; InFavoritesMenu = false; - cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel()); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByNumber(cDevice::CurrentChannel()); +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + schedules = Schedules; +#else schedules = cSchedules::Schedules(schedulesLock); +#endif if (channel) { cMenuWhatsOnSearch::SetCurrentChannel(channel->Number()); if (EPGSearchConfig.StartMenu == 0 || forceMenu != 0) @@ -108,7 +122,7 @@ int cMenuSearchMain::GetTab(int Tab) return cTemplFile::GetTemplateByName("MenuSchedule")->Tab(Tab-1); } -void cMenuSearchMain::PrepareSchedule(cChannel *Channel) +void cMenuSearchMain::PrepareSchedule(const cChannel *Channel) { Clear(); cString buffer = cString::sprintf("%s - %s", trVDR("Schedule"), Channel->Name()); @@ -163,11 +177,11 @@ void cMenuSearchMain::PrepareSchedule(cChannel *Channel) } } -bool cMenuSearchMain::Update(void) +bool cMenuSearchMain::Update(const cTimers* vdrtimers) { bool result = false; for (cOsdItem *item = First(); item; item = Next(item)) { - if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update()) + if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update(vdrtimers)) result = true; } return result; @@ -176,11 +190,20 @@ bool cMenuSearchMain::Update(void) eOSState cMenuSearchMain::Record(void) { cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current()); + cTimers *vdrtimers; if (item) { +#if VDRVERSNUM > 20300 + { + LOCK_TIMERS_READ; + vdrtimers = (cTimers *)Timers; + } +#else + vdrtimers = &Timers; +#endif if (item->timerMatch == tmFull) { eTimerMatch tm = tmNone; - cTimer *timer = Timers.GetMatch(item->event, &tm); + cTimer *timer = vdrtimers->GetMatch(item->event, &tm); if (timer) { if (EPGSearchConfig.useVDRTimerEditMenu) @@ -192,7 +215,13 @@ eOSState cMenuSearchMain::Record(void) cTimer *timer = new cTimer(item->event); PrepareTimerFile(item->event, timer); - cTimer *t = Timers.GetTimer(timer); +#if VDRVERSNUM > 20300 + { + LOCK_TIMERS_READ; + vdrtimers = (cTimers *)Timers; + } +#endif + cTimer *t = vdrtimers->GetTimer(timer); if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL))) { if (t) @@ -229,15 +258,32 @@ eOSState cMenuSearchMain::Record(void) #endif SetAux(timer, fullaux); - Timers.Add(timer); +#if VDRVERSNUM > 20300 + if (*Setup.SVDRPDefaultHost) + timer->SetRemote(Setup.SVDRPDefaultHost); + { + LOCK_TIMERS_WRITE; + vdrtimers = Timers; + vdrtimers->Add(timer); // implicit SetModified + } +#else + vdrtimers->Add(timer); +#endif gl_timerStatusMonitor->SetConflictCheckAdvised(); timer->Matches(); - Timers.SetModified(); +#if VDRVERSNUM < 20300 + vdrtimers->SetModified(); +#else + if (!HandleRemoteModifications(timer,NULL)) { + vdrtimers->Del(timer); + delete timer; + } +#endif LogFile.iSysLog("timer %s added (active)", *timer->ToDescr()); if (HasSubMenu()) CloseSubMenu(); - if (Update()) + if (Update(vdrtimers)) Display(); SetHelpKeys(); } @@ -249,7 +295,13 @@ eOSState cMenuSearchMain::Switch(void) { cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current()); if (item) { - cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(item->event->ChannelID(), true, true); if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true)) return osEnd; } @@ -306,8 +358,14 @@ void cMenuSearchMain::SetHelpKeys(bool Force) SetHelp((EPGSearchConfig.redkeymode==0?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), trVDR("Button$Now"), trVDR("Button$Next"), EPGSearchConfig.bluekeymode==0?trVDR("Button$Switch"):tr("Button$Search")); else { - const char* szGreenToggled = CHANNELNAME(Channels.GetByNumber(currentChannel-1,-1)); - const char* szYellowToggled = CHANNELNAME(Channels.GetByNumber(currentChannel+1,1)); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const char* szGreenToggled = CHANNELNAME(vdrchannels->GetByNumber(currentChannel-1,-1)); + const char* szYellowToggled = CHANNELNAME(vdrchannels->GetByNumber(currentChannel+1,1)); SetHelp((EPGSearchConfig.redkeymode==1?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), (EPGSearchConfig.toggleGreenYellow==0?trVDR("Button$Now"):szGreenToggled), (EPGSearchConfig.toggleGreenYellow==0?trVDR("Button$Next"):szYellowToggled), EPGSearchConfig.bluekeymode==1?trVDR("Button$Switch"):tr("Button$Search")); @@ -319,7 +377,13 @@ void cMenuSearchMain::SetHelpKeys(bool Force) eOSState cMenuSearchMain::Shift(int iMinutes) { shiftTime += iMinutes; - cChannel *channel = Channels.GetByNumber(currentChannel); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByNumber(currentChannel); PrepareSchedule(channel); Display(); SetHelpKeys(); @@ -433,7 +497,13 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key) cMenuMyScheduleItem* Item = (cMenuMyScheduleItem *)Get(Current()); if (Item && Item->event) { - cChannel *channel = Channels.GetByChannelID(Item->event->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(Item->event->ChannelID(), true, true); if (channel) ChannelNr = channel->Number(); } @@ -451,7 +521,13 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key) } else { - cChannel *channel = Channels.GetByNumber(currentChannel-1,-1); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByNumber(currentChannel-1,-1); if (channel) { PrepareSchedule(channel); @@ -483,7 +559,13 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key) } else { - cChannel *channel = Channels.GetByNumber(currentChannel+1,1); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByNumber(currentChannel+1,1); if (channel) { PrepareSchedule(channel); if (channel->Number() != cDevice::CurrentChannel()) { @@ -517,9 +599,15 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key) } } if (!HasSubMenu()) { - cChannel *ch = cMenuWhatsOnSearch::ScheduleChannel(); + const cChannel *ch = cMenuWhatsOnSearch::ScheduleChannel(); InWhatsOnMenu = false; InFavoritesMenu = false; +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif if (ch) { // when switch from the other menus to the schedule, try to keep the same time if (cMenuWhatsOnSearch::shiftTime) @@ -536,7 +624,7 @@ eOSState cMenuSearchMain::ProcessKey(eKeys Key) } Display(); } - else if ((HadSubMenu || gl_TimerProgged) && Update()) + else if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers)) { if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP { diff --git a/menu_main.h b/menu_main.h index e4a6bb8..26452bf 100644 --- a/menu_main.h +++ b/menu_main.h @@ -38,7 +38,7 @@ class cMenuSearchMain : public cOsdMenu { int currentChannel; eOSState Record(void); eOSState ExtendedSearch(void); - void PrepareSchedule(cChannel *Channel); + void PrepareSchedule(const cChannel *Channel); eOSState Commands(eKeys Key); void SetHelpKeys(bool Force = false); int GetTab(int Tab); @@ -53,7 +53,7 @@ class cMenuSearchMain : public cOsdMenu { eOSState Switch(void); eOSState Shift(int iMinutes); eOSState ShowSummary(); - bool Update(void); + bool Update(const cTimers *vdrtimers); void UpdateCurrent(); #ifdef USE_GRAPHTFT virtual const char* MenuKind() { return "MenuEpgsSchedule"; } diff --git a/menu_myedittimer.c b/menu_myedittimer.c index a6529a4..563b3b4 100644 --- a/menu_myedittimer.c +++ b/menu_myedittimer.c @@ -36,6 +36,9 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #include <math.h> const char *cMenuMyEditTimer::CheckModes[3]; +#if VDRVERSNUM > 20300 +extern bool HandleRemoteModifications(cTimer* NewTimer, cTimer* OldTimer); +#endif cMenuMyEditTimer::cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* Event, const cChannel* forcechannel) :cOsdMenu(trVDR("Edit timer"), 14) @@ -76,7 +79,9 @@ cMenuMyEditTimer::cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* Event, Set(); SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, NULL, NULL); } +#if VDRVERSNUM < 20300 Timers.IncBeingEdited(); +#endif } void cMenuMyEditTimer::SplitFile() @@ -130,7 +135,13 @@ void cMenuMyEditTimer::Set() #ifdef USE_PINPLUGIN if (cOsd::pinValid || !fskProtection) Add(new cMenuEditChanItem(tr("Channel"), &channel)); else { - cString buf = cString::sprintf("%s\t%s", tr("Channel"), Channels.GetByNumber(channel)->Name()); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + cString buf = cString::sprintf("%s\t%s", tr("Channel"), vdrchannels->GetByNumber(channel)->Name()); Add(new cOsdItem(buf)); } #else @@ -162,7 +173,13 @@ void cMenuMyEditTimer::Set() } else if (IsSingleEvent() && event) { - checkmode = DefTimerCheckModes.GetMode(Channels.GetByNumber(channel)); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + checkmode = DefTimerCheckModes.GetMode(vdrchannels->GetByNumber(channel)); char* checkmodeAux = GetAuxValue(timer, "update"); if (checkmodeAux) { @@ -196,7 +213,9 @@ cMenuMyEditTimer::~cMenuMyEditTimer() { if (timer && addIfConfirmed) delete timer; // apparently it wasn't confirmed +#if VDRVERSNUM < 20300 Timers.DecBeingEdited(); +#endif } void cMenuMyEditTimer::HandleSubtitle() @@ -233,20 +252,36 @@ bool cMenuMyEditTimer::IsSingleEvent(void) const eOSState cMenuMyEditTimer::DeleteTimer() { // Check if this timer is active: +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + if (!Timers) { + ERROR("Epgsearch: Recursive LOCK DeleteTimer failed"); + return osContinue; + } + Timers->SetExplicitModify(); + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif if (timer && !addIfConfirmed) { if (Interface->Confirm(trVDR("Delete timer?"))) { if (timer->Recording()) { if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) { timer->Skip(); +#if VDRVERSNUM > 20300 + cRecordControls::Process(vdrtimers, time(NULL)); +#else cRecordControls::Process(time(NULL)); +#endif } else return osContinue; } LogFile.iSysLog("deleting timer %s", *timer->ToDescr()); - Timers.Del(timer); + vdrtimers->Del(timer); + gl_timerStatusMonitor->SetConflictCheckAdvised(); - Timers.SetModified(); + vdrtimers->SetModified(); return osBack; } } @@ -324,7 +359,13 @@ eOSState cMenuMyEditTimer::ProcessKey(eKeys Key) { case kOk: { - cChannel *ch = Channels.GetByNumber(channel); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *ch = vdrchannels->GetByNumber(channel); if (!ch) { ERROR(tr("*** Invalid Channel ***")); @@ -405,12 +446,41 @@ eOSState cMenuMyEditTimer::ProcessKey(eKeys Key) free(tmpFile); free(tmpDir); - if (addIfConfirmed) - Timers.Add(timer); +#if VDRVERSNUM > 20300 + { + LOCK_TIMERS_WRITE; + if (!Timers) { + ERROR("Epgsearch: recursive TIMERS LOCK"); + return osBack; + } + Timers->SetExplicitModify(); + cTimers* vdrtimers = Timers; + if (*Setup.SVDRPDefaultHost) + timer->SetRemote(Setup.SVDRPDefaultHost); +#else + cTimers* vdrtimers = &Timers; +#endif + if (addIfConfirmed) { + vdrtimers->Add(timer); +#if VDRVERSNUM > 20300 + vdrtimers->SetModified(); + if (!HandleRemoteModifications(timer,NULL)) { + vdrtimers->Del(timer); + delete timer; + } + } + } + LOCK_SCHEDULES_READ; + timer->SetEventFromSchedule(Schedules); +#else + } timer->SetEventFromSchedule(); +#endif timer->Matches(); gl_timerStatusMonitor->SetConflictCheckAdvised(); - Timers.SetModified(); +#if VDRVERSNUM < 20300 + vdrtimers->SetModified(); +#endif addIfConfirmed = false; } else { free(tmpFile); diff --git a/menu_quicksearch.c b/menu_quicksearch.c index 069d5d8..53aeff5 100644 --- a/menu_quicksearch.c +++ b/menu_quicksearch.c @@ -248,7 +248,13 @@ eOSState cMenuQuickSearch::ProcessKey(eKeys Key) case kOk: if (data.useChannel==1) { - cChannel *ch = Channels.GetByNumber(channelMin); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *ch = vdrchannels->GetByNumber(channelMin); if (ch) data.channelMin = ch; else @@ -256,7 +262,7 @@ eOSState cMenuQuickSearch::ProcessKey(eKeys Key) ERROR(tr("*** Invalid Channel ***")); break; } - ch = Channels.GetByNumber(channelMax); + ch = vdrchannels->GetByNumber(channelMax); if (ch) data.channelMax = ch; else diff --git a/menu_searchedit.c b/menu_searchedit.c index e44e8c8..9328e5b 100644 --- a/menu_searchedit.c +++ b/menu_searchedit.c @@ -643,7 +643,13 @@ eOSState cMenuEditSearchExt::ProcessKey(eKeys Key) case kOk: if (data.useChannel==1) { - cChannel *ch = Channels.GetByNumber(channelMin); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *ch = vdrchannels->GetByNumber(channelMin); if (ch) data.channelMin = ch; else @@ -651,7 +657,7 @@ eOSState cMenuEditSearchExt::ProcessKey(eKeys Key) ERROR(tr("*** Invalid Channel ***")); break; } - ch = Channels.GetByNumber(channelMax); + ch = vdrchannels->GetByNumber(channelMax); if (ch) data.channelMax = ch; else diff --git a/menu_searchresults.c b/menu_searchresults.c index dd46d95..6635d43 100644 --- a/menu_searchresults.c +++ b/menu_searchresults.c @@ -44,6 +44,9 @@ The project's page is at http://winni.vdr-developer.org/epgsearch const char* ButtonBlue[3] = {NULL, NULL, NULL}; extern int gl_InfoConflict; extern bool isUTF8; +#if VDRVERSNUM > 20300 +extern bool HandleRemoteModifications(cTimer* NewTimer, cTimer* OldTimer); +#endif static int CompareRecording(const void *p1, const void *p2) { @@ -67,10 +70,16 @@ cMenuSearchResultsItem::cMenuSearchResultsItem(const cEvent *EventInfo, bool Epi menuTemplate = MenuTemplate?MenuTemplate:cTemplFile::GetTemplateByName("MenuSearchResults"); search = Search; inSwitchList = false; - Update(true); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + Update(vdrtimers, true); } -bool cMenuSearchResultsItem::Update(bool Force) +bool cMenuSearchResultsItem::Update(const cTimers* vdrtimers, bool Force) { if (!menuTemplate) return false; @@ -80,8 +89,12 @@ bool cMenuSearchResultsItem::Update(bool Force) eTimerMatch OldTimerMatch = timerMatch; bool OldInSwitchList = inSwitchList; bool hasMatch = false; - cTimer* timer = NULL; - if (event) timer = Timers.GetMatch(event, &timerMatch); + const cTimer* timer = NULL; +#if VDRVERSNUM > 20300 + if (event) timer = vdrtimers->GetMatch(event, &timerMatch); +#else + if (event) timer = ((cTimers*)vdrtimers)->GetMatch(event, &timerMatch); +#endif if (event) inSwitchList = (SwitchTimers.InSwitchList(event)!=NULL); if (timer) hasMatch = true; @@ -161,8 +174,12 @@ bool cMenuSearchResultsItem::Update(bool Force) if (EPGSearchConfig.checkTimerConflAfterTimerProg && !Force && timer && timerMatch && timerMatch != OldTimerMatch) { cConflictCheck C; +#if VDRVERSNUM > 20300 + C.Check(vdrtimers); +#else C.Check(); - if (C.TimerInConflict(timer)) +#endif + if (C.TimerInConflict(vdrtimers, timer)) gl_InfoConflict = 1; } @@ -171,7 +188,7 @@ bool cMenuSearchResultsItem::Update(bool Force) return result; } -cMenuSearchResultsItem::cMenuSearchResultsItem(cRecording *Recording) +cMenuSearchResultsItem::cMenuSearchResultsItem(const cRecording *Recording) { previewTimer = false; episodeOnly = false; @@ -187,7 +204,13 @@ cMenuSearchResultsItem::cMenuSearchResultsItem(cRecording *Recording) void cMenuSearchResultsItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable) { #if APIVERSNUM >= 10733 - cChannel *channel = event?Channels.GetByChannelID(event->ChannelID(), true, true):NULL; +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = event?vdrchannels->GetByChannelID(event->ChannelID(), true, true):NULL; if (!event) DisplayMenu->SetItem(Text(), Index, Current, Selectable); else if (!DisplayMenu->SetItemEvent(event, Index, Current, Selectable, channel, true, timerMatch)) @@ -222,11 +245,11 @@ int cMenuSearchResults::GetTab(int Tab) return menuTemplate->Tab(Tab-1); } -bool cMenuSearchResults::Update(void) +bool cMenuSearchResults::Update(const cTimers* vdrtimers) { bool result = false; for (cOsdItem *item = First(); item; item = Next(item)) { - if (((cMenuSearchResultsItem *)item)->Update()) + if (((cMenuSearchResultsItem *)item)->Update(vdrtimers)) result = true; } return result; @@ -237,10 +260,17 @@ eOSState cMenuSearchResults::Record(void) UpdateCurrent(); cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current()); if (item) { +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif if (item->timerMatch == tmFull) { eTimerMatch tm = tmNone; - cTimer *timer = Timers.GetMatch(item->event, &tm); + cTimer *timer = vdrtimers->GetMatch(item->event, &tm); if (timer) { if (EPGSearchConfig.useVDRTimerEditMenu) @@ -252,7 +282,7 @@ eOSState cMenuSearchResults::Record(void) cTimer *timer = new cTimer(item->event); PrepareTimerFile(item->event, timer); - cTimer *t = Timers.GetTimer(timer); + cTimer *t = vdrtimers->GetTimer(timer); if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL))) { if (t) @@ -290,15 +320,26 @@ eOSState cMenuSearchResults::Record(void) #endif SetAux(timer, fullaux); - Timers.Add(timer); +#if VDRVERSNUM > 20300 + if (*Setup.SVDRPDefaultHost) + timer->SetRemote(Setup.SVDRPDefaultHost); +#endif + vdrtimers->Add(timer); gl_timerStatusMonitor->SetConflictCheckAdvised(); timer->Matches(); - Timers.SetModified(); + vdrtimers->SetModified(); +#if VDRVERSNUM > 20300 + if (!HandleRemoteModifications(timer,NULL)) { + vdrtimers->Del(timer); + delete timer; + } +#else LogFile.iSysLog("timer %s added (active)", *timer->ToDescr()); +#endif if (HasSubMenu()) CloseSubMenu(); - if (Update()) + if (Update(vdrtimers)) Display(); SetHelpKeys(); } @@ -312,7 +353,13 @@ eOSState cMenuSearchResults::Switch(void) UpdateCurrent(); cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current()); if (item) { - cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(item->event->ChannelID(), true, true); if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true)) return osEnd; } @@ -342,7 +389,13 @@ eOSState cMenuSearchResults::ShowSummary() const cEvent *ei = ((cMenuSearchResultsItem *)Get(Current()))->event; if (ei) { - cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(ei->ChannelID(), true, true); if (channel) return AddSubMenu(new cMenuEventSearch(ei, eventObjects)); } @@ -454,7 +507,13 @@ eOSState cMenuSearchResults::ProcessKey(eKeys Key) } if (!HasSubMenu()) { - if ((HadSubMenu || gl_TimerProgged) && Update()) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers)) { if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP { @@ -768,12 +827,18 @@ cMenuSearchResultsForRecs::cMenuSearchResultsForRecs(const char *query) bool cMenuSearchResultsForRecs::BuildList() { - cRecording **pArray = NULL; + const cRecording **pArray = NULL; int num = 0; int current = Current(); Clear(); - for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { +#if VDRVERSNUM > 20300 + LOCK_RECORDINGS_READ; + const cRecordings *vdrrecordings = Recordings; +#else + cRecordings *vdrrecordings = &Recordings; +#endif + for (const cRecording *recording = vdrrecordings->First(); recording; recording = vdrrecordings->Next(recording)) { const cRecordingInfo *recInfo = recording->Info(); if (!recInfo) continue; string s1 = (recInfo && recInfo->Title())?recInfo->Title():""; @@ -808,7 +873,7 @@ bool cMenuSearchResultsForRecs::BuildList() } if (match) { - cRecording **tmp = (cRecording **)realloc(pArray, (num + 1) * sizeof(cRecording *)); + const cRecording **tmp = (const cRecording **)realloc(pArray, (num + 1) * sizeof(cRecording *)); if (tmp) { pArray=tmp; @@ -829,9 +894,15 @@ bool cMenuSearchResultsForRecs::BuildList() return true; } -cRecording *cMenuSearchResultsForRecs::GetRecording(cMenuSearchResultsItem *Item) +const cRecording *cMenuSearchResultsForRecs::GetRecording(cMenuSearchResultsItem *Item) { - cRecording *recording = Recordings.GetByName(Item->FileName()); +#if VDRVERSNUM > 20300 + LOCK_RECORDINGS_READ; + const cRecordings *vdrrecordings = Recordings; +#else + cRecordings *vdrrecordings = &Recordings; +#endif + const cRecording *recording = vdrrecordings->GetByName(Item->FileName()); if (!recording) ERROR(tr("Error while accessing recording!")); return recording; @@ -842,7 +913,7 @@ eOSState cMenuSearchResultsForRecs::Play(void) cMenuSearchResultsItem *ri = (cMenuSearchResultsItem*)Get(Current()); if (ri) { - cRecording *recording = GetRecording(ri); + const cRecording *recording = GetRecording(ri); if (recording) { #if APIVERSNUM < 10728 cReplayControl::SetRecording(recording->FileName(), recording->Title()); diff --git a/menu_searchresults.h b/menu_searchresults.h index 05d5660..f31d9c0 100644 --- a/menu_searchresults.h +++ b/menu_searchresults.h @@ -58,8 +58,8 @@ class cMenuSearchResultsItem : public cOsdItem { cMenuSearchResultsItem(const cEvent *EventInfo, bool EpisodeOnly = false, bool PreviewTimer = false, cMenuTemplate* MenuTemplate = NULL, const cSearchExt* Search = NULL); - cMenuSearchResultsItem(cRecording *Recording); - bool Update(bool Force = false); + cMenuSearchResultsItem(const cRecording *Recording); + bool Update(const cTimers* vdrtimers, bool Force = false); void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); }; @@ -83,7 +83,7 @@ class cMenuSearchResults : public cOsdMenu { eOSState Commands(eKeys Key, cSearchExt* SearchExt = NULL); int GetTab(int Tab); virtual void SetHelpKeys(bool Force=false)=0; - bool Update(void); + bool Update(const cTimers* vdrtimers); void UpdateCurrent(); static const cEvent *scheduleEventInfo; @@ -131,7 +131,7 @@ class cMenuSearchResultsForRecs : public cMenuSearchResultsForQuery { virtual bool BuildList(); eOSState ProcessKey(eKeys Key); eOSState Play(void); - cRecording *GetRecording(cMenuSearchResultsItem *Item); + const cRecording *GetRecording(cMenuSearchResultsItem *Item); public: cMenuSearchResultsForRecs(const char *query); }; diff --git a/menu_switchtimers.c b/menu_switchtimers.c index 1a8139a..7c1bc72 100644 --- a/menu_switchtimers.c +++ b/menu_switchtimers.c @@ -136,7 +136,13 @@ void cMenuSwitchTimerItem::Set() tm *tm = localtime_r(&startTime, &tm_r); strftime(datebuf, sizeof(datebuf), "%d.%m", tm); - cChannel* channel = Channels.GetByChannelID(switchTimer->channelID,true,true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->GetByChannelID(switchTimer->channelID,true,true); msprintf(&buffer, "%s\t%d\t%s\t%s\t%d\'\t%s~%s", switchTimer->mode==1?"":">", channel?channel->Number():-1, datebuf, TIMESTRING(startTime), switchTimer->switchMinsBefore, event->Title()?event->Title():"", event->ShortText()?event->ShortText():""); SetText(buffer, false); diff --git a/menu_templateedit.c b/menu_templateedit.c index f1c02b3..fc7d9c3 100644 --- a/menu_templateedit.c +++ b/menu_templateedit.c @@ -187,7 +187,13 @@ eOSState cMenuEditTemplate::ProcessKey(eKeys Key) case kOk: if (data.useChannel==1) { - cChannel *ch = Channels.GetByNumber(channelMin); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *ch = vdrchannels->GetByNumber(channelMin); if (ch) data.channelMin = ch; else @@ -195,7 +201,7 @@ eOSState cMenuEditTemplate::ProcessKey(eKeys Key) ERROR(tr("*** Invalid Channel ***")); break; } - ch = Channels.GetByNumber(channelMax); + ch = vdrchannels->GetByNumber(channelMax); if (ch) data.channelMax = ch; else diff --git a/menu_timersdone.c b/menu_timersdone.c index a239892..6eb370d 100644 --- a/menu_timersdone.c +++ b/menu_timersdone.c @@ -44,7 +44,13 @@ void cMenuTimerDoneItem::Set(void) tm *tm = localtime_r(&timerDone->start, &tm_r); strftime(buf, sizeof(buf), "%d.%m.%y %H:%M", tm); - const cChannel* ch = Channels.GetByChannelID(timerDone->channelID, true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* ch = vdrchannels->GetByChannelID(timerDone->channelID, true, true); msprintf(&buffer, "%d\t%s\t%s~%s", ch?ch->Number():0, buf, timerDone->title.c_str(), timerDone->shorttext.c_str()); SetText(buffer, false); } diff --git a/menu_whatson.c b/menu_whatson.c index daa4359..862084d 100644 --- a/menu_whatson.c +++ b/menu_whatson.c @@ -52,10 +52,13 @@ The project's page is at http://winni.vdr-developer.org/epgsearch extern int exitToMainMenu; extern bool isUTF8; +#if VDRVERSNUM > 20300 +extern bool HandleRemoteModifications(cTimer* NewTimer, cTimer* OldTimer); +#endif int gl_InfoConflict = 0; // --- cMenuMyScheduleItem ------------------------------------------------------ -cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, cChannel *Channel, showMode Mode, cMenuTemplate* MenuTemplate) +cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, const cChannel *Channel, showMode Mode, cMenuTemplate* MenuTemplate) { event = Event; channel = Channel; @@ -63,10 +66,16 @@ cMenuMyScheduleItem::cMenuMyScheduleItem(const cEvent *Event, cChannel *Channel, timerMatch = tmNone; inSwitchList = false; menuTemplate = MenuTemplate; - Update(true); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + Update(vdrtimers, true); } -bool cMenuMyScheduleItem::Update(bool Force) +bool cMenuMyScheduleItem::Update(const cTimers* vdrtimers, bool Force) { if (!menuTemplate) return false; @@ -80,8 +89,12 @@ bool cMenuMyScheduleItem::Update(bool Force) eTimerMatch OldTimerMatch = timerMatch; bool OldInSwitchList = inSwitchList; bool hasMatch = false; - cTimer* timer = NULL; - if (event) timer = Timers.GetMatch(event, &timerMatch); + const cTimer* timer = NULL; +#if VDRVERSNUM > 20300 + if (event) timer = vdrtimers->GetMatch(event, &timerMatch); +#else + if (event) timer = ((cTimers*)vdrtimers)->GetMatch(event, &timerMatch); +#endif if (event) inSwitchList = (SwitchTimers.InSwitchList(event)!=NULL); if (timer) hasMatch = true; @@ -239,7 +252,7 @@ bool cMenuMyScheduleItem::Update(bool Force) { cConflictCheck C; C.Check(); - if (C.TimerInConflict(timer)) + if (C.TimerInConflict(vdrtimers, timer)) gl_InfoConflict = 1; } return true; @@ -257,14 +270,20 @@ void cMenuMyScheduleItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, } // --- cMenuMyScheduleSepItem ------------------------------------------------------ -cMenuMyScheduleSepItem::cMenuMyScheduleSepItem(const cEvent *Event, cChannel *Channel) +cMenuMyScheduleSepItem::cMenuMyScheduleSepItem(const cEvent *Event, const cChannel *Channel) : cMenuMyScheduleItem(Event, Channel, showNow, NULL) { event = Event; channel = Channel; dummyEvent = NULL; SetSelectable(false); - Update(true); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + Update(vdrtimers, true); } cMenuMyScheduleSepItem::~cMenuMyScheduleSepItem() @@ -273,7 +292,7 @@ cMenuMyScheduleSepItem::~cMenuMyScheduleSepItem() delete dummyEvent; } -bool cMenuMyScheduleSepItem::Update(bool Force) +bool cMenuMyScheduleSepItem::Update(const cTimers* vdrtimer, bool Force) { if (channel) SetText(cString::sprintf("%s\t %s %s", MENU_SEPARATOR_ITEMS, channel->Name(), MENU_SEPARATOR_ITEMS)); @@ -300,7 +319,7 @@ void cMenuMyScheduleSepItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Inde int cMenuWhatsOnSearch::currentChannel = 0; showMode cMenuWhatsOnSearch::currentShowMode = showNow; -cChannel *cMenuWhatsOnSearch::scheduleChannel = NULL; +const cChannel *cMenuWhatsOnSearch::scheduleChannel = NULL; extern const char *ShowModes[]; cList<cShowMode> cMenuWhatsOnSearch::showModes; time_t cMenuWhatsOnSearch::seekTime = 0; @@ -429,7 +448,13 @@ void cMenuWhatsOnSearch::LoadSchedules() if (currentChannel > maxChannel) maxChannel = 0; - for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + for (const cChannel *Channel = vdrchannels->First(); Channel; Channel = vdrchannels->Next(Channel)) { if (!Channel->GroupSep()) { @@ -544,9 +569,9 @@ cShowMode* cMenuWhatsOnSearch::GetShowMode(showMode mode) return NULL; } -cChannel *cMenuWhatsOnSearch::ScheduleChannel(cChannel *force_channel) +const cChannel *cMenuWhatsOnSearch::ScheduleChannel(const cChannel *force_channel) { - cChannel *ch = force_channel?force_channel:scheduleChannel; + const cChannel *ch = force_channel?force_channel:scheduleChannel; scheduleChannel = NULL; return ch; } @@ -568,10 +593,17 @@ eOSState cMenuWhatsOnSearch::Record(void) cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current()); if (item) { +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; + Timers->SetExplicitModify(); + cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif if (item->timerMatch == tmFull) { eTimerMatch tm = tmNone; - cTimer *timer = Timers.GetMatch(item->event, &tm); + cTimer *timer = vdrtimers->GetMatch(item->event, &tm); if (timer) { if (EPGSearchConfig.useVDRTimerEditMenu) @@ -588,9 +620,13 @@ eOSState cMenuWhatsOnSearch::Record(void) PrepareTimerFile(item->event, timer); } else +#if VDRVERSNUM > 20300 timer = new cTimer(false, false, item->channel); +#else + timer = new cTimer(false, false, (cChannel*)item->channel); +#endif - cTimer *t = Timers.GetTimer(timer); + cTimer *t = vdrtimers->GetTimer(timer); if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL))) { if (t) @@ -627,15 +663,26 @@ eOSState cMenuWhatsOnSearch::Record(void) fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); #endif SetAux(timer, fullaux); - Timers.Add(timer); +#if VDRVERSNUM > 20300 + if (*Setup.SVDRPDefaultHost) + timer->SetRemote(Setup.SVDRPDefaultHost); +#endif + vdrtimers->Add(timer); gl_timerStatusMonitor->SetConflictCheckAdvised(); timer->Matches(); - Timers.SetModified(); + vdrtimers->SetModified(); +#if VDRVERSNUM > 20300 + if (!HandleRemoteModifications(timer,NULL)) { + vdrtimers->Del(timer); + delete timer; + } +#else LogFile.iSysLog("timer %s added (active)", *timer->ToDescr()); +#endif if (HasSubMenu()) CloseSubMenu(); - if (Update()) + if (Update(vdrtimers)) Display(); SetHelpKeys(); } @@ -643,11 +690,11 @@ eOSState cMenuWhatsOnSearch::Record(void) return osContinue; } -bool cMenuWhatsOnSearch::Update(void) +bool cMenuWhatsOnSearch::Update(const cTimers* vdrtimers) { bool result = false; for (cOsdItem *item = First(); item; item = Next(item)) { - if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update()) + if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update(vdrtimers)) result = true; } return result; @@ -725,7 +772,13 @@ eOSState cMenuWhatsOnSearch::Shift(int iMinutes) if (mi) { currentChannel = mi->channel->Number(); - scheduleChannel = Channels.GetByNumber(currentChannel); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + scheduleChannel = vdrchannels->GetByNumber(currentChannel); } LoadSchedules(); Display(); @@ -741,7 +794,13 @@ eOSState cMenuWhatsOnSearch::ShowSummary() const cEvent *ei = ((cMenuMyScheduleItem *)Get(Current()))->event; if (ei) { - cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(ei->ChannelID(), true, true); if (channel) return AddSubMenu(new cMenuEventSearch(ei, eventObjects, SurfModeChannel)); } @@ -866,7 +925,13 @@ eOSState cMenuWhatsOnSearch::ProcessKey(eKeys Key) if (mi && mi->Selectable()) { currentChannel = mi->channel->Number(); - scheduleChannel = Channels.GetByNumber(currentChannel); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + scheduleChannel = vdrchannels->GetByNumber(currentChannel); } } else @@ -904,7 +969,13 @@ eOSState cMenuWhatsOnSearch::ProcessKey(eKeys Key) } if (!HasSubMenu()) { - if ((HadSubMenu || gl_TimerProgged) && Update()) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + if ((HadSubMenu || gl_TimerProgged) && Update(vdrtimers)) { if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP { diff --git a/menu_whatson.h b/menu_whatson.h index 3fd028d..34d6de3 100644 --- a/menu_whatson.h +++ b/menu_whatson.h @@ -33,14 +33,14 @@ The project's page is at http://winni.vdr-developer.org/epgsearch class cMenuMyScheduleItem : public cOsdItem { public: const cEvent *event; - cChannel *channel; + const cChannel *channel; showMode mode; eTimerMatch timerMatch; bool inSwitchList; cMenuTemplate* menuTemplate; - cMenuMyScheduleItem(const cEvent *Event, cChannel *Channel = NULL, showMode ShowMode = showNow, cMenuTemplate* menuTemplate = NULL); - virtual bool Update(bool Force = false); + cMenuMyScheduleItem(const cEvent *Event, const cChannel *Channel = NULL, showMode ShowMode = showNow, cMenuTemplate* menuTemplate = NULL); + virtual bool Update(const cTimers* vdrtimers, bool Force = false); virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); }; @@ -52,9 +52,9 @@ class cMenuMyScheduleSepItem : public cMenuMyScheduleItem { // if VDR had a SetItemSeparator function for this public: - cMenuMyScheduleSepItem(const cEvent *Event, cChannel *Channel = NULL); + cMenuMyScheduleSepItem(const cEvent *Event, const cChannel *Channel = NULL); ~cMenuMyScheduleSepItem(); - virtual bool Update(bool Force = false); + virtual bool Update(const cTimers* vdrtimers, bool Force = false); virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); }; @@ -68,7 +68,7 @@ private: static int currentChannel; cEventObjects eventObjects; public: - static cChannel *scheduleChannel; + static const cChannel *scheduleChannel; static cList<cShowMode> showModes; static showMode currentShowMode; static int shiftTime; @@ -80,7 +80,7 @@ private: void LoadSchedules(); static int CurrentChannel(void) { return currentChannel; } static void SetCurrentChannel(int ChannelNr) { currentChannel = ChannelNr; } - static cChannel *ScheduleChannel(cChannel* forceChannel = NULL); + static const cChannel *ScheduleChannel(const cChannel* forceChannel = NULL); virtual eOSState ProcessKey(eKeys Key); virtual eOSState Switch(void); virtual eOSState Shift(int); @@ -88,7 +88,7 @@ private: virtual eOSState ShowSummary(); void SetHelpKeys(bool Force = false); int GetTab(int Tab); - bool Update(void); + bool Update(const cTimers* vdrtimers); void CreateShowModes(); static cShowMode* GetShowMode(showMode mode); void UpdateCurrent(); diff --git a/patches/vdr.epgsearch-exttimeredit-2.3.1.diff b/patches/vdr.epgsearch-exttimeredit-2.3.1.diff new file mode 100644 index 0000000..4de62a8 --- /dev/null +++ b/patches/vdr.epgsearch-exttimeredit-2.3.1.diff @@ -0,0 +1,114 @@ +Index: current/menu.c +=================================================================== +--- menu.c.orig 2015-11-02 11:54:55.310709767 +0100 ++++ menu.c 2015-11-02 11:54:55.310709767 +0100 +@@ -1190,6 +1190,7 @@ + class cMenuTimerItem : public cOsdItem { + private: + const cTimer *timer; ++ void DoSet(void); + public: + cMenuTimerItem(const cTimer *Timer); + virtual int Compare(const cListObject &ListObject) const; +@@ -1201,7 +1202,7 @@ + cMenuTimerItem::cMenuTimerItem(const cTimer *Timer) + { + timer = Timer; +- Set(); ++ DoSet(); + } + + int cMenuTimerItem::Compare(const cListObject &ListObject) const +@@ -1211,6 +1212,19 @@ + + void cMenuTimerItem::Set(void) + { ++ // check for deleted timer ++ LOCK_TIMERS_READ; ++ for (const cTimer *t = Timers->First(); ; t = Timers->Next(t)) { ++ if (t == timer) ++ break; // timer still there ++ if (t == NULL) ++ return; // no matching timer found ++ } ++ DoSet(); ++} ++ ++void cMenuTimerItem::DoSet(void) ++{ + cString day, name(""); + if (timer->WeekDays()) + day = timer->PrintDay(0, timer->WeekDays(), false); +@@ -1258,8 +1273,7 @@ + cStateKey timersStateKey; + int helpKeys; + void Set(void); +- eOSState Edit(void); +- eOSState New(void); ++ eOSState Edit(bool New = false); + eOSState Delete(void); + eOSState OnOff(void); + eOSState Info(void); +@@ -1351,20 +1365,29 @@ + return osContinue; + } + +-eOSState cMenuTimers::Edit(void) +-{ +- if (HasSubMenu() || Count() == 0) +- return osContinue; +- return AddSubMenu(new cMenuEditTimer(GetTimer())); +-} +- +-eOSState cMenuTimers::New(void) ++eOSState cMenuTimers::Edit(bool New) + { +- if (HasSubMenu()) ++ if (HasSubMenu() || Count() == 0 && !New) + return osContinue; + cTimer *Timer = new cTimer; + if (*Setup.SVDRPDefaultHost) + Timer->SetRemote(Setup.SVDRPDefaultHost); ++ // Data structure for service "Epgsearch-exttimeredit-v1.0" ++ struct Epgsearch_exttimeredit_v1_0 ++ { ++ // in ++ cTimer* timer; // pointer to the timer to edit ++ bool bNew; // flag that indicates, if this is a new timer or an existing one ++ const cEvent* event; // pointer to the event corresponding to this timer (may be NULL) ++ // out ++ cOsdMenu* pTimerMenu; // pointer to the menu of results ++ } exttimeredit; ++ exttimeredit.timer = New ? (new cTimer) : GetTimer(); ++ exttimeredit.bNew = New; ++ exttimeredit.event = exttimeredit.timer->Event(); ++ if (cPluginManager::CallFirstService("Epgsearch-exttimeredit-v1.0", &exttimeredit)) ++ return AddSubMenu(exttimeredit.pTimerMenu); ++ + return AddSubMenu(new cMenuEditTimer(Timer, true)); + } + +@@ -1423,7 +1446,7 @@ + switch (Key) { + case kOk: return Edit(); + case kRed: state = OnOff(); break; // must go through SetHelpKeys()! +- case kGreen: return New(); ++ case kGreen: return Edit(true); + case kYellow: state = Delete(); break; + case kInfo: + case kBlue: return Info(); +@@ -1437,6 +1460,14 @@ + Add(new cMenuTimerItem(Timer), true); + Display(); + } ++ if (!HasSubMenu()) { ++ LOCK_TIMERS_READ; ++ if (Timers->Count()<Count()) { ++ // timer was deleted ++ cOsdMenu::Del(Current()); ++ Display(); ++ } ++ } + if (Key != kNone) + SetHelpKeys(); + return state; diff --git a/pending_notifications.c b/pending_notifications.c index 4ce480f..8d3046d 100644 --- a/pending_notifications.c +++ b/pending_notifications.c @@ -121,7 +121,13 @@ const char *cPendingNotification::ToText(void) const free(buffer); buffer = NULL; - cChannel *channel = Channels.GetByChannelID(channelID, true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true); if (!channel) LogFile.Log(3,"invalid channel in pending notifications!"); @@ -50,7 +50,7 @@ cRecDone::cRecDone() rawdescription = NULL; } -cRecDone::cRecDone(cTimer* Timer, const cEvent* Event, cSearchExt* Search) +cRecDone::cRecDone(const cTimer* Timer, const cEvent* Event, cSearchExt* Search) { title = shortText = description = aux = rawdescription = NULL; startTime = 0; @@ -200,7 +200,13 @@ const char *cRecDone::ToText(void) free(buffer); buffer = NULL; - cChannel *channel = Channels.GetByChannelID(channelID, true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true); if (!channel) LogFile.Log(3,"invalid channel in recs done!"); @@ -226,7 +232,13 @@ bool cRecDone::Save(FILE *f) int cRecDone::ChannelNr() { - cChannel* channel = Channels.GetByChannelID(channelID, true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel* channel = vdrchannels->GetByChannelID(channelID, true, true); if (!channel) return -1; else @@ -47,7 +47,7 @@ public: static char *buffer; cRecDone(); - cRecDone(cTimer*, const cEvent* event, cSearchExt* search); + cRecDone(const cTimer*, const cEvent* event, cSearchExt* search); ~cRecDone(); static bool Read(FILE *f); diff --git a/recstatus.c b/recstatus.c index 8e6afd8..f2fd993 100644 --- a/recstatus.c +++ b/recstatus.c @@ -27,11 +27,14 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #include "conflictcheck_thread.h" #include "epgsearchcfg.h" #include <math.h> - +#if VDRVERSNUM > 20300 +#include "status_thread.h" +#else #define ALLOWED_BREAK_INSECS 2 extern int updateForced; extern int gl_InfoConflict; +#endif cRecStatusMonitor* gl_recStatusMonitor = NULL; @@ -42,6 +45,9 @@ cRecStatusMonitor::cRecStatusMonitor() void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const char* Filename, bool On) { +#if VDRVERSNUM > 20300 + cStatusThread::Init(Device,Name,Filename,On); +#else time_t now = time(NULL); // insert new timers currently recording in TimersRecording if (On && Name) @@ -130,7 +136,13 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const // check if recording has ended before timer end bool complete = true; - cRecording *pRecording = Recordings.GetByName(Filename); +#if VDRVERSNUM > 20300 + LOCK_RECORDINGS_READ; + const cRecordings *vdrrecordings = Recordings; +#else + cRecordings *vdrrecordings = &Recordings; +#endif + const cRecording *pRecording = vdrrecordings->GetByName(Filename); long timerLengthSecs = tiR->timer->StopTime()-tiR->timer->StartTime(); int recFraction = 100; if (pRecording && timerLengthSecs) @@ -191,9 +203,10 @@ void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const tiR = TimersRecording.Next(tiR); } } +#endif } -int cRecStatusMonitor::TimerRecDevice(cTimer* timer) +int cRecStatusMonitor::TimerRecDevice(const cTimer* timer) { if (!timer) return 0; for (cRecDoneTimerObj *tiR = TimersRecording.First(); tiR; tiR = TimersRecording.Next(tiR)) @@ -201,7 +214,7 @@ int cRecStatusMonitor::TimerRecDevice(cTimer* timer) return 0; } -bool cRecStatusMonitor::IsPesRecording(cRecording *pRecording) +bool cRecStatusMonitor::IsPesRecording(const cRecording *pRecording) { #if VDRVERSNUM < 10703 return true; @@ -214,7 +227,7 @@ bool cRecStatusMonitor::IsPesRecording(cRecording *pRecording) #if VDRVERSNUM < 10703 -int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording) +int cRecStatusMonitor::RecLengthInSecs(const cRecording *pRecording) { struct stat buf; cString fullname = cString::sprintf("%s%s", pRecording->FileName(), "/index.vdr"); @@ -249,7 +262,7 @@ struct tIndexTs { } }; -int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording) +int cRecStatusMonitor::RecLengthInSecs(const cRecording *pRecording) { struct stat buf; cString fullname = cString::sprintf("%s%s", pRecording->FileName(), IsPesRecording(pRecording) ? LOC_INDEXFILESUFFIX ".vdr" : LOC_INDEXFILESUFFIX); @@ -263,4 +276,3 @@ int cRecStatusMonitor::RecLengthInSecs(cRecording *pRecording) return -1; } #endif - diff --git a/recstatus.h b/recstatus.h index 1195bca..0d08b6c 100644 --- a/recstatus.h +++ b/recstatus.h @@ -32,20 +32,23 @@ public: cRecDone* recDone; time_t lastBreak; public: - cRecDoneTimerObj(cTimer* Timer, int DeviceNr) : cTimerObj(Timer), deviceNr(DeviceNr), recDone(NULL), lastBreak(0) {} + cRecDoneTimerObj(const cTimer* Timer, int DeviceNr) : cTimerObj(Timer), deviceNr(DeviceNr), recDone(NULL), lastBreak(0) {} ~cRecDoneTimerObj() { timer = NULL; recDone = NULL; } // do not delete anything! }; class cRecStatusMonitor : public cStatus { +#if VDRVERSNUM > 20300 +public: +#endif cList<cRecDoneTimerObj> TimersRecording; protected: virtual void Recording(const cDevice *Device, const char *Name, const char*, bool On); public: cRecStatusMonitor(); - int TimerRecDevice(cTimer*); - bool IsPesRecording(cRecording *pRecording); - int RecLengthInSecs(cRecording *pRecording); + int TimerRecDevice(const cTimer*); + bool IsPesRecording(const cRecording *pRecording); + int RecLengthInSecs(const cRecording *pRecording); }; extern cRecStatusMonitor* gl_recStatusMonitor; diff --git a/searchtimer_thread.c b/searchtimer_thread.c index 34d625f..6039c54 100644 --- a/searchtimer_thread.c +++ b/searchtimer_thread.c @@ -52,6 +52,9 @@ The project's page is at http://winni.vdr-developer.org/epgsearch #define DAYBUFFERSIZE 32 extern int updateForced; +#if VDRVERSNUM > 20300 +extern bool HandleRemoteModifications(cTimer* NewTimer, cTimer* OldTimer); +#endif cSearchTimerThread *cSearchTimerThread::m_Instance = NULL; cSearchResults cSearchTimerThread::announceList; @@ -99,9 +102,15 @@ void cSearchTimerThread::Stop(void) { } -cTimer *cSearchTimerThread::GetTimer(cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly) +const cTimer *cSearchTimerThread::GetTimer(const cTimers* vdrtimers, cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly) { - cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true); if (!channel) return NULL; @@ -129,7 +138,7 @@ cTimer *cSearchTimerThread::GetTimer(cSearchExt *searchExt, const cEvent *pEvent tm *tmStartEv = localtime_r(&eStart, &tm_r); - for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) + for (const cTimer *ti = vdrtimers->First(); ti; ti = vdrtimers->Next(ti)) { if (ti->Channel() != channel) continue; @@ -172,7 +181,7 @@ cTimer *cSearchTimerThread::GetTimer(cSearchExt *searchExt, const cEvent *pEvent return NULL; } -bool cSearchTimerThread::TimerWasModified(cTimer* t) +bool cSearchTimerThread::TimerWasModified(const cTimer* t) { if (!t) return false; if (t->HasFlags(tfVps)) return false; // if timer uses VPS we ignore user changes @@ -228,11 +237,18 @@ void cSearchTimerThread::Action(void) while(EITScanner.Active() && m_Active && Running()); LogFile.Log(1,"EPG scan finished"); } +#if VDRVERSNUM > 20300 + // wait if TimersWriteLock is set or waited for + { + LOCK_TIMERS_READ; + } +#else if (Timers.BeingEdited()) { Wait.Wait(1000); continue; } +#endif LogFile.iSysLog("search timer update started"); UserVars.ResetCache(); // reset internal cache of user vars @@ -252,7 +268,15 @@ void cSearchTimerThread::Action(void) searchExt = localSearchExts->Next(searchExt); continue; } - pOutdatedTimers = searchExt->GetTimerList(pOutdatedTimers); + { +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + pOutdatedTimers = searchExt->GetTimerList(vdrtimers, pOutdatedTimers); + } // End of Block should release ReadLock cSearchResults* pSearchResults = searchExt->Run(-1, true); if (!pSearchResults) @@ -274,9 +298,17 @@ void cSearchTimerThread::Action(void) if (!pEvent) continue; - cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true); + { +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true); if (!channel) continue; + } int index = 0; cTimer *timer = new cTimer(pEvent); @@ -303,7 +335,15 @@ void cSearchTimerThread::Action(void) // search for an already existing timer bool bTimesMatchExactly = false; - cTimer *t = GetTimer(searchExt, pEvent, bTimesMatchExactly); +#if VDRVERSNUM > 20300 + const cTimer *t = NULL; + { + LOCK_TIMERS_READ; + t = GetTimer(Timers,searchExt, pEvent, bTimesMatchExactly); + } +#else + const cTimer *t = GetTimer(&Timers,searchExt, pEvent, bTimesMatchExactly); +#endif char* Summary = NULL; uint timerMod = tmNoChange; @@ -494,15 +534,25 @@ void cSearchTimerThread::Action(void) LogFile.Log(1,"removing outdated timers"); for(cTimerObj *tObj = pOutdatedTimers->First(); tObj; tObj = pOutdatedTimers->Next(tObj)) { - cTimer* t = tObj->timer; + const 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 VDRVERSNUM > 20300 + { + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + for(const cTimer* checkT = vdrtimers->First(); checkT; checkT = vdrtimers->Next(checkT)) if (checkT == t) { found = true; break; } +#if VDRVERSNUM > 20300 + } +#endif if (!found) continue; if (TimerWasModified(t)) continue; @@ -606,7 +656,7 @@ bool cSearchTimerThread::NeedUpdate() return (m_lastUpdate <= LastModifiedTime(AddDirectory(CONFIGDIR, ".epgsearchupdate")) || updateForced>0); } -char* cSearchTimerThread::SummaryExtended(cSearchExt* searchExt, cTimer* Timer, const cEvent* pEvent) +char* cSearchTimerThread::SummaryExtended(cSearchExt* searchExt, const cTimer* Timer, const cEvent* pEvent) { bool UseVPS = searchExt->useVPS && pEvent->Vps() && Setup.UseVps; time_t eStart; @@ -669,6 +719,7 @@ bool cSearchTimerThread::AddModTimer(cTimer* Timer, int index, cSearchExt* searc time_t start = eStart - (searchExt->MarginStart * 60); time_t stop = eStop + (searchExt->MarginStop * 60); int Flags = Timer->Flags(); + LogFile.Log(1, "AddModTimer"); //JF if (searchExt->useVPS && pEvent->Vps() && Setup.UseVps) { start = pEvent->Vps(); @@ -696,7 +747,11 @@ bool cSearchTimerThread::AddModTimer(cTimer* Timer, int index, cSearchExt* searc } else tmpSummary = SummaryExtended(searchExt, Timer, pEvent); - +#if VDRVERSNUM > 20300 + if (*Setup.SVDRPDefaultHost) + Timer->SetRemote(Setup.SVDRPDefaultHost); + else { +#endif if (index==0) msprintf(&cmdbuf, "NEWT %d:%d:%s:%s:%s:%d:%d:%s:%s", Flags, @@ -723,6 +778,13 @@ bool cSearchTimerThread::AddModTimer(cTimer* Timer, int index, cSearchExt* searc if (!SendViaSVDRP(cmdbuf)) return false; + LogFile.Log(1, "AddModTimer SVDRP done"); //JF +#if VDRVERSNUM > 20300 + } + if (!HandleRemoteModifications(Timer,NULL)) + return false; + LogFile.Log(1, "AddModTimer HandleRemoteModifications done"); //JF +#endif if (gl_timerStatusMonitor) gl_timerStatusMonitor->SetConflictCheckAdvised(); @@ -745,7 +807,7 @@ bool cSearchTimerThread::AddModTimer(cTimer* Timer, int index, cSearchExt* searc return true; } -void cSearchTimerThread::RemoveTimer(cTimer* t, const cEvent* e) +void cSearchTimerThread::RemoveTimer(const cTimer* t, const cEvent* e) { if (!t) return; if (EPGSearchConfig.sendMailOnSearchtimers) @@ -773,9 +835,15 @@ void cSearchTimerThread::DelRecording(int index) void cSearchTimerThread::CheckExpiredRecs() { LogFile.Log(1, "check for expired recordings started"); +#if VDRVERSNUM > 20300 + LOCK_RECORDINGS_WRITE; + cRecordings *vdrrecordings = Recordings; +#else cThreadLock RecordingsLock(&Recordings); + cRecordings *vdrrecordings = &Recordings; +#endif cList<cRecordingObj> DelRecordings; - for (cRecording *recording = Recordings.First(); recording && m_Active; recording = Recordings.Next(recording)) + for (cRecording *recording = vdrrecordings->First(); recording && m_Active; recording = vdrrecordings->Next(recording)) { #if APIVERSNUM < 10721 LogFile.Log(3, "check recording %s from %s for expiration", recording->Name(), DAYDATETIME(recording->start)); @@ -829,7 +897,7 @@ void cSearchTimerThread::CheckExpiredRecs() { cRecording* recording = recordingObj->recording; cSearchExt* search = recordingObj->search; - if (search->recordingsKeep > 0 && search->recordingsKeep >= search->GetCountRecordings()) + if (search->recordingsKeep > 0 && search->recordingsKeep >= search->GetCountRecordings(vdrrecordings)) { #if APIVERSNUM < 10721 LogFile.Log(1, "recording '%s' from %s expired, but will be kept, search timer %s", recording->Name(), DAYDATETIME(recording->start), recordingObj->search->search); @@ -849,7 +917,7 @@ void cSearchTimerThread::CheckExpiredRecs() if (!recording->Delete()) LogFile.Log(1, "error deleting recording!"); else - ::Recordings.DelByName(recording->FileName()); + vdrrecordings->DelByName(recording->FileName()); } else LogFile.Log(1, "recording already in use by a timer!"); @@ -895,15 +963,22 @@ void cSearchTimerThread::ModifyManualTimer(const cEvent* event, const cTimer* ti free(cmdbuf); } -void cSearchTimerThread::CheckManualTimers() +void cSearchTimerThread::CheckManualTimers(void) { LogFile.Log(1, "manual timer check started"); - cSchedulesLock schedulesLock; - const cSchedules *schedules; - schedules = cSchedules::Schedules(schedulesLock); +#if VDRVERSNUM > 20300 + LOCK_TIMERS_WRITE; // to be checked !!! + cTimers *vdrtimers = Timers; + LOCK_SCHEDULES_READ; + const cSchedules *schedules = Schedules; +#else + cTimers *vdrtimers = &Timers; + cSchedulesLock SchedulesLock; + const cSchedules* schedules = cSchedules::Schedules(SchedulesLock); +#endif - for (cTimer *ti = Timers.First(); ti && m_Active; ti = Timers.Next(ti)) + for (const cTimer *ti = vdrtimers->First(); ti && m_Active; ti = vdrtimers->Next(ti)) { if (TriggeredFromSearchTimerID(ti) != -1) continue; // manual timer? @@ -953,7 +1028,7 @@ void cSearchTimerThread::CheckManualTimers() { // collect all events touching the old timer margins cSearchResults eventlist; - for (cEvent *testevent = schedule->Events()->First(); testevent; testevent = schedule->Events()->Next(testevent)) + for (const cEvent *testevent = schedule->Events()->First(); testevent; testevent = schedule->Events()->Next(testevent)) { if (testevent->StartTime() < ti->StopTime() && testevent->EndTime() > ti->StartTime()) eventlist.Add(new cSearchResult(testevent, (const cSearchExt*)NULL)); @@ -1013,15 +1088,19 @@ void cSearchTimerThread::CheckEPGHours() time_t checkTime = time(NULL) + EPGSearchConfig.checkEPGHours * 60 * 60; - cSchedulesLock schedulesLock; - const cSchedules *schedules; - schedules = cSchedules::Schedules(schedulesLock); +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + const cSchedules *schedules = Schedules; +#else + cSchedulesLock SchedulesLock; + const cSchedules* schedules = cSchedules::Schedules(SchedulesLock); +#endif cChannelGroup channelsWithSmallEPG; cChannelGroupItem* channelInGroup = channelGroup->channels.First(); while (channelInGroup) { - cChannel* channel = channelInGroup->channel; + const cChannel* channel = channelInGroup->channel; // get the channels schedule const cSchedule* schedule = schedules->GetSchedule(channel); if (!schedule || !schedule->GetEventAround(checkTime)) @@ -1040,7 +1119,7 @@ void cSearchTimerThread::CheckEPGHours() channelInGroup = channelsWithSmallEPG.channels.First(); while (channelInGroup) { - cChannel* channel = channelInGroup->channel; + const cChannel* channel = channelInGroup->channel; if (channel) sBuffer += " " + string(channel->ShortName(true)); channelInGroup = channelsWithSmallEPG.channels.Next(channelInGroup); diff --git a/searchtimer_thread.h b/searchtimer_thread.h index 91476ac..fe8d6dd 100644 --- a/searchtimer_thread.h +++ b/searchtimer_thread.h @@ -53,15 +53,15 @@ class cSearchTimerThread: public cThread { protected: virtual void Action(void); bool AddModTimer(cTimer* Timer, int, cSearchExt*, const cEvent*, int Prio, int Lifetime, char* Summary = NULL, uint timerMod = tmNoChange); - void RemoveTimer(cTimer* Timer, const cEvent* Event = NULL); + void RemoveTimer(const cTimer* Timer, const cEvent* Event = NULL); void Stop(void); bool NeedUpdate(); - bool TimerWasModified(cTimer* t); + bool TimerWasModified(const cTimer* t); public: static cSearchResults announceList; - static char* SummaryExtended(cSearchExt* searchExt, cTimer* Timer, const cEvent* pEvent); + static char* SummaryExtended(cSearchExt* searchExt, const cTimer* Timer, const cEvent* pEvent); static cSearchTimerThread *m_Instance; - static cTimer* GetTimer(cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly); + static const cTimer* GetTimer(const cTimers* vdrtimers, cSearchExt *searchExt, const cEvent *pEvent, bool& bTimesMatchExactly); static bool justRunning; cSearchTimerThread(cPluginEpgsearch* thePlugin); @@ -70,7 +70,7 @@ class cSearchTimerThread: public cThread { static void Exit(void); void CheckExpiredRecs(); void DelRecording(int index); - void CheckManualTimers(); + void CheckManualTimers(void); void ModifyManualTimer(const cEvent* event, const cTimer* timer, int bstart, int bstop); void CheckEPGHours(); }; @@ -145,13 +145,25 @@ std::list<std::string> cEpgsearchServiceHandler::TranslateResults(cSearchResults eTimerMatch timerMatch; bool hasTimer = false; - if (Timers.GetMatch(pEvent, &timerMatch)) +#if VDRVERSNUM > 20300 + LOCK_TIMERS_READ; + const cTimers *vdrtimers = Timers; +#else + cTimers *vdrtimers = &Timers; +#endif + if (vdrtimers->GetMatch(pEvent, &timerMatch)) hasTimer = (timerMatch == tmFull); if (!result->search->useAsSearchTimer) result->needsTimer = false; - cChannel *channel = Channels.GetByChannelID(pEvent->ChannelID(), true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(pEvent->ChannelID(), true, true); int timerMode = hasTimer?1:(result->needsTimer?2:0); std::string title = pEvent->Title()?ReplaceAll(pEvent->Title(), "|", "!^pipe!^"):""; diff --git a/status_thread.c b/status_thread.c new file mode 100644 index 0000000..f9c7a3e --- /dev/null +++ b/status_thread.c @@ -0,0 +1,253 @@ +/* -*- 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 <string> +#include <list> +#ifdef __FreeBSD__ +#include <netinet/in.h> +#endif +#include "timer_thread.h" +#include "epgsearchcfg.h" +#include "epgsearchtools.h" +#include "services.h" +#include "svdrpclient.h" +#include "timerstatus.h" +#include "recstatus.h" +#include "recdone.h" +#include "conflictcheck_thread.h" +#include "status_thread.h" +#include <math.h> + +#include <vdr/tools.h> +#include <vdr/plugin.h> + +#if VDRVERSNUM > 20300 + +#define ALLOWED_BREAK_INSECS 2 + +extern int updateForced; + +cStatusThread *cStatusThread::m_Instance = NULL; +StatusThreadStatus cStatusThread::m_Status = StatusThreadReady; +int gl_StatusProgged=0; // Flag that indicates, when programming is finished + +cStatusThread::cStatusThread() +: cThread("EPGSearch: recstatus") +{ + m_Active = false; +} + +cStatusThread::~cStatusThread() { + if (m_Active) + Stop(); + cStatusThread::m_Instance = NULL; +} + +void cStatusThread::Init(const cDevice *Device, const char *Name, const char *Filename, bool On) { + if (m_Instance == NULL) { + m_Instance = new cStatusThread; + } + else { + if (m_Instance->m_Active) { + LogFile.eSysLog("Epgsearch recstatus_thread called too fast"); //should stack + return; + } + } + m_Instance->m_device=Device; + m_Instance->m_name=Name; + m_Instance->m_filename=Filename; + m_Instance->m_on=On; + m_Instance->Start(); +} + +void cStatusThread::Exit(void) { + if (m_Instance != NULL) { + m_Instance->Stop(); + DELETENULL(m_Instance); + } + +} + +void cStatusThread::Stop(void) { + m_Active = false; + Cancel(3); +} + +void cStatusThread::Action(void) +{ + m_Active = true; + time_t now = time(NULL); + // insert new timers currently recording in TimersRecording + if (m_on && m_name) + { + if (EPGSearchConfig.checkTimerConflOnRecording) + cConflictCheckThread::Init((cPluginEpgsearch*)cPluginManager::GetPlugin("epgsearch"), true); + + LOCK_TIMERS_READ; + + for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti)) + if (ti->Recording()) + { + // check if this is a new entry + cRecDoneTimerObj *tiRFound = NULL; + for (cRecDoneTimerObj *tiR = gl_recStatusMonitor->TimersRecording.First(); tiR; tiR = gl_recStatusMonitor->TimersRecording.Next(tiR)) + if (tiR->timer == ti) + { + tiRFound = tiR; + break; + } + + if (tiRFound) // already handled, perhaps a resume + { + if (tiRFound->lastBreak > 0 && now - tiRFound->lastBreak <= ALLOWED_BREAK_INSECS) + { + LogFile.Log(1,"accepting resume of '%s' on device %d", m_name, m_device->CardIndex()); + tiRFound->lastBreak = 0; + } + continue; + } + + cRecDoneTimerObj* timerObj = new cRecDoneTimerObj(ti, m_device->DeviceNumber()); + gl_recStatusMonitor->TimersRecording.Add(timerObj); + + cSearchExt* search = TriggeredFromSearchTimer(ti); + if (!search || (search->avoidRepeats == 0 && search->delMode == 0)) // ignore if not avoid repeats and no auto-delete + continue; + + bool vpsUsed = ti->HasFlags(tfVps) && ti->Event() && ti->Event()->Vps(); + LogFile.Log(1,"recording started '%s' on device %d (search timer '%s'); VPS used: %s", m_name, m_device->CardIndex(), search->search, vpsUsed ? "Yes": "No"); + const cEvent* event = ti->Event(); + if (!event) + { + event = GetEvent(ti); + if (event) + LogFile.Log(3,"timer had no event: assigning '%s'", event->Title()); + } + if (!event) + { + LogFile.Log(1,"no event for timer found! will be ignored in done list"); + continue; + } + time_t now = time(NULL); + if (vpsUsed || now < ti->StartTime() + 60) // allow a delay of one minute + { + timerObj->recDone = new cRecDone(ti, event, search); + return; + } + else + LogFile.Log(1,"recording started too late! will be ignored"); + } + } + + if (!m_on) + { + cMutexLock RecsDoneLock(&RecsDone); + // remove timers that finished recording from TimersRecording + // incomplete recordings are kept for a while, perhaps they will be resumed + cRecDoneTimerObj *tiR = gl_recStatusMonitor->TimersRecording.First(); + while(tiR) + { + // check if timer still exists + bool found = false; + LOCK_TIMERS_READ; + for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti)) + if (ti == tiR->timer) + { + found = true; + break; + } + if (found && !tiR->timer->Recording()) + { + if (tiR->recDone) + { + cSearchExt* search = SearchExts.GetSearchFromID(tiR->recDone->searchID); + if (!search) return; + + // check if recording has ended before timer end + + bool complete = true; + LOCK_RECORDINGS_READ; + const cRecording *pRecording = Recordings->GetByName(m_filename); + long timerLengthSecs = tiR->timer->StopTime()-tiR->timer->StartTime(); + int recFraction = 100; + if (pRecording && timerLengthSecs) + { + int recLen = gl_recStatusMonitor->RecLengthInSecs(pRecording); + recFraction = double(recLen) * 100 / timerLengthSecs; + } + bool vpsUsed = tiR->timer->HasFlags(tfVps) && tiR->timer->Event() && tiR->timer->Event()->Vps(); + if ((!vpsUsed && now < tiR->timer->StopTime()) || recFraction < (vpsUsed ? 90: 98)) // assure timer has reached its end or at least 98% were recorded + { + complete = false; + LogFile.Log(1,"finished: '%s' (not complete! - recorded only %d%%); search timer: '%s'; VPS used: %s", tiR->timer->File(), recFraction, search->search, vpsUsed ? "Yes": "No"); + } + else + { + LogFile.Log(1,"finished: '%s'; search timer: '%s'; VPS used: %s", tiR->timer->File(), search->search, vpsUsed ? "Yes": "No"); + if (recFraction < 100) + LogFile.Log(2,"recorded %d%%'", recFraction); + } + if (complete) + { + RecsDone.Add(tiR->recDone); + LogFile.Log(1,"added rec done for '%s~%s';%s", tiR->recDone->title?tiR->recDone->title:"unknown title", + tiR->recDone->shortText?tiR->recDone->shortText:"unknown subtitle", + search->search); + RecsDone.Save(); + tiR->recDone = NULL; // prevent deletion + tiR->lastBreak = 0; + + // check for search timers to delete automatically + SearchExts.CheckForAutoDelete(search); + + // trigger a search timer update (skip running events) + search->skipRunningEvents = true; + updateForced = 1; + } + else if (tiR->lastBreak == 0) // store first break + tiR->lastBreak = now; + } + if (tiR->lastBreak == 0 || (now - tiR->lastBreak) > ALLOWED_BREAK_INSECS) + { // remove finished recordings or those with an unallowed break + if (tiR->recDone) delete tiR->recDone; // clean up + cRecDoneTimerObj *tiRNext = gl_recStatusMonitor->TimersRecording.Next(tiR); + gl_recStatusMonitor->TimersRecording.Del(tiR); + tiR = tiRNext; + continue; + } + break; + } + if (!found) + { + if (tiR->recDone) delete tiR->recDone; // clean up + cRecDoneTimerObj *tiRNext = gl_recStatusMonitor->TimersRecording.Next(tiR); + gl_recStatusMonitor->TimersRecording.Del(tiR); + tiR = tiRNext; + continue; + } + tiR = gl_recStatusMonitor->TimersRecording.Next(tiR); + } + } + m_Active = false; +} +#endif diff --git a/status_thread.h b/status_thread.h new file mode 100644 index 0000000..e2bdb6e --- /dev/null +++ b/status_thread.h @@ -0,0 +1,65 @@ +/* -*- 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 +*/ + +#ifndef VDR_STATUS_THREAD_H +#define VDR_STATUS_THREAD_H + +#include <vdr/thread.h> +#include <vdr/status.h> +#include "epgsearchext.h" +#include "recdone.h" +#include "epgsearchtools.h" +#include "log.h" + +extern int gl_StatusProgged; + +typedef enum +{ + StatusThreadReady, + StatusThreadWorking, + StatusThreadError, + StatusThreadDone +} StatusThreadStatus; + +class cStatusThread: public cThread { +private: + static cStatusThread *m_Instance; + const cDevice * m_device; + const char * m_name; + const char * m_filename; + bool m_on; + static StatusThreadStatus m_Status; +protected: + virtual void Action(void); + void Stop(void); +public: + bool m_Active; + StatusThreadStatus GetStatus() { return cStatusThread::m_Status; } + void SetStatus(StatusThreadStatus Status) { LogFile.eSysLog("%d", int(Status)); cStatusThread::m_Status = Status; } + cStatusThread(); + virtual ~cStatusThread(); + static void Init(const cDevice *Device, const char *Name, const char *Filename, bool On); + void Exit(void); +}; + +#endif diff --git a/switchtimer.c b/switchtimer.c index 20c017b..d145c7a 100644 --- a/switchtimer.c +++ b/switchtimer.c @@ -114,8 +114,13 @@ const cEvent* cSwitchTimer::Event() const cEvent* event = NULL; if (startTime > now) { - cSchedulesLock schedulesLock; - const cSchedules* schedules = cSchedules::Schedules(schedulesLock); +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + const cSchedules *schedules = Schedules; +#else + cSchedulesLock SchedulesLock; + const cSchedules* schedules = cSchedules::Schedules(SchedulesLock); +#endif if (!schedules) return NULL; const cSchedule *Schedule = schedules->GetSchedule(channelID); if (Schedule) @@ -136,7 +141,13 @@ cString cSwitchTimer::ToText(bool& ignore) ignore = true; return NULL; } - cChannel *channel = Channels.GetByChannelID(channelID, true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true); if (!channel) return NULL; cString buffer = cString::sprintf("%s:%u:%ld:%d:%d:%d", CHANNELSTRING(channel), eventID, diff --git a/switchtimer_thread.c b/switchtimer_thread.c index b027b4b..3b2ce99 100644 --- a/switchtimer_thread.c +++ b/switchtimer_thread.c @@ -81,14 +81,20 @@ void cSwitchTimerThread::Action(void) if (now >= nextUpdate) { LogFile.Log(3,"locking switch timers"); - SwitchTimers.Lock(); + SwitchTimers.cMutex::Lock(); LogFile.Log(3,"switch timer check started"); cSwitchTimer* switchTimer = SwitchTimers.First(); while (switchTimer && m_Active && Running()) { if (switchTimer->startTime - now < switchTimer->switchMinsBefore*60 + MSG_DELAY + 1) { - cChannel *channel = Channels.GetByChannelID(switchTimer->channelID, true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(switchTimer->channelID, true, true); bool doSwitch = (switchTimer->mode == 0); bool doAsk = (switchTimer->mode == 2); bool doUnmute = switchTimer->unmute; diff --git a/templatefile.c b/templatefile.c index 44ade92..fdce3bf 100644 --- a/templatefile.c +++ b/templatefile.c @@ -210,6 +210,12 @@ bool cTemplFile::Parse(const char *Name, const char *Value) void cTemplFile::PrepareDefaultTemplates() { char channelnr[20] = ""; +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif sprintf(channelnr, "%%chnr%%:%d|", CHNUMWIDTH); bool text2skin = !(strcmp(Setup.OSDSkin, "soppalusikka") == 0 || diff --git a/timer_thread.c b/timer_thread.c index 306d10a..e4c8be1 100644 --- a/timer_thread.c +++ b/timer_thread.c @@ -89,11 +89,17 @@ void cTimerThread::Action(void) m_Active=false; break; } +#if VDRVERSNUM > 20300 + { + LOCK_TIMERS_READ; + } +#else if (Timers.BeingEdited()) { sleepSec(1); continue; } +#endif bool bSuccess = SendViaSVDRP(m_cmd); if (!bSuccess) { diff --git a/timerdone.c b/timerdone.c index b00679c..06d2b23 100644 --- a/timerdone.c +++ b/timerdone.c @@ -126,7 +126,13 @@ bool cTimerDone::Parse(const char *s) cString cTimerDone::ToText(void) const { - cChannel *channel = Channels.GetByChannelID(channelID, true, true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(channelID, true, true); string info = string(DAYDATETIME(start)) + " - " + string(channel?channel->Name():""); cString buffer = cString::sprintf("%s:%ld:%ld:%d:%s:%s:%s", @@ -147,10 +153,15 @@ bool cTimerDone::Save(FILE *f) const cEvent* cTimerDone::GetEvent() const { - cSchedulesLock schedulesLock; - const cSchedules* Schedules = cSchedules::Schedules(schedulesLock); - if (!Schedules) return NULL; - const cSchedule *Schedule = Schedules->GetSchedule(channelID); +#if VDRVERSNUM > 20300 + LOCK_SCHEDULES_READ; + const cSchedules *schedules = Schedules; +#else + cSchedulesLock SchedulesLock; + const cSchedules* schedules = cSchedules::Schedules(SchedulesLock); +#endif + if (!schedules) return NULL; + const cSchedule *Schedule = schedules->GetSchedule(channelID); if (!Schedule) return NULL; const cEvent* Event = Schedule->GetEventAround(start + (stop - start)/2); return Event; @@ -176,7 +176,13 @@ public: string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; - cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true); if (!channel) return ""; string res(channel->GetChannelID().ToString()); @@ -415,7 +421,13 @@ public: string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; - cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true); string res = channel?channel->ShortName(true):""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } @@ -427,7 +439,13 @@ public: string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; - cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true); string res = channel?channel->Name():""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } @@ -439,7 +457,13 @@ class cChannelDataVar : public cInternalVar { string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; - cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true); return channel?CHANNELSTRING(channel):""; } }; @@ -451,9 +475,15 @@ public: { if (!e) return ""; ostringstream os; - cChannel *channel = Channels.GetByChannelID(e->ChannelID(), true); +#if VDRVERSNUM > 20300 + LOCK_CHANNELS_READ; + const cChannels *vdrchannels = Channels; +#else + cChannels *vdrchannels = &Channels; +#endif + const cChannel *channel = vdrchannels->GetByChannelID(e->ChannelID(), true); while(channel && !channel->GroupSep()) - channel = Channels.Prev(channel); + channel = vdrchannels->Prev(channel); if (!channel || !channel->Name()) return ""; string grpName = channel->Name(); if (escapeStrings) return "'" + EscapeString(grpName) + "'"; else return grpName; |