mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	Spawned timers that don't use VPS now automatically adjust their start/stop times to changes in the respective event's times
This commit is contained in:
		
							
								
								
									
										4
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								HISTORY
									
									
									
									
									
								
							| @@ -9578,7 +9578,7 @@ Video Disk Recorder Revision History | ||||
|   given (reported by Manuel Reimer). | ||||
| - Fixed handling $(PKG_CONFIG) in newplugin (thanks to Winfried K<>hler). | ||||
|  | ||||
| 2021-04-04: | ||||
| 2021-04-05: | ||||
|  | ||||
| - Fixed strreplace() to handle NULL strings (reported by J<>rgen Schneider). | ||||
| - Somewhere down the road the 'x' bit of Doxyfile.filter got lost, so the | ||||
| @@ -9633,3 +9633,5 @@ Video Disk Recorder Revision History | ||||
|     is changed while the recording is already going on. | ||||
| - The margins for timer recordings are now always limited to the duration of the | ||||
|   previous and next event. | ||||
| - Spawned timers that don't use VPS now automatically adjust their start/stop times | ||||
|   to changes in the respective event's times. | ||||
|   | ||||
							
								
								
									
										3
									
								
								MANUAL
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								MANUAL
									
									
									
									
									
								
							| @@ -556,6 +556,9 @@ The following rules apply to pattern timers: | ||||
| - Recording is done according to the event's begin/end times, either | ||||
|   by adding the start/stop margins (for non-VPS timers) or by using the | ||||
|   event's running status (for VPS timers). | ||||
| - If the times of the event change, a non-VPS pattern timer automatically adjusts | ||||
|   itself to the new times. This also happens if the start/stop margins are changed | ||||
|   in the setup. | ||||
| - The recording of a pattern timer is stored under the given file name, just like | ||||
|   regular timers do. In addition to the "TITLE" and "EPISODE" macros the file | ||||
|   name of a pattern timer can also use "{<}" and "{>}" to reference the part of the | ||||
|   | ||||
							
								
								
									
										63
									
								
								timers.c
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								timers.c
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | ||||
|  * See the main source file 'vdr.c' for copyright information and | ||||
|  * how to reach the author. | ||||
|  * | ||||
|  * $Id: timers.c 5.6 2021/04/04 13:38:13 kls Exp $ | ||||
|  * $Id: timers.c 5.7 2021/04/06 08:48:35 kls Exp $ | ||||
|  */ | ||||
|  | ||||
| #include "timers.h" | ||||
| @@ -27,7 +27,7 @@ cTimer::cTimer(bool Instant, bool Pause, const cChannel *Channel) | ||||
| { | ||||
|   id = 0; | ||||
|   startTime = stopTime = 0; | ||||
|   scheduleState = -1; | ||||
|   scheduleStateSet = scheduleStateSpawn = scheduleStateAdjust = -1; | ||||
|   deferred = 0; | ||||
|   pending = inVpsMargin = false; | ||||
|   flags = tfNone; | ||||
| @@ -176,7 +176,7 @@ cTimer::cTimer(const cEvent *Event, const char *FileName, const cTimer *PatternT | ||||
| { | ||||
|   id = 0; | ||||
|   startTime = stopTime = 0; | ||||
|   scheduleState = -1; | ||||
|   scheduleStateSet = scheduleStateSpawn = scheduleStateAdjust = -1; | ||||
|   deferred = 0; | ||||
|   pending = inVpsMargin = false; | ||||
|   flags = tfActive; | ||||
| @@ -242,7 +242,7 @@ cTimer& cTimer::operator= (const cTimer &Timer) | ||||
|      id           = Timer.id; | ||||
|      startTime    = Timer.startTime; | ||||
|      stopTime     = Timer.stopTime; | ||||
|      scheduleState = -1; | ||||
|      scheduleStateSet = scheduleStateSpawn = scheduleStateAdjust = -1; | ||||
|      deferred     = 0; | ||||
|      pending      = Timer.pending; | ||||
|      inVpsMargin  = Timer.inVpsMargin; | ||||
| @@ -724,7 +724,7 @@ bool cTimer::SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers) | ||||
|   bool TimersSpawned = false; | ||||
|   const cSchedule *Schedule = Schedules->GetSchedule(Channel()); | ||||
|   if (Schedule && Schedule->Events()->First()) { | ||||
|      if (Schedule->Modified(scheduleState)) { | ||||
|      if (Schedule->Modified(scheduleStateSpawn)) { | ||||
|         time_t Now = time(NULL); | ||||
|         for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { | ||||
|             if (Matches(e) != tmNone) { | ||||
| @@ -757,6 +757,41 @@ bool cTimer::SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers) | ||||
|   return TimersSpawned; | ||||
| } | ||||
|  | ||||
| bool cTimer::AdjustSpawnedTimer(void) | ||||
| { | ||||
|   if (Event()) { | ||||
|      if (const cSchedule *Schedule = Event()->Schedule()) { // events may be deleted from their schedule in cSchedule::DropOutdated()! | ||||
|         if (Schedule->Modified(scheduleStateAdjust)) { | ||||
|            // Adjust the timer to shifted start/stop times of the event if necessary: | ||||
|            time_t tstart = Event()->StartTime(); | ||||
|            time_t tstop = Event()->EndTime(); | ||||
|            int MarginStart = 0; | ||||
|            int MarginStop  = 0; | ||||
|            CalcMargins(MarginStart, MarginStop, Event()); | ||||
|            tstart -= MarginStart; | ||||
|            tstop  += MarginStop; | ||||
|            // Event start/end times are given in "seconds since the epoch". Some broadcasters use values | ||||
|            // that result in full minutes (with zero seconds), while others use any values. VDR's timers | ||||
|            // use times given in full minutes, truncating any seconds. Thus we only react if the start/stop | ||||
|            // times of the timer are off by at least one minute: | ||||
|            if (abs(StartTime() - tstart) >= 60 || abs(StopTime() - tstop) >= 60) { | ||||
|               cTimer OldTimer = *this; | ||||
|               struct tm tm_r; | ||||
|               struct tm *time = localtime_r(&tstart, &tm_r); | ||||
|               SetDay(cTimer::SetTime(tstart, 0)); | ||||
|               SetStart(time->tm_hour * 100 + time->tm_min); | ||||
|               time = localtime_r(&tstop, &tm_r); | ||||
|               SetStop(time->tm_hour * 100 + time->tm_min); | ||||
|               Matches(); | ||||
|               isyslog("timer %s times changed to %s-%s", *ToDescr(), *TimeString(tstart), *TimeString(tstop)); | ||||
|               return true; | ||||
|               } | ||||
|            } | ||||
|         } | ||||
|      } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| void cTimer::TriggerRespawn(void) | ||||
| { | ||||
|   if (HasFlags(tfSpawned) || IsPatternTimer()) { | ||||
| @@ -777,7 +812,7 @@ bool cTimer::SetEventFromSchedule(const cSchedules *Schedules) | ||||
|      return SetEvent(NULL); | ||||
|   const cSchedule *Schedule = Schedules->GetSchedule(Channel()); | ||||
|   if (Schedule && Schedule->Events()->First()) { | ||||
|      if (Schedule->Modified(scheduleState)) { | ||||
|      if (Schedule->Modified(scheduleStateSet)) { | ||||
|         const cEvent *Event = NULL; | ||||
|         if (HasFlags(tfVps) && Schedule->Events()->First()->Vps()) { | ||||
|            // VPS timers only match if their start time exactly matches the event's VPS time: | ||||
| @@ -828,11 +863,11 @@ bool cTimer::SetEvent(const cEvent *Event) | ||||
|      if (Event) { | ||||
|         isyslog("timer %s set to event %s", *ToDescr(), *Event->ToDescr()); | ||||
|         Event->IncNumTimers(); | ||||
|         Event->Schedule()->Modified(scheduleState); // to get the current state | ||||
|         Event->Schedule()->Modified(scheduleStateSet); // to get the current state | ||||
|         } | ||||
|      else { | ||||
|         isyslog("timer %s set to no event", *ToDescr()); | ||||
|         scheduleState = -1; | ||||
|         scheduleStateSet = scheduleStateSpawn = scheduleStateAdjust = -1; | ||||
|         } | ||||
|      event = Event; | ||||
|      return true; | ||||
| @@ -1132,6 +1167,18 @@ bool cTimers::SpawnPatternTimers(const cSchedules *Schedules) | ||||
|   return TimersModified; | ||||
| } | ||||
|  | ||||
| bool cTimers::AdjustSpawnedTimers(void) | ||||
| { | ||||
|   bool TimersModified = false; | ||||
|   for (cTimer *ti = First(); ti; ti = Next(ti)) { | ||||
|       if (ti->Local()) { | ||||
|          if (ti->HasFlags(tfSpawned) && !ti->HasFlags(tfVps)) | ||||
|             TimersModified |= ti->AdjustSpawnedTimer(); | ||||
|          } | ||||
|       } | ||||
|   return TimersModified; | ||||
| } | ||||
|  | ||||
| bool cTimers::DeleteExpired(void) | ||||
| { | ||||
|   if (time(NULL) - lastDeleteExpired < 30) | ||||
|   | ||||
							
								
								
									
										8
									
								
								timers.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								timers.h
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | ||||
|  * See the main source file 'vdr.c' for copyright information and | ||||
|  * how to reach the author. | ||||
|  * | ||||
|  * $Id: timers.h 5.3 2021/04/04 13:38:13 kls Exp $ | ||||
|  * $Id: timers.h 5.4 2021/04/06 08:48:35 kls Exp $ | ||||
|  */ | ||||
|  | ||||
| #ifndef __TIMERS_H | ||||
| @@ -33,7 +33,9 @@ class cTimer : public cListObject { | ||||
| private: | ||||
|   int id; | ||||
|   mutable time_t startTime, stopTime; | ||||
|   int scheduleState; | ||||
|   int scheduleStateSet; | ||||
|   int scheduleStateSpawn; | ||||
|   int scheduleStateAdjust; | ||||
|   mutable time_t deferred; ///< Matches(time_t, ...) will return false if the current time is before this value | ||||
|   bool pending, inVpsMargin; | ||||
|   uint flags; | ||||
| @@ -99,6 +101,7 @@ public: | ||||
|   void SetId(int Id); | ||||
|   void SpawnPatternTimer(const cEvent *Event, cTimers *Timers); | ||||
|   bool SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers); | ||||
|   bool AdjustSpawnedTimer(void); | ||||
|   void TriggerRespawn(void); | ||||
|   bool SetEventFromSchedule(const cSchedules *Schedules); | ||||
|   bool SetEvent(const cEvent *Event); | ||||
| @@ -196,6 +199,7 @@ public: | ||||
|   const cTimer *UsesChannel(const cChannel *Channel) const; | ||||
|   bool SetEvents(const cSchedules *Schedules); | ||||
|   bool SpawnPatternTimers(const cSchedules *Schedules); | ||||
|   bool AdjustSpawnedTimers(void); | ||||
|   bool DeleteExpired(void); | ||||
|   void Add(cTimer *Timer, cTimer *After = NULL); | ||||
|   void Ins(cTimer *Timer, cTimer *Before = NULL); | ||||
|   | ||||
							
								
								
									
										6
									
								
								vdr.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								vdr.c
									
									
									
									
									
								
							| @@ -22,7 +22,7 @@ | ||||
|  * | ||||
|  * The project's page is at http://www.tvdr.de | ||||
|  * | ||||
|  * $Id: vdr.c 5.1 2020/12/26 15:49:01 kls Exp $ | ||||
|  * $Id: vdr.c 5.2 2021/04/06 08:48:35 kls Exp $ | ||||
|  */ | ||||
|  | ||||
| #include <getopt.h> | ||||
| @@ -1109,8 +1109,8 @@ int main(int argc, char *argv[]) | ||||
|                Timers->SetSyncStateKey(StateKeySVDRPRemoteTimersPoll); // setting events shall not trigger a remote timer poll... | ||||
|                if (Timers->SetEvents(Schedules)) | ||||
|                   TimersModified = true; | ||||
|                if (Timers->SpawnPatternTimers(Schedules)) { | ||||
|                   StateKeySVDRPRemoteTimersPoll.Reset(); // ...but spawning new timers must! | ||||
|                if (Timers->SpawnPatternTimers(Schedules) | Timers->AdjustSpawnedTimers()) { // this really is '|', not '||'! | ||||
|                   StateKeySVDRPRemoteTimersPoll.Reset(); // ...but spawning new timers or adjusting spawned timers must! | ||||
|                   TimersModified = true; | ||||
|                   } | ||||
|                SchedulesStateKey.Remove(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user