Add support for MIDI using FluidSynth
[alure.git] / src / alure.cpp
blob606139ba471f329654559a636bb469c392b7fdde
1 /*
2 * ALURE OpenAL utility library
3 * Copyright (c) 2009 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 /* Title: Main and Miscellanious */
26 #include "config.h"
28 #include "main.h"
30 #include <string.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <time.h>
34 #ifdef HAVE_WINDOWS_H
35 #include <windows.h>
36 #endif
38 #include <vector>
39 #include <string>
40 #include <map>
42 std::map<ALint,UserCallbacks> InstalledCallbacks;
43 CRITICAL_SECTION cs_StreamPlay;
44 alureStream::ListType alureStream::StreamList;
46 void *vorbisfile_handle = NULL;
47 void *flac_handle = NULL;
48 void *dumb_handle = NULL;
49 void *mp123_handle = NULL;
50 void *sndfile_handle = NULL;
51 void *fsynth_handle = NULL;
53 #define MAKE_FUNC(x) typeof(x)* p##x
54 #ifdef HAS_VORBISFILE
55 MAKE_FUNC(ov_clear);
56 MAKE_FUNC(ov_info);
57 MAKE_FUNC(ov_open_callbacks);
58 MAKE_FUNC(ov_pcm_seek);
59 MAKE_FUNC(ov_read);
60 #endif
61 #ifdef HAS_FLAC
62 MAKE_FUNC(FLAC__stream_decoder_get_state);
63 MAKE_FUNC(FLAC__stream_decoder_finish);
64 MAKE_FUNC(FLAC__stream_decoder_new);
65 MAKE_FUNC(FLAC__stream_decoder_seek_absolute);
66 MAKE_FUNC(FLAC__stream_decoder_delete);
67 MAKE_FUNC(FLAC__stream_decoder_process_single);
68 MAKE_FUNC(FLAC__stream_decoder_init_stream);
69 #endif
70 #ifdef HAS_DUMB
71 MAKE_FUNC(dumbfile_open_ex);
72 MAKE_FUNC(dumbfile_close);
73 MAKE_FUNC(dumb_read_mod);
74 MAKE_FUNC(dumb_read_s3m);
75 MAKE_FUNC(dumb_read_xm);
76 MAKE_FUNC(dumb_read_it);
77 MAKE_FUNC(dumb_silence);
78 MAKE_FUNC(duh_sigrenderer_generate_samples);
79 MAKE_FUNC(duh_get_it_sigrenderer);
80 MAKE_FUNC(duh_end_sigrenderer);
81 MAKE_FUNC(unload_duh);
82 MAKE_FUNC(dumb_it_start_at_order);
83 MAKE_FUNC(dumb_it_set_loop_callback);
84 MAKE_FUNC(dumb_it_sr_get_speed);
85 MAKE_FUNC(dumb_it_sr_set_speed);
86 #endif
87 #ifdef HAS_MPG123
88 MAKE_FUNC(mpg123_read);
89 MAKE_FUNC(mpg123_init);
90 MAKE_FUNC(mpg123_open_feed);
91 MAKE_FUNC(mpg123_new);
92 MAKE_FUNC(mpg123_delete);
93 MAKE_FUNC(mpg123_feed);
94 MAKE_FUNC(mpg123_exit);
95 MAKE_FUNC(mpg123_getformat);
96 MAKE_FUNC(mpg123_format_none);
97 MAKE_FUNC(mpg123_decode);
98 MAKE_FUNC(mpg123_format);
99 #endif
100 #ifdef HAS_SNDFILE
101 MAKE_FUNC(sf_close);
102 MAKE_FUNC(sf_open_virtual);
103 MAKE_FUNC(sf_readf_short);
104 MAKE_FUNC(sf_seek);
105 #endif
106 #ifdef HAS_FLUIDSYNTH
107 MAKE_FUNC(fluid_settings_setstr);
108 MAKE_FUNC(fluid_synth_program_change);
109 MAKE_FUNC(fluid_synth_sfload);
110 MAKE_FUNC(fluid_settings_setnum);
111 MAKE_FUNC(fluid_synth_sysex);
112 MAKE_FUNC(fluid_synth_cc);
113 MAKE_FUNC(fluid_synth_pitch_bend);
114 MAKE_FUNC(fluid_synth_channel_pressure);
115 MAKE_FUNC(fluid_synth_write_float);
116 MAKE_FUNC(new_fluid_synth);
117 MAKE_FUNC(delete_fluid_settings);
118 MAKE_FUNC(delete_fluid_synth);
119 MAKE_FUNC(fluid_synth_program_reset);
120 MAKE_FUNC(fluid_settings_setint);
121 MAKE_FUNC(new_fluid_settings);
122 MAKE_FUNC(fluid_synth_write_s16);
123 MAKE_FUNC(fluid_synth_noteoff);
124 MAKE_FUNC(fluid_synth_sfunload);
125 MAKE_FUNC(fluid_synth_noteon);
126 #endif
127 #undef MAKE_FUNC
129 #if defined(_WIN32) && !defined(ALURE_STATIC_LIBRARY)
130 static void init_alure(void);
131 static void deinit_alure(void);
132 static struct MyConstructorClass {
133 ~MyConstructorClass()
134 { alureStream::Clear(); };
135 } MyConstructor;
137 extern "C" BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID reserved)
139 (void)reserved;
141 // Perform actions based on the reason for calling.
142 switch(reason)
144 case DLL_PROCESS_ATTACH:
145 DisableThreadLibraryCalls(module);
146 init_alure();
147 break;
149 case DLL_PROCESS_DETACH:
150 deinit_alure();
151 break;
153 return TRUE;
155 #elif defined(HAVE_GCC_CONSTRUCTOR)
156 static void init_alure(void) __attribute__((constructor));
157 static void deinit_alure(void) __attribute__((destructor));
158 static struct MyConstructorClass {
159 ~MyConstructorClass()
160 { alureStream::Clear(); };
161 } MyConstructor;
162 #else
163 static void init_alure(void);
164 static void deinit_alure(void);
166 static struct MyConstructorClass {
167 MyConstructorClass()
168 { init_alure(); };
169 ~MyConstructorClass()
170 { alureStream::Clear();
171 deinit_alure(); };
172 } MyConstructor;
173 #endif
175 #ifndef _WIN32
177 #ifdef DYNLOAD
178 static inline void *LoadLibraryA(const char *libname)
180 dlerror();
181 void *hdl = dlopen(libname, RTLD_NOW);
182 const char *err;
183 if((err=dlerror()) != NULL)
185 fprintf(stderr, "Error loading %s: %s\n", libname, err);
186 return NULL;
188 return hdl;
190 static inline void *GetProcAddress(void *hdl, const char *funcname)
192 dlerror();
193 void *fn = dlsym(hdl, funcname);
194 const char *err;
195 if((err=dlerror()) != NULL)
197 fprintf(stderr, "Error loading %s: %s\n", funcname, err);
198 return NULL;
200 return fn;
202 static inline void FreeLibrary(void *hdl)
204 dlclose(hdl);
206 #else // DYNLOAD
207 static inline void *LoadLibraryA(const char*)
208 { return (void*)0xDEADBEEF; }
209 static inline void FreeLibrary(void*)
211 #define LOAD_FUNC(h, x) p##x = x
212 #endif
214 #else // _WIN32
216 #ifndef DYNLOAD
217 #define LoadLibraryA(x) ((void*)0xDEADBEEF)
218 #define FreeLibrary(x)
219 #define LOAD_FUNC(h, x) p##x = x
220 #else
221 #define GetProcAddress(x,y) GetProcAddress((HINSTANCE)(x),(y))
222 #define FreeLibrary(x) FreeLibrary((HINSTANCE)(x))
223 #endif
225 #endif
227 static void init_alure(void)
229 InitializeCriticalSection(&cs_StreamPlay);
231 #ifndef LOAD_FUNC
232 #define LOAD_FUNC(h, x) p##x = (typeof(p##x))GetProcAddress(h##_handle, #x); \
233 if(!p##x) \
235 FreeLibrary(h##_handle); \
236 h##_handle = NULL; \
237 break; \
239 #endif
241 #ifdef _WIN32
242 #define VORBISFILE_LIB "vorbisfile.dll"
243 #define FLAC_LIB "libFLAC.dll"
244 #define DUMB_LIB "libdumb.dll"
245 #define MPG123_LIB "libmpg123.dll"
246 #define SNDFILE_LIB "libsndfile-1.dll"
247 #define FLUIDSYNTH_LIB "libfluidsynth.dll"
248 #elif defined(__APPLE__)
249 #define VORBISFILE_LIB "libvorbisfile.3.dylib"
250 #define FLAC_LIB "libFLAC.8.dylib"
251 #define DUMB_LIB "libdumb.dylib"
252 #define MPG123_LIB "libmpg123.0.dylib"
253 #define SNDFILE_LIB "libsndfile.1.dylib"
254 #define FLUIDSYNTH_LIB "libfluidsynth.1.dylib"
255 #else
256 #define VORBISFILE_LIB "libvorbisfile.so.3"
257 #define FLAC_LIB "libFLAC.so.8"
258 #define DUMB_LIB "libdumb.so"
259 #define MPG123_LIB "libmpg123.so.0"
260 #define SNDFILE_LIB "libsndfile.so.1"
261 #define FLUIDSYNTH_LIB "libfluidsynth.so.1"
262 #endif
264 #ifdef HAS_VORBISFILE
265 vorbisfile_handle = LoadLibraryA(VORBISFILE_LIB);
266 while(vorbisfile_handle)
268 LOAD_FUNC(vorbisfile, ov_clear);
269 LOAD_FUNC(vorbisfile, ov_info);
270 LOAD_FUNC(vorbisfile, ov_open_callbacks);
271 LOAD_FUNC(vorbisfile, ov_pcm_seek);
272 LOAD_FUNC(vorbisfile, ov_read);
273 break;
275 #endif
277 #ifdef HAS_FLAC
278 flac_handle = LoadLibraryA(FLAC_LIB);
279 while(flac_handle)
281 LOAD_FUNC(flac, FLAC__stream_decoder_get_state);
282 LOAD_FUNC(flac, FLAC__stream_decoder_finish);
283 LOAD_FUNC(flac, FLAC__stream_decoder_new);
284 LOAD_FUNC(flac, FLAC__stream_decoder_seek_absolute);
285 LOAD_FUNC(flac, FLAC__stream_decoder_delete);
286 LOAD_FUNC(flac, FLAC__stream_decoder_process_single);
287 LOAD_FUNC(flac, FLAC__stream_decoder_init_stream);
288 break;
290 #endif
292 #ifdef HAS_DUMB
293 dumb_handle = LoadLibraryA(DUMB_LIB);
294 while(dumb_handle)
296 LOAD_FUNC(dumb, dumbfile_open_ex);
297 LOAD_FUNC(dumb, dumbfile_close);
298 LOAD_FUNC(dumb, dumb_read_mod);
299 LOAD_FUNC(dumb, dumb_read_s3m);
300 LOAD_FUNC(dumb, dumb_read_xm);
301 LOAD_FUNC(dumb, dumb_read_it);
302 LOAD_FUNC(dumb, dumb_silence);
303 LOAD_FUNC(dumb, duh_sigrenderer_generate_samples);
304 LOAD_FUNC(dumb, duh_get_it_sigrenderer);
305 LOAD_FUNC(dumb, duh_end_sigrenderer);
306 LOAD_FUNC(dumb, unload_duh);
307 LOAD_FUNC(dumb, dumb_it_start_at_order);
308 LOAD_FUNC(dumb, dumb_it_set_loop_callback);
309 LOAD_FUNC(dumb, dumb_it_sr_get_speed);
310 LOAD_FUNC(dumb, dumb_it_sr_set_speed);
311 break;
313 #endif
315 #ifdef HAS_MPG123
316 mp123_handle = LoadLibraryA(MPG123_LIB);
317 while(mp123_handle)
319 LOAD_FUNC(mp123, mpg123_read);
320 LOAD_FUNC(mp123, mpg123_init);
321 LOAD_FUNC(mp123, mpg123_open_feed);
322 LOAD_FUNC(mp123, mpg123_new);
323 LOAD_FUNC(mp123, mpg123_delete);
324 LOAD_FUNC(mp123, mpg123_feed);
325 LOAD_FUNC(mp123, mpg123_exit);
326 LOAD_FUNC(mp123, mpg123_getformat);
327 LOAD_FUNC(mp123, mpg123_format_none);
328 LOAD_FUNC(mp123, mpg123_decode);
329 LOAD_FUNC(mp123, mpg123_format);
330 pmpg123_init();
331 break;
333 #endif
335 #ifdef HAS_SNDFILE
336 sndfile_handle = LoadLibraryA(SNDFILE_LIB);
337 while(sndfile_handle)
339 LOAD_FUNC(sndfile, sf_close);
340 LOAD_FUNC(sndfile, sf_open_virtual);
341 LOAD_FUNC(sndfile, sf_readf_short);
342 LOAD_FUNC(sndfile, sf_seek);
343 break;
345 #endif
347 #ifdef HAS_FLUIDSYNTH
348 fsynth_handle = LoadLibraryA(FLUIDSYNTH_LIB);
349 while(fsynth_handle)
351 LOAD_FUNC(fsynth, fluid_settings_setstr);
352 LOAD_FUNC(fsynth, fluid_synth_program_change);
353 LOAD_FUNC(fsynth, fluid_synth_sfload);
354 LOAD_FUNC(fsynth, fluid_settings_setnum);
355 LOAD_FUNC(fsynth, fluid_synth_sysex);
356 LOAD_FUNC(fsynth, fluid_synth_cc);
357 LOAD_FUNC(fsynth, fluid_synth_pitch_bend);
358 LOAD_FUNC(fsynth, fluid_synth_channel_pressure);
359 LOAD_FUNC(fsynth, fluid_synth_write_float);
360 LOAD_FUNC(fsynth, new_fluid_synth);
361 LOAD_FUNC(fsynth, delete_fluid_settings);
362 LOAD_FUNC(fsynth, delete_fluid_synth);
363 LOAD_FUNC(fsynth, fluid_synth_program_reset);
364 LOAD_FUNC(fsynth, fluid_settings_setint);
365 LOAD_FUNC(fsynth, new_fluid_settings);
366 LOAD_FUNC(fsynth, fluid_synth_write_s16);
367 LOAD_FUNC(fsynth, fluid_synth_noteoff);
368 LOAD_FUNC(fsynth, fluid_synth_sfunload);
369 LOAD_FUNC(fsynth, fluid_synth_noteon);
370 break;
372 #endif
374 #undef VORBISFILE_LIB
375 #undef FLAC_LIB
376 #undef DUMB_LIB
377 #undef MPG123_LIB
378 #undef SNDFILE_LIB
379 #undef LOAD_FUNC
382 static void deinit_alure(void)
384 #ifdef HAS_VORBISFILE
385 if(vorbisfile_handle)
386 FreeLibrary(vorbisfile_handle);
387 vorbisfile_handle = NULL;
388 #endif
389 #ifdef HAS_FLAC
390 if(flac_handle)
391 FreeLibrary(flac_handle);
392 flac_handle = NULL;
393 #endif
394 #ifdef HAS_DUMB
395 if(dumb_handle)
396 FreeLibrary(dumb_handle);
397 dumb_handle = NULL;
398 #endif
399 #ifdef HAS_MPG123
400 if(mp123_handle)
402 pmpg123_exit();
403 FreeLibrary(mp123_handle);
405 mp123_handle = NULL;
406 #endif
407 #ifdef HAS_SNDFILE
408 if(sndfile_handle)
409 FreeLibrary(sndfile_handle);
410 sndfile_handle = NULL;
411 #endif
413 DeleteCriticalSection(&cs_StreamPlay);
417 static const ALchar *last_error = "No error";
419 void SetError(const char *err)
421 last_error = err;
424 ALuint DetectBlockAlignment(ALenum format)
426 switch(format)
428 #define CHECK_RET(f,s) case (f): return (s)
429 CHECK_RET(AL_FORMAT_MONO8, sizeof(ALubyte));
430 CHECK_RET(AL_FORMAT_MONO16, sizeof(ALshort));
431 CHECK_RET(AL_FORMAT_MONO_FLOAT32, sizeof(ALfloat));
432 CHECK_RET(AL_FORMAT_MONO_DOUBLE_EXT, sizeof(ALdouble));
433 CHECK_RET(AL_FORMAT_MONO_MULAW, sizeof(ALubyte)*1);
435 CHECK_RET(AL_FORMAT_STEREO8, sizeof(ALubyte)*2);
436 CHECK_RET(AL_FORMAT_STEREO16, sizeof(ALshort)*2);
437 CHECK_RET(AL_FORMAT_STEREO_FLOAT32, sizeof(ALfloat)*2);
438 CHECK_RET(AL_FORMAT_STEREO_DOUBLE_EXT, sizeof(ALdouble)*2);
439 CHECK_RET(AL_FORMAT_STEREO_MULAW, sizeof(ALubyte)*2);
441 CHECK_RET(AL_FORMAT_QUAD8, sizeof(ALubyte)*4);
442 CHECK_RET(AL_FORMAT_QUAD16, sizeof(ALshort)*4);
443 CHECK_RET(AL_FORMAT_QUAD32, sizeof(ALfloat)*4);
444 CHECK_RET(AL_FORMAT_QUAD_MULAW, sizeof(ALubyte)*4);
446 CHECK_RET(AL_FORMAT_REAR8, sizeof(ALubyte)*2);
447 CHECK_RET(AL_FORMAT_REAR16, sizeof(ALshort)*2);
448 CHECK_RET(AL_FORMAT_REAR32, sizeof(ALfloat)*2);
449 CHECK_RET(AL_FORMAT_REAR_MULAW, sizeof(ALubyte)*2);
451 CHECK_RET(AL_FORMAT_51CHN8, sizeof(ALubyte)*6);
452 CHECK_RET(AL_FORMAT_51CHN16, sizeof(ALshort)*6);
453 CHECK_RET(AL_FORMAT_51CHN32, sizeof(ALfloat)*6);
454 CHECK_RET(AL_FORMAT_51CHN_MULAW, sizeof(ALubyte)*6);
456 CHECK_RET(AL_FORMAT_61CHN8, sizeof(ALubyte)*7);
457 CHECK_RET(AL_FORMAT_61CHN16, sizeof(ALshort)*7);
458 CHECK_RET(AL_FORMAT_61CHN32, sizeof(ALfloat)*7);
459 CHECK_RET(AL_FORMAT_61CHN_MULAW, sizeof(ALubyte)*7);
461 CHECK_RET(AL_FORMAT_71CHN8, sizeof(ALubyte)*8);
462 CHECK_RET(AL_FORMAT_71CHN16, sizeof(ALshort)*8);
463 CHECK_RET(AL_FORMAT_71CHN32, sizeof(ALfloat)*8);
464 CHECK_RET(AL_FORMAT_71CHN_MULAW, sizeof(ALubyte)*8);
466 CHECK_RET(AL_FORMAT_MONO_IMA4, 36);
467 CHECK_RET(AL_FORMAT_STEREO_IMA4, 36*2);
468 #undef CHECK_RET
470 return 0;
473 ALuint DetectCompressionRate(ALenum format)
475 switch(format)
477 case AL_FORMAT_MONO8:
478 case AL_FORMAT_MONO16:
479 case AL_FORMAT_MONO_FLOAT32:
480 case AL_FORMAT_MONO_DOUBLE_EXT:
481 case AL_FORMAT_STEREO8:
482 case AL_FORMAT_STEREO16:
483 case AL_FORMAT_STEREO_FLOAT32:
484 case AL_FORMAT_STEREO_DOUBLE_EXT:
485 case AL_FORMAT_QUAD8:
486 case AL_FORMAT_QUAD16:
487 case AL_FORMAT_QUAD32:
488 case AL_FORMAT_REAR8:
489 case AL_FORMAT_REAR16:
490 case AL_FORMAT_REAR32:
491 case AL_FORMAT_51CHN8:
492 case AL_FORMAT_51CHN16:
493 case AL_FORMAT_51CHN32:
494 case AL_FORMAT_61CHN8:
495 case AL_FORMAT_61CHN16:
496 case AL_FORMAT_61CHN32:
497 case AL_FORMAT_71CHN8:
498 case AL_FORMAT_71CHN16:
499 case AL_FORMAT_71CHN32:
500 return 1;
502 case AL_FORMAT_MONO_MULAW:
503 case AL_FORMAT_STEREO_MULAW:
504 case AL_FORMAT_QUAD_MULAW:
505 case AL_FORMAT_REAR_MULAW:
506 case AL_FORMAT_51CHN_MULAW:
507 case AL_FORMAT_61CHN_MULAW:
508 case AL_FORMAT_71CHN_MULAW:
509 return 1;
511 case AL_FORMAT_MONO_IMA4:
512 case AL_FORMAT_STEREO_IMA4:
513 return 65;
515 fprintf(stderr, "Alure lib: Unhandled format: %#x\n", format);
516 return 0;
519 ALenum GetSampleFormat(ALuint channels, ALuint bits, bool isFloat)
521 #define CHECK_FMT_RET(f) do { \
522 ALenum fmt = alGetEnumValue(#f); \
523 if(alGetError() == AL_NO_ERROR && fmt != 0 && fmt != -1) \
524 return fmt; \
525 } while(0)
526 if(!isFloat)
528 if(bits == 8)
530 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO8);
531 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO8);
532 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
534 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD8);
535 if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN8);
536 if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN8);
537 if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN8);
539 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
541 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD8_LOKI);
543 SetError("Unsupported 8-bit channel count\n");
544 return AL_NONE;
546 if(bits == 16)
548 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO16);
549 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO16);
550 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
552 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD16);
553 if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN16);
554 if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN16);
555 if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN16);
557 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
559 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD16_LOKI);
561 SetError("Unsupported 16-bit channel count\n");
562 return AL_NONE;
564 SetError("Unsupported PCM bit depth\n");
565 return AL_NONE;
568 if(bits == 32 && alIsExtensionPresent("AL_EXT_FLOAT32"))
570 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO_FLOAT32);
571 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO_FLOAT32);
572 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
574 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD32);
575 if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN32);
576 if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN32);
577 if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN32);
579 SetError("Unsupported float32 channel count\n");
580 return AL_NONE;
582 if(bits == 64 && alIsExtensionPresent("AL_EXT_DOUBLE"))
584 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO_DOUBLE_EXT);
585 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO_DOUBLE_EXT);
586 SetError("Unsupported double channel count\n");
587 return AL_NONE;
589 #undef CHECK_FMT_RET
591 SetError("Unsupported float bit depth\n");
592 return AL_NONE;
595 extern "C" {
597 /* Function: alureGetVersion
599 * Stores the major and minor version of the library. If either major or minor
600 * are NULL, that value is not provided.
602 ALURE_API void ALURE_APIENTRY alureGetVersion(ALuint *major, ALuint *minor)
604 if(major) *major = ALURE_VER_MAJOR;
605 if(minor) *minor = ALURE_VER_MINOR;
608 /* Function: alureGetErrorString
610 * Returns a string describing the last error encountered.
612 ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(void)
614 const ALchar *ret = last_error;
615 last_error = "No error";
616 return ret;
620 /* Function: alureGetDeviceNames
622 * Gets an array of device name strings from OpenAL. This encapsulates
623 * AL_ENUMERATE_ALL_EXT (if supported and 'all' is true) and standard
624 * enumeration, with 'count' being set to the number of returned device
625 * names.
627 * Returns:
628 * An array of device name strings, or NULL on error.
630 * See Also:
631 * <alureFreeDeviceNames>
633 ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(ALCboolean all, ALCsizei *count)
635 const ALCchar *list = NULL;
636 if(all && alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
637 list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
638 else
639 list = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
640 if(!list)
642 alcGetError(NULL);
643 SetError("No device names found");
644 return NULL;
647 const ALCchar *cur = list;
648 ALuint retlistLen = 0;
649 while(*cur)
651 cur += strlen(cur)+1;
652 retlistLen++;
655 const ALCchar **retlist = new const ALCchar*[retlistLen+1];
656 retlistLen = 0;
657 cur = list;
658 while(*cur)
660 ALCuint len = strlen(cur)+1;
661 ALCchar *newstr = new ALCchar[len];
663 memcpy(newstr, cur, len);
664 cur += len;
666 retlist[retlistLen] = newstr;
667 retlistLen++;
669 retlist[retlistLen] = NULL;
671 *count = retlistLen;
672 return retlist;
675 /* Function: alureFreeDeviceNames
677 * Frees the device name array returned from alureGetDeviceNames.
679 * See Also:
680 * <alureGetDeviceNames>
682 ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(const ALCchar **names)
684 if(names)
686 for(ALCuint i = 0;names[i];i++)
687 delete[] const_cast<ALCchar*>(names[i]);
688 delete[] names;
693 /* Function: alureInitDevice
695 * Opens the named device, creates a context with the given attributes, and
696 * sets that context as current. The name and attribute list would be the same
697 * as what's passed to alcOpenDevice and alcCreateContext respectively.
699 * Returns:
700 * AL_FALSE on error.
702 * See Also:
703 * <alureShutdownDevice>
705 ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(const ALCchar *name, const ALCint *attribs)
707 ALCdevice *device = alcOpenDevice(name);
708 if(!device)
710 alcGetError(NULL);
712 SetError("Device open failed");
713 return AL_FALSE;
716 ALCcontext *context = alcCreateContext(device, attribs);
717 if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
719 if(context)
720 alcDestroyContext(context);
721 alcCloseDevice(device);
723 SetError("Context setup failed");
724 return AL_FALSE;
726 alcGetError(device);
728 return AL_TRUE;
731 /* Function: alureShutdownDevice
733 * Destroys the current context and closes its associated device.
735 * Returns:
736 * AL_FALSE on error.
738 * See Also:
739 * <alureInitDevice>
741 ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(void)
743 ALCcontext *context = alcGetCurrentContext();
744 ALCdevice *device = alcGetContextsDevice(context);
745 if(!context || !device)
747 alcGetError(device);
748 SetError("Failed to get current device");
749 return AL_FALSE;
752 if(alcMakeContextCurrent(NULL) == ALC_FALSE)
754 alcGetError(NULL);
755 SetError("Failed to unset current context");
756 return AL_FALSE;
759 alcDestroyContext(context);
760 alcCloseDevice(device);
761 alcGetError(NULL);
763 return AL_TRUE;
767 /* Function: alureGetSampleFormat
769 * Retrieves an OpenAL format for the given sample format. If bits is non-0,
770 * floatbits must be 0, and if floatbits is non-0, bits must be 0. The
771 * application should not rely on any particular format enum being returned as
772 * it is dependant on the available extensions. The returned format will be
773 * valid for the current context. Requires an active context.
775 * Returns:
776 * An OpenAL format enum for the given sample format, or AL_NONE if one can't
777 * be found.
779 ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(ALuint channels, ALuint bits, ALuint floatbits)
781 if(alGetError() != AL_NO_ERROR)
783 SetError("Existing OpenAL error");
784 return AL_NONE;
787 if(bits && floatbits)
789 SetError("Both bit-types specified");
790 return AL_NONE;
793 if(bits)
794 return GetSampleFormat(channels, bits, false);
795 return GetSampleFormat(channels, floatbits, true);
799 /* Function: alureInstallDecodeCallbacks
801 * Installs callbacks to enable ALURE to handle more file types. The index is
802 * the order that each given set of callbacks will be tried, starting at the
803 * most negative number (INT_MIN) and going up. Negative indices will be tried
804 * before the built-in decoders, and positive indices will be tried after.
805 * Installing callbacks onto the same index multiple times will remove the
806 * previous callbacks, and removing old callbacks won't affect any opened files
807 * using them (they'll continue to use the old functions until properly closed,
808 * although newly opened files will use the new ones). Passing NULL for all
809 * callbacks is a valid way to remove an installed set, otherwise certain
810 * callbacks must be specified. Callbacks that are not specified will assume
811 * failure.
813 * Parameters:
814 * open_file - This callback is expected to open the named file and prepare it
815 * for decoding. If the callbacks cannot decode the file, NULL
816 * should be returned to indicate failure. Upon success, a non-NULL
817 * handle must be returned, which will be used as a unique
818 * identifier for the decoder instance. This callback is required
819 * if open_memory is not specified.
820 * open_memory - This callback behaves the same as open_file, except it takes a
821 * memory segment for input instead of a filename. The given
822 * memory will remain valid while the instance is open. This
823 * callback is required if open_file is not specified.
824 * get_format - This callback is used to retrieve the format of the decoded
825 * data for the given instance. It is the responsibility of the
826 * function to make sure the returned format is valid for the
827 * current AL context (eg. don't return AL_FORMAT_QUAD16 if the
828 * AL_EXT_MCFORMATS extension isn't available). Returning 0 for
829 * samplerate or blocksize, or returning AL_NONE for format, will
830 * cause a failure. Returning AL_FALSE indicates failure. This
831 * callback is required.
832 * decode - This callback is called to get more decoded data. Up to the
833 * specified amount of bytes should be written to the data pointer.
834 * The number of bytes written should be a multiple of the block size,
835 * otherwise an OpenAL error may occur during buffering. The function
836 * should return the number of bytes written. This callback is
837 * required.
838 * rewind - This callback is for rewinding the instance so that the next decode
839 * calls for it will get audio data from the start of the sound file.
840 * If the stream fails to rewind, AL_FALSE should be returned.
841 * close - This callback is called at the end of processing for a particular
842 * instance. The handle will not be used further and any associated
843 * data may be deleted.
845 * Returns:
846 * AL_FALSE on error.
848 ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(ALint index,
849 void* (*open_file)(const ALchar *filename),
850 void* (*open_memory)(const ALubyte *data, ALuint length),
851 ALboolean (*get_format)(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize),
852 ALuint (*decode)(void *instance, ALubyte *data, ALuint bytes),
853 ALboolean (*rewind)(void *instance),
854 void (*close)(void *instance))
856 if(!open_file && !open_memory && !get_format && !decode && !rewind && !close)
858 std::map<ALint,UserCallbacks>::iterator i = InstalledCallbacks.find(index);
859 if(i != InstalledCallbacks.end())
860 InstalledCallbacks.erase(i);
861 return AL_TRUE;
864 if((!open_file && !open_memory) || !get_format || !decode)
866 SetError("Missing callback functions");
867 return AL_FALSE;
870 UserCallbacks newcb;
871 newcb.open_file = open_file;
872 newcb.open_mem = open_memory;
873 newcb.get_fmt = get_format;
874 newcb.decode = decode;
875 newcb.rewind = rewind;
876 newcb.close = close;
878 InstalledCallbacks[index] = newcb;
880 return AL_TRUE;
884 /* Function: alureSleep
886 * Rests the calling thread for the given number of seconds.
888 * Returns:
889 * AL_FALSE on error.
891 ALURE_API ALboolean ALURE_APIENTRY alureSleep(ALfloat duration)
893 if(duration < 0.0f)
895 SetError("Invalid duration");
896 return AL_FALSE;
899 ALuint seconds = (ALuint)duration;
900 ALfloat rest = duration - (ALfloat)seconds;
902 #ifdef HAVE_NANOSLEEP
904 struct timespec t, remainingTime;
905 t.tv_sec = (time_t)seconds;
906 t.tv_nsec = (long)(rest*1000000)*1000;
908 while(nanosleep(&t, &remainingTime) < 0 && errno == EINTR)
909 t = remainingTime;
911 #elif defined(HAVE_WINDOWS_H)
913 while(seconds > 0)
915 Sleep(1000);
916 seconds--;
918 Sleep((DWORD)(rest * 1000));
920 #endif
922 return AL_TRUE;
926 /* Function: alureGetProcAddress
928 * Returns a pointer for the named ALURE function.
930 * Returns:
931 * NULL on error.
933 * *Version Added*: 1.1
935 ALURE_API void* ALURE_APIENTRY alureGetProcAddress(const ALchar *funcname)
937 static const struct {
938 const char *name;
939 void *func;
940 } FunctionList[] = {
941 #define ADD_FUNCTION(x) { #x, (void*)x },
942 ADD_FUNCTION(alureGetVersion)
943 ADD_FUNCTION(alureGetErrorString)
944 ADD_FUNCTION(alureGetDeviceNames)
945 ADD_FUNCTION(alureFreeDeviceNames)
946 ADD_FUNCTION(alureInitDevice)
947 ADD_FUNCTION(alureShutdownDevice)
948 ADD_FUNCTION(alureGetSampleFormat)
949 ADD_FUNCTION(alureSleep)
950 ADD_FUNCTION(alureCreateBufferFromFile)
951 ADD_FUNCTION(alureCreateBufferFromMemory)
952 ADD_FUNCTION(alureBufferDataFromFile)
953 ADD_FUNCTION(alureBufferDataFromMemory)
954 ADD_FUNCTION(alureCreateStreamFromFile)
955 ADD_FUNCTION(alureCreateStreamFromMemory)
956 ADD_FUNCTION(alureCreateStreamFromStaticMemory)
957 ADD_FUNCTION(alureCreateStreamFromCallback)
958 ADD_FUNCTION(alureRewindStream)
959 ADD_FUNCTION(alureDestroyStream)
960 ADD_FUNCTION(alureInstallDecodeCallbacks)
961 ADD_FUNCTION(alureSetIOCallbacks)
962 ADD_FUNCTION(alureGetProcAddress)
963 ADD_FUNCTION(alurePlaySourceStream)
964 ADD_FUNCTION(alurePlaySource)
965 ADD_FUNCTION(alureStopSource)
966 ADD_FUNCTION(alureGetSourceOffset)
967 #undef ADD_FUNCTION
968 { NULL, NULL }
971 size_t i;
972 for(i = 0;FunctionList[i].name;i++)
974 if(strcmp(FunctionList[i].name, funcname) == 0)
975 break;
978 if(!FunctionList[i].name)
979 SetError("Function not found");
980 return FunctionList[i].func;
983 } // extern "C"