Update the context state properties separately
[openal-soft.git] / OpenAL32 / alState.c
blob86534efb1a1182d66158763d77dc88247b24a0aa
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 alSinc4Resampler[] = "3rd order Sinc";
54 static const ALchar alBSinc12Resampler[] = "11th order Sinc";
55 static const ALchar alBSinc24Resampler[] = "23rd order Sinc";
57 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
59 ALCcontext *context;
61 context = GetContextRef();
62 if(!context) return;
64 WriteLock(&context->PropLock);
65 switch(capability)
67 case AL_SOURCE_DISTANCE_MODEL:
68 context->SourceDistanceModel = AL_TRUE;
69 break;
71 default:
72 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
74 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
75 UpdateContextProps(context);
77 done:
78 WriteUnlock(&context->PropLock);
79 ALCcontext_DecRef(context);
82 AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
84 ALCcontext *context;
86 context = GetContextRef();
87 if(!context) return;
89 WriteLock(&context->PropLock);
90 switch(capability)
92 case AL_SOURCE_DISTANCE_MODEL:
93 context->SourceDistanceModel = AL_FALSE;
94 break;
96 default:
97 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
99 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
100 UpdateContextProps(context);
102 done:
103 WriteUnlock(&context->PropLock);
104 ALCcontext_DecRef(context);
107 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
109 ALCcontext *context;
110 ALboolean value=AL_FALSE;
112 context = GetContextRef();
113 if(!context) return AL_FALSE;
115 switch(capability)
117 case AL_SOURCE_DISTANCE_MODEL:
118 value = context->SourceDistanceModel;
119 break;
121 default:
122 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
125 done:
126 ALCcontext_DecRef(context);
128 return value;
131 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
133 ALCcontext *context;
134 ALboolean value=AL_FALSE;
136 context = GetContextRef();
137 if(!context) return AL_FALSE;
139 switch(pname)
141 case AL_DOPPLER_FACTOR:
142 if(context->DopplerFactor != 0.0f)
143 value = AL_TRUE;
144 break;
146 case AL_DOPPLER_VELOCITY:
147 if(context->DopplerVelocity != 0.0f)
148 value = AL_TRUE;
149 break;
151 case AL_DISTANCE_MODEL:
152 if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
153 value = AL_TRUE;
154 break;
156 case AL_SPEED_OF_SOUND:
157 if(context->SpeedOfSound != 0.0f)
158 value = AL_TRUE;
159 break;
161 case AL_DEFERRED_UPDATES_SOFT:
162 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
163 value = AL_TRUE;
164 break;
166 case AL_GAIN_LIMIT_SOFT:
167 if(GAIN_MIX_MAX/context->GainBoost != 0.0f)
168 value = AL_TRUE;
169 break;
171 case AL_NUM_RESAMPLERS_SOFT:
172 /* Always non-0. */
173 value = AL_TRUE;
174 break;
176 case AL_DEFAULT_RESAMPLER_SOFT:
177 value = ResamplerDefault ? AL_TRUE : AL_FALSE;
178 break;
180 default:
181 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
184 done:
185 ALCcontext_DecRef(context);
187 return value;
190 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
192 ALCcontext *context;
193 ALdouble value = 0.0;
195 context = GetContextRef();
196 if(!context) return 0.0;
198 switch(pname)
200 case AL_DOPPLER_FACTOR:
201 value = (ALdouble)context->DopplerFactor;
202 break;
204 case AL_DOPPLER_VELOCITY:
205 value = (ALdouble)context->DopplerVelocity;
206 break;
208 case AL_DISTANCE_MODEL:
209 value = (ALdouble)context->DistanceModel;
210 break;
212 case AL_SPEED_OF_SOUND:
213 value = (ALdouble)context->SpeedOfSound;
214 break;
216 case AL_DEFERRED_UPDATES_SOFT:
217 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
218 value = (ALdouble)AL_TRUE;
219 break;
221 case AL_GAIN_LIMIT_SOFT:
222 value = (ALdouble)GAIN_MIX_MAX/context->GainBoost;
223 break;
225 case AL_NUM_RESAMPLERS_SOFT:
226 value = (ALdouble)(ResamplerMax + 1);
227 break;
229 case AL_DEFAULT_RESAMPLER_SOFT:
230 value = (ALdouble)ResamplerDefault;
231 break;
233 default:
234 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
237 done:
238 ALCcontext_DecRef(context);
240 return value;
243 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
245 ALCcontext *context;
246 ALfloat value = 0.0f;
248 context = GetContextRef();
249 if(!context) return 0.0f;
251 switch(pname)
253 case AL_DOPPLER_FACTOR:
254 value = context->DopplerFactor;
255 break;
257 case AL_DOPPLER_VELOCITY:
258 value = context->DopplerVelocity;
259 break;
261 case AL_DISTANCE_MODEL:
262 value = (ALfloat)context->DistanceModel;
263 break;
265 case AL_SPEED_OF_SOUND:
266 value = context->SpeedOfSound;
267 break;
269 case AL_DEFERRED_UPDATES_SOFT:
270 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
271 value = (ALfloat)AL_TRUE;
272 break;
274 case AL_GAIN_LIMIT_SOFT:
275 value = GAIN_MIX_MAX/context->GainBoost;
276 break;
278 case AL_NUM_RESAMPLERS_SOFT:
279 value = (ALfloat)(ResamplerMax + 1);
280 break;
282 case AL_DEFAULT_RESAMPLER_SOFT:
283 value = (ALfloat)ResamplerDefault;
284 break;
286 default:
287 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
290 done:
291 ALCcontext_DecRef(context);
293 return value;
296 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
298 ALCcontext *context;
299 ALint value = 0;
301 context = GetContextRef();
302 if(!context) return 0;
304 switch(pname)
306 case AL_DOPPLER_FACTOR:
307 value = (ALint)context->DopplerFactor;
308 break;
310 case AL_DOPPLER_VELOCITY:
311 value = (ALint)context->DopplerVelocity;
312 break;
314 case AL_DISTANCE_MODEL:
315 value = (ALint)context->DistanceModel;
316 break;
318 case AL_SPEED_OF_SOUND:
319 value = (ALint)context->SpeedOfSound;
320 break;
322 case AL_DEFERRED_UPDATES_SOFT:
323 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
324 value = (ALint)AL_TRUE;
325 break;
327 case AL_GAIN_LIMIT_SOFT:
328 value = (ALint)(GAIN_MIX_MAX/context->GainBoost);
329 break;
331 case AL_NUM_RESAMPLERS_SOFT:
332 value = ResamplerMax + 1;
333 break;
335 case AL_DEFAULT_RESAMPLER_SOFT:
336 value = ResamplerDefault;
337 break;
339 default:
340 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
343 done:
344 ALCcontext_DecRef(context);
346 return value;
349 AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
351 ALCcontext *context;
352 ALint64SOFT value = 0;
354 context = GetContextRef();
355 if(!context) return 0;
357 switch(pname)
359 case AL_DOPPLER_FACTOR:
360 value = (ALint64SOFT)context->DopplerFactor;
361 break;
363 case AL_DOPPLER_VELOCITY:
364 value = (ALint64SOFT)context->DopplerVelocity;
365 break;
367 case AL_DISTANCE_MODEL:
368 value = (ALint64SOFT)context->DistanceModel;
369 break;
371 case AL_SPEED_OF_SOUND:
372 value = (ALint64SOFT)context->SpeedOfSound;
373 break;
375 case AL_DEFERRED_UPDATES_SOFT:
376 if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
377 value = (ALint64SOFT)AL_TRUE;
378 break;
380 case AL_GAIN_LIMIT_SOFT:
381 value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost);
382 break;
384 case AL_NUM_RESAMPLERS_SOFT:
385 value = (ALint64SOFT)(ResamplerMax + 1);
386 break;
388 case AL_DEFAULT_RESAMPLER_SOFT:
389 value = (ALint64SOFT)ResamplerDefault;
390 break;
392 default:
393 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
396 done:
397 ALCcontext_DecRef(context);
399 return value;
402 AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
404 ALCcontext *context;
406 if(values)
408 switch(pname)
410 case AL_DOPPLER_FACTOR:
411 case AL_DOPPLER_VELOCITY:
412 case AL_DISTANCE_MODEL:
413 case AL_SPEED_OF_SOUND:
414 case AL_DEFERRED_UPDATES_SOFT:
415 case AL_GAIN_LIMIT_SOFT:
416 case AL_NUM_RESAMPLERS_SOFT:
417 case AL_DEFAULT_RESAMPLER_SOFT:
418 values[0] = alGetBoolean(pname);
419 return;
423 context = GetContextRef();
424 if(!context) return;
426 if(!(values))
427 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
428 switch(pname)
430 default:
431 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
434 done:
435 ALCcontext_DecRef(context);
438 AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
440 ALCcontext *context;
442 if(values)
444 switch(pname)
446 case AL_DOPPLER_FACTOR:
447 case AL_DOPPLER_VELOCITY:
448 case AL_DISTANCE_MODEL:
449 case AL_SPEED_OF_SOUND:
450 case AL_DEFERRED_UPDATES_SOFT:
451 case AL_GAIN_LIMIT_SOFT:
452 case AL_NUM_RESAMPLERS_SOFT:
453 case AL_DEFAULT_RESAMPLER_SOFT:
454 values[0] = alGetDouble(pname);
455 return;
459 context = GetContextRef();
460 if(!context) return;
462 if(!(values))
463 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
464 switch(pname)
466 default:
467 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
470 done:
471 ALCcontext_DecRef(context);
474 AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
476 ALCcontext *context;
478 if(values)
480 switch(pname)
482 case AL_DOPPLER_FACTOR:
483 case AL_DOPPLER_VELOCITY:
484 case AL_DISTANCE_MODEL:
485 case AL_SPEED_OF_SOUND:
486 case AL_DEFERRED_UPDATES_SOFT:
487 case AL_GAIN_LIMIT_SOFT:
488 case AL_NUM_RESAMPLERS_SOFT:
489 case AL_DEFAULT_RESAMPLER_SOFT:
490 values[0] = alGetFloat(pname);
491 return;
495 context = GetContextRef();
496 if(!context) return;
498 if(!(values))
499 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
500 switch(pname)
502 default:
503 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
506 done:
507 ALCcontext_DecRef(context);
510 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
512 ALCcontext *context;
514 if(values)
516 switch(pname)
518 case AL_DOPPLER_FACTOR:
519 case AL_DOPPLER_VELOCITY:
520 case AL_DISTANCE_MODEL:
521 case AL_SPEED_OF_SOUND:
522 case AL_DEFERRED_UPDATES_SOFT:
523 case AL_GAIN_LIMIT_SOFT:
524 case AL_NUM_RESAMPLERS_SOFT:
525 case AL_DEFAULT_RESAMPLER_SOFT:
526 values[0] = alGetInteger(pname);
527 return;
531 context = GetContextRef();
532 if(!context) return;
534 switch(pname)
536 default:
537 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
540 done:
541 ALCcontext_DecRef(context);
544 AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
546 ALCcontext *context;
548 if(values)
550 switch(pname)
552 case AL_DOPPLER_FACTOR:
553 case AL_DOPPLER_VELOCITY:
554 case AL_DISTANCE_MODEL:
555 case AL_SPEED_OF_SOUND:
556 case AL_DEFERRED_UPDATES_SOFT:
557 case AL_GAIN_LIMIT_SOFT:
558 case AL_NUM_RESAMPLERS_SOFT:
559 case AL_DEFAULT_RESAMPLER_SOFT:
560 values[0] = alGetInteger64SOFT(pname);
561 return;
565 context = GetContextRef();
566 if(!context) return;
568 switch(pname)
570 default:
571 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
574 done:
575 ALCcontext_DecRef(context);
578 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
580 const ALchar *value = NULL;
581 ALCcontext *context;
583 context = GetContextRef();
584 if(!context) return NULL;
586 switch(pname)
588 case AL_VENDOR:
589 value = alVendor;
590 break;
592 case AL_VERSION:
593 value = alVersion;
594 break;
596 case AL_RENDERER:
597 value = alRenderer;
598 break;
600 case AL_EXTENSIONS:
601 value = context->ExtensionList;
602 break;
604 case AL_NO_ERROR:
605 value = alNoError;
606 break;
608 case AL_INVALID_NAME:
609 value = alErrInvalidName;
610 break;
612 case AL_INVALID_ENUM:
613 value = alErrInvalidEnum;
614 break;
616 case AL_INVALID_VALUE:
617 value = alErrInvalidValue;
618 break;
620 case AL_INVALID_OPERATION:
621 value = alErrInvalidOp;
622 break;
624 case AL_OUT_OF_MEMORY:
625 value = alErrOutOfMemory;
626 break;
628 default:
629 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
632 done:
633 ALCcontext_DecRef(context);
635 return value;
638 AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
640 ALCcontext *context;
642 context = GetContextRef();
643 if(!context) return;
645 if(!(value >= 0.0f && isfinite(value)))
646 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
648 WriteLock(&context->PropLock);
649 context->DopplerFactor = value;
650 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
651 UpdateContextProps(context);
652 WriteUnlock(&context->PropLock);
654 done:
655 ALCcontext_DecRef(context);
658 AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
660 ALCcontext *context;
662 context = GetContextRef();
663 if(!context) return;
665 if(!(value >= 0.0f && isfinite(value)))
666 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
668 WriteLock(&context->PropLock);
669 context->DopplerVelocity = value;
670 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
671 UpdateContextProps(context);
672 WriteUnlock(&context->PropLock);
674 done:
675 ALCcontext_DecRef(context);
678 AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
680 ALCcontext *context;
682 context = GetContextRef();
683 if(!context) return;
685 if(!(value > 0.0f && isfinite(value)))
686 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
688 WriteLock(&context->PropLock);
689 context->SpeedOfSound = value;
690 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
691 UpdateContextProps(context);
692 WriteUnlock(&context->PropLock);
694 done:
695 ALCcontext_DecRef(context);
698 AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
700 ALCcontext *context;
702 context = GetContextRef();
703 if(!context) return;
705 if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
706 value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
707 value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
708 value == AL_NONE))
709 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
711 WriteLock(&context->PropLock);
712 context->DistanceModel = value;
713 if(!context->SourceDistanceModel)
715 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
716 UpdateContextProps(context);
718 WriteUnlock(&context->PropLock);
720 done:
721 ALCcontext_DecRef(context);
725 AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
727 ALCcontext *context;
729 context = GetContextRef();
730 if(!context) return;
732 ALCcontext_DeferUpdates(context);
734 ALCcontext_DecRef(context);
737 AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
739 ALCcontext *context;
741 context = GetContextRef();
742 if(!context) return;
744 ALCcontext_ProcessUpdates(context);
746 ALCcontext_DecRef(context);
750 AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
752 const char *ResamplerNames[] = {
753 alPointResampler, alLinearResampler,
754 alSinc4Resampler, alBSinc12Resampler,
755 alBSinc24Resampler,
757 const ALchar *value = NULL;
758 ALCcontext *context;
760 static_assert(COUNTOF(ResamplerNames) == ResamplerMax+1, "Incorrect ResamplerNames list");
762 context = GetContextRef();
763 if(!context) return NULL;
765 switch(pname)
767 case AL_RESAMPLER_NAME_SOFT:
768 if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
769 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
770 value = ResamplerNames[index];
771 break;
773 default:
774 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
777 done:
778 ALCcontext_DecRef(context);
780 return value;
784 void UpdateContextProps(ALCcontext *context)
786 struct ALcontextProps *props;
788 /* Get an unused proprty container, or allocate a new one as needed. */
789 props = ATOMIC_LOAD(&context->FreeList, almemory_order_acquire);
790 if(!props)
791 props = al_calloc(16, sizeof(*props));
792 else
794 struct ALcontextProps *next;
795 do {
796 next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
797 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeList, &props, next,
798 almemory_order_seq_cst, almemory_order_acquire) == 0);
801 /* Copy in current property values. */
802 props->MetersPerUnit = context->MetersPerUnit;
804 props->DopplerFactor = context->DopplerFactor;
805 props->DopplerVelocity = context->DopplerVelocity;
806 props->SpeedOfSound = context->SpeedOfSound;
808 props->SourceDistanceModel = context->SourceDistanceModel;
809 props->DistanceModel = context->DistanceModel;
811 /* Set the new container for updating internal parameters. */
812 props = ATOMIC_EXCHANGE_PTR(&context->Update, props, almemory_order_acq_rel);
813 if(props)
815 /* If there was an unused update container, put it back in the
816 * freelist.
818 ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &context->FreeList, props);