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
24 /* Title: Main and Miscellanious */
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
57 MAKE_FUNC(ov_open_callbacks
);
58 MAKE_FUNC(ov_pcm_seek
);
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
);
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
);
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
);
102 MAKE_FUNC(sf_open_virtual
);
103 MAKE_FUNC(sf_readf_short
);
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
);
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(); };
137 extern "C" BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID reserved
)
141 // Perform actions based on the reason for calling.
144 case DLL_PROCESS_ATTACH
:
145 DisableThreadLibraryCalls(module
);
149 case DLL_PROCESS_DETACH
:
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(); };
163 static void init_alure(void);
164 static void deinit_alure(void);
166 static struct MyConstructorClass
{
169 ~MyConstructorClass()
170 { alureStream::Clear();
178 static inline void *LoadLibraryA(const char *libname
)
181 void *hdl
= dlopen(libname
, RTLD_NOW
);
183 if((err
=dlerror()) != NULL
)
185 fprintf(stderr
, "Error loading %s: %s\n", libname
, err
);
190 static inline void *GetProcAddress(void *hdl
, const char *funcname
)
193 void *fn
= dlsym(hdl
, funcname
);
195 if((err
=dlerror()) != NULL
)
197 fprintf(stderr
, "Error loading %s: %s\n", funcname
, err
);
202 static inline void FreeLibrary(void *hdl
)
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
217 #define LoadLibraryA(x) ((void*)0xDEADBEEF)
218 #define FreeLibrary(x)
219 #define LOAD_FUNC(h, x) p##x = x
221 #define GetProcAddress(x,y) GetProcAddress((HINSTANCE)(x),(y))
222 #define FreeLibrary(x) FreeLibrary((HINSTANCE)(x))
227 static void init_alure(void)
229 InitializeCriticalSection(&cs_StreamPlay
);
232 #define LOAD_FUNC(h, x) p##x = (typeof(p##x))GetProcAddress(h##_handle, #x); \
235 FreeLibrary(h##_handle); \
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"
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"
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
);
278 flac_handle
= LoadLibraryA(FLAC_LIB
);
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
);
293 dumb_handle
= LoadLibraryA(DUMB_LIB
);
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
);
316 mp123_handle
= LoadLibraryA(MPG123_LIB
);
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
);
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
);
347 #ifdef HAS_FLUIDSYNTH
348 fsynth_handle
= LoadLibraryA(FLUIDSYNTH_LIB
);
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
);
374 #undef VORBISFILE_LIB
382 static void deinit_alure(void)
384 #ifdef HAS_VORBISFILE
385 if(vorbisfile_handle
)
386 FreeLibrary(vorbisfile_handle
);
387 vorbisfile_handle
= NULL
;
391 FreeLibrary(flac_handle
);
396 FreeLibrary(dumb_handle
);
403 FreeLibrary(mp123_handle
);
409 FreeLibrary(sndfile_handle
);
410 sndfile_handle
= NULL
;
413 DeleteCriticalSection(&cs_StreamPlay
);
417 static const ALchar
*last_error
= "No error";
419 void SetError(const char *err
)
424 ALuint
DetectBlockAlignment(ALenum 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);
473 ALuint
DetectCompressionRate(ALenum 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
:
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
:
511 case AL_FORMAT_MONO_IMA4
:
512 case AL_FORMAT_STEREO_IMA4
:
515 fprintf(stderr
, "Alure lib: Unhandled format: %#x\n", format
);
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) \
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");
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");
564 SetError("Unsupported PCM bit depth\n");
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");
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");
591 SetError("Unsupported float bit depth\n");
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";
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
628 * An array of device name strings, or NULL on error.
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
);
639 list
= alcGetString(NULL
, ALC_DEVICE_SPECIFIER
);
643 SetError("No device names found");
647 const ALCchar
*cur
= list
;
648 ALuint retlistLen
= 0;
651 cur
+= strlen(cur
)+1;
655 const ALCchar
**retlist
= new const ALCchar
*[retlistLen
+1];
660 ALCuint len
= strlen(cur
)+1;
661 ALCchar
*newstr
= new ALCchar
[len
];
663 memcpy(newstr
, cur
, len
);
666 retlist
[retlistLen
] = newstr
;
669 retlist
[retlistLen
] = NULL
;
675 /* Function: alureFreeDeviceNames
677 * Frees the device name array returned from alureGetDeviceNames.
680 * <alureGetDeviceNames>
682 ALURE_API ALvoid ALURE_APIENTRY
alureFreeDeviceNames(const ALCchar
**names
)
686 for(ALCuint i
= 0;names
[i
];i
++)
687 delete[] const_cast<ALCchar
*>(names
[i
]);
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.
703 * <alureShutdownDevice>
705 ALURE_API ALboolean ALURE_APIENTRY
alureInitDevice(const ALCchar
*name
, const ALCint
*attribs
)
707 ALCdevice
*device
= alcOpenDevice(name
);
712 SetError("Device open failed");
716 ALCcontext
*context
= alcCreateContext(device
, attribs
);
717 if(!context
|| alcMakeContextCurrent(context
) == ALC_FALSE
)
720 alcDestroyContext(context
);
721 alcCloseDevice(device
);
723 SetError("Context setup failed");
731 /* Function: alureShutdownDevice
733 * Destroys the current context and closes its associated device.
741 ALURE_API ALboolean ALURE_APIENTRY
alureShutdownDevice(void)
743 ALCcontext
*context
= alcGetCurrentContext();
744 ALCdevice
*device
= alcGetContextsDevice(context
);
745 if(!context
|| !device
)
748 SetError("Failed to get current device");
752 if(alcMakeContextCurrent(NULL
) == ALC_FALSE
)
755 SetError("Failed to unset current context");
759 alcDestroyContext(context
);
760 alcCloseDevice(device
);
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.
776 * An OpenAL format enum for the given sample format, or AL_NONE if one can't
779 ALURE_API ALenum ALURE_APIENTRY
alureGetSampleFormat(ALuint channels
, ALuint bits
, ALuint floatbits
)
781 if(alGetError() != AL_NO_ERROR
)
783 SetError("Existing OpenAL error");
787 if(bits
&& floatbits
)
789 SetError("Both bit-types specified");
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
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
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.
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
);
864 if((!open_file
&& !open_memory
) || !get_format
|| !decode
)
866 SetError("Missing callback functions");
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
;
878 InstalledCallbacks
[index
] = newcb
;
884 /* Function: alureSleep
886 * Rests the calling thread for the given number of seconds.
891 ALURE_API ALboolean ALURE_APIENTRY
alureSleep(ALfloat duration
)
895 SetError("Invalid duration");
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
)
911 #elif defined(HAVE_WINDOWS_H)
918 Sleep((DWORD
)(rest
* 1000));
926 /* Function: alureGetProcAddress
928 * Returns a pointer for the named ALURE function.
933 * *Version Added*: 1.1
935 ALURE_API
void* ALURE_APIENTRY
alureGetProcAddress(const ALchar
*funcname
)
937 static const struct {
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
)
972 for(i
= 0;FunctionList
[i
].name
;i
++)
974 if(strcmp(FunctionList
[i
].name
, funcname
) == 0)
978 if(!FunctionList
[i
].name
)
979 SetError("Function not found");
980 return FunctionList
[i
].func
;