aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/alState.c
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32/alState.c')
-rw-r--r--OpenAL32/alState.c401
1 files changed, 333 insertions, 68 deletions
diff --git a/OpenAL32/alState.c b/OpenAL32/alState.c
index dca41363..ce93e143 100644
--- a/OpenAL32/alState.c
+++ b/OpenAL32/alState.c
@@ -20,12 +20,15 @@
#include "config.h"
+#include "version.h"
+
#include <stdlib.h>
#include "alMain.h"
#include "AL/alc.h"
#include "AL/al.h"
#include "AL/alext.h"
#include "alError.h"
+#include "alListener.h"
#include "alSource.h"
#include "alAuxEffectSlot.h"
@@ -44,6 +47,31 @@ static const ALchar alErrInvalidValue[] = "Invalid Value";
static const ALchar alErrInvalidOp[] = "Invalid Operation";
static const ALchar alErrOutOfMemory[] = "Out of Memory";
+/* Resampler strings */
+static const ALchar alPointResampler[] = "Nearest";
+static const ALchar alLinearResampler[] = "Linear";
+static const ALchar alCubicResampler[] = "Cubic";
+static const ALchar alBSinc12Resampler[] = "11th order Sinc";
+static const ALchar alBSinc24Resampler[] = "23rd order Sinc";
+
+/* WARNING: Non-standard export! Not part of any extension, or exposed in the
+ * alcFunctions list.
+ */
+AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
+{
+ const char *spoof = getenv("ALSOFT_SPOOF_VERSION");
+ if(spoof && spoof[0] != '\0') return spoof;
+ return ALSOFT_VERSION;
+}
+
+#define DO_UPDATEPROPS() do { \
+ if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
+ UpdateContextProps(context); \
+ else \
+ ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release); \
+} while(0)
+
+
AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
{
ALCcontext *context;
@@ -51,18 +79,19 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
context = GetContextRef();
if(!context) return;
+ almtx_lock(&context->PropLock);
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
context->SourceDistanceModel = AL_TRUE;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ DO_UPDATEPROPS();
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
}
@@ -73,18 +102,19 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
context = GetContextRef();
if(!context) return;
+ almtx_lock(&context->PropLock);
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
context->SourceDistanceModel = AL_FALSE;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ DO_UPDATEPROPS();
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
}
@@ -96,6 +126,7 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
context = GetContextRef();
if(!context) return AL_FALSE;
+ almtx_lock(&context->PropLock);
switch(capability)
{
case AL_SOURCE_DISTANCE_MODEL:
@@ -103,12 +134,11 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
-
return value;
}
@@ -120,6 +150,7 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
context = GetContextRef();
if(!context) return AL_FALSE;
+ almtx_lock(&context->PropLock);
switch(pname)
{
case AL_DOPPLER_FACTOR:
@@ -143,16 +174,30 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
break;
case AL_DEFERRED_UPDATES_SOFT:
- value = context->DeferUpdates;
+ if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
+ value = AL_TRUE;
+ break;
+
+ case AL_GAIN_LIMIT_SOFT:
+ if(GAIN_MIX_MAX/context->GainBoost != 0.0f)
+ value = AL_TRUE;
+ break;
+
+ case AL_NUM_RESAMPLERS_SOFT:
+ /* Always non-0. */
+ value = AL_TRUE;
+ break;
+
+ case AL_DEFAULT_RESAMPLER_SOFT:
+ value = ResamplerDefault ? AL_TRUE : AL_FALSE;
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
-
return value;
}
@@ -164,6 +209,7 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
context = GetContextRef();
if(!context) return 0.0;
+ almtx_lock(&context->PropLock);
switch(pname)
{
case AL_DOPPLER_FACTOR:
@@ -183,16 +229,28 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
break;
case AL_DEFERRED_UPDATES_SOFT:
- value = (ALdouble)context->DeferUpdates;
+ if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
+ value = (ALdouble)AL_TRUE;
+ break;
+
+ case AL_GAIN_LIMIT_SOFT:
+ value = (ALdouble)GAIN_MIX_MAX/context->GainBoost;
+ break;
+
+ case AL_NUM_RESAMPLERS_SOFT:
+ value = (ALdouble)(ResamplerMax + 1);
+ break;
+
+ case AL_DEFAULT_RESAMPLER_SOFT:
+ value = (ALdouble)ResamplerDefault;
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
-
return value;
}
@@ -204,6 +262,7 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
context = GetContextRef();
if(!context) return 0.0f;
+ almtx_lock(&context->PropLock);
switch(pname)
{
case AL_DOPPLER_FACTOR:
@@ -223,16 +282,28 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
break;
case AL_DEFERRED_UPDATES_SOFT:
- value = (ALfloat)context->DeferUpdates;
+ if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
+ value = (ALfloat)AL_TRUE;
+ break;
+
+ case AL_GAIN_LIMIT_SOFT:
+ value = GAIN_MIX_MAX/context->GainBoost;
+ break;
+
+ case AL_NUM_RESAMPLERS_SOFT:
+ value = (ALfloat)(ResamplerMax + 1);
+ break;
+
+ case AL_DEFAULT_RESAMPLER_SOFT:
+ value = (ALfloat)ResamplerDefault;
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
-
return value;
}
@@ -244,6 +315,7 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
context = GetContextRef();
if(!context) return 0;
+ almtx_lock(&context->PropLock);
switch(pname)
{
case AL_DOPPLER_FACTOR:
@@ -263,16 +335,28 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
break;
case AL_DEFERRED_UPDATES_SOFT:
- value = (ALint)context->DeferUpdates;
+ if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
+ value = (ALint)AL_TRUE;
+ break;
+
+ case AL_GAIN_LIMIT_SOFT:
+ value = (ALint)(GAIN_MIX_MAX/context->GainBoost);
+ break;
+
+ case AL_NUM_RESAMPLERS_SOFT:
+ value = ResamplerMax + 1;
+ break;
+
+ case AL_DEFAULT_RESAMPLER_SOFT:
+ value = ResamplerDefault;
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
-
return value;
}
@@ -284,6 +368,7 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
context = GetContextRef();
if(!context) return 0;
+ almtx_lock(&context->PropLock);
switch(pname)
{
case AL_DOPPLER_FACTOR:
@@ -303,16 +388,56 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
break;
case AL_DEFERRED_UPDATES_SOFT:
- value = (ALint64SOFT)context->DeferUpdates;
+ if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
+ value = (ALint64SOFT)AL_TRUE;
+ break;
+
+ case AL_GAIN_LIMIT_SOFT:
+ value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost);
+ break;
+
+ case AL_NUM_RESAMPLERS_SOFT:
+ value = (ALint64SOFT)(ResamplerMax + 1);
+ break;
+
+ case AL_DEFAULT_RESAMPLER_SOFT:
+ value = (ALint64SOFT)ResamplerDefault;
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
}
+ almtx_unlock(&context->PropLock);
-done:
ALCcontext_DecRef(context);
+ return value;
+}
+
+AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
+{
+ ALCcontext *context;
+ void *value = NULL;
+ context = GetContextRef();
+ if(!context) return NULL;
+
+ almtx_lock(&context->PropLock);
+ switch(pname)
+ {
+ case AL_EVENT_CALLBACK_FUNCTION_SOFT:
+ value = context->EventCb;
+ break;
+
+ case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
+ value = context->EventParam;
+ break;
+
+ default:
+ alSetError(context, AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
+ }
+ almtx_unlock(&context->PropLock);
+
+ ALCcontext_DecRef(context);
return value;
}
@@ -329,6 +454,9 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
+ case AL_GAIN_LIMIT_SOFT:
+ case AL_NUM_RESAMPLERS_SOFT:
+ case AL_DEFAULT_RESAMPLER_SOFT:
values[0] = alGetBoolean(pname);
return;
}
@@ -337,15 +465,14 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
context = GetContextRef();
if(!context) return;
- if(!(values))
- SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ if(!values)
+ alSetError(context, AL_INVALID_VALUE, "NULL pointer");
switch(pname)
{
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
}
-done:
ALCcontext_DecRef(context);
}
@@ -362,6 +489,9 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
+ case AL_GAIN_LIMIT_SOFT:
+ case AL_NUM_RESAMPLERS_SOFT:
+ case AL_DEFAULT_RESAMPLER_SOFT:
values[0] = alGetDouble(pname);
return;
}
@@ -370,15 +500,14 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
context = GetContextRef();
if(!context) return;
- if(!(values))
- SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ if(!values)
+ alSetError(context, AL_INVALID_VALUE, "NULL pointer");
switch(pname)
{
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
}
-done:
ALCcontext_DecRef(context);
}
@@ -395,6 +524,9 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
+ case AL_GAIN_LIMIT_SOFT:
+ case AL_NUM_RESAMPLERS_SOFT:
+ case AL_DEFAULT_RESAMPLER_SOFT:
values[0] = alGetFloat(pname);
return;
}
@@ -403,15 +535,14 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
context = GetContextRef();
if(!context) return;
- if(!(values))
- SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ if(!values)
+ alSetError(context, AL_INVALID_VALUE, "NULL pointer");
switch(pname)
{
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
}
-done:
ALCcontext_DecRef(context);
}
@@ -428,6 +559,9 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
+ case AL_GAIN_LIMIT_SOFT:
+ case AL_NUM_RESAMPLERS_SOFT:
+ case AL_DEFAULT_RESAMPLER_SOFT:
values[0] = alGetInteger(pname);
return;
}
@@ -436,13 +570,14 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
context = GetContextRef();
if(!context) return;
+ if(!values)
+ alSetError(context, AL_INVALID_VALUE, "NULL pointer");
switch(pname)
{
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
}
-done:
ALCcontext_DecRef(context);
}
@@ -459,6 +594,9 @@ AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
case AL_DISTANCE_MODEL:
case AL_SPEED_OF_SOUND:
case AL_DEFERRED_UPDATES_SOFT:
+ case AL_GAIN_LIMIT_SOFT:
+ case AL_NUM_RESAMPLERS_SOFT:
+ case AL_DEFAULT_RESAMPLER_SOFT:
values[0] = alGetInteger64SOFT(pname);
return;
}
@@ -467,13 +605,43 @@ AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
context = GetContextRef();
if(!context) return;
+ if(!values)
+ alSetError(context, AL_INVALID_VALUE, "NULL pointer");
switch(pname)
{
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
+ }
+
+ ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
+{
+ ALCcontext *context;
+
+ if(values)
+ {
+ switch(pname)
+ {
+ case AL_EVENT_CALLBACK_FUNCTION_SOFT:
+ case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
+ values[0] = alGetPointerSOFT(pname);
+ return;
+ }
+ }
+
+ context = GetContextRef();
+ if(!context) return;
+
+ if(!values)
+ alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+ switch(pname)
+ {
+ default:
+ alSetError(context, AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
}
-done:
ALCcontext_DecRef(context);
}
@@ -528,12 +696,10 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
break;
default:
- SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ alSetError(context, AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
}
-done:
ALCcontext_DecRef(context);
-
return value;
}
@@ -545,12 +711,15 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
if(!context) return;
if(!(value >= 0.0f && isfinite(value)))
- SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
- context->DopplerFactor = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ alSetError(context, AL_INVALID_VALUE, "Doppler factor %f out of range", value);
+ else
+ {
+ almtx_lock(&context->PropLock);
+ context->DopplerFactor = value;
+ DO_UPDATEPROPS();
+ almtx_unlock(&context->PropLock);
+ }
-done:
ALCcontext_DecRef(context);
}
@@ -561,13 +730,30 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
context = GetContextRef();
if(!context) return;
- if(!(value >= 0.0f && isfinite(value)))
- SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ if((ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed)&EventType_Deprecated))
+ {
+ static const ALCchar msg[] =
+ "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
+ const ALsizei msglen = (ALsizei)strlen(msg);
+ ALbitfieldSOFT enabledevts;
+ almtx_lock(&context->EventCbLock);
+ enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
+ if((enabledevts&EventType_Deprecated) && context->EventCb)
+ (*context->EventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
+ context->EventParam);
+ almtx_unlock(&context->EventCbLock);
+ }
- context->DopplerVelocity = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ if(!(value >= 0.0f && isfinite(value)))
+ alSetError(context, AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
+ else
+ {
+ almtx_lock(&context->PropLock);
+ context->DopplerVelocity = value;
+ DO_UPDATEPROPS();
+ almtx_unlock(&context->PropLock);
+ }
-done:
ALCcontext_DecRef(context);
}
@@ -579,12 +765,15 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
if(!context) return;
if(!(value > 0.0f && isfinite(value)))
- SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
- context->SpeedOfSound = value;
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ alSetError(context, AL_INVALID_VALUE, "Speed of sound %f out of range", value);
+ else
+ {
+ almtx_lock(&context->PropLock);
+ context->SpeedOfSound = value;
+ DO_UPDATEPROPS();
+ almtx_unlock(&context->PropLock);
+ }
-done:
ALCcontext_DecRef(context);
}
@@ -599,13 +788,16 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
value == AL_NONE))
- SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
- context->DistanceModel = value;
- if(!context->SourceDistanceModel)
- ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
+ alSetError(context, AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
+ else
+ {
+ almtx_lock(&context->PropLock);
+ context->DistanceModel = value;
+ if(!context->SourceDistanceModel)
+ DO_UPDATEPROPS();
+ almtx_unlock(&context->PropLock);
+ }
-done:
ALCcontext_DecRef(context);
}
@@ -633,3 +825,76 @@ AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
ALCcontext_DecRef(context);
}
+
+
+AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
+{
+ const char *ResamplerNames[] = {
+ alPointResampler, alLinearResampler,
+ alCubicResampler, alBSinc12Resampler,
+ alBSinc24Resampler,
+ };
+ const ALchar *value = NULL;
+ ALCcontext *context;
+
+ static_assert(COUNTOF(ResamplerNames) == ResamplerMax+1, "Incorrect ResamplerNames list");
+
+ context = GetContextRef();
+ if(!context) return NULL;
+
+ switch(pname)
+ {
+ case AL_RESAMPLER_NAME_SOFT:
+ if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
+ SETERR_GOTO(context, AL_INVALID_VALUE, done, "Resampler name index %d out of range",
+ index);
+ value = ResamplerNames[index];
+ break;
+
+ default:
+ alSetError(context, AL_INVALID_VALUE, "Invalid string indexed property");
+ }
+
+done:
+ ALCcontext_DecRef(context);
+ return value;
+}
+
+
+void UpdateContextProps(ALCcontext *context)
+{
+ struct ALcontextProps *props;
+
+ /* Get an unused proprty container, or allocate a new one as needed. */
+ props = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
+ if(!props)
+ props = al_calloc(16, sizeof(*props));
+ else
+ {
+ struct ALcontextProps *next;
+ do {
+ next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+ } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeContextProps, &props, next,
+ almemory_order_seq_cst, almemory_order_acquire) == 0);
+ }
+
+ /* Copy in current property values. */
+ props->MetersPerUnit = context->MetersPerUnit;
+
+ props->DopplerFactor = context->DopplerFactor;
+ props->DopplerVelocity = context->DopplerVelocity;
+ props->SpeedOfSound = context->SpeedOfSound;
+
+ props->SourceDistanceModel = context->SourceDistanceModel;
+ props->DistanceModel = context->DistanceModel;
+
+ /* Set the new container for updating internal parameters. */
+ props = ATOMIC_EXCHANGE_PTR(&context->Update, props, almemory_order_acq_rel);
+ if(props)
+ {
+ /* If there was an unused update container, put it back in the
+ * freelist.
+ */
+ ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &context->FreeContextProps, props);
+ }
+}