diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 208f106e..88c0f13e 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -1227,6 +1227,7 @@ Peter Bieringer for reporting a problem with the backslash ('\') in parameters when executing external commands for making the functions cRecordingInfo::SetData() and cRecordingInfo::SetAux() public + for adding some missing user command calls for copying, renaming and moving recordings Alexander Damhuis for reporting problems when deleting a timer that is currently recording diff --git a/HISTORY b/HISTORY index d019d608..c9adec0f 100644 --- a/HISTORY +++ b/HISTORY @@ -9603,3 +9603,5 @@ Video Disk Recorder Revision History is no info file (the change in version 1.7.28 broke the fallback to the old 'summary.vdr'). - Now making sure a spawned timer only fully overlaps the given event (reported by Jürgen Schneider). +- Added some missing user command calls for copying, renaming and moving recordings + (thanks to Peter Bieringer). diff --git a/INSTALL b/INSTALL index 1abed8f8..364668f5 100644 --- a/INSTALL +++ b/INSTALL @@ -264,11 +264,10 @@ Executing commands before and after a recording: ------------------------------------------------ You can use the '-r' option to define a program or script that gets called -before and after a recording is performed, and after an editing process -has finished or a recording has been deleted. +at various stages of handling recordings. -The program will be called with two or three (in case of "editing" and "edited") -string parameters. The first parameter is one of +The program will be called with two or three string parameters. +The first parameter is one of before if this is *before* a recording starts started if this is after a recording has *started* @@ -276,13 +275,16 @@ string parameters. The first parameter is one of editing if this is before *editing* a recording edited if this is after a recording has been *edited* deleted if this is after a recording has been *deleted* + copying if this is before *copying* a recording + copied if this is after a recording has been *copied* + renamed if this is after a recording has been *renamed* + moved if this is after a recording has been *moved* + (note that a move across file system borders triggers a sequence + of "copying", "copied" and "deleted") -and the second parameter contains the full name of the recording's +and the second and third parameter (if present) contain the full name of the recording's directory (which may not yet exists at that moment in the "before" case). -In the "editing" and "edited" case it will be the name of the edited version -(second parameter) and the name of the source version (third parameter). -In the "deleted" case the extension of the directory name is ".del" -instead of ".rec". +See the example below for the exact meaning of these parameters. Within this program you can do anything you would like to do before and/or after a recording or after an editing process. However, the program must return @@ -315,6 +317,22 @@ case "$1" in deleted) echo "Deleted recording $2" ;; + copying) + echo "Destination recording $2" + echo "Source recording $3" + ;; + copied) + echo "Destination recording $2" + echo "Source recording $3" + ;; + renamed) + echo "New name of recording $2" + echo "Old name of recording $3" + ;; + moved) + echo "New path of recording $2" + echo "Old path of recording $3" + ;; *) echo "ERROR: unknown state: $1" ;; diff --git a/recording.c b/recording.c index c84b7d62..c1baf54e 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 5.4 2021/01/18 13:35:16 kls Exp $ + * $Id: recording.c 5.5 2021/01/19 20:38:28 kls Exp $ */ #include "recording.h" @@ -1924,6 +1924,7 @@ bool cRecordingsHandlerEntry::Active(cRecordings *Recordings) Recordings->AddByName(FileNameDst(), false); } else if ((Usage() & (ruMove | ruCopy)) != 0) { + cRecordingUserCommand::InvokeCommand(RUC_COPYINGRECORDING, FileNameDst(), FileNameSrc()); copier = new cDirCopier(FileNameSrc(), FileNameDst()); copier->Start(); } @@ -1932,10 +1933,14 @@ bool cRecordingsHandlerEntry::Active(cRecordings *Recordings) return true; } // We're done: + if (!error && (usage & (ruMove | ruCopy)) != 0) + cRecordingUserCommand::InvokeCommand(RUC_COPIEDRECORDING, FileNameDst(), FileNameSrc()); if (!error && (usage & ruMove) != 0) { cRecording Recording(FileNameSrc()); - if (Recording.Delete()) + if (Recording.Delete()) { + cRecordingUserCommand::InvokeCommand(RUC_MOVEDRECORDING, FileNameDst(), FileNameSrc()); Recordings->DelByName(Recording.FileName()); + } } Recordings->SetModified(); // to trigger a state change Recordings->TouchUpdate(); diff --git a/recording.h b/recording.h index 208bd8b5..217adea9 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 5.2 2021/01/18 12:55:47 kls Exp $ + * $Id: recording.h 5.3 2021/01/19 20:38:28 kls Exp $ */ #ifndef __RECORDING_H @@ -421,6 +421,10 @@ public: #define RUC_EDITINGRECORDING "editing" #define RUC_EDITEDRECORDING "edited" #define RUC_DELETERECORDING "deleted" +#define RUC_RENAMEDRECORDING "renamed" // same directory, only the base name is changed +#define RUC_MOVEDRECORDING "moved" // different directory (and maybe base name), or "copy" to other filesystem + delete original (triggers copying->copied->deleted) +#define RUC_COPYINGRECORDING "copying" +#define RUC_COPIEDRECORDING "copied" class cRecordingUserCommand { private: diff --git a/tools.c b/tools.c index 88bfad32..ed0589cb 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 5.2 2020/12/29 21:40:29 kls Exp $ + * $Id: tools.c 5.3 2021/01/19 20:38:28 kls Exp $ */ #include "tools.h" @@ -200,6 +200,16 @@ int strcountchr(const char *s, char c) return n; } +cString strgetbefore(const char *s, char c, int n) +{ + const char *p = strrchr(s, 0); // points to the terminating 0 of s + while (--p >= s) { + if (*p == c && --n == 0) + break; + } + return cString(s, p); +} + const char *strgetlast(const char *s, char c) { const char *p = strrchr(s, c); diff --git a/tools.h b/tools.h index 2c27b593..5a77813a 100644 --- a/tools.h +++ b/tools.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.h 5.2 2021/01/01 15:26:27 kls Exp $ + * $Id: tools.h 5.3 2021/01/19 20:38:28 kls Exp $ */ #ifndef __TOOLS_H @@ -233,6 +233,7 @@ char *strreplace(char *s, char c1, char c2); char *strreplace(char *s, const char *s1, const char *s2); ///< re-allocates 's' and deletes the original string if necessary! const char *strchrn(const char *s, char c, size_t n); ///< returns a pointer to the n'th occurrence (counting from 1) of c in s, or NULL if no such character was found. If n is 0, s is returned. int strcountchr(const char *s, char c); ///< returns the number of occurrences of 'c' in 's'. +cString strgetbefore(const char *s, char c, int n = 1); // returns the part of 's' before (and excluding) the n'th occurrence of 'c' from the right, or an empty string if there is no such 'c'. const char *strgetlast(const char *s, char c); // returns the part of 's' after the last occurrence of 'c', or 's' if there is no 'c'. inline char *strgetlast(char *s, char c) { return const_cast(strgetlast(static_cast(s), c)); } // returns the part of 's' after the last occurrence of 'c', or 's' if there is no 'c'. inline char *skipspace(const char *s) diff --git a/videodir.c b/videodir.c index b2257fa6..c5545285 100644 --- a/videodir.c +++ b/videodir.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: videodir.c 4.1 2015/08/11 13:39:59 kls Exp $ + * $Id: videodir.c 5.1 2021/01/19 20:38:28 kls Exp $ */ #include "videodir.h" @@ -96,6 +96,11 @@ bool cVideoDirectory::Move(const char *FromName, const char *ToName) LOG_ERROR_STR(ToName); return false; } + // detect whether it's a real recording move inside same file system or a recording rename + if (strcmp(strgetbefore(FromName, '/', 2), strgetbefore(ToName, '/', 2))) + cRecordingUserCommand::InvokeCommand(RUC_MOVEDRECORDING, ToName, FromName); + else + cRecordingUserCommand::InvokeCommand(RUC_RENAMEDRECORDING, ToName, FromName); } else return RecordingsHandler.Add(ruMove, FromName, ToName);