Use a plain mutex for the property lock
[openal-soft.git] / OpenAL32 / alState.c
blob460c93e03993b0cb8c5f60c05db5278ed34487e3
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 <stdlib.h>
26 #include "alMain.h"
27 #include "AL/alc.h"
28 #include "AL/al.h"
29 #include "AL/alext.h"
30 #include "alError.h"
31 #include "alListener.h"
32 #include "alSource.h"
33 #include "alAuxEffectSlot.h"
35 #include "backends/base.h"
38 static const ALchar alVendor[] = "OpenAL Community";
39 static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
40 static const ALchar alRenderer[] = "OpenAL Soft";
42 // Error Messages
43 static const ALchar alNoError[] = "No Error";
44 static const ALchar alErrInvalidName[] = "Invalid Name";
45 static const ALchar alErrInvalidEnum[] = "Invalid Enum";
46 static const ALchar alErrInvalidValue[] = "Invalid Value";
47 static const ALchar alErrInvalidOp[] = "Invalid Operation";
48 static const ALchar alErrOutOfMemory[] = "Out of Memory";
50 /* Resampler strings */
51 static const ALchar alPointResampler[] = "Nearest";
52 static const ALchar alLinearResampler[] = "Linear";
53 static const ALchar alCubicResampler[] = "Cubic";
54 static const ALchar alBSinc12Resampler[] = "11th order Sinc";
55 static const ALchar alBSinc24Resampler[] = "23rd order Sinc";
57 /* WARNING: Non-standard export! Not part of any extension, or exposed in the
58 * alcFunctions list.
60 AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
62 const char *spoof = getenv("ALSOFT_SPOOF_VERSION");
63 if(spoof && spoof[0] != '\0') return spoof;
64 return ALSOFT_VERSION;
67 #define DO_UPDATEPROPS() do { \
68 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
69 UpdateContextProps(context); \
70 else \
71 ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release); \
72 } while(0)
75 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
77 ALCcontext *context;
79 context = GetContextRef();
80 if(!context) return;
82 almtx_lock(&context->PropLock);
83 switch(capability)
85 case AL_SOURCE_DISTANCE_MODEL:
86 context->SourceDistanceModel = AL_TRUE;
87 DO_UPDATEPROPS();
88 break;
90 default:
91 alSetError(context, AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
93 almtx_unlock(&context->PropLock);
95 ALCcontext_DecRef(context);
98 AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
100 ALCcontext *context;
102 context = GetContextRef();
103 if(!context) return;
105 almtx_lock(&context->PropLock);
106 switch(capability)
108 case AL_SOURCE_DISTANCE_MODEL:
109 context->SourceDistanceModel = AL_FALSE;
110 DO_UPDATEPROPS();
111 break;
113 default:
114 alSetError(context, AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
116 almtx_unlock(&context->PropLock);
118 ALCcontext_DecRef(context);
121 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
123 ALCcontext *context;
124 ALboolean value=AL_FALSE;
126 context = GetContextRef();
127 if(!context) return AL_FALSE;
129 switch(capability)
131 case AL_SOURCE_DISTANCE_MODEL:
132 value = context->SourceDistanceModel;
133 break;
135 default:
136 alSetError(context, AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
139 ALCcontext_DecRef(context);
140 return value;
143 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
145 ALCcontext *context;
146 ALboolean value=AL_FALSE;
148 context = GetContextRef();
149 if(!context) return AL_FALSE;
151 switch(pname)
153 case AL_DOPPLER_FACTOR:
154 if(context->DopplerFactor != 0.0f)
155 value = AL_TRUE;
156 break;
158 case AL_DOPPLER_VELOCITY:
159 if(context->DopplerVelocity != 0.0f)
160 value = AL_TRUE;
161 break;
163 case AL_DISTANCE_MODEL:
164 if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
165 value = AL_TRUE;
166 break;
168 case AL_SPEED_OF_SOUND:
169 if(context->SpeedOfSound != 0.0f)
170 value = AL_TRUE;
171 break;
173 case AL_DEFERRED_UPDATES_SOFT:
174 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
175 value = AL_TRUE;
176 break;
178 case AL_GAIN_LIMIT_SOFT:
179 if(GAIN_MIX_MAX/context->GainBoost != 0.0f)
180 value = AL_TRUE;
181 break;
183 case AL_NUM_RESAMPLERS_SOFT:
184 /* Always non-0. */
185 value = AL_TRUE;
186 break;
188 case AL_DEFAULT_RESAMPLER_SOFT:
189 value = ResamplerDefault ? AL_TRUE : AL_FALSE;
190 break;
192 default:
193 alSetError(context, AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
196 ALCcontext_DecRef(context);
197 return value;
200 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
202 ALCcontext *context;
203 ALdouble value = 0.0;
205 context = GetContextRef();
206 if(!context) return 0.0;
208 switch(pname)
210 case AL_DOPPLER_FACTOR:
211 value = (ALdouble)context->DopplerFactor;
212 break;
214 case AL_DOPPLER_VELOCITY:
215 value = (ALdouble)context->DopplerVelocity;
216 break;
218 case AL_DISTANCE_MODEL:
219 value = (ALdouble)context->DistanceModel;
220 break;
222 case AL_SPEED_OF_SOUND:
223 value = (ALdouble)context->SpeedOfSound;
224 break;
226 case AL_DEFERRED_UPDATES_SOFT:
227 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
228 value = (ALdouble)AL_TRUE;
229 break;
231 case AL_GAIN_LIMIT_SOFT:
232 value = (ALdouble)GAIN_MIX_MAX/context->GainBoost;
233 break;
235 case AL_NUM_RESAMPLERS_SOFT:
236 value = (ALdouble)(ResamplerMax + 1);
237 break;
239 case AL_DEFAULT_RESAMPLER_SOFT:
240 value = (ALdouble)ResamplerDefault;
241 break;
243 default:
244 alSetError(context, AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
247 ALCcontext_DecRef(context);
248 return value;
251 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
253 ALCcontext *context;
254 ALfloat value = 0.0f;
256 context = GetContextRef();
257 if(!context) return 0.0f;
259 switch(pname)
261 case AL_DOPPLER_FACTOR:
262 value = context->DopplerFactor;
263 break;
265 case AL_DOPPLER_VELOCITY:
266 value = context->DopplerVelocity;
267 break;
269 case AL_DISTANCE_MODEL:
270 value = (ALfloat)context->DistanceModel;
271 break;
273 case AL_SPEED_OF_SOUND:
274 value = context->SpeedOfSound;
275 break;
277 case AL_DEFERRED_UPDATES_SOFT:
278 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
279 value = (ALfloat)AL_TRUE;
280 break;
282 case AL_GAIN_LIMIT_SOFT:
283 value = GAIN_MIX_MAX/context->GainBoost;
284 break;
286 case AL_NUM_RESAMPLERS_SOFT:
287 value = (ALfloat)(ResamplerMax + 1);
288 break;
290 case AL_DEFAULT_RESAMPLER_SOFT:
291 value = (ALfloat)ResamplerDefault;
292 break;
294 default:
295 alSetError(context, AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
298 ALCcontext_DecRef(context);
299 return value;
302 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
304 ALCcontext *context;
305 ALint value = 0;
307 context = GetContextRef();
308 if(!context) return 0;
310 switch(pname)
312 case AL_DOPPLER_FACTOR:
313 value = (ALint)context->DopplerFactor;
314 break;
316 case AL_DOPPLER_VELOCITY:
317 value = (ALint)context->DopplerVelocity;
318 break;
320 case AL_DISTANCE_MODEL:
321 value = (ALint)context->DistanceModel;
322 break;
324 case AL_SPEED_OF_SOUND:
325 value = (ALint)context->SpeedOfSound;
326 break;
328 case AL_DEFERRED_UPDATES_SOFT:
329 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
330 value = (ALint)AL_TRUE;
331 break;
333 case AL_GAIN_LIMIT_SOFT:
334 value = (ALint)(GAIN_MIX_MAX/context->GainBoost);
335 break;
337 case AL_NUM_RESAMPLERS_SOFT:
338 value = ResamplerMax + 1;
339 break;
341 case AL_DEFAULT_RESAMPLER_SOFT:
342 value = ResamplerDefault;
343 break;
345 default:
346 alSetError(context, AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
349 ALCcontext_DecRef(context);
350 return value;
353 AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
355 ALCcontext *context;
356 ALint64SOFT value = 0;
358 context = GetContextRef();
359 if(!context) return 0;
361 switch(pname)
363 case AL_DOPPLER_FACTOR:
364 value = (ALint64SOFT)context->DopplerFactor;
365 break;
367 case AL_DOPPLER_VELOCITY:
368 value = (ALint64SOFT)context->DopplerVelocity;
369 break;
371 case AL_DISTANCE_MODEL:
372 value = (ALint64SOFT)context->DistanceModel;
373 break;
375 case AL_SPEED_OF_SOUND:
376 value = (ALint64SOFT)context->SpeedOfSound;
377 break;
379 case AL_DEFERRED_UPDATES_SOFT:
380 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
381 value = (ALint64SOFT)AL_TRUE;
382 break;
384 case AL_GAIN_LIMIT_SOFT:
385 value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost);
386 break;
388 case AL_NUM_RESAMPLERS_SOFT:
389 value = (ALint64SOFT)(ResamplerMax + 1);
390 break;
392 case AL_DEFAULT_RESAMPLER_SOFT:
393 value = (ALint64SOFT)ResamplerDefault;
394 break;
396 default:
397 alSetError(context, AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
400 ALCcontext_DecRef(context);
401 return value;
404 AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
406 ALCcontext *context;
407 void *value = NULL;
409 context = GetContextRef();
410 if(!context) return NULL;
412 switch(pname)
414 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
415 value = context->EventCb;
416 break;
418 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
419 value = context->EventParam;
420 break;
422 default:
423 alSetError(context, AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
426 ALCcontext_DecRef(context);
427 return value;
430 AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
432 ALCcontext *context;
434 if(values)
436 switch(pname)
438 case AL_DOPPLER_FACTOR:
439 case AL_DOPPLER_VELOCITY:
440 case AL_DISTANCE_MODEL:
441 case AL_SPEED_OF_SOUND:
442 case AL_DEFERRED_UPDATES_SOFT:
443 case AL_GAIN_LIMIT_SOFT:
444 case AL_NUM_RESAMPLERS_SOFT:
445 case AL_DEFAULT_RESAMPLER_SOFT:
446 values[0] = alGetBoolean(pname);
447 return;
451 context = GetContextRef();
452 if(!context) return;
454 if(!values)
455 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
456 switch(pname)
458 default:
459 alSetError(context, AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
462 ALCcontext_DecRef(context);
465 AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
467 ALCcontext *context;
469 if(values)
471 switch(pname)
473 case AL_DOPPLER_FACTOR:
474 case AL_DOPPLER_VELOCITY:
475 case AL_DISTANCE_MODEL:
476 case AL_SPEED_OF_SOUND:
477 case AL_DEFERRED_UPDATES_SOFT:
478 case AL_GAIN_LIMIT_SOFT:
479 case AL_NUM_RESAMPLERS_SOFT:
480 case AL_DEFAULT_RESAMPLER_SOFT:
481 values[0] = alGetDouble(pname);
482 return;
486 context = GetContextRef();
487 if(!context) return;
489 if(!values)
490 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
491 switch(pname)
493 default:
494 alSetError(context, AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
497 ALCcontext_DecRef(context);
500 AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
502 ALCcontext *context;
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] = alGetFloat(pname);
517 return;
521 context = GetContextRef();
522 if(!context) return;
524 if(!values)
525 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
526 switch(pname)
528 default:
529 alSetError(context, AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
532 ALCcontext_DecRef(context);
535 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
537 ALCcontext *context;
539 if(values)
541 switch(pname)
543 case AL_DOPPLER_FACTOR:
544 case AL_DOPPLER_VELOCITY:
545 case AL_DISTANCE_MODEL:
546 case AL_SPEED_OF_SOUND:
547 case AL_DEFERRED_UPDATES_SOFT:
548 case AL_GAIN_LIMIT_SOFT:
549 case AL_NUM_RESAMPLERS_SOFT:
550 case AL_DEFAULT_RESAMPLER_SOFT:
551 values[0] = alGetInteger(pname);
552 return;
556 context = GetContextRef();
557 if(!context) return;
559 if(!values)
560 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
561 switch(pname)
563 default:
564 alSetError(context, AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
567 ALCcontext_DecRef(context);
570 AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
572 ALCcontext *context;
574 if(values)
576 switch(pname)
578 case AL_DOPPLER_FACTOR:
579 case AL_DOPPLER_VELOCITY:
580 case AL_DISTANCE_MODEL:
581 case AL_SPEED_OF_SOUND:
582 case AL_DEFERRED_UPDATES_SOFT:
583 case AL_GAIN_LIMIT_SOFT:
584 case AL_NUM_RESAMPLERS_SOFT:
585 case AL_DEFAULT_RESAMPLER_SOFT:
586 values[0] = alGetInteger64SOFT(pname);
587 return;
591 context = GetContextRef();
592 if(!context) return;
594 if(!values)
595 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
596 switch(pname)
598 default:
599 alSetError(context, AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
602 ALCcontext_DecRef(context);
605 AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
607 ALCcontext *context;
609 if(values)
611 switch(pname)
613 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
614 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
615 values[0] = alGetPointerSOFT(pname);
616 return;
620 context = GetContextRef();
621 if(!context) return;
623 if(!values)
624 alSetError(context, AL_INVALID_VALUE, "NULL pointer");
625 switch(pname)
627 default:
628 alSetError(context, AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
631 ALCcontext_DecRef(context);
634 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
636 const ALchar *value = NULL;
637 ALCcontext *context;
639 context = GetContextRef();
640 if(!context) return NULL;
642 switch(pname)
644 case AL_VENDOR:
645 value = alVendor;
646 break;
648 case AL_VERSION:
649 value = alVersion;
650 break;
652 case AL_RENDERER:
653 value = alRenderer;
654 break;
656 case AL_EXTENSIONS:
657 value = context->ExtensionList;
658 break;
660 case AL_NO_ERROR:
661 value = alNoError;
662 break;
664 case AL_INVALID_NAME:
665 value = alErrInvalidName;
666 break;
668 case AL_INVALID_ENUM:
669 value = alErrInvalidEnum;
670 break;
672 case AL_INVALID_VALUE:
673 value = alErrInvalidValue;
674 break;
676 case AL_INVALID_OPERATION:
677 value = alErrInvalidOp;
678 break;
680 case AL_OUT_OF_MEMORY:
681 value = alErrOutOfMemory;
682 break;
684 default:
685 alSetError(context, AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
688 ALCcontext_DecRef(context);
689 return value;
692 AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
694 ALCcontext *context;
696 context = GetContextRef();
697 if(!context) return;
699 if(!(value >= 0.0f && isfinite(value)))
700 alSetError(context, AL_INVALID_VALUE, "Doppler factor %f out of range", value);
701 else
703 almtx_lock(&context->PropLock);
704 context->DopplerFactor = value;
705 DO_UPDATEPROPS();
706 almtx_unlock(&context->PropLock);
709 ALCcontext_DecRef(context);
712 AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
714 ALCcontext *context;
716 context = GetContextRef();
717 if(!context) return;
719 if((ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed)&EventType_Deprecated))
721 static const ALCchar msg[] =
722 "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
723 const ALsizei msglen = (ALsizei)strlen(msg);
724 ALbitfieldSOFT enabledevts;
725 almtx_lock(&context->EventCbLock);
726 enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
727 if((enabledevts&EventType_Deprecated) && context->EventCb)
728 (*context->EventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
729 context->EventParam);
730 almtx_unlock(&context->EventCbLock);
733 if(!(value >= 0.0f && isfinite(value)))
734 alSetError(context, AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
735 else
737 almtx_lock(&context->PropLock);
738 context->DopplerVelocity = value;
739 DO_UPDATEPROPS();
740 almtx_unlock(&context->PropLock);
743 ALCcontext_DecRef(context);
746 AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
748 ALCcontext *context;
750 context = GetContextRef();
751 if(!context) return;
753 if(!(value > 0.0f && isfinite(value)))
754 alSetError(context, AL_INVALID_VALUE, "Speed of sound %f out of range", value);
755 else
757 almtx_lock(&context->PropLock);
758 context->SpeedOfSound = value;
759 DO_UPDATEPROPS();
760 almtx_unlock(&context->PropLock);
763 ALCcontext_DecRef(context);
766 AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
768 ALCcontext *context;
770 context = GetContextRef();
771 if(!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 alSetError(context, AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
778 else
780 almtx_lock(&context->PropLock);
781 context->DistanceModel = value;
782 if(!context->SourceDistanceModel)
783 DO_UPDATEPROPS();
784 almtx_unlock(&context->PropLock);
787 ALCcontext_DecRef(context);
791 AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
793 ALCcontext *context;
795 context = GetContextRef();
796 if(!context) return;
798 ALCcontext_DeferUpdates(context);
800 ALCcontext_DecRef(context);
803 AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
805 ALCcontext *context;
807 context = GetContextRef();
808 if(!context) return;
810 ALCcontext_ProcessUpdates(context);
812 ALCcontext_DecRef(context);
816 AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
818 const char *ResamplerNames[] = {
819 alPointResampler, alLinearResampler,
820 alCubicResampler, alBSinc12Resampler,
821 alBSinc24Resampler,
823 const ALchar *value = NULL;
824 ALCcontext *context;
826 static_assert(COUNTOF(ResamplerNames) == ResamplerMax+1, "Incorrect ResamplerNames list");
828 context = GetContextRef();
829 if(!context) return NULL;
831 switch(pname)
833 case AL_RESAMPLER_NAME_SOFT:
834 if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
835 SETERR_GOTO(context, AL_INVALID_VALUE, done, "Resampler name index %d out of range",
836 index);
837 value = ResamplerNames[index];
838 break;
840 default:
841 alSetError(context, AL_INVALID_VALUE, "Invalid string indexed property");
844 done:
845 ALCcontext_DecRef(context);
846 return value;
850 void UpdateContextProps(ALCcontext *context)
852 struct ALcontextProps *props;
854 /* Get an unused proprty container, or allocate a new one as needed. */
855 props = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
856 if(!props)
857 props = al_calloc(16, sizeof(*props));
858 else
860 struct ALcontextProps *next;
861 do {
862 next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
863 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeContextProps, &props, next,
864 almemory_order_seq_cst, almemory_order_acquire) == 0);
867 /* Copy in current property values. */
868 props->MetersPerUnit = context->MetersPerUnit;
870 props->DopplerFactor = context->DopplerFactor;
871 props->DopplerVelocity = context->DopplerVelocity;
872 props->SpeedOfSound = context->SpeedOfSound;
874 props->SourceDistanceModel = context->SourceDistanceModel;
875 props->DistanceModel = context->DistanceModel;
877 /* Set the new container for updating internal parameters. */
878 props = ATOMIC_EXCHANGE_PTR(&context->Update, props, almemory_order_acq_rel);
879 if(props)
881 /* If there was an unused update container, put it back in the
882 * freelist.
884 ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &context->FreeContextProps, props);