Use a more compliant array of sample pointers for DUMB
[alure.git] / include / main.h
blob88ba1c92e6f09aea72b14a5c6c0158d1d69d9bce
1 #ifndef MAIN_H
2 #define MAIN_H
4 #include "AL/alure.h"
5 #include "alext.h"
7 #ifdef HAS_SNDFILE
8 #include <sndfile.h>
9 #endif
10 #ifdef HAS_VORBISFILE
11 #include <vorbis/vorbisfile.h>
12 #endif
13 #ifdef HAS_FLAC
14 #include <FLAC/all.h>
15 #endif
16 #ifdef HAS_MPG123
17 #include <mpg123.h>
18 #endif
19 #ifdef HAS_DUMB
20 #include <dumb.h>
21 #endif
22 #ifdef HAS_GSTREAMER
23 #include <gst/gst.h>
24 #include <gst/app/gstappsrc.h>
25 #include <gst/app/gstappsink.h>
26 #include <gst/app/gstappbuffer.h>
27 #endif
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
32 #endif
33 #ifdef HAVE_SYS_WAIT_H
34 #include <sys/wait.h>
35 #endif
36 #ifdef HAVE_SIGNAL_H
37 #include <signal.h>
38 #endif
40 #ifdef HAVE_WINDOWS_H
42 #include <windows.h>
44 #else
46 #ifdef HAVE_DLFCN_H
47 #include <dlfcn.h>
48 #endif
50 #include <assert.h>
51 #include <pthread.h>
52 #ifdef HAVE_PTHREAD_NP_H
53 #include <pthread_np.h>
54 #endif
55 #include <errno.h>
57 typedef pthread_mutex_t CRITICAL_SECTION;
58 static inline void EnterCriticalSection(CRITICAL_SECTION *cs)
60 int ret;
61 ret = pthread_mutex_lock(cs);
62 assert(ret == 0);
64 static inline void LeaveCriticalSection(CRITICAL_SECTION *cs)
66 int ret;
67 ret = pthread_mutex_unlock(cs);
68 assert(ret == 0);
70 static inline void InitializeCriticalSection(CRITICAL_SECTION *cs)
72 pthread_mutexattr_t attrib;
73 int ret;
75 ret = pthread_mutexattr_init(&attrib);
76 assert(ret == 0);
78 ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE);
79 #ifdef HAVE_PTHREAD_NP_H
80 if(ret != 0)
81 ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE);
82 #endif
83 assert(ret == 0);
84 ret = pthread_mutex_init(cs, &attrib);
85 assert(ret == 0);
87 pthread_mutexattr_destroy(&attrib);
89 static inline void DeleteCriticalSection(CRITICAL_SECTION *cs)
91 int ret;
92 ret = pthread_mutex_destroy(cs);
93 assert(ret == 0);
96 #endif
98 #include <map>
99 #include <streambuf>
100 #include <istream>
101 #include <list>
102 #include <algorithm>
104 static const union {
105 int val;
106 char b[sizeof(int)];
107 } endian_test = { 1 };
108 static const bool LittleEndian = (endian_test.b[0] != 0);
109 static const bool BigEndian = !LittleEndian;
112 void SetError(const char *err);
113 ALuint DetectBlockAlignment(ALenum format);
115 struct UserCallbacks {
116 void* (*open_file)(const ALchar*);
117 void* (*open_mem)(const ALubyte*,ALuint);
118 ALboolean (*get_fmt)(void*,ALenum*,ALuint*,ALuint*);
119 ALuint (*decode)(void*,ALubyte*,ALuint);
120 ALboolean (*rewind)(void*);
121 void (*close)(void*);
123 extern std::map<ALint,UserCallbacks> InstalledCallbacks;
126 struct alureStream {
127 ALubyte *data;
129 ALubyte *dataChunk;
130 ALsizei chunkLen;
132 std::istream *fstream;
134 virtual bool IsValid() = 0;
135 virtual bool GetFormat(ALenum*,ALuint*,ALuint*) = 0;
136 virtual ALuint GetData(ALubyte*,ALuint) = 0;
137 virtual bool Rewind() = 0;
138 virtual bool SetOrder(ALuint order)
140 if(!order) return Rewind();
141 SetError("Invalid order for stream");
142 return false;
145 alureStream(std::istream *_stream)
146 : data(NULL), dataChunk(NULL), fstream(_stream)
147 { StreamList.push_front(this); }
148 virtual ~alureStream()
150 delete[] data; delete[] dataChunk;
151 StreamList.erase(std::find(StreamList.begin(), StreamList.end(), this));
154 static void Clear(void)
156 while(StreamList.size() > 0)
157 alureDestroyStream(*(StreamList.begin()), 0, NULL);
160 static bool Verify(alureStream *stream)
162 ListType::iterator i = std::find(StreamList.begin(), StreamList.end(), stream);
163 return (i != StreamList.end());
166 private:
167 typedef std::list<alureStream*> ListType;
168 static ListType StreamList;
170 void StopStream(alureStream *stream);
173 struct MemDataInfo {
174 const ALubyte *Data;
175 size_t Length;
176 size_t Pos;
178 MemDataInfo() : Data(NULL), Length(0), Pos(0)
180 MemDataInfo(const MemDataInfo &inf) : Data(inf.Data), Length(inf.Length),
181 Pos(inf.Pos)
185 class MemStreamBuf : public std::streambuf {
186 MemDataInfo memInfo;
188 virtual int_type underflow();
189 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);
190 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
192 public:
193 MemStreamBuf(const MemDataInfo &data)
194 : memInfo(data)
196 memInfo.Pos /= sizeof(char_type);
197 memInfo.Length /= sizeof(char_type);
199 virtual ~MemStreamBuf() { }
202 struct UserFuncs {
203 void* (*open)(const char *filename, ALuint mode);
204 void (*close)(void *f);
205 ALsizei (*read)(void *f, ALubyte *buf, ALuint count);
206 ALsizei (*write)(void *f, const ALubyte *buf, ALuint count);
207 alureInt64 (*seek)(void *f, alureInt64 offset, int whence);
209 extern UserFuncs Funcs;
211 class FileStreamBuf : public std::streambuf {
212 void *usrFile;
213 UserFuncs fio;
215 char buffer[1024];
217 virtual int_type underflow();
218 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);
219 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out);
221 public:
222 bool IsOpen()
223 { return usrFile != NULL; }
225 FileStreamBuf(const char *filename, ALint mode)
226 : usrFile(NULL), fio(Funcs)
227 { usrFile = fio.open(filename, mode); }
228 virtual ~FileStreamBuf()
229 { if(usrFile) fio.close(usrFile); }
232 class InStream : public std::istream {
233 public:
234 InStream(const char *filename)
235 : std::istream(new FileStreamBuf(filename, 0))
237 if(!(static_cast<FileStreamBuf*>(rdbuf())->IsOpen()))
238 clear(failbit);
240 InStream(const MemDataInfo &memInfo)
241 : std::istream(new MemStreamBuf(memInfo))
243 virtual ~InStream()
244 { delete rdbuf(); }
248 struct customStream : public alureStream {
249 void *usrFile;
250 ALenum format;
251 ALuint samplerate;
252 ALuint blockAlign;
253 MemDataInfo memInfo;
255 UserCallbacks cb;
257 virtual bool IsValid();
258 virtual bool GetFormat(ALenum *format, ALuint *frequency, ALuint *blockalign);
259 virtual ALuint GetData(ALubyte *data, ALuint bytes);
260 virtual bool Rewind();
262 customStream(const char *fname, const UserCallbacks &callbacks);
263 customStream(const MemDataInfo &memData, const UserCallbacks &callbacks);
264 customStream(void *userdata, ALenum fmt, ALuint srate, const UserCallbacks &callbacks);
265 virtual ~customStream();
269 extern CRITICAL_SECTION cs_StreamPlay;
271 alureStream *create_stream(const char *fname);
272 alureStream *create_stream(const MemDataInfo &memData);
274 template <typename T>
275 const T& clamp(const T& val, const T& min, const T& max)
276 { return std::max(std::min(val, max), min); }
278 #endif // MAIN_H