18 #define DECL(x) { #x, reinterpret_cast<void*>(x) }
19 struct FuncExportEntry
{
20 const ALCchar
*funcName
;
23 static const std::array
<FuncExportEntry
,95> alcFunctions
{{
24 DECL(alcCreateContext
),
25 DECL(alcMakeContextCurrent
),
26 DECL(alcProcessContext
),
27 DECL(alcSuspendContext
),
28 DECL(alcDestroyContext
),
29 DECL(alcGetCurrentContext
),
30 DECL(alcGetContextsDevice
),
34 DECL(alcIsExtensionPresent
),
35 DECL(alcGetProcAddress
),
36 DECL(alcGetEnumValue
),
39 DECL(alcCaptureOpenDevice
),
40 DECL(alcCaptureCloseDevice
),
41 DECL(alcCaptureStart
),
43 DECL(alcCaptureSamples
),
45 DECL(alcSetThreadContext
),
46 DECL(alcGetThreadContext
),
61 DECL(alIsExtensionPresent
),
62 DECL(alGetProcAddress
),
71 DECL(alGetListener3f
),
72 DECL(alGetListenerfv
),
74 DECL(alGetListener3i
),
75 DECL(alGetListeneriv
),
77 DECL(alDeleteSources
),
93 DECL(alSourceRewindv
),
99 DECL(alSourceQueueBuffers
),
100 DECL(alSourceUnqueueBuffers
),
102 DECL(alDeleteBuffers
),
117 DECL(alDopplerFactor
),
118 DECL(alDopplerVelocity
),
119 DECL(alSpeedOfSound
),
120 DECL(alDistanceModel
),
124 #define DECL(x) { #x, (x) }
125 struct EnumExportEntry
{
126 const ALCchar
*enumName
;
129 static const std::array
<EnumExportEntry
,92> alcEnumerations
{{
134 DECL(ALC_MAJOR_VERSION
),
135 DECL(ALC_MINOR_VERSION
),
136 DECL(ALC_ATTRIBUTES_SIZE
),
137 DECL(ALC_ALL_ATTRIBUTES
),
138 DECL(ALC_DEFAULT_DEVICE_SPECIFIER
),
139 DECL(ALC_DEVICE_SPECIFIER
),
140 DECL(ALC_ALL_DEVICES_SPECIFIER
),
141 DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER
),
142 DECL(ALC_EXTENSIONS
),
146 DECL(ALC_MONO_SOURCES
),
147 DECL(ALC_STEREO_SOURCES
),
148 DECL(ALC_CAPTURE_DEVICE_SPECIFIER
),
149 DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
),
150 DECL(ALC_CAPTURE_SAMPLES
),
153 DECL(ALC_INVALID_DEVICE
),
154 DECL(ALC_INVALID_CONTEXT
),
155 DECL(ALC_INVALID_ENUM
),
156 DECL(ALC_INVALID_VALUE
),
157 DECL(ALC_OUT_OF_MEMORY
),
164 DECL(AL_SOURCE_RELATIVE
),
165 DECL(AL_CONE_INNER_ANGLE
),
166 DECL(AL_CONE_OUTER_ANGLE
),
176 DECL(AL_ORIENTATION
),
177 DECL(AL_REFERENCE_DISTANCE
),
178 DECL(AL_ROLLOFF_FACTOR
),
179 DECL(AL_CONE_OUTER_GAIN
),
180 DECL(AL_MAX_DISTANCE
),
182 DECL(AL_SAMPLE_OFFSET
),
183 DECL(AL_BYTE_OFFSET
),
184 DECL(AL_SOURCE_TYPE
),
187 DECL(AL_UNDETERMINED
),
189 DECL(AL_SOURCE_STATE
),
195 DECL(AL_BUFFERS_QUEUED
),
196 DECL(AL_BUFFERS_PROCESSED
),
198 DECL(AL_FORMAT_MONO8
),
199 DECL(AL_FORMAT_MONO16
),
200 DECL(AL_FORMAT_STEREO8
),
201 DECL(AL_FORMAT_STEREO16
),
213 DECL(AL_INVALID_NAME
),
214 DECL(AL_INVALID_ENUM
),
215 DECL(AL_INVALID_VALUE
),
216 DECL(AL_INVALID_OPERATION
),
217 DECL(AL_OUT_OF_MEMORY
),
224 DECL(AL_DOPPLER_FACTOR
),
225 DECL(AL_DOPPLER_VELOCITY
),
226 DECL(AL_DISTANCE_MODEL
),
227 DECL(AL_SPEED_OF_SOUND
),
229 DECL(AL_INVERSE_DISTANCE
),
230 DECL(AL_INVERSE_DISTANCE_CLAMPED
),
231 DECL(AL_LINEAR_DISTANCE
),
232 DECL(AL_LINEAR_DISTANCE_CLAMPED
),
233 DECL(AL_EXPONENT_DISTANCE
),
234 DECL(AL_EXPONENT_DISTANCE_CLAMPED
),
238 static const ALCchar alcNoError
[] = "No Error";
239 static const ALCchar alcErrInvalidDevice
[] = "Invalid Device";
240 static const ALCchar alcErrInvalidContext
[] = "Invalid Context";
241 static const ALCchar alcErrInvalidEnum
[] = "Invalid Enum";
242 static const ALCchar alcErrInvalidValue
[] = "Invalid Value";
243 static const ALCchar alcErrOutOfMemory
[] = "Out of Memory";
244 static const ALCchar alcExtensionList
[] =
245 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE "
246 "ALC_EXT_thread_local_context";
248 static const ALCint alcMajorVersion
= 1;
249 static const ALCint alcMinorVersion
= 1;
252 static std::mutex EnumerationLock
;
253 static std::mutex ContextSwitchLock
;
255 static std::atomic
<ALCenum
> LastError
{ALC_NO_ERROR
};
256 static PtrIntMap DeviceIfaceMap
;
257 static PtrIntMap ContextIfaceMap
;
260 typedef struct EnumeratedList
{
261 std::vector
<ALCchar
> Names
;
262 std::vector
<ALCint
> Indicies
;
270 static EnumeratedList DevicesList
;
271 static EnumeratedList AllDevicesList
;
272 static EnumeratedList CaptureDevicesList
;
274 static void AppendDeviceList(EnumeratedList
*list
, const ALCchar
*names
, ALint idx
)
276 const ALCchar
*name_end
= names
;
277 if(!name_end
) return;
282 TRACE("Enumerated \"%s\", driver %d\n", name_end
, idx
);
284 name_end
+= strlen(name_end
)+1;
286 if(names
== name_end
)
289 list
->Names
.reserve(list
->Names
.size() + (name_end
- names
) + 1);
290 list
->Names
.insert(list
->Names
.cend(), names
, name_end
);
292 list
->Indicies
.reserve(list
->Indicies
.size() + count
);
293 list
->Indicies
.insert(list
->Indicies
.cend(), count
, idx
);
296 static ALint
GetDriverIndexForName(const EnumeratedList
*list
, const ALCchar
*name
)
298 const ALCchar
*devnames
= list
->Names
.data();
299 const ALCint
*index
= list
->Indicies
.data();
301 while(devnames
&& *devnames
)
303 if(strcmp(name
, devnames
) == 0)
305 devnames
+= strlen(devnames
)+1;
312 ALC_API ALCdevice
* ALC_APIENTRY
alcOpenDevice(const ALCchar
*devicename
)
314 ALCdevice
*device
= nullptr;
317 /* Prior to the enumeration extension, apps would hardcode these names as a
318 * quality hint for the wrapper driver. Ignore them since there's no sane
321 if(devicename
&& (devicename
[0] == '\0' ||
322 strcmp(devicename
, "DirectSound3D") == 0 ||
323 strcmp(devicename
, "DirectSound") == 0 ||
324 strcmp(devicename
, "MMSYSTEM") == 0))
325 devicename
= nullptr;
328 { std::lock_guard
<std::mutex
> _
{EnumerationLock
};
329 if(DevicesList
.Names
.empty())
330 (void)alcGetString(nullptr, ALC_DEVICE_SPECIFIER
);
331 idx
= GetDriverIndexForName(&DevicesList
, devicename
);
334 if(AllDevicesList
.Names
.empty())
335 (void)alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER
);
336 idx
= GetDriverIndexForName(&AllDevicesList
, devicename
);
342 LastError
.store(ALC_INVALID_VALUE
);
343 TRACE("Failed to find driver for name \"%s\"\n", devicename
);
346 TRACE("Found driver %d for name \"%s\"\n", idx
, devicename
);
347 device
= DriverList
[idx
].alcOpenDevice(devicename
);
351 for(const auto &drv
: DriverList
)
353 if(drv
.ALCVer
>= MAKE_ALC_VER(1, 1) ||
354 drv
.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
356 TRACE("Using default device from driver %d\n", idx
);
357 device
= drv
.alcOpenDevice(nullptr);
366 if(DeviceIfaceMap
.insert(device
, idx
) != ALC_NO_ERROR
)
368 DriverList
[idx
].alcCloseDevice(device
);
376 ALC_API ALCboolean ALC_APIENTRY
alcCloseDevice(ALCdevice
*device
)
380 if(!device
|| (idx
=DeviceIfaceMap
.lookupByKey(device
)) < 0)
382 LastError
.store(ALC_INVALID_DEVICE
);
385 if(!DriverList
[idx
].alcCloseDevice(device
))
387 DeviceIfaceMap
.removeByKey(device
);
392 ALC_API ALCcontext
* ALC_APIENTRY
alcCreateContext(ALCdevice
*device
, const ALCint
*attrlist
)
397 if(!device
|| (idx
=DeviceIfaceMap
.lookupByKey(device
)) < 0)
399 LastError
.store(ALC_INVALID_DEVICE
);
402 context
= DriverList
[idx
].alcCreateContext(device
, attrlist
);
405 if(ContextIfaceMap
.insert(context
, idx
) != ALC_NO_ERROR
)
407 DriverList
[idx
].alcDestroyContext(context
);
415 ALC_API ALCboolean ALC_APIENTRY
alcMakeContextCurrent(ALCcontext
*context
)
419 std::lock_guard
<std::mutex
> _
{ContextSwitchLock
};
422 idx
= ContextIfaceMap
.lookupByKey(context
);
425 LastError
.store(ALC_INVALID_CONTEXT
);
428 if(!DriverList
[idx
].alcMakeContextCurrent(context
))
432 /* Unset the context from the old driver if it's different from the new
437 DriverIface
*oldiface
= ThreadCtxDriver
;
438 if(oldiface
) oldiface
->alcSetThreadContext(nullptr);
439 oldiface
= CurrentCtxDriver
.exchange(nullptr);
440 if(oldiface
) oldiface
->alcMakeContextCurrent(nullptr);
444 DriverIface
*oldiface
= ThreadCtxDriver
;
445 if(oldiface
&& oldiface
!= &DriverList
[idx
])
446 oldiface
->alcSetThreadContext(nullptr);
447 oldiface
= CurrentCtxDriver
.exchange(&DriverList
[idx
]);
448 if(oldiface
&& oldiface
!= &DriverList
[idx
])
449 oldiface
->alcMakeContextCurrent(nullptr);
451 ThreadCtxDriver
= nullptr;
456 ALC_API
void ALC_APIENTRY
alcProcessContext(ALCcontext
*context
)
460 ALint idx
= ContextIfaceMap
.lookupByKey(context
);
462 return DriverList
[idx
].alcProcessContext(context
);
464 LastError
.store(ALC_INVALID_CONTEXT
);
467 ALC_API
void ALC_APIENTRY
alcSuspendContext(ALCcontext
*context
)
471 ALint idx
= ContextIfaceMap
.lookupByKey(context
);
473 return DriverList
[idx
].alcSuspendContext(context
);
475 LastError
.store(ALC_INVALID_CONTEXT
);
478 ALC_API
void ALC_APIENTRY
alcDestroyContext(ALCcontext
*context
)
482 if(!context
|| (idx
=ContextIfaceMap
.lookupByKey(context
)) < 0)
484 LastError
.store(ALC_INVALID_CONTEXT
);
488 DriverList
[idx
].alcDestroyContext(context
);
489 ContextIfaceMap
.removeByKey(context
);
492 ALC_API ALCcontext
* ALC_APIENTRY
alcGetCurrentContext(void)
494 DriverIface
*iface
= ThreadCtxDriver
;
495 if(!iface
) iface
= CurrentCtxDriver
.load();
496 return iface
? iface
->alcGetCurrentContext() : nullptr;
499 ALC_API ALCdevice
* ALC_APIENTRY
alcGetContextsDevice(ALCcontext
*context
)
503 ALint idx
= ContextIfaceMap
.lookupByKey(context
);
505 return DriverList
[idx
].alcGetContextsDevice(context
);
507 LastError
.store(ALC_INVALID_CONTEXT
);
512 ALC_API ALCenum ALC_APIENTRY
alcGetError(ALCdevice
*device
)
516 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
517 if(idx
< 0) return ALC_INVALID_DEVICE
;
518 return DriverList
[idx
].alcGetError(device
);
520 return LastError
.exchange(ALC_NO_ERROR
);
523 ALC_API ALCboolean ALC_APIENTRY
alcIsExtensionPresent(ALCdevice
*device
, const ALCchar
*extname
)
530 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
533 LastError
.store(ALC_INVALID_DEVICE
);
536 return DriverList
[idx
].alcIsExtensionPresent(device
, extname
);
539 len
= strlen(extname
);
540 ptr
= alcExtensionList
;
543 if(al::strncasecmp(ptr
, extname
, len
) == 0 && (ptr
[len
] == '\0' || isspace(ptr
[len
])))
545 if((ptr
=strchr(ptr
, ' ')) != nullptr)
549 } while(isspace(*ptr
));
555 ALC_API
void* ALC_APIENTRY
alcGetProcAddress(ALCdevice
*device
, const ALCchar
*funcname
)
559 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
562 LastError
.store(ALC_INVALID_DEVICE
);
565 return DriverList
[idx
].alcGetProcAddress(device
, funcname
);
568 auto iter
= std::find_if(alcFunctions
.cbegin(), alcFunctions
.cend(),
569 [funcname
](const FuncExportEntry
&entry
) -> bool
570 { return strcmp(funcname
, entry
.funcName
) == 0; }
572 return (iter
!= alcFunctions
.cend()) ? iter
->address
: nullptr;
575 ALC_API ALCenum ALC_APIENTRY
alcGetEnumValue(ALCdevice
*device
, const ALCchar
*enumname
)
579 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
582 LastError
.store(ALC_INVALID_DEVICE
);
585 return DriverList
[idx
].alcGetEnumValue(device
, enumname
);
588 auto iter
= std::find_if(alcEnumerations
.cbegin(), alcEnumerations
.cend(),
589 [enumname
](const EnumExportEntry
&entry
) -> bool
590 { return strcmp(enumname
, entry
.enumName
) == 0; }
592 return (iter
!= alcEnumerations
.cend()) ? iter
->value
: 0;
595 ALC_API
const ALCchar
* ALC_APIENTRY
alcGetString(ALCdevice
*device
, ALCenum param
)
599 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
602 LastError
.store(ALC_INVALID_DEVICE
);
605 return DriverList
[idx
].alcGetString(device
, param
);
612 case ALC_INVALID_ENUM
:
613 return alcErrInvalidEnum
;
614 case ALC_INVALID_VALUE
:
615 return alcErrInvalidValue
;
616 case ALC_INVALID_DEVICE
:
617 return alcErrInvalidDevice
;
618 case ALC_INVALID_CONTEXT
:
619 return alcErrInvalidContext
;
620 case ALC_OUT_OF_MEMORY
:
621 return alcErrOutOfMemory
;
623 return alcExtensionList
;
625 case ALC_DEVICE_SPECIFIER
:
626 { std::lock_guard
<std::mutex
> _
{EnumerationLock
};
629 for(const auto &drv
: DriverList
)
631 /* Only enumerate names from drivers that support it. */
632 if(drv
.ALCVer
>= MAKE_ALC_VER(1, 1) ||
633 drv
.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
634 AppendDeviceList(&DevicesList
,
635 drv
.alcGetString(nullptr, ALC_DEVICE_SPECIFIER
), idx
639 /* Ensure the list is double-null termianted. */
640 if(DevicesList
.Names
.empty())
641 DevicesList
.Names
.emplace_back('\0');
642 DevicesList
.Names
.emplace_back('\0');
643 return DevicesList
.Names
.data();
646 case ALC_ALL_DEVICES_SPECIFIER
:
647 { std::lock_guard
<std::mutex
> _
{EnumerationLock
};
648 AllDevicesList
.clear();
650 for(const auto &drv
: DriverList
)
652 /* If the driver doesn't support ALC_ENUMERATE_ALL_EXT, substitute
653 * standard enumeration.
655 if(drv
.alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"))
656 AppendDeviceList(&AllDevicesList
,
657 drv
.alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER
), idx
659 else if(drv
.ALCVer
>= MAKE_ALC_VER(1, 1) ||
660 drv
.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT"))
661 AppendDeviceList(&AllDevicesList
,
662 drv
.alcGetString(nullptr, ALC_DEVICE_SPECIFIER
), idx
666 /* Ensure the list is double-null termianted. */
667 if(AllDevicesList
.Names
.empty())
668 AllDevicesList
.Names
.emplace_back('\0');
669 AllDevicesList
.Names
.emplace_back('\0');
670 return AllDevicesList
.Names
.data();
673 case ALC_CAPTURE_DEVICE_SPECIFIER
:
674 { std::lock_guard
<std::mutex
> _
{EnumerationLock
};
675 CaptureDevicesList
.clear();
677 for(const auto &drv
: DriverList
)
679 if(drv
.ALCVer
>= MAKE_ALC_VER(1, 1) ||
680 drv
.alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"))
681 AppendDeviceList(&CaptureDevicesList
,
682 drv
.alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER
), idx
686 /* Ensure the list is double-null termianted. */
687 if(CaptureDevicesList
.Names
.empty())
688 CaptureDevicesList
.Names
.emplace_back('\0');
689 CaptureDevicesList
.Names
.emplace_back('\0');
690 return CaptureDevicesList
.Names
.data();
693 case ALC_DEFAULT_DEVICE_SPECIFIER
:
695 auto iter
= std::find_if(DriverList
.cbegin(), DriverList
.cend(),
696 [](const DriverIface
&drv
) -> bool
698 return drv
.ALCVer
>= MAKE_ALC_VER(1, 1) ||
699 drv
.alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT");
702 if(iter
!= DriverList
.cend())
703 return iter
->alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER
);
707 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER
:
709 auto iter
= std::find_if(DriverList
.cbegin(), DriverList
.cend(),
710 [](const DriverIface
&drv
) -> bool
711 { return drv
.alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT") != ALC_FALSE
; }
713 if(iter
!= DriverList
.cend())
714 return iter
->alcGetString(nullptr, ALC_DEFAULT_ALL_DEVICES_SPECIFIER
);
718 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
:
720 auto iter
= std::find_if(DriverList
.cbegin(), DriverList
.cend(),
721 [](const DriverIface
&drv
) -> bool
723 return drv
.ALCVer
>= MAKE_ALC_VER(1, 1) ||
724 drv
.alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE");
727 if(iter
!= DriverList
.cend())
728 return iter
->alcGetString(nullptr, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER
);
733 LastError
.store(ALC_INVALID_ENUM
);
739 ALC_API
void ALC_APIENTRY
alcGetIntegerv(ALCdevice
*device
, ALCenum param
, ALCsizei size
, ALCint
*values
)
743 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
746 LastError
.store(ALC_INVALID_DEVICE
);
749 return DriverList
[idx
].alcGetIntegerv(device
, param
, size
, values
);
752 if(size
<= 0 || values
== nullptr)
754 LastError
.store(ALC_INVALID_VALUE
);
760 case ALC_MAJOR_VERSION
:
763 values
[0] = alcMajorVersion
;
767 case ALC_MINOR_VERSION
:
770 values
[0] = alcMinorVersion
;
773 LastError
.store(ALC_INVALID_VALUE
);
776 case ALC_ATTRIBUTES_SIZE
:
777 case ALC_ALL_ATTRIBUTES
:
781 case ALC_MONO_SOURCES
:
782 case ALC_STEREO_SOURCES
:
783 case ALC_CAPTURE_SAMPLES
:
784 LastError
.store(ALC_INVALID_DEVICE
);
788 LastError
.store(ALC_INVALID_ENUM
);
794 ALC_API ALCdevice
* ALC_APIENTRY
alcCaptureOpenDevice(const ALCchar
*devicename
, ALCuint frequency
, ALCenum format
, ALCsizei buffersize
)
796 ALCdevice
*device
= nullptr;
799 if(devicename
&& devicename
[0] == '\0')
800 devicename
= nullptr;
803 { std::lock_guard
<std::mutex
> _
{EnumerationLock
};
804 if(CaptureDevicesList
.Names
.empty())
805 (void)alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER
);
806 idx
= GetDriverIndexForName(&CaptureDevicesList
, devicename
);
811 LastError
.store(ALC_INVALID_VALUE
);
812 TRACE("Failed to find driver for name \"%s\"\n", devicename
);
815 TRACE("Found driver %d for name \"%s\"\n", idx
, devicename
);
816 device
= DriverList
[idx
].alcCaptureOpenDevice(
817 devicename
, frequency
, format
, buffersize
822 for(const auto &drv
: DriverList
)
824 if(drv
.ALCVer
>= MAKE_ALC_VER(1, 1) ||
825 drv
.alcIsExtensionPresent(nullptr, "ALC_EXT_CAPTURE"))
827 TRACE("Using default capture device from driver %d\n", idx
);
828 device
= drv
.alcCaptureOpenDevice(
829 nullptr, frequency
, format
, buffersize
839 if(DeviceIfaceMap
.insert(device
, idx
) != ALC_NO_ERROR
)
841 DriverList
[idx
].alcCaptureCloseDevice(device
);
849 ALC_API ALCboolean ALC_APIENTRY
alcCaptureCloseDevice(ALCdevice
*device
)
853 if(!device
|| (idx
=DeviceIfaceMap
.lookupByKey(device
)) < 0)
855 LastError
.store(ALC_INVALID_DEVICE
);
858 if(!DriverList
[idx
].alcCaptureCloseDevice(device
))
860 DeviceIfaceMap
.removeByKey(device
);
864 ALC_API
void ALC_APIENTRY
alcCaptureStart(ALCdevice
*device
)
868 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
870 return DriverList
[idx
].alcCaptureStart(device
);
872 LastError
.store(ALC_INVALID_DEVICE
);
875 ALC_API
void ALC_APIENTRY
alcCaptureStop(ALCdevice
*device
)
879 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
881 return DriverList
[idx
].alcCaptureStop(device
);
883 LastError
.store(ALC_INVALID_DEVICE
);
886 ALC_API
void ALC_APIENTRY
alcCaptureSamples(ALCdevice
*device
, ALCvoid
*buffer
, ALCsizei samples
)
890 ALint idx
= DeviceIfaceMap
.lookupByKey(device
);
892 return DriverList
[idx
].alcCaptureSamples(device
, buffer
, samples
);
894 LastError
.store(ALC_INVALID_DEVICE
);
898 ALC_API ALCboolean ALC_APIENTRY
alcSetThreadContext(ALCcontext
*context
)
900 ALCenum err
= ALC_INVALID_CONTEXT
;
905 DriverIface
*oldiface
= ThreadCtxDriver
;
906 if(oldiface
&& !oldiface
->alcSetThreadContext(nullptr))
908 ThreadCtxDriver
= nullptr;
912 idx
= ContextIfaceMap
.lookupByKey(context
);
915 if(DriverList
[idx
].alcSetThreadContext(context
))
917 DriverIface
*oldiface
= ThreadCtxDriver
;
918 if(oldiface
!= &DriverList
[idx
])
920 ThreadCtxDriver
= &DriverList
[idx
];
921 if(oldiface
) oldiface
->alcSetThreadContext(nullptr);
925 err
= DriverList
[idx
].alcGetError(nullptr);
927 LastError
.store(err
);
931 ALC_API ALCcontext
* ALC_APIENTRY
alcGetThreadContext(void)
933 DriverIface
*iface
= ThreadCtxDriver
;
934 if(iface
) return iface
->alcGetThreadContext();