mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Removed the code for distributing recordings over several video directories; added the cVideoDirectory plugin API
This commit is contained in:
parent
209b850067
commit
3971cc6e88
23
HISTORY
23
HISTORY
@ -7943,3 +7943,26 @@ Video Disk Recorder Revision History
|
|||||||
respectively, during replay (reported by Thomas Maass).
|
respectively, during replay (reported by Thomas Maass).
|
||||||
- The Yellow button in the main menu no longer acts as "Pause" if "Pause key handling"
|
- The Yellow button in the main menu no longer acts as "Pause" if "Pause key handling"
|
||||||
is set to "do not pause live video" (suggested by Ulf Kiener).
|
is set to "do not pause live video" (suggested by Ulf Kiener).
|
||||||
|
- The code for distributing recordings over several video directories has been
|
||||||
|
removed. VDR now by default assumes that the video directory is one big disk.
|
||||||
|
If you absolutely need to use several separate disks to store recordings, you can
|
||||||
|
write a plugin that uses the new cVideoDirectory API to implement the necessary
|
||||||
|
functionality (see PLUGINS.html, section "The video directory"). You can copy the
|
||||||
|
respective code from previous versions of videodir.c.
|
||||||
|
IMPORTANT NOTE: If you write a plugin that implements a distributed video directory,
|
||||||
|
=============== be sure to make cVideoDirectory::Rename() follow symbolic links!
|
||||||
|
This functionality was never implemented in VDR and it therefore
|
||||||
|
used a workaround in cutter.c. See the section marked with
|
||||||
|
// XXX this can be removed once RenameVideoFile() follows symlinks
|
||||||
|
in previous versions of cutter.c.
|
||||||
|
+ CloseVideoFile() is obsolete and has been removed.
|
||||||
|
+ The functions OpenVideoFile(), RenameVideoFile(), RemoveVideoFile(), VideoFileSpaceAvailable(),
|
||||||
|
VideoDiskSpace(), RemoveEmptyVideoDirectories(), IsOnVideoDirectoryFileSystem() and
|
||||||
|
PrefixVideoFileName() are now static members of cVideoDirectory and need to be called
|
||||||
|
with the proper prefix.
|
||||||
|
+ The name of the video directory is now available through cVideoDirectory::Name().
|
||||||
|
The former global variable VideoDirectory is still there for backwards compatibility,
|
||||||
|
but will be removed in a future version. Comment out the line
|
||||||
|
#define DEPRECATED_VIDEODIR
|
||||||
|
in videodir.h and recompile your plugins to see whether your code will work without
|
||||||
|
this variable. If you get a compile error, replace it with cVideoDirectory::Name().
|
||||||
|
37
PLUGINS.html
37
PLUGINS.html
@ -104,6 +104,7 @@ structures and allows it to hook itself into specific areas to perform special a
|
|||||||
<li><a href="#Remote Control">Remote Control</a>
|
<li><a href="#Remote Control">Remote Control</a>
|
||||||
<li><a href="#Conditional Access">Conditional Access</a>
|
<li><a href="#Conditional Access">Conditional Access</a>
|
||||||
<li><a href="#Electronic Program Guide">Electronic Program Guide</a>
|
<li><a href="#Electronic Program Guide">Electronic Program Guide</a>
|
||||||
|
<li><modified><a href="#The video directory">The video directory</a></modified>
|
||||||
</ul>
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -2300,5 +2301,41 @@ to signal VDR that no other EPG handlers shall be queried after this one.
|
|||||||
<p>
|
<p>
|
||||||
See <tt>VDR/epg.h</tt> for details.
|
See <tt>VDR/epg.h</tt> for details.
|
||||||
|
|
||||||
|
<div class="modified">
|
||||||
|
<hr><h2><a name="The video directory">The video directory</a></h2>
|
||||||
|
|
||||||
|
<div class="blurb">Bits and pieces...</div><p>
|
||||||
|
|
||||||
|
By default VDR assumes that the video directory consists of one large
|
||||||
|
volume, on which it can store its recordings. If you want to distribute your
|
||||||
|
recordings over several physical drives, you can derive from <tt>cVideoDirectory</tt>,
|
||||||
|
as in
|
||||||
|
|
||||||
|
<p><table><tr><td class="code"><pre>
|
||||||
|
#include <vdr/videodir.h>
|
||||||
|
|
||||||
|
class cMyVideoDirectory : public cVideoDirectory {
|
||||||
|
public:
|
||||||
|
cMyVideoDirectory(void);
|
||||||
|
virtual ~cMyVideoDirectory();
|
||||||
|
virtual int FreeMB(int *UsedMB = NULL);
|
||||||
|
virtual bool Register(const char *FileName);
|
||||||
|
virtual bool Rename(const char *OldName, const char *NewName);
|
||||||
|
virtual bool Move(const char *FromName, const char *ToName);
|
||||||
|
virtual bool Remove(const char *Name);
|
||||||
|
virtual void Cleanup(const char *IgnoreFiles[] = NULL);
|
||||||
|
virtual bool Contains(const char *Name);
|
||||||
|
};
|
||||||
|
</pre></td></tr></table><p>
|
||||||
|
|
||||||
|
See the description in <tt>videodir.h</tt> for details.
|
||||||
|
<p>
|
||||||
|
You should create your derived video directory object in the
|
||||||
|
<a href="#Getting started"><tt>Start()</tt></a> function of your plugin.
|
||||||
|
Note that the object has to be created on the heap (using <tt>new</tt>),
|
||||||
|
and you shall not delete it at any point (it will be deleted automatically
|
||||||
|
when the program ends).
|
||||||
|
</div modified>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
18
cutter.c
18
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 3.2 2013/08/21 13:15:24 kls Exp $
|
* $Id: cutter.c 3.3 2013/09/10 14:51:45 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cutter.h"
|
#include "cutter.h"
|
||||||
@ -664,19 +664,7 @@ bool cCutter::Start(const char *FileName)
|
|||||||
Recording.SetStartTime(Recording.Start() + (int(First->Position() / Recording.FramesPerSecond() + 30) / 60) * 60);
|
Recording.SetStartTime(Recording.Start() + (int(First->Position() / Recording.FramesPerSecond() + 30) / 60) * 60);
|
||||||
|
|
||||||
const char *evn = Recording.PrefixFileName('%');
|
const char *evn = Recording.PrefixFileName('%');
|
||||||
if (evn && RemoveVideoFile(evn) && MakeDirs(evn, true)) {
|
if (evn && cVideoDirectory::RemoveVideoFile(evn) && MakeDirs(evn, true)) {
|
||||||
// XXX this can be removed once RenameVideoFile() follows symlinks (see videodir.c)
|
|
||||||
// remove a possible deleted recording with the same name to avoid symlink mixups:
|
|
||||||
char *s = strdup(evn);
|
|
||||||
char *e = strrchr(s, '.');
|
|
||||||
if (e) {
|
|
||||||
if (strcmp(e, ".rec") == 0) {
|
|
||||||
strcpy(e, ".del");
|
|
||||||
RemoveVideoFile(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(s);
|
|
||||||
// XXX
|
|
||||||
editedVersionName = evn;
|
editedVersionName = evn;
|
||||||
Recording.WriteInfo();
|
Recording.WriteInfo();
|
||||||
Recordings.AddByName(editedVersionName, false);
|
Recordings.AddByName(editedVersionName, false);
|
||||||
@ -701,7 +689,7 @@ void cCutter::Stop(void)
|
|||||||
esyslog("ERROR: '%s' during editing process", Error);
|
esyslog("ERROR: '%s' during editing process", Error);
|
||||||
if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), editedVersionName) == 0)
|
if (cReplayControl::NowReplaying() && strcmp(cReplayControl::NowReplaying(), editedVersionName) == 0)
|
||||||
cControl::Shutdown();
|
cControl::Shutdown();
|
||||||
RemoveVideoFile(editedVersionName);
|
cVideoDirectory::RemoveVideoFile(editedVersionName);
|
||||||
Recordings.DelByName(editedVersionName);
|
Recordings.DelByName(editedVersionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
menu.c
6
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 3.5 2013/09/07 12:43:26 kls Exp $
|
* $Id: menu.c 3.6 2013/09/10 13:16:40 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -2316,7 +2316,7 @@ void cMenuRecordings::Set(bool Refresh)
|
|||||||
|
|
||||||
cString cMenuRecordings::DirectoryName(void)
|
cString cMenuRecordings::DirectoryName(void)
|
||||||
{
|
{
|
||||||
cString d(VideoDirectory);
|
cString d(cVideoDirectory::Name());
|
||||||
if (base) {
|
if (base) {
|
||||||
char *s = ExchangeChars(strdup(base), true);
|
char *s = ExchangeChars(strdup(base), true);
|
||||||
d = AddDirectory(d, s);
|
d = AddDirectory(d, s);
|
||||||
@ -4342,7 +4342,7 @@ bool cRecordControls::Start(cTimer *Timer, bool Pause)
|
|||||||
AssertFreeDiskSpace(Timer->Priority(), !Timer->Pending());
|
AssertFreeDiskSpace(Timer->Priority(), !Timer->Pending());
|
||||||
Timer->SetPending(true);
|
Timer->SetPending(true);
|
||||||
}
|
}
|
||||||
VideoDiskSpace(&FreeMB);
|
cVideoDirectory::VideoDiskSpace(&FreeMB);
|
||||||
if (FreeMB < MINFREEDISK) {
|
if (FreeMB < MINFREEDISK) {
|
||||||
if (!Timer || time(NULL) - LastNoDiskSpaceMessage > NODISKSPACEDELTA) {
|
if (!Timer || time(NULL) - LastNoDiskSpaceMessage > NODISKSPACEDELTA) {
|
||||||
isyslog("not enough disk space to start recording%s%s", Timer ? " timer " : "", Timer ? *Timer->ToDescr() : "");
|
isyslog("not enough disk space to start recording%s%s", Timer ? " timer " : "", Timer ? *Timer->ToDescr() : "");
|
||||||
|
41
recording.c
41
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 3.2 2013/08/21 13:56:33 kls Exp $
|
* $Id: recording.c 3.3 2013/09/11 08:28:27 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
@ -90,7 +90,7 @@ cRemoveDeletedRecordingsThread::cRemoveDeletedRecordingsThread(void)
|
|||||||
void cRemoveDeletedRecordingsThread::Action(void)
|
void cRemoveDeletedRecordingsThread::Action(void)
|
||||||
{
|
{
|
||||||
// Make sure only one instance of VDR does this:
|
// Make sure only one instance of VDR does this:
|
||||||
cLockFile LockFile(VideoDirectory);
|
cLockFile LockFile(cVideoDirectory::Name());
|
||||||
if (LockFile.Lock()) {
|
if (LockFile.Lock()) {
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
cThreadLock DeletedRecordingsLock(&DeletedRecordings);
|
cThreadLock DeletedRecordingsLock(&DeletedRecordings);
|
||||||
@ -109,7 +109,7 @@ void cRemoveDeletedRecordingsThread::Action(void)
|
|||||||
}
|
}
|
||||||
if (deleted) {
|
if (deleted) {
|
||||||
const char *IgnoreFiles[] = { SORTMODEFILE, NULL };
|
const char *IgnoreFiles[] = { SORTMODEFILE, NULL };
|
||||||
RemoveEmptyVideoDirectories(IgnoreFiles);
|
cVideoDirectory::RemoveEmptyVideoDirectories(IgnoreFiles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,9 +145,9 @@ void AssertFreeDiskSpace(int Priority, bool Force)
|
|||||||
static time_t LastFreeDiskCheck = 0;
|
static time_t LastFreeDiskCheck = 0;
|
||||||
int Factor = (Priority == -1) ? 10 : 1;
|
int Factor = (Priority == -1) ? 10 : 1;
|
||||||
if (Force || time(NULL) - LastFreeDiskCheck > DISKCHECKDELTA / Factor) {
|
if (Force || time(NULL) - LastFreeDiskCheck > DISKCHECKDELTA / Factor) {
|
||||||
if (!VideoFileSpaceAvailable(MINDISKSPACE)) {
|
if (!cVideoDirectory::VideoFileSpaceAvailable(MINDISKSPACE)) {
|
||||||
// Make sure only one instance of VDR does this:
|
// Make sure only one instance of VDR does this:
|
||||||
cLockFile LockFile(VideoDirectory);
|
cLockFile LockFile(cVideoDirectory::Name());
|
||||||
if (!LockFile.Lock())
|
if (!LockFile.Lock())
|
||||||
return;
|
return;
|
||||||
// Remove the oldest file that has been "deleted":
|
// Remove the oldest file that has been "deleted":
|
||||||
@ -800,8 +800,8 @@ cRecording::cRecording(const char *FileName)
|
|||||||
FileName = fileName = strdup(FileName);
|
FileName = fileName = strdup(FileName);
|
||||||
if (*(fileName + strlen(fileName) - 1) == '/')
|
if (*(fileName + strlen(fileName) - 1) == '/')
|
||||||
*(fileName + strlen(fileName) - 1) = 0;
|
*(fileName + strlen(fileName) - 1) = 0;
|
||||||
if (strstr(FileName, VideoDirectory) == FileName)
|
if (strstr(FileName, cVideoDirectory::Name()) == FileName)
|
||||||
FileName += strlen(VideoDirectory) + 1;
|
FileName += strlen(cVideoDirectory::Name()) + 1;
|
||||||
const char *p = strrchr(FileName, '/');
|
const char *p = strrchr(FileName, '/');
|
||||||
|
|
||||||
name = NULL;
|
name = NULL;
|
||||||
@ -949,7 +949,7 @@ char *cRecording::SortName(void) const
|
|||||||
{
|
{
|
||||||
char **sb = (RecordingsSortMode == rsmName) ? &sortBufferName : &sortBufferTime;
|
char **sb = (RecordingsSortMode == rsmName) ? &sortBufferName : &sortBufferTime;
|
||||||
if (!*sb) {
|
if (!*sb) {
|
||||||
char *s = strdup(FileName() + strlen(VideoDirectory));
|
char *s = strdup(FileName() + strlen(cVideoDirectory::Name()));
|
||||||
if (RecordingsSortMode != rsmName || Setup.AlwaysSortFoldersFirst)
|
if (RecordingsSortMode != rsmName || Setup.AlwaysSortFoldersFirst)
|
||||||
s = StripEpisodeName(s, RecordingsSortMode != rsmName);
|
s = StripEpisodeName(s, RecordingsSortMode != rsmName);
|
||||||
strreplace(s, '/', '0'); // some locales ignore '/' when sorting
|
strreplace(s, '/', '0'); // some locales ignore '/' when sorting
|
||||||
@ -990,11 +990,11 @@ const char *cRecording::FileName(void) const
|
|||||||
const char *fmt = isPesRecording ? NAMEFORMATPES : NAMEFORMATTS;
|
const char *fmt = isPesRecording ? NAMEFORMATPES : NAMEFORMATTS;
|
||||||
int ch = isPesRecording ? priority : channel;
|
int ch = isPesRecording ? priority : channel;
|
||||||
int ri = isPesRecording ? lifetime : instanceId;
|
int ri = isPesRecording ? lifetime : instanceId;
|
||||||
char *Name = LimitNameLengths(strdup(name), DirectoryPathMax - strlen(VideoDirectory) - 1 - 42, DirectoryNameMax); // 42 = length of an actual recording directory name (generated with DATAFORMATTS) plus some reserve
|
char *Name = LimitNameLengths(strdup(name), DirectoryPathMax - strlen(cVideoDirectory::Name()) - 1 - 42, DirectoryNameMax); // 42 = length of an actual recording directory name (generated with DATAFORMATTS) plus some reserve
|
||||||
if (strcmp(Name, name) != 0)
|
if (strcmp(Name, name) != 0)
|
||||||
dsyslog("recording file name '%s' truncated to '%s'", name, Name);
|
dsyslog("recording file name '%s' truncated to '%s'", name, Name);
|
||||||
Name = ExchangeChars(Name, true);
|
Name = ExchangeChars(Name, true);
|
||||||
fileName = strdup(cString::sprintf(fmt, VideoDirectory, Name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, ch, ri));
|
fileName = strdup(cString::sprintf(fmt, cVideoDirectory::Name(), Name, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, ch, ri));
|
||||||
free(Name);
|
free(Name);
|
||||||
}
|
}
|
||||||
return fileName;
|
return fileName;
|
||||||
@ -1063,7 +1063,7 @@ const char *cRecording::Title(char Delimiter, bool NewIndicator, int Level) cons
|
|||||||
|
|
||||||
const char *cRecording::PrefixFileName(char Prefix)
|
const char *cRecording::PrefixFileName(char Prefix)
|
||||||
{
|
{
|
||||||
cString p = PrefixVideoFileName(FileName(), Prefix);
|
cString p = cVideoDirectory::PrefixVideoFileName(FileName(), Prefix);
|
||||||
if (*p) {
|
if (*p) {
|
||||||
free(fileName);
|
free(fileName);
|
||||||
fileName = strdup(p);
|
fileName = strdup(p);
|
||||||
@ -1093,7 +1093,7 @@ bool cRecording::IsEdited(void) const
|
|||||||
bool cRecording::IsOnVideoDirectoryFileSystem(void) const
|
bool cRecording::IsOnVideoDirectoryFileSystem(void) const
|
||||||
{
|
{
|
||||||
if (isOnVideoDirectoryFileSystem < 0)
|
if (isOnVideoDirectoryFileSystem < 0)
|
||||||
isOnVideoDirectoryFileSystem = ::IsOnVideoDirectoryFileSystem(FileName());
|
isOnVideoDirectoryFileSystem = cVideoDirectory::IsOnVideoDirectoryFileSystem(FileName());
|
||||||
return isOnVideoDirectoryFileSystem;
|
return isOnVideoDirectoryFileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1135,11 +1135,11 @@ bool cRecording::Delete(void)
|
|||||||
if (access(NewName, F_OK) == 0) {
|
if (access(NewName, F_OK) == 0) {
|
||||||
// the new name already exists, so let's remove that one first:
|
// the new name already exists, so let's remove that one first:
|
||||||
isyslog("removing recording '%s'", NewName);
|
isyslog("removing recording '%s'", NewName);
|
||||||
RemoveVideoFile(NewName);
|
cVideoDirectory::RemoveVideoFile(NewName);
|
||||||
}
|
}
|
||||||
isyslog("deleting recording '%s'", FileName());
|
isyslog("deleting recording '%s'", FileName());
|
||||||
if (access(FileName(), F_OK) == 0) {
|
if (access(FileName(), F_OK) == 0) {
|
||||||
result = RenameVideoFile(FileName(), NewName);
|
result = cVideoDirectory::RenameVideoFile(FileName(), NewName);
|
||||||
cRecordingUserCommand::InvokeCommand(RUC_DELETERECORDING, NewName);
|
cRecordingUserCommand::InvokeCommand(RUC_DELETERECORDING, NewName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1159,7 +1159,7 @@ bool cRecording::Remove(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
isyslog("removing recording %s", FileName());
|
isyslog("removing recording %s", FileName());
|
||||||
return RemoveVideoFile(FileName());
|
return cVideoDirectory::RemoveVideoFile(FileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cRecording::Undelete(void)
|
bool cRecording::Undelete(void)
|
||||||
@ -1177,7 +1177,7 @@ bool cRecording::Undelete(void)
|
|||||||
else {
|
else {
|
||||||
isyslog("undeleting recording '%s'", FileName());
|
isyslog("undeleting recording '%s'", FileName());
|
||||||
if (access(FileName(), F_OK) == 0)
|
if (access(FileName(), F_OK) == 0)
|
||||||
result = RenameVideoFile(FileName(), NewName);
|
result = cVideoDirectory::RenameVideoFile(FileName(), NewName);
|
||||||
else {
|
else {
|
||||||
isyslog("deleted recording '%s' vanished", FileName());
|
isyslog("deleted recording '%s' vanished", FileName());
|
||||||
result = false;
|
result = false;
|
||||||
@ -1250,7 +1250,7 @@ void cRecordings::Action(void)
|
|||||||
const char *cRecordings::UpdateFileName(void)
|
const char *cRecordings::UpdateFileName(void)
|
||||||
{
|
{
|
||||||
if (!updateFileName)
|
if (!updateFileName)
|
||||||
updateFileName = strdup(AddDirectory(VideoDirectory, ".update"));
|
updateFileName = strdup(AddDirectory(cVideoDirectory::Name(), ".update"));
|
||||||
return updateFileName;
|
return updateFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1261,7 +1261,7 @@ void cRecordings::Refresh(bool Foreground)
|
|||||||
Clear();
|
Clear();
|
||||||
ChangeState();
|
ChangeState();
|
||||||
Unlock();
|
Unlock();
|
||||||
ScanVideoDir(VideoDirectory, Foreground);
|
ScanVideoDir(cVideoDirectory::Name(), Foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLevel)
|
void cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLevel)
|
||||||
@ -2274,7 +2274,7 @@ cUnbufferedFile *cFileName::Open(void)
|
|||||||
int BlockingFlag = blocking ? 0 : O_NONBLOCK;
|
int BlockingFlag = blocking ? 0 : O_NONBLOCK;
|
||||||
if (record) {
|
if (record) {
|
||||||
dsyslog("recording to '%s'", fileName);
|
dsyslog("recording to '%s'", fileName);
|
||||||
file = OpenVideoFile(fileName, O_RDWR | O_CREAT | O_LARGEFILE | BlockingFlag);
|
file = cVideoDirectory::OpenVideoFile(fileName, O_RDWR | O_CREAT | O_LARGEFILE | BlockingFlag);
|
||||||
if (!file)
|
if (!file)
|
||||||
LOG_ERROR_STR(fileName);
|
LOG_ERROR_STR(fileName);
|
||||||
}
|
}
|
||||||
@ -2295,8 +2295,9 @@ cUnbufferedFile *cFileName::Open(void)
|
|||||||
void cFileName::Close(void)
|
void cFileName::Close(void)
|
||||||
{
|
{
|
||||||
if (file) {
|
if (file) {
|
||||||
if (CloseVideoFile(file) < 0)
|
if (file->Close() < 0)
|
||||||
LOG_ERROR_STR(fileName);
|
LOG_ERROR_STR(fileName);
|
||||||
|
delete file;
|
||||||
file = NULL;
|
file = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
svdrp.c
4
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 2.24 2013/02/17 13:18:01 kls Exp $
|
* $Id: svdrp.c 3.1 2013/09/10 13:21:38 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "svdrp.h"
|
#include "svdrp.h"
|
||||||
@ -1550,7 +1550,7 @@ void cSVDRP::CmdSTAT(const char *Option)
|
|||||||
if (*Option) {
|
if (*Option) {
|
||||||
if (strcasecmp(Option, "DISK") == 0) {
|
if (strcasecmp(Option, "DISK") == 0) {
|
||||||
int FreeMB, UsedMB;
|
int FreeMB, UsedMB;
|
||||||
int Percent = VideoDiskSpace(&FreeMB, &UsedMB);
|
int Percent = cVideoDirectory::VideoDiskSpace(&FreeMB, &UsedMB);
|
||||||
Reply(250, "%dMB %dMB %d%%", FreeMB + UsedMB, FreeMB, Percent);
|
Reply(250, "%dMB %dMB %d%%", FreeMB + UsedMB, FreeMB, Percent);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
5
vdr.c
5
vdr.c
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
* The project's page is at http://www.tvdr.de
|
* The project's page is at http://www.tvdr.de
|
||||||
*
|
*
|
||||||
* $Id: vdr.c 3.1 2013/06/10 14:28:43 kls Exp $
|
* $Id: vdr.c 3.2 2013/09/10 13:58:34 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -663,7 +663,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// Directories:
|
// Directories:
|
||||||
|
|
||||||
SetVideoDirectory(VideoDirectory);
|
cVideoDirectory::SetName(VideoDirectory);
|
||||||
if (!ConfigDirectory)
|
if (!ConfigDirectory)
|
||||||
ConfigDirectory = DEFAULTCONFDIR;
|
ConfigDirectory = DEFAULTCONFDIR;
|
||||||
cPlugin::SetConfigDirectory(ConfigDirectory);
|
cPlugin::SetConfigDirectory(ConfigDirectory);
|
||||||
@ -1406,6 +1406,7 @@ Exit:
|
|||||||
}
|
}
|
||||||
cDevice::Shutdown();
|
cDevice::Shutdown();
|
||||||
cPositioner::DestroyPositioner();
|
cPositioner::DestroyPositioner();
|
||||||
|
cVideoDirectory::Destroy();
|
||||||
EpgHandlers.Clear();
|
EpgHandlers.Clear();
|
||||||
PluginManager.Shutdown(true);
|
PluginManager.Shutdown(true);
|
||||||
cSchedules::Cleanup(true);
|
cSchedules::Cleanup(true);
|
||||||
|
290
videodir.c
290
videodir.c
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* videodir.c: Functions to maintain a distributed video directory
|
* videodir.c: Functions to maintain the video directory
|
||||||
*
|
*
|
||||||
* 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: videodir.c 3.1 2013/08/23 12:28:06 kls Exp $
|
* $Id: videodir.c 3.2 2013/09/11 12:20:37 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "videodir.h"
|
#include "videodir.h"
|
||||||
@ -19,213 +19,129 @@
|
|||||||
#include "recording.h"
|
#include "recording.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
//#define DEPRECATED_DISTRIBUTED_VIDEODIR // Code enclosed with this macro is deprecated and will be removed in a future version
|
#ifdef DEPRECATED_VIDEODIR
|
||||||
|
|
||||||
const char *VideoDirectory = VIDEODIR;
|
const char *VideoDirectory = VIDEODIR;
|
||||||
|
|
||||||
void SetVideoDirectory(const char *Directory)
|
|
||||||
{
|
|
||||||
VideoDirectory = strdup(Directory);
|
|
||||||
}
|
|
||||||
|
|
||||||
class cVideoDirectory {
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
private:
|
|
||||||
char *name, *stored, *adjusted;
|
|
||||||
int length, number, digits;
|
|
||||||
#endif
|
#endif
|
||||||
public:
|
cString cVideoDirectory::name;
|
||||||
cVideoDirectory(void);
|
cVideoDirectory *cVideoDirectory::current = NULL;
|
||||||
~cVideoDirectory();
|
|
||||||
int FreeMB(int *UsedMB = NULL);
|
|
||||||
const char *Name(void) { return
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
name ? name :
|
|
||||||
#endif
|
|
||||||
VideoDirectory; }
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
const char *Stored(void) { return stored; }
|
|
||||||
int Length(void) { return length; }
|
|
||||||
bool IsDistributed(void) { return name != NULL; }
|
|
||||||
bool Next(void);
|
|
||||||
void Store(void);
|
|
||||||
const char *Adjust(const char *FileName);
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
cVideoDirectory::cVideoDirectory(void)
|
cVideoDirectory::cVideoDirectory(void)
|
||||||
{
|
{
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
delete current;
|
||||||
length = strlen(VideoDirectory);
|
current = this;
|
||||||
name = (VideoDirectory[length - 1] == '0') ? strdup(VideoDirectory) : NULL;
|
|
||||||
stored = adjusted = NULL;
|
|
||||||
number = -1;
|
|
||||||
digits = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cVideoDirectory::~cVideoDirectory()
|
cVideoDirectory::~cVideoDirectory()
|
||||||
{
|
{
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
current = NULL;
|
||||||
free(name);
|
}
|
||||||
free(stored);
|
|
||||||
free(adjusted);
|
cVideoDirectory *cVideoDirectory::Current(void)
|
||||||
#endif
|
{
|
||||||
|
if (!current)
|
||||||
|
current = new cVideoDirectory;
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideoDirectory::Destroy(void)
|
||||||
|
{
|
||||||
|
delete current;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideoDirectory::FreeMB(int *UsedMB)
|
int cVideoDirectory::FreeMB(int *UsedMB)
|
||||||
{
|
{
|
||||||
return FreeDiskSpaceMB(
|
return FreeDiskSpaceMB(Name(), UsedMB);
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
}
|
||||||
name ? name :
|
|
||||||
|
const char *cVideoDirectory::Name(void)
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideoDirectory::SetName(const char *Name)
|
||||||
|
{
|
||||||
|
name = Name;
|
||||||
|
#ifdef DEPRECATED_VIDEODIR
|
||||||
|
VideoDirectory = Name;
|
||||||
#endif
|
#endif
|
||||||
VideoDirectory, UsedMB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
bool cVideoDirectory::Register(const char *FileName)
|
||||||
bool cVideoDirectory::Next(void)
|
|
||||||
{
|
{
|
||||||
if (name) {
|
|
||||||
if (number < 0) {
|
|
||||||
int l = length;
|
|
||||||
while (l-- > 0 && isdigit(name[l]))
|
|
||||||
;
|
|
||||||
l++;
|
|
||||||
digits = length - l;
|
|
||||||
int n = atoi(&name[l]);
|
|
||||||
if (n == 0)
|
|
||||||
number = n;
|
|
||||||
else
|
|
||||||
return false; // base video directory must end with zero
|
|
||||||
}
|
|
||||||
if (++number > 0) {
|
|
||||||
char buf[16];
|
|
||||||
if (sprintf(buf, "%0*d", digits, number) == digits) {
|
|
||||||
strcpy(&name[length - digits], buf);
|
|
||||||
return DirectoryOk(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cVideoDirectory::Store(void)
|
|
||||||
{
|
|
||||||
if (name) {
|
|
||||||
free(stored);
|
|
||||||
stored = strdup(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *cVideoDirectory::Adjust(const char *FileName)
|
|
||||||
{
|
|
||||||
if (stored) {
|
|
||||||
free(adjusted);
|
|
||||||
adjusted = strdup(FileName);
|
|
||||||
return strncpy(adjusted, stored, length);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags)
|
|
||||||
{
|
|
||||||
const char *ActualFileName = FileName;
|
|
||||||
|
|
||||||
// Incoming name must be in base video directory:
|
// Incoming name must be in base video directory:
|
||||||
if (strstr(FileName, VideoDirectory) != FileName) {
|
if (strstr(FileName, Name()) != FileName) {
|
||||||
esyslog("ERROR: %s not in %s", FileName, VideoDirectory);
|
esyslog("ERROR: %s not in %s", FileName, Name());
|
||||||
errno = ENOENT; // must set 'errno' - any ideas for a better value?
|
errno = ENOENT; // must set 'errno' - any ideas for a better value?
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
return true;
|
||||||
// Are we going to create a new file?
|
|
||||||
if ((Flags & O_CREAT) != 0) {
|
|
||||||
cVideoDirectory Dir;
|
|
||||||
if (Dir.IsDistributed()) {
|
|
||||||
// Find the directory with the most free space:
|
|
||||||
int MaxFree = Dir.FreeMB();
|
|
||||||
while (Dir.Next()) {
|
|
||||||
int Free = FreeDiskSpaceMB(Dir.Name());
|
|
||||||
if (Free > MaxFree) {
|
|
||||||
Dir.Store();
|
|
||||||
MaxFree = Free;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (Dir.Stored()) {
|
|
||||||
ActualFileName = Dir.Adjust(FileName);
|
|
||||||
if (!MakeDirs(ActualFileName, false))
|
|
||||||
return NULL; // errno has been set by MakeDirs()
|
|
||||||
if (symlink(ActualFileName, FileName) < 0) {
|
|
||||||
LOG_ERROR_STR(FileName);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ActualFileName = strdup(ActualFileName); // must survive Dir!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
cUnbufferedFile *File = cUnbufferedFile::Create(ActualFileName, Flags, DEFFILEMODE);
|
|
||||||
if (ActualFileName != FileName)
|
|
||||||
free((char *)ActualFileName);
|
|
||||||
return File;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CloseVideoFile(cUnbufferedFile *File)
|
bool cVideoDirectory::Rename(const char *OldName, const char *NewName)
|
||||||
{
|
{
|
||||||
int Result = File->Close();
|
|
||||||
delete File;
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenameVideoFile(const char *OldName, const char *NewName)
|
|
||||||
{
|
|
||||||
// Only the base video directory entry will be renamed, leaving the
|
|
||||||
// possible symlinks untouched. Going through all the symlinks and disks
|
|
||||||
// would be unnecessary work - maybe later...
|
|
||||||
if (rename(OldName, NewName) == -1) {
|
if (rename(OldName, NewName) == -1) {
|
||||||
LOG_ERROR_STR(OldName);
|
LOG_ERROR_STR(NewName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoveVideoFile(const char *FileName)
|
bool cVideoDirectory::Move(const char *FromName, const char *ToName)
|
||||||
{
|
{
|
||||||
return RemoveFileOrDir(FileName, true);
|
if (rename(FromName, ToName) == -1) {
|
||||||
}
|
LOG_ERROR_STR(ToName);
|
||||||
|
|
||||||
bool VideoFileSpaceAvailable(int SizeMB)
|
|
||||||
{
|
|
||||||
cVideoDirectory Dir;
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
if (Dir.IsDistributed()) {
|
|
||||||
if (Dir.FreeMB() >= SizeMB * 2) // base directory needs additional space
|
|
||||||
return true;
|
|
||||||
while (Dir.Next()) {
|
|
||||||
if (Dir.FreeMB() >= SizeMB)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
return true;
|
||||||
return Dir.FreeMB() >= SizeMB;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int VideoDiskSpace(int *FreeMB, int *UsedMB)
|
bool cVideoDirectory::Remove(const char *Name)
|
||||||
{
|
{
|
||||||
int free = 0, used = 0;
|
return RemoveFileOrDir(Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cVideoDirectory::Cleanup(const char *IgnoreFiles[])
|
||||||
|
{
|
||||||
|
RemoveEmptyDirectories(Name(), false, IgnoreFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cVideoDirectory::Contains(const char *Name)
|
||||||
|
{
|
||||||
|
return EntriesOnSameFileSystem(this->Name(), Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
cUnbufferedFile *cVideoDirectory::OpenVideoFile(const char *FileName, int Flags)
|
||||||
|
{
|
||||||
|
if (Current()->Register(FileName))
|
||||||
|
return cUnbufferedFile::Create(FileName, Flags, DEFFILEMODE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cVideoDirectory::RenameVideoFile(const char *OldName, const char *NewName)
|
||||||
|
{
|
||||||
|
return Current()->Rename(OldName, NewName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cVideoDirectory::MoveVideoFile(const char *FromName, const char *ToName)
|
||||||
|
{
|
||||||
|
return Current()->Move(FromName, ToName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cVideoDirectory::RemoveVideoFile(const char *FileName)
|
||||||
|
{
|
||||||
|
return Current()->Remove(FileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cVideoDirectory::VideoFileSpaceAvailable(int SizeMB)
|
||||||
|
{
|
||||||
|
return Current()->FreeMB() >= SizeMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideoDirectory::VideoDiskSpace(int *FreeMB, int *UsedMB)
|
||||||
|
{
|
||||||
|
int used = 0;
|
||||||
|
int free = Current()->FreeMB(&used);
|
||||||
int deleted = DeletedRecordings.TotalFileSizeMB();
|
int deleted = DeletedRecordings.TotalFileSizeMB();
|
||||||
cVideoDirectory Dir;
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
do {
|
|
||||||
#endif
|
|
||||||
int u;
|
|
||||||
free += Dir.FreeMB(&u);
|
|
||||||
used += u;
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
} while (Dir.Next());
|
|
||||||
#endif
|
|
||||||
if (deleted > used)
|
if (deleted > used)
|
||||||
deleted = used; // let's not get beyond 100%
|
deleted = used; // let's not get beyond 100%
|
||||||
free += deleted;
|
free += deleted;
|
||||||
@ -237,7 +153,7 @@ int VideoDiskSpace(int *FreeMB, int *UsedMB)
|
|||||||
return (free + used) ? used * 100 / (free + used) : 0;
|
return (free + used) ? used * 100 / (free + used) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cString PrefixVideoFileName(const char *FileName, char Prefix)
|
cString cVideoDirectory::PrefixVideoFileName(const char *FileName, char Prefix)
|
||||||
{
|
{
|
||||||
char PrefixedName[strlen(FileName) + 2];
|
char PrefixedName[strlen(FileName) + 2];
|
||||||
|
|
||||||
@ -257,30 +173,14 @@ cString PrefixVideoFileName(const char *FileName, char Prefix)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveEmptyVideoDirectories(const char *IgnoreFiles[])
|
void cVideoDirectory::RemoveEmptyVideoDirectories(const char *IgnoreFiles[])
|
||||||
{
|
{
|
||||||
cVideoDirectory Dir;
|
Current()->Cleanup(IgnoreFiles);
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
do {
|
|
||||||
#endif
|
|
||||||
RemoveEmptyDirectories(Dir.Name(), false, IgnoreFiles);
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
} while (Dir.Next());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsOnVideoDirectoryFileSystem(const char *FileName)
|
bool cVideoDirectory::IsOnVideoDirectoryFileSystem(const char *FileName)
|
||||||
{
|
{
|
||||||
cVideoDirectory Dir;
|
return Current()->Contains(FileName);
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
do {
|
|
||||||
#endif
|
|
||||||
if (EntriesOnSameFileSystem(Dir.Name(), FileName))
|
|
||||||
return true;
|
|
||||||
#ifdef DEPRECATED_DISTRIBUTED_VIDEODIR
|
|
||||||
} while (Dir.Next());
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cVideoDiskUsage -------------------------------------------------------
|
// --- cVideoDiskUsage -------------------------------------------------------
|
||||||
@ -298,7 +198,7 @@ bool cVideoDiskUsage::HasChanged(int &State)
|
|||||||
{
|
{
|
||||||
if (time(NULL) - lastChecked > DISKSPACECHEK) {
|
if (time(NULL) - lastChecked > DISKSPACECHEK) {
|
||||||
int FreeMB;
|
int FreeMB;
|
||||||
int UsedPercent = VideoDiskSpace(&FreeMB);
|
int UsedPercent = cVideoDirectory::VideoDiskSpace(&FreeMB);
|
||||||
if (FreeMB != freeMB) {
|
if (FreeMB != freeMB) {
|
||||||
usedPercent = UsedPercent;
|
usedPercent = UsedPercent;
|
||||||
freeMB = FreeMB;
|
freeMB = FreeMB;
|
||||||
|
86
videodir.h
86
videodir.h
@ -1,10 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* videodir.h: Functions to maintain a distributed video directory
|
* videodir.h: Functions to maintain the video directory
|
||||||
*
|
*
|
||||||
* 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: videodir.h 2.3 2012/09/30 11:01:15 kls Exp $
|
* $Id: videodir.h 3.1 2013/09/11 12:19:47 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __VIDEODIR_H
|
#ifndef __VIDEODIR_H
|
||||||
@ -13,18 +13,80 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
|
#define DEPRECATED_VIDEODIR
|
||||||
|
#ifdef DEPRECATED_VIDEODIR
|
||||||
extern const char *VideoDirectory;
|
extern const char *VideoDirectory;
|
||||||
|
#endif
|
||||||
|
|
||||||
void SetVideoDirectory(const char *Directory);
|
class cVideoDirectory {
|
||||||
cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags);
|
private:
|
||||||
int CloseVideoFile(cUnbufferedFile *File);
|
static cString name;
|
||||||
bool RenameVideoFile(const char *OldName, const char *NewName);
|
static cVideoDirectory *current;
|
||||||
bool RemoveVideoFile(const char *FileName);
|
static cVideoDirectory *Current(void);
|
||||||
bool VideoFileSpaceAvailable(int SizeMB);
|
public:
|
||||||
int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent
|
cVideoDirectory(void);
|
||||||
cString PrefixVideoFileName(const char *FileName, char Prefix);
|
virtual ~cVideoDirectory();
|
||||||
void RemoveEmptyVideoDirectories(const char *IgnoreFiles[] = NULL);
|
virtual int FreeMB(int *UsedMB = NULL);
|
||||||
bool IsOnVideoDirectoryFileSystem(const char *FileName);
|
///< Returns the total amount (in MB) of free disk space for recording.
|
||||||
|
///< If UsedMB is given, it returns the amount of disk space in use by
|
||||||
|
///< existing recordings (or anything else) on that disk.
|
||||||
|
virtual bool Register(const char *FileName);
|
||||||
|
///< By default VDR assumes that the video directory consists of one large
|
||||||
|
///< volume, on which it can store its recordings. A derived cVideoDirectory
|
||||||
|
///< may, for instance, use several separate disks to store recordings.
|
||||||
|
///< The given FileName is the full path name (including the video directory) of
|
||||||
|
///< a recording file ('*.ts') that is about to be opened for writing. If the actual
|
||||||
|
///< file shall be put on an other disk, the derived cVideoDirectory should
|
||||||
|
///< create a symbolic link from the given FileName to the other location.
|
||||||
|
///< Returns true if the operation was successful.
|
||||||
|
///< The default implementation just checks whether the incoming file name really
|
||||||
|
///< is under the video directory.
|
||||||
|
virtual bool Rename(const char *OldName, const char *NewName);
|
||||||
|
///< Renames the directory OldName to NewName.
|
||||||
|
///< OldName and NewName are full path names that begin with the name of the
|
||||||
|
///< video directory and end with '*.rec' or '*.del'. Only the base name (the
|
||||||
|
///< rightmost component) of the two names may be different.
|
||||||
|
///< Returns true if the operation was successful.
|
||||||
|
///< The default implementation just calls the system's rename() function.
|
||||||
|
virtual bool Move(const char *FromName, const char *ToName);
|
||||||
|
///< Moves the directory FromName to the location ToName. FromName is the full
|
||||||
|
///< path name of a recording's '*.rec' directory. ToName has the same '*.rec'
|
||||||
|
///< part as FromName, but a different directory path above it.
|
||||||
|
///< Returns true if the operation was successful.
|
||||||
|
///< The default implementation just calls the system's rename() function.
|
||||||
|
virtual bool Remove(const char *Name);
|
||||||
|
///< Removes the directory with the given Name and everything it contains.
|
||||||
|
///< Name is a full path name that begins with the name of the video directory.
|
||||||
|
///< Returns true if the operation was successful.
|
||||||
|
///< The default implementation calls RemoveFileOrDir().
|
||||||
|
virtual void Cleanup(const char *IgnoreFiles[] = NULL);
|
||||||
|
///< Recursively removes all empty directories under the video directory.
|
||||||
|
///< If IgnoreFiles is given, the file names in this (NULL terminated) array
|
||||||
|
///< are ignored when checking whether a directory is empty. These are
|
||||||
|
///< typically "dot files", like e.g. ".sort".
|
||||||
|
///< The default implementation calls RemoveEmptyDirectories().
|
||||||
|
virtual bool Contains(const char *Name);
|
||||||
|
///< Checks whether the directory Name is on the same file system as the
|
||||||
|
///< video directory. Name is the full path name of a recording's '*.rec'
|
||||||
|
///< directory. This function is usually called when an ongoing recording
|
||||||
|
///< is about to run out of disk space, and an existing (old) recording needs
|
||||||
|
///< to be deleted. It shall make sure that deleting this old recording will
|
||||||
|
///< actually free up space in the video directory, and not on some other
|
||||||
|
///< device that just happens to be mounted.
|
||||||
|
///< The default implementation calls EntriesOnSameFileSystem().
|
||||||
|
static const char *Name(void);
|
||||||
|
static void SetName(const char *Name);
|
||||||
|
static void Destroy(void);
|
||||||
|
static cUnbufferedFile *OpenVideoFile(const char *FileName, int Flags);
|
||||||
|
static bool RenameVideoFile(const char *OldName, const char *NewName);
|
||||||
|
static bool MoveVideoFile(const char *FromName, const char *ToName);
|
||||||
|
static bool RemoveVideoFile(const char *FileName);
|
||||||
|
static bool VideoFileSpaceAvailable(int SizeMB);
|
||||||
|
static int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent
|
||||||
|
static cString PrefixVideoFileName(const char *FileName, char Prefix);
|
||||||
|
static void RemoveEmptyVideoDirectories(const char *IgnoreFiles[] = NULL);
|
||||||
|
static bool IsOnVideoDirectoryFileSystem(const char *FileName);
|
||||||
|
};
|
||||||
|
|
||||||
class cVideoDiskUsage {
|
class cVideoDiskUsage {
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user