diff --git a/HISTORY b/HISTORY index 3522d34a..5f49c016 100644 --- a/HISTORY +++ b/HISTORY @@ -9162,7 +9162,7 @@ Video Disk Recorder Revision History a subdirectory. - SVDRP peering can now be limited to the default SVDRP host (see MANUAL for details). -2018-02-12: Version 2.3.9 +2018-02-13: Version 2.3.9 - Updated the Italian OSD texts (thanks to Diego Pierotto). - Updated the Finnish OSD texts (thanks to Rolf Ahrenberg). @@ -9271,3 +9271,7 @@ Video Disk Recorder Revision History jumping to the proper offset. - Fixed getting the info of a newly edited recording (reported by Matthias Senzel). - Improved calculating signal strength and quality (thanks to Helmut Binder). +- While a timer is recording, the file '.timer' in the recording directory now contains + the full id of the timer that is currently recording into this directory. This is used + to determine whether a timer is still recording on a remote VDR when deleting a recording + from the Recordings menu. diff --git a/menu.c b/menu.c index c767f357..1759670d 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 4.60 2018/02/10 12:45:36 kls Exp $ + * $Id: menu.c 4.61 2018/02/13 09:25:43 kls Exp $ */ #include "menu.h" @@ -3111,6 +3111,56 @@ eOSState cMenuRecordings::Rewind(void) return osContinue; } +static bool TimerStillRecording(const char *FileName) +{ + if (cRecordControl *rc = cRecordControls::GetRecordControl(FileName)) { + // local timer + if (Interface->Confirm(tr("Timer still recording - really delete?"))) { + LOCK_TIMERS_WRITE; + if (cTimer *Timer = rc->Timer()) { + Timer->Skip(); + cRecordControls::Process(Timers, time(NULL)); + if (Timer->IsSingleEvent()) { + Timers->Del(Timer); + isyslog("deleted timer %s", *Timer->ToDescr()); + } + } + } + else + return true; // user didn't confirm deletion + } + else { + // remote timer + cString TimerId = GetRecordingTimerId(FileName); + if (*TimerId) { + int Id; + char *RemoteBuf = NULL; + cString Remote; + if (2 == sscanf(TimerId, "%d@%m[^ \n]", &Id, &RemoteBuf)) { + Remote = RemoteBuf; + free(RemoteBuf); + if (Interface->Confirm(tr("Timer still recording - really delete?"))) { + LOCK_TIMERS_WRITE; + if (cTimer *Timer = Timers->GetById(Id, Remote)) { + Timer->Skip(); + if (Timer->IsSingleEvent()) { + if (HandleRemoteModifications(NULL, Timer)) + Timers->Del(Timer); + else + return true; // error while deleting remote timer + } + else if (!HandleRemoteModifications(Timer)) + return true; // error while modifying remote timer + } + } + else + return true; // user didn't confirm deletion + } + } + } + return false; +} + eOSState cMenuRecordings::Delete(void) { if (HasSubMenu() || Count() == 0) @@ -3118,21 +3168,8 @@ eOSState cMenuRecordings::Delete(void) cMenuRecordingItem *ri = (cMenuRecordingItem *)Get(Current()); if (ri && !ri->IsDirectory()) { if (Interface->Confirm(tr("Delete recording?"))) { - if (cRecordControl *rc = cRecordControls::GetRecordControl(ri->Recording()->FileName())) { - if (Interface->Confirm(tr("Timer still recording - really delete?"))) { - if (cTimer *Timer = rc->Timer()) { - LOCK_TIMERS_WRITE; - Timer->Skip(); - cRecordControls::Process(Timers, time(NULL)); - if (Timer->IsSingleEvent()) { - Timers->Del(Timer); - isyslog("deleted timer %s", *Timer->ToDescr()); - } - } - } - else - return osContinue; - } + if (TimerStillRecording(ri->Recording()->FileName())) + return osContinue; cString FileName; { LOCK_RECORDINGS_READ; @@ -5198,6 +5235,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimers *Timers, cTimer *Timer, SchedulesStateKey.Remove(); LOCK_RECORDINGS_WRITE; Recordings->AddByName(fileName); + SetRecordingTimerId(fileName, cString::sprintf("%d@%s", Timer->Id(), Setup.SVDRPHostName)); return; } else @@ -5250,6 +5288,7 @@ void cRecordControl::Stop(bool ExecuteUserCommand) DELETENULL(recorder); timer->SetRecording(false); timer = NULL; + SetRecordingTimerId(fileName, NULL); cStatus::MsgRecording(device, NULL, fileName, false); if (ExecuteUserCommand) cRecordingUserCommand::InvokeCommand(RUC_AFTERRECORDING, fileName); diff --git a/recording.c b/recording.c index 3a6ec4ff..9cd47687 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 4.19 2018/02/10 13:24:04 kls Exp $ + * $Id: recording.c 4.20 2018/02/13 08:44:19 kls Exp $ */ #include "recording.h" @@ -57,6 +57,7 @@ #define MARKSFILESUFFIX "/marks" #define SORTMODEFILE ".sort" +#define TIMERRECFILE ".timer" #define MINDISKSPACE 1024 // MB @@ -117,7 +118,7 @@ void cRemoveDeletedRecordingsThread::Action(void) r = DeletedRecordings->Next(r); } if (deleted) { - const char *IgnoreFiles[] = { SORTMODEFILE, NULL }; + const char *IgnoreFiles[] = { SORTMODEFILE, TIMERRECFILE, NULL }; cVideoDirectory::RemoveEmptyVideoDirectories(IgnoreFiles); } } @@ -3122,3 +3123,38 @@ void IncRecordingsSortMode(const char *Directory) RecordingsSortMode = eRecordingsSortMode(0); SetRecordingsSortMode(Directory, RecordingsSortMode); } + +// --- Recording Timer Indicator --------------------------------------------- + +void SetRecordingTimerId(const char *Directory, const char *TimerId) +{ + cString FileName = AddDirectory(Directory, TIMERRECFILE); + if (TimerId) { + dsyslog("writing timer id '%s' to %s", TimerId, *FileName); + if (FILE *f = fopen(FileName, "w")) { + fprintf(f, "%s\n", TimerId); + fclose(f); + } + else + LOG_ERROR_STR(*FileName); + } + else { + dsyslog("removing %s", *FileName); + unlink(FileName); + } +} + +cString GetRecordingTimerId(const char *Directory) +{ + cString FileName = AddDirectory(Directory, TIMERRECFILE); + const char *Id = NULL; + if (FILE *f = fopen(FileName, "r")) { + char buf[HOST_NAME_MAX + 10]; // +10 for numeric timer id and '@' + if (fgets(buf, sizeof(buf), f)) { + stripspace(buf); + Id = buf; + } + fclose(f); + } + return Id; +} diff --git a/recording.h b/recording.h index 626bc8d9..c5052044 100644 --- a/recording.h +++ b/recording.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.h 4.7 2017/12/11 12:56:57 kls Exp $ + * $Id: recording.h 4.8 2018/02/13 08:44:19 kls Exp $ */ #ifndef __RECORDING_H @@ -535,4 +535,7 @@ void GetRecordingsSortMode(const char *Directory); void SetRecordingsSortMode(const char *Directory, eRecordingsSortMode SortMode); void IncRecordingsSortMode(const char *Directory); +void SetRecordingTimerId(const char *Directory, const char *TimerId); +cString GetRecordingTimerId(const char *Directory); + #endif //__RECORDING_H diff --git a/svdrp.c b/svdrp.c index c3cc7527..93a7de4d 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 4.24 2018/02/05 14:52:27 kls Exp $ + * $Id: svdrp.c 4.25 2018/02/13 09:23:11 kls Exp $ */ #include "svdrp.h" @@ -1334,8 +1334,10 @@ void cSVDRPServer::CmdDELT(const char *Option) LOCK_TIMERS_WRITE; Timers->SetExplicitModify(); if (cTimer *Timer = Timers->GetById(strtol(Option, NULL, 10))) { - if (Timer->Recording()) + if (Timer->Recording()) { Timer->Skip(); + cRecordControls::Process(Timers, time(NULL)); + } Timers->Del(Timer); Timers->SetModified(); isyslog("SVDRP < %s deleted timer %s", *connection, *Timer->ToDescr()); diff --git a/vdr.5 b/vdr.5 index df954c79..1e48a97f 100644 --- a/vdr.5 +++ b/vdr.5 @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.5 4.5 2018/02/03 13:56:27 kls Exp $ +.\" $Id: vdr.5 4.6 2018/02/13 09:33:41 kls Exp $ .\" .TH vdr 5 "19 Feb 2015" "2.2" "Video Disk Recorder Files" .SH NAME @@ -821,6 +821,15 @@ closer). \fBCURRENT RESTRICTIONS:\fR -\ the comment is currently not used by VDR +.SS RECORDING TIMER +The file \fI.timer\fR (if present in a recording directory) contains +the full id of the timer that is currently recording into this directory. +Timer ids are of the form + +\fBid@hostname\fR + +where \fBid\fR is the timer's numerical id on the VDR with the name \fBhostname\fR. +This file is created when the timer starts recording, and is deleted when it ends. .SS EPG DATA The file \fIepg.data\fR contains the EPG data in an easily parsable format. The first character of each line defines what kind of data this line contains.