summaryrefslogtreecommitdiff
path: root/recording.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2015-09-01 11:14:27 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2015-09-01 11:14:27 +0200
commit3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d (patch)
treeda57ce74189de9bfb27e1a747063c37cd62de501 /recording.c
parent8a7bc6a0bbf60cae8b6391a630880aad5cba3363 (diff)
downloadvdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.gz
vdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.bz2
Implemented strict locking of global lists
Diffstat (limited to 'recording.c')
-rw-r--r--recording.c457
1 files changed, 225 insertions, 232 deletions
diff --git a/recording.c b/recording.c
index a28bb444..3f5cec7c 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.2 2015/04/18 13:14:55 kls Exp $
+ * $Id: recording.c 4.3 2015/08/29 14:42:53 kls Exp $
*/
#include "recording.h"
@@ -76,9 +76,6 @@ int DirectoryNameMax = NAME_MAX;
bool DirectoryEncoding = false;
int InstanceId = 0;
-cRecordings DeletedRecordings(true);
-static cRecordings VanishedRecordings;
-
// --- cRemoveDeletedRecordingsThread ----------------------------------------
class cRemoveDeletedRecordingsThread : public cThread {
@@ -100,8 +97,8 @@ void cRemoveDeletedRecordingsThread::Action(void)
if (LockFile.Lock()) {
time_t StartTime = time(NULL);
bool deleted = false;
- cThreadLock DeletedRecordingsLock(&DeletedRecordings);
- for (cRecording *r = DeletedRecordings.First(); r; ) {
+ LOCK_DELETEDRECORDINGS_WRITE;
+ for (cRecording *r = DeletedRecordings->First(); r; ) {
if (cIoThrottle::Engaged())
return;
if (time(NULL) - StartTime > MAXREMOVETIME)
@@ -109,14 +106,14 @@ void cRemoveDeletedRecordingsThread::Action(void)
if (cRemote::HasKeys())
return; // react immediately on user input
if (r->Deleted() && time(NULL) - r->Deleted() > DELETEDLIFETIME) {
- cRecording *next = DeletedRecordings.Next(r);
+ cRecording *next = DeletedRecordings->Next(r);
r->Remove();
- DeletedRecordings.Del(r);
+ DeletedRecordings->Del(r);
r = next;
deleted = true;
continue;
}
- r = DeletedRecordings.Next(r);
+ r = DeletedRecordings->Next(r);
}
if (deleted) {
const char *IgnoreFiles[] = { SORTMODEFILE, NULL };
@@ -134,8 +131,8 @@ void RemoveDeletedRecordings(void)
static time_t LastRemoveCheck = 0;
if (time(NULL) - LastRemoveCheck > REMOVECHECKDELTA) {
if (!RemoveDeletedRecordingsThread.Active()) {
- cThreadLock DeletedRecordingsLock(&DeletedRecordings);
- for (cRecording *r = DeletedRecordings.First(); r; r = DeletedRecordings.Next(r)) {
+ LOCK_DELETEDRECORDINGS_READ;
+ for (const cRecording *r = DeletedRecordings->First(); r; r = DeletedRecordings->Next(r)) {
if (r->Deleted() && time(NULL) - r->Deleted() > DELETEDLIFETIME) {
RemoveDeletedRecordingsThread.Start();
break;
@@ -163,37 +160,43 @@ void AssertFreeDiskSpace(int Priority, bool Force)
return;
// Remove the oldest file that has been "deleted":
isyslog("low disk space while recording, trying to remove a deleted recording...");
- cThreadLock DeletedRecordingsLock(&DeletedRecordings);
- if (DeletedRecordings.Count()) {
- cRecording *r = DeletedRecordings.First();
- cRecording *r0 = NULL;
- while (r) {
- if (r->IsOnVideoDirectoryFileSystem()) { // only remove recordings that will actually increase the free video disk space
- if (!r0 || r->Start() < r0->Start())
- r0 = r;
- }
- r = DeletedRecordings.Next(r);
- }
- if (r0) {
- if (r0->Remove())
- LastFreeDiskCheck += REMOVELATENCY / Factor;
- DeletedRecordings.Del(r0);
- return;
- }
- }
- else {
+ int NumDeletedRecordings = 0;
+ {
+ LOCK_DELETEDRECORDINGS_WRITE;
+ NumDeletedRecordings = DeletedRecordings->Count();
+ if (NumDeletedRecordings) {
+ cRecording *r = DeletedRecordings->First();
+ cRecording *r0 = NULL;
+ while (r) {
+ if (r->IsOnVideoDirectoryFileSystem()) { // only remove recordings that will actually increase the free video disk space
+ if (!r0 || r->Start() < r0->Start())
+ r0 = r;
+ }
+ r = DeletedRecordings->Next(r);
+ }
+ if (r0) {
+ if (r0->Remove())
+ LastFreeDiskCheck += REMOVELATENCY / Factor;
+ DeletedRecordings->Del(r0);
+ return;
+ }
+ }
+ }
+ if (NumDeletedRecordings == 0) {
// DeletedRecordings was empty, so to be absolutely sure there are no
// deleted recordings we need to double check:
- DeletedRecordings.Update(true);
- if (DeletedRecordings.Count())
+ cRecordings::Update(true);
+ LOCK_DELETEDRECORDINGS_READ;
+ if (DeletedRecordings->Count())
return; // the next call will actually remove it
}
// No "deleted" files to remove, so let's see if we can delete a recording:
if (Priority > 0) {
isyslog("...no deleted recording found, trying to delete an old recording...");
- cThreadLock RecordingsLock(&Recordings);
- if (Recordings.Count()) {
- cRecording *r = Recordings.First();
+ LOCK_RECORDINGS_WRITE;
+ Recordings->SetExplicitModify();
+ if (Recordings->Count()) {
+ cRecording *r = Recordings->First();
cRecording *r0 = NULL;
while (r) {
if (r->IsOnVideoDirectoryFileSystem()) { // only delete recordings that will actually increase the free video disk space
@@ -209,10 +212,11 @@ void AssertFreeDiskSpace(int Priority, bool Force)
}
}
}
- r = Recordings.Next(r);
+ r = Recordings->Next(r);
}
if (r0 && r0->Delete()) {
- Recordings.Del(r0);
+ Recordings->Del(r0);
+ Recordings->SetModified();
return;
}
}
@@ -227,14 +231,6 @@ void AssertFreeDiskSpace(int Priority, bool Force)
}
}
-// --- Clear vanished recordings ---------------------------------------------
-
-void ClearVanishedRecordings(void)
-{
- cThreadLock RecordingsLock(&Recordings); // yes, it *is* Recordings!
- VanishedRecordings.Clear();
-}
-
// --- cResumeFile -----------------------------------------------------------
cResumeFile::cResumeFile(const char *FileName, bool IsPesRecording)
@@ -309,7 +305,8 @@ bool cResumeFile::Save(int Index)
if (safe_write(f, &Index, sizeof(Index)) < 0)
LOG_ERROR_STR(fileName);
close(f);
- Recordings.ResetResume(fileName);
+ LOCK_RECORDINGS_WRITE;
+ Recordings->ResetResume(fileName);
return true;
}
}
@@ -318,7 +315,8 @@ bool cResumeFile::Save(int Index)
if (f) {
fprintf(f, "I %d\n", Index);
fclose(f);
- Recordings.ResetResume(fileName);
+ LOCK_RECORDINGS_WRITE;
+ Recordings->ResetResume(fileName);
}
else
LOG_ERROR_STR(fileName);
@@ -331,8 +329,10 @@ bool cResumeFile::Save(int Index)
void cResumeFile::Delete(void)
{
if (fileName) {
- if (remove(fileName) == 0)
- Recordings.ResetResume(fileName);
+ if (remove(fileName) == 0) {
+ LOCK_RECORDINGS_WRITE;
+ Recordings->ResetResume(fileName);
+ }
else if (errno != ENOENT)
LOG_ERROR_STR(fileName);
}
@@ -787,10 +787,8 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event)
else
break;
}
- if (Timer->IsSingleEvent()) {
+ if (Timer->IsSingleEvent())
Timer->SetFile(name); // this was an instant recording, so let's set the actual data
- Timers.SetModified();
- }
}
else if (Timer->IsSingleEvent() || !Setup.UseSubtitle)
name = strdup(Timer->File());
@@ -1017,7 +1015,7 @@ int cRecording::Compare(const cListObject &ListObject) const
return strcasecmp(SortName(), r->SortName());
}
-bool cRecording::IsInPath(const char *Path)
+bool cRecording::IsInPath(const char *Path) const
{
if (isempty(Path))
return true;
@@ -1154,20 +1152,14 @@ bool cRecording::IsOnVideoDirectoryFileSystem(void) const
return isOnVideoDirectoryFileSystem;
}
-bool cRecording::HasMarks(void)
+bool cRecording::HasMarks(void) const
{
return access(cMarks::MarksFileName(this), F_OK) == 0;
}
bool cRecording::DeleteMarks(void)
{
- if (remove(cMarks::MarksFileName(this)) < 0) {
- if (errno != ENOENT) {
- LOG_ERROR_STR(fileName);
- return false;
- }
- }
- return true;
+ return cMarks::DeleteMarksFile(this);
}
void cRecording::ReadInfo(void)
@@ -1219,8 +1211,6 @@ bool cRecording::ChangePriorityLifetime(int NewPriority, int NewLifetime)
if (!WriteInfo())
return false;
}
- Recordings.ChangeState();
- Recordings.TouchUpdate();
}
return true;
}
@@ -1245,8 +1235,6 @@ bool cRecording::ChangeName(const char *NewName)
}
isOnVideoDirectoryFileSystem = -1; // it might have been moved to a different file system
ClearSortName();
- Recordings.ChangeState();
- Recordings.TouchUpdate();
}
return true;
}
@@ -1360,59 +1348,53 @@ int cRecording::FileSizeMB(void) const
return fileSizeMB;
}
-// --- cRecordings -----------------------------------------------------------
+// --- cVideoDirectoryScannerThread ------------------------------------------
-cRecordings Recordings;
-
-char *cRecordings::updateFileName = NULL;
+class cVideoDirectoryScannerThread : public cThread {
+private:
+ cRecordings *recordings;
+ cRecordings *deletedRecordings;
+ bool initial;
+ void ScanVideoDir(const char *DirName, int LinkLevel = 0, int DirLevel = 0);
+protected:
+ virtual void Action(void);
+public:
+ cVideoDirectoryScannerThread(cRecordings *Recordings, cRecordings *DeletedRecordings);
+ ~cVideoDirectoryScannerThread();
+ };
-cRecordings::cRecordings(bool Deleted)
+cVideoDirectoryScannerThread::cVideoDirectoryScannerThread(cRecordings *Recordings, cRecordings *DeletedRecordings)
:cThread("video directory scanner", true)
{
- deleted = Deleted;
+ recordings = Recordings;
+ deletedRecordings = DeletedRecordings;
initial = true;
- lastUpdate = 0;
- state = 0;
}
-cRecordings::~cRecordings()
+cVideoDirectoryScannerThread::~cVideoDirectoryScannerThread()
{
Cancel(3);
}
-void cRecordings::Action(void)
+void cVideoDirectoryScannerThread::Action(void)
{
- Refresh();
-}
-
-const char *cRecordings::UpdateFileName(void)
-{
- if (!updateFileName)
- updateFileName = strdup(AddDirectory(cVideoDirectory::Name(), ".update"));
- return updateFileName;
+ cStateKey StateKey;
+ recordings->Lock(StateKey);
+ initial = recordings->Count() == 0; // no name checking if the list is initially empty
+ StateKey.Remove();
+ deletedRecordings->Lock(StateKey, true);
+ deletedRecordings->Clear();
+ StateKey.Remove();
+ ScanVideoDir(cVideoDirectory::Name());
}
-void cRecordings::Refresh(bool Foreground)
+void cVideoDirectoryScannerThread::ScanVideoDir(const char *DirName, int LinkLevel, int DirLevel)
{
- lastUpdate = time(NULL); // doing this first to make sure we don't miss anything
- initial = Count() == 0; // no name checking if the list is initially empty
- if (deleted) {
- Lock();
- Clear();
- ChangeState();
- Unlock();
- }
- ScanVideoDir(cVideoDirectory::Name(), Foreground);
-}
-
-bool cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLevel, int DirLevel)
-{
- bool DoChangeState = false;
// Find any new recordings:
cReadDir d(DirName);
struct dirent *e;
- while ((Foreground || Running()) && (e = d.Next()) != NULL) {
- if (!Foreground && cIoThrottle::Engaged())
+ while (Running() && (e = d.Next()) != NULL) {
+ if (cIoThrottle::Engaged())
cCondWait::SleepMs(100);
cString buffer = AddDirectory(DirName, e->d_name);
struct stat st;
@@ -1428,57 +1410,73 @@ bool cRecordings::ScanVideoDir(const char *DirName, bool Foreground, int LinkLev
continue;
}
if (S_ISDIR(st.st_mode)) {
- if (endswith(buffer, deleted ? DELEXT : RECEXT)) {
- if (deleted || initial || !GetByName(buffer)) {
+ cRecordings *Recordings = NULL;
+ if (endswith(buffer, RECEXT))
+ Recordings = recordings;
+ else if (endswith(buffer, DELEXT))
+ Recordings = deletedRecordings;
+ if (Recordings) {
+ cStateKey StateKey;
+ Recordings->Lock(StateKey, true);
+ if (Recordings == deletedRecordings || initial || !Recordings->GetByName(buffer)) {
cRecording *r = new cRecording(buffer);
if (r->Name()) {
r->NumFrames(); // initializes the numFrames member
r->FileSizeMB(); // initializes the fileSizeMB member
r->IsOnVideoDirectoryFileSystem(); // initializes the isOnVideoDirectoryFileSystem member
- if (deleted)
- r->deleted = time(NULL);
- Lock();
- Add(r);
- if (initial)
- ChangeState();
- else
- DoChangeState = true;
- Unlock();
+ if (Recordings == deletedRecordings)
+ r->SetDeleted();
+ Recordings->Add(r);
}
else
delete r;
}
+ StateKey.Remove();
}
else
- DoChangeState |= ScanVideoDir(buffer, Foreground, LinkLevel + Link, DirLevel + 1);
+ ScanVideoDir(buffer, LinkLevel + Link, DirLevel + 1);
}
}
}
// Handle any vanished recordings:
- if (!deleted && !initial && DirLevel == 0) {
- for (cRecording *recording = First(); recording; ) {
- cRecording *r = recording;
- recording = Next(recording);
- if (access(r->FileName(), F_OK) != 0) {
- Lock();
- Del(r, false);
- VanishedRecordings.Add(r);
- DoChangeState = true;
- Unlock();
- }
+ if (!initial && DirLevel == 0) {
+ cStateKey StateKey;
+ recordings->Lock(StateKey, true);
+ for (cRecording *Recording = recordings->First(); Recording; ) {
+ cRecording *r = Recording;
+ Recording = recordings->Next(Recording);
+ if (access(r->FileName(), F_OK) != 0)
+ recordings->Del(r);
}
+ StateKey.Remove();
}
- if (DoChangeState && DirLevel == 0)
- ChangeState();
- return DoChangeState;
}
-bool cRecordings::StateChanged(int &State)
+// --- cRecordings -----------------------------------------------------------
+
+cRecordings cRecordings::recordings;
+cRecordings cRecordings::deletedRecordings(true);
+char *cRecordings::updateFileName = NULL;
+cVideoDirectoryScannerThread *cRecordings::videoDirectoryScannerThread = NULL;
+time_t cRecordings::lastUpdate = 0;
+
+cRecordings::cRecordings(bool Deleted)
+:cList<cRecording>(Deleted ? "DelRecs" : "Recordings")
{
- int NewState = state;
- bool Result = State != NewState;
- State = state;
- return Result;
+}
+
+cRecordings::~cRecordings()
+{
+ // The first one to be destructed deletes it:
+ delete videoDirectoryScannerThread;
+ videoDirectoryScannerThread = NULL;
+}
+
+const char *cRecordings::UpdateFileName(void)
+{
+ if (!updateFileName)
+ updateFileName = strdup(AddDirectory(cVideoDirectory::Name(), ".update"));
+ return updateFileName;
}
void cRecordings::TouchUpdate(void)
@@ -1497,24 +1495,24 @@ bool cRecordings::NeedsUpdate(void)
return lastUpdate < lastModified;
}
-bool cRecordings::Update(bool Wait)
+void cRecordings::Update(bool Wait)
{
+ if (!videoDirectoryScannerThread)
+ videoDirectoryScannerThread = new cVideoDirectoryScannerThread(&recordings, &deletedRecordings);
+ lastUpdate = time(NULL); // doing this first to make sure we don't miss anything
+ videoDirectoryScannerThread->Start();
if (Wait) {
- Refresh(true);
- return Count() > 0;
+ while (videoDirectoryScannerThread->Active())
+ cCondWait::SleepMs(100);
}
- else
- Start();
- return false;
}
-cRecording *cRecordings::GetByName(const char *FileName)
+const cRecording *cRecordings::GetByName(const char *FileName) const
{
if (FileName) {
- LOCK_THREAD;
- for (cRecording *recording = First(); recording; recording = Next(recording)) {
- if (strcmp(recording->FileName(), FileName) == 0)
- return recording;
+ for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) {
+ if (strcmp(Recording->FileName(), FileName) == 0)
+ return Recording;
}
}
return NULL;
@@ -1522,12 +1520,8 @@ cRecording *cRecordings::GetByName(const char *FileName)
void cRecordings::AddByName(const char *FileName, bool TriggerUpdate)
{
- LOCK_THREAD;
- cRecording *recording = GetByName(FileName);
- if (!recording) {
- recording = new cRecording(FileName);
- Add(recording);
- ChangeState();
+ if (!GetByName(FileName)) {
+ Add(new cRecording(FileName));
if (TriggerUpdate)
TouchUpdate();
}
@@ -1535,58 +1529,52 @@ void cRecordings::AddByName(const char *FileName, bool TriggerUpdate)
void cRecordings::DelByName(const char *FileName)
{
- LOCK_THREAD;
- cRecording *recording = GetByName(FileName);
+ cRecording *Recording = GetByName(FileName);
cRecording *dummy = NULL;
- if (!recording)
- recording = dummy = new cRecording(FileName); // allows us to use a FileName that is not in the Recordings list
- cThreadLock DeletedRecordingsLock(&DeletedRecordings);
+ if (!Recording)
+ Recording = dummy = new cRecording(FileName); // allows us to use a FileName that is not in the Recordings list
+ LOCK_DELETEDRECORDINGS_WRITE;
if (!dummy)
- Del(recording, false);
- char *ext = strrchr(recording->fileName, '.');
+ Del(Recording, false);
+ char *ext = strrchr(Recording->fileName, '.');
if (ext) {
strncpy(ext, DELEXT, strlen(ext));
- if (access(recording->FileName(), F_OK) == 0) {
- recording->deleted = time(NULL);
- DeletedRecordings.Add(recording);
- recording = NULL; // to prevent it from being deleted below
+ if (access(Recording->FileName(), F_OK) == 0) {
+ Recording->SetDeleted();
+ DeletedRecordings->Add(Recording);
+ Recording = NULL; // to prevent it from being deleted below
}
}
- delete recording;
- ChangeState();
+ delete Recording;
TouchUpdate();
}
void cRecordings::UpdateByName(const char *FileName)
{
- LOCK_THREAD;
- cRecording *recording = GetByName(FileName);
- if (recording)
- recording->ReadInfo();
+ if (cRecording *Recording = GetByName(FileName))
+ Recording->ReadInfo();
}
-int cRecordings::TotalFileSizeMB(void)
+int cRecordings::TotalFileSizeMB(void) const
{
int size = 0;
- LOCK_THREAD;
- for (cRecording *recording = First(); recording; recording = Next(recording)) {
- int FileSizeMB = recording->FileSizeMB();
- if (FileSizeMB > 0 && recording->IsOnVideoDirectoryFileSystem())
+ for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) {
+ int FileSizeMB = Recording->FileSizeMB();
+ if (FileSizeMB > 0 && Recording->IsOnVideoDirectoryFileSystem())
size += FileSizeMB;
}
return size;
}
-double cRecordings::MBperMinute(void)
+double cRecordings::MBperMinute(void) const
{
int size = 0;
int length = 0;
- LOCK_THREAD;
- for (cRecording *recording = First(); recording; recording = Next(recording)) {
- if (recording->IsOnVideoDirectoryFileSystem()) {
- int FileSizeMB = recording->FileSizeMB();
+ for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) {
+ if (Recording->IsOnVideoDirectoryFileSystem()) {
+ int FileSizeMB = Recording->FileSizeMB();
if (FileSizeMB > 0) {
- int LengthInSeconds = recording->LengthInSeconds();
+ int LengthInSeconds = Recording->LengthInSeconds();
if (LengthInSeconds > 0) {
if (LengthInSeconds / FileSizeMB < LIMIT_SECS_PER_MB_RADIO) { // don't count radio recordings
size += FileSizeMB;
@@ -1599,23 +1587,21 @@ double cRecordings::MBperMinute(void)
return (size && length) ? double(size) * 60 / length : -1;
}
-int cRecordings::PathIsInUse(const char *Path)
+int cRecordings::PathIsInUse(const char *Path) const
{
- LOCK_THREAD;
int Use = ruNone;
- for (cRecording *recording = First(); recording; recording = Next(recording)) {
- if (recording->IsInPath(Path))
- Use |= recording->IsInUse();
+ for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) {
+ if (Recording->IsInPath(Path))
+ Use |= Recording->IsInUse();
}
return Use;
}
-int cRecordings::GetNumRecordingsInPath(const char *Path)
+int cRecordings::GetNumRecordingsInPath(const char *Path) const
{
- LOCK_THREAD;
int n = 0;
- for (cRecording *recording = First(); recording; recording = Next(recording)) {
- if (recording->IsInPath(Path))
+ for (const cRecording *Recording = First(); Recording; Recording = Next(Recording)) {
+ if (Recording->IsInPath(Path))
n++;
}
return n;
@@ -1624,36 +1610,35 @@ int cRecordings::GetNumRecordingsInPath(const char *Path)
bool cRecordings::MoveRecordings(const char *OldPath, const char *NewPath)
{
if (OldPath && NewPath && strcmp(OldPath, NewPath)) {
- LOCK_THREAD;
dsyslog("moving '%s' to '%s'", OldPath, NewPath);
- for (cRecording *recording = First(); recording; recording = Next(recording)) {
- if (recording->IsInPath(OldPath)) {
- const char *p = recording->Name() + strlen(OldPath);
+ bool Moved = false;
+ for (cRecording *Recording = First(); Recording; Recording = Next(Recording)) {
+ if (Recording->IsInPath(OldPath)) {
+ const char *p = Recording->Name() + strlen(OldPath);
cString NewName = cString::sprintf("%s%s", NewPath, p);
- if (!recording->ChangeName(NewName))
+ if (!Recording->ChangeName(NewName))
return false;
- ChangeState();
+ Moved = true;
}
}
+ if (Moved)
+ TouchUpdate();
}
return true;
}
void cRecordings::ResetResume(const char *ResumeFileName)
{
- LOCK_THREAD;
- for (cRecording *recording = First(); recording; recording = Next(recording)) {
- if (!ResumeFileName || strncmp(ResumeFileName, recording->FileName(), strlen(recording->FileName())) == 0)
- recording->ResetResume();
+ for (cRecording *Recording = First(); Recording; Recording = Next(Recording)) {
+ if (!ResumeFileName || strncmp(ResumeFileName, Recording->FileName(), strlen(Recording->FileName())) == 0)
+ Recording->ResetResume();
}
- ChangeState();
}
void cRecordings::ClearSortNames(void)
{
- LOCK_THREAD;
- for (cRecording *recording = First(); recording; recording = Next(recording))
- recording->ClearSortName();
+ for (cRecording *Recording = First(); Recording; Recording = Next(Recording))
+ Recording->ClearSortName();
}
// --- cDirCopier ------------------------------------------------------------
@@ -1812,8 +1797,9 @@ void cDirCopier::Stop(void)
Cancel(3);
if (error) {
cVideoDirectory::RemoveVideoFile(dirNameDst);
- Recordings.AddByName(dirNameSrc);
- Recordings.DelByName(dirNameDst);
+ LOCK_RECORDINGS_WRITE;
+ Recordings->AddByName(dirNameSrc);
+ Recordings->DelByName(dirNameDst);
}
}
@@ -1893,17 +1879,19 @@ bool cRecordingsHandlerEntry::Active(bool &Error)
copier->Start();
}
ClearPending();
- Recordings.ChangeState();
+ LOCK_RECORDINGS_WRITE; // to trigger a state change
return true;
}
// Clean up:
if (CopierFinishedOk && (Usage() & ruMove) != 0) {
cRecording Recording(FileNameSrc());
- if (Recording.Delete())
- Recordings.DelByName(Recording.FileName());
+ if (Recording.Delete()) {
+ LOCK_RECORDINGS_WRITE;
+ Recordings->DelByName(Recording.FileName());
+ }
}
- Recordings.ChangeState();
- Recordings.TouchUpdate();
+ LOCK_RECORDINGS_WRITE; // to trigger a state change
+ Recordings->TouchUpdate();
return false;
}
@@ -1947,7 +1935,7 @@ bool cRecordingsHandler::Add(int Usage, const char *FileNameSrc, const char *Fil
operations.Add(new cRecordingsHandlerEntry(Usage, FileNameSrc, FileNameDst));
finished = false;
Active(); // start it right away if possible
- Recordings.ChangeState();
+ LOCK_RECORDINGS_WRITE; // to trigger a state change
return true;
}
else
@@ -1969,7 +1957,7 @@ void cRecordingsHandler::Del(const char *FileName)
cMutexLock MutexLock(&mutex);
if (cRecordingsHandlerEntry *r = Get(FileName)) {
operations.Del(r);
- Recordings.ChangeState();
+ LOCK_RECORDINGS_WRITE; // to trigger a state change
}
}
@@ -1977,7 +1965,7 @@ void cRecordingsHandler::DelAll(void)
{
cMutexLock MutexLock(&mutex);
operations.Clear();
- Recordings.ChangeState();
+ LOCK_RECORDINGS_WRITE; // to trigger a state change
}
int cRecordingsHandler::GetUsage(const char *FileName)
@@ -2059,9 +2047,19 @@ cString cMarks::MarksFileName(const cRecording *Recording)
return AddDirectory(Recording->FileName(), Recording->IsPesRecording() ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX);
}
+bool cMarks::DeleteMarksFile(const cRecording *Recording)
+{
+ if (remove(cMarks::MarksFileName(Recording)) < 0) {
+ if (errno != ENOENT) {
+ LOG_ERROR_STR(Recording->FileName());
+ return false;
+ }
+ }
+ return true;
+}
+
bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool IsPesRecording)
{
- cMutexLock MutexLock(this);
recordingFileName = RecordingFileName;
fileName = AddDirectory(RecordingFileName, IsPesRecording ? MARKSFILESUFFIX ".vdr" : MARKSFILESUFFIX);
framesPerSecond = FramesPerSecond;
@@ -2074,7 +2072,6 @@ bool cMarks::Load(const char *RecordingFileName, double FramesPerSecond, bool Is
bool cMarks::Update(void)
{
- cMutexLock MutexLock(this);
time_t t = time(NULL);
if (t > nextUpdate && *fileName) {
time_t LastModified = LastModifiedTime(fileName);
@@ -2106,7 +2103,6 @@ bool cMarks::Update(void)
bool cMarks::Save(void)
{
- cMutexLock MutexLock(this);
if (cConfig<cMark>::Save()) {
lastFileTime = LastModifiedTime(fileName);
return true;
@@ -2116,7 +2112,6 @@ bool cMarks::Save(void)
void cMarks::Align(void)
{
- cMutexLock MutexLock(this);
cIndexFile IndexFile(recordingFileName, false, isPesRecording);
for (cMark *m = First(); m; m = Next(m)) {
int p = IndexFile.GetClosestIFrame(m->Position());
@@ -2129,7 +2124,6 @@ void cMarks::Align(void)
void cMarks::Sort(void)
{
- cMutexLock MutexLock(this);
for (cMark *m1 = First(); m1; m1 = Next(m1)) {
for (cMark *m2 = Next(m1); m2; m2 = Next(m2)) {
if (m2->Position() < m1->Position()) {
@@ -2142,43 +2136,42 @@ void cMarks::Sort(void)
void cMarks::Add(int Position)
{
- cMutexLock MutexLock(this);
cConfig<cMark>::Add(new cMark(Position, NULL, framesPerSecond));
Sort();
}
-cMark *cMarks::Get(int Position)
+const cMark *cMarks::Get(int Position) const
{
- for (cMark *mi = First(); mi; mi = Next(mi)) {
+ for (const cMark *mi = First(); mi; mi = Next(mi)) {
if (mi->Position() == Position)
return mi;
}
return NULL;
}
-cMark *cMarks::GetPrev(int Position)
+const cMark *cMarks::GetPrev(int Position) const
{
- for (cMark *mi = Last(); mi; mi = Prev(mi)) {
+ for (const cMark *mi = Last(); mi; mi = Prev(mi)) {
if (mi->Position() < Position)
return mi;
}
return NULL;
}
-cMark *cMarks::GetNext(int Position)
+const cMark *cMarks::GetNext(int Position) const
{
- for (cMark *mi = First(); mi; mi = Next(mi)) {
+ for (const cMark *mi = First(); mi; mi = Next(mi)) {
if (mi->Position() > Position)
return mi;
}
return NULL;
}
-cMark *cMarks::GetNextBegin(cMark *EndMark)
+const cMark *cMarks::GetNextBegin(const cMark *EndMark) const
{
- cMark *BeginMark = EndMark ? Next(EndMark) : First();
+ const cMark *BeginMark = EndMark ? Next(EndMark) : First();
if (BeginMark && EndMark && BeginMark->Position() == EndMark->Position()) {
- while (cMark *NextMark = Next(BeginMark)) {
+ while (const cMark *NextMark = Next(BeginMark)) {
if (BeginMark->Position() == NextMark->Position()) { // skip Begin/End at the same position
if (!(BeginMark = Next(NextMark)))
break;
@@ -2190,13 +2183,13 @@ cMark *cMarks::GetNextBegin(cMark *EndMark)
return BeginMark;
}
-cMark *cMarks::GetNextEnd(cMark *BeginMark)
+const cMark *cMarks::GetNextEnd(const cMark *BeginMark) const
{
if (!BeginMark)
return NULL;
- cMark *EndMark = Next(BeginMark);
+ const cMark *EndMark = Next(BeginMark);
if (EndMark && BeginMark && BeginMark->Position() == EndMark->Position()) {
- while (cMark *NextMark = Next(EndMark)) {
+ while (const cMark *NextMark = Next(EndMark)) {
if (EndMark->Position() == NextMark->Position()) { // skip End/Begin at the same position
if (!(EndMark = Next(NextMark)))
break;
@@ -2208,12 +2201,11 @@ cMark *cMarks::GetNextEnd(cMark *BeginMark)
return EndMark;
}
-int cMarks::GetNumSequences(void)
+int cMarks::GetNumSequences(void) const
{
- cMutexLock MutexLock(this);
int NumSequences = 0;
- if (cMark *BeginMark = GetNextBegin()) {
- while (cMark *EndMark = GetNextEnd(BeginMark)) {
+ if (const cMark *BeginMark = GetNextBegin()) {
+ while (const cMark *EndMark = GetNextEnd(BeginMark)) {
NumSequences++;
BeginMark = GetNextBegin(EndMark);
}
@@ -2403,7 +2395,8 @@ void cIndexFileGenerator::Action(void)
if (FrameDetector.FramesPerSecond() > 0 && !DoubleEqual(RecordingInfo.FramesPerSecond(), FrameDetector.FramesPerSecond())) {
RecordingInfo.SetFramesPerSecond(FrameDetector.FramesPerSecond());
RecordingInfo.Write();
- Recordings.UpdateByName(recordingName);
+ LOCK_RECORDINGS_WRITE;
+ Recordings->UpdateByName(recordingName);
}
}
Skins.QueueMessage(mtInfo, tr("Index file regeneration complete"));