summaryrefslogtreecommitdiff
path: root/recording.h
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.h
parent8a7bc6a0bbf60cae8b6391a630880aad5cba3363 (diff)
downloadvdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.gz
vdr-3cd5294d8a337ee5cd2ec894c9fbe04ad3a7690d.tar.bz2
Implemented strict locking of global lists
Diffstat (limited to 'recording.h')
-rw-r--r--recording.h105
1 files changed, 63 insertions, 42 deletions
diff --git a/recording.h b/recording.h
index dca5ee3d..cebd2ee0 100644
--- a/recording.h
+++ b/recording.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.h 4.2 2015/04/28 09:26:02 kls Exp $
+ * $Id: recording.h 4.3 2015/08/29 14:12:14 kls Exp $
*/
#ifndef __RECORDING_H
@@ -41,7 +41,6 @@ enum eRecordingUsage {
};
void RemoveDeletedRecordings(void);
-void ClearVanishedRecordings(void);
void AssertFreeDiskSpace(int Priority = 0, bool Force = false);
///< The special Priority value -1 means that we shall get rid of any
///< deleted recordings faster than normal (because we're cutting).
@@ -129,8 +128,9 @@ public:
int Priority(void) const { return priority; }
int Lifetime(void) const { return lifetime; }
time_t Deleted(void) const { return deleted; }
+ void SetDeleted(void) { deleted = time(NULL); }
virtual int Compare(const cListObject &ListObject) const;
- bool IsInPath(const char *Path);
+ bool IsInPath(const char *Path) const;
///< Returns true if this recording is stored anywhere under the given Path.
///< If Path is NULL or an empty string, the entire video directory is checked.
cString Folder(void) const;
@@ -140,7 +140,7 @@ public:
///< Returns the base name of this recording (without the
///< video directory and folder). For use in menus etc.
const char *Name(void) const { return name; }
- ///< Returns the full name of the recording (without the video directory.
+ ///< Returns the full name of the recording (without the video directory).
///< For use in menus etc.
const char *FileName(void) const;
///< Returns the full path name to the recording directory, including the
@@ -166,7 +166,7 @@ public:
bool IsEdited(void) const;
bool IsPesRecording(void) const { return isPesRecording; }
bool IsOnVideoDirectoryFileSystem(void) const;
- bool HasMarks(void);
+ bool HasMarks(void) const;
///< Returns true if this recording has any editing marks.
bool DeleteMarks(void);
///< Deletes the editing marks from this recording (if any).
@@ -216,49 +216,54 @@ public:
///< as in time-shift).
};
-class cRecordings : public cList<cRecording>, public cThread {
+class cVideoDirectoryScannerThread;
+
+class cRecordings : public cList<cRecording> {
private:
+ static cRecordings recordings;
+ static cRecordings deletedRecordings;
static char *updateFileName;
- bool deleted;
- bool initial;
- time_t lastUpdate;
- int state;
- const char *UpdateFileName(void);
- void Refresh(bool Foreground = false);
- bool ScanVideoDir(const char *DirName, bool Foreground = false, int LinkLevel = 0, int DirLevel = 0);
-protected:
- virtual void Action(void);
+ static time_t lastUpdate;
+ static cVideoDirectoryScannerThread *videoDirectoryScannerThread;
+ static const char *UpdateFileName(void);
public:
cRecordings(bool Deleted = false);
virtual ~cRecordings();
- bool Load(void) { return Update(true); }
- ///< Loads the current list of recordings and returns true if there
- ///< is anything in it (for compatibility with older plugins - use
- ///< Update(true) instead).
- bool Update(bool Wait = false);
+ static const cRecordings *GetRecordingsRead(cStateKey &StateKey, int TimeoutMs = 0) { return recordings.Lock(StateKey, false, TimeoutMs) ? &recordings : NULL; }
+ ///< Gets the list of recordings for read access.
+ ///< See cTimers::GetTimersRead() for details.
+ static cRecordings *GetRecordingsWrite(cStateKey &StateKey, int TimeoutMs = 0) { return recordings.Lock(StateKey, true, TimeoutMs) ? &recordings : NULL; }
+ ///< Gets the list of recordings for write access.
+ ///< See cTimers::GetTimersWrite() for details.
+ static const cRecordings *GetDeletedRecordingsRead(cStateKey &StateKey, int TimeoutMs = 0) { return deletedRecordings.Lock(StateKey, false, TimeoutMs) ? &deletedRecordings : NULL; }
+ ///< Gets the list of deleted recordings for read access.
+ ///< See cTimers::GetTimersRead() for details.
+ static cRecordings *GetDeletedRecordingsWrite(cStateKey &StateKey, int TimeoutMs = 0) { return deletedRecordings.Lock(StateKey, true, TimeoutMs) ? &deletedRecordings : NULL; }
+ ///< Gets the list of deleted recordings for write access.
+ ///< See cTimers::GetTimersWrite() for details.
+ static void Update(bool Wait = false);
///< Triggers an update of the list of recordings, which will run
///< as a separate thread if Wait is false. If Wait is true, the
///< function returns only after the update has completed.
- ///< Returns true if Wait is true and there is anything in the list
- ///< of recordings, false otherwise.
- void TouchUpdate(void);
+ static void TouchUpdate(void);
///< Touches the '.update' file in the video directory, so that other
///< instances of VDR that access the same video directory can be triggered
///< to update their recordings list.
- bool NeedsUpdate(void);
- void ChangeState(void) { state++; }
- bool StateChanged(int &State);
+ ///< This function is 'const', because it doesn't actually modify the list
+ ///< of recordings.
+ static bool NeedsUpdate(void);
void ResetResume(const char *ResumeFileName = NULL);
void ClearSortNames(void);
- cRecording *GetByName(const char *FileName);
+ const cRecording *GetByName(const char *FileName) const;
+ cRecording *GetByName(const char *FileName) { return const_cast<cRecording *>(static_cast<const cRecordings *>(this)->GetByName(FileName)); }
void AddByName(const char *FileName, bool TriggerUpdate = true);
void DelByName(const char *FileName);
void UpdateByName(const char *FileName);
- int TotalFileSizeMB(void);
- double MBperMinute(void);
+ int TotalFileSizeMB(void) const;
+ double MBperMinute(void) const;
///< Returns the average data rate (in MB/min) of all recordings, or -1 if
///< this value is unknown.
- int PathIsInUse(const char *Path);
+ int PathIsInUse(const char *Path) const;
///< Checks whether any recording in the given Path is currently in use and therefore
///< the whole Path shall not be tampered with. Returns 0 (ruNone) if no recording
///< is in use.
@@ -266,7 +271,7 @@ public:
///< If several recordings in the Path are currently in use, the return value will
///< be the combination of all individual recordings' flags.
///< If Path is NULL or an empty string, the entire video directory is checked.
- int GetNumRecordingsInPath(const char *Path);
+ int GetNumRecordingsInPath(const char *Path) const;
///< Returns the total number of recordings in the given Path, including all
///< sub-folders of Path.
///< If Path is NULL or an empty string, the entire video directory is checked.
@@ -281,10 +286,19 @@ public:
///< if all recordings have been successfully added to the RecordingsHandler.
};
-/// Any access to Recordings that loops through the list of recordings
-/// needs to hold a thread lock on this object!
-extern cRecordings Recordings;
-extern cRecordings DeletedRecordings;
+// Provide lock controlled access to the list:
+
+DEF_LIST_LOCK(Recordings);
+DEF_LIST_LOCK2(Recordings, DeletedRecordings);
+
+// These macros provide a convenient way of locking the global recordings list
+// and making sure the lock is released as soon as the current scope is left
+// (note that these macros wait forever to obtain the lock!):
+
+#define LOCK_RECORDINGS_READ USE_LIST_LOCK_READ(Recordings)
+#define LOCK_RECORDINGS_WRITE USE_LIST_LOCK_WRITE(Recordings)
+#define LOCK_DELETEDRECORDINGS_READ USE_LIST_LOCK_READ2(Recordings, DeletedRecordings)
+#define LOCK_DELETEDRECORDINGS_WRITE USE_LIST_LOCK_WRITE2(Recordings, DeletedRecordings)
class cRecordingsHandlerEntry;
@@ -350,7 +364,7 @@ public:
bool Save(FILE *f);
};
-class cMarks : public cConfig<cMark>, public cMutex {
+class cMarks : public cConfig<cMark> {
private:
cString recordingFileName;
cString fileName;
@@ -360,9 +374,11 @@ private:
time_t lastFileTime;
time_t lastChange;
public:
+ cMarks(void): cConfig<cMark>("Marks") {};
static cString MarksFileName(const cRecording *Recording);
///< Returns the marks file name for the given Recording (regardless whether such
///< a file actually exists).
+ static bool DeleteMarksFile(const cRecording *Recording);
bool Load(const char *RecordingFileName, double FramesPerSecond = DEFAULTFRAMESPERSECOND, bool IsPesRecording = false);
bool Update(void);
bool Save(void);
@@ -374,22 +390,27 @@ public:
///< calls to Del(), or any of the functions that return a "cMark *", in case
///< an other thread might modifiy the list while the returned pointer is
///< considered valid.
- cMark *Get(int Position);
- cMark *GetPrev(int Position);
- cMark *GetNext(int Position);
- cMark *GetNextBegin(cMark *EndMark = NULL);
+ const cMark *Get(int Position) const;
+ const cMark *GetPrev(int Position) const;
+ const cMark *GetNext(int Position) const;
+ const cMark *GetNextBegin(const cMark *EndMark = NULL) const;
///< Returns the next "begin" mark after EndMark, skipping any marks at the
///< same position as EndMark. If EndMark is NULL, the first actual "begin"
///< will be returned (if any).
- cMark *GetNextEnd(cMark *BeginMark);
+ const cMark *GetNextEnd(const cMark *BeginMark) const;
///< Returns the next "end" mark after BeginMark, skipping any marks at the
///< same position as BeginMark.
- int GetNumSequences(void);
+ int GetNumSequences(void) const;
///< Returns the actual number of sequences to be cut from the recording.
///< If there is only one actual "begin" mark, and it is positioned at index
///< 0 (the beginning of the recording), and there is no "end" mark, the
///< return value is 0, which means that the result is the same as the original
///< recording.
+ cMark *Get(int Position) { return const_cast<cMark *>(static_cast<const cMarks *>(this)->Get(Position)); }
+ cMark *GetPrev(int Position) { return const_cast<cMark *>(static_cast<const cMarks *>(this)->GetPrev(Position)); }
+ cMark *GetNext(int Position) { return const_cast<cMark *>(static_cast<const cMarks *>(this)->GetNext(Position)); }
+ cMark *GetNextBegin(const cMark *EndMark = NULL) { return const_cast<cMark *>(static_cast<const cMarks *>(this)->GetNextBegin(EndMark)); }
+ cMark *GetNextEnd(const cMark *BeginMark) { return const_cast<cMark *>(static_cast<const cMarks *>(this)->GetNextEnd(BeginMark)); }
};
#define RUC_BEFORERECORDING "before"