Print the opened device in alffplay
[openal-soft.git] / router / alc.c
blobe8346ef152b2c210ce654b9e64710f56cdabb695
2 #include "config.h"
4 #include <stddef.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdio.h>
9 #include "AL/alc.h"
10 #include "router.h"
11 #include "almalloc.h"
14 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
16 #define DECL(x) { #x, (ALCvoid*)(x) }
17 static const struct {
18 const ALCchar *funcName;
19 ALCvoid *address;
20 } alcFunctions[] = {
21 DECL(alcCreateContext),
22 DECL(alcMakeContextCurrent),
23 DECL(alcProcessContext),
24 DECL(alcSuspendContext),
25 DECL(alcDestroyContext),
26 DECL(alcGetCurrentContext),
27 DECL(alcGetContextsDevice),
28 DECL(alcOpenDevice),
29 DECL(alcCloseDevice),
30 DECL(alcGetError),
31 DECL(alcIsExtensionPresent),
32 DECL(alcGetProcAddress),
33 DECL(alcGetEnumValue),
34 DECL(alcGetString),
35 DECL(alcGetIntegerv),
36 DECL(alcCaptureOpenDevice),
37 DECL(alcCaptureCloseDevice),
38 DECL(alcCaptureStart),
39 DECL(alcCaptureStop),
40 DECL(alcCaptureSamples),
42 DECL(alEnable),
43 DECL(alDisable),
44 DECL(alIsEnabled),
45 DECL(alGetString),
46 DECL(alGetBooleanv),
47 DECL(alGetIntegerv),
48 DECL(alGetFloatv),
49 DECL(alGetDoublev),
50 DECL(alGetBoolean),
51 DECL(alGetInteger),
52 DECL(alGetFloat),
53 DECL(alGetDouble),
54 DECL(alGetError),
55 DECL(alIsExtensionPresent),
56 DECL(alGetProcAddress),
57 DECL(alGetEnumValue),
58 DECL(alListenerf),
59 DECL(alListener3f),
60 DECL(alListenerfv),
61 DECL(alListeneri),
62 DECL(alListener3i),
63 DECL(alListeneriv),
64 DECL(alGetListenerf),
65 DECL(alGetListener3f),
66 DECL(alGetListenerfv),
67 DECL(alGetListeneri),
68 DECL(alGetListener3i),
69 DECL(alGetListeneriv),
70 DECL(alGenSources),
71 DECL(alDeleteSources),
72 DECL(alIsSource),
73 DECL(alSourcef),
74 DECL(alSource3f),
75 DECL(alSourcefv),
76 DECL(alSourcei),
77 DECL(alSource3i),
78 DECL(alSourceiv),
79 DECL(alGetSourcef),
80 DECL(alGetSource3f),
81 DECL(alGetSourcefv),
82 DECL(alGetSourcei),
83 DECL(alGetSource3i),
84 DECL(alGetSourceiv),
85 DECL(alSourcePlayv),
86 DECL(alSourceStopv),
87 DECL(alSourceRewindv),
88 DECL(alSourcePausev),
89 DECL(alSourcePlay),
90 DECL(alSourceStop),
91 DECL(alSourceRewind),
92 DECL(alSourcePause),
93 DECL(alSourceQueueBuffers),
94 DECL(alSourceUnqueueBuffers),
95 DECL(alGenBuffers),
96 DECL(alDeleteBuffers),
97 DECL(alIsBuffer),
98 DECL(alBufferData),
99 DECL(alBufferf),
100 DECL(alBuffer3f),
101 DECL(alBufferfv),
102 DECL(alBufferi),
103 DECL(alBuffer3i),
104 DECL(alBufferiv),
105 DECL(alGetBufferf),
106 DECL(alGetBuffer3f),
107 DECL(alGetBufferfv),
108 DECL(alGetBufferi),
109 DECL(alGetBuffer3i),
110 DECL(alGetBufferiv),
111 DECL(alDopplerFactor),
112 DECL(alDopplerVelocity),
113 DECL(alSpeedOfSound),
114 DECL(alDistanceModel),
116 #undef DECL
118 #define DECL(x) { #x, (x) }
119 static const struct {
120 const ALCchar *enumName;
121 ALCenum value;
122 } alcEnumerations[] = {
123 DECL(ALC_INVALID),
124 DECL(ALC_FALSE),
125 DECL(ALC_TRUE),
127 DECL(ALC_MAJOR_VERSION),
128 DECL(ALC_MINOR_VERSION),
129 DECL(ALC_ATTRIBUTES_SIZE),
130 DECL(ALC_ALL_ATTRIBUTES),
131 DECL(ALC_DEFAULT_DEVICE_SPECIFIER),
132 DECL(ALC_DEVICE_SPECIFIER),
133 DECL(ALC_ALL_DEVICES_SPECIFIER),
134 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER),
135 DECL(ALC_EXTENSIONS),
136 DECL(ALC_FREQUENCY),
137 DECL(ALC_REFRESH),
138 DECL(ALC_SYNC),
139 DECL(ALC_MONO_SOURCES),
140 DECL(ALC_STEREO_SOURCES),
141 DECL(ALC_CAPTURE_DEVICE_SPECIFIER),
142 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER),
143 DECL(ALC_CAPTURE_SAMPLES),
145 DECL(ALC_NO_ERROR),
146 DECL(ALC_INVALID_DEVICE),
147 DECL(ALC_INVALID_CONTEXT),
148 DECL(ALC_INVALID_ENUM),
149 DECL(ALC_INVALID_VALUE),
150 DECL(ALC_OUT_OF_MEMORY),
152 DECL(AL_INVALID),
153 DECL(AL_NONE),
154 DECL(AL_FALSE),
155 DECL(AL_TRUE),
157 DECL(AL_SOURCE_RELATIVE),
158 DECL(AL_CONE_INNER_ANGLE),
159 DECL(AL_CONE_OUTER_ANGLE),
160 DECL(AL_PITCH),
161 DECL(AL_POSITION),
162 DECL(AL_DIRECTION),
163 DECL(AL_VELOCITY),
164 DECL(AL_LOOPING),
165 DECL(AL_BUFFER),
166 DECL(AL_GAIN),
167 DECL(AL_MIN_GAIN),
168 DECL(AL_MAX_GAIN),
169 DECL(AL_ORIENTATION),
170 DECL(AL_REFERENCE_DISTANCE),
171 DECL(AL_ROLLOFF_FACTOR),
172 DECL(AL_CONE_OUTER_GAIN),
173 DECL(AL_MAX_DISTANCE),
174 DECL(AL_SEC_OFFSET),
175 DECL(AL_SAMPLE_OFFSET),
176 DECL(AL_BYTE_OFFSET),
177 DECL(AL_SOURCE_TYPE),
178 DECL(AL_STATIC),
179 DECL(AL_STREAMING),
180 DECL(AL_UNDETERMINED),
182 DECL(AL_SOURCE_STATE),
183 DECL(AL_INITIAL),
184 DECL(AL_PLAYING),
185 DECL(AL_PAUSED),
186 DECL(AL_STOPPED),
188 DECL(AL_BUFFERS_QUEUED),
189 DECL(AL_BUFFERS_PROCESSED),
191 DECL(AL_FORMAT_MONO8),
192 DECL(AL_FORMAT_MONO16),
193 DECL(AL_FORMAT_STEREO8),
194 DECL(AL_FORMAT_STEREO16),
196 DECL(AL_FREQUENCY),
197 DECL(AL_BITS),
198 DECL(AL_CHANNELS),
199 DECL(AL_SIZE),
201 DECL(AL_UNUSED),
202 DECL(AL_PENDING),
203 DECL(AL_PROCESSED),
205 DECL(AL_NO_ERROR),
206 DECL(AL_INVALID_NAME),
207 DECL(AL_INVALID_ENUM),
208 DECL(AL_INVALID_VALUE),
209 DECL(AL_INVALID_OPERATION),
210 DECL(AL_OUT_OF_MEMORY),
212 DECL(AL_VENDOR),
213 DECL(AL_VERSION),
214 DECL(AL_RENDERER),
215 DECL(AL_EXTENSIONS),
217 DECL(AL_DOPPLER_FACTOR),
218 DECL(AL_DOPPLER_VELOCITY),
219 DECL(AL_DISTANCE_MODEL),
220 DECL(AL_SPEED_OF_SOUND),
222 DECL(AL_INVERSE_DISTANCE),
223 DECL(AL_INVERSE_DISTANCE_CLAMPED),
224 DECL(AL_LINEAR_DISTANCE),
225 DECL(AL_LINEAR_DISTANCE_CLAMPED),
226 DECL(AL_EXPONENT_DISTANCE),
227 DECL(AL_EXPONENT_DISTANCE_CLAMPED),
229 #undef DECL
231 static const ALCchar alcNoError[] = "No Error";
232 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
233 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
234 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
235 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
236 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
237 static const ALCchar alcExtensionList[] =
238 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE";
240 static const ALCint alcMajorVersion = 1;
241 static const ALCint alcMinorVersion = 1;
244 static almtx_t EnumerationLock;
245 static almtx_t ContextSwitchLock;
247 static ATOMIC(ALCenum) LastError = ATOMIC_INIT_STATIC(ALC_NO_ERROR);
248 static PtrIntMap DeviceIfaceMap = PTRINTMAP_STATIC_INITIALIZE;
249 static PtrIntMap ContextIfaceMap = PTRINTMAP_STATIC_INITIALIZE;
252 typedef struct EnumeratedList {
253 ALCchar *Names;
254 ALCchar *NamesEnd;
255 ALCint *Indicies;
256 ALCsizei IndexSize;
257 } EnumeratedList;
258 static EnumeratedList DevicesList = { NULL, NULL, NULL, 0 };
259 static EnumeratedList AllDevicesList = { NULL, NULL, NULL, 0 };
260 static EnumeratedList CaptureDevicesList = { NULL, NULL, NULL, 0 };
262 static void ClearDeviceList(EnumeratedList *list)
264 al_free(list->Names);
265 list->Names = NULL;
266 list->NamesEnd = NULL;
268 al_free(list->Indicies);
269 list->Indicies = NULL;
270 list->IndexSize = 0;
273 static void AppendDeviceList(EnumeratedList *list, const ALCchar *names, ALint idx)
275 const ALCchar *name_end = names;
276 ALCsizei count = 0;
277 ALCchar *new_list;
278 ALCint *new_indicies;
279 size_t len;
280 ALCsizei i;
282 if(!name_end)
283 return;
284 while(*name_end)
286 TRACE("Enumerated \"%s\", driver %d\n", name_end, idx);
287 count++;
288 name_end += strlen(name_end)+1;
290 if(names == name_end)
291 return;
293 len = (list->NamesEnd - list->Names) + (name_end - names);
294 new_list = al_calloc(DEF_ALIGN, len + 1);
295 memcpy(new_list, list->Names, list->NamesEnd - list->Names);
296 memcpy(new_list + (list->NamesEnd - list->Names), names, name_end - names);
297 al_free(list->Names);
298 list->Names = new_list;
299 list->NamesEnd = list->Names + len;
301 new_indicies = al_calloc(16, sizeof(ALCint)*(list->IndexSize + count));
302 for(i = 0;i < list->IndexSize;i++)
303 new_indicies[i] = list->Indicies[i];
304 for(i = 0;i < count;i++)
305 new_indicies[list->IndexSize+i] = idx;
306 al_free(list->Indicies);
307 list->Indicies = new_indicies;
308 list->IndexSize += count;
311 static ALint GetDriverIndexForName(const EnumeratedList *list, const ALCchar *name)
313 const ALCchar *devnames = list->Names;
314 const ALCint *index = list->Indicies;
316 while(devnames && *devnames)
318 if(strcmp(name, devnames) == 0)
320 TRACE("Found driver %d for name \"%s\"\n", *index, name);
321 return *index;
323 devnames += strlen(devnames)+1;
324 index++;
326 TRACE("Failed to find driver for name \"%s\"\n", name);
327 return -1;
330 void InitALC(void)
332 almtx_init(&EnumerationLock, almtx_recursive);
333 almtx_init(&ContextSwitchLock, almtx_plain);
336 void ReleaseALC(void)
338 ClearDeviceList(&DevicesList);
339 ClearDeviceList(&AllDevicesList);
340 ClearDeviceList(&CaptureDevicesList);
342 ResetPtrIntMap(&ContextIfaceMap);
343 ResetPtrIntMap(&DeviceIfaceMap);
345 almtx_destroy(&ContextSwitchLock);
346 almtx_destroy(&EnumerationLock);
350 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename)
352 ALCdevice *device = NULL;
353 ALint idx;
355 /* Prior to the enumeration extension, apps would hardcode these names as a
356 * quality hint for the wrapper driver. Ignore them since there's no sane
357 * way to map them.
359 if(devicename && (devicename[0] == '\0' ||
360 strcmp(devicename, "DirectSound3D") == 0 ||
361 strcmp(devicename, "DirectSound") == 0 ||
362 strcmp(devicename, "MMSYSTEM") == 0))
363 devicename = NULL;
364 if(devicename)
366 almtx_lock(&EnumerationLock);
367 if(!DevicesList.Names)
368 (void)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
369 idx = GetDriverIndexForName(&DevicesList, devicename);
370 if(idx < 0)
372 if(!AllDevicesList.Names)
373 (void)alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER);
374 idx = GetDriverIndexForName(&AllDevicesList, devicename);
376 almtx_unlock(&EnumerationLock);
377 if(idx >= 0)
378 device = DriverList[idx].alcOpenDevice(devicename);
379 else for(idx = 0;idx < DriverListSize;idx++)
381 device = DriverList[idx].alcOpenDevice(devicename);
382 if(device) break;
385 else
387 int i;
388 for(i = 0;i < DriverListSize;i++)
390 if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
391 DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
393 idx = i;
394 device = DriverList[idx].alcOpenDevice(NULL);
395 break;
400 if(device)
402 if(InsertPtrIntMapEntry(&DeviceIfaceMap, device, idx) != ALC_NO_ERROR)
404 DriverList[idx].alcCloseDevice(device);
405 device = NULL;
409 return device;
412 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device)
414 ALint idx;
416 if(!device || (idx=LookupPtrIntMapKey(&DeviceIfaceMap, device)) < 0)
418 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
419 return ALC_FALSE;
421 if(!DriverList[idx].alcCloseDevice(device))
422 return ALC_FALSE;
423 RemovePtrIntMapKey(&DeviceIfaceMap, device);
424 return ALC_TRUE;
428 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrlist)
430 ALCcontext *context;
431 ALint idx;
433 if(!device || (idx=LookupPtrIntMapKey(&DeviceIfaceMap, device)) < 0)
435 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
436 return ALC_FALSE;
438 context = DriverList[idx].alcCreateContext(device, attrlist);
439 if(context)
441 if(InsertPtrIntMapEntry(&ContextIfaceMap, context, idx) != ALC_NO_ERROR)
443 DriverList[idx].alcDestroyContext(context);
444 context = NULL;
448 return context;
451 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context)
453 ALint idx = -1;
455 almtx_lock(&ContextSwitchLock);
456 if(context)
458 idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
459 if(idx < 0)
461 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
462 almtx_unlock(&ContextSwitchLock);
463 return ALC_FALSE;
465 if(!DriverList[idx].alcMakeContextCurrent(context))
467 almtx_unlock(&ContextSwitchLock);
468 return ALC_FALSE;
472 /* Unset the context from the old driver if it's different from the new
473 * current one.
475 if(idx < 0)
477 DriverIface *oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, NULL);
478 if(oldiface) oldiface->alcMakeContextCurrent(NULL);
480 else
482 DriverIface *oldiface = ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver, &DriverList[idx]);
483 if(oldiface && oldiface != &DriverList[idx])
484 oldiface->alcMakeContextCurrent(NULL);
486 almtx_unlock(&ContextSwitchLock);
488 return ALC_TRUE;
491 ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context)
493 if(context)
495 ALint idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
496 if(idx >= 0)
497 return DriverList[idx].alcProcessContext(context);
499 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
502 ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context)
504 if(context)
506 ALint idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
507 if(idx >= 0)
508 return DriverList[idx].alcSuspendContext(context);
510 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
513 ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context)
515 ALint idx;
517 if(!context || (idx=LookupPtrIntMapKey(&ContextIfaceMap, context)) < 0)
519 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
520 return;
523 DriverList[idx].alcDestroyContext(context);
524 RemovePtrIntMapKey(&ContextIfaceMap, context);
527 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void)
529 DriverIface *iface = ATOMIC_LOAD_SEQ(&CurrentCtxDriver);
530 return iface ? iface->alcGetCurrentContext() : NULL;
533 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context)
535 if(context)
537 ALint idx = LookupPtrIntMapKey(&ContextIfaceMap, context);
538 if(idx >= 0)
539 return DriverList[idx].alcGetContextsDevice(context);
541 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_CONTEXT);
542 return NULL;
546 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
548 if(device)
550 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
551 if(idx < 0) return ALC_INVALID_DEVICE;
552 return DriverList[idx].alcGetError(device);
554 return ATOMIC_EXCHANGE_SEQ(&LastError, ALC_NO_ERROR);
557 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname)
559 const char *ptr;
560 size_t len;
562 if(device)
564 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
565 if(idx < 0)
567 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
568 return ALC_FALSE;
570 return DriverList[idx].alcIsExtensionPresent(device, extname);
573 len = strlen(extname);
574 ptr = alcExtensionList;
575 while(ptr && *ptr)
577 if(strncasecmp(ptr, extname, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len])))
578 return ALC_TRUE;
579 if((ptr=strchr(ptr, ' ')) != NULL)
581 do {
582 ++ptr;
583 } while(isspace(*ptr));
586 return ALC_FALSE;
589 ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname)
591 size_t i;
593 if(device)
595 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
596 if(idx < 0)
598 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
599 return NULL;
601 return DriverList[idx].alcGetProcAddress(device, funcname);
604 for(i = 0;i < COUNTOF(alcFunctions);i++)
606 if(strcmp(funcname, alcFunctions[i].funcName) == 0)
607 return alcFunctions[i].address;
609 return NULL;
612 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname)
614 size_t i;
616 if(device)
618 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
619 if(idx < 0)
621 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
622 return 0;
624 return DriverList[idx].alcGetEnumValue(device, enumname);
627 for(i = 0;i < COUNTOF(alcEnumerations);i++)
629 if(strcmp(enumname, alcEnumerations[i].enumName) == 0)
630 return alcEnumerations[i].value;
632 return 0;
635 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param)
637 ALsizei i = 0;
639 if(device)
641 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
642 if(idx < 0)
644 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
645 return NULL;
647 return DriverList[idx].alcGetString(device, param);
650 switch(param)
652 case ALC_NO_ERROR:
653 return alcNoError;
654 case ALC_INVALID_ENUM:
655 return alcErrInvalidEnum;
656 case ALC_INVALID_VALUE:
657 return alcErrInvalidValue;
658 case ALC_INVALID_DEVICE:
659 return alcErrInvalidDevice;
660 case ALC_INVALID_CONTEXT:
661 return alcErrInvalidContext;
662 case ALC_OUT_OF_MEMORY:
663 return alcErrOutOfMemory;
664 case ALC_EXTENSIONS:
665 return alcExtensionList;
667 case ALC_DEVICE_SPECIFIER:
668 almtx_lock(&EnumerationLock);
669 ClearDeviceList(&DevicesList);
670 for(i = 0;i < DriverListSize;i++)
672 /* Only enumerate names from drivers that support it. */
673 if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
674 DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
675 AppendDeviceList(&DevicesList,
676 DriverList[i].alcGetString(NULL, ALC_DEVICE_SPECIFIER), i
679 almtx_unlock(&EnumerationLock);
680 return DevicesList.Names;
682 case ALC_ALL_DEVICES_SPECIFIER:
683 almtx_lock(&EnumerationLock);
684 ClearDeviceList(&AllDevicesList);
685 for(i = 0;i < DriverListSize;i++)
687 /* If the driver doesn't support ALC_ENUMERATE_ALL_EXT, substitute
688 * standard enumeration.
690 if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
691 AppendDeviceList(&AllDevicesList,
692 DriverList[i].alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER), i
694 else if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
695 DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
696 AppendDeviceList(&AllDevicesList,
697 DriverList[i].alcGetString(NULL, ALC_DEVICE_SPECIFIER), i
700 almtx_unlock(&EnumerationLock);
701 return AllDevicesList.Names;
703 case ALC_CAPTURE_DEVICE_SPECIFIER:
704 almtx_lock(&EnumerationLock);
705 ClearDeviceList(&CaptureDevicesList);
706 for(i = 0;i < DriverListSize;i++)
708 if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
709 DriverList[i].alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE"))
710 AppendDeviceList(&CaptureDevicesList,
711 DriverList[i].alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER), i
714 almtx_unlock(&EnumerationLock);
715 return CaptureDevicesList.Names;
717 case ALC_DEFAULT_DEVICE_SPECIFIER:
718 for(i = 0;i < DriverListSize;i++)
720 if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
721 DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
722 return DriverList[i].alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
724 return "";
726 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
727 for(i = 0;i < DriverListSize;i++)
729 if(DriverList[i].alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT"))
730 return DriverList[i].alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER);
732 return "";
734 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
735 for(i = 0;i < DriverListSize;i++)
737 if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
738 DriverList[i].alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE"))
739 return DriverList[i].alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
741 return "";
743 default:
744 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_ENUM);
745 break;
747 return NULL;
750 ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
752 if(device)
754 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
755 if(idx < 0)
757 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
758 return;
760 return DriverList[idx].alcGetIntegerv(device, param, size, values);
763 if(size <= 0 || values == NULL)
765 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_VALUE);
766 return;
769 switch(param)
771 case ALC_MAJOR_VERSION:
772 if(size >= 1)
774 values[0] = alcMajorVersion;
775 return;
777 /*fall-through*/
778 case ALC_MINOR_VERSION:
779 if(size >= 1)
781 values[0] = alcMinorVersion;
782 return;
784 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_VALUE);
785 return;
787 case ALC_ATTRIBUTES_SIZE:
788 case ALC_ALL_ATTRIBUTES:
789 case ALC_FREQUENCY:
790 case ALC_REFRESH:
791 case ALC_SYNC:
792 case ALC_MONO_SOURCES:
793 case ALC_STEREO_SOURCES:
794 case ALC_CAPTURE_SAMPLES:
795 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
796 return;
798 default:
799 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_ENUM);
800 return;
805 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize)
807 ALCdevice *device = NULL;
808 ALint idx;
810 if(devicename && devicename[0] == '\0')
811 devicename = NULL;
812 if(devicename)
814 almtx_lock(&EnumerationLock);
815 if(!CaptureDevicesList.Names)
816 (void)alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
817 idx = GetDriverIndexForName(&CaptureDevicesList, devicename);
818 almtx_unlock(&EnumerationLock);
819 if(idx >= 0)
820 device = DriverList[idx].alcCaptureOpenDevice(
821 devicename, frequency, format, buffersize
823 else for(idx = 0;idx < DriverListSize;idx++)
825 device = DriverList[idx].alcCaptureOpenDevice(
826 devicename, frequency, format, buffersize
828 if(device) break;
831 else
833 int i;
834 for(i = 0;i < DriverListSize;i++)
836 if(DriverList[i].ALCVer >= MAKE_ALC_VER(1, 1) ||
837 DriverList[i].alcIsExtensionPresent(NULL, "ALC_EXT_CAPTURE"))
839 idx = i;
840 device = DriverList[idx].alcCaptureOpenDevice(
841 NULL, frequency, format, buffersize
843 break;
848 if(device)
850 if(InsertPtrIntMapEntry(&DeviceIfaceMap, device, idx) != ALC_NO_ERROR)
852 DriverList[idx].alcCaptureCloseDevice(device);
853 device = NULL;
857 return device;
860 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
862 ALint idx;
864 if(!device || (idx=LookupPtrIntMapKey(&DeviceIfaceMap, device)) < 0)
866 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
867 return ALC_FALSE;
869 if(!DriverList[idx].alcCaptureCloseDevice(device))
870 return ALC_FALSE;
871 RemovePtrIntMapKey(&DeviceIfaceMap, device);
872 return ALC_TRUE;
875 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
877 if(device)
879 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
880 if(idx >= 0)
881 return DriverList[idx].alcCaptureStart(device);
883 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
886 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
888 if(device)
890 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
891 if(idx >= 0)
892 return DriverList[idx].alcCaptureStop(device);
894 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);
897 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
899 if(device)
901 ALint idx = LookupPtrIntMapKey(&DeviceIfaceMap, device);
902 if(idx >= 0)
903 return DriverList[idx].alcCaptureSamples(device, buffer, samples);
905 ATOMIC_STORE_SEQ(&LastError, ALC_INVALID_DEVICE);