mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Recordings now have unique ids
This commit is contained in:
parent
e622854789
commit
67cb53d587
@ -3469,6 +3469,8 @@ Aitugan Sarbassov <isarbassov@gmail.com>
|
|||||||
Sergey Chernyavskiy <glenvt18@gmail.com>
|
Sergey Chernyavskiy <glenvt18@gmail.com>
|
||||||
for reporting truncated date/time strings in the skins on multi-byte UTF-8
|
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 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>
|
Frank Richter <kulpstur@t-online.de>
|
||||||
for adding 'S3W ABS-3A' to sources.conf
|
for adding 'S3W ABS-3A' to sources.conf
|
||||||
|
6
HISTORY
6
HISTORY
@ -8953,3 +8953,9 @@ Video Disk Recorder Revision History
|
|||||||
an "SVDRP default host" has been set for normal timer recordings.
|
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
|
- cOsdMenu::Display() now checks whether the OSD size has changed and if so calls
|
||||||
SetDisplayMenu().
|
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.
|
||||||
|
25
recording.c
25
recording.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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"
|
#include "recording.h"
|
||||||
@ -753,6 +753,7 @@ char *LimitNameLengths(char *s, int PathMax, int NameMax)
|
|||||||
|
|
||||||
cRecording::cRecording(cTimer *Timer, const cEvent *Event)
|
cRecording::cRecording(cTimer *Timer, const cEvent *Event)
|
||||||
{
|
{
|
||||||
|
id = 0;
|
||||||
resume = RESUME_NOT_INITIALIZED;
|
resume = RESUME_NOT_INITIALIZED;
|
||||||
titleBuffer = NULL;
|
titleBuffer = NULL;
|
||||||
sortBufferName = sortBufferTime = NULL;
|
sortBufferName = sortBufferTime = NULL;
|
||||||
@ -808,6 +809,7 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event)
|
|||||||
|
|
||||||
cRecording::cRecording(const char *FileName)
|
cRecording::cRecording(const char *FileName)
|
||||||
{
|
{
|
||||||
|
id = 0;
|
||||||
resume = RESUME_NOT_INITIALIZED;
|
resume = RESUME_NOT_INITIALIZED;
|
||||||
fileSizeMB = -1; // unknown
|
fileSizeMB = -1; // unknown
|
||||||
channel = -1;
|
channel = -1;
|
||||||
@ -1000,6 +1002,11 @@ void cRecording::ClearSortName(void)
|
|||||||
sortBufferName = sortBufferTime = NULL;
|
sortBufferName = sortBufferTime = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cRecording::SetId(int Id)
|
||||||
|
{
|
||||||
|
id = Id;
|
||||||
|
}
|
||||||
|
|
||||||
int cRecording::GetResume(void) const
|
int cRecording::GetResume(void) const
|
||||||
{
|
{
|
||||||
if (resume == RESUME_NOT_INITIALIZED) {
|
if (resume == RESUME_NOT_INITIALIZED) {
|
||||||
@ -1456,6 +1463,7 @@ void cVideoDirectoryScannerThread::ScanVideoDir(const char *DirName, int LinkLev
|
|||||||
|
|
||||||
cRecordings cRecordings::recordings;
|
cRecordings cRecordings::recordings;
|
||||||
cRecordings cRecordings::deletedRecordings(true);
|
cRecordings cRecordings::deletedRecordings(true);
|
||||||
|
int cRecordings::lastRecordingId = 0;
|
||||||
char *cRecordings::updateFileName = NULL;
|
char *cRecordings::updateFileName = NULL;
|
||||||
cVideoDirectoryScannerThread *cRecordings::videoDirectoryScannerThread = NULL;
|
cVideoDirectoryScannerThread *cRecordings::videoDirectoryScannerThread = NULL;
|
||||||
time_t cRecordings::lastUpdate = 0;
|
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
|
const cRecording *cRecordings::GetByName(const char *FileName) const
|
||||||
{
|
{
|
||||||
if (FileName) {
|
if (FileName) {
|
||||||
@ -1518,6 +1535,12 @@ const cRecording *cRecordings::GetByName(const char *FileName) const
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cRecordings::Add(cRecording *Recording)
|
||||||
|
{
|
||||||
|
Recording->SetId(++lastRecordingId);
|
||||||
|
cList<cRecording>::Add(Recording);
|
||||||
|
}
|
||||||
|
|
||||||
void cRecordings::AddByName(const char *FileName, bool TriggerUpdate)
|
void cRecordings::AddByName(const char *FileName, bool TriggerUpdate)
|
||||||
{
|
{
|
||||||
if (!GetByName(FileName)) {
|
if (!GetByName(FileName)) {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#ifndef __RECORDING_H
|
||||||
@ -97,6 +97,7 @@ public:
|
|||||||
class cRecording : public cListObject {
|
class cRecording : public cListObject {
|
||||||
friend class cRecordings;
|
friend class cRecordings;
|
||||||
private:
|
private:
|
||||||
|
int id;
|
||||||
mutable int resume;
|
mutable int resume;
|
||||||
mutable char *titleBuffer;
|
mutable char *titleBuffer;
|
||||||
mutable char *sortBufferName;
|
mutable char *sortBufferName;
|
||||||
@ -116,6 +117,7 @@ private:
|
|||||||
static char *StripEpisodeName(char *s, bool Strip);
|
static char *StripEpisodeName(char *s, bool Strip);
|
||||||
char *SortName(void) const;
|
char *SortName(void) const;
|
||||||
void ClearSortName(void);
|
void ClearSortName(void);
|
||||||
|
void SetId(int Id); // should only be set by cRecordings
|
||||||
time_t start;
|
time_t start;
|
||||||
int priority;
|
int priority;
|
||||||
int lifetime;
|
int lifetime;
|
||||||
@ -124,6 +126,7 @@ public:
|
|||||||
cRecording(cTimer *Timer, const cEvent *Event);
|
cRecording(cTimer *Timer, const cEvent *Event);
|
||||||
cRecording(const char *FileName);
|
cRecording(const char *FileName);
|
||||||
virtual ~cRecording();
|
virtual ~cRecording();
|
||||||
|
int Id(void) const { return id; }
|
||||||
time_t Start(void) const { return start; }
|
time_t Start(void) const { return start; }
|
||||||
int Priority(void) const { return priority; }
|
int Priority(void) const { return priority; }
|
||||||
int Lifetime(void) const { return lifetime; }
|
int Lifetime(void) const { return lifetime; }
|
||||||
@ -222,6 +225,7 @@ class cRecordings : public cList<cRecording> {
|
|||||||
private:
|
private:
|
||||||
static cRecordings recordings;
|
static cRecordings recordings;
|
||||||
static cRecordings deletedRecordings;
|
static cRecordings deletedRecordings;
|
||||||
|
static int lastRecordingId;
|
||||||
static char *updateFileName;
|
static char *updateFileName;
|
||||||
static time_t lastUpdate;
|
static time_t lastUpdate;
|
||||||
static cVideoDirectoryScannerThread *videoDirectoryScannerThread;
|
static cVideoDirectoryScannerThread *videoDirectoryScannerThread;
|
||||||
@ -254,8 +258,11 @@ public:
|
|||||||
static bool NeedsUpdate(void);
|
static bool NeedsUpdate(void);
|
||||||
void ResetResume(const char *ResumeFileName = NULL);
|
void ResetResume(const char *ResumeFileName = NULL);
|
||||||
void ClearSortNames(void);
|
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;
|
const cRecording *GetByName(const char *FileName) const;
|
||||||
cRecording *GetByName(const char *FileName) { return const_cast<cRecording *>(static_cast<const cRecordings *>(this)->GetByName(FileName)); }
|
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 AddByName(const char *FileName, bool TriggerUpdate = true);
|
||||||
void DelByName(const char *FileName);
|
void DelByName(const char *FileName);
|
||||||
void UpdateByName(const char *FileName);
|
void UpdateByName(const char *FileName);
|
||||||
|
53
svdrp.c
53
svdrp.c
@ -10,7 +10,7 @@
|
|||||||
* and interact with the Video Disk Recorder - or write a full featured
|
* and interact with the Video Disk Recorder - or write a full featured
|
||||||
* graphical interface that sits on top of an SVDRP connection.
|
* 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"
|
#include "svdrp.h"
|
||||||
@ -723,18 +723,19 @@ const char *HelpPages[] = {
|
|||||||
" interfere with data from the broadcasters.",
|
" interfere with data from the broadcasters.",
|
||||||
"DELC <number>\n"
|
"DELC <number>\n"
|
||||||
" Delete channel.",
|
" Delete channel.",
|
||||||
"DELR <number>\n"
|
"DELR <id>\n"
|
||||||
" Delete the recording with the given number. Before a recording can be\n"
|
" Delete the recording with the given id. Before a recording can be\n"
|
||||||
" deleted, an LSTR command must have been executed in order to retrieve\n"
|
" deleted, an LSTR command should have been executed in order to retrieve\n"
|
||||||
" the recording numbers. The numbers don't change during subsequent DELR\n"
|
" the recording ids. The ids are unique and don't change while this\n"
|
||||||
" commands. CAUTION: THERE IS NO CONFIRMATION PROMPT WHEN DELETING A\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!",
|
" RECORDING - BE SURE YOU KNOW WHAT YOU ARE DOING!",
|
||||||
"DELT <number>\n"
|
"DELT <number>\n"
|
||||||
" Delete timer.",
|
" Delete timer.",
|
||||||
"EDIT <number>\n"
|
"EDIT <id>\n"
|
||||||
" Edit the recording with the given number. Before a recording can be\n"
|
" Edit the recording with the given id. Before a recording can be\n"
|
||||||
" edited, an LSTR command must have been executed in order to retrieve\n"
|
" edited, an LSTR command should have been executed in order to retrieve\n"
|
||||||
" the recording numbers.",
|
" the recording ids.",
|
||||||
"GRAB <filename> [ <quality> [ <sizex> <sizey> ] ]\n"
|
"GRAB <filename> [ <quality> [ <sizex> <sizey> ] ]\n"
|
||||||
" Grab the current frame and save it to the given file. Images can\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"
|
" 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"
|
" only data for that channel is listed. 'now', 'next', or 'at <time>'\n"
|
||||||
" restricts the returned data to present events, following events, or\n"
|
" restricts the returned data to present events, following events, or\n"
|
||||||
" events at the given time (which must be in time_t form).",
|
" 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"
|
" List recordings. Without option, all recordings are listed. Otherwise\n"
|
||||||
" the information for the given recording is listed. If a recording\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"
|
" id and the keyword 'path' is given, the actual file name of that\n"
|
||||||
" recording's directory is listed.",
|
" 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"
|
"LSTT [ <number> ] [ id ]\n"
|
||||||
" List timers. Without option, all timers are listed. Otherwise\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"
|
" 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.",
|
" used to easily activate or deactivate a timer.",
|
||||||
"MOVC <number> <to>\n"
|
"MOVC <number> <to>\n"
|
||||||
" Move a channel to a new position.",
|
" Move a channel to a new position.",
|
||||||
"MOVR <number> <new name>\n"
|
"MOVR <id> <new name>\n"
|
||||||
" Move the recording with the given number. Before a recording can be\n"
|
" Move the recording with the given id. Before a recording can be\n"
|
||||||
" moved, an LSTR command must have been executed in order to retrieve\n"
|
" moved, an LSTR command should have been executed in order to retrieve\n"
|
||||||
" the recording numbers. The numbers don't change during subsequent MOVR\n"
|
" the recording ids. The ids don't change during subsequent MOVR\n"
|
||||||
" commands.\n",
|
" commands.\n",
|
||||||
"NEWC <settings>\n"
|
"NEWC <settings>\n"
|
||||||
" Create a new channel. Settings must be in the same format as returned\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"
|
" 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"
|
" from timing out. May be used at any time and simply returns a line of\n"
|
||||||
" the form '<hostname> is alive'.",
|
" the form '<hostname> is alive'.",
|
||||||
"PLAY <number> [ begin | <position> ]\n"
|
"PLAY <id> [ begin | <position> ]\n"
|
||||||
" Play the recording with the given number. Before a recording can be\n"
|
" Play the recording with the given id. Before a recording can be\n"
|
||||||
" played, an LSTR command must have been executed in order to retrieve\n"
|
" played, an LSTR command should have been executed in order to retrieve\n"
|
||||||
" the recording numbers.\n"
|
" the recording ids.\n"
|
||||||
" The keyword 'begin' plays the recording from its very beginning, while\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"
|
" 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"
|
" 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)) {
|
if (isnumber(Option)) {
|
||||||
LOCK_RECORDINGS_WRITE;
|
LOCK_RECORDINGS_WRITE;
|
||||||
Recordings->SetExplicitModify();
|
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())
|
if (int RecordingInUse = Recording->IsInUse())
|
||||||
Reply(550, "%s", *RecordingInUseMessage(RecordingInUse, Option, Recording));
|
Reply(550, "%s", *RecordingInUseMessage(RecordingInUse, Option, Recording));
|
||||||
else {
|
else {
|
||||||
@ -1707,7 +1710,7 @@ void cSVDRPServer::CmdLSTR(const char *Option)
|
|||||||
p = strtok_r(NULL, delim, &strtok_next);
|
p = strtok_r(NULL, delim, &strtok_next);
|
||||||
}
|
}
|
||||||
if (Number) {
|
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");
|
FILE *f = fdopen(file, "w");
|
||||||
if (f) {
|
if (f) {
|
||||||
if (Path)
|
if (Path)
|
||||||
@ -1729,7 +1732,7 @@ void cSVDRPServer::CmdLSTR(const char *Option)
|
|||||||
else if (Recordings->Count()) {
|
else if (Recordings->Count()) {
|
||||||
const cRecording *Recording = Recordings->First();
|
const cRecording *Recording = Recordings->First();
|
||||||
while (Recording) {
|
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);
|
Recording = Recordings->Next(Recording);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1940,7 +1943,7 @@ void cSVDRPServer::CmdMOVR(const char *Option)
|
|||||||
if (isnumber(num)) {
|
if (isnumber(num)) {
|
||||||
LOCK_RECORDINGS_WRITE;
|
LOCK_RECORDINGS_WRITE;
|
||||||
Recordings->SetExplicitModify();
|
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())
|
if (int RecordingInUse = Recording->IsInUse())
|
||||||
Reply(550, "%s", *RecordingInUseMessage(RecordingInUse, Option, Recording));
|
Reply(550, "%s", *RecordingInUseMessage(RecordingInUse, Option, Recording));
|
||||||
else {
|
else {
|
||||||
|
Loading…
Reference in New Issue
Block a user