Get it rid of an unused macro
[alure.git] / src / alure.cpp
blob2bd2f756c6b5136a0db336ca51cdfc3960866670
1 /*
2 * ALURE OpenAL utility library
3 * Copyright (c) 2009 by Chris Robinson.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 /* Title: Main and Miscellanious */
26 #include "config.h"
28 #include "main.h"
30 #include <string.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <time.h>
34 #ifdef HAVE_WINDOWS_H
35 #include <windows.h>
36 #endif
38 #include <vector>
39 #include <string>
40 #include <map>
42 std::map<ALint,UserCallbacks> InstalledCallbacks;
43 CRITICAL_SECTION cs_StreamPlay;
44 alureStream::ListType alureStream::StreamList;
47 #ifdef HAVE_GCC_CONSTRUCTOR
48 static void init_alure(void) __attribute__((constructor));
49 static void deinit_alure(void) __attribute__((destructor));
50 static struct MyConstructorClass {
51 ~MyConstructorClass()
52 { alureStream::Clear(); };
53 } MyConstructor;
54 #elif defined(_WIN32) && !defined(ALURE_STATIC_LIBRARY)
55 static void init_alure(void);
56 static void deinit_alure(void);
57 static struct MyConstructorClass {
58 ~MyConstructorClass()
59 { alureStream::Clear(); };
60 } MyConstructor;
62 extern "C" BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/)
64 // Perform actions based on the reason for calling.
65 switch(reason)
67 case DLL_PROCESS_ATTACH:
68 DisableThreadLibraryCalls(module);
69 init_alure();
70 break;
72 case DLL_PROCESS_DETACH:
73 deinit_alure();
74 break;
76 return TRUE;
78 #else
79 static void init_alure(void);
80 static void deinit_alure(void);
82 static struct MyConstructorClass {
83 MyConstructorClass()
84 { init_alure(); };
85 ~MyConstructorClass()
86 { alureStream::Clear();
87 deinit_alure(); };
88 } MyConstructor;
89 #endif
91 static void init_alure(void)
93 InitializeCriticalSection(&cs_StreamPlay);
95 // These calls actually just return references to the codecs' Decoder
96 // objects. They aren't really used for anything other than to prevent the
97 // compiler from removing the codec initializers.
98 alure_init_wav();
99 alure_init_aiff();
100 #ifdef HAS_VORBISFILE
101 alure_init_vorbisfile();
102 #endif
103 #ifdef HAS_FLAC
104 alure_init_flac();
105 #endif
106 #ifdef HAS_SNDFILE
107 alure_init_sndfile();
108 #endif
109 #ifdef HAS_FLUIDSYNTH
110 alure_init_fluidsynth();
111 #endif
112 #ifdef HAS_DUMB
113 alure_init_dumb();
114 #endif
115 #ifdef HAS_MODPLUG
116 alure_init_modplug();
117 #endif
118 #ifdef HAS_MPG123
119 alure_init_mpg123();
120 #endif
123 static void deinit_alure(void)
125 DeleteCriticalSection(&cs_StreamPlay);
129 #ifndef DYNLOAD
130 void *OpenLib(const char*)
131 { return (void*)0xDEADBEEF; }
132 void CloseLib(void*)
135 #elif defined(_WIN32)
137 void *OpenLib(const char *libname)
138 { return LoadLibraryA(libname); }
139 void CloseLib(void *hdl)
140 { FreeLibrary((HINSTANCE)hdl); }
141 void *GetLibProc(void *hdl, const char *funcname)
142 { return (void*)GetProcAddress((HINSTANCE)hdl, funcname); }
144 #else
146 void *OpenLib(const char *libname)
148 const char *err = dlerror();
149 void *hdl = dlopen(libname, RTLD_NOW);
150 if((err=dlerror()) != NULL)
152 fprintf(stderr, "Error loading %s: %s\n", libname, err);
153 return NULL;
155 return hdl;
157 void *GetLibProc(void *hdl, const char *funcname)
159 const char *err = dlerror();
160 void *fn = dlsym(hdl, funcname);
161 if((err=dlerror()) != NULL)
163 fprintf(stderr, "Error loading %s: %s\n", funcname, err);
164 return NULL;
166 return fn;
168 void CloseLib(void *hdl)
169 { dlclose(hdl); }
170 #endif
173 static const ALchar *last_error = "No error";
174 void SetError(const char *err)
176 last_error = err;
180 ALuint DetectBlockAlignment(ALenum format)
182 switch(format)
184 #define CHECK_RET(f,s) case (f): return (s)
185 CHECK_RET(AL_FORMAT_MONO8, sizeof(ALubyte));
186 CHECK_RET(AL_FORMAT_MONO16, sizeof(ALshort));
187 CHECK_RET(AL_FORMAT_MONO_FLOAT32, sizeof(ALfloat));
188 CHECK_RET(AL_FORMAT_MONO_DOUBLE_EXT, sizeof(ALdouble));
189 CHECK_RET(AL_FORMAT_MONO_MULAW, sizeof(ALubyte)*1);
191 CHECK_RET(AL_FORMAT_STEREO8, sizeof(ALubyte)*2);
192 CHECK_RET(AL_FORMAT_STEREO16, sizeof(ALshort)*2);
193 CHECK_RET(AL_FORMAT_STEREO_FLOAT32, sizeof(ALfloat)*2);
194 CHECK_RET(AL_FORMAT_STEREO_DOUBLE_EXT, sizeof(ALdouble)*2);
195 CHECK_RET(AL_FORMAT_STEREO_MULAW, sizeof(ALubyte)*2);
197 CHECK_RET(AL_FORMAT_QUAD8, sizeof(ALubyte)*4);
198 CHECK_RET(AL_FORMAT_QUAD16, sizeof(ALshort)*4);
199 CHECK_RET(AL_FORMAT_QUAD32, sizeof(ALfloat)*4);
200 CHECK_RET(AL_FORMAT_QUAD_MULAW, sizeof(ALubyte)*4);
202 CHECK_RET(AL_FORMAT_REAR8, sizeof(ALubyte)*2);
203 CHECK_RET(AL_FORMAT_REAR16, sizeof(ALshort)*2);
204 CHECK_RET(AL_FORMAT_REAR32, sizeof(ALfloat)*2);
205 CHECK_RET(AL_FORMAT_REAR_MULAW, sizeof(ALubyte)*2);
207 CHECK_RET(AL_FORMAT_51CHN8, sizeof(ALubyte)*6);
208 CHECK_RET(AL_FORMAT_51CHN16, sizeof(ALshort)*6);
209 CHECK_RET(AL_FORMAT_51CHN32, sizeof(ALfloat)*6);
210 CHECK_RET(AL_FORMAT_51CHN_MULAW, sizeof(ALubyte)*6);
212 CHECK_RET(AL_FORMAT_61CHN8, sizeof(ALubyte)*7);
213 CHECK_RET(AL_FORMAT_61CHN16, sizeof(ALshort)*7);
214 CHECK_RET(AL_FORMAT_61CHN32, sizeof(ALfloat)*7);
215 CHECK_RET(AL_FORMAT_61CHN_MULAW, sizeof(ALubyte)*7);
217 CHECK_RET(AL_FORMAT_71CHN8, sizeof(ALubyte)*8);
218 CHECK_RET(AL_FORMAT_71CHN16, sizeof(ALshort)*8);
219 CHECK_RET(AL_FORMAT_71CHN32, sizeof(ALfloat)*8);
220 CHECK_RET(AL_FORMAT_71CHN_MULAW, sizeof(ALubyte)*8);
222 CHECK_RET(AL_FORMAT_MONO_IMA4, 36);
223 CHECK_RET(AL_FORMAT_STEREO_IMA4, 36*2);
224 #undef CHECK_RET
226 return 0;
229 ALuint DetectCompressionRate(ALenum format)
231 switch(format)
233 case AL_FORMAT_MONO8:
234 case AL_FORMAT_MONO16:
235 case AL_FORMAT_MONO_FLOAT32:
236 case AL_FORMAT_MONO_DOUBLE_EXT:
237 case AL_FORMAT_STEREO8:
238 case AL_FORMAT_STEREO16:
239 case AL_FORMAT_STEREO_FLOAT32:
240 case AL_FORMAT_STEREO_DOUBLE_EXT:
241 case AL_FORMAT_QUAD8:
242 case AL_FORMAT_QUAD16:
243 case AL_FORMAT_QUAD32:
244 case AL_FORMAT_REAR8:
245 case AL_FORMAT_REAR16:
246 case AL_FORMAT_REAR32:
247 case AL_FORMAT_51CHN8:
248 case AL_FORMAT_51CHN16:
249 case AL_FORMAT_51CHN32:
250 case AL_FORMAT_61CHN8:
251 case AL_FORMAT_61CHN16:
252 case AL_FORMAT_61CHN32:
253 case AL_FORMAT_71CHN8:
254 case AL_FORMAT_71CHN16:
255 case AL_FORMAT_71CHN32:
256 return 1;
258 case AL_FORMAT_MONO_MULAW:
259 case AL_FORMAT_STEREO_MULAW:
260 case AL_FORMAT_QUAD_MULAW:
261 case AL_FORMAT_REAR_MULAW:
262 case AL_FORMAT_51CHN_MULAW:
263 case AL_FORMAT_61CHN_MULAW:
264 case AL_FORMAT_71CHN_MULAW:
265 return 1;
267 case AL_FORMAT_MONO_IMA4:
268 case AL_FORMAT_STEREO_IMA4:
269 return 65;
271 fprintf(stderr, "Alure lib: Unhandled format: %#x\n", format);
272 return 0;
275 ALenum GetSampleFormat(ALuint channels, ALuint bits, bool isFloat)
277 #define CHECK_FMT_RET(f) do { \
278 ALenum fmt = alGetEnumValue(#f); \
279 if(alGetError() == AL_NO_ERROR && fmt != 0 && fmt != -1) \
280 return fmt; \
281 } while(0)
282 if(!isFloat)
284 if(bits == 8)
286 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO8);
287 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO8);
288 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
290 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD8);
291 if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN8);
292 if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN8);
293 if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN8);
295 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
297 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD8_LOKI);
299 SetError("Unsupported 8-bit channel count\n");
300 return AL_NONE;
302 if(bits == 16)
304 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO16);
305 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO16);
306 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
308 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD16);
309 if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN16);
310 if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN16);
311 if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN16);
313 if(alIsExtensionPresent("AL_LOKI_quadriphonic"))
315 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD16_LOKI);
317 SetError("Unsupported 16-bit channel count\n");
318 return AL_NONE;
320 SetError("Unsupported PCM bit depth\n");
321 return AL_NONE;
324 if(bits == 32 && alIsExtensionPresent("AL_EXT_FLOAT32"))
326 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO_FLOAT32);
327 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO_FLOAT32);
328 if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
330 if(channels == 4) CHECK_FMT_RET(AL_FORMAT_QUAD32);
331 if(channels == 6) CHECK_FMT_RET(AL_FORMAT_51CHN32);
332 if(channels == 7) CHECK_FMT_RET(AL_FORMAT_61CHN32);
333 if(channels == 8) CHECK_FMT_RET(AL_FORMAT_71CHN32);
335 SetError("Unsupported float32 channel count\n");
336 return AL_NONE;
338 if(bits == 64 && alIsExtensionPresent("AL_EXT_DOUBLE"))
340 if(channels == 1) CHECK_FMT_RET(AL_FORMAT_MONO_DOUBLE_EXT);
341 if(channels == 2) CHECK_FMT_RET(AL_FORMAT_STEREO_DOUBLE_EXT);
342 SetError("Unsupported double channel count\n");
343 return AL_NONE;
345 #undef CHECK_FMT_RET
347 SetError("Unsupported float bit depth\n");
348 return AL_NONE;
351 extern "C" {
353 /* Function: alureGetVersion
355 * Stores the major and minor version of the library. If either major or minor
356 * are NULL, that value is not provided.
358 ALURE_API void ALURE_APIENTRY alureGetVersion(ALuint *major, ALuint *minor)
360 if(major) *major = ALURE_VER_MAJOR;
361 if(minor) *minor = ALURE_VER_MINOR;
364 /* Function: alureGetErrorString
366 * Returns a string describing the last error encountered.
368 ALURE_API const ALchar* ALURE_APIENTRY alureGetErrorString(void)
370 const ALchar *ret = last_error;
371 last_error = "No error";
372 return ret;
376 /* Function: alureGetDeviceNames
378 * Gets an array of device name strings from OpenAL. This encapsulates
379 * AL_ENUMERATE_ALL_EXT (if supported and 'all' is true) and standard
380 * enumeration, with 'count' being set to the number of returned device
381 * names.
383 * Returns:
384 * An array of device name strings, or NULL on error.
386 * See Also:
387 * <alureFreeDeviceNames>
389 ALURE_API const ALCchar** ALURE_APIENTRY alureGetDeviceNames(ALCboolean all, ALCsizei *count)
391 const ALCchar *list = NULL;
392 if(all && alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
393 list = alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
394 else
395 list = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
396 if(!list)
398 alcGetError(NULL);
399 SetError("No device names found");
400 return NULL;
403 const ALCchar *cur = list;
404 ALuint retlistLen = 0;
405 while(*cur)
407 cur += strlen(cur)+1;
408 retlistLen++;
411 const ALCchar **retlist = new const ALCchar*[retlistLen+1];
412 retlistLen = 0;
413 cur = list;
414 while(*cur)
416 ALCuint len = strlen(cur)+1;
417 ALCchar *newstr = new ALCchar[len];
419 memcpy(newstr, cur, len);
420 cur += len;
422 retlist[retlistLen] = newstr;
423 retlistLen++;
425 retlist[retlistLen] = NULL;
427 *count = retlistLen;
428 return retlist;
431 /* Function: alureFreeDeviceNames
433 * Frees the device name array returned from alureGetDeviceNames.
435 * See Also:
436 * <alureGetDeviceNames>
438 ALURE_API ALvoid ALURE_APIENTRY alureFreeDeviceNames(const ALCchar **names)
440 if(names)
442 for(ALCuint i = 0;names[i];i++)
443 delete[] const_cast<ALCchar*>(names[i]);
444 delete[] names;
449 /* Function: alureInitDevice
451 * Opens the named device, creates a context with the given attributes, and
452 * sets that context as current. The name and attribute list would be the same
453 * as what's passed to alcOpenDevice and alcCreateContext respectively.
455 * Returns:
456 * AL_FALSE on error.
458 * See Also:
459 * <alureShutdownDevice>
461 ALURE_API ALboolean ALURE_APIENTRY alureInitDevice(const ALCchar *name, const ALCint *attribs)
463 ALCdevice *device = alcOpenDevice(name);
464 if(!device)
466 alcGetError(NULL);
468 SetError("Device open failed");
469 return AL_FALSE;
472 ALCcontext *context = alcCreateContext(device, attribs);
473 if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
475 if(context)
476 alcDestroyContext(context);
477 alcCloseDevice(device);
479 SetError("Context setup failed");
480 return AL_FALSE;
482 alcGetError(device);
484 return AL_TRUE;
487 /* Function: alureShutdownDevice
489 * Destroys the current context and closes its associated device.
491 * Returns:
492 * AL_FALSE on error.
494 * See Also:
495 * <alureInitDevice>
497 ALURE_API ALboolean ALURE_APIENTRY alureShutdownDevice(void)
499 ALCcontext *context = alcGetCurrentContext();
500 ALCdevice *device = alcGetContextsDevice(context);
501 if(!context || !device)
503 alcGetError(device);
504 SetError("Failed to get current device");
505 return AL_FALSE;
508 if(alcMakeContextCurrent(NULL) == ALC_FALSE)
510 alcGetError(NULL);
511 SetError("Failed to unset current context");
512 return AL_FALSE;
515 alcDestroyContext(context);
516 alcCloseDevice(device);
517 alcGetError(NULL);
519 return AL_TRUE;
523 /* Function: alureGetSampleFormat
525 * Retrieves an OpenAL format for the given sample format. If bits is non-0,
526 * floatbits must be 0, and if floatbits is non-0, bits must be 0. The
527 * application should not rely on any particular format enum being returned as
528 * it is dependant on the available extensions. The returned format will be
529 * valid for the current context. Requires an active context.
531 * Returns:
532 * An OpenAL format enum for the given sample format, or AL_NONE if one can't
533 * be found.
535 ALURE_API ALenum ALURE_APIENTRY alureGetSampleFormat(ALuint channels, ALuint bits, ALuint floatbits)
537 if(alGetError() != AL_NO_ERROR)
539 SetError("Existing OpenAL error");
540 return AL_NONE;
543 if(bits && floatbits)
545 SetError("Both bit-types specified");
546 return AL_NONE;
549 if(bits)
550 return GetSampleFormat(channels, bits, false);
551 return GetSampleFormat(channels, floatbits, true);
555 /* Function: alureInstallDecodeCallbacks
557 * Installs callbacks to enable ALURE to handle more file types. The index is
558 * the order that each given set of callbacks will be tried, starting at the
559 * most negative number (INT_MIN) and going up. Negative indices will be tried
560 * before the built-in decoders, and positive indices will be tried after.
561 * Installing callbacks onto the same index multiple times will remove the
562 * previous callbacks, and removing old callbacks won't affect any opened files
563 * using them (they'll continue to use the old functions until properly closed,
564 * although newly opened files will use the new ones). Passing NULL for all
565 * callbacks is a valid way to remove an installed set, otherwise certain
566 * callbacks must be specified. Callbacks that are not specified will assume
567 * failure.
569 * Parameters:
570 * open_file - This callback is expected to open the named file and prepare it
571 * for decoding. If the callbacks cannot decode the file, NULL
572 * should be returned to indicate failure. Upon success, a non-NULL
573 * handle must be returned, which will be used as a unique
574 * identifier for the decoder instance. This callback is required
575 * if open_memory is not specified.
576 * open_memory - This callback behaves the same as open_file, except it takes a
577 * memory segment for input instead of a filename. The given
578 * memory will remain valid while the instance is open. This
579 * callback is required if open_file is not specified.
580 * get_format - This callback is used to retrieve the format of the decoded
581 * data for the given instance. It is the responsibility of the
582 * function to make sure the returned format is valid for the
583 * current AL context (eg. don't return AL_FORMAT_QUAD16 if the
584 * AL_EXT_MCFORMATS extension isn't available). Returning 0 for
585 * samplerate or blocksize, or returning AL_NONE for format, will
586 * cause a failure. Returning AL_FALSE indicates failure. This
587 * callback is required.
588 * decode - This callback is called to get more decoded data. Up to the
589 * specified amount of bytes should be written to the data pointer.
590 * The number of bytes written should be a multiple of the block size,
591 * otherwise an OpenAL error may occur during buffering. The function
592 * should return the number of bytes written. This callback is
593 * required.
594 * rewind - This callback is for rewinding the instance so that the next decode
595 * calls for it will get audio data from the start of the sound file.
596 * If the stream fails to rewind, AL_FALSE should be returned.
597 * close - This callback is called at the end of processing for a particular
598 * instance. The handle will not be used further and any associated
599 * data may be deleted.
601 * Returns:
602 * AL_FALSE on error.
604 ALURE_API ALboolean ALURE_APIENTRY alureInstallDecodeCallbacks(ALint index,
605 void* (*open_file)(const ALchar *filename),
606 void* (*open_memory)(const ALubyte *data, ALuint length),
607 ALboolean (*get_format)(void *instance, ALenum *format, ALuint *samplerate, ALuint *blocksize),
608 ALuint (*decode)(void *instance, ALubyte *data, ALuint bytes),
609 ALboolean (*rewind)(void *instance),
610 void (*close)(void *instance))
612 if(!open_file && !open_memory && !get_format && !decode && !rewind && !close)
614 std::map<ALint,UserCallbacks>::iterator i = InstalledCallbacks.find(index);
615 if(i != InstalledCallbacks.end())
616 InstalledCallbacks.erase(i);
617 return AL_TRUE;
620 if((!open_file && !open_memory) || !get_format || !decode)
622 SetError("Missing callback functions");
623 return AL_FALSE;
626 UserCallbacks newcb;
627 newcb.open_file = open_file;
628 newcb.open_mem = open_memory;
629 newcb.get_fmt = get_format;
630 newcb.decode = decode;
631 newcb.rewind = rewind;
632 newcb.close = close;
634 InstalledCallbacks[index] = newcb;
636 return AL_TRUE;
640 /* Function: alureSleep
642 * Rests the calling thread for the given number of seconds.
644 * Returns:
645 * AL_FALSE on error.
647 ALURE_API ALboolean ALURE_APIENTRY alureSleep(ALfloat duration)
649 if(duration < 0.0f)
651 SetError("Invalid duration");
652 return AL_FALSE;
655 ALuint seconds = (ALuint)duration;
656 ALfloat rest = duration - (ALfloat)seconds;
658 #ifdef HAVE_NANOSLEEP
660 struct timespec t, remainingTime;
661 t.tv_sec = (time_t)seconds;
662 t.tv_nsec = (long)(rest*1000000)*1000;
664 while(nanosleep(&t, &remainingTime) < 0 && errno == EINTR)
665 t = remainingTime;
667 #elif defined(HAVE_WINDOWS_H)
669 while(seconds > 0)
671 Sleep(1000);
672 seconds--;
674 Sleep((DWORD)(rest * 1000));
676 #endif
678 return AL_TRUE;
682 /* Function: alureGetProcAddress
684 * Returns a pointer for the named ALURE function.
686 * Returns:
687 * NULL on error.
689 * *Version Added*: 1.1
691 ALURE_API void* ALURE_APIENTRY alureGetProcAddress(const ALchar *funcname)
693 static const struct {
694 const char *name;
695 void *func;
696 } FunctionList[] = {
697 #define ADD_FUNCTION(x) { #x, (void*)x },
698 ADD_FUNCTION(alureGetVersion)
699 ADD_FUNCTION(alureGetErrorString)
700 ADD_FUNCTION(alureGetDeviceNames)
701 ADD_FUNCTION(alureFreeDeviceNames)
702 ADD_FUNCTION(alureInitDevice)
703 ADD_FUNCTION(alureShutdownDevice)
704 ADD_FUNCTION(alureGetSampleFormat)
705 ADD_FUNCTION(alureSleep)
706 ADD_FUNCTION(alureCreateBufferFromFile)
707 ADD_FUNCTION(alureCreateBufferFromMemory)
708 ADD_FUNCTION(alureBufferDataFromFile)
709 ADD_FUNCTION(alureBufferDataFromMemory)
710 ADD_FUNCTION(alureCreateStreamFromFile)
711 ADD_FUNCTION(alureCreateStreamFromMemory)
712 ADD_FUNCTION(alureCreateStreamFromStaticMemory)
713 ADD_FUNCTION(alureCreateStreamFromCallback)
714 ADD_FUNCTION(alureRewindStream)
715 ADD_FUNCTION(alureDestroyStream)
716 ADD_FUNCTION(alureInstallDecodeCallbacks)
717 ADD_FUNCTION(alureSetIOCallbacks)
718 ADD_FUNCTION(alureGetProcAddress)
719 ADD_FUNCTION(alurePlaySourceStream)
720 ADD_FUNCTION(alurePlaySource)
721 ADD_FUNCTION(alureStopSource)
722 #undef ADD_FUNCTION
723 { NULL, NULL }
726 size_t i;
727 for(i = 0;FunctionList[i].name;i++)
729 if(strcmp(FunctionList[i].name, funcname) == 0)
730 break;
733 if(!FunctionList[i].name)
734 SetError("Function not found");
735 return FunctionList[i].func;
738 } // extern "C"