diff options
-rw-r--r-- | CONTRIBUTORS | 2 | ||||
-rw-r--r-- | HISTORY | 6 | ||||
-rw-r--r-- | recording.c | 25 | ||||
-rw-r--r-- | recording.h | 9 | ||||
-rw-r--r-- | svdrp.c | 53 |
5 files changed, 68 insertions, 27 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index bbcc13ee..c51ead69 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -3469,6 +3469,8 @@ Aitugan Sarbassov <isarbassov@gmail.com> Sergey Chernyavskiy <glenvt18@gmail.com> for reporting truncated date/time strings in the skins on multi-byte UTF-8 for adding a short sleep to cTSBuffer::Action() to avoid high CPU usage + for making the SVDRP commands that deal with recordings use a unique id for each + recording Frank Richter <kulpstur@t-online.de> for adding 'S3W ABS-3A' to sources.conf @@ -8953,3 +8953,9 @@ Video Disk Recorder Revision History an "SVDRP default host" has been set for normal timer recordings. - cOsdMenu::Display() now checks whether the OSD size has changed and if so calls SetDisplayMenu(). +- The SVDRP commands that deal with recordings (DELR, EDIT, LSTR, MOVR, and PLAY) + now use a unique id for each recording, which remains valid as long as this + instance of VDR is running. This means that recordings are no longer continuously + numbered from 1 to N in LSTR. There may be gaps in the sequence, in case recordings + have been deleted, and they are not necessarily listed in numeric order. + Thanks to Sergey Chernyavskiy. diff --git a/recording.c b/recording.c index 63980585..9f96b73d 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.7 2017/01/01 17:52:51 kls Exp $ + * $Id: recording.c 4.8 2017/04/03 13:34:30 kls Exp $ */ #include "recording.h" @@ -753,6 +753,7 @@ char *LimitNameLengths(char *s, int PathMax, int NameMax) cRecording::cRecording(cTimer *Timer, const cEvent *Event) { + id = 0; resume = RESUME_NOT_INITIALIZED; titleBuffer = NULL; sortBufferName = sortBufferTime = NULL; @@ -808,6 +809,7 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event) cRecording::cRecording(const char *FileName) { + id = 0; resume = RESUME_NOT_INITIALIZED; fileSizeMB = -1; // unknown channel = -1; @@ -1000,6 +1002,11 @@ void cRecording::ClearSortName(void) sortBufferName = sortBufferTime = NULL; } +void cRecording::SetId(int Id) +{ + id = Id; +} + int cRecording::GetResume(void) const { if (resume == RESUME_NOT_INITIALIZED) { @@ -1456,6 +1463,7 @@ void cVideoDirectoryScannerThread::ScanVideoDir(const char *DirName, int LinkLev cRecordings cRecordings::recordings; cRecordings cRecordings::deletedRecordings(true); +int cRecordings::lastRecordingId = 0; char *cRecordings::updateFileName = NULL; cVideoDirectoryScannerThread *cRecordings::videoDirectoryScannerThread = NULL; time_t cRecordings::lastUpdate = 0; @@ -1507,6 +1515,15 @@ void cRecordings::Update(bool Wait) } } +const cRecording *cRecordings::GetById(int Id) const +{ + for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) { + if (Recording->Id() == Id) + return Recording; + } + return NULL; +} + const cRecording *cRecordings::GetByName(const char *FileName) const { if (FileName) { @@ -1518,6 +1535,12 @@ const cRecording *cRecordings::GetByName(const char *FileName) const return NULL; } +void cRecordings::Add(cRecording *Recording) +{ + Recording->SetId(++lastRecordingId); + cList<cRecording>::Add(Recording); +} + void cRecordings::AddByName(const char *FileName, bool TriggerUpdate) { if (!GetByName(FileName)) { diff --git a/recording.h b/recording.h index b649f6fd..200af45a 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.4 2016/12/13 13:12:12 kls Exp $ + * $Id: recording.h 4.5 2017/04/03 13:31:16 kls Exp $ */ #ifndef __RECORDING_H @@ -97,6 +97,7 @@ public: class cRecording : public cListObject { friend class cRecordings; private: + int id; mutable int resume; mutable char *titleBuffer; mutable char *sortBufferName; @@ -116,6 +117,7 @@ private: static char *StripEpisodeName(char *s, bool Strip); char *SortName(void) const; void ClearSortName(void); + void SetId(int Id); // should only be set by cRecordings time_t start; int priority; int lifetime; @@ -124,6 +126,7 @@ public: cRecording(cTimer *Timer, const cEvent *Event); cRecording(const char *FileName); virtual ~cRecording(); + int Id(void) const { return id; } time_t Start(void) const { return start; } int Priority(void) const { return priority; } int Lifetime(void) const { return lifetime; } @@ -222,6 +225,7 @@ class cRecordings : public cList<cRecording> { private: static cRecordings recordings; static cRecordings deletedRecordings; + static int lastRecordingId; static char *updateFileName; static time_t lastUpdate; static cVideoDirectoryScannerThread *videoDirectoryScannerThread; @@ -254,8 +258,11 @@ public: static bool NeedsUpdate(void); void ResetResume(const char *ResumeFileName = NULL); void ClearSortNames(void); + const cRecording *GetById(int Id) const; + cRecording *GetById(int Id) { return const_cast<cRecording *>(static_cast<const cRecordings *>(this)->GetById(Id)); }; const cRecording *GetByName(const char *FileName) const; cRecording *GetByName(const char *FileName) { return const_cast<cRecording *>(static_cast<const cRecordings *>(this)->GetByName(FileName)); } + void Add(cRecording *Recording); void AddByName(const char *FileName, bool TriggerUpdate = true); void DelByName(const char *FileName); void UpdateByName(const char *FileName); @@ -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.11 2016/12/08 10:48:53 kls Exp $ + * $Id: svdrp.c 4.12 2017/04/03 13:56:52 kls Exp $ */ #include "svdrp.h" @@ -723,18 +723,19 @@ const char *HelpPages[] = { " interfere with data from the broadcasters.", "DELC <number>\n" " Delete channel.", - "DELR <number>\n" - " Delete the recording with the given number. Before a recording can be\n" - " deleted, an LSTR command must have been executed in order to retrieve\n" - " the recording numbers. The numbers don't change during subsequent DELR\n" - " commands. CAUTION: THERE IS NO CONFIRMATION PROMPT WHEN DELETING A\n" + "DELR <id>\n" + " Delete the recording with the given id. Before a recording can be\n" + " deleted, an LSTR command should have been executed in order to retrieve\n" + " the recording ids. The ids are unique and don't change while this\n" + " instance of VDR is running.\n" + " CAUTION: THERE IS NO CONFIRMATION PROMPT WHEN DELETING A\n" " RECORDING - BE SURE YOU KNOW WHAT YOU ARE DOING!", "DELT <number>\n" " Delete timer.", - "EDIT <number>\n" - " Edit the recording with the given number. Before a recording can be\n" - " edited, an LSTR command must have been executed in order to retrieve\n" - " the recording numbers.", + "EDIT <id>\n" + " Edit the recording with the given id. Before a recording can be\n" + " edited, an LSTR command should have been executed in order to retrieve\n" + " the recording ids.", "GRAB <filename> [ <quality> [ <sizex> <sizey> ] ]\n" " Grab the current frame and save it to the given file. Images can\n" " be stored as JPEG or PNM, depending on the given file name extension.\n" @@ -764,11 +765,13 @@ const char *HelpPages[] = { " only data for that channel is listed. 'now', 'next', or 'at <time>'\n" " restricts the returned data to present events, following events, or\n" " events at the given time (which must be in time_t form).", - "LSTR [ <number> [ path ] ]\n" + "LSTR [ <id> [ path ] ]\n" " List recordings. Without option, all recordings are listed. Otherwise\n" " the information for the given recording is listed. If a recording\n" - " number and the keyword 'path' is given, the actual file name of that\n" - " recording's directory is listed.", + " id and the keyword 'path' is given, the actual file name of that\n" + " recording's directory is listed.\n" + " Note that the ids of the recordings are not necessarily given in\n" + " numeric order.", "LSTT [ <number> ] [ id ]\n" " List timers. Without option, all timers are listed. Otherwise\n" " only the given timer is listed. If the keyword 'id' is given, the\n" @@ -787,10 +790,10 @@ const char *HelpPages[] = { " used to easily activate or deactivate a timer.", "MOVC <number> <to>\n" " Move a channel to a new position.", - "MOVR <number> <new name>\n" - " Move the recording with the given number. Before a recording can be\n" - " moved, an LSTR command must have been executed in order to retrieve\n" - " the recording numbers. The numbers don't change during subsequent MOVR\n" + "MOVR <id> <new name>\n" + " Move the recording with the given id. Before a recording can be\n" + " moved, an LSTR command should have been executed in order to retrieve\n" + " the recording ids. The ids don't change during subsequent MOVR\n" " commands.\n", "NEWC <settings>\n" " Create a new channel. Settings must be in the same format as returned\n" @@ -812,10 +815,10 @@ const char *HelpPages[] = { " Used by peer-to-peer connections between VDRs to keep the connection\n" " from timing out. May be used at any time and simply returns a line of\n" " the form '<hostname> is alive'.", - "PLAY <number> [ begin | <position> ]\n" - " Play the recording with the given number. Before a recording can be\n" - " played, an LSTR command must have been executed in order to retrieve\n" - " the recording numbers.\n" + "PLAY <id> [ begin | <position> ]\n" + " Play the recording with the given id. Before a recording can be\n" + " played, an LSTR command should have been executed in order to retrieve\n" + " the recording ids.\n" " The keyword 'begin' plays the recording from its very beginning, while\n" " a <position> (given as hh:mm:ss[.ff] or framenumber) starts at that\n" " position. If neither 'begin' nor a <position> are given, replay is resumed\n" @@ -1280,7 +1283,7 @@ void cSVDRPServer::CmdDELR(const char *Option) if (isnumber(Option)) { LOCK_RECORDINGS_WRITE; Recordings->SetExplicitModify(); - if (cRecording *Recording = Recordings->Get(strtol(Option, NULL, 10) - 1)) { + if (cRecording *Recording = Recordings->GetById(strtol(Option, NULL, 10))) { if (int RecordingInUse = Recording->IsInUse()) Reply(550, "%s", *RecordingInUseMessage(RecordingInUse, Option, Recording)); else { @@ -1707,7 +1710,7 @@ void cSVDRPServer::CmdLSTR(const char *Option) p = strtok_r(NULL, delim, &strtok_next); } if (Number) { - if (const cRecording *Recording = Recordings->Get(strtol(Option, NULL, 10) - 1)) { + if (const cRecording *Recording = Recordings->GetById(strtol(Option, NULL, 10))) { FILE *f = fdopen(file, "w"); if (f) { if (Path) @@ -1729,7 +1732,7 @@ void cSVDRPServer::CmdLSTR(const char *Option) else if (Recordings->Count()) { const cRecording *Recording = Recordings->First(); while (Recording) { - Reply(Recording == Recordings->Last() ? 250 : -250, "%d %s", Recording->Index() + 1, Recording->Title(' ', true)); + Reply(Recording == Recordings->Last() ? 250 : -250, "%d %s", Recording->Id(), Recording->Title(' ', true)); Recording = Recordings->Next(Recording); } } @@ -1940,7 +1943,7 @@ void cSVDRPServer::CmdMOVR(const char *Option) if (isnumber(num)) { LOCK_RECORDINGS_WRITE; Recordings->SetExplicitModify(); - if (cRecording *Recording = Recordings->Get(strtol(num, NULL, 10) - 1)) { + if (cRecording *Recording = Recordings->GetById(strtol(num, NULL, 10))) { if (int RecordingInUse = Recording->IsInUse()) Reply(550, "%s", *RecordingInUseMessage(RecordingInUse, Option, Recording)); else { |