Restore context for another EOS callback call
[alure.git] / include / main.h
blobc11b08181c5f92f65531f50694fa211c36fefe0e
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 #ifdef _MSC_VER
22 #if _MSC_VER >= 1600
23 #define typeof decltype
24 #endif
25 #endif
27 #else
29 #ifdef HAVE_DLFCN_H
30 #include <dlfcn.h>
31 #endif
33 #include <assert.h>
34 #include <pthread.h>
35 #ifdef HAVE_PTHREAD_NP_H
36 #include <pthread_np.h>
37 #endif
38 #include <errno.h>
40 typedef pthread_mutex_t CRITICAL_SECTION;
41 static inline void EnterCriticalSection(CRITICAL_SECTION *cs)
43 int ret;
44 ret = pthread_mutex_lock(cs);
45 assert(ret == 0);
47 static inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
49 int ret;
50 ret = pthread_mutex_unlock(cs);
51 assert(ret == 0);
53 static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
55 pthread_mutexattr_t attrib;
56 int ret;
58 ret = pthread_mutexattr_init(&attrib);
59 assert(ret == 0);
61 ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
62 #ifdef HAVE_PTHREAD_NP_H
63 if(ret != 0)
64 ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
65 #endif
66 assert(ret == 0);
67 ret = pthread_mutex_init(cs, &attrib);
68 assert(ret == 0);
70 pthread_mutexattr_destroy(&attrib);
72 static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
74 int ret;
75 ret = pthread_mutex_destroy(cs);
76 assert(ret == 0);
79 #endif
81 #include <map>
82 #include <streambuf>
83 #include <istream>
84 #include <list>
85 #include <algorithm>
86 #include <vector>
87 #include <memory>
89 static const union {
90 int val;
91 char b[sizeof(int)];
92 } endian_test = { 1 };
93 static const bool LittleEndian = (endian_test.b[0] != 0);
94 static const bool BigEndian = !LittleEndian;
97 void *OpenLib(const char *libname);
98 void CloseLib(void *handle);
99 #ifndef DYNLOAD
100 #define LOAD_FUNC(h, x) p##x = x
101 #else
102 void *GetLibProc(void *handle, const char *funcname);
104 template<typename T>
105 void LoadFunc(void *handle, const char *funcname, T **funcptr)
106 { *funcptr = reinterpret_cast<T*>(GetLibProc(handle, funcname)); }
108 #define LOAD_FUNC(h, x) LoadFunc((h), #x, &(p##x)); \
109 if(!(p##x)) \
111 CloseLib((h)); \
112 (h) = NULL; \
113 return; \
115 #endif
118 extern PFNALCSETTHREADCONTEXTPROC alcSetThreadContext;
119 extern PFNALCGETTHREADCONTEXTPROC alcGetThreadContext;
121 void SetError(const char *err);
122 ALuint DetectBlockAlignment(ALenum format);
123 ALuint DetectCompressionRate(ALenum format);
124 ALenum GetSampleFormat(ALuint channels, ALuint bits, bool isFloat);
126 struct UserCallbacks {
127 void* (*open_file)(const ALchar*);
128 void* (*open_mem)(const ALubyte*,ALuint);
129 ALboolean (*get_fmt)(void*,ALenum*,ALuint*,ALuint*);
130 ALuint (*decode)(void*,ALubyte*,ALuint);
131 ALboolean (*rewind)(void*);
132 void (*close)(void*);
134 extern std::map<ALint,UserCallbacks> InstalledCallbacks;
137 struct alureStream {
138 // Local copy of memory data
139 ALubyte *data;
141 // Storage when reading chunks
142 std::vector<ALubyte> dataChunk;
144 // Abstracted input stream
145 std::istream *fstream;
147 virtual bool IsValid() = 0;
148 virtual bool GetFormat(ALenum*,ALuint*,ALuint*) = 0;
149 virtual ALuint GetData(ALubyte*,ALuint) = 0;
150 virtual bool Rewind() = 0;
151 virtual bool SetOrder(ALuint order)
153 if(!order) return Rewind();
154 SetError("Invalid order for stream");
155 return false;
157 virtual bool SetPatchset(const char*)
158 { return true; }
160 alureStream(std::istream *_stream)
161 : data(NULL), fstream(_stream)
162 { StreamList.push_front(this); }
163 virtual ~alureStream()
165 delete[] data;
166 StreamList.erase(std::find(StreamList.begin(), StreamList.end(), this));
169 static void Clear(void)
171 while(StreamList.size() > 0)
172 alureDestroyStream(*(StreamList.begin()), 0, NULL);
175 static bool Verify(alureStream *stream)
177 ListType::iterator i = std::find(StreamList.begin(), StreamList.end(), stream);
178 return (i != StreamList.end());
181 private:
182 typedef std::list<alureStream*> ListType;
183 static ListType StreamList;
185 void StopStream(alureStream *stream);
188 struct MemDataInfo {
189 const ALubyte *Data;
190 size_t Length;
191 size_t Pos;
193 MemDataInfo() : Data(NULL), Length(0), Pos(0)
195 MemDataInfo(const MemDataInfo &inf) : Data(inf.Data), Length(inf.Length),
196 Pos(inf.Pos)
200 class MemStreamBuf : public std::streambuf {
201 MemDataInfo memInfo;
203 virtual int_type underflow();
204 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);
205 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
207 public:
208 MemStreamBuf(const MemDataInfo &data)
209 : memInfo(data)
211 memInfo.Pos /= sizeof(char_type);
212 memInfo.Length /= sizeof(char_type);
214 virtual ~MemStreamBuf() { }
217 struct UserFuncs {
218 void* (*open)(const char *filename, ALuint mode);
219 void (*close)(void *f);
220 ALsizei (*read)(void *f, ALubyte *buf, ALuint count);
221 ALsizei (*write)(void *f, const ALubyte *buf, ALuint count);
222 alureInt64 (*seek)(void *f, alureInt64 offset, int whence);
224 extern UserFuncs Funcs;
226 class FileStreamBuf : public std::streambuf {
227 void *usrFile;
228 UserFuncs fio;
230 char buffer[1024];
232 virtual int_type underflow();
233 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);
234 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
236 public:
237 bool IsOpen()
238 { return usrFile != NULL; }
240 FileStreamBuf(const char *filename, ALint mode)
241 : usrFile(NULL), fio(Funcs)
242 { usrFile = fio.open(filename, mode); }
243 virtual ~FileStreamBuf()
244 { if(usrFile) fio.close(usrFile); }
247 class InStream : public std::istream {
248 public:
249 InStream(const char *filename)
250 : std::istream(new FileStreamBuf(filename, 0))
252 if(!(static_cast<FileStreamBuf*>(rdbuf())->IsOpen()))
253 clear(failbit);
255 InStream(const MemDataInfo &memInfo)
256 : std::istream(new MemStreamBuf(memInfo))
258 virtual ~InStream()
259 { delete rdbuf(); }
263 static inline ALuint read_le32(std::istream *file)
265 ALubyte buffer[4];
266 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
267 return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
270 static inline ALushort read_le16(std::istream *file)
272 ALubyte buffer[2];
273 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
274 return buffer[0] | (buffer[1]<<8);
277 static inline ALuint read_be32(std::istream *file)
279 ALubyte buffer[4];
280 if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
281 return (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8) | buffer[3];
284 static inline ALushort read_be16(std::istream *file)
286 ALubyte buffer[2];
287 if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
288 return (buffer[0]<<8) | buffer[1];
291 static inline ALuint read_be80extended(std::istream *file)
293 ALubyte buffer[10];
294 if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
295 ALuint mantissa, last = 0;
296 ALubyte exp = buffer[1];
297 exp = 30 - exp;
298 mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
299 while (exp--)
301 last = mantissa;
302 mantissa >>= 1;
304 if((last&1)) mantissa++;
305 return mantissa;
309 extern CRITICAL_SECTION cs_StreamPlay;
311 alureStream *create_stream(const char *fname);
312 alureStream *create_stream(const MemDataInfo &memData);
313 alureStream *create_stream(ALvoid *userdata, ALenum format, ALuint rate, const UserCallbacks &cb);
315 template <typename T>
316 const T& clamp(const T& val, const T& min, const T& max)
317 { return std::max(std::min(val, max), min); }
319 template <typename T>
320 void swap(T &val1, T &val2)
322 val1 ^= val2;
323 val2 ^= val1;
324 val1 ^= val2;
328 template<typename T1, typename T2>
329 T1 SearchSecond(T1 start, T1 end, T2 val)
331 while(start != end && start->second != val)
332 ++start;
333 return start;
336 struct Decoder {
337 typedef std::auto_ptr<alureStream>(*FactoryType)(std::istream*);
338 typedef std::multimap<ALint,FactoryType> ListType;
340 static const ListType& GetList();
342 protected:
343 static ListType& AddList(FactoryType func=NULL, ALint prio=0);
346 template<typename T, ALint prio>
347 struct DecoderDecl : public Decoder {
348 DecoderDecl()
350 T::Init();
351 AddList(Factory, prio);
353 ~DecoderDecl()
355 ListType &list = AddList();
356 list.erase(SearchSecond(list.begin(), list.end(), Factory));
357 T::Deinit();
360 private:
361 static std::auto_ptr<alureStream> Factory(std::istream *file)
363 std::auto_ptr<alureStream> ret(new T(file));
364 if(ret->IsValid()) return ret;
365 return std::auto_ptr<alureStream>();
369 Decoder &alure_init_wav(void);
370 Decoder &alure_init_aiff(void);
371 Decoder &alure_init_vorbisfile(void);
372 Decoder &alure_init_flac(void);
373 Decoder &alure_init_sndfile(void);
374 Decoder &alure_init_fluidsynth(void);
375 Decoder &alure_init_dumb(void);
376 Decoder &alure_init_modplug(void);
377 Decoder &alure_init_mpg123(void);
379 #endif // MAIN_H