12 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
14 #define DECL(x) { #x, (ALCvoid*)(x) }
16 const ALCchar
*funcName
;
19 DECL(alcCreateContext
),
20 DECL(alcMakeContextCurrent
),
21 DECL(alcProcessContext
),
22 DECL(alcSuspendContext
),
23 DECL(alcDestroyContext
),
24 DECL(alcGetCurrentContext
),
25 DECL(alcGetContextsDevice
),
29 DECL(alcIsExtensionPresent
),
30 DECL(alcGetProcAddress
),
31 DECL(alcGetEnumValue
),
34 DECL(alcCaptureOpenDevice
),
35 DECL(alcCaptureCloseDevice
),
36 DECL(alcCaptureStart
),
38 DECL(alcCaptureSamples
),
53 DECL(alIsExtensionPresent
),
54 DECL(alGetProcAddress
),
63 DECL(alGetListener3f
),
64 DECL(alGetListenerfv
),
66 DECL(alGetListener3i
),
67 DECL(alGetListeneriv
),
69 DECL(alDeleteSources
),
85 DECL(alSourceRewindv
),
91 DECL(alSourceQueueBuffers
),
92 DECL(alSourceUnqueueBuffers
),
94 DECL(alDeleteBuffers
),
109 DECL(alDopplerFactor
),
110 DECL(alDopplerVelocity
),
111 DECL(alSpeedOfSound
),
112 DECL(alDistanceModel
),
116 #define DECL(x) { #x, (x) }
117 static const struct {
118 const ALCchar
*enumName
;
120 } alcEnumerations
[] = {
125 DECL(ALC_MAJOR_VERSION
),
126 DECL(ALC_MINOR_VERSION
),
127 DECL(ALC_ATTRIBUTES_SIZE
),
128 DECL(ALC_ALL_ATTRIBUTES
),
129 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
130 DECL(ALC_DEVICE_SPECIFIER
),
131 DECL(ALC_ALL_DEVICES_SPECIFIER
),
132 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
133 DECL(ALC_EXTENSIONS
),
137 DECL(ALC_MONO_SOURCES
),
138 DECL(ALC_STEREO_SOURCES
),
139 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
140 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
141 DECL(ALC_CAPTURE_SAMPLES
),
144 DECL(ALC_INVALID_DEVICE
),
145 DECL(ALC_INVALID_CONTEXT
),
146 DECL(ALC_INVALID_ENUM
),
147 DECL(ALC_INVALID_VALUE
),
148 DECL(ALC_OUT_OF_MEMORY
),
155 DECL(AL_SOURCE_RELATIVE
),
156 DECL(AL_CONE_INNER_ANGLE
),
157 DECL(AL_CONE_OUTER_ANGLE
),
167 DECL(AL_ORIENTATION
),
168 DECL(AL_REFERENCE_DISTANCE
),
169 DECL(AL_ROLLOFF_FACTOR
),
170 DECL(AL_CONE_OUTER_GAIN
),
171 DECL(AL_MAX_DISTANCE
),
173 DECL(AL_SAMPLE_OFFSET
),
174 DECL(AL_BYTE_OFFSET
),
175 DECL(AL_SOURCE_TYPE
),
178 DECL(AL_UNDETERMINED
),
180 DECL(AL_SOURCE_STATE
),
186 DECL(AL_BUFFERS_QUEUED
),
187 DECL(AL_BUFFERS_PROCESSED
),
189 DECL(AL_FORMAT_MONO8
),
190 DECL(AL_FORMAT_MONO16
),
191 DECL(AL_FORMAT_STEREO8
),
192 DECL(AL_FORMAT_STEREO16
),
204 DECL(AL_INVALID_NAME
),
205 DECL(AL_INVALID_ENUM
),
206 DECL(AL_INVALID_VALUE
),
207 DECL(AL_INVALID_OPERATION
),
208 DECL(AL_OUT_OF_MEMORY
),
215 DECL(AL_DOPPLER_FACTOR
),
216 DECL(AL_DOPPLER_VELOCITY
),
217 DECL(AL_DISTANCE_MODEL
),
218 DECL(AL_SPEED_OF_SOUND
),
220 DECL(AL_INVERSE_DISTANCE
),
221 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
222 DECL(AL_LINEAR_DISTANCE
),
223 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
224 DECL(AL_EXPONENT_DISTANCE
),
225 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
229 static const ALCchar alcNoError
[] = "No Error";
230 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
231 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
232 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
233 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
234 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
235 static const ALCchar alcExtensionList
[] =
236 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE";
238 static const ALCint alcMajorVersion
= 1;
239 static const ALCint alcMinorVersion
= 1;
242 static ATOMIC(ALCenum
) LastError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
243 PtrIntMap DeviceIfaceMap
= PTRINTMAP_STATIC_INITIALIZE
;
244 PtrIntMap ContextIfaceMap
= PTRINTMAP_STATIC_INITIALIZE
;
247 typedef struct EnumeratedList
{
253 static EnumeratedList DevicesList
= { NULL
, NULL
, NULL
, 0 };
254 static EnumeratedList AllDevicesList
= { NULL
, NULL
, NULL
, 0 };
255 static EnumeratedList CaptureDevicesList
= { NULL
, NULL
, NULL
, 0 };
257 static void ClearDeviceList(EnumeratedList
*list
)
261 list
->NamesEnd
= NULL
;
263 free(list
->Indicies
);
264 list
->Indicies
= NULL
;
268 static void AppendDeviceList(EnumeratedList
*list
, const ALCchar
*names
, ALint idx
)
270 const ALCchar
*name_end
= names
;
273 ALCint
*new_indicies
;
282 name_end
+= strlen(name_end
)+1;
284 if(names
== name_end
)
287 len
= (list
->NamesEnd
- list
->Names
) + (name_end
- names
);
288 new_list
= calloc(1, len
+ 1);
289 memcpy(new_list
, list
->Names
, list
->NamesEnd
- list
->Names
);
290 memcpy(new_list
+ (list
->NamesEnd
- list
->Names
), names
, name_end
- names
);
292 list
->Names
= new_list
;
293 list
->NamesEnd
= list
->Names
+ len
;
295 new_indicies
= calloc(sizeof(ALCint
), list
->IndexSize
+ count
);
296 for(i
= 0;i
< list
->IndexSize
;i
++)
297 new_indicies
[i
] = list
->Indicies
[i
];
298 for(i
= 0;i
< count
;i
++)
299 new_indicies
[list
->IndexSize
+i
] = idx
;
300 free(list
->Indicies
);
301 list
->Indicies
= new_indicies
;
302 list
->IndexSize
+= count
;
306 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*devicename
)
311 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
317 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrlist
)
322 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
327 ALC_API
void ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
331 ALint idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
333 return DriverList
[idx
].alcProcessContext(context
);
335 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
338 ALC_API
void ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
342 ALint idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
344 return DriverList
[idx
].alcSuspendContext(context
);
346 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
349 ALC_API
void ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
353 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
358 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*context
)
362 ALint idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
364 return DriverList
[idx
].alcGetContextsDevice(context
);
366 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
371 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
375 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
376 if(idx
< 0) return ALC_INVALID_DEVICE
;
377 return DriverList
[idx
].alcGetError(device
);
379 return ATOMIC_EXCHANGE_SEQ(&LastError
, ALC_NO_ERROR
);
382 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extname
)
389 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
392 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
395 return DriverList
[idx
].alcIsExtensionPresent(device
, extname
);
398 len
= strlen(extname
);
399 ptr
= alcExtensionList
;
402 if(strncasecmp(ptr
, extname
, len
) == 0 && (ptr
[len
] == '\0' || isspace(ptr
[len
])))
404 if((ptr
=strchr(ptr
, ' ')) != NULL
)
408 } while(isspace(*ptr
));
414 ALC_API
void* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcname
)
420 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
423 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
426 return DriverList
[idx
].alcGetProcAddress(device
, funcname
);
429 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
431 if(strcmp(funcname
, alcFunctions
[i
].funcName
) == 0)
432 return alcFunctions
[i
].address
;
437 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumname
)
443 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
446 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
449 return DriverList
[idx
].alcGetEnumValue(device
, enumname
);
452 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
454 if(strcmp(enumname
, alcEnumerations
[i
].enumName
) == 0)
455 return alcEnumerations
[i
].value
;
460 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*device
, ALCenum param
)
466 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
469 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
472 return DriverList
[idx
].alcGetString(device
, param
);
479 case ALC_INVALID_ENUM
:
480 return alcErrInvalidEnum
;
481 case ALC_INVALID_VALUE
:
482 return alcErrInvalidValue
;
483 case ALC_INVALID_DEVICE
:
484 return alcErrInvalidDevice
;
485 case ALC_INVALID_CONTEXT
:
486 return alcErrInvalidContext
;
487 case ALC_OUT_OF_MEMORY
:
488 return alcErrOutOfMemory
;
492 case ALC_DEVICE_SPECIFIER
:
493 ClearDeviceList(&DevicesList
);
494 for(i
= 0;i
< DriverListSize
;i
++)
496 /* Only enumerate names from drivers that support it.
497 * FIXME: Check for ALC 1.1 too, since that guarantees enumeration
500 if(DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATION_EXT"))
501 AppendDeviceList(&DevicesList
,
502 DriverList
[i
].alcGetString(NULL
, ALC_DEVICE_SPECIFIER
), i
505 return DevicesList
.Names
;
507 case ALC_ALL_DEVICES_SPECIFIER
:
508 ClearDeviceList(&AllDevicesList
);
509 for(i
= 0;i
< DriverListSize
;i
++)
511 /* If the driver doesn't support ALC_ENUMERATE_ALL_EXT, substitute
512 * standard enumeration.
514 if(DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT"))
515 AppendDeviceList(&AllDevicesList
,
516 DriverList
[i
].alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
), i
518 else if(DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATION_EXT"))
519 AppendDeviceList(&AllDevicesList
,
520 DriverList
[i
].alcGetString(NULL
, ALC_DEVICE_SPECIFIER
), i
523 return AllDevicesList
.Names
;
525 case ALC_CAPTURE_DEVICE_SPECIFIER
:
526 ClearDeviceList(&CaptureDevicesList
);
527 for(i
= 0;i
< DriverListSize
;i
++)
529 if(DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_EXT_CAPTURE"))
530 AppendDeviceList(&CaptureDevicesList
,
531 DriverList
[i
].alcGetString(NULL
, ALC_CAPTURE_DEVICE_SPECIFIER
), i
534 return CaptureDevicesList
.Names
;
536 case ALC_DEFAULT_DEVICE_SPECIFIER
:
537 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
538 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
539 if(DriverListSize
> 0)
540 return DriverList
[0].alcGetString(NULL
, param
);
544 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_ENUM
);
550 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
554 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
557 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
560 return DriverList
[idx
].alcGetIntegerv(device
, param
, size
, values
);
563 if(size
<= 0 || values
== NULL
)
565 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_VALUE
);
571 case ALC_MAJOR_VERSION
:
574 values
[0] = alcMajorVersion
;
578 case ALC_MINOR_VERSION
:
581 values
[0] = alcMinorVersion
;
584 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_VALUE
);
587 case ALC_ATTRIBUTES_SIZE
:
588 case ALC_ALL_ATTRIBUTES
:
592 case ALC_MONO_SOURCES
:
593 case ALC_STEREO_SOURCES
:
594 case ALC_CAPTURE_SAMPLES
:
595 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
599 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_ENUM
);
605 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*devicename
, ALCuint frequency
, ALCenum format
, ALCsizei buffersize
)
610 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
615 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
619 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
621 return DriverList
[idx
].alcCaptureStart(device
);
623 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
626 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
630 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
632 return DriverList
[idx
].alcCaptureStop(device
);
634 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
637 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
641 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
643 return DriverList
[idx
].alcCaptureSamples(device
, buffer
, samples
);
645 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);