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 std::map
<std::string
,void*> FunctionList
;
40 CRITICAL_SECTION cs_StreamPlay
;
41 alureStream::ListType
alureStream::StreamList
;
43 void *vorbisfile_handle
= NULL
;
44 void *flac_handle
= NULL
;
45 void *dumb_handle
= NULL
;
46 void *mp123_handle
= NULL
;
47 void *sndfile_handle
= NULL
;
49 #define MAKE_FUNC(x) typeof(x)* p##x
53 MAKE_FUNC(ov_open_callbacks
);
54 MAKE_FUNC(ov_pcm_seek
);
58 MAKE_FUNC(FLAC__stream_decoder_get_state
);
59 MAKE_FUNC(FLAC__stream_decoder_finish
);
60 MAKE_FUNC(FLAC__stream_decoder_new
);
61 MAKE_FUNC(FLAC__stream_decoder_seek_absolute
);
62 MAKE_FUNC(FLAC__stream_decoder_delete
);
63 MAKE_FUNC(FLAC__stream_decoder_process_single
);
64 MAKE_FUNC(FLAC__stream_decoder_init_stream
);
67 MAKE_FUNC(dumbfile_open_ex
);
68 MAKE_FUNC(dumbfile_close
);
69 MAKE_FUNC(dumb_read_mod
);
70 MAKE_FUNC(dumb_read_s3m
);
71 MAKE_FUNC(dumb_read_xm
);
72 MAKE_FUNC(dumb_read_it
);
73 MAKE_FUNC(dumb_silence
);
74 MAKE_FUNC(duh_sigrenderer_generate_samples
);
75 MAKE_FUNC(duh_get_it_sigrenderer
);
76 MAKE_FUNC(duh_end_sigrenderer
);
77 MAKE_FUNC(unload_duh
);
78 MAKE_FUNC(dumb_it_start_at_order
);
79 MAKE_FUNC(dumb_it_set_loop_callback
);
80 MAKE_FUNC(dumb_it_sr_get_speed
);
81 MAKE_FUNC(dumb_it_sr_set_speed
);
84 MAKE_FUNC(mpg123_read
);
85 MAKE_FUNC(mpg123_init
);
86 MAKE_FUNC(mpg123_open_feed
);
87 MAKE_FUNC(mpg123_new
);
88 MAKE_FUNC(mpg123_delete
);
89 MAKE_FUNC(mpg123_feed
);
90 MAKE_FUNC(mpg123_exit
);
91 MAKE_FUNC(mpg123_getformat
);
92 MAKE_FUNC(mpg123_format_none
);
93 MAKE_FUNC(mpg123_decode
);
94 MAKE_FUNC(mpg123_format
);
98 MAKE_FUNC(sf_open_virtual
);
99 MAKE_FUNC(sf_readf_short
);
104 #if defined(_WIN32) && !defined(ALURE_STATIC_LIBRARY)
105 static void init_alure(void);
106 static void deinit_alure(void);
107 static struct MyConstructorClass
{
108 ~MyConstructorClass()
109 { alureStream::Clear(); };
112 extern "C" BOOL APIENTRY
DllMain(HINSTANCE module
, DWORD reason
, LPVOID reserved
)
116 // Perform actions based on the reason for calling.
119 case DLL_PROCESS_ATTACH
:
120 DisableThreadLibraryCalls(module
);
124 case DLL_PROCESS_DETACH
:
130 #elif defined(HAVE_GCC_CONSTRUCTOR)
131 static void init_alure(void) __attribute__((constructor
));
132 static void deinit_alure(void) __attribute__((destructor
));
133 static struct MyConstructorClass
{
134 ~MyConstructorClass()
135 { alureStream::Clear(); };
138 static void init_alure(void);
139 static void deinit_alure(void);
141 static struct MyConstructorClass
{
144 ~MyConstructorClass()
145 { alureStream::Clear();
153 static inline void *LoadLibraryA(const char *libname
)
155 void *hdl
= dlopen(libname
, RTLD_NOW
);
157 if((err
=dlerror()) != NULL
)
159 fprintf(stderr
, "Error loading %s: %s\n", libname
, err
);
164 static inline void *GetProcAddress(void *hdl
, const char *funcname
)
166 void *fn
= dlsym(hdl
, funcname
);
168 if((err
=dlerror()) != NULL
)
170 fprintf(stderr
, "Error loading %s: %s\n", funcname
, err
);
175 static inline void FreeLibrary(void *hdl
)
180 static inline void *LoadLibraryA(const char*)
181 { return (void*)0xDEADBEEF; }
182 static inline void FreeLibrary(void*)
184 #define LOAD_FUNC(h, x) p##x = x
189 #define GetProcAddress(x,y) GetProcAddress((HINSTANCE)(x),(y))
190 #define FreeLibrary(x) FreeLibrary((HINSTANCE)(x))
192 #define LOAD_FUNC(h, x) p##x = x
197 static void init_alure(void)
199 InitializeCriticalSection(&cs_StreamPlay
);
202 #define LOAD_FUNC(h, x) p##x = (typeof(p##x))GetProcAddress(h##_handle, #x); \
205 FreeLibrary(h##_handle); \
212 #define VORBISFILE_LIB "vorbisfile.dll"
213 #define FLAC_LIB "libFLAC.dll"
214 #define DUMB_LIB "libdumb.dll"
215 #define MPG123_LIB "libmpg123.dll"
216 #define SNDFILE_LIB "libsndfile-1.dll"
217 #elif defined(__APPLE__)
218 #define VORBISFILE_LIB "libvorbisfile.3.dylib"
219 #define FLAC_LIB "libFLAC.8.dylib"
220 #define DUMB_LIB "libdumb.dylib"
221 #define MPG123_LIB "libmpg123.0.dylib"
222 #define SNDFILE_LIB "libsndfile.1.dylib"
224 #define VORBISFILE_LIB "libvorbisfile.so.3"
225 #define FLAC_LIB "libFLAC.so.8"
226 #define DUMB_LIB "libdumb.so"
227 #define MPG123_LIB "libmpg123.so.0"
228 #define SNDFILE_LIB "libsndfile.so.1"
231 #ifdef HAS_VORBISFILE
232 vorbisfile_handle
= LoadLibraryA(VORBISFILE_LIB
);
233 while(vorbisfile_handle
)
235 LOAD_FUNC(vorbisfile
, ov_clear
);
236 LOAD_FUNC(vorbisfile
, ov_info
);
237 LOAD_FUNC(vorbisfile
, ov_open_callbacks
);
238 LOAD_FUNC(vorbisfile
, ov_pcm_seek
);
239 LOAD_FUNC(vorbisfile
, ov_read
);
245 flac_handle
= LoadLibraryA(FLAC_LIB
);
248 LOAD_FUNC(flac
, FLAC__stream_decoder_get_state
);
249 LOAD_FUNC(flac
, FLAC__stream_decoder_finish
);
250 LOAD_FUNC(flac
, FLAC__stream_decoder_new
);
251 LOAD_FUNC(flac
, FLAC__stream_decoder_seek_absolute
);
252 LOAD_FUNC(flac
, FLAC__stream_decoder_delete
);
253 LOAD_FUNC(flac
, FLAC__stream_decoder_process_single
);
254 LOAD_FUNC(flac
, FLAC__stream_decoder_init_stream
);
260 dumb_handle
= LoadLibraryA(DUMB_LIB
);
263 LOAD_FUNC(dumb
, dumbfile_open_ex
);
264 LOAD_FUNC(dumb
, dumbfile_close
);
265 LOAD_FUNC(dumb
, dumb_read_mod
);
266 LOAD_FUNC(dumb
, dumb_read_s3m
);
267 LOAD_FUNC(dumb
, dumb_read_xm
);
268 LOAD_FUNC(dumb
, dumb_read_it
);
269 LOAD_FUNC(dumb
, dumb_silence
);
270 LOAD_FUNC(dumb
, duh_sigrenderer_generate_samples
);
271 LOAD_FUNC(dumb
, duh_get_it_sigrenderer
);
272 LOAD_FUNC(dumb
, duh_end_sigrenderer
);
273 LOAD_FUNC(dumb
, unload_duh
);
274 LOAD_FUNC(dumb
, dumb_it_start_at_order
);
275 LOAD_FUNC(dumb
, dumb_it_set_loop_callback
);
276 LOAD_FUNC(dumb
, dumb_it_sr_get_speed
);
277 LOAD_FUNC(dumb
, dumb_it_sr_set_speed
);
283 mp123_handle
= LoadLibraryA(MPG123_LIB
);
286 LOAD_FUNC(mp123
, mpg123_read
);
287 LOAD_FUNC(mp123
, mpg123_init
);
288 LOAD_FUNC(mp123
, mpg123_open_feed
);
289 LOAD_FUNC(mp123
, mpg123_new
);
290 LOAD_FUNC(mp123
, mpg123_delete
);
291 LOAD_FUNC(mp123
, mpg123_feed
);
292 LOAD_FUNC(mp123
, mpg123_exit
);
293 LOAD_FUNC(mp123
, mpg123_getformat
);
294 LOAD_FUNC(mp123
, mpg123_format_none
);
295 LOAD_FUNC(mp123
, mpg123_decode
);
296 LOAD_FUNC(mp123
, mpg123_format
);
303 sndfile_handle
= LoadLibraryA(SNDFILE_LIB
);
304 while(sndfile_handle
)
306 LOAD_FUNC(sndfile
, sf_close
);
307 LOAD_FUNC(sndfile
, sf_open_virtual
);
308 LOAD_FUNC(sndfile
, sf_readf_short
);
309 LOAD_FUNC(sndfile
, sf_seek
);
314 #undef VORBISFILE_LIB
322 static void deinit_alure(void)
324 #ifdef HAS_VORBISFILE
325 if(vorbisfile_handle
)
326 FreeLibrary(vorbisfile_handle
);
327 vorbisfile_handle
= NULL
;
331 FreeLibrary(flac_handle
);
336 FreeLibrary(dumb_handle
);
343 FreeLibrary(mp123_handle
);
349 FreeLibrary(sndfile_handle
);
350 sndfile_handle
= NULL
;
353 DeleteCriticalSection(&cs_StreamPlay
);
357 static const ALchar
*last_error
= "No error";
359 void SetError(const char *err
)
364 ALuint
DetectBlockAlignment(ALenum format
)
368 #define CHECK_RET(f,s) case (f): return (s)
369 CHECK_RET(AL_FORMAT_MONO8
, sizeof(ALubyte
));
370 CHECK_RET(AL_FORMAT_MONO16
, sizeof(ALshort
));
371 CHECK_RET(AL_FORMAT_MONO_FLOAT32
, sizeof(ALfloat
));
373 CHECK_RET(AL_FORMAT_STEREO8
, sizeof(ALubyte
)*2);
374 CHECK_RET(AL_FORMAT_STEREO16
, sizeof(ALshort
)*2);
375 CHECK_RET(AL_FORMAT_STEREO_FLOAT32
, sizeof(ALfloat
)*2);
377 CHECK_RET(AL_FORMAT_QUAD8
, sizeof(ALubyte
)*4);
378 CHECK_RET(AL_FORMAT_QUAD16
, sizeof(ALshort
)*4);
379 CHECK_RET(AL_FORMAT_QUAD32
, sizeof(ALfloat
)*4);
381 CHECK_RET(AL_FORMAT_REAR8
, sizeof(ALubyte
)*2);
382 CHECK_RET(AL_FORMAT_REAR16
, sizeof(ALshort
)*2);
383 CHECK_RET(AL_FORMAT_REAR32
, sizeof(ALfloat
)*2);
385 CHECK_RET(AL_FORMAT_51CHN8
, sizeof(ALubyte
)*6);
386 CHECK_RET(AL_FORMAT_51CHN16
, sizeof(ALshort
)*6);
387 CHECK_RET(AL_FORMAT_51CHN32
, sizeof(ALfloat
)*6);
389 CHECK_RET(AL_FORMAT_61CHN8
, sizeof(ALubyte
)*7);
390 CHECK_RET(AL_FORMAT_61CHN16
, sizeof(ALshort
)*7);
391 CHECK_RET(AL_FORMAT_61CHN32
, sizeof(ALfloat
)*7);
393 CHECK_RET(AL_FORMAT_71CHN8
, sizeof(ALubyte
)*8);
394 CHECK_RET(AL_FORMAT_71CHN16
, sizeof(ALshort
)*8);
395 CHECK_RET(AL_FORMAT_71CHN32
, sizeof(ALfloat
)*8);
397 CHECK_RET(AL_FORMAT_MONO_IMA4
, 36);
398 CHECK_RET(AL_FORMAT_STEREO_IMA4
, 36*2);
401 fprintf(stderr
, "Alure lib: Unhandled format: %#x\n", format
);
405 ALenum
GetSampleFormat(ALuint channels
, ALuint bits
, bool isFloat
)
407 #define CHECK_FMT_RET(f) do { \
408 ALenum fmt = alGetEnumValue(#f); \
409 if(alGetError() == AL_NO_ERROR && fmt != 0 && fmt != -1) \
416 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO8
);
417 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO8
);
418 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
420 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD8
);
421 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN8
);
422 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN8
);
423 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN8
);
425 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
427 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD8_LOKI
);
429 SetError("Unsupported channel count\n");
434 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO16
);
435 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO16
);
436 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
438 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD16
);
439 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN16
);
440 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN16
);
441 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN16
);
443 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
445 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD16_LOKI
);
447 SetError("Unsupported channel count\n");
455 if(alIsExtensionPresent("AL_EXT_FLOAT32"))
457 if(channels
== 1) CHECK_FMT_RET(AL_FORMAT_MONO_FLOAT32
);
458 if(channels
== 2) CHECK_FMT_RET(AL_FORMAT_STEREO_FLOAT32
);
459 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
461 if(channels
== 4) CHECK_FMT_RET(AL_FORMAT_QUAD32
);
462 if(channels
== 6) CHECK_FMT_RET(AL_FORMAT_51CHN32
);
463 if(channels
== 7) CHECK_FMT_RET(AL_FORMAT_61CHN32
);
464 if(channels
== 8) CHECK_FMT_RET(AL_FORMAT_71CHN32
);
466 SetError("Unsupported channel count\n");
475 SetError("Unsupported float bit depth\n");
478 SetError("Unsupported PCM bit depth\n");
484 /* Function: alureGetVersion
486 * Stores the major and minor version of the library. If either major or minor
487 * are NULL, that value is not provided.
489 ALURE_API
void ALURE_APIENTRY
alureGetVersion(ALuint
*major
, ALuint
*minor
)
491 if(major
) *major
= ALURE_VER_MAJOR
;
492 if(minor
) *minor
= ALURE_VER_MINOR
;
495 /* Function: alureGetErrorString
497 * Returns a string describing the last error encountered.
499 ALURE_API
const ALchar
* ALURE_APIENTRY
alureGetErrorString(void)
501 const ALchar
*ret
= last_error
;
502 last_error
= "No error";
507 /* Function: alureGetDeviceNames
509 * Gets an array of device name strings from OpenAL. This encapsulates
510 * AL_ENUMERATE_ALL_EXT (if supported and 'all' is true) and standard
511 * enumeration, with 'count' being set to the number of returned device
515 * An array of device name strings, or NULL on error.
518 * <alureFreeDeviceNames>
520 ALURE_API
const ALCchar
** ALURE_APIENTRY
alureGetDeviceNames(ALCboolean all
, ALCsizei
*count
)
522 const ALCchar
*list
= NULL
;
523 if(all
&& alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT"))
524 list
= alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
);
526 list
= alcGetString(NULL
, ALC_DEVICE_SPECIFIER
);
530 SetError("No device names found");
534 const ALCchar
*cur
= list
;
535 ALuint retlistLen
= 0;
538 cur
+= strlen(cur
)+1;
542 const ALCchar
**retlist
= new const ALCchar
*[retlistLen
+1];
547 ALCuint len
= strlen(cur
)+1;
548 ALCchar
*newstr
= new ALCchar
[len
];
550 memcpy(newstr
, cur
, len
);
553 retlist
[retlistLen
] = newstr
;
556 retlist
[retlistLen
] = NULL
;
562 /* Function: alureFreeDeviceNames
564 * Frees the device name array returned from alureGetDeviceNames.
567 * <alureGetDeviceNames>
569 ALURE_API ALvoid ALURE_APIENTRY
alureFreeDeviceNames(const ALCchar
**names
)
573 for(ALCuint i
= 0;names
[i
];i
++)
574 delete[] const_cast<ALCchar
*>(names
[i
]);
580 /* Function: alureInitDevice
582 * Opens the named device, creates a context with the given attributes, and
583 * sets that context as current. The name and attribute list would be the same
584 * as what's passed to alcOpenDevice and alcCreateContext respectively.
590 * <alureShutdownDevice>
592 ALURE_API ALboolean ALURE_APIENTRY
alureInitDevice(const ALCchar
*name
, const ALCint
*attribs
)
594 ALCdevice
*device
= alcOpenDevice(name
);
599 SetError("Device open failed");
603 ALCcontext
*context
= alcCreateContext(device
, attribs
);
604 if(alcGetError(device
) != ALC_NO_ERROR
|| !context
)
606 alcCloseDevice(device
);
608 SetError("Context creation failed");
612 alcMakeContextCurrent(context
);
613 if(alcGetError(device
) != AL_NO_ERROR
)
615 alcDestroyContext(context
);
616 alcCloseDevice(device
);
618 SetError("Context setup failed");
625 /* Function: alureShutdownDevice
627 * Destroys the current context and closes its associated device.
635 ALURE_API ALboolean ALURE_APIENTRY
alureShutdownDevice(void)
637 ALCcontext
*context
= alcGetCurrentContext();
638 ALCdevice
*device
= alcGetContextsDevice(context
);
639 if(alcGetError(device
) != ALC_NO_ERROR
|| !device
)
641 SetError("Failed to get current device");
645 if(alcMakeContextCurrent(NULL
) == ALC_FALSE
)
648 SetError("Failed to unset current context");
652 alcDestroyContext(context
);
653 alcCloseDevice(device
);
660 /* Function: alureGetSampleFormat
662 * Retrieves an OpenAL format for the given sample format. If bits is non-0,
663 * floatbits must be 0, and if floatbits is non-0, bits must be 0. The
664 * application should not rely on any particular format enum being returned as
665 * it is dependant on the available extensions. The returned format will be
666 * valid for the current context. Requires an active context.
669 * An OpenAL format enum for the given sample format, or AL_NONE if one can't
672 ALURE_API ALenum ALURE_APIENTRY
alureGetSampleFormat(ALuint channels
, ALuint bits
, ALuint floatbits
)
674 if(alGetError() != AL_NO_ERROR
)
676 SetError("Existing OpenAL error");
680 if(bits
&& floatbits
)
682 SetError("Both bit-types specified");
687 return GetSampleFormat(channels
, bits
, false);
688 return GetSampleFormat(channels
, floatbits
, true);
692 /* Function: alureInstallDecodeCallbacks
694 * Installs callbacks to enable ALURE to handle more file types. The index is
695 * the order that each given set of callbacks will be tried, starting at the
696 * most negative number (INT_MIN) and going up. Negative indices will be tried
697 * before the built-in decoders, and positive indices will be tried after.
698 * Installing callbacks onto the same index multiple times will remove the
699 * previous callbacks, and removing old callbacks won't affect any opened files
700 * using them (they'll continue to use the old functions until properly closed,
701 * although newly opened files will use the new ones). Passing NULL for all
702 * callbacks is a valid way to remove an installed set, otherwise certain
703 * callbacks must be specified. Callbacks that are not specified will assume
707 * open_file - This callback is expected to open the named file and prepare it
708 * for decoding. If the callbacks cannot decode the file, NULL
709 * should be returned to indicate failure. Upon success, a non-NULL
710 * handle must be returned, which will be used as a unique
711 * identifier for the decoder instance. This callback is required
712 * if open_memory is not specified.
713 * open_memory - This callback behaves the same as open_file, except it takes a
714 * memory segment for input instead of a filename. The given
715 * memory will remain valid while the instance is open. This
716 * callback is required if open_file is not specified.
717 * get_format - This callback is used to retrieve the format of the decoded
718 * data for the given instance. It is the responsibility of the
719 * function to make sure the returned format is valid for the
720 * current AL context (eg. don't return AL_FORMAT_QUAD16 if the
721 * AL_EXT_MCFORMATS extension isn't available). Returning 0 for
722 * samplerate or blocksize, or returning AL_NONE for format, will
723 * cause a failure. Returning AL_FALSE indicates failure. This
724 * callback is required.
725 * decode - This callback is called to get more decoded data. Up to the
726 * specified amount of bytes should be written to the data pointer.
727 * The number of bytes written should be a multiple of the block size,
728 * otherwise an OpenAL error may occur during buffering. The function
729 * should return the number of bytes written. This callback is
731 * rewind - This callback is for rewinding the instance so that the next decode
732 * calls for it will get audio data from the start of the sound file.
733 * If the stream fails to rewind, AL_FALSE should be returned.
734 * close - This callback is called at the end of processing for a particular
735 * instance. The handle will not be used further and any associated
736 * data may be deleted.
741 ALURE_API ALboolean ALURE_APIENTRY
alureInstallDecodeCallbacks(ALint index
,
742 void* (*open_file
)(const ALchar
*filename
),
743 void* (*open_memory
)(const ALubyte
*data
, ALuint length
),
744 ALboolean (*get_format
)(void *instance
, ALenum
*format
, ALuint
*samplerate
, ALuint
*blocksize
),
745 ALuint (*decode
)(void *instance
, ALubyte
*data
, ALuint bytes
),
746 ALboolean (*rewind
)(void *instance
),
747 void (*close
)(void *instance
))
749 if(!open_file
&& !open_memory
&& !get_format
&& !decode
&& !rewind
&& !close
)
751 std::map
<ALint
,UserCallbacks
>::iterator i
= InstalledCallbacks
.find(index
);
752 if(i
!= InstalledCallbacks
.end())
753 InstalledCallbacks
.erase(i
);
757 if((!open_file
&& !open_memory
) || !get_format
|| !decode
)
759 SetError("Missing callback functions");
764 newcb
.open_file
= open_file
;
765 newcb
.open_mem
= open_memory
;
766 newcb
.get_fmt
= get_format
;
767 newcb
.decode
= decode
;
768 newcb
.rewind
= rewind
;
771 InstalledCallbacks
[index
] = newcb
;
777 /* Function: alureSleep
779 * Rests the calling thread for the given number of seconds.
784 ALURE_API ALboolean ALURE_APIENTRY
alureSleep(ALfloat duration
)
788 SetError("Invalid duration");
792 ALuint seconds
= (ALuint
)duration
;
793 ALfloat rest
= duration
- (ALfloat
)seconds
;
795 #ifdef HAVE_NANOSLEEP
797 struct timespec t
, remainingTime
;
798 t
.tv_sec
= (time_t)seconds
;
799 t
.tv_nsec
= (long)(rest
*1000000)*1000;
801 while(nanosleep(&t
, &remainingTime
) < 0 && errno
== EINTR
)
804 #elif defined(HAVE_WINDOWS_H)
811 Sleep((DWORD
)(rest
* 1000));
819 /* Function: alureGetProcAddress
821 * Returns a pointer for the named ALURE function.
826 ALURE_API
void* ALURE_APIENTRY
alureGetProcAddress(const ALchar
*funcname
)
828 if(FunctionList
.size() == 0)
830 #define ADD_FUNCTION(x) FunctionList[#x] = (void*)(x)
831 ADD_FUNCTION(alureGetVersion
);
832 ADD_FUNCTION(alureGetErrorString
);
833 ADD_FUNCTION(alureGetDeviceNames
);
834 ADD_FUNCTION(alureFreeDeviceNames
);
835 ADD_FUNCTION(alureInitDevice
);
836 ADD_FUNCTION(alureShutdownDevice
);
837 ADD_FUNCTION(alureGetSampleFormat
);
838 ADD_FUNCTION(alureSleep
);
839 ADD_FUNCTION(alureCreateBufferFromFile
);
840 ADD_FUNCTION(alureCreateBufferFromMemory
);
841 ADD_FUNCTION(alureBufferDataFromFile
);
842 ADD_FUNCTION(alureBufferDataFromMemory
);
843 ADD_FUNCTION(alureCreateStreamFromFile
);
844 ADD_FUNCTION(alureCreateStreamFromMemory
);
845 ADD_FUNCTION(alureCreateStreamFromStaticMemory
);
846 ADD_FUNCTION(alureCreateStreamFromCallback
);
847 ADD_FUNCTION(alureRewindStream
);
848 ADD_FUNCTION(alureDestroyStream
);
849 ADD_FUNCTION(alureInstallDecodeCallbacks
);
850 ADD_FUNCTION(alureSetIOCallbacks
);
851 ADD_FUNCTION(alureGetProcAddress
);
852 ADD_FUNCTION(alurePlaySourceStream
);
853 ADD_FUNCTION(alurePlaySource
);
854 ADD_FUNCTION(alureStopSource
);
855 ADD_FUNCTION(alureGetSourceOffset
);
859 std::map
<std::string
,void*>::iterator i
= FunctionList
.find(funcname
);
860 if(i
!= FunctionList
.end())
863 SetError("Function not found");