diff --git a/CONTRIBUTORS b/CONTRIBUTORS index c468a486..292b8eff 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -381,6 +381,7 @@ Mirko D for reporting a bug when a timer records over midnight of a day that had a change in Daylight Saving Time for suggesting to avoid the external 'find' command to scan the video directory + for reporting a problem with inconsistent channel and timer lists Michael Rakowski for translating OSD texts to the Polish language diff --git a/HISTORY b/HISTORY index 6f802d9c..fb0e50bd 100644 --- a/HISTORY +++ b/HISTORY @@ -3093,3 +3093,6 @@ Video Disk Recorder Revision History cCondVar to make sure any sleepers will wake up (suggested by Werner Fink). Also using pthread_cond_broadcast() instead of pthread_cond_signal() in cCondWait, in case there is more than one sleeper. +- Making sure that timers and channels are only saved together, in a consistent + manner (thanks to Mirko Dölle for reporting a problem with inconsistent + channel and timer lists). diff --git a/menu.c b/menu.c index 18c2d5bf..b193292b 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.315 2004/10/30 15:37:16 kls Exp $ + * $Id: menu.c 1.316 2004/10/31 10:09:16 kls Exp $ */ #include "menu.h" @@ -639,7 +639,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key) if (addIfConfirmed) Timers.Add(timer); timer->Matches(); - Timers.Save(); + Timers.SetModified(); isyslog("timer %d %s (%s)", timer->Index() + 1, addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive"); addIfConfirmed = false; } @@ -747,7 +747,7 @@ eOSState cMenuTimers::OnOff(void) isyslog("timer %d first day set to %s", timer->Index() + 1, timer->PrintFirstDay()); else isyslog("timer %d %sactivated", timer->Index() + 1, timer->HasFlags(tfActive) ? "" : "de"); - Timers.Save(); + Timers.SetModified(); } return osContinue; } @@ -784,7 +784,7 @@ eOSState cMenuTimers::Delete(void) int Index = ti->Index(); Timers.Del(ti); cOsdMenu::Del(Current()); - Timers.Save(); + Timers.SetModified(); Display(); isyslog("timer %d deleted", Index + 1); } @@ -796,7 +796,7 @@ void cMenuTimers::Move(int From, int To) { Timers.Move(From, To); cOsdMenu::Move(From, To); - Timers.Save(); + Timers.SetModified(); Display(); isyslog("timer %d moved to %d", From + 1, To + 1); } @@ -1556,7 +1556,7 @@ eOSState cMenuRecordings::Delete(void) Timers.Del(timer); isyslog("timer %d deleted", Index + 1); } - Timers.Save(); + Timers.SetModified(); } } else @@ -2734,7 +2734,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) if (!timer) { timer = new cTimer(true, Pause); Timers.Add(timer); - Timers.Save(); + Timers.SetModified(); asprintf(&instantId, cDevice::NumDevices() > 1 ? "%s - %d" : "%s", timer->Channel()->Name(), device->CardIndex() + 1); } timer->SetPending(true); @@ -2763,7 +2763,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) } else { Timers.Del(timer); - Timers.Save(); + Timers.SetModified(); if (!cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo() cReplayControl::SetRecording(fileName, Recording.Name()); } @@ -2833,7 +2833,7 @@ void cRecordControl::Stop(bool KeepInstant) if ((IsInstant() && !KeepInstant) || (timer->IsSingleEvent() && timer->StopTime() <= time(NULL))) { isyslog("deleting timer %d", timer->Index() + 1); Timers.Del(timer); - Timers.Save(); + Timers.SetModified(); } timer = NULL; cStatus::MsgRecording(device, NULL); diff --git a/recording.c b/recording.c index e33e2315..5cb06571 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 1.89 2004/07/17 11:22:29 kls Exp $ + * $Id: recording.c 1.90 2004/10/31 10:09:36 kls Exp $ */ #include "recording.h" @@ -335,7 +335,7 @@ cRecording::cRecording(cTimer *Timer, const char *Title, const char *Subtitle, c name = strreplace(name, TIMERMACRO_EPISODE, Subtitle); if (Timer->IsSingleEvent()) { Timer->SetFile(name); // this was an instant recording, so let's set the actual data - Timers.Save(); + Timers.SetModified(); } } else if (Timer->IsSingleEvent() || !Setup.UseSubtitle) diff --git a/svdrp.c b/svdrp.c index 788b1682..eec6869c 100644 --- a/svdrp.c +++ b/svdrp.c @@ -10,7 +10,7 @@ * and interact with the Video Disk Recorder - or write a full featured * graphical interface that sits on top of an SVDRP connection. * - * $Id: svdrp.c 1.64 2004/10/17 10:28:47 kls Exp $ + * $Id: svdrp.c 1.65 2004/10/31 10:09:53 kls Exp $ */ #include "svdrp.h" @@ -529,7 +529,7 @@ void cSVDRP::CmdDELT(const char *Option) if (timer) { if (!timer->Recording()) { Timers.Del(timer); - Timers.Save(); + Timers.SetModified(); isyslog("timer %s deleted", Option); Reply(250, "Timer \"%s\" deleted", Option); } @@ -915,7 +915,7 @@ void cSVDRP::CmdMODT(const char *Option) return; } *timer = t; - Timers.Save(); + Timers.SetModified(); isyslog("timer %d modified (%s)", timer->Index() + 1, timer->HasFlags(tfActive) ? "active" : "inactive"); Reply(250, "%d %s", timer->Index() + 1, timer->ToText()); } @@ -973,7 +973,7 @@ void cSVDRP::CmdNEWT(const char *Option) cTimer *t = Timers.GetTimer(timer); if (!t) { Timers.Add(timer); - Timers.Save(); + Timers.SetModified(); isyslog("timer %d added", timer->Index() + 1); Reply(250, "%d %s", timer->Index() + 1, timer->ToText()); return; @@ -1057,7 +1057,7 @@ void cSVDRP::CmdUPDT(const char *Option) Timers.Add(timer); isyslog("timer %d added", timer->Index() + 1); } - Timers.Save(); + Timers.SetModified(); Reply(250, "%d %s", timer->Index() + 1, timer->ToText()); return; } diff --git a/timers.c b/timers.c index 4c4ba213..20391d3a 100644 --- a/timers.c +++ b/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 1.14 2004/10/24 14:56:55 kls Exp $ + * $Id: timers.c 1.15 2004/10/31 10:07:43 kls Exp $ */ #include "timers.h" @@ -458,6 +458,7 @@ cTimers Timers; cTimers::cTimers(void) { + modified = false; beingEdited = 0;; lastSetEvents = 0; } @@ -511,6 +512,18 @@ cTimer *cTimers::GetNextActiveTimer(void) return t0; } +void cTimers::SetModified(void) +{ + modified = true; +} + +bool cTimers::Modified(void) +{ + bool Result = modified; + modified = false; + return Result; +} + void cTimers::SetEvents(void) { if (time(NULL) - lastSetEvents < 5) diff --git a/timers.h b/timers.h index cbc6a92f..03ff4b01 100644 --- a/timers.h +++ b/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 1.8 2004/10/24 14:40:37 kls Exp $ + * $Id: timers.h 1.9 2004/10/31 10:06:54 kls Exp $ */ #ifndef __TIMERS_H @@ -92,6 +92,7 @@ public: class cTimers : public cConfig { private: + bool modified; int beingEdited; time_t lastSetEvents; public: @@ -103,6 +104,10 @@ public: int BeingEdited(void) { return beingEdited; } void IncBeingEdited(void) { beingEdited++; } void DecBeingEdited(void) { if (!--beingEdited) lastSetEvents = 0; } + void SetModified(void); + bool Modified(void); + ///< Returns true if any of the timers have been modified. + ///< Calling this function resets the 'modified' flag to false. void SetEvents(void); }; diff --git a/vdr.c b/vdr.c index 08df727d..d91308f5 100644 --- a/vdr.c +++ b/vdr.c @@ -22,7 +22,7 @@ * * The project's page is at http://www.cadsoft.de/vdr * - * $Id: vdr.c 1.191 2004/10/31 09:35:55 kls Exp $ + * $Id: vdr.c 1.192 2004/10/31 10:17:23 kls Exp $ */ #include @@ -540,11 +540,13 @@ int main(int argc, char *argv[]) dsyslog("max. latency time %d seconds", MaxLatencyTime); } } - // Handle channel modifications: - if (!Channels.BeingEdited()) { + // Handle channel and timer modifications: + if (!Channels.BeingEdited() && !Timers.BeingEdited()) { int modified = Channels.Modified(); static time_t ChannelSaveTimeout = 0; - if (modified == CHANNELSMOD_USER) + // Channels and timers need to be stored in a consistent manner, + // therefore if one of them is changed, we save both. + if (modified == CHANNELSMOD_USER || Timers.Modified()) ChannelSaveTimeout = 1; // triggers an immediate save else if (modified && !ChannelSaveTimeout) ChannelSaveTimeout = time(NULL) + CHANNELSAVEDELTA;