14 #define COUNTOF(x) (sizeof(x)/sizeof(x[0]))
16 #define DECL(x) { #x, (ALCvoid*)(x) }
18 const ALCchar
*funcName
;
21 DECL(alcCreateContext
),
22 DECL(alcMakeContextCurrent
),
23 DECL(alcProcessContext
),
24 DECL(alcSuspendContext
),
25 DECL(alcDestroyContext
),
26 DECL(alcGetCurrentContext
),
27 DECL(alcGetContextsDevice
),
31 DECL(alcIsExtensionPresent
),
32 DECL(alcGetProcAddress
),
33 DECL(alcGetEnumValue
),
36 DECL(alcCaptureOpenDevice
),
37 DECL(alcCaptureCloseDevice
),
38 DECL(alcCaptureStart
),
40 DECL(alcCaptureSamples
),
42 DECL(alcSetThreadContext
),
43 DECL(alcGetThreadContext
),
58 DECL(alIsExtensionPresent
),
59 DECL(alGetProcAddress
),
68 DECL(alGetListener3f
),
69 DECL(alGetListenerfv
),
71 DECL(alGetListener3i
),
72 DECL(alGetListeneriv
),
74 DECL(alDeleteSources
),
90 DECL(alSourceRewindv
),
96 DECL(alSourceQueueBuffers
),
97 DECL(alSourceUnqueueBuffers
),
99 DECL(alDeleteBuffers
),
114 DECL(alDopplerFactor
),
115 DECL(alDopplerVelocity
),
116 DECL(alSpeedOfSound
),
117 DECL(alDistanceModel
),
121 #define DECL(x) { #x, (x) }
122 static const struct {
123 const ALCchar
*enumName
;
125 } alcEnumerations
[] = {
130 DECL(ALC_MAJOR_VERSION
),
131 DECL(ALC_MINOR_VERSION
),
132 DECL(ALC_ATTRIBUTES_SIZE
),
133 DECL(ALC_ALL_ATTRIBUTES
),
134 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
135 DECL(ALC_DEVICE_SPECIFIER
),
136 DECL(ALC_ALL_DEVICES_SPECIFIER
),
137 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
138 DECL(ALC_EXTENSIONS
),
142 DECL(ALC_MONO_SOURCES
),
143 DECL(ALC_STEREO_SOURCES
),
144 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
145 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
146 DECL(ALC_CAPTURE_SAMPLES
),
149 DECL(ALC_INVALID_DEVICE
),
150 DECL(ALC_INVALID_CONTEXT
),
151 DECL(ALC_INVALID_ENUM
),
152 DECL(ALC_INVALID_VALUE
),
153 DECL(ALC_OUT_OF_MEMORY
),
160 DECL(AL_SOURCE_RELATIVE
),
161 DECL(AL_CONE_INNER_ANGLE
),
162 DECL(AL_CONE_OUTER_ANGLE
),
172 DECL(AL_ORIENTATION
),
173 DECL(AL_REFERENCE_DISTANCE
),
174 DECL(AL_ROLLOFF_FACTOR
),
175 DECL(AL_CONE_OUTER_GAIN
),
176 DECL(AL_MAX_DISTANCE
),
178 DECL(AL_SAMPLE_OFFSET
),
179 DECL(AL_BYTE_OFFSET
),
180 DECL(AL_SOURCE_TYPE
),
183 DECL(AL_UNDETERMINED
),
185 DECL(AL_SOURCE_STATE
),
191 DECL(AL_BUFFERS_QUEUED
),
192 DECL(AL_BUFFERS_PROCESSED
),
194 DECL(AL_FORMAT_MONO8
),
195 DECL(AL_FORMAT_MONO16
),
196 DECL(AL_FORMAT_STEREO8
),
197 DECL(AL_FORMAT_STEREO16
),
209 DECL(AL_INVALID_NAME
),
210 DECL(AL_INVALID_ENUM
),
211 DECL(AL_INVALID_VALUE
),
212 DECL(AL_INVALID_OPERATION
),
213 DECL(AL_OUT_OF_MEMORY
),
220 DECL(AL_DOPPLER_FACTOR
),
221 DECL(AL_DOPPLER_VELOCITY
),
222 DECL(AL_DISTANCE_MODEL
),
223 DECL(AL_SPEED_OF_SOUND
),
225 DECL(AL_INVERSE_DISTANCE
),
226 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
227 DECL(AL_LINEAR_DISTANCE
),
228 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
229 DECL(AL_EXPONENT_DISTANCE
),
230 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
234 static const ALCchar alcNoError
[] = "No Error";
235 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
236 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
237 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
238 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
239 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
240 static const ALCchar alcExtensionList
[] =
241 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
242 "ALC_EXT_thread_local_context";
244 static const ALCint alcMajorVersion
= 1;
245 static const ALCint alcMinorVersion
= 1;
248 static almtx_t EnumerationLock
;
249 static almtx_t ContextSwitchLock
;
251 static ATOMIC(ALCenum
) LastError
= ATOMIC_INIT_STATIC(ALC_NO_ERROR
);
252 static PtrIntMap DeviceIfaceMap
= PTRINTMAP_STATIC_INITIALIZE
;
253 static PtrIntMap ContextIfaceMap
= PTRINTMAP_STATIC_INITIALIZE
;
256 typedef struct EnumeratedList
{
262 static EnumeratedList DevicesList
= { NULL
, NULL
, NULL
, 0 };
263 static EnumeratedList AllDevicesList
= { NULL
, NULL
, NULL
, 0 };
264 static EnumeratedList CaptureDevicesList
= { NULL
, NULL
, NULL
, 0 };
266 static void ClearDeviceList(EnumeratedList
*list
)
268 al_free(list
->Names
);
270 list
->NamesEnd
= NULL
;
272 al_free(list
->Indicies
);
273 list
->Indicies
= NULL
;
277 static void AppendDeviceList(EnumeratedList
*list
, const ALCchar
*names
, ALint idx
)
279 const ALCchar
*name_end
= names
;
282 ALCint
*new_indicies
;
290 TRACE("Enumerated \"%s\", driver %d\n", name_end
, idx
);
292 name_end
+= strlen(name_end
)+1;
294 if(names
== name_end
)
297 len
= (list
->NamesEnd
- list
->Names
) + (name_end
- names
);
298 new_list
= al_calloc(DEF_ALIGN
, len
+ 1);
299 memcpy(new_list
, list
->Names
, list
->NamesEnd
- list
->Names
);
300 memcpy(new_list
+ (list
->NamesEnd
- list
->Names
), names
, name_end
- names
);
301 al_free(list
->Names
);
302 list
->Names
= new_list
;
303 list
->NamesEnd
= list
->Names
+ len
;
305 new_indicies
= al_calloc(16, sizeof(ALCint
)*(list
->IndexSize
+ count
));
306 for(i
= 0;i
< list
->IndexSize
;i
++)
307 new_indicies
[i
] = list
->Indicies
[i
];
308 for(i
= 0;i
< count
;i
++)
309 new_indicies
[list
->IndexSize
+i
] = idx
;
310 al_free(list
->Indicies
);
311 list
->Indicies
= new_indicies
;
312 list
->IndexSize
+= count
;
315 static ALint
GetDriverIndexForName(const EnumeratedList
*list
, const ALCchar
*name
)
317 const ALCchar
*devnames
= list
->Names
;
318 const ALCint
*index
= list
->Indicies
;
320 while(devnames
&& *devnames
)
322 if(strcmp(name
, devnames
) == 0)
324 devnames
+= strlen(devnames
)+1;
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
;
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
359 if(devicename
&& (devicename
[0] == '\0' ||
360 strcmp(devicename
, "DirectSound3D") == 0 ||
361 strcmp(devicename
, "DirectSound") == 0 ||
362 strcmp(devicename
, "MMSYSTEM") == 0))
366 almtx_lock(&EnumerationLock
);
367 if(!DevicesList
.Names
)
368 (void)alcGetString(NULL
, ALC_DEVICE_SPECIFIER
);
369 idx
= GetDriverIndexForName(&DevicesList
, devicename
);
372 if(!AllDevicesList
.Names
)
373 (void)alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
);
374 idx
= GetDriverIndexForName(&AllDevicesList
, devicename
);
376 almtx_unlock(&EnumerationLock
);
379 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_VALUE
);
380 TRACE("Failed to find driver for name \"%s\"\n", devicename
);
383 TRACE("Found driver %d for name \"%s\"\n", idx
, devicename
);
384 device
= DriverList
[idx
].alcOpenDevice(devicename
);
389 for(i
= 0;i
< DriverListSize
;i
++)
391 if(DriverList
[i
].ALCVer
>= MAKE_ALC_VER(1, 1) ||
392 DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATION_EXT"))
395 TRACE("Using default device from driver %d\n", idx
);
396 device
= DriverList
[idx
].alcOpenDevice(NULL
);
404 if(InsertPtrIntMapEntry(&DeviceIfaceMap
, device
, idx
) != ALC_NO_ERROR
)
406 DriverList
[idx
].alcCloseDevice(device
);
414 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
418 if(!device
|| (idx
=LookupPtrIntMapKey(&DeviceIfaceMap
, device
)) < 0)
420 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
423 if(!DriverList
[idx
].alcCloseDevice(device
))
425 RemovePtrIntMapKey(&DeviceIfaceMap
, device
);
430 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrlist
)
435 if(!device
|| (idx
=LookupPtrIntMapKey(&DeviceIfaceMap
, device
)) < 0)
437 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
440 context
= DriverList
[idx
].alcCreateContext(device
, attrlist
);
443 if(InsertPtrIntMapEntry(&ContextIfaceMap
, context
, idx
) != ALC_NO_ERROR
)
445 DriverList
[idx
].alcDestroyContext(context
);
453 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
457 almtx_lock(&ContextSwitchLock
);
460 idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
463 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
464 almtx_unlock(&ContextSwitchLock
);
467 if(!DriverList
[idx
].alcMakeContextCurrent(context
))
469 almtx_unlock(&ContextSwitchLock
);
474 /* Unset the context from the old driver if it's different from the new
479 DriverIface
*oldiface
= altss_get(ThreadCtxDriver
);
480 if(oldiface
) oldiface
->alcSetThreadContext(NULL
);
481 oldiface
= ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver
, NULL
);
482 if(oldiface
) oldiface
->alcMakeContextCurrent(NULL
);
486 DriverIface
*oldiface
= altss_get(ThreadCtxDriver
);
487 if(oldiface
&& oldiface
!= &DriverList
[idx
])
488 oldiface
->alcSetThreadContext(NULL
);
489 oldiface
= ATOMIC_EXCHANGE_PTR_SEQ(&CurrentCtxDriver
, &DriverList
[idx
]);
490 if(oldiface
&& oldiface
!= &DriverList
[idx
])
491 oldiface
->alcMakeContextCurrent(NULL
);
493 almtx_unlock(&ContextSwitchLock
);
494 altss_set(ThreadCtxDriver
, NULL
);
499 ALC_API
void ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
503 ALint idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
505 return DriverList
[idx
].alcProcessContext(context
);
507 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
510 ALC_API
void ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
514 ALint idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
516 return DriverList
[idx
].alcSuspendContext(context
);
518 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
521 ALC_API
void ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
525 if(!context
|| (idx
=LookupPtrIntMapKey(&ContextIfaceMap
, context
)) < 0)
527 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
531 DriverList
[idx
].alcDestroyContext(context
);
532 RemovePtrIntMapKey(&ContextIfaceMap
, context
);
535 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
537 DriverIface
*iface
= altss_get(ThreadCtxDriver
);
538 if(!iface
) iface
= ATOMIC_LOAD_SEQ(&CurrentCtxDriver
);
539 return iface
? iface
->alcGetCurrentContext() : NULL
;
542 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*context
)
546 ALint idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
548 return DriverList
[idx
].alcGetContextsDevice(context
);
550 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_CONTEXT
);
555 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
559 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
560 if(idx
< 0) return ALC_INVALID_DEVICE
;
561 return DriverList
[idx
].alcGetError(device
);
563 return ATOMIC_EXCHANGE_SEQ(&LastError
, ALC_NO_ERROR
);
566 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extname
)
573 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
576 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
579 return DriverList
[idx
].alcIsExtensionPresent(device
, extname
);
582 len
= strlen(extname
);
583 ptr
= alcExtensionList
;
586 if(strncasecmp(ptr
, extname
, len
) == 0 && (ptr
[len
] == '\0' || isspace(ptr
[len
])))
588 if((ptr
=strchr(ptr
, ' ')) != NULL
)
592 } while(isspace(*ptr
));
598 ALC_API
void* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcname
)
604 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
607 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
610 return DriverList
[idx
].alcGetProcAddress(device
, funcname
);
613 for(i
= 0;i
< COUNTOF(alcFunctions
);i
++)
615 if(strcmp(funcname
, alcFunctions
[i
].funcName
) == 0)
616 return alcFunctions
[i
].address
;
621 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumname
)
627 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
630 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
633 return DriverList
[idx
].alcGetEnumValue(device
, enumname
);
636 for(i
= 0;i
< COUNTOF(alcEnumerations
);i
++)
638 if(strcmp(enumname
, alcEnumerations
[i
].enumName
) == 0)
639 return alcEnumerations
[i
].value
;
644 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*device
, ALCenum param
)
650 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
653 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
656 return DriverList
[idx
].alcGetString(device
, param
);
663 case ALC_INVALID_ENUM
:
664 return alcErrInvalidEnum
;
665 case ALC_INVALID_VALUE
:
666 return alcErrInvalidValue
;
667 case ALC_INVALID_DEVICE
:
668 return alcErrInvalidDevice
;
669 case ALC_INVALID_CONTEXT
:
670 return alcErrInvalidContext
;
671 case ALC_OUT_OF_MEMORY
:
672 return alcErrOutOfMemory
;
674 return alcExtensionList
;
676 case ALC_DEVICE_SPECIFIER
:
677 almtx_lock(&EnumerationLock
);
678 ClearDeviceList(&DevicesList
);
679 for(i
= 0;i
< DriverListSize
;i
++)
681 /* Only enumerate names from drivers that support it. */
682 if(DriverList
[i
].ALCVer
>= MAKE_ALC_VER(1, 1) ||
683 DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATION_EXT"))
684 AppendDeviceList(&DevicesList
,
685 DriverList
[i
].alcGetString(NULL
, ALC_DEVICE_SPECIFIER
), i
688 almtx_unlock(&EnumerationLock
);
689 return DevicesList
.Names
;
691 case ALC_ALL_DEVICES_SPECIFIER
:
692 almtx_lock(&EnumerationLock
);
693 ClearDeviceList(&AllDevicesList
);
694 for(i
= 0;i
< DriverListSize
;i
++)
696 /* If the driver doesn't support ALC_ENUMERATE_ALL_EXT, substitute
697 * standard enumeration.
699 if(DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT"))
700 AppendDeviceList(&AllDevicesList
,
701 DriverList
[i
].alcGetString(NULL
, ALC_ALL_DEVICES_SPECIFIER
), i
703 else if(DriverList
[i
].ALCVer
>= MAKE_ALC_VER(1, 1) ||
704 DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATION_EXT"))
705 AppendDeviceList(&AllDevicesList
,
706 DriverList
[i
].alcGetString(NULL
, ALC_DEVICE_SPECIFIER
), i
709 almtx_unlock(&EnumerationLock
);
710 return AllDevicesList
.Names
;
712 case ALC_CAPTURE_DEVICE_SPECIFIER
:
713 almtx_lock(&EnumerationLock
);
714 ClearDeviceList(&CaptureDevicesList
);
715 for(i
= 0;i
< DriverListSize
;i
++)
717 if(DriverList
[i
].ALCVer
>= MAKE_ALC_VER(1, 1) ||
718 DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_EXT_CAPTURE"))
719 AppendDeviceList(&CaptureDevicesList
,
720 DriverList
[i
].alcGetString(NULL
, ALC_CAPTURE_DEVICE_SPECIFIER
), i
723 almtx_unlock(&EnumerationLock
);
724 return CaptureDevicesList
.Names
;
726 case ALC_DEFAULT_DEVICE_SPECIFIER
:
727 for(i
= 0;i
< DriverListSize
;i
++)
729 if(DriverList
[i
].ALCVer
>= MAKE_ALC_VER(1, 1) ||
730 DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATION_EXT"))
731 return DriverList
[i
].alcGetString(NULL
, ALC_DEFAULT_DEVICE_SPECIFIER
);
735 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
736 for(i
= 0;i
< DriverListSize
;i
++)
738 if(DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_ENUMERATE_ALL_EXT"))
739 return DriverList
[i
].alcGetString(NULL
, ALC_DEFAULT_ALL_DEVICES_SPECIFIER
);
743 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
744 for(i
= 0;i
< DriverListSize
;i
++)
746 if(DriverList
[i
].ALCVer
>= MAKE_ALC_VER(1, 1) ||
747 DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_EXT_CAPTURE"))
748 return DriverList
[i
].alcGetString(NULL
, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
);
753 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_ENUM
);
759 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
763 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
766 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
769 return DriverList
[idx
].alcGetIntegerv(device
, param
, size
, values
);
772 if(size
<= 0 || values
== NULL
)
774 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_VALUE
);
780 case ALC_MAJOR_VERSION
:
783 values
[0] = alcMajorVersion
;
787 case ALC_MINOR_VERSION
:
790 values
[0] = alcMinorVersion
;
793 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_VALUE
);
796 case ALC_ATTRIBUTES_SIZE
:
797 case ALC_ALL_ATTRIBUTES
:
801 case ALC_MONO_SOURCES
:
802 case ALC_STEREO_SOURCES
:
803 case ALC_CAPTURE_SAMPLES
:
804 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
808 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_ENUM
);
814 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*devicename
, ALCuint frequency
, ALCenum format
, ALCsizei buffersize
)
816 ALCdevice
*device
= NULL
;
819 if(devicename
&& devicename
[0] == '\0')
823 almtx_lock(&EnumerationLock
);
824 if(!CaptureDevicesList
.Names
)
825 (void)alcGetString(NULL
, ALC_CAPTURE_DEVICE_SPECIFIER
);
826 idx
= GetDriverIndexForName(&CaptureDevicesList
, devicename
);
827 almtx_unlock(&EnumerationLock
);
830 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_VALUE
);
831 TRACE("Failed to find driver for name \"%s\"\n", devicename
);
834 TRACE("Found driver %d for name \"%s\"\n", idx
, devicename
);
835 device
= DriverList
[idx
].alcCaptureOpenDevice(
836 devicename
, frequency
, format
, buffersize
842 for(i
= 0;i
< DriverListSize
;i
++)
844 if(DriverList
[i
].ALCVer
>= MAKE_ALC_VER(1, 1) ||
845 DriverList
[i
].alcIsExtensionPresent(NULL
, "ALC_EXT_CAPTURE"))
848 TRACE("Using default capture device from driver %d\n", idx
);
849 device
= DriverList
[idx
].alcCaptureOpenDevice(
850 NULL
, frequency
, format
, buffersize
859 if(InsertPtrIntMapEntry(&DeviceIfaceMap
, device
, idx
) != ALC_NO_ERROR
)
861 DriverList
[idx
].alcCaptureCloseDevice(device
);
869 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
873 if(!device
|| (idx
=LookupPtrIntMapKey(&DeviceIfaceMap
, device
)) < 0)
875 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
878 if(!DriverList
[idx
].alcCaptureCloseDevice(device
))
880 RemovePtrIntMapKey(&DeviceIfaceMap
, device
);
884 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
888 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
890 return DriverList
[idx
].alcCaptureStart(device
);
892 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
895 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
899 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
901 return DriverList
[idx
].alcCaptureStop(device
);
903 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
906 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
910 ALint idx
= LookupPtrIntMapKey(&DeviceIfaceMap
, device
);
912 return DriverList
[idx
].alcCaptureSamples(device
, buffer
, samples
);
914 ATOMIC_STORE_SEQ(&LastError
, ALC_INVALID_DEVICE
);
918 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
920 ALCenum err
= ALC_INVALID_CONTEXT
;
925 DriverIface
*oldiface
= altss_get(ThreadCtxDriver
);
926 if(oldiface
&& !oldiface
->alcSetThreadContext(NULL
))
928 altss_set(ThreadCtxDriver
, NULL
);
932 idx
= LookupPtrIntMapKey(&ContextIfaceMap
, context
);
935 if(DriverList
[idx
].alcSetThreadContext(context
))
937 DriverIface
*oldiface
= altss_get(ThreadCtxDriver
);
938 if(oldiface
!= &DriverList
[idx
])
940 altss_set(ThreadCtxDriver
, &DriverList
[idx
]);
941 if(oldiface
) oldiface
->alcSetThreadContext(NULL
);
945 err
= DriverList
[idx
].alcGetError(NULL
);
947 ATOMIC_STORE_SEQ(&LastError
, err
);
951 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
953 DriverIface
*iface
= altss_get(ThreadCtxDriver
);
954 if(iface
) return iface
->alcGetThreadContext();