mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The list of recordings is now kept statically in memory
This commit is contained in:
parent
1369239b53
commit
5ed57fa1c5
9
HISTORY
9
HISTORY
@ -2893,7 +2893,7 @@ Video Disk Recorder Revision History
|
|||||||
strings in order to avoid buffer overflows (thanks to Philip Lawatsch for
|
strings in order to avoid buffer overflows (thanks to Philip Lawatsch for
|
||||||
debugging a buffer overflow in eit.c).
|
debugging a buffer overflow in eit.c).
|
||||||
|
|
||||||
2004-06-12: Version 1.3.11
|
2004-06-13: Version 1.3.11
|
||||||
|
|
||||||
- In order to avoid problems on NPTL systems, VDR now checks for the presence
|
- In order to avoid problems on NPTL systems, VDR now checks for the presence
|
||||||
of NPTL at program start, and if it is, exists and tells the user to do
|
of NPTL at program start, and if it is, exists and tells the user to do
|
||||||
@ -2911,3 +2911,10 @@ Video Disk Recorder Revision History
|
|||||||
- Fixed switching channels while an encrypted channel is being recorded, because the
|
- Fixed switching channels while an encrypted channel is being recorded, because the
|
||||||
channel was switched if the new channel was on the same transponder and was
|
channel was switched if the new channel was on the same transponder and was
|
||||||
a radio channel (thanks to Martin Dauskardt for reporting this one).
|
a radio channel (thanks to Martin Dauskardt for reporting this one).
|
||||||
|
- The list of recordings is now kept statically in memory to avoid long delays
|
||||||
|
when opening the "Recordings" menu. As a side effect, external modifications to
|
||||||
|
the video directory are no longer immediately reflected in the "Recordings" menu.
|
||||||
|
If a plugin manipulates the video directory in any way, it can call the function
|
||||||
|
Recordings.TriggerUpdate() to trigger an update of the list of recordings.
|
||||||
|
If some external tool manipulates the video directory, it can touch the file
|
||||||
|
'.update' in the video directory to trigger an update of the list of recordings.
|
||||||
|
4
cutter.c
4
cutter.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: cutter.c 1.6 2003/10/18 11:29:37 kls Exp $
|
* $Id: cutter.c 1.7 2004/06/13 16:04:08 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cutter.h"
|
#include "cutter.h"
|
||||||
@ -205,6 +205,7 @@ bool cCutter::Start(const char *FileName)
|
|||||||
// XXX
|
// XXX
|
||||||
editedVersionName = strdup(evn);
|
editedVersionName = strdup(evn);
|
||||||
Recording.WriteSummary();
|
Recording.WriteSummary();
|
||||||
|
Recordings.AddByName(editedVersionName);
|
||||||
cuttingThread = new cCuttingThread(FileName, editedVersionName);
|
cuttingThread = new cCuttingThread(FileName, editedVersionName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -224,6 +225,7 @@ void cCutter::Stop(void)
|
|||||||
if (Error)
|
if (Error)
|
||||||
esyslog("ERROR: '%s' during editing process", Error);
|
esyslog("ERROR: '%s' during editing process", Error);
|
||||||
RemoveVideoFile(editedVersionName); //XXX what if this file is currently being replayed?
|
RemoveVideoFile(editedVersionName); //XXX what if this file is currently being replayed?
|
||||||
|
Recordings.DelByName(editedVersionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
menu.c
61
menu.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: menu.c 1.308 2004/06/06 09:47:44 kls Exp $
|
* $Id: menu.c 1.309 2004/06/13 20:26:51 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -1410,7 +1410,6 @@ void cMenuRecordingItem::IncrementCounter(bool New)
|
|||||||
|
|
||||||
// --- cMenuRecordings -------------------------------------------------------
|
// --- cMenuRecordings -------------------------------------------------------
|
||||||
|
|
||||||
cRecordings cMenuRecordings::Recordings;
|
|
||||||
int cMenuRecordings::helpKeys = -1;
|
int cMenuRecordings::helpKeys = -1;
|
||||||
|
|
||||||
cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
|
cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
|
||||||
@ -1419,40 +1418,35 @@ cMenuRecordings::cMenuRecordings(const char *Base, int Level, bool OpenSubMenus)
|
|||||||
base = Base ? strdup(Base) : NULL;
|
base = Base ? strdup(Base) : NULL;
|
||||||
level = Setup.RecordingDirs ? Level : -1;
|
level = Setup.RecordingDirs ? Level : -1;
|
||||||
Display(); // this keeps the higher level menus from showing up briefly when pressing 'Back' during replay
|
Display(); // this keeps the higher level menus from showing up briefly when pressing 'Back' during replay
|
||||||
|
const char *LastReplayed = cReplayControl::LastReplayed();
|
||||||
|
cMenuRecordingItem *LastItem = NULL;
|
||||||
|
char *LastItemText = NULL;
|
||||||
if (!Base)
|
if (!Base)
|
||||||
Skins.Message(mtStatus, tr("scanning recordings..."));
|
Recordings.Sort();
|
||||||
bool Loaded = Base || Recordings.Load();
|
for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
|
||||||
if (!Base)
|
if (!Base || (strstr(recording->Name(), Base) == recording->Name() && recording->Name()[strlen(Base)] == '~')) {
|
||||||
Skins.Message(mtStatus, NULL);
|
cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level);
|
||||||
if (Loaded) {
|
if (*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText) != 0)) {
|
||||||
const char *LastReplayed = cReplayControl::LastReplayed();
|
Add(Item);
|
||||||
cMenuRecordingItem *LastItem = NULL;
|
LastItem = Item;
|
||||||
char *LastItemText = NULL;
|
free(LastItemText);
|
||||||
for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
|
LastItemText = strdup(LastItem->Text()); // must use a copy because of the counters!
|
||||||
if (!Base || (strstr(recording->Name(), Base) == recording->Name() && recording->Name()[strlen(Base)] == '~')) {
|
}
|
||||||
cMenuRecordingItem *Item = new cMenuRecordingItem(recording, level);
|
else
|
||||||
if (*Item->Text() && (!LastItem || strcmp(Item->Text(), LastItemText) != 0)) {
|
delete Item;
|
||||||
Add(Item);
|
if (LastItem) {
|
||||||
LastItem = Item;
|
if (LastReplayed && strcmp(LastReplayed, recording->FileName()) == 0)
|
||||||
free(LastItemText);
|
SetCurrent(LastItem);
|
||||||
LastItemText = strdup(LastItem->Text()); // must use a copy because of the counters!
|
if (LastItem->IsDirectory())
|
||||||
}
|
LastItem->IncrementCounter(recording->IsNew());
|
||||||
else
|
|
||||||
delete Item;
|
|
||||||
if (LastItem) {
|
|
||||||
if (LastReplayed && strcmp(LastReplayed, recording->FileName()) == 0)
|
|
||||||
SetCurrent(LastItem);
|
|
||||||
if (LastItem->IsDirectory())
|
|
||||||
LastItem->IncrementCounter(recording->IsNew());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(LastItemText);
|
}
|
||||||
if (Current() < 0)
|
free(LastItemText);
|
||||||
SetCurrent(First());
|
if (Current() < 0)
|
||||||
else if (OpenSubMenus && Open(true))
|
SetCurrent(First());
|
||||||
return;
|
else if (OpenSubMenus && Open(true))
|
||||||
}
|
return;
|
||||||
SetHelpKeys();
|
SetHelpKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2780,6 +2774,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
|
|||||||
cStatus::MsgRecording(device, Recording.Name());
|
cStatus::MsgRecording(device, Recording.Name());
|
||||||
if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
|
if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
|
||||||
cReplayControl::SetRecording(fileName, Recording.Name());
|
cReplayControl::SetRecording(fileName, Recording.Name());
|
||||||
|
Recordings.AddByName(fileName);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DELETENULL(recorder);
|
DELETENULL(recorder);
|
||||||
|
4
menu.h
4
menu.h
@ -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: menu.h 1.63 2004/05/23 09:47:26 kls Exp $
|
* $Id: menu.h 1.64 2004/06/13 11:46:03 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MENU_H
|
#ifndef __MENU_H
|
||||||
@ -16,7 +16,6 @@
|
|||||||
#include "osdbase.h"
|
#include "osdbase.h"
|
||||||
#include "dvbplayer.h"
|
#include "dvbplayer.h"
|
||||||
#include "recorder.h"
|
#include "recorder.h"
|
||||||
#include "recording.h"
|
|
||||||
#include "skins.h"
|
#include "skins.h"
|
||||||
|
|
||||||
class cMenuText : public cOsdMenu {
|
class cMenuText : public cOsdMenu {
|
||||||
@ -107,7 +106,6 @@ class cMenuRecordingItem;
|
|||||||
|
|
||||||
class cMenuRecordings : public cOsdMenu {
|
class cMenuRecordings : public cOsdMenu {
|
||||||
private:
|
private:
|
||||||
static cRecordings Recordings;
|
|
||||||
char *base;
|
char *base;
|
||||||
int level;
|
int level;
|
||||||
static int helpKeys;
|
static int helpKeys;
|
||||||
|
132
recording.c
132
recording.c
@ -4,10 +4,11 @@
|
|||||||
* 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 1.87 2004/05/07 14:24:18 kls Exp $
|
* $Id: recording.c 1.88 2004/06/13 20:25:19 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -25,7 +26,7 @@
|
|||||||
#define RECEXT ".rec"
|
#define RECEXT ".rec"
|
||||||
#define DELEXT ".del"
|
#define DELEXT ".del"
|
||||||
/* This was the original code, which works fine in a Linux only environment.
|
/* This was the original code, which works fine in a Linux only environment.
|
||||||
Unfortunately, because of windows and its brain dead file system, we have
|
Unfortunately, because of Windows and its brain dead file system, we have
|
||||||
to use a more complicated approach, in order to allow users who have enabled
|
to use a more complicated approach, in order to allow users who have enabled
|
||||||
the VFAT compile time option to see their recordings even if they forget to
|
the VFAT compile time option to see their recordings even if they forget to
|
||||||
enable VFAT when compiling a new version of VDR... Gee, do I hate Windows.
|
enable VFAT when compiling a new version of VDR... Gee, do I hate Windows.
|
||||||
@ -47,8 +48,6 @@
|
|||||||
#define SUMMARYFILESUFFIX "/summary.vdr"
|
#define SUMMARYFILESUFFIX "/summary.vdr"
|
||||||
#define MARKSFILESUFFIX "/marks.vdr"
|
#define MARKSFILESUFFIX "/marks.vdr"
|
||||||
|
|
||||||
#define FINDCMD "cd '%s' && find '%s' -follow -type d -name '%s' 2> /dev/null"
|
|
||||||
|
|
||||||
#define MINDISKSPACE 1024 // MB
|
#define MINDISKSPACE 1024 // MB
|
||||||
|
|
||||||
#define DELETEDLIFETIME 1 // hours after which a deleted recording will be actually removed
|
#define DELETEDLIFETIME 1 // hours after which a deleted recording will be actually removed
|
||||||
@ -70,14 +69,14 @@ void RemoveDeletedRecordings(void)
|
|||||||
if (!LockFile.Lock())
|
if (!LockFile.Lock())
|
||||||
return;
|
return;
|
||||||
// Remove the oldest file that has been "deleted":
|
// Remove the oldest file that has been "deleted":
|
||||||
cRecordings Recordings;
|
cRecordings DeletedRecordings(true);
|
||||||
if (Recordings.Load(true)) {
|
if (DeletedRecordings.Load()) {
|
||||||
cRecording *r = Recordings.First();
|
cRecording *r = DeletedRecordings.First();
|
||||||
cRecording *r0 = r;
|
cRecording *r0 = r;
|
||||||
while (r) {
|
while (r) {
|
||||||
if (r->start < r0->start)
|
if (r->start < r0->start)
|
||||||
r0 = r;
|
r0 = r;
|
||||||
r = Recordings.Next(r);
|
r = DeletedRecordings.Next(r);
|
||||||
}
|
}
|
||||||
if (r0 && time(NULL) - r0->start > DELETEDLIFETIME * 3600) {
|
if (r0 && time(NULL) - r0->start > DELETEDLIFETIME * 3600) {
|
||||||
r0->Remove();
|
r0->Remove();
|
||||||
@ -105,14 +104,14 @@ void AssertFreeDiskSpace(int Priority)
|
|||||||
return;
|
return;
|
||||||
// Remove the oldest file that has been "deleted":
|
// Remove the oldest file that has been "deleted":
|
||||||
isyslog("low disk space while recording, trying to remove a deleted recording...");
|
isyslog("low disk space while recording, trying to remove a deleted recording...");
|
||||||
cRecordings Recordings;
|
cRecordings DeletedRecordings(true);
|
||||||
if (Recordings.Load(true)) {
|
if (DeletedRecordings.Load()) {
|
||||||
cRecording *r = Recordings.First();
|
cRecording *r = DeletedRecordings.First();
|
||||||
cRecording *r0 = r;
|
cRecording *r0 = r;
|
||||||
while (r) {
|
while (r) {
|
||||||
if (r->start < r0->start)
|
if (r->start < r0->start)
|
||||||
r0 = r;
|
r0 = r;
|
||||||
r = Recordings.Next(r);
|
r = DeletedRecordings.Next(r);
|
||||||
}
|
}
|
||||||
if (r0 && r0->Remove()) {
|
if (r0 && r0->Remove()) {
|
||||||
LastFreeDiskCheck += REMOVELATENCY / Factor;
|
LastFreeDiskCheck += REMOVELATENCY / Factor;
|
||||||
@ -121,7 +120,7 @@ void AssertFreeDiskSpace(int Priority)
|
|||||||
}
|
}
|
||||||
// No "deleted" files to remove, so let's see if we can delete a recording:
|
// No "deleted" files to remove, so let's see if we can delete a recording:
|
||||||
isyslog("...no deleted recording found, trying to delete an old recording...");
|
isyslog("...no deleted recording found, trying to delete an old recording...");
|
||||||
if (Recordings.Load(false)) {
|
if (Recordings.Load()) {
|
||||||
cRecording *r = Recordings.First();
|
cRecording *r = Recordings.First();
|
||||||
cRecording *r0 = NULL;
|
cRecording *r0 = NULL;
|
||||||
while (r) {
|
while (r) {
|
||||||
@ -138,8 +137,10 @@ void AssertFreeDiskSpace(int Priority)
|
|||||||
}
|
}
|
||||||
r = Recordings.Next(r);
|
r = Recordings.Next(r);
|
||||||
}
|
}
|
||||||
if (r0 && r0->Delete())
|
if (r0 && r0->Delete()) {
|
||||||
|
Recordings.Del(r0);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Unable to free disk space, but there's nothing we can do about that...
|
// Unable to free disk space, but there's nothing we can do about that...
|
||||||
isyslog("...no old recording found, giving up");
|
isyslog("...no old recording found, giving up");
|
||||||
@ -617,30 +618,75 @@ bool cRecording::Remove(void)
|
|||||||
|
|
||||||
// --- cRecordings -----------------------------------------------------------
|
// --- cRecordings -----------------------------------------------------------
|
||||||
|
|
||||||
bool cRecordings::Load(bool Deleted)
|
cRecordings Recordings;
|
||||||
|
|
||||||
|
cRecordings::cRecordings(bool Deleted)
|
||||||
{
|
{
|
||||||
Clear();
|
deleted = Deleted;
|
||||||
bool result = false;
|
lastUpdate = 0;
|
||||||
char *cmd = NULL;
|
}
|
||||||
asprintf(&cmd, FINDCMD, VideoDirectory, VideoDirectory, Deleted ? "*" DELEXT : "*" RECEXT);
|
|
||||||
FILE *p = popen(cmd, "r");
|
bool cRecordings::ScanVideoDir(const char *DirName)
|
||||||
if (p) {
|
{
|
||||||
char *s;
|
DIR *d = opendir(DirName);
|
||||||
while ((s = readline(p)) != NULL) {
|
if (d) {
|
||||||
cRecording *r = new cRecording(s);
|
struct dirent *e;
|
||||||
if (r->Name())
|
while ((e = readdir(d)) != NULL) {
|
||||||
Add(r);
|
if (strcmp(e->d_name, ".") && strcmp(e->d_name, "..")) {
|
||||||
else
|
char *buffer;
|
||||||
delete r;
|
asprintf(&buffer, "%s/%s", DirName, e->d_name);
|
||||||
|
struct stat st;
|
||||||
|
if (stat(buffer, &st) == 0) {
|
||||||
|
if (S_ISLNK(st.st_mode)) {
|
||||||
|
free(buffer);
|
||||||
|
buffer = ReadLink(buffer);
|
||||||
|
if (!buffer)
|
||||||
|
return false;
|
||||||
|
if (stat(buffer, &st) != 0) {
|
||||||
|
LOG_ERROR_STR(DirName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
if (endswith(buffer, deleted ? DELEXT : RECEXT)) {
|
||||||
|
cRecording *r = new cRecording(buffer);
|
||||||
|
if (r->Name())
|
||||||
|
Add(r);
|
||||||
|
else
|
||||||
|
delete r;
|
||||||
|
}
|
||||||
|
else if (!ScanVideoDir(buffer))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_ERROR_STR(DirName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pclose(p);
|
closedir(d);
|
||||||
Sort();
|
|
||||||
result = Count() > 0;
|
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
Skins.Message(mtError, "Error while opening pipe!");
|
LOG_ERROR_STR(DirName);
|
||||||
free(cmd);
|
return false;
|
||||||
return result;
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRecordings::NeedsUpdate(void)
|
||||||
|
{
|
||||||
|
return lastUpdate <= LastModifiedTime(AddDirectory(VideoDirectory, ".update"));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cRecordings::Load(void)
|
||||||
|
{
|
||||||
|
lastUpdate = time(NULL); // doing this first to make sure we don't miss anything
|
||||||
|
Clear();
|
||||||
|
ScanVideoDir(VideoDirectory);
|
||||||
|
Sort();
|
||||||
|
return Count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cRecording *cRecordings::GetByName(const char *FileName)
|
cRecording *cRecordings::GetByName(const char *FileName)
|
||||||
@ -652,6 +698,22 @@ cRecording *cRecordings::GetByName(const char *FileName)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cRecordings::AddByName(const char *FileName)
|
||||||
|
{
|
||||||
|
cRecording *recording = GetByName(FileName);
|
||||||
|
if (!recording) {
|
||||||
|
recording = new cRecording(FileName);
|
||||||
|
Add(recording);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cRecordings::DelByName(const char *FileName)
|
||||||
|
{
|
||||||
|
cRecording *recording = GetByName(FileName);
|
||||||
|
if (recording)
|
||||||
|
Del(recording);
|
||||||
|
}
|
||||||
|
|
||||||
// --- cMark -----------------------------------------------------------------
|
// --- cMark -----------------------------------------------------------------
|
||||||
|
|
||||||
char *cMark::buffer = NULL;
|
char *cMark::buffer = NULL;
|
||||||
|
15
recording.h
15
recording.h
@ -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 1.29 2004/05/07 14:24:22 kls Exp $
|
* $Id: recording.h 1.30 2004/06/13 15:37:42 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __RECORDING_H
|
#ifndef __RECORDING_H
|
||||||
@ -69,11 +69,22 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class cRecordings : public cList<cRecording> {
|
class cRecordings : public cList<cRecording> {
|
||||||
|
private:
|
||||||
|
bool deleted;
|
||||||
|
time_t lastUpdate;
|
||||||
|
bool ScanVideoDir(const char *DirName);
|
||||||
public:
|
public:
|
||||||
bool Load(bool Deleted = false);
|
cRecordings(bool Deleted = false);
|
||||||
|
bool Load(void);
|
||||||
|
void TriggerUpdate(void) { lastUpdate = 0; }
|
||||||
|
bool NeedsUpdate(void);
|
||||||
cRecording *GetByName(const char *FileName);
|
cRecording *GetByName(const char *FileName);
|
||||||
|
void AddByName(const char *FileName);
|
||||||
|
void DelByName(const char *FileName);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern cRecordings Recordings;
|
||||||
|
|
||||||
class cMark : public cListObject {
|
class cMark : public cListObject {
|
||||||
private:
|
private:
|
||||||
static char *buffer;
|
static char *buffer;
|
||||||
|
6
svdrp.c
6
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 1.62 2004/03/25 17:00:23 kls Exp $
|
* $Id: svdrp.c 1.63 2004/06/13 13:38:38 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "svdrp.h"
|
#include "svdrp.h"
|
||||||
@ -504,8 +504,10 @@ void cSVDRP::CmdDELR(const char *Option)
|
|||||||
if (isnumber(Option)) {
|
if (isnumber(Option)) {
|
||||||
cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1);
|
cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1);
|
||||||
if (recording) {
|
if (recording) {
|
||||||
if (recording->Delete())
|
if (recording->Delete()) {
|
||||||
Reply(250, "Recording \"%s\" deleted", Option);
|
Reply(250, "Recording \"%s\" deleted", Option);
|
||||||
|
::Recordings.Load(); // must make sure the global recordings list is updated
|
||||||
|
}
|
||||||
else
|
else
|
||||||
Reply(554, "Error while deleting recording!");
|
Reply(554, "Error while deleting recording!");
|
||||||
}
|
}
|
||||||
|
10
tools.c
10
tools.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: tools.c 1.79 2004/05/22 12:13:27 kls Exp $
|
* $Id: tools.c 1.80 2004/06/13 14:36:41 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
@ -481,6 +481,14 @@ bool SpinUpDisk(const char *FileName)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time_t LastModifiedTime(const char *FileName)
|
||||||
|
{
|
||||||
|
struct stat fs;
|
||||||
|
if (stat(FileName, &fs) == 0)
|
||||||
|
return fs.st_mtime;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const char *WeekDayName(int WeekDay)
|
const char *WeekDayName(int WeekDay)
|
||||||
{
|
{
|
||||||
static char buffer[4];
|
static char buffer[4];
|
||||||
|
3
tools.h
3
tools.h
@ -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: tools.h 1.56 2004/05/22 12:11:44 kls Exp $
|
* $Id: tools.h 1.57 2004/06/13 14:13:26 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TOOLS_H
|
#ifndef __TOOLS_H
|
||||||
@ -83,6 +83,7 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
|
|||||||
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false);
|
bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false);
|
||||||
char *ReadLink(const char *FileName);
|
char *ReadLink(const char *FileName);
|
||||||
bool SpinUpDisk(const char *FileName);
|
bool SpinUpDisk(const char *FileName);
|
||||||
|
time_t LastModifiedTime(const char *FileName);
|
||||||
const char *WeekDayName(int WeekDay); ///< \warning returns a statically allocated string!
|
const char *WeekDayName(int WeekDay); ///< \warning returns a statically allocated string!
|
||||||
const char *WeekDayName(time_t t); ///< \warning returns a statically allocated string!
|
const char *WeekDayName(time_t t); ///< \warning returns a statically allocated string!
|
||||||
const char *DayDateTime(time_t t = 0); ///< \warning returns a statically allocated string!
|
const char *DayDateTime(time_t t = 0); ///< \warning returns a statically allocated string!
|
||||||
|
6
vdr.1
6
vdr.1
@ -8,7 +8,7 @@
|
|||||||
.\" License as specified in the file COPYING that comes with the
|
.\" License as specified in the file COPYING that comes with the
|
||||||
.\" vdr distribution.
|
.\" vdr distribution.
|
||||||
.\"
|
.\"
|
||||||
.\" $Id: vdr.1 1.10 2004/05/16 12:10:52 kls Exp $
|
.\" $Id: vdr.1 1.11 2004/06/13 14:48:03 kls Exp $
|
||||||
.\"
|
.\"
|
||||||
.TH vdr 1 "1 June 2003" "1.2.0" "Video Disk Recorder"
|
.TH vdr 1 "1 June 2003" "1.2.0" "Video Disk Recorder"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
@ -176,6 +176,10 @@ The actual data files of a recording.
|
|||||||
.I epg.data
|
.I epg.data
|
||||||
Contains all current EPG data. Can be used for external processing and will
|
Contains all current EPG data. Can be used for external processing and will
|
||||||
also be read at program startup to have the full EPG data available immediately.
|
also be read at program startup to have the full EPG data available immediately.
|
||||||
|
.TP
|
||||||
|
.I .update
|
||||||
|
If this file is present in the video directory, its last modification time will
|
||||||
|
be used to trigger an update of the list of recordings in the "Recordings" menu.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR vdr (5)
|
.BR vdr (5)
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
|
8
vdr.c
8
vdr.c
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
* The project's page is at http://www.cadsoft.de/vdr
|
* The project's page is at http://www.cadsoft.de/vdr
|
||||||
*
|
*
|
||||||
* $Id: vdr.c 1.183 2004/06/12 10:07:17 kls Exp $
|
* $Id: vdr.c 1.184 2004/06/13 13:52:09 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -475,6 +475,10 @@ int main(int argc, char *argv[])
|
|||||||
else
|
else
|
||||||
cDevice::PrimaryDevice()->SetVolume(Setup.CurrentVolume, true);
|
cDevice::PrimaryDevice()->SetVolume(Setup.CurrentVolume, true);
|
||||||
|
|
||||||
|
// Recordings:
|
||||||
|
|
||||||
|
Recordings.Load();
|
||||||
|
|
||||||
// Signal handlers:
|
// Signal handlers:
|
||||||
|
|
||||||
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
|
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
|
||||||
@ -606,6 +610,8 @@ int main(int argc, char *argv[])
|
|||||||
TimerInVpsMargin = true;
|
TimerInVpsMargin = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!Menu && Recordings.NeedsUpdate())
|
||||||
|
Recordings.Load();
|
||||||
// CAM control:
|
// CAM control:
|
||||||
if (!Menu && !cOsd::IsOpen())
|
if (!Menu && !cOsd::IsOpen())
|
||||||
Menu = CamControl();
|
Menu = CamControl();
|
||||||
|
Loading…
Reference in New Issue
Block a user