mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	- Added some missing braces in remux.c (thanks to Wayne Keer for reporting this one). - Removed unused MAINMENUENTRY from svdrpdemo.c (thanks to Udo Richter for reporting this one). - Fixed appending sequence end code in cDvbPlayer::Goto() (thanks to Reinhard Nissl). - Fixed syncing in cRepacker (thanks to Reinhard Nissl). - Now always using stream id 0xE0 for the video stream, to avoid problems with post processing tools that choke on different ids (suggested by Reinhard Nissl). - Updated the Estonian OSD texts (thanks to Arthur Konovalov). - Fixed cDvbPlayer::SkipFrames() to properly handle radio recordings (thanks to Reinhard Nissl). - Updated the Swedish OSD texts (thanks to Tomas Prybil). - Updated the Slovenian OSD texts (thanks to Matjaz Thaler). - Updated the Danish OSD texts (thanks to Mogens Elneff). - Made LIRC command parsing more robust (thanks to Ville Skyttä). - Introduced a separate 'plugins-install' target in the Makefile (thanks to Daniel Thompson). - Re-introduced the code that waits for a tuner lock in VDR/device.c, since apparently some users actually need it. It's not active by default, you'll have to define the WAIT_FOR_TUNER_LOCK macro in that file if you need it (suggested by Malcolm Caldwell). - Adjusted the Makefile to the dvb-kernel driver on kernel 2.6 and up (thanks to Lauri Tischler). - Repeat keys are now ignored when waiting for a keypress to cancel an operation (thanks to Marko Mäkelä). - The main menu function of a plugin can now be activated through a key macro of the form "@plugin" even if that plugin doesn't have a main menu entry (using part of a patch by Hardy Flor, which originally implemented calling plugins from SVDRP). - The menu timeout handling is now done centrally in the main program loop. - Added missing help for the 'help' keyword in the SVDRP command PLUG. - The main menu function of a plugin can now be called programmatically through the static function cRemote::CallPlugin(). - The SVDRP command PLUG now has a new option 'main' which can be used to initiate a call to the main menu function of a plugin (using part of a patch by Hardy Flor). - The new command line option '--vfat' can be used to make VDR encode special characters in recording file names, even if it wasn't compiled with VFAT=1 (suggested by Peter Bieringer). The compile time option VFAT still exists and creates a VDR that always behaves as if it were called with '--vfat'. - Replaced the ':' delimiter between hour and minute in recording file names with a '.' under Linux, too. Existing recordings with ':' as delimiter will still work. - Implemented the SVDRP command MOVC (thanks to Andreas Brachold). - Added support for multiple audio language codes in ISO639LanguageDescriptors to 'libsi' (thanks to Marcel Wiesweg). - Changed the audio PID language codes to hold up to two 3 letter codes, separated by '+', to store separate languages broadcast in two channel audio mode. - If the preferred audio language is broadcast on a PID that has two different languages in the two stereo channels, the audio channel is now properly set when switching to such a channel (thanks to Mogens Elneff for his help in testing this). - Fixed some typos in MANUAL (thanks to Ville Skyttä). - Fixed the default value for "Setup/EPG bugfix level" (thanks to Ville Skyttä for reporting this one). - Fixed defining timers that only differ in the day of week (thanks to Patrick Rother for reporting this one). - Fixed converting summary.vdr files that would result in a very long 'short text' (thanks to Carsten Koch). - Implemented a hash for the channels to reduce the system load in the EIT scanning thread (based on a patch by Georg Acher).
		
			
				
	
	
		
			290 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			290 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * tools.h: Various tools
 | |
|  *
 | |
|  * See the main source file 'vdr.c' for copyright information and
 | |
|  * how to reach the author.
 | |
|  *
 | |
|  * $Id: tools.h 1.76 2005/09/11 13:04:03 kls Exp $
 | |
|  */
 | |
| 
 | |
| #ifndef __TOOLS_H
 | |
| #define __TOOLS_H
 | |
| 
 | |
| #include <dirent.h>
 | |
| #include <errno.h>
 | |
| #include <fcntl.h>
 | |
| #include <poll.h>
 | |
| #include <stddef.h>
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <syslog.h>
 | |
| #include <sys/stat.h>
 | |
| #include <sys/types.h>
 | |
| 
 | |
| typedef unsigned char uchar;
 | |
| typedef unsigned long long int uint64;
 | |
| 
 | |
| extern int SysLogLevel;
 | |
| 
 | |
| #define esyslog(a...) void( (SysLogLevel > 0) ? syslog(LOG_ERR,   a) : void() )
 | |
| #define isyslog(a...) void( (SysLogLevel > 1) ? syslog(LOG_INFO,  a) : void() )
 | |
| #define dsyslog(a...) void( (SysLogLevel > 2) ? syslog(LOG_DEBUG, a) : void() )
 | |
| 
 | |
| #define LOG_ERROR         esyslog("ERROR (%s,%d): %m", __FILE__, __LINE__)
 | |
| #define LOG_ERROR_STR(s)  esyslog("ERROR: %s: %m", s)
 | |
| 
 | |
| #define SECSINDAY  86400
 | |
| 
 | |
| #define KILOBYTE(n) ((n) * 1024)
 | |
| #define MEGABYTE(n) ((n) * 1024 * 1024)
 | |
| 
 | |
| #define MAXPARSEBUFFER KILOBYTE(10)
 | |
| 
 | |
| #define MALLOC(type, size)  (type *)malloc(sizeof(type) * (size))
 | |
| 
 | |
| #define DELETENULL(p) (delete (p), p = NULL)
 | |
| 
 | |
| #define CHECK(s) { if ((s) < 0) LOG_ERROR; } // used for 'ioctl()' calls
 | |
| #define FATALERRNO (errno != EAGAIN && errno != EINTR)
 | |
| 
 | |
| #ifndef __STL_CONFIG_H // in case some plugin needs to use the STL
 | |
| template<class T> inline T min(T a, T b) { return a <= b ? a : b; }
 | |
| template<class T> inline T max(T a, T b) { return a >= b ? a : b; }
 | |
| template<class T> inline int sgn(T a) { return a < 0 ? -1 : a > 0 ? 1 : 0; }
 | |
| template<class T> inline void swap(T &a, T &b) { T t = a; a = b; b = t; }
 | |
| #endif
 | |
| 
 | |
| #define BCDCHARTOINT(x) (10 * ((x & 0xF0) >> 4) + (x & 0xF))
 | |
| int BCD2INT(int x);
 | |
| 
 | |
| // Unfortunately there are no platform independent macros for unaligned
 | |
| // access. so we do it this way:
 | |
| 
 | |
| template<class T> inline T get_unaligned(T *p)
 | |
| {
 | |
|   struct s { T v; } __attribute__((packed));
 | |
|   return ((s *)p)->v;
 | |
| }
 | |
| 
 | |
| template<class T> inline void put_unaligned(unsigned int v, T* p)
 | |
| {
 | |
|   struct s { T v; } __attribute__((packed));
 | |
|   ((s *)p)->v = v;
 | |
| }
 | |
| 
 | |
| class cString {
 | |
| private:
 | |
|   char *s;
 | |
| public:
 | |
|   cString(const char *S = NULL, bool TakePointer = false);
 | |
|   virtual ~cString();
 | |
|   operator const char * () const { return s; } // for use in (const char *) context
 | |
|   const char * operator*() const { return s; } // for use in (const void *) context (printf() etc.)
 | |
|   cString &operator=(const cString &String);
 | |
|   static cString sprintf(const char *fmt, ...);
 | |
|   };
 | |
| 
 | |
| ssize_t safe_read(int filedes, void *buffer, size_t size);
 | |
| ssize_t safe_write(int filedes, const void *buffer, size_t size);
 | |
| void writechar(int filedes, char c);
 | |
| int WriteAllOrNothing(int fd, const uchar *Data, int Length, int TimeoutMs = 0, int RetryMs = 0);
 | |
|     ///< Writes either all Data to the given file descriptor, or nothing at all.
 | |
|     ///< If TimeoutMs is greater than 0, it will only retry for that long, otherwise
 | |
|     ///< it will retry forever. RetryMs defines the time between two retries.
 | |
| char *strcpyrealloc(char *dest, const char *src);
 | |
| char *strn0cpy(char *dest, const char *src, size_t n);
 | |
| char *strreplace(char *s, char c1, char c2);
 | |
| char *strreplace(char *s, const char *s1, const char *s2); ///< re-allocates 's' and deletes the original string if necessary!
 | |
| char *skipspace(const char *s);
 | |
| char *stripspace(char *s);
 | |
| char *compactspace(char *s);
 | |
| cString strescape(const char *s, const char *chars);
 | |
| bool startswith(const char *s, const char *p);
 | |
| bool endswith(const char *s, const char *p);
 | |
| bool isempty(const char *s);
 | |
| int numdigits(int n);
 | |
| bool isnumber(const char *s);
 | |
| cString itoa(int n);
 | |
| cString AddDirectory(const char *DirName, const char *FileName);
 | |
| int FreeDiskSpaceMB(const char *Directory, int *UsedMB = NULL);
 | |
| bool DirectoryOk(const char *DirName, bool LogErrors = false);
 | |
| bool MakeDirs(const char *FileName, bool IsDirectory = false);
 | |
| bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
 | |
| bool RemoveEmptyDirectories(const char *DirName, bool RemoveThis = false);
 | |
| char *ReadLink(const char *FileName); ///< returns a new strings allocated on the heap, which the caller must delete (or NULL in case of an error)
 | |
| bool SpinUpDisk(const char *FileName);
 | |
| time_t LastModifiedTime(const char *FileName);
 | |
| cString WeekDayName(int WeekDay);
 | |
| cString WeekDayName(time_t t);
 | |
| cString DayDateTime(time_t t = 0);
 | |
| cString TimeToString(time_t t);
 | |
| cString DateString(time_t t);
 | |
| cString TimeString(time_t t);
 | |
| 
 | |
| class cTimeMs {
 | |
| private:
 | |
|   uint64 begin;
 | |
| public:
 | |
|   cTimeMs(void);
 | |
|   static uint64 Now(void);
 | |
|   void Set(int Ms = 0);
 | |
|   bool TimedOut(void);
 | |
|   uint64 Elapsed(void);
 | |
|   };
 | |
| 
 | |
| class cReadLine {
 | |
| private:
 | |
|   char buffer[MAXPARSEBUFFER];
 | |
| public:
 | |
|   char *Read(FILE *f);
 | |
|   };
 | |
| 
 | |
| class cPoller {
 | |
| private:
 | |
|   enum { MaxPollFiles = 16 };
 | |
|   pollfd pfd[MaxPollFiles];
 | |
|   int numFileHandles;
 | |
| public:
 | |
|   cPoller(int FileHandle = -1, bool Out = false);
 | |
|   bool Add(int FileHandle, bool Out);
 | |
|   bool Poll(int TimeoutMs = 0);
 | |
|   };
 | |
|   
 | |
| class cReadDir {
 | |
| private:
 | |
|   DIR *directory;
 | |
|   struct dirent *result;
 | |
|   union { // according to "The GNU C Library Reference Manual"
 | |
|     struct dirent d;
 | |
|     char b[offsetof(struct dirent, d_name) + NAME_MAX + 1];
 | |
|     } u;
 | |
| public:
 | |
|   cReadDir(const char *Directory);
 | |
|   ~cReadDir();
 | |
|   bool Ok(void) { return directory != NULL; }
 | |
|   struct dirent *Next(void);
 | |
|   };
 | |
| 
 | |
| class cFile {
 | |
| private:
 | |
|   static bool files[];
 | |
|   static int maxFiles;
 | |
|   int f;
 | |
| public:
 | |
|   cFile(void);
 | |
|   ~cFile();
 | |
|   operator int () { return f; }
 | |
|   bool Open(const char *FileName, int Flags, mode_t Mode = DEFFILEMODE);
 | |
|   bool Open(int FileDes);
 | |
|   void Close(void);
 | |
|   bool IsOpen(void) { return f >= 0; }
 | |
|   bool Ready(bool Wait = true);
 | |
|   static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000);
 | |
|   static bool FileReady(int FileDes, int TimeoutMs = 1000);
 | |
|   static bool FileReadyForWriting(int FileDes, int TimeoutMs = 1000);
 | |
|   };
 | |
| 
 | |
| class cSafeFile {
 | |
| private:
 | |
|   FILE *f;
 | |
|   char *fileName;
 | |
|   char *tempName;
 | |
| public:
 | |
|   cSafeFile(const char *FileName);
 | |
|   ~cSafeFile();
 | |
|   operator FILE* () { return f; }
 | |
|   bool Open(void);
 | |
|   bool Close(void);
 | |
|   };
 | |
| 
 | |
| class cLockFile {
 | |
| private:
 | |
|   char *fileName;
 | |
|   int f;
 | |
| public:
 | |
|   cLockFile(const char *Directory);
 | |
|   ~cLockFile();
 | |
|   bool Lock(int WaitSeconds = 0);
 | |
|   void Unlock(void);
 | |
|   };
 | |
| 
 | |
| class cListObject {
 | |
| private:
 | |
|   cListObject *prev, *next;
 | |
| public:
 | |
|   cListObject(void);
 | |
|   virtual ~cListObject();
 | |
|   virtual int Compare(const cListObject &ListObject) const { return 0; }
 | |
|       ///< Must return 0 if this object is equal to ListObject, a positive value
 | |
|       ///< if it is "greater", and a negative value if it is "smaller".
 | |
|   void Append(cListObject *Object);
 | |
|   void Insert(cListObject *Object);
 | |
|   void Unlink(void);
 | |
|   int Index(void) const;
 | |
|   cListObject *Prev(void) const { return prev; }
 | |
|   cListObject *Next(void) const { return next; }
 | |
|   };
 | |
| 
 | |
| class cListBase {
 | |
| protected:
 | |
|   cListObject *objects, *lastObject;
 | |
|   cListBase(void);
 | |
|   int count;
 | |
| public:
 | |
|   virtual ~cListBase();
 | |
|   void Add(cListObject *Object, cListObject *After = NULL);
 | |
|   void Ins(cListObject *Object, cListObject *Before = NULL);
 | |
|   void Del(cListObject *Object, bool DeleteObject = true);
 | |
|   virtual void Move(int From, int To);
 | |
|   void Move(cListObject *From, cListObject *To);
 | |
|   virtual void Clear(void);
 | |
|   cListObject *Get(int Index) const;
 | |
|   int Count(void) const { return count; }
 | |
|   void Sort(void);
 | |
|   };
 | |
| 
 | |
| template<class T> class cList : public cListBase {
 | |
| public:
 | |
|   T *Get(int Index) const { return (T *)cListBase::Get(Index); }
 | |
|   T *First(void) const { return (T *)objects; }
 | |
|   T *Last(void) const { return (T *)lastObject; }
 | |
|   T *Prev(const T *object) const { return (T *)object->cListObject::Prev(); } // need to call cListObject's members to
 | |
|   T *Next(const T *object) const { return (T *)object->cListObject::Next(); } // avoid ambiguities in case of a "list of lists"
 | |
|   };
 | |
| 
 | |
| class cHashObject : public cListObject {
 | |
|   friend class cHashBase;
 | |
| private:
 | |
|   unsigned int id;
 | |
|   cListObject *object;
 | |
| public:
 | |
|   cHashObject(cListObject *Object, unsigned int Id) { object = Object; id = Id; }
 | |
|   cListObject *Object(void) { return object; }
 | |
|   };
 | |
| 
 | |
| class cHashBase {
 | |
| private:
 | |
|   cList<cHashObject> **hashTable;
 | |
|   int size;
 | |
|   unsigned int hashfn(unsigned int Id) const { return Id % size; }
 | |
| protected:
 | |
|   cHashBase(int Size);
 | |
| public:
 | |
|   virtual ~cHashBase();
 | |
|   void Add(cListObject *Object, unsigned int Id);
 | |
|   void Del(cListObject *Object, unsigned int Id);
 | |
|   void Clear(void);
 | |
|   cListObject *Get(unsigned int Id) const;
 | |
|   cList<cHashObject> *GetList(unsigned int Id) const;
 | |
|   };
 | |
| 
 | |
| #define HASHSIZE 512
 | |
| 
 | |
| template<class T> class cHash : public cHashBase {
 | |
| public:
 | |
|   cHash(int Size = HASHSIZE) : cHashBase(Size) {}
 | |
|   T *Get(unsigned int Id) const { return (T *)cHashBase::Get(Id); }
 | |
| };
 | |
| 
 | |
| #endif //__TOOLS_H
 |