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 *mod_handle
= NULL
;
50 void *mp123_handle
= NULL
;
51 void *sndfile_handle
= NULL
;
52 void *fsynth_handle
= NULL
;
54 #define MAKE_FUNC(x) typeof(x)* p##x
58 MAKE_FUNC(ov_open_callbacks
);
59 MAKE_FUNC(ov_pcm_seek
);
63 MAKE_FUNC(FLAC__stream_decoder_get_state
);
64 MAKE_FUNC(FLAC__stream_decoder_finish
);
65 MAKE_FUNC(FLAC__stream_decoder_new
);
66 MAKE_FUNC(FLAC__stream_decoder_seek_absolute
);
67 MAKE_FUNC(FLAC__stream_decoder_delete
);
68 MAKE_FUNC(FLAC__stream_decoder_process_single
);
69 MAKE_FUNC(FLAC__stream_decoder_init_stream
);
72 MAKE_FUNC(dumbfile_open_ex
);
73 MAKE_FUNC(dumbfile_close
);
74 MAKE_FUNC(dumb_read_mod
);
75 MAKE_FUNC(dumb_read_s3m
);
76 MAKE_FUNC(dumb_read_xm
);
77 MAKE_FUNC(dumb_read_it
);
78 MAKE_FUNC(dumb_silence
);
79 MAKE_FUNC(duh_sigrenderer_generate_samples
);
80 MAKE_FUNC(duh_get_it_sigrenderer
);
81 MAKE_FUNC(duh_end_sigrenderer
);
82 MAKE_FUNC(unload_duh
);
83 MAKE_FUNC(dumb_it_start_at_order
);
84 MAKE_FUNC(dumb_it_set_loop_callback
);
85 MAKE_FUNC(dumb_it_sr_get_speed
);
86 MAKE_FUNC(dumb_it_sr_set_speed
);
89 MAKE_FUNC(ModPlug_Load
);
90 MAKE_FUNC(ModPlug_Unload
);
91 MAKE_FUNC(ModPlug_Read
);
92 MAKE_FUNC(ModPlug_SeekOrder
);
95 MAKE_FUNC(mpg123_read
);
96 MAKE_FUNC(mpg123_init
);
97 MAKE_FUNC(mpg123_open_feed
);
98 MAKE_FUNC(mpg123_new
);
99 MAKE_FUNC(mpg123_delete
);
100 MAKE_FUNC(mpg123_feed
);
101 MAKE_FUNC(mpg123_exit
);
102 MAKE_FUNC(mpg123_getformat
);
103 MAKE_FUNC(mpg123_format_none
);
104 MAKE_FUNC(mpg123_decode
);
105 MAKE_FUNC(mpg123_format
);
109 MAKE_FUNC(sf_open_virtual
);
110 MAKE_FUNC(sf_readf_short
);
113 #ifdef HAS_FLUIDSYNTH
114 MAKE_FUNC(fluid_settings_setstr
);
115 MAKE_FUNC(fluid_synth_program_change
);
116 MAKE_FUNC(fluid_synth_sfload
);
117 MAKE_FUNC(fluid_settings_setnum
);
118 MAKE_FUNC(fluid_synth_sysex
);
119 MAKE_FUNC(fluid_synth_cc
);
120 MAKE_FUNC(fluid_synth_pitch_bend
);
121 MAKE_FUNC(fluid_synth_channel_pressure
);
122 MAKE_FUNC(fluid_synth_write_float
);
123 MAKE_FUNC(new_fluid_synth
);
124 MAKE_FUNC(delete_fluid_settings
);
125 MAKE_FUNC(delete_fluid_synth
);
126 MAKE_FUNC(fluid_synth_program_reset
);
127 MAKE_FUNC(fluid_settings_setint
);
128 MAKE_FUNC(new_fluid_settings
);
129 MAKE_FUNC(fluid_synth_write_s16
);
130 MAKE_FUNC(fluid_synth_noteoff
);
131 MAKE_FUNC(fluid_synth_sfunload
);
132 MAKE_FUNC(fluid_synth_noteon
);
136 #ifdef HAVE_GCC_CONSTRUCTOR
137 static void init_alure(void) __attribute__((constructor
));
138 static void deinit_alure(void) __attribute__((destructor
));
139 static struct MyConstructorClass
{
140 ~MyConstructorClass()
141 { alureStream::Clear(); };
143 #elif defined(_WIN32) && !defined(ALURE_STATIC_LIBRARY)
144 static void init_alure(void);
145 static void deinit_alure(void);
146 static struct MyConstructorClass
{
147 ~MyConstructorClass()
148 { alureStream::Clear(); };
151 extern "C" BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID reserved
)
155 // Perform actions based on the reason for calling.
158 case DLL_PROCESS_ATTACH
:
159 DisableThreadLibraryCalls(module
);
163 case DLL_PROCESS_DETACH
:
170 static void init_alure(void);
171 static void deinit_alure(void);
173 static struct MyConstructorClass
{
176 ~MyConstructorClass()
177 { alureStream::Clear();
184 static inline void *OpenLib(const char*)
185 { return (void*)0xDEADBEEF; }
186 static inline void CloseLib(void*)
188 #define LOAD_FUNC(h, x) p##x = x
193 static inline void *OpenLib(const char *libname
)
194 { return LoadLibraryA(libname
); }
195 static inline void CloseLib(void*)
196 { FreeLibrary((HINSTANCE
)(x
)); }
197 static inline void *GetLibProc(void *hdl
, const char *funcname
)
198 { return GetProcAddress((HINSTANCE
)hdl
, funcname
); }
202 static inline void *OpenLib(const char *libname
)
205 void *hdl
= dlopen(libname
, RTLD_NOW
);
207 if((err
=dlerror()) != NULL
)
209 fprintf(stderr
, "Error loading %s: %s\n", libname
, err
);
214 static inline void *GetLibProc(void *hdl
, const char *funcname
)
217 void *fn
= dlsym(hdl
, funcname
);
219 if((err
=dlerror()) != NULL
)
221 fprintf(stderr
, "Error loading %s: %s\n", funcname
, err
);
226 static inline void CloseLib(void *hdl
)
230 #define LOAD_FUNC(h, x) p##x = (typeof(p##x))GetLibProc(h##_handle, #x); \
233 CloseLib(h##_handle); \
239 static void init_alure(void)
241 InitializeCriticalSection(&cs_StreamPlay
);
244 #define VORBISFILE_LIB "vorbisfile.dll"
245 #define FLAC_LIB "libFLAC.dll"
246 #define DUMB_LIB "libdumb.dll"
247 #define MODPLUG_LIB "libmodplug.dll"
248 #define MPG123_LIB "libmpg123.dll"
249 #define SNDFILE_LIB "libsndfile-1.dll"
250 #define FLUIDSYNTH_LIB "libfluidsynth.dll"
251 #elif defined(__APPLE__)
252 #define VORBISFILE_LIB "libvorbisfile.3.dylib"
253 #define FLAC_LIB "libFLAC.8.dylib"
254 #define DUMB_LIB "libdumb.dylib"
255 #define MODPLUG_LIB "libmodplug.1.dylib"
256 #define MPG123_LIB "libmpg123.0.dylib"
257 #define SNDFILE_LIB "libsndfile.1.dylib"
258 #define FLUIDSYNTH_LIB "libfluidsynth.1.dylib"
260 #define VORBISFILE_LIB "libvorbisfile.so.3"
261 #define FLAC_LIB "libFLAC.so.8"
262 #define DUMB_LIB "libdumb.so"
263 #define MODPLUG_LIB "libmodplug.so.1"
264 #define MPG123_LIB "libmpg123.so.0"
265 #define SNDFILE_LIB "libsndfile.so.1"
266 #define FLUIDSYNTH_LIB "libfluidsynth.so.1"
269 #ifdef HAS_VORBISFILE
270 vorbisfile_handle
= OpenLib(VORBISFILE_LIB
);
271 while(vorbisfile_handle
)
273 LOAD_FUNC(vorbisfile
, ov_clear
);
274 LOAD_FUNC(vorbisfile
, ov_info
);
275 LOAD_FUNC(vorbisfile
, ov_open_callbacks
);
276 LOAD_FUNC(vorbisfile
, ov_pcm_seek
);
277 LOAD_FUNC(vorbisfile
, ov_read
);
283 flac_handle
= OpenLib(FLAC_LIB
);
286 LOAD_FUNC(flac
, FLAC__stream_decoder_get_state
);
287 LOAD_FUNC(flac
, FLAC__stream_decoder_finish
);
288 LOAD_FUNC(flac
, FLAC__stream_decoder_new
);
289 LOAD_FUNC(flac
, FLAC__stream_decoder_seek_absolute
);
290 LOAD_FUNC(flac
, FLAC__stream_decoder_delete
);
291 LOAD_FUNC(flac
, FLAC__stream_decoder_process_single
);
292 LOAD_FUNC(flac
, FLAC__stream_decoder_init_stream
);
298 dumb_handle
= OpenLib(DUMB_LIB
);
301 LOAD_FUNC(dumb
, dumbfile_open_ex
);
302 LOAD_FUNC(dumb
, dumbfile_close
);
303 LOAD_FUNC(dumb
, dumb_read_mod
);
304 LOAD_FUNC(dumb
, dumb_read_s3m
);
305 LOAD_FUNC(dumb
, dumb_read_xm
);
306 LOAD_FUNC(dumb
, dumb_read_it
);
307 LOAD_FUNC(dumb
, dumb_silence
);
308 LOAD_FUNC(dumb
, duh_sigrenderer_generate_samples
);
309 LOAD_FUNC(dumb
, duh_get_it_sigrenderer
);
310 LOAD_FUNC(dumb
, duh_end_sigrenderer
);
311 LOAD_FUNC(dumb
, unload_duh
);
312 LOAD_FUNC(dumb
, dumb_it_start_at_order
);
313 LOAD_FUNC(dumb
, dumb_it_set_loop_callback
);
314 LOAD_FUNC(dumb
, dumb_it_sr_get_speed
);
315 LOAD_FUNC(dumb
, dumb_it_sr_set_speed
);
321 mod_handle
= OpenLib(MODPLUG_LIB
);
324 LOAD_FUNC(mod
, ModPlug_Load
);
325 LOAD_FUNC(mod
, ModPlug_Unload
);
326 LOAD_FUNC(mod
, ModPlug_Read
);
327 LOAD_FUNC(mod
, ModPlug_SeekOrder
);
333 mp123_handle
= OpenLib(MPG123_LIB
);
336 LOAD_FUNC(mp123
, mpg123_read
);
337 LOAD_FUNC(mp123
, mpg123_init
);
338 LOAD_FUNC(mp123
, mpg123_open_feed
);
339 LOAD_FUNC(mp123
, mpg123_new
);
340 LOAD_FUNC(mp123
, mpg123_delete
);
341 LOAD_FUNC(mp123
, mpg123_feed
);
342 LOAD_FUNC(mp123
, mpg123_exit
);
343 LOAD_FUNC(mp123
, mpg123_getformat
);
344 LOAD_FUNC(mp123
, mpg123_format_none
);
345 LOAD_FUNC(mp123
, mpg123_decode
);
346 LOAD_FUNC(mp123
, mpg123_format
);
353 sndfile_handle
= OpenLib(SNDFILE_LIB
);
354 while(sndfile_handle
)
356 LOAD_FUNC(sndfile
, sf_close
);
357 LOAD_FUNC(sndfile
, sf_open_virtual
);
358 LOAD_FUNC(sndfile
, sf_readf_short
);
359 LOAD_FUNC(sndfile
, sf_seek
);
364 #ifdef HAS_FLUIDSYNTH
365 fsynth_handle
= OpenLib(FLUIDSYNTH_LIB
);
368 LOAD_FUNC(fsynth
, fluid_settings_setstr
);
369 LOAD_FUNC(fsynth
, fluid_synth_program_change
);
370 LOAD_FUNC(fsynth
, fluid_synth_sfload
);
371 LOAD_FUNC(fsynth
, fluid_settings_setnum
);
372 LOAD_FUNC(fsynth
, fluid_synth_sysex
);
373 LOAD_FUNC(fsynth
, fluid_synth_cc
);
374 LOAD_FUNC(fsynth
, fluid_synth_pitch_bend
);
375 LOAD_FUNC(fsynth
, fluid_synth_channel_pressure
);
376 LOAD_FUNC(fsynth
, fluid_synth_write_float
);
377 LOAD_FUNC(fsynth
, new_fluid_synth
);
378 LOAD_FUNC(fsynth
, delete_fluid_settings
);
379 LOAD_FUNC(fsynth
, delete_fluid_synth
);
380 LOAD_FUNC(fsynth
, fluid_synth_program_reset
);
381 LOAD_FUNC(fsynth
, fluid_settings_setint
);
382 LOAD_FUNC(fsynth
, new_fluid_settings
);
383 LOAD_FUNC(fsynth
, fluid_synth_write_s16
);
384 LOAD_FUNC(fsynth
, fluid_synth_noteoff
);
385 LOAD_FUNC(fsynth
, fluid_synth_sfunload
);
386 LOAD_FUNC(fsynth
, fluid_synth_noteon
);
391 #undef VORBISFILE_LIB
399 static void deinit_alure(void)
401 #ifdef HAS_VORBISFILE
402 if(vorbisfile_handle
)
403 CloseLib(vorbisfile_handle
);
404 vorbisfile_handle
= NULL
;
408 CloseLib(flac_handle
);
413 CloseLib(dumb_handle
);
420 CloseLib(mp123_handle
);
426 CloseLib(sndfile_handle
);
427 sndfile_handle
= NULL
;
430 DeleteCriticalSection(&cs_StreamPlay
);
434 static const ALchar
*last_error
= "No error";
436 void SetError(const char *err
)
441 ALuint
DetectBlockAlignment(ALenum format
)
445 #define CHECK_RET(f,s) case (f): return (s)
446 CHECK_RET(AL_FORMAT_MONO8
, sizeof(ALubyte
));
447 CHECK_RET(AL_FORMAT_MONO16
, sizeof(ALshort
));
448 CHECK_RET(AL_FORMAT_MONO_FLOAT32
, sizeof(ALfloat
));
449 CHECK_RET(AL_FORMAT_MONO_DOUBLE_EXT
, sizeof(ALdouble
));
450 CHECK_RET(AL_FORMAT_MONO_MULAW
, sizeof(ALubyte
)*1);
452 CHECK_RET(AL_FORMAT_STEREO8
, sizeof(ALubyte
)*2);
453 CHECK_RET(AL_FORMAT_STEREO16
, sizeof(ALshort
)*2);
454 CHECK_RET(AL_FORMAT_STEREO_FLOAT32
, sizeof(ALfloat
)*2);
455 CHECK_RET(AL_FORMAT_STEREO_DOUBLE_EXT
, sizeof(ALdouble
)*2);
456 CHECK_RET(AL_FORMAT_STEREO_MULAW
, sizeof(ALubyte
)*2);
458 CHECK_RET(AL_FORMAT_QUAD8
, sizeof(ALubyte
)*4);
459 CHECK_RET(AL_FORMAT_QUAD16
, sizeof(ALshort
)*4);
460 CHECK_RET(AL_FORMAT_QUAD32
, sizeof(ALfloat
)*4);
461 CHECK_RET(AL_FORMAT_QUAD_MULAW
, sizeof(ALubyte
)*4);
463 CHECK_RET(AL_FORMAT_REAR8
, sizeof(ALubyte
)*2);
464 CHECK_RET(AL_FORMAT_REAR16
, sizeof(ALshort
)*2);
465 CHECK_RET(AL_FORMAT_REAR32
, sizeof(ALfloat
)*2);
466 CHECK_RET(AL_FORMAT_REAR_MULAW
, sizeof(ALubyte
)*2);
468 CHECK_RET(AL_FORMAT_51CHN8
, sizeof(ALubyte
)*6);
469 CHECK_RET(AL_FORMAT_51CHN16
, sizeof(ALshort
)*6);
470 CHECK_RET(AL_FORMAT_51CHN32
, sizeof(ALfloat
)*6);
471 CHECK_RET(AL_FORMAT_51CHN_MULAW
, sizeof(ALubyte
)*6);
473 CHECK_RET(AL_FORMAT_61CHN8
, sizeof(ALubyte
)*7);
474 CHECK_RET(AL_FORMAT_61CHN16
, sizeof(ALshort
)*7);
475 CHECK_RET(AL_FORMAT_61CHN32
, sizeof(ALfloat
)*7);
476 CHECK_RET(AL_FORMAT_61CHN_MULAW
, sizeof(ALubyte
)*7);
478 CHECK_RET(AL_FORMAT_71CHN8
, sizeof(ALubyte
)*8);
479 CHECK_RET(AL_FORMAT_71CHN16
, sizeof(ALshort
)*8);
480 CHECK_RET(AL_FORMAT_71CHN32
, sizeof(ALfloat
)*8);
481 CHECK_RET(AL_FORMAT_71CHN_MULAW
, sizeof(ALubyte
)*8);
483 CHECK_RET(AL_FORMAT_MONO_IMA4
, 36);
484 CHECK_RET(AL_FORMAT_STEREO_IMA4
, 36*2);
490 ALuint
DetectCompressionRate(ALenum format
)
494 case AL_FORMAT_MONO8
:
495 case AL_FORMAT_MONO16
:
496 case AL_FORMAT_MONO_FLOAT32
:
497 case AL_FORMAT_MONO_DOUBLE_EXT
:
498 case AL_FORMAT_STEREO8
:
499 case AL_FORMAT_STEREO16
:
500 case AL_FORMAT_STEREO_FLOAT32
:
501 case AL_FORMAT_STEREO_DOUBLE_EXT
:
502 case AL_FORMAT_QUAD8
:
503 case AL_FORMAT_QUAD16
:
504 case AL_FORMAT_QUAD32
:
505 case AL_FORMAT_REAR8
:
506 case AL_FORMAT_REAR16
:
507 case AL_FORMAT_REAR32
:
508 case AL_FORMAT_51CHN8
:
509 case AL_FORMAT_51CHN16
:
510 case AL_FORMAT_51CHN32
:
511 case AL_FORMAT_61CHN8
:
512 case AL_FORMAT_61CHN16
:
513 case AL_FORMAT_61CHN32
:
514 case AL_FORMAT_71CHN8
:
515 case AL_FORMAT_71CHN16
:
516 case AL_FORMAT_71CHN32
:
519 case AL_FORMAT_MONO_MULAW
:
520 case AL_FORMAT_STEREO_MULAW
:
521 case AL_FORMAT_QUAD_MULAW
:
522 case AL_FORMAT_REAR_MULAW
:
523 case AL_FORMAT_51CHN_MULAW
:
524 case AL_FORMAT_61CHN_MULAW
:
525 case AL_FORMAT_71CHN_MULAW
:
528 case AL_FORMAT_MONO_IMA4
:
529 case AL_FORMAT_STEREO_IMA4
:
532 fprintf(stderr
, "Alure lib: Unhandled format: %#x\n", format
);
536 ALenum
GetSampleFormat(ALuint channels
, ALuint bits
, bool isFloat
)
538 #define CHECK_FMT_RET(f) do { \
539 ALenum fmt = alGetEnumValue(#f); \
540 if(alGetError() == AL_NO_ERROR && fmt != 0 && fmt != -1) \
547 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO8
);
548 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO8
);
549 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
551 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD8
);
552 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN8
);
553 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN8
);
554 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN8
);
556 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
558 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD8_LOKI
);
560 SetError("Unsupported 8-bit channel count\n");
565 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO16
);
566 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO16
);
567 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
569 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD16
);
570 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN16
);
571 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN16
);
572 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN16
);
574 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
576 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD16_LOKI
);
578 SetError("Unsupported 16-bit channel count\n");
581 SetError("Unsupported PCM bit depth\n");
585 if(bits
== 32 && alIsExtensionPresent("AL_EXT_FLOAT32"))
587 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO_FLOAT32
);
588 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO_FLOAT32
);
589 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
591 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD32
);
592 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN32
);
593 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN32
);
594 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN32
);
596 SetError("Unsupported float32 channel count\n");
599 if(bits
== 64 && alIsExtensionPresent("AL_EXT_DOUBLE"))
601 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO_DOUBLE_EXT
);
602 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO_DOUBLE_EXT
);
603 SetError("Unsupported double channel count\n");
608 SetError("Unsupported float bit depth\n");
614 /* Function: alureGetVersion
616 * Stores the major and minor version of the library. If either major or minor
617 * are NULL, that value is not provided.
619 ALURE_API
void ALURE_APIENTRY
alureGetVersion(ALuint
*major
, ALuint
*minor
)
621 if(major
) *major
= ALURE_VER_MAJOR
;
622 if(minor
) *minor
= ALURE_VER_MINOR
;
625 /* Function: alureGetErrorString
627 * Returns a string describing the last error encountered.
629 ALURE_API
const ALchar
* ALURE_APIENTRY
alureGetErrorString(void)
631 const ALchar
*ret
= last_error
;
632 last_error
= "No error";
637 /* Function: alureGetDeviceNames
639 * Gets an array of device name strings from OpenAL. This encapsulates
640 * AL_ENUMERATE_ALL_EXT (if supported and 'all' is true) and standard
641 * enumeration, with 'count' being set to the number of returned device
645 * An array of device name strings, or NULL on error.
648 * <alureFreeDeviceNames>
650 ALURE_API
const ALCchar
** ALURE_APIENTRY
alureGetDeviceNames(ALCboolean all
, ALCsizei
*count
)
652 const ALCchar
*list
= NULL
;
653 if(all
&& alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT"))
654 list
= alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
);
656 list
= alcGetString(NULL
, ALC_DEVICE_SPECIFIER
);
660 SetError("No device names found");
664 const ALCchar
*cur
= list
;
665 ALuint retlistLen
= 0;
668 cur
+= strlen(cur
)+1;
672 const ALCchar
**retlist
= new const ALCchar
*[retlistLen
+1];
677 ALCuint len
= strlen(cur
)+1;
678 ALCchar
*newstr
= new ALCchar
[len
];
680 memcpy(newstr
, cur
, len
);
683 retlist
[retlistLen
] = newstr
;
686 retlist
[retlistLen
] = NULL
;
692 /* Function: alureFreeDeviceNames
694 * Frees the device name array returned from alureGetDeviceNames.
697 * <alureGetDeviceNames>
699 ALURE_API ALvoid ALURE_APIENTRY
alureFreeDeviceNames(const ALCchar
**names
)
703 for(ALCuint i
= 0;names
[i
];i
++)
704 delete[] const_cast<ALCchar
*>(names
[i
]);
710 /* Function: alureInitDevice
712 * Opens the named device, creates a context with the given attributes, and
713 * sets that context as current. The name and attribute list would be the same
714 * as what's passed to alcOpenDevice and alcCreateContext respectively.
720 * <alureShutdownDevice>
722 ALURE_API ALboolean ALURE_APIENTRY
alureInitDevice(const ALCchar
*name
, const ALCint
*attribs
)
724 ALCdevice
*device
= alcOpenDevice(name
);
729 SetError("Device open failed");
733 ALCcontext
*context
= alcCreateContext(device
, attribs
);
734 if(!context
|| alcMakeContextCurrent(context
) == ALC_FALSE
)
737 alcDestroyContext(context
);
738 alcCloseDevice(device
);
740 SetError("Context setup failed");
748 /* Function: alureShutdownDevice
750 * Destroys the current context and closes its associated device.
758 ALURE_API ALboolean ALURE_APIENTRY
alureShutdownDevice(void)
760 ALCcontext
*context
= alcGetCurrentContext();
761 ALCdevice
*device
= alcGetContextsDevice(context
);
762 if(!context
|| !device
)
765 SetError("Failed to get current device");
769 if(alcMakeContextCurrent(NULL
) == ALC_FALSE
)
772 SetError("Failed to unset current context");
776 alcDestroyContext(context
);
777 alcCloseDevice(device
);
784 /* Function: alureGetSampleFormat
786 * Retrieves an OpenAL format for the given sample format. If bits is non-0,
787 * floatbits must be 0, and if floatbits is non-0, bits must be 0. The
788 * application should not rely on any particular format enum being returned as
789 * it is dependant on the available extensions. The returned format will be
790 * valid for the current context. Requires an active context.
793 * An OpenAL format enum for the given sample format, or AL_NONE if one can't
796 ALURE_API ALenum ALURE_APIENTRY
alureGetSampleFormat(ALuint channels
, ALuint bits
, ALuint floatbits
)
798 if(alGetError() != AL_NO_ERROR
)
800 SetError("Existing OpenAL error");
804 if(bits
&& floatbits
)
806 SetError("Both bit-types specified");
811 return GetSampleFormat(channels
, bits
, false);
812 return GetSampleFormat(channels
, floatbits
, true);
816 /* Function: alureInstallDecodeCallbacks
818 * Installs callbacks to enable ALURE to handle more file types. The index is
819 * the order that each given set of callbacks will be tried, starting at the
820 * most negative number (INT_MIN) and going up. Negative indices will be tried
821 * before the built-in decoders, and positive indices will be tried after.
822 * Installing callbacks onto the same index multiple times will remove the
823 * previous callbacks, and removing old callbacks won't affect any opened files
824 * using them (they'll continue to use the old functions until properly closed,
825 * although newly opened files will use the new ones). Passing NULL for all
826 * callbacks is a valid way to remove an installed set, otherwise certain
827 * callbacks must be specified. Callbacks that are not specified will assume
831 * open_file - This callback is expected to open the named file and prepare it
832 * for decoding. If the callbacks cannot decode the file, NULL
833 * should be returned to indicate failure. Upon success, a non-NULL
834 * handle must be returned, which will be used as a unique
835 * identifier for the decoder instance. This callback is required
836 * if open_memory is not specified.
837 * open_memory - This callback behaves the same as open_file, except it takes a
838 * memory segment for input instead of a filename. The given
839 * memory will remain valid while the instance is open. This
840 * callback is required if open_file is not specified.
841 * get_format - This callback is used to retrieve the format of the decoded
842 * data for the given instance. It is the responsibility of the
843 * function to make sure the returned format is valid for the
844 * current AL context (eg. don't return AL_FORMAT_QUAD16 if the
845 * AL_EXT_MCFORMATS extension isn't available). Returning 0 for
846 * samplerate or blocksize, or returning AL_NONE for format, will
847 * cause a failure. Returning AL_FALSE indicates failure. This
848 * callback is required.
849 * decode - This callback is called to get more decoded data. Up to the
850 * specified amount of bytes should be written to the data pointer.
851 * The number of bytes written should be a multiple of the block size,
852 * otherwise an OpenAL error may occur during buffering. The function
853 * should return the number of bytes written. This callback is
855 * rewind - This callback is for rewinding the instance so that the next decode
856 * calls for it will get audio data from the start of the sound file.
857 * If the stream fails to rewind, AL_FALSE should be returned.
858 * close - This callback is called at the end of processing for a particular
859 * instance. The handle will not be used further and any associated
860 * data may be deleted.
865 ALURE_API ALboolean ALURE_APIENTRY
alureInstallDecodeCallbacks(ALint index
,
866 void* (*open_file
)(const ALchar
*filename
),
867 void* (*open_memory
)(const ALubyte
*data
, ALuint length
),
868 ALboolean (*get_format
)(void *instance
, ALenum
*format
, ALuint
*samplerate
, ALuint
*blocksize
),
869 ALuint (*decode
)(void *instance
, ALubyte
*data
, ALuint bytes
),
870 ALboolean (*rewind
)(void *instance
),
871 void (*close
)(void *instance
))
873 if(!open_file
&& !open_memory
&& !get_format
&& !decode
&& !rewind
&& !close
)
875 std::map
<ALint
,UserCallbacks
>::iterator i
= InstalledCallbacks
.find(index
);
876 if(i
!= InstalledCallbacks
.end())
877 InstalledCallbacks
.erase(i
);
881 if((!open_file
&& !open_memory
) || !get_format
|| !decode
)
883 SetError("Missing callback functions");
888 newcb
.open_file
= open_file
;
889 newcb
.open_mem
= open_memory
;
890 newcb
.get_fmt
= get_format
;
891 newcb
.decode
= decode
;
892 newcb
.rewind
= rewind
;
895 InstalledCallbacks
[index
] = newcb
;
901 /* Function: alureSleep
903 * Rests the calling thread for the given number of seconds.
908 ALURE_API ALboolean ALURE_APIENTRY
alureSleep(ALfloat duration
)
912 SetError("Invalid duration");
916 ALuint seconds
= (ALuint
)duration
;
917 ALfloat rest
= duration
- (ALfloat
)seconds
;
919 #ifdef HAVE_NANOSLEEP
921 struct timespec t
, remainingTime
;
922 t
.tv_sec
= (time_t)seconds
;
923 t
.tv_nsec
= (long)(rest
*1000000)*1000;
925 while(nanosleep(&t
, &remainingTime
) < 0 && errno
== EINTR
)
928 #elif defined(HAVE_WINDOWS_H)
935 Sleep((DWORD
)(rest
* 1000));
943 /* Function: alureGetProcAddress
945 * Returns a pointer for the named ALURE function.
950 * *Version Added*: 1.1
952 ALURE_API
void* ALURE_APIENTRY
alureGetProcAddress(const ALchar
*funcname
)
954 static const struct {
958 #define ADD_FUNCTION(x) { #x, (void*)x },
959 ADD_FUNCTION(alureGetVersion
)
960 ADD_FUNCTION(alureGetErrorString
)
961 ADD_FUNCTION(alureGetDeviceNames
)
962 ADD_FUNCTION(alureFreeDeviceNames
)
963 ADD_FUNCTION(alureInitDevice
)
964 ADD_FUNCTION(alureShutdownDevice
)
965 ADD_FUNCTION(alureGetSampleFormat
)
966 ADD_FUNCTION(alureSleep
)
967 ADD_FUNCTION(alureCreateBufferFromFile
)
968 ADD_FUNCTION(alureCreateBufferFromMemory
)
969 ADD_FUNCTION(alureBufferDataFromFile
)
970 ADD_FUNCTION(alureBufferDataFromMemory
)
971 ADD_FUNCTION(alureCreateStreamFromFile
)
972 ADD_FUNCTION(alureCreateStreamFromMemory
)
973 ADD_FUNCTION(alureCreateStreamFromStaticMemory
)
974 ADD_FUNCTION(alureCreateStreamFromCallback
)
975 ADD_FUNCTION(alureRewindStream
)
976 ADD_FUNCTION(alureDestroyStream
)
977 ADD_FUNCTION(alureInstallDecodeCallbacks
)
978 ADD_FUNCTION(alureSetIOCallbacks
)
979 ADD_FUNCTION(alureGetProcAddress
)
980 ADD_FUNCTION(alurePlaySourceStream
)
981 ADD_FUNCTION(alurePlaySource
)
982 ADD_FUNCTION(alureStopSource
)
988 for(i
= 0;FunctionList
[i
].name
;i
++)
990 if(strcmp(FunctionList
[i
].name
, funcname
) == 0)
994 if(!FunctionList
[i
].name
)
995 SetError("Function not found");
996 return FunctionList
[i
].func
;