2 * ALURE OpenAL utility library
3 * Copyright (C) 2009 by Chris Robinson.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 /* Title: Main and Miscellanious */
38 std::map
<ALint
,UserCallbacks
> InstalledCallbacks
;
39 CRITICAL_SECTION cs_StreamPlay
;
40 alureStream::ListType
alureStream::StreamList
;
42 void *vorbisfile_handle
= NULL
;
43 void *flac_handle
= NULL
;
44 void *dumb_handle
= NULL
;
45 void *mp123_handle
= NULL
;
46 void *sndfile_handle
= NULL
;
48 #define MAKE_FUNC(x) typeof(x)* p##x
52 MAKE_FUNC(ov_open_callbacks
);
53 MAKE_FUNC(ov_pcm_seek
);
57 MAKE_FUNC(FLAC__stream_decoder_get_state
);
58 MAKE_FUNC(FLAC__stream_decoder_finish
);
59 MAKE_FUNC(FLAC__stream_decoder_new
);
60 MAKE_FUNC(FLAC__stream_decoder_seek_absolute
);
61 MAKE_FUNC(FLAC__stream_decoder_delete
);
62 MAKE_FUNC(FLAC__stream_decoder_process_single
);
63 MAKE_FUNC(FLAC__stream_decoder_init_stream
);
66 MAKE_FUNC(dumbfile_open_ex
);
67 MAKE_FUNC(dumbfile_close
);
68 MAKE_FUNC(dumb_read_mod
);
69 MAKE_FUNC(dumb_read_s3m
);
70 MAKE_FUNC(dumb_read_xm
);
71 MAKE_FUNC(dumb_read_it
);
72 MAKE_FUNC(dumb_silence
);
73 MAKE_FUNC(duh_sigrenderer_generate_samples
);
74 MAKE_FUNC(duh_get_it_sigrenderer
);
75 MAKE_FUNC(duh_end_sigrenderer
);
76 MAKE_FUNC(unload_duh
);
77 MAKE_FUNC(dumb_it_start_at_order
);
78 MAKE_FUNC(dumb_it_set_loop_callback
);
79 MAKE_FUNC(dumb_it_sr_get_speed
);
80 MAKE_FUNC(dumb_it_sr_set_speed
);
83 MAKE_FUNC(mpg123_read
);
84 MAKE_FUNC(mpg123_init
);
85 MAKE_FUNC(mpg123_open_feed
);
86 MAKE_FUNC(mpg123_new
);
87 MAKE_FUNC(mpg123_delete
);
88 MAKE_FUNC(mpg123_feed
);
89 MAKE_FUNC(mpg123_exit
);
90 MAKE_FUNC(mpg123_getformat
);
91 MAKE_FUNC(mpg123_format_none
);
92 MAKE_FUNC(mpg123_decode
);
93 MAKE_FUNC(mpg123_format
);
97 MAKE_FUNC(sf_open_virtual
);
98 MAKE_FUNC(sf_readf_short
);
103 #if defined(_WIN32) && !defined(ALURE_STATIC_LIBRARY)
104 static void init_alure(void);
105 static void deinit_alure(void);
106 static struct MyConstructorClass
{
107 ~MyConstructorClass()
108 { alureStream::Clear(); };
111 extern "C" BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID reserved
)
115 // Perform actions based on the reason for calling.
118 case DLL_PROCESS_ATTACH
:
119 DisableThreadLibraryCalls(module
);
123 case DLL_PROCESS_DETACH
:
129 #elif defined(HAVE_GCC_CONSTRUCTOR)
130 static void init_alure(void) __attribute__((constructor
));
131 static void deinit_alure(void) __attribute__((destructor
));
132 static struct MyConstructorClass
{
133 ~MyConstructorClass()
134 { alureStream::Clear(); };
137 static void init_alure(void);
138 static void deinit_alure(void);
140 static struct MyConstructorClass
{
143 ~MyConstructorClass()
144 { alureStream::Clear();
152 static inline void *LoadLibraryA(const char *libname
)
154 void *hdl
= dlopen(libname
, RTLD_NOW
);
156 if((err
=dlerror()) != NULL
)
158 fprintf(stderr
, "Error loading %s: %s\n", libname
, err
);
163 static inline void *GetProcAddress(void *hdl
, const char *funcname
)
165 void *fn
= dlsym(hdl
, funcname
);
167 if((err
=dlerror()) != NULL
)
169 fprintf(stderr
, "Error loading %s: %s\n", funcname
, err
);
174 static inline void FreeLibrary(void *hdl
)
179 static inline void *LoadLibraryA(const char*)
180 { return (void*)0xDEADBEEF; }
181 static inline void FreeLibrary(void*)
183 #define LOAD_FUNC(h, x) p##x = x
189 #define LoadLibraryA(x) ((void*)0xDEADBEEF)
190 #define FreeLibrary(x)
191 #define LOAD_FUNC(h, x) p##x = x
193 #define GetProcAddress(x,y) GetProcAddress((HINSTANCE)(x),(y))
194 #define FreeLibrary(x) FreeLibrary((HINSTANCE)(x))
199 static void init_alure(void)
201 InitializeCriticalSection(&cs_StreamPlay
);
204 #define LOAD_FUNC(h, x) p##x = (typeof(p##x))GetProcAddress(h##_handle, #x); \
207 FreeLibrary(h##_handle); \
214 #define VORBISFILE_LIB "vorbisfile.dll"
215 #define FLAC_LIB "libFLAC.dll"
216 #define DUMB_LIB "libdumb.dll"
217 #define MPG123_LIB "libmpg123.dll"
218 #define SNDFILE_LIB "libsndfile-1.dll"
219 #elif defined(__APPLE__)
220 #define VORBISFILE_LIB "libvorbisfile.3.dylib"
221 #define FLAC_LIB "libFLAC.8.dylib"
222 #define DUMB_LIB "libdumb.dylib"
223 #define MPG123_LIB "libmpg123.0.dylib"
224 #define SNDFILE_LIB "libsndfile.1.dylib"
226 #define VORBISFILE_LIB "libvorbisfile.so.3"
227 #define FLAC_LIB "libFLAC.so.8"
228 #define DUMB_LIB "libdumb.so"
229 #define MPG123_LIB "libmpg123.so.0"
230 #define SNDFILE_LIB "libsndfile.so.1"
233 #ifdef HAS_VORBISFILE
234 vorbisfile_handle
= LoadLibraryA(VORBISFILE_LIB
);
235 while(vorbisfile_handle
)
237 LOAD_FUNC(vorbisfile
, ov_clear
);
238 LOAD_FUNC(vorbisfile
, ov_info
);
239 LOAD_FUNC(vorbisfile
, ov_open_callbacks
);
240 LOAD_FUNC(vorbisfile
, ov_pcm_seek
);
241 LOAD_FUNC(vorbisfile
, ov_read
);
247 flac_handle
= LoadLibraryA(FLAC_LIB
);
250 LOAD_FUNC(flac
, FLAC__stream_decoder_get_state
);
251 LOAD_FUNC(flac
, FLAC__stream_decoder_finish
);
252 LOAD_FUNC(flac
, FLAC__stream_decoder_new
);
253 LOAD_FUNC(flac
, FLAC__stream_decoder_seek_absolute
);
254 LOAD_FUNC(flac
, FLAC__stream_decoder_delete
);
255 LOAD_FUNC(flac
, FLAC__stream_decoder_process_single
);
256 LOAD_FUNC(flac
, FLAC__stream_decoder_init_stream
);
262 dumb_handle
= LoadLibraryA(DUMB_LIB
);
265 LOAD_FUNC(dumb
, dumbfile_open_ex
);
266 LOAD_FUNC(dumb
, dumbfile_close
);
267 LOAD_FUNC(dumb
, dumb_read_mod
);
268 LOAD_FUNC(dumb
, dumb_read_s3m
);
269 LOAD_FUNC(dumb
, dumb_read_xm
);
270 LOAD_FUNC(dumb
, dumb_read_it
);
271 LOAD_FUNC(dumb
, dumb_silence
);
272 LOAD_FUNC(dumb
, duh_sigrenderer_generate_samples
);
273 LOAD_FUNC(dumb
, duh_get_it_sigrenderer
);
274 LOAD_FUNC(dumb
, duh_end_sigrenderer
);
275 LOAD_FUNC(dumb
, unload_duh
);
276 LOAD_FUNC(dumb
, dumb_it_start_at_order
);
277 LOAD_FUNC(dumb
, dumb_it_set_loop_callback
);
278 LOAD_FUNC(dumb
, dumb_it_sr_get_speed
);
279 LOAD_FUNC(dumb
, dumb_it_sr_set_speed
);
285 mp123_handle
= LoadLibraryA(MPG123_LIB
);
288 LOAD_FUNC(mp123
, mpg123_read
);
289 LOAD_FUNC(mp123
, mpg123_init
);
290 LOAD_FUNC(mp123
, mpg123_open_feed
);
291 LOAD_FUNC(mp123
, mpg123_new
);
292 LOAD_FUNC(mp123
, mpg123_delete
);
293 LOAD_FUNC(mp123
, mpg123_feed
);
294 LOAD_FUNC(mp123
, mpg123_exit
);
295 LOAD_FUNC(mp123
, mpg123_getformat
);
296 LOAD_FUNC(mp123
, mpg123_format_none
);
297 LOAD_FUNC(mp123
, mpg123_decode
);
298 LOAD_FUNC(mp123
, mpg123_format
);
305 sndfile_handle
= LoadLibraryA(SNDFILE_LIB
);
306 while(sndfile_handle
)
308 LOAD_FUNC(sndfile
, sf_close
);
309 LOAD_FUNC(sndfile
, sf_open_virtual
);
310 LOAD_FUNC(sndfile
, sf_readf_short
);
311 LOAD_FUNC(sndfile
, sf_seek
);
316 #undef VORBISFILE_LIB
324 static void deinit_alure(void)
326 #ifdef HAS_VORBISFILE
327 if(vorbisfile_handle
)
328 FreeLibrary(vorbisfile_handle
);
329 vorbisfile_handle
= NULL
;
333 FreeLibrary(flac_handle
);
338 FreeLibrary(dumb_handle
);
345 FreeLibrary(mp123_handle
);
351 FreeLibrary(sndfile_handle
);
352 sndfile_handle
= NULL
;
355 DeleteCriticalSection(&cs_StreamPlay
);
359 static const ALchar
*last_error
= "No error";
361 void SetError(const char *err
)
366 ALuint
DetectBlockAlignment(ALenum format
)
370 #define CHECK_RET(f,s) case (f): return (s)
371 CHECK_RET(AL_FORMAT_MONO8
, sizeof(ALubyte
));
372 CHECK_RET(AL_FORMAT_MONO16
, sizeof(ALshort
));
373 CHECK_RET(AL_FORMAT_MONO_FLOAT32
, sizeof(ALfloat
));
374 CHECK_RET(AL_FORMAT_MONO_DOUBLE_EXT
, sizeof(ALdouble
));
375 CHECK_RET(AL_FORMAT_MONO_MULAW
, sizeof(ALubyte
)*1);
377 CHECK_RET(AL_FORMAT_STEREO8
, sizeof(ALubyte
)*2);
378 CHECK_RET(AL_FORMAT_STEREO16
, sizeof(ALshort
)*2);
379 CHECK_RET(AL_FORMAT_STEREO_FLOAT32
, sizeof(ALfloat
)*2);
380 CHECK_RET(AL_FORMAT_STEREO_DOUBLE_EXT
, sizeof(ALdouble
)*2);
381 CHECK_RET(AL_FORMAT_STEREO_MULAW
, sizeof(ALubyte
)*2);
383 CHECK_RET(AL_FORMAT_QUAD8
, sizeof(ALubyte
)*4);
384 CHECK_RET(AL_FORMAT_QUAD16
, sizeof(ALshort
)*4);
385 CHECK_RET(AL_FORMAT_QUAD32
, sizeof(ALfloat
)*4);
386 CHECK_RET(AL_FORMAT_QUAD_MULAW
, sizeof(ALubyte
)*4);
388 CHECK_RET(AL_FORMAT_REAR8
, sizeof(ALubyte
)*2);
389 CHECK_RET(AL_FORMAT_REAR16
, sizeof(ALshort
)*2);
390 CHECK_RET(AL_FORMAT_REAR32
, sizeof(ALfloat
)*2);
391 CHECK_RET(AL_FORMAT_REAR_MULAW
, sizeof(ALubyte
)*2);
393 CHECK_RET(AL_FORMAT_51CHN8
, sizeof(ALubyte
)*6);
394 CHECK_RET(AL_FORMAT_51CHN16
, sizeof(ALshort
)*6);
395 CHECK_RET(AL_FORMAT_51CHN32
, sizeof(ALfloat
)*6);
396 CHECK_RET(AL_FORMAT_51CHN_MULAW
, sizeof(ALubyte
)*6);
398 CHECK_RET(AL_FORMAT_61CHN8
, sizeof(ALubyte
)*7);
399 CHECK_RET(AL_FORMAT_61CHN16
, sizeof(ALshort
)*7);
400 CHECK_RET(AL_FORMAT_61CHN32
, sizeof(ALfloat
)*7);
401 CHECK_RET(AL_FORMAT_61CHN_MULAW
, sizeof(ALubyte
)*7);
403 CHECK_RET(AL_FORMAT_71CHN8
, sizeof(ALubyte
)*8);
404 CHECK_RET(AL_FORMAT_71CHN16
, sizeof(ALshort
)*8);
405 CHECK_RET(AL_FORMAT_71CHN32
, sizeof(ALfloat
)*8);
406 CHECK_RET(AL_FORMAT_71CHN_MULAW
, sizeof(ALubyte
)*8);
408 CHECK_RET(AL_FORMAT_MONO_IMA4
, 36);
409 CHECK_RET(AL_FORMAT_STEREO_IMA4
, 36*2);
412 fprintf(stderr
, "Alure lib: Unhandled format: %#x\n", format
);
416 void DetectCompressionRate(ALenum format
, ALuint
*framesperblock
)
420 #define CHECK_RET(f,s) case (f): *framesperblock = (s); return
421 case AL_FORMAT_MONO8
:
422 case AL_FORMAT_MONO16
:
423 case AL_FORMAT_MONO_FLOAT32
:
424 case AL_FORMAT_MONO_DOUBLE_EXT
:
425 case AL_FORMAT_STEREO8
:
426 case AL_FORMAT_STEREO16
:
427 case AL_FORMAT_STEREO_FLOAT32
:
428 case AL_FORMAT_STEREO_DOUBLE_EXT
:
429 case AL_FORMAT_QUAD8
:
430 case AL_FORMAT_QUAD16
:
431 case AL_FORMAT_QUAD32
:
432 case AL_FORMAT_REAR8
:
433 case AL_FORMAT_REAR16
:
434 case AL_FORMAT_REAR32
:
435 case AL_FORMAT_51CHN8
:
436 case AL_FORMAT_51CHN16
:
437 case AL_FORMAT_51CHN32
:
438 case AL_FORMAT_61CHN8
:
439 case AL_FORMAT_61CHN16
:
440 case AL_FORMAT_61CHN32
:
441 case AL_FORMAT_71CHN8
:
442 case AL_FORMAT_71CHN16
:
443 case AL_FORMAT_71CHN32
:
447 case AL_FORMAT_MONO_MULAW
:
448 case AL_FORMAT_STEREO_MULAW
:
449 case AL_FORMAT_QUAD_MULAW
:
450 case AL_FORMAT_REAR_MULAW
:
451 case AL_FORMAT_51CHN_MULAW
:
452 case AL_FORMAT_61CHN_MULAW
:
453 case AL_FORMAT_71CHN_MULAW
:
457 case AL_FORMAT_MONO_IMA4
:
458 case AL_FORMAT_STEREO_IMA4
:
459 *framesperblock
= 65;
462 fprintf(stderr
, "Alure lib: Unhandled format: %#x\n", format
);
466 ALenum
GetSampleFormat(ALuint channels
, ALuint bits
, bool isFloat
)
468 #define CHECK_FMT_RET(f) do { \
469 ALenum fmt = alGetEnumValue(#f); \
470 if(alGetError() == AL_NO_ERROR && fmt != 0 && fmt != -1) \
477 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO8
);
478 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO8
);
479 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
481 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD8
);
482 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN8
);
483 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN8
);
484 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN8
);
486 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
488 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD8_LOKI
);
490 SetError("Unsupported channel count\n");
495 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO16
);
496 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO16
);
497 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
499 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD16
);
500 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN16
);
501 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN16
);
502 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN16
);
504 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
506 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD16_LOKI
);
508 SetError("Unsupported channel count\n");
516 if(alIsExtensionPresent("AL_EXT_FLOAT32"))
518 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO_FLOAT32
);
519 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO_FLOAT32
);
520 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
522 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD32
);
523 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN32
);
524 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN32
);
525 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN32
);
527 SetError("Unsupported channel count\n");
536 SetError("Unsupported float bit depth\n");
539 SetError("Unsupported PCM bit depth\n");
545 /* Function: alureGetVersion
547 * Stores the major and minor version of the library. If either major or minor
548 * are NULL, that value is not provided.
550 ALURE_API
void ALURE_APIENTRY
alureGetVersion(ALuint
*major
, ALuint
*minor
)
552 if(major
) *major
= ALURE_VER_MAJOR
;
553 if(minor
) *minor
= ALURE_VER_MINOR
;
556 /* Function: alureGetErrorString
558 * Returns a string describing the last error encountered.
560 ALURE_API
const ALchar
* ALURE_APIENTRY
alureGetErrorString(void)
562 const ALchar
*ret
= last_error
;
563 last_error
= "No error";
568 /* Function: alureGetDeviceNames
570 * Gets an array of device name strings from OpenAL. This encapsulates
571 * AL_ENUMERATE_ALL_EXT (if supported and 'all' is true) and standard
572 * enumeration, with 'count' being set to the number of returned device
576 * An array of device name strings, or NULL on error.
579 * <alureFreeDeviceNames>
581 ALURE_API
const ALCchar
** ALURE_APIENTRY
alureGetDeviceNames(ALCboolean all
, ALCsizei
*count
)
583 const ALCchar
*list
= NULL
;
584 if(all
&& alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT"))
585 list
= alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
);
587 list
= alcGetString(NULL
, ALC_DEVICE_SPECIFIER
);
591 SetError("No device names found");
595 const ALCchar
*cur
= list
;
596 ALuint retlistLen
= 0;
599 cur
+= strlen(cur
)+1;
603 const ALCchar
**retlist
= new const ALCchar
*[retlistLen
+1];
608 ALCuint len
= strlen(cur
)+1;
609 ALCchar
*newstr
= new ALCchar
[len
];
611 memcpy(newstr
, cur
, len
);
614 retlist
[retlistLen
] = newstr
;
617 retlist
[retlistLen
] = NULL
;
623 /* Function: alureFreeDeviceNames
625 * Frees the device name array returned from alureGetDeviceNames.
628 * <alureGetDeviceNames>
630 ALURE_API ALvoid ALURE_APIENTRY
alureFreeDeviceNames(const ALCchar
**names
)
634 for(ALCuint i
= 0;names
[i
];i
++)
635 delete[] const_cast<ALCchar
*>(names
[i
]);
641 /* Function: alureInitDevice
643 * Opens the named device, creates a context with the given attributes, and
644 * sets that context as current. The name and attribute list would be the same
645 * as what's passed to alcOpenDevice and alcCreateContext respectively.
651 * <alureShutdownDevice>
653 ALURE_API ALboolean ALURE_APIENTRY
alureInitDevice(const ALCchar
*name
, const ALCint
*attribs
)
655 ALCdevice
*device
= alcOpenDevice(name
);
660 SetError("Device open failed");
664 ALCcontext
*context
= alcCreateContext(device
, attribs
);
665 if(alcGetError(device
) != ALC_NO_ERROR
|| !context
)
667 alcCloseDevice(device
);
669 SetError("Context creation failed");
673 alcMakeContextCurrent(context
);
674 if(alcGetError(device
) != AL_NO_ERROR
)
676 alcDestroyContext(context
);
677 alcCloseDevice(device
);
679 SetError("Context setup failed");
686 /* Function: alureShutdownDevice
688 * Destroys the current context and closes its associated device.
696 ALURE_API ALboolean ALURE_APIENTRY
alureShutdownDevice(void)
698 ALCcontext
*context
= alcGetCurrentContext();
699 ALCdevice
*device
= alcGetContextsDevice(context
);
700 if(alcGetError(device
) != ALC_NO_ERROR
|| !device
)
702 SetError("Failed to get current device");
706 if(alcMakeContextCurrent(NULL
) == ALC_FALSE
)
709 SetError("Failed to unset current context");
713 alcDestroyContext(context
);
714 alcCloseDevice(device
);
721 /* Function: alureGetSampleFormat
723 * Retrieves an OpenAL format for the given sample format. If bits is non-0,
724 * floatbits must be 0, and if floatbits is non-0, bits must be 0. The
725 * application should not rely on any particular format enum being returned as
726 * it is dependant on the available extensions. The returned format will be
727 * valid for the current context. Requires an active context.
730 * An OpenAL format enum for the given sample format, or AL_NONE if one can't
733 ALURE_API ALenum ALURE_APIENTRY
alureGetSampleFormat(ALuint channels
, ALuint bits
, ALuint floatbits
)
735 if(alGetError() != AL_NO_ERROR
)
737 SetError("Existing OpenAL error");
741 if(bits
&& floatbits
)
743 SetError("Both bit-types specified");
748 return GetSampleFormat(channels
, bits
, false);
749 return GetSampleFormat(channels
, floatbits
, true);
753 /* Function: alureInstallDecodeCallbacks
755 * Installs callbacks to enable ALURE to handle more file types. The index is
756 * the order that each given set of callbacks will be tried, starting at the
757 * most negative number (INT_MIN) and going up. Negative indices will be tried
758 * before the built-in decoders, and positive indices will be tried after.
759 * Installing callbacks onto the same index multiple times will remove the
760 * previous callbacks, and removing old callbacks won't affect any opened files
761 * using them (they'll continue to use the old functions until properly closed,
762 * although newly opened files will use the new ones). Passing NULL for all
763 * callbacks is a valid way to remove an installed set, otherwise certain
764 * callbacks must be specified. Callbacks that are not specified will assume
768 * open_file - This callback is expected to open the named file and prepare it
769 * for decoding. If the callbacks cannot decode the file, NULL
770 * should be returned to indicate failure. Upon success, a non-NULL
771 * handle must be returned, which will be used as a unique
772 * identifier for the decoder instance. This callback is required
773 * if open_memory is not specified.
774 * open_memory - This callback behaves the same as open_file, except it takes a
775 * memory segment for input instead of a filename. The given
776 * memory will remain valid while the instance is open. This
777 * callback is required if open_file is not specified.
778 * get_format - This callback is used to retrieve the format of the decoded
779 * data for the given instance. It is the responsibility of the
780 * function to make sure the returned format is valid for the
781 * current AL context (eg. don't return AL_FORMAT_QUAD16 if the
782 * AL_EXT_MCFORMATS extension isn't available). Returning 0 for
783 * samplerate or blocksize, or returning AL_NONE for format, will
784 * cause a failure. Returning AL_FALSE indicates failure. This
785 * callback is required.
786 * decode - This callback is called to get more decoded data. Up to the
787 * specified amount of bytes should be written to the data pointer.
788 * The number of bytes written should be a multiple of the block size,
789 * otherwise an OpenAL error may occur during buffering. The function
790 * should return the number of bytes written. This callback is
792 * rewind - This callback is for rewinding the instance so that the next decode
793 * calls for it will get audio data from the start of the sound file.
794 * If the stream fails to rewind, AL_FALSE should be returned.
795 * close - This callback is called at the end of processing for a particular
796 * instance. The handle will not be used further and any associated
797 * data may be deleted.
802 ALURE_API ALboolean ALURE_APIENTRY
alureInstallDecodeCallbacks(ALint index
,
803 void* (*open_file
)(const ALchar
*filename
),
804 void* (*open_memory
)(const ALubyte
*data
, ALuint length
),
805 ALboolean (*get_format
)(void *instance
, ALenum
*format
, ALuint
*samplerate
, ALuint
*blocksize
),
806 ALuint (*decode
)(void *instance
, ALubyte
*data
, ALuint bytes
),
807 ALboolean (*rewind
)(void *instance
),
808 void (*close
)(void *instance
))
810 if(!open_file
&& !open_memory
&& !get_format
&& !decode
&& !rewind
&& !close
)
812 std::map
<ALint
,UserCallbacks
>::iterator i
= InstalledCallbacks
.find(index
);
813 if(i
!= InstalledCallbacks
.end())
814 InstalledCallbacks
.erase(i
);
818 if((!open_file
&& !open_memory
) || !get_format
|| !decode
)
820 SetError("Missing callback functions");
825 newcb
.open_file
= open_file
;
826 newcb
.open_mem
= open_memory
;
827 newcb
.get_fmt
= get_format
;
828 newcb
.decode
= decode
;
829 newcb
.rewind
= rewind
;
832 InstalledCallbacks
[index
] = newcb
;
838 /* Function: alureSleep
840 * Rests the calling thread for the given number of seconds.
845 ALURE_API ALboolean ALURE_APIENTRY
alureSleep(ALfloat duration
)
849 SetError("Invalid duration");
853 ALuint seconds
= (ALuint
)duration
;
854 ALfloat rest
= duration
- (ALfloat
)seconds
;
856 #ifdef HAVE_NANOSLEEP
858 struct timespec t
, remainingTime
;
859 t
.tv_sec
= (time_t)seconds
;
860 t
.tv_nsec
= (long)(rest
*1000000)*1000;
862 while(nanosleep(&t
, &remainingTime
) < 0 && errno
== EINTR
)
865 #elif defined(HAVE_WINDOWS_H)
872 Sleep((DWORD
)(rest
* 1000));
880 /* Function: alureGetProcAddress
882 * Returns a pointer for the named ALURE function.
887 * *Version Added*: 1.1
889 ALURE_API
void* ALURE_APIENTRY
alureGetProcAddress(const ALchar
*funcname
)
891 static const struct {
895 #define ADD_FUNCTION(x) { #x, (void*)x },
896 ADD_FUNCTION(alureGetVersion
)
897 ADD_FUNCTION(alureGetErrorString
)
898 ADD_FUNCTION(alureGetDeviceNames
)
899 ADD_FUNCTION(alureFreeDeviceNames
)
900 ADD_FUNCTION(alureInitDevice
)
901 ADD_FUNCTION(alureShutdownDevice
)
902 ADD_FUNCTION(alureGetSampleFormat
)
903 ADD_FUNCTION(alureSleep
)
904 ADD_FUNCTION(alureCreateBufferFromFile
)
905 ADD_FUNCTION(alureCreateBufferFromMemory
)
906 ADD_FUNCTION(alureBufferDataFromFile
)
907 ADD_FUNCTION(alureBufferDataFromMemory
)
908 ADD_FUNCTION(alureCreateStreamFromFile
)
909 ADD_FUNCTION(alureCreateStreamFromMemory
)
910 ADD_FUNCTION(alureCreateStreamFromStaticMemory
)
911 ADD_FUNCTION(alureCreateStreamFromCallback
)
912 ADD_FUNCTION(alureRewindStream
)
913 ADD_FUNCTION(alureDestroyStream
)
914 ADD_FUNCTION(alureInstallDecodeCallbacks
)
915 ADD_FUNCTION(alureSetIOCallbacks
)
916 ADD_FUNCTION(alureGetProcAddress
)
917 ADD_FUNCTION(alurePlaySourceStream
)
918 ADD_FUNCTION(alurePlaySource
)
919 ADD_FUNCTION(alureStopSource
)
920 ADD_FUNCTION(alureGetSourceOffset
)
926 for(i
= 0;FunctionList
[i
].name
;i
++)
928 if(strcmp(FunctionList
[i
].name
, funcname
) == 0)
932 if(!FunctionList
[i
].name
)
933 SetError("Function not found");
934 return FunctionList
[i
].func
;