Cast the ringbuffer size to the correct type
[openal-soft.git] / al / state.cpp
blobdcc87972845813abaf351be1c9ff3932ef2c0b61
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2000 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "version.h"
25 #include <atomic>
26 #include <cmath>
27 #include <cstdlib>
28 #include <cstring>
29 #include <mutex>
31 #include "AL/al.h"
32 #include "AL/alc.h"
33 #include "AL/alext.h"
35 #include "alcontext.h"
36 #include "alexcpt.h"
37 #include "almalloc.h"
38 #include "alnumeric.h"
39 #include "alspan.h"
40 #include "alu.h"
41 #include "atomic.h"
42 #include "event.h"
43 #include "inprogext.h"
44 #include "opthelpers.h"
45 #include "strutils.h"
48 namespace {
50 constexpr ALchar alVendor[] = "OpenAL Community";
51 constexpr ALchar alVersion[] = "1.1 ALSOFT " ALSOFT_VERSION;
52 constexpr ALchar alRenderer[] = "OpenAL Soft";
54 // Error Messages
55 constexpr ALchar alNoError[] = "No Error";
56 constexpr ALchar alErrInvalidName[] = "Invalid Name";
57 constexpr ALchar alErrInvalidEnum[] = "Invalid Enum";
58 constexpr ALchar alErrInvalidValue[] = "Invalid Value";
59 constexpr ALchar alErrInvalidOp[] = "Invalid Operation";
60 constexpr ALchar alErrOutOfMemory[] = "Out of Memory";
62 /* Resampler strings */
63 template<Resampler rtype> struct ResamplerName { };
64 template<> struct ResamplerName<Resampler::Point>
65 { static constexpr const ALchar *Get() noexcept { return "Nearest"; } };
66 template<> struct ResamplerName<Resampler::Linear>
67 { static constexpr const ALchar *Get() noexcept { return "Linear"; } };
68 template<> struct ResamplerName<Resampler::Cubic>
69 { static constexpr const ALchar *Get() noexcept { return "Cubic"; } };
70 template<> struct ResamplerName<Resampler::FastBSinc12>
71 { static constexpr const ALchar *Get() noexcept { return "11th order Sinc (fast)"; } };
72 template<> struct ResamplerName<Resampler::BSinc12>
73 { static constexpr const ALchar *Get() noexcept { return "11th order Sinc"; } };
74 template<> struct ResamplerName<Resampler::FastBSinc24>
75 { static constexpr const ALchar *Get() noexcept { return "23rd order Sinc (fast)"; } };
76 template<> struct ResamplerName<Resampler::BSinc24>
77 { static constexpr const ALchar *Get() noexcept { return "23rd order Sinc"; } };
79 const ALchar *GetResamplerName(const Resampler rtype)
81 #define HANDLE_RESAMPLER(r) case r: return ResamplerName<r>::Get()
82 switch(rtype)
84 HANDLE_RESAMPLER(Resampler::Point);
85 HANDLE_RESAMPLER(Resampler::Linear);
86 HANDLE_RESAMPLER(Resampler::Cubic);
87 HANDLE_RESAMPLER(Resampler::FastBSinc12);
88 HANDLE_RESAMPLER(Resampler::BSinc12);
89 HANDLE_RESAMPLER(Resampler::FastBSinc24);
90 HANDLE_RESAMPLER(Resampler::BSinc24);
92 #undef HANDLE_RESAMPLER
93 /* Should never get here. */
94 throw std::runtime_error{"Unexpected resampler index"};
97 } // namespace
99 /* WARNING: Non-standard export! Not part of any extension, or exposed in the
100 * alcFunctions list.
102 extern "C" AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
103 START_API_FUNC
105 static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION");
106 if(spoof) return spoof->c_str();
107 return ALSOFT_VERSION;
109 END_API_FUNC
111 #define DO_UPDATEPROPS() do { \
112 if(!context->mDeferUpdates.load(std::memory_order_acquire)) \
113 UpdateContextProps(context.get()); \
114 else \
115 context->mPropsClean.clear(std::memory_order_release); \
116 } while(0)
119 AL_API void AL_APIENTRY alEnable(ALenum capability)
120 START_API_FUNC
122 ContextRef context{GetContextRef()};
123 if UNLIKELY(!context) return;
125 std::lock_guard<std::mutex> _{context->mPropLock};
126 switch(capability)
128 case AL_SOURCE_DISTANCE_MODEL:
129 context->mSourceDistanceModel = true;
130 DO_UPDATEPROPS();
131 break;
133 default:
134 context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
137 END_API_FUNC
139 AL_API void AL_APIENTRY alDisable(ALenum capability)
140 START_API_FUNC
142 ContextRef context{GetContextRef()};
143 if UNLIKELY(!context) return;
145 std::lock_guard<std::mutex> _{context->mPropLock};
146 switch(capability)
148 case AL_SOURCE_DISTANCE_MODEL:
149 context->mSourceDistanceModel = false;
150 DO_UPDATEPROPS();
151 break;
153 default:
154 context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
157 END_API_FUNC
159 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
160 START_API_FUNC
162 ContextRef context{GetContextRef()};
163 if UNLIKELY(!context) return AL_FALSE;
165 std::lock_guard<std::mutex> _{context->mPropLock};
166 ALboolean value{AL_FALSE};
167 switch(capability)
169 case AL_SOURCE_DISTANCE_MODEL:
170 value = context->mSourceDistanceModel ? AL_TRUE : AL_FALSE;
171 break;
173 default:
174 context->setError(AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
177 return value;
179 END_API_FUNC
181 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
182 START_API_FUNC
184 ContextRef context{GetContextRef()};
185 if UNLIKELY(!context) return AL_FALSE;
187 std::lock_guard<std::mutex> _{context->mPropLock};
188 ALboolean value{AL_FALSE};
189 switch(pname)
191 case AL_DOPPLER_FACTOR:
192 if(context->mDopplerFactor != 0.0f)
193 value = AL_TRUE;
194 break;
196 case AL_DOPPLER_VELOCITY:
197 if(context->mDopplerVelocity != 0.0f)
198 value = AL_TRUE;
199 break;
201 case AL_DISTANCE_MODEL:
202 if(context->mDistanceModel == DistanceModel::Default)
203 value = AL_TRUE;
204 break;
206 case AL_SPEED_OF_SOUND:
207 if(context->mSpeedOfSound != 0.0f)
208 value = AL_TRUE;
209 break;
211 case AL_DEFERRED_UPDATES_SOFT:
212 if(context->mDeferUpdates.load(std::memory_order_acquire))
213 value = AL_TRUE;
214 break;
216 case AL_GAIN_LIMIT_SOFT:
217 if(GAIN_MIX_MAX/context->mGainBoost != 0.0f)
218 value = AL_TRUE;
219 break;
221 case AL_NUM_RESAMPLERS_SOFT:
222 /* Always non-0. */
223 value = AL_TRUE;
224 break;
226 case AL_DEFAULT_RESAMPLER_SOFT:
227 value = static_cast<int>(ResamplerDefault) ? AL_TRUE : AL_FALSE;
228 break;
230 default:
231 context->setError(AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
234 return value;
236 END_API_FUNC
238 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
239 START_API_FUNC
241 ContextRef context{GetContextRef()};
242 if UNLIKELY(!context) return 0.0;
244 std::lock_guard<std::mutex> _{context->mPropLock};
245 ALdouble value{0.0};
246 switch(pname)
248 case AL_DOPPLER_FACTOR:
249 value = context->mDopplerFactor;
250 break;
252 case AL_DOPPLER_VELOCITY:
253 value = context->mDopplerVelocity;
254 break;
256 case AL_DISTANCE_MODEL:
257 value = static_cast<ALdouble>(context->mDistanceModel);
258 break;
260 case AL_SPEED_OF_SOUND:
261 value = context->mSpeedOfSound;
262 break;
264 case AL_DEFERRED_UPDATES_SOFT:
265 if(context->mDeferUpdates.load(std::memory_order_acquire))
266 value = static_cast<ALdouble>(AL_TRUE);
267 break;
269 case AL_GAIN_LIMIT_SOFT:
270 value = ALdouble{GAIN_MIX_MAX}/context->mGainBoost;
271 break;
273 case AL_NUM_RESAMPLERS_SOFT:
274 value = static_cast<ALdouble>(Resampler::Max) + 1.0;
275 break;
277 case AL_DEFAULT_RESAMPLER_SOFT:
278 value = static_cast<ALdouble>(ResamplerDefault);
279 break;
281 default:
282 context->setError(AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
285 return value;
287 END_API_FUNC
289 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
290 START_API_FUNC
292 ContextRef context{GetContextRef()};
293 if UNLIKELY(!context) return 0.0f;
295 std::lock_guard<std::mutex> _{context->mPropLock};
296 ALfloat value{0.0f};
297 switch(pname)
299 case AL_DOPPLER_FACTOR:
300 value = context->mDopplerFactor;
301 break;
303 case AL_DOPPLER_VELOCITY:
304 value = context->mDopplerVelocity;
305 break;
307 case AL_DISTANCE_MODEL:
308 value = static_cast<ALfloat>(context->mDistanceModel);
309 break;
311 case AL_SPEED_OF_SOUND:
312 value = context->mSpeedOfSound;
313 break;
315 case AL_DEFERRED_UPDATES_SOFT:
316 if(context->mDeferUpdates.load(std::memory_order_acquire))
317 value = static_cast<ALfloat>(AL_TRUE);
318 break;
320 case AL_GAIN_LIMIT_SOFT:
321 value = GAIN_MIX_MAX/context->mGainBoost;
322 break;
324 case AL_NUM_RESAMPLERS_SOFT:
325 value = static_cast<ALfloat>(Resampler::Max) + 1.0f;
326 break;
328 case AL_DEFAULT_RESAMPLER_SOFT:
329 value = static_cast<ALfloat>(ResamplerDefault);
330 break;
332 default:
333 context->setError(AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
336 return value;
338 END_API_FUNC
340 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
341 START_API_FUNC
343 ContextRef context{GetContextRef()};
344 if UNLIKELY(!context) return 0;
346 std::lock_guard<std::mutex> _{context->mPropLock};
347 ALint value{0};
348 switch(pname)
350 case AL_DOPPLER_FACTOR:
351 value = static_cast<ALint>(context->mDopplerFactor);
352 break;
354 case AL_DOPPLER_VELOCITY:
355 value = static_cast<ALint>(context->mDopplerVelocity);
356 break;
358 case AL_DISTANCE_MODEL:
359 value = static_cast<ALint>(context->mDistanceModel);
360 break;
362 case AL_SPEED_OF_SOUND:
363 value = static_cast<ALint>(context->mSpeedOfSound);
364 break;
366 case AL_DEFERRED_UPDATES_SOFT:
367 if(context->mDeferUpdates.load(std::memory_order_acquire))
368 value = AL_TRUE;
369 break;
371 case AL_GAIN_LIMIT_SOFT:
372 value = static_cast<ALint>(GAIN_MIX_MAX/context->mGainBoost);
373 break;
375 case AL_NUM_RESAMPLERS_SOFT:
376 value = static_cast<int>(Resampler::Max) + 1;
377 break;
379 case AL_DEFAULT_RESAMPLER_SOFT:
380 value = static_cast<int>(ResamplerDefault);
381 break;
383 default:
384 context->setError(AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
387 return value;
389 END_API_FUNC
391 extern "C" AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
392 START_API_FUNC
394 ContextRef context{GetContextRef()};
395 if UNLIKELY(!context) return 0_i64;
397 std::lock_guard<std::mutex> _{context->mPropLock};
398 ALint64SOFT value{0};
399 switch(pname)
401 case AL_DOPPLER_FACTOR:
402 value = static_cast<ALint64SOFT>(context->mDopplerFactor);
403 break;
405 case AL_DOPPLER_VELOCITY:
406 value = static_cast<ALint64SOFT>(context->mDopplerVelocity);
407 break;
409 case AL_DISTANCE_MODEL:
410 value = static_cast<ALint64SOFT>(context->mDistanceModel);
411 break;
413 case AL_SPEED_OF_SOUND:
414 value = static_cast<ALint64SOFT>(context->mSpeedOfSound);
415 break;
417 case AL_DEFERRED_UPDATES_SOFT:
418 if(context->mDeferUpdates.load(std::memory_order_acquire))
419 value = AL_TRUE;
420 break;
422 case AL_GAIN_LIMIT_SOFT:
423 value = static_cast<ALint64SOFT>(GAIN_MIX_MAX/context->mGainBoost);
424 break;
426 case AL_NUM_RESAMPLERS_SOFT:
427 value = static_cast<ALint64SOFT>(Resampler::Max) + 1;
428 break;
430 case AL_DEFAULT_RESAMPLER_SOFT:
431 value = static_cast<ALint64SOFT>(ResamplerDefault);
432 break;
434 default:
435 context->setError(AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
438 return value;
440 END_API_FUNC
442 AL_API ALvoid* AL_APIENTRY alGetPointerSOFT(ALenum pname)
443 START_API_FUNC
445 ContextRef context{GetContextRef()};
446 if UNLIKELY(!context) return nullptr;
448 std::lock_guard<std::mutex> _{context->mPropLock};
449 void *value{nullptr};
450 switch(pname)
452 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
453 value = reinterpret_cast<void*>(context->mEventCb);
454 break;
456 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
457 value = context->mEventParam;
458 break;
460 default:
461 context->setError(AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
464 return value;
466 END_API_FUNC
468 AL_API void AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
469 START_API_FUNC
471 if(values)
473 switch(pname)
475 case AL_DOPPLER_FACTOR:
476 case AL_DOPPLER_VELOCITY:
477 case AL_DISTANCE_MODEL:
478 case AL_SPEED_OF_SOUND:
479 case AL_DEFERRED_UPDATES_SOFT:
480 case AL_GAIN_LIMIT_SOFT:
481 case AL_NUM_RESAMPLERS_SOFT:
482 case AL_DEFAULT_RESAMPLER_SOFT:
483 values[0] = alGetBoolean(pname);
484 return;
488 ContextRef context{GetContextRef()};
489 if UNLIKELY(!context) return;
491 if(!values)
492 context->setError(AL_INVALID_VALUE, "NULL pointer");
493 else switch(pname)
495 default:
496 context->setError(AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
499 END_API_FUNC
501 AL_API void AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
502 START_API_FUNC
504 if(values)
506 switch(pname)
508 case AL_DOPPLER_FACTOR:
509 case AL_DOPPLER_VELOCITY:
510 case AL_DISTANCE_MODEL:
511 case AL_SPEED_OF_SOUND:
512 case AL_DEFERRED_UPDATES_SOFT:
513 case AL_GAIN_LIMIT_SOFT:
514 case AL_NUM_RESAMPLERS_SOFT:
515 case AL_DEFAULT_RESAMPLER_SOFT:
516 values[0] = alGetDouble(pname);
517 return;
521 ContextRef context{GetContextRef()};
522 if UNLIKELY(!context) return;
524 if(!values)
525 context->setError(AL_INVALID_VALUE, "NULL pointer");
526 else switch(pname)
528 default:
529 context->setError(AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
532 END_API_FUNC
534 AL_API void AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
535 START_API_FUNC
537 if(values)
539 switch(pname)
541 case AL_DOPPLER_FACTOR:
542 case AL_DOPPLER_VELOCITY:
543 case AL_DISTANCE_MODEL:
544 case AL_SPEED_OF_SOUND:
545 case AL_DEFERRED_UPDATES_SOFT:
546 case AL_GAIN_LIMIT_SOFT:
547 case AL_NUM_RESAMPLERS_SOFT:
548 case AL_DEFAULT_RESAMPLER_SOFT:
549 values[0] = alGetFloat(pname);
550 return;
554 ContextRef context{GetContextRef()};
555 if UNLIKELY(!context) return;
557 if(!values)
558 context->setError(AL_INVALID_VALUE, "NULL pointer");
559 else switch(pname)
561 default:
562 context->setError(AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
565 END_API_FUNC
567 AL_API void AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
568 START_API_FUNC
570 if(values)
572 switch(pname)
574 case AL_DOPPLER_FACTOR:
575 case AL_DOPPLER_VELOCITY:
576 case AL_DISTANCE_MODEL:
577 case AL_SPEED_OF_SOUND:
578 case AL_DEFERRED_UPDATES_SOFT:
579 case AL_GAIN_LIMIT_SOFT:
580 case AL_NUM_RESAMPLERS_SOFT:
581 case AL_DEFAULT_RESAMPLER_SOFT:
582 values[0] = alGetInteger(pname);
583 return;
587 ContextRef context{GetContextRef()};
588 if UNLIKELY(!context) return;
590 if(!values)
591 context->setError(AL_INVALID_VALUE, "NULL pointer");
592 else switch(pname)
594 default:
595 context->setError(AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
598 END_API_FUNC
600 extern "C" AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
601 START_API_FUNC
603 if(values)
605 switch(pname)
607 case AL_DOPPLER_FACTOR:
608 case AL_DOPPLER_VELOCITY:
609 case AL_DISTANCE_MODEL:
610 case AL_SPEED_OF_SOUND:
611 case AL_DEFERRED_UPDATES_SOFT:
612 case AL_GAIN_LIMIT_SOFT:
613 case AL_NUM_RESAMPLERS_SOFT:
614 case AL_DEFAULT_RESAMPLER_SOFT:
615 values[0] = alGetInteger64SOFT(pname);
616 return;
620 ContextRef context{GetContextRef()};
621 if UNLIKELY(!context) return;
623 if(!values)
624 context->setError(AL_INVALID_VALUE, "NULL pointer");
625 else switch(pname)
627 default:
628 context->setError(AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
631 END_API_FUNC
633 AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, ALvoid **values)
634 START_API_FUNC
636 if(values)
638 switch(pname)
640 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
641 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
642 values[0] = alGetPointerSOFT(pname);
643 return;
647 ContextRef context{GetContextRef()};
648 if UNLIKELY(!context) return;
650 if(!values)
651 context->setError(AL_INVALID_VALUE, "NULL pointer");
652 else switch(pname)
654 default:
655 context->setError(AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
658 END_API_FUNC
660 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
661 START_API_FUNC
663 ContextRef context{GetContextRef()};
664 if UNLIKELY(!context) return nullptr;
666 const ALchar *value{nullptr};
667 switch(pname)
669 case AL_VENDOR:
670 value = alVendor;
671 break;
673 case AL_VERSION:
674 value = alVersion;
675 break;
677 case AL_RENDERER:
678 value = alRenderer;
679 break;
681 case AL_EXTENSIONS:
682 value = context->mExtensionList;
683 break;
685 case AL_NO_ERROR:
686 value = alNoError;
687 break;
689 case AL_INVALID_NAME:
690 value = alErrInvalidName;
691 break;
693 case AL_INVALID_ENUM:
694 value = alErrInvalidEnum;
695 break;
697 case AL_INVALID_VALUE:
698 value = alErrInvalidValue;
699 break;
701 case AL_INVALID_OPERATION:
702 value = alErrInvalidOp;
703 break;
705 case AL_OUT_OF_MEMORY:
706 value = alErrOutOfMemory;
707 break;
709 default:
710 context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
712 return value;
714 END_API_FUNC
716 AL_API void AL_APIENTRY alDopplerFactor(ALfloat value)
717 START_API_FUNC
719 ContextRef context{GetContextRef()};
720 if UNLIKELY(!context) return;
722 if(!(value >= 0.0f && std::isfinite(value)))
723 context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value);
724 else
726 std::lock_guard<std::mutex> _{context->mPropLock};
727 context->mDopplerFactor = value;
728 DO_UPDATEPROPS();
731 END_API_FUNC
733 AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value)
734 START_API_FUNC
736 ContextRef context{GetContextRef()};
737 if UNLIKELY(!context) return;
739 if(!(value >= 0.0f && std::isfinite(value)))
740 context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
741 else
743 std::lock_guard<std::mutex> _{context->mPropLock};
744 context->mDopplerVelocity = value;
745 DO_UPDATEPROPS();
748 END_API_FUNC
750 AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value)
751 START_API_FUNC
753 ContextRef context{GetContextRef()};
754 if UNLIKELY(!context) return;
756 if(!(value > 0.0f && std::isfinite(value)))
757 context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value);
758 else
760 std::lock_guard<std::mutex> _{context->mPropLock};
761 context->mSpeedOfSound = value;
762 DO_UPDATEPROPS();
765 END_API_FUNC
767 AL_API void AL_APIENTRY alDistanceModel(ALenum value)
768 START_API_FUNC
770 ContextRef context{GetContextRef()};
771 if UNLIKELY(!context) return;
773 if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
774 value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
775 value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
776 value == AL_NONE))
777 context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
778 else
780 std::lock_guard<std::mutex> _{context->mPropLock};
781 context->mDistanceModel = static_cast<DistanceModel>(value);
782 if(!context->mSourceDistanceModel)
783 DO_UPDATEPROPS();
786 END_API_FUNC
789 AL_API void AL_APIENTRY alDeferUpdatesSOFT(void)
790 START_API_FUNC
792 ContextRef context{GetContextRef()};
793 if UNLIKELY(!context) return;
795 context->deferUpdates();
797 END_API_FUNC
799 AL_API void AL_APIENTRY alProcessUpdatesSOFT(void)
800 START_API_FUNC
802 ContextRef context{GetContextRef()};
803 if UNLIKELY(!context) return;
805 context->processUpdates();
807 END_API_FUNC
810 AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
811 START_API_FUNC
813 ContextRef context{GetContextRef()};
814 if UNLIKELY(!context) return nullptr;
816 const ALchar *value{nullptr};
817 switch(pname)
819 case AL_RESAMPLER_NAME_SOFT:
820 if(index < 0 || index > static_cast<ALint>(Resampler::Max))
821 context->setError(AL_INVALID_VALUE, "Resampler name index %d out of range", index);
822 else
823 value = GetResamplerName(static_cast<Resampler>(index));
824 break;
826 default:
827 context->setError(AL_INVALID_VALUE, "Invalid string indexed property");
829 return value;
831 END_API_FUNC
834 void UpdateContextProps(ALCcontext *context)
836 /* Get an unused proprty container, or allocate a new one as needed. */
837 ALcontextProps *props{context->mFreeContextProps.load(std::memory_order_acquire)};
838 if(!props)
839 props = new ALcontextProps{};
840 else
842 ALcontextProps *next;
843 do {
844 next = props->next.load(std::memory_order_relaxed);
845 } while(context->mFreeContextProps.compare_exchange_weak(props, next,
846 std::memory_order_seq_cst, std::memory_order_acquire) == 0);
849 /* Copy in current property values. */
850 props->DopplerFactor = context->mDopplerFactor;
851 props->DopplerVelocity = context->mDopplerVelocity;
852 props->SpeedOfSound = context->mSpeedOfSound;
854 props->SourceDistanceModel = context->mSourceDistanceModel;
855 props->mDistanceModel = context->mDistanceModel;
857 /* Set the new container for updating internal parameters. */
858 props = context->mUpdate.exchange(props, std::memory_order_acq_rel);
859 if(props)
861 /* If there was an unused update container, put it back in the
862 * freelist.
864 AtomicReplaceHead(context->mFreeContextProps, props);