Move decoder (de)initialization into their respective classes
[alure.git] / include / main.h
blobc5f7618f2df2e8595119b101cbfb51a32d1e0888
1 #ifndef MAIN_H
2 #define MAIN_H
4 #include "AL/alure.h"
5 #include "alext.h"
7 #ifdef HAVE_SYS_TYPES_H
8 #include <sys/types.h>
9 #endif
10 #ifdef HAVE_SYS_WAIT_H
11 #include <sys/wait.h>
12 #endif
13 #ifdef HAVE_SIGNAL_H
14 #include <signal.h>
15 #endif
17 #ifdef HAVE_WINDOWS_H
19 #include <windows.h>
21 #else
23 #ifdef HAVE_DLFCN_H
24 #include <dlfcn.h>
25 #endif
27 #include <assert.h>
28 #include <pthread.h>
29 #ifdef HAVE_PTHREAD_NP_H
30 #include <pthread_np.h>
31 #endif
32 #include <errno.h>
34 typedef pthread_mutex_t CRITICAL_SECTION;
35 static inline void EnterCriticalSection(CRITICAL_SECTION *cs)
37 int ret;
38 ret = pthread_mutex_lock(cs);
39 assert(ret == 0);
41 static inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
43 int ret;
44 ret = pthread_mutex_unlock(cs);
45 assert(ret == 0);
47 static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
49 pthread_mutexattr_t attrib;
50 int ret;
52 ret = pthread_mutexattr_init(&attrib);
53 assert(ret == 0);
55 ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
56 #ifdef HAVE_PTHREAD_NP_H
57 if(ret != 0)
58 ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
59 #endif
60 assert(ret == 0);
61 ret = pthread_mutex_init(cs, &attrib);
62 assert(ret == 0);
64 pthread_mutexattr_destroy(&attrib);
66 static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
68 int ret;
69 ret = pthread_mutex_destroy(cs);
70 assert(ret == 0);
73 #endif
75 #include <map>
76 #include <streambuf>
77 #include <istream>
78 #include <list>
79 #include <algorithm>
80 #include <vector>
81 #include <memory>
83 static const union {
84 int val;
85 char b[sizeof(int)];
86 } endian_test = { 1 };
87 static const bool LittleEndian = (endian_test.b[0] != 0);
88 static const bool BigEndian = !LittleEndian;
91 void *OpenLib(const char *libname);
92 void CloseLib(void *handle);
93 #ifndef DYNLOAD
94 #define LOAD_FUNC(h, x) p##x = x
95 #else
96 void *GetLibProc(void *handle, const char *funcname);
98 template<typename T>
99 void LoadFunc(void *handle, const char *funcname, T **funcptr)
100 { *funcptr = reinterpret_cast<T*>(GetLibProc(handle, funcname)); }
102 #define LOAD_FUNC(h, x) LoadFunc((h), #x, &(p##x)); \
103 if(!(p##x)) \
105 CloseLib((h)); \
106 (h) = NULL; \
107 return; \
109 #endif
112 void SetError(const char *err);
113 ALuint DetectBlockAlignment(ALenum format);
114 ALuint DetectCompressionRate(ALenum format);
115 ALenum GetSampleFormat(ALuint channels, ALuint bits, bool isFloat);
117 struct UserCallbacks {
118 void* (*open_file)(const ALchar*);
119 void* (*open_mem)(const ALubyte*,ALuint);
120 ALboolean (*get_fmt)(void*,ALenum*,ALuint*,ALuint*);
121 ALuint (*decode)(void*,ALubyte*,ALuint);
122 ALboolean (*rewind)(void*);
123 void (*close)(void*);
125 extern std::map<ALint,UserCallbacks> InstalledCallbacks;
128 struct alureStream {
129 // Local copy of memory data
130 ALubyte *data;
132 // Storage when reading chunks
133 std::vector<ALubyte> dataChunk;
135 // Abstracted input stream
136 std::istream *fstream;
138 virtual bool IsValid() = 0;
139 virtual bool GetFormat(ALenum*,ALuint*,ALuint*) = 0;
140 virtual ALuint GetData(ALubyte*,ALuint) = 0;
141 virtual bool Rewind() = 0;
142 virtual bool SetOrder(ALuint order)
144 if(!order) return Rewind();
145 SetError("Invalid order for stream");
146 return false;
148 virtual bool SetPatchset(const char*)
149 { return true; }
151 alureStream(std::istream *_stream)
152 : data(NULL), fstream(_stream)
153 { StreamList.push_front(this); }
154 virtual ~alureStream()
156 delete[] data;
157 StreamList.erase(std::find(StreamList.begin(), StreamList.end(), this));
160 static void Clear(void)
162 while(StreamList.size() > 0)
163 alureDestroyStream(*(StreamList.begin()), 0, NULL);
166 static bool Verify(alureStream *stream)
168 ListType::iterator i = std::find(StreamList.begin(), StreamList.end(), stream);
169 return (i != StreamList.end());
172 private:
173 typedef std::list<alureStream*> ListType;
174 static ListType StreamList;
176 void StopStream(alureStream *stream);
179 struct MemDataInfo {
180 const ALubyte *Data;
181 size_t Length;
182 size_t Pos;
184 MemDataInfo() : Data(NULL), Length(0), Pos(0)
186 MemDataInfo(const MemDataInfo &inf) : Data(inf.Data), Length(inf.Length),
187 Pos(inf.Pos)
191 class MemStreamBuf : public std::streambuf {
192 MemDataInfo memInfo;
194 virtual int_type underflow();
195 virtual pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
196 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
198 public:
199 MemStreamBuf(const MemDataInfo &data)
200 : memInfo(data)
202 memInfo.Pos /= sizeof(char_type);
203 memInfo.Length /= sizeof(char_type);
205 virtual ~MemStreamBuf() { }
208 struct UserFuncs {
209 void* (*open)(const char *filename, ALuint mode);
210 void (*close)(void *f);
211 ALsizei (*read)(void *f, ALubyte *buf, ALuint count);
212 ALsizei (*write)(void *f, const ALubyte *buf, ALuint count);
213 alureInt64 (*seek)(void *f, alureInt64 offset, int whence);
215 extern UserFuncs Funcs;
217 class FileStreamBuf : public std::streambuf {
218 void *usrFile;
219 UserFuncs fio;
221 char buffer[1024];
223 virtual int_type underflow();
224 virtual pos_type seekoff(off_type offset, std::ios_base::seekdir whence, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
225 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
227 public:
228 bool IsOpen()
229 { return usrFile != NULL; }
231 FileStreamBuf(const char *filename, ALint mode)
232 : usrFile(NULL), fio(Funcs)
233 { usrFile = fio.open(filename, mode); }
234 virtual ~FileStreamBuf()
235 { if(usrFile) fio.close(usrFile); }
238 class InStream : public std::istream {
239 public:
240 InStream(const char *filename)
241 : std::istream(new FileStreamBuf(filename, 0))
243 if(!(static_cast<FileStreamBuf*>(rdbuf())->IsOpen()))
244 clear(failbit);
246 InStream(const MemDataInfo &memInfo)
247 : std::istream(new MemStreamBuf(memInfo))
249 virtual ~InStream()
250 { delete rdbuf(); }
254 static inline ALuint read_le32(std::istream *file)
256 ALubyte buffer[4];
257 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
258 return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
261 static inline ALushort read_le16(std::istream *file)
263 ALubyte buffer[2];
264 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
265 return buffer[0] | (buffer[1]<<8);
268 static inline ALuint read_be32(std::istream *file)
270 ALubyte buffer[4];
271 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
272 return (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8) | buffer[3];
275 static inline ALushort read_be16(std::istream *file)
277 ALubyte buffer[2];
278 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
279 return (buffer[0]<<8) | buffer[1];
282 static inline ALuint read_be80extended(std::istream *file)
284 ALubyte buffer[10];
285 if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
286 ALuint mantissa, last = 0;
287 ALubyte exp = buffer[1];
288 exp = 30 - exp;
289 mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
290 while (exp--)
292 last = mantissa;
293 mantissa >>= 1;
295 if((last&1)) mantissa++;
296 return mantissa;
300 extern CRITICAL_SECTION cs_StreamPlay;
302 alureStream *create_stream(const char *fname);
303 alureStream *create_stream(const MemDataInfo &memData);
304 alureStream *create_stream(ALvoid *userdata, ALenum format, ALuint rate, const UserCallbacks &cb);
306 template <typename T>
307 const T& clamp(const T& val, const T& min, const T& max)
308 { return std::max(std::min(val, max), min); }
310 template <typename T>
311 void swap(T &val1, T &val2)
313 val1 ^= val2;
314 val2 ^= val1;
315 val1 ^= val2;
319 struct Decoder {
320 typedef std::auto_ptr<alureStream>(*FactoryType)(std::istream*);
321 typedef std::vector<FactoryType> ListType;
323 static const ListType& GetList();
325 protected:
326 static ListType& AddList(FactoryType func);
329 template<typename T>
330 struct DecoderDecl : public Decoder {
331 DecoderDecl()
333 T::Init();
334 AddList(Factory);
336 ~DecoderDecl()
338 ListType &list = AddList(NULL);
339 list.erase(std::find(list.begin(), list.end(), Factory));
340 T::Deinit();
343 private:
344 static std::auto_ptr<alureStream> Factory(std::istream *file)
346 std::auto_ptr<alureStream> ret(new T(file));
347 if(ret->IsValid()) return ret;
348 return std::auto_ptr<alureStream>();
352 #endif // MAIN_H