vdr  1.7.31
recording.h
Go to the documentation of this file.
1 /*
2  * recording.h: Recording file handling
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: recording.h 2.37 2012/09/17 08:53:23 kls Exp $
8  */
9 
10 #ifndef __RECORDING_H
11 #define __RECORDING_H
12 
13 #include <time.h>
14 #include "channels.h"
15 #include "config.h"
16 #include "epg.h"
17 #include "thread.h"
18 #include "timers.h"
19 #include "tools.h"
20 
21 #define FOLDERDELIMCHAR '~'
22 #define TIMERMACRO_TITLE "TITLE"
23 #define TIMERMACRO_EPISODE "EPISODE"
24 
25 extern bool VfatFileSystem;
26 extern int InstanceId;
27 
28 void RemoveDeletedRecordings(void);
29 void AssertFreeDiskSpace(int Priority = 0, bool Force = false);
34 
35 class cResumeFile {
36 private:
37  char *fileName;
38  bool isPesRecording;
39 public:
40  cResumeFile(const char *FileName, bool IsPesRecording);
41  ~cResumeFile();
42  int Read(void);
43  bool Save(int Index);
44  void Delete(void);
45  };
46 
47 class cRecordingInfo {
48  friend class cRecording;
49 private:
51  char *channelName;
52  const cEvent *event;
54  char *aux;
55  double framesPerSecond;
56  int priority;
57  int lifetime;
58  char *fileName;
59  cRecordingInfo(const cChannel *Channel = NULL, const cEvent *Event = NULL);
60  bool Read(FILE *f);
61  void SetData(const char *Title, const char *ShortText, const char *Description);
62  void SetAux(const char *Aux);
63 public:
64  cRecordingInfo(const char *FileName);
66  tChannelID ChannelID(void) const { return channelID; }
67  const char *ChannelName(void) const { return channelName; }
68  const cEvent *GetEvent(void) const { return event; }
69  const char *Title(void) const { return event->Title(); }
70  const char *ShortText(void) const { return event->ShortText(); }
71  const char *Description(void) const { return event->Description(); }
72  const cComponents *Components(void) const { return event->Components(); }
73  const char *Aux(void) const { return aux; }
74  double FramesPerSecond(void) const { return framesPerSecond; }
76  bool Write(FILE *f, const char *Prefix = "") const;
77  bool Read(void);
78  bool Write(void) const;
79  };
80 
81 class cRecording : public cListObject {
82  friend class cRecordings;
83 private:
84  mutable int resume;
85  mutable char *titleBuffer;
86  mutable char *sortBufferName;
87  mutable char *sortBufferTime;
88  mutable char *fileName;
89  mutable char *name;
90  mutable int fileSizeMB;
91  mutable int numFrames;
92  int channel;
93  int instanceId;
94  bool isPesRecording;
95  mutable int isOnVideoDirectoryFileSystem; // -1 = unknown, 0 = no, 1 = yes
96  double framesPerSecond;
98  cRecording(const cRecording&); // can't copy cRecording
99  cRecording &operator=(const cRecording &); // can't assign cRecording
100  static char *StripEpisodeName(char *s);
101  char *SortName(void) const;
102  int GetResume(void) const;
103  time_t start;
104  int priority;
105  int lifetime;
106  time_t deleted;
107 public:
108  cRecording(cTimer *Timer, const cEvent *Event);
109  cRecording(const char *FileName);
110  virtual ~cRecording();
111  time_t Start(void) const { return start; }
112  int Priority(void) const { return priority; }
113  int Lifetime(void) const { return lifetime; }
114  time_t Deleted(void) const { return deleted; }
115  virtual int Compare(const cListObject &ListObject) const;
116  const char *Name(void) const { return name; }
117  const char *FileName(void) const;
118  const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
119  const cRecordingInfo *Info(void) const { return info; }
120  const char *PrefixFileName(char Prefix);
121  const char *UpdateFileName(const char *FileName);
122  int HierarchyLevels(void) const;
123  void ResetResume(void) const;
124  double FramesPerSecond(void) const { return framesPerSecond; }
125  int NumFrames(void) const;
128  int LengthInSeconds(void) const;
130  int FileSizeMB(void) const;
133  bool IsNew(void) const { return GetResume() <= 0; }
134  bool IsEdited(void) const;
135  bool IsPesRecording(void) const { return isPesRecording; }
136  bool IsOnVideoDirectoryFileSystem(void) const;
137  void ReadInfo(void);
138  bool WriteInfo(void);
139  void SetStartTime(time_t Start);
147  bool Delete(void);
150  bool Remove(void);
153  bool Undelete(void);
157  };
158 
159 class cRecordings : public cList<cRecording>, public cThread {
160 private:
161  static char *updateFileName;
162  bool deleted;
163  time_t lastUpdate;
164  int state;
165  const char *UpdateFileName(void);
166  void Refresh(bool Foreground = false);
167  void ScanVideoDir(const char *DirName, bool Foreground = false, int LinkLevel = 0);
168 protected:
169  void Action(void);
170 public:
171  cRecordings(bool Deleted = false);
172  virtual ~cRecordings();
173  bool Load(void) { return Update(true); }
177  bool Update(bool Wait = false);
183  void TouchUpdate(void);
187  bool NeedsUpdate(void);
188  void ChangeState(void) { state++; }
189  bool StateChanged(int &State);
190  void ResetResume(const char *ResumeFileName = NULL);
191  cRecording *GetByName(const char *FileName);
192  void AddByName(const char *FileName, bool TriggerUpdate = true);
193  void DelByName(const char *FileName, bool RemoveRecording = true);
194  void UpdateByName(const char *FileName);
195  int TotalFileSizeMB(void);
196  double MBperMinute(void);
199  };
200 
201 extern cRecordings Recordings;
203 
204 #define DEFAULTFRAMESPERSECOND 25.0
205 
206 class cMark : public cListObject {
207  friend class cMarks; // for sorting
208 private:
209  double framesPerSecond;
210  int position;
212 public:
213  cMark(int Position = 0, const char *Comment = NULL, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
214  virtual ~cMark();
215  int Position(void) const { return position; }
216  const char *Comment(void) const { return comment; }
218  void SetComment(const char *Comment) { comment = Comment; }
219  cString ToText(void);
220  bool Parse(const char *s);
221  bool Save(FILE *f);
222  };
223 
224 class cMarks : public cConfig<cMark> {
225 private:
227  double framesPerSecond;
228  time_t nextUpdate;
229  time_t lastFileTime;
230  time_t lastChange;
231 public:
232  bool Load(const char *RecordingFileName, double FramesPerSecond = DEFAULTFRAMESPERSECOND, bool IsPesRecording = false);
233  bool Update(void);
234  void Sort(void);
235  cMark *Add(int Position);
236  cMark *Get(int Position);
237  cMark *GetPrev(int Position);
238  cMark *GetNext(int Position);
239  };
240 
241 #define RUC_BEFORERECORDING "before"
242 #define RUC_AFTERRECORDING "after"
243 #define RUC_EDITEDRECORDING "edited"
244 #define RUC_DELETERECORDING "deleted"
245 
246 class cRecordingUserCommand {
247 private:
248  static const char *command;
249 public:
250  static void SetCommand(const char *Command) { command = Command; }
251  static void InvokeCommand(const char *State, const char *RecordingFileName, const char *SourceFileName = NULL);
252  };
253 
254 // The maximum size of a single frame (up to HDTV 1920x1080):
255 #define MAXFRAMESIZE (KILOBYTE(1024) / TS_SIZE * TS_SIZE) // multiple of TS_SIZE to avoid breaking up TS packets
256 
257 // The maximum file size is limited by the range that can be covered
258 // with a 40 bit 'unsigned int', which is 1TB. The actual maximum value
259 // used is 6MB below the theoretical maximum, to have some safety (the
260 // actual file size may be slightly higher because we stop recording only
261 // before the next independent frame, to have a complete Group Of Pictures):
262 #define MAXVIDEOFILESIZETS 1048570 // MB
263 #define MAXVIDEOFILESIZEPES 2000 // MB
264 #define MINVIDEOFILESIZE 1 // MB
265 #define MAXVIDEOFILESIZEDEFAULT MAXVIDEOFILESIZEPES
266 
267 #define MINRECORDINGSIZE 25 // GB
268 #define MAXRECORDINGSIZE 500 // GB
269 #define DEFAULTRECORDINGSIZE 100 // GB
270 // Dynamic recording size:
271 // Keep recording file size at Setup.MaxVideoFileSize for as long as possible,
272 // but switch to MAXVIDEOFILESIZE early enough, so that Setup.MaxRecordingSize
273 // will be reached, before recording to file 65535.vdr
274 
275 struct tIndexTs;
276 class cIndexFileGenerator;
277 
278 class cIndexFile {
279 private:
280  int f;
282  int size, last;
283  tIndexTs *index;
284  bool isPesRecording;
287  cMutex mutex;
288  static cMutex indexListMutex;
290  static void AddToIndexList(const cIndexFile *IndexFile);
291  static void RemoveFromIndexList(const cIndexFile *IndexFile);
292  static bool IsInIndexList(const cIndexFile *IndexFile);
293  void ConvertFromPes(tIndexTs *IndexTs, int Count);
294  void ConvertToPes(tIndexTs *IndexTs, int Count);
295  bool CatchUp(int Index = -1);
296 public:
297  cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false, bool PauseLive = false);
298  ~cIndexFile();
299  bool Ok(void) { return index != NULL; }
300  bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset);
301  bool Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *Independent = NULL, int *Length = NULL);
302  int GetNextIFrame(int Index, bool Forward, uint16_t *FileNumber = NULL, off_t *FileOffset = NULL, int *Length = NULL);
303  int Get(uint16_t FileNumber, off_t FileOffset);
304  int Last(void) { CatchUp(); return last; }
305  int GetResume(void) { return resumeFile.Read(); }
306  bool StoreResume(int Index) { return resumeFile.Save(Index); }
307  bool IsStillRecording(void);
308  void Delete(void);
309  static int GetLength(const char *FileName, bool IsPesRecording = false);
312  static cString IndexFileName(const char *FileName, bool IsPesRecording);
313  };
314 
315 class cFileName {
316 private:
318  uint16_t fileNumber;
319  char *fileName, *pFileNumber;
320  bool record;
321  bool blocking;
322  bool isPesRecording;
323 public:
324  cFileName(const char *FileName, bool Record, bool Blocking = false, bool IsPesRecording = false);
325  ~cFileName();
326  const char *Name(void) { return fileName; }
327  uint16_t Number(void) { return fileNumber; }
328  bool GetLastPatPmtVersions(int &PatVersion, int &PmtVersion);
329  cUnbufferedFile *Open(void);
330  void Close(void);
331  cUnbufferedFile *SetOffset(int Number, off_t Offset = 0); // yes, Number is int for easier internal calculating
332  off_t MaxFileSize();
333  // Dynamic file size for this file
334  cUnbufferedFile *NextFile(void);
335  };
336 
337 cString IndexToHMSF(int Index, bool WithFrame = false, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
338  // Converts the given index to a string, optionally containing the frame number.
339 int HMSFToIndex(const char *HMSF, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
340  // Converts the given string (format: "hh:mm:ss.ff") to an index.
341 int SecondsToFrames(int Seconds, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
342  // Returns the number of frames corresponding to the given number of seconds.
343 
344 int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max);
345 
346 char *ExchangeChars(char *s, bool ToFileSystem);
347  // Exchanges the characters in the given string to or from a file system
348  // specific representation (depending on ToFileSystem). The given string will
349  // be modified and may be reallocated if more space is needed. The return
350  // value points to the resulting string, which may be different from s.
351 
352 bool GenerateIndex(const char *FileName);
353 
356 bool HasRecordingsSortMode(const char *Directory);
357 void GetRecordingsSortMode(const char *Directory);
358 void SetRecordingsSortMode(const char *Directory, eRecordingsSortMode SortMode);
359 void IncRecordingsSortMode(const char *Directory);
360 
361 #endif //__RECORDING_H