vdr  1.7.27
recording.h
Go to the documentation of this file.
00001 /*
00002  * recording.h: Recording file handling
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: recording.h 2.30 2012/03/13 12:41:05 kls Exp $
00008  */
00009 
00010 #ifndef __RECORDING_H
00011 #define __RECORDING_H
00012 
00013 #include <time.h>
00014 #include "channels.h"
00015 #include "config.h"
00016 #include "epg.h"
00017 #include "thread.h"
00018 #include "timers.h"
00019 #include "tools.h"
00020 
00021 #define FOLDERDELIMCHAR '~'
00022 #define TIMERMACRO_TITLE    "TITLE"
00023 #define TIMERMACRO_EPISODE  "EPISODE"
00024 
00025 //#define __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS // Code enclosed with this macro is deprecated and may be removed in a future version
00026 
00027 extern bool VfatFileSystem;
00028 extern int InstanceId;
00029 
00030 void RemoveDeletedRecordings(void);
00031 void AssertFreeDiskSpace(int Priority = 0, bool Force = false);
00036 
00037 class cResumeFile {
00038 private:
00039   char *fileName;
00040   bool isPesRecording;
00041 public:
00042   cResumeFile(const char *FileName, bool IsPesRecording);
00043   ~cResumeFile();
00044   int Read(void);
00045   bool Save(int Index);
00046   void Delete(void);
00047   };
00048 
00049 class cRecordingInfo {
00050   friend class cRecording;
00051 private:
00052   tChannelID channelID;
00053   char *channelName;
00054   const cEvent *event;
00055   cEvent *ownEvent;
00056   char *aux;
00057   double framesPerSecond;
00058   int priority;
00059   int lifetime;
00060   char *fileName;
00061   cRecordingInfo(const cChannel *Channel = NULL, const cEvent *Event = NULL);
00062   bool Read(FILE *f);
00063   void SetData(const char *Title, const char *ShortText, const char *Description);
00064   void SetAux(const char *Aux);
00065 public:
00066   cRecordingInfo(const char *FileName);
00067   ~cRecordingInfo();
00068   tChannelID ChannelID(void) const { return channelID; }
00069   const char *ChannelName(void) const { return channelName; }
00070   const cEvent *GetEvent(void) const { return event; }
00071   const char *Title(void) const { return event->Title(); }
00072   const char *ShortText(void) const { return event->ShortText(); }
00073   const char *Description(void) const { return event->Description(); }
00074   const cComponents *Components(void) const { return event->Components(); }
00075   const char *Aux(void) const { return aux; }
00076   double FramesPerSecond(void) const { return framesPerSecond; }
00077   void SetFramesPerSecond(double FramesPerSecond);
00078   bool Write(FILE *f, const char *Prefix = "") const;
00079   bool Read(void);
00080   bool Write(void) const;
00081   };
00082 
00083 class cRecording : public cListObject {
00084   friend class cRecordings;
00085 private:
00086   mutable int resume;
00087   mutable char *titleBuffer;
00088   mutable char *sortBuffer;
00089   mutable char *fileName;
00090   mutable char *name;
00091   mutable int fileSizeMB;
00092   mutable int numFrames;
00093   int channel;
00094   int instanceId;
00095   bool isPesRecording;
00096   double framesPerSecond;
00097   cRecordingInfo *info;
00098   cRecording(const cRecording&); // can't copy cRecording
00099   cRecording &operator=(const cRecording &); // can't assign cRecording
00100   static char *StripEpisodeName(char *s);
00101   char *SortName(void) const;
00102   int GetResume(void) const;
00103 #ifdef __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS
00104 public:
00105 #endif
00106   time_t start;
00107   int priority;
00108   int lifetime;
00109   time_t deleted;
00110 public:
00111   cRecording(cTimer *Timer, const cEvent *Event);
00112   cRecording(const char *FileName);
00113   virtual ~cRecording();
00114   time_t Start(void) const { return start; }
00115   int Priority(void) const { return priority; }
00116   int Lifetime(void) const { return lifetime; }
00117   time_t Deleted(void) const { return deleted; }
00118   virtual int Compare(const cListObject &ListObject) const;
00119   const char *Name(void) const { return name; }
00120   const char *FileName(void) const;
00121   const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
00122   const cRecordingInfo *Info(void) const { return info; }
00123   const char *PrefixFileName(char Prefix);
00124   const char *UpdateFileName(const char *FileName);
00125   int HierarchyLevels(void) const;
00126   void ResetResume(void) const;
00127   double FramesPerSecond(void) const { return framesPerSecond; }
00128   int NumFrames(void) const;
00131   int LengthInSeconds(void) const;
00133   int FileSizeMB(void) const;
00136   bool IsNew(void) const { return GetResume() <= 0; }
00137   bool IsEdited(void) const;
00138   bool IsPesRecording(void) const { return isPesRecording; }
00139   void ReadInfo(void);
00140   bool WriteInfo(void);
00141   void SetStartTime(time_t Start);
00149   bool Delete(void);
00152   bool Remove(void);
00155   bool Undelete(void);
00159   };
00160 
00161 class cRecordings : public cList<cRecording>, public cThread {
00162 private:
00163   static char *updateFileName;
00164   bool deleted;
00165   time_t lastUpdate;
00166   int state;
00167   const char *UpdateFileName(void);
00168   void Refresh(bool Foreground = false);
00169   void ScanVideoDir(const char *DirName, bool Foreground = false, int LinkLevel = 0);
00170 protected:
00171   void Action(void);
00172 public:
00173   cRecordings(bool Deleted = false);
00174   virtual ~cRecordings();
00175   bool Load(void) { return Update(true); }
00179   bool Update(bool Wait = false);
00185   void TouchUpdate(void);
00189   bool NeedsUpdate(void);
00190   void ChangeState(void) { state++; }
00191   bool StateChanged(int &State);
00192   void ResetResume(const char *ResumeFileName = NULL);
00193   cRecording *GetByName(const char *FileName);
00194   void AddByName(const char *FileName, bool TriggerUpdate = true);
00195   void DelByName(const char *FileName, bool RemoveRecording = true);
00196   void UpdateByName(const char *FileName);
00197   int TotalFileSizeMB(void);
00198   double MBperMinute(void);
00201   };
00202 
00203 extern cRecordings Recordings;
00204 extern cRecordings DeletedRecordings;
00205 
00206 #define DEFAULTFRAMESPERSECOND 25.0
00207 
00208 class cMark : public cListObject {
00209   friend class cMarks; // for sorting
00210 private:
00211   double framesPerSecond;
00212 #ifdef __RECORDING_H_DEPRECATED_DIRECT_MEMBER_ACCESS
00213 public:
00214 #endif
00215   int position;
00216   cString comment;
00217 public:
00218   cMark(int Position = 0, const char *Comment = NULL, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
00219   virtual ~cMark();
00220   int Position(void) const { return position; }
00221   const char *Comment(void) const { return comment; }
00222   void SetPosition(int Position) { position = Position; }
00223   void SetComment(const char *Comment) { comment = Comment; }
00224   cString ToText(void);
00225   bool Parse(const char *s);
00226   bool Save(FILE *f);
00227   };
00228 
00229 class cMarks : public cConfig<cMark> {
00230 private:
00231   cString fileName;
00232   double framesPerSecond;
00233   time_t nextUpdate;
00234   time_t lastFileTime;
00235   time_t lastChange;
00236 public:
00237   bool Load(const char *RecordingFileName, double FramesPerSecond = DEFAULTFRAMESPERSECOND, bool IsPesRecording = false);
00238   bool Update(void);
00239   void Sort(void);
00240   cMark *Add(int Position);
00241   cMark *Get(int Position);
00242   cMark *GetPrev(int Position);
00243   cMark *GetNext(int Position);
00244   };
00245 
00246 #define RUC_BEFORERECORDING "before"
00247 #define RUC_AFTERRECORDING  "after"
00248 #define RUC_EDITEDRECORDING "edited"
00249 
00250 class cRecordingUserCommand {
00251 private:
00252   static const char *command;
00253 public:
00254   static void SetCommand(const char *Command) { command = Command; }
00255   static void InvokeCommand(const char *State, const char *RecordingFileName);
00256   };
00257 
00258 // The maximum size of a single frame (up to HDTV 1920x1080):
00259 #define MAXFRAMESIZE  (KILOBYTE(1024) / TS_SIZE * TS_SIZE) // multiple of TS_SIZE to avoid breaking up TS packets
00260 
00261 // The maximum file size is limited by the range that can be covered
00262 // with a 40 bit 'unsigned int', which is 1TB. The actual maximum value
00263 // used is 6MB below the theoretical maximum, to have some safety (the
00264 // actual file size may be slightly higher because we stop recording only
00265 // before the next independent frame, to have a complete Group Of Pictures):
00266 #define MAXVIDEOFILESIZETS  1048570 // MB
00267 #define MAXVIDEOFILESIZEPES    2000 // MB
00268 #define MINVIDEOFILESIZE          1 // MB
00269 #define MAXVIDEOFILESIZEDEFAULT MAXVIDEOFILESIZEPES
00270 
00271 #define MINRECORDINGSIZE      25 // GB
00272 #define MAXRECORDINGSIZE     500 // GB
00273 #define DEFAULTRECORDINGSIZE 100 // GB
00274 // Dynamic recording size:
00275 // Keep recording file size at Setup.MaxVideoFileSize for as long as possible,
00276 // but switch to MAXVIDEOFILESIZE early enough, so that Setup.MaxRecordingSize
00277 // will be reached, before recording to file 65535.vdr
00278 
00279 struct tIndexTs;
00280 class cIndexFileGenerator;
00281 
00282 class cIndexFile {
00283 private:
00284   int f;
00285   cString fileName;
00286   int size, last;
00287   tIndexTs *index;
00288   bool isPesRecording;
00289   cResumeFile resumeFile;
00290   cIndexFileGenerator *indexFileGenerator;
00291   cMutex mutex;
00292   static cString IndexFileName(const char *FileName, bool IsPesRecording);
00293   void ConvertFromPes(tIndexTs *IndexTs, int Count);
00294   void ConvertToPes(tIndexTs *IndexTs, int Count);
00295   bool CatchUp(int Index = -1);
00296 public:
00297   cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false, bool PauseLive = false);
00298   ~cIndexFile();
00299   bool Ok(void) { return index != NULL; }
00300   bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset);
00301   bool Get(int Index, uint16_t *FileNumber, off_t *FileOffset, bool *Independent = NULL, int *Length = NULL);
00302   int GetNextIFrame(int Index, bool Forward, uint16_t *FileNumber = NULL, off_t *FileOffset = NULL, int *Length = NULL);
00303   int Get(uint16_t FileNumber, off_t FileOffset);
00304   int Last(void) { CatchUp(); return last; }
00305   int GetResume(void) { return resumeFile.Read(); }
00306   bool StoreResume(int Index) { return resumeFile.Save(Index); }
00307   bool IsStillRecording(void);
00308   void Delete(void);
00309   static int GetLength(const char *FileName, bool IsPesRecording = false);
00312   };
00313 
00314 class cFileName {
00315 private:
00316   cUnbufferedFile *file;
00317   uint16_t fileNumber;
00318   char *fileName, *pFileNumber;
00319   bool record;
00320   bool blocking;
00321   bool isPesRecording;
00322 public:
00323   cFileName(const char *FileName, bool Record, bool Blocking = false, bool IsPesRecording = false);
00324   ~cFileName();
00325   const char *Name(void) { return fileName; }
00326   uint16_t Number(void) { return fileNumber; }
00327   bool GetLastPatPmtVersions(int &PatVersion, int &PmtVersion);
00328   cUnbufferedFile *Open(void);
00329   void Close(void);
00330   cUnbufferedFile *SetOffset(int Number, off_t Offset = 0); // yes, Number is int for easier internal calculating
00331   off_t MaxFileSize();
00332       // Dynamic file size for this file
00333   cUnbufferedFile *NextFile(void);
00334   };
00335 
00336 cString IndexToHMSF(int Index, bool WithFrame = false, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
00337       // Converts the given index to a string, optionally containing the frame number.
00338 int HMSFToIndex(const char *HMSF, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
00339       // Converts the given string (format: "hh:mm:ss.ff") to an index.
00340 int SecondsToFrames(int Seconds, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
00341       // Returns the number of frames corresponding to the given number of seconds.
00342 
00343 int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max);
00344 
00345 char *ExchangeChars(char *s, bool ToFileSystem);
00346       // Exchanges the characters in the given string to or from a file system
00347       // specific representation (depending on ToFileSystem). The given string will
00348       // be modified and may be reallocated if more space is needed. The return
00349       // value points to the resulting string, which may be different from s.
00350 
00351 bool GenerateIndex(const char *FileName);
00352 
00353 #endif //__RECORDING_H