Imported Upstream version 1.2
[platform/upstream/alure.git] / include / main.h
1 #ifndef MAIN_H
2 #define MAIN_H
3
4 #include "AL/alure.h"
5 #include "alext.h"
6
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
16
17 #ifdef HAVE_WINDOWS_H
18
19 #include <windows.h>
20
21 #ifdef _MSC_VER
22  #if _MSC_VER >= 1600
23   #define typeof decltype
24  #endif
25 #endif
26
27 #else
28
29 #ifdef HAVE_DLFCN_H
30 #include <dlfcn.h>
31 #endif
32
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>
39
40 typedef pthread_mutex_t CRITICAL_SECTION;
41 void EnterCriticalSection(CRITICAL_SECTION *cs);
42 void LeaveCriticalSection(CRITICAL_SECTION *cs);
43 void InitializeCriticalSection(CRITICAL_SECTION *cs);
44 void DeleteCriticalSection(CRITICAL_SECTION *cs);
45
46 #endif
47
48 #include <map>
49 #include <streambuf>
50 #include <istream>
51 #include <list>
52 #include <algorithm>
53 #include <vector>
54 #include <memory>
55
56 static const union {
57     int val;
58     char b[sizeof(int)];
59 } endian_test = { 1 };
60 static const bool LittleEndian = (endian_test.b[0] != 0);
61 static const bool BigEndian = !LittleEndian;
62
63
64 #ifdef DYNLOAD
65 void *OpenLib(const char *libname);
66 void CloseLib(void *handle);
67 void *GetLibProc(void *handle, const char *funcname);
68
69 template<typename T>
70 void LoadFunc(void *handle, const char *funcname, T **funcptr)
71 { *funcptr = reinterpret_cast<T*>(GetLibProc(handle, funcname)); }
72
73 #define LOAD_FUNC(h, x) LoadFunc((h), #x, &(p##x));                          \
74 if(!(p##x))                                                                  \
75 {                                                                            \
76     CloseLib((h));                                                           \
77     (h) = NULL;                                                              \
78     return;                                                                  \
79 }
80 #endif
81
82
83 extern PFNALCSETTHREADCONTEXTPROC palcSetThreadContext;
84 extern PFNALCGETTHREADCONTEXTPROC palcGetThreadContext;
85 #define alcSetThreadContext palcSetThreadContext
86 #define alcGetThreadContext palcGetThreadContext
87
88 void SetError(const char *err);
89 ALuint DetectBlockAlignment(ALenum format);
90 ALuint DetectCompressionRate(ALenum format);
91 ALenum GetSampleFormat(ALuint channels, ALuint bits, bool isFloat);
92
93 struct UserCallbacks {
94     void*     (*open_file)(const ALchar*);
95     void*     (*open_mem)(const ALubyte*,ALuint);
96     ALboolean (*get_fmt)(void*,ALenum*,ALuint*,ALuint*);
97     ALuint    (*decode)(void*,ALubyte*,ALuint);
98     ALboolean (*rewind)(void*);
99     void      (*close)(void*);
100 };
101 extern std::map<ALint,UserCallbacks> InstalledCallbacks;
102
103
104 void StopStream(alureStream *stream);
105 struct alureStream {
106     // Local copy of memory data
107     ALubyte *data;
108
109     // Storage when reading chunks
110     std::vector<ALubyte> dataChunk;
111
112     // Abstracted input stream
113     std::istream *fstream;
114
115     virtual bool IsValid() = 0;
116     virtual bool GetFormat(ALenum*,ALuint*,ALuint*) = 0;
117     virtual ALuint GetData(ALubyte*,ALuint) = 0;
118     virtual bool Rewind() = 0;
119     virtual bool SetOrder(ALuint order)
120     {
121         if(!order) return Rewind();
122         SetError("Invalid order for stream");
123         return false;
124     }
125     virtual bool SetPatchset(const char*)
126     { return true; }
127     virtual alureInt64 GetLength()
128     { return 0; }
129
130     alureStream(std::istream *_stream)
131       : data(NULL), fstream(_stream)
132     { StreamList.push_front(this); }
133     virtual ~alureStream()
134     {
135         delete[] data;
136         StreamList.erase(std::find(StreamList.begin(), StreamList.end(), this));
137     }
138
139     static void Clear(void)
140     {
141         while(StreamList.size() > 0)
142         {
143             alureStream *stream = *(StreamList.begin());
144             StopStream(stream);
145             std::istream *f = stream->fstream;
146             delete stream;
147             delete f;
148         }
149     }
150
151     static bool Verify(alureStream *stream)
152     {
153         ListType::iterator i = std::find(StreamList.begin(), StreamList.end(), stream);
154         return (i != StreamList.end());
155     }
156
157 private:
158     typedef std::list<alureStream*> ListType;
159     static ListType StreamList;
160 };
161
162
163 struct MemDataInfo {
164     const ALubyte *Data;
165     size_t Length;
166     size_t Pos;
167
168     MemDataInfo() : Data(NULL), Length(0), Pos(0)
169     { }
170     MemDataInfo(const MemDataInfo &inf) : Data(inf.Data), Length(inf.Length),
171                                           Pos(inf.Pos)
172     { }
173 };
174
175 class MemStreamBuf : public std::streambuf {
176     MemDataInfo memInfo;
177
178     virtual int_type underflow();
179     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);
180     virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
181
182 public:
183     MemStreamBuf(const MemDataInfo &data)
184       : memInfo(data)
185     {
186         memInfo.Pos /= sizeof(char_type);
187         memInfo.Length /= sizeof(char_type);
188     }
189     virtual ~MemStreamBuf() { }
190 };
191
192 struct UserFuncs {
193     void* (*open)(const char *filename, ALuint mode);
194     void (*close)(void *f);
195     ALsizei (*read)(void *f, ALubyte *buf, ALuint count);
196     ALsizei (*write)(void *f, const ALubyte *buf, ALuint count);
197     alureInt64 (*seek)(void *f, alureInt64 offset, int whence);
198 };
199 extern UserFuncs Funcs;
200 extern bool UsingSTDIO;
201
202 class FileStreamBuf : public std::streambuf {
203     void *usrFile;
204     UserFuncs fio;
205
206     char buffer[1024];
207
208     virtual int_type underflow();
209     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);
210     virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
211
212 public:
213     bool IsOpen()
214     { return usrFile != NULL; }
215
216     FileStreamBuf(const char *filename, ALint mode)
217       : usrFile(NULL), fio(Funcs)
218     { usrFile = fio.open(filename, mode); }
219     virtual ~FileStreamBuf()
220     { if(usrFile) fio.close(usrFile); }
221 };
222
223 class InStream : public std::istream {
224 public:
225     InStream(const char *filename)
226       : std::istream(new FileStreamBuf(filename, 0))
227     {
228         if(!(static_cast<FileStreamBuf*>(rdbuf())->IsOpen()))
229             clear(failbit);
230     }
231     InStream(const MemDataInfo &memInfo)
232       : std::istream(new MemStreamBuf(memInfo))
233     { }
234     virtual ~InStream()
235     { delete rdbuf(); }
236 };
237
238
239 static inline ALuint read_le32(std::istream *file)
240 {
241     ALubyte buffer[4];
242     if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
243     return buffer[0] | (buffer[1]<<8) | (buffer[2]<<16) | (buffer[3]<<24);
244 }
245
246 static inline ALushort read_le16(std::istream *file)
247 {
248     ALubyte buffer[2];
249     if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
250     return buffer[0] | (buffer[1]<<8);
251 }
252
253 static inline ALuint read_be32(std::istream *file)
254 {
255     ALubyte buffer[4];
256     if(!file->read(reinterpret_cast<char*>(buffer), 4)) return 0;
257     return (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8) | buffer[3];
258 }
259
260 static inline ALushort read_be16(std::istream *file)
261 {
262     ALubyte buffer[2];
263     if(!file->read(reinterpret_cast<char*>(buffer), 2)) return 0;
264     return (buffer[0]<<8) | buffer[1];
265 }
266
267 static inline ALuint read_be80extended(std::istream *file)
268 {
269     ALubyte buffer[10];
270     if(!file->read(reinterpret_cast<char*>(buffer), 10)) return 0;
271     ALuint mantissa, last = 0;
272     ALubyte exp = buffer[1];
273     exp = 30 - exp;
274     mantissa = (buffer[2]<<24) | (buffer[3]<<16) | (buffer[4]<<8) | buffer[5];
275     while (exp--)
276     {
277         last = mantissa;
278         mantissa >>= 1;
279     }
280     if((last&1)) mantissa++;
281     return mantissa;
282 }
283
284
285 extern CRITICAL_SECTION cs_StreamPlay;
286
287 alureStream *create_stream(const char *fname);
288 alureStream *create_stream(const MemDataInfo &memData);
289 alureStream *create_stream(ALvoid *userdata, ALenum format, ALuint rate, const UserCallbacks &cb);
290
291 template <typename T>
292 const T& clamp(const T& val, const T& min, const T& max)
293 { return std::max(std::min(val, max), min); }
294
295 template <typename T>
296 void swap(T &val1, T &val2)
297 {
298     val1 ^= val2;
299     val2 ^= val1;
300     val1 ^= val2;
301 }
302
303
304 template<typename T1, typename T2>
305 T1 SearchSecond(T1 start, T1 end, T2 val)
306 {
307     while(start != end && start->second != val)
308         ++start;
309     return start;
310 }
311
312 struct Decoder {
313     typedef std::auto_ptr<alureStream>(*FactoryType)(std::istream*);
314     typedef std::multimap<ALint,FactoryType> ListType;
315
316     static const ListType& GetList();
317
318 protected:
319     static ListType& AddList(FactoryType func=NULL, ALint prio=0);
320 };
321
322 template<typename T, ALint prio>
323 struct DecoderDecl : public Decoder {
324     DecoderDecl()
325     {
326         T::Init();
327         AddList(Factory, prio);
328     }
329     ~DecoderDecl()
330     {
331         ListType &list = AddList();
332         list.erase(SearchSecond(list.begin(), list.end(), Factory));
333         T::Deinit();
334     }
335
336 private:
337     static std::auto_ptr<alureStream> Factory(std::istream *file)
338     {
339         std::auto_ptr<alureStream> ret(new T(file));
340         if(ret->IsValid()) return ret;
341         return std::auto_ptr<alureStream>();
342     }
343 };
344
345 Decoder &alure_init_wav(void);
346 Decoder &alure_init_aiff(void);
347 Decoder &alure_init_vorbisfile(void);
348 Decoder &alure_init_flac(void);
349 Decoder &alure_init_sndfile(void);
350 Decoder &alure_init_fluidsynth(void);
351 Decoder &alure_init_dumb(void);
352 Decoder &alure_init_modplug(void);
353 Decoder &alure_init_mpg123(void);
354
355 #endif // MAIN_H