Use a lockless method for updating listener and context properties
[openal-soft.git] / OpenAL32 / alState.c
blob899dacd49fe8e05906a7df0c1e3ce5c77236efcd
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 <stdlib.h>
24 #include "alMain.h"
25 #include "AL/alc.h"
26 #include "AL/al.h"
27 #include "AL/alext.h"
28 #include "alError.h"
29 #include "alListener.h"
30 #include "alSource.h"
31 #include "alAuxEffectSlot.h"
33 #include "backends/base.h"
36 static const ALchar alVendor[] = "OpenAL Community";
37 static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION;
38 static const ALchar alRenderer[] = "OpenAL Soft";
40 // Error Messages
41 static const ALchar alNoError[] = "No Error";
42 static const ALchar alErrInvalidName[] = "Invalid Name";
43 static const ALchar alErrInvalidEnum[] = "Invalid Enum";
44 static const ALchar alErrInvalidValue[] = "Invalid Value";
45 static const ALchar alErrInvalidOp[] = "Invalid Operation";
46 static const ALchar alErrOutOfMemory[] = "Out of Memory";
48 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
50 ALCcontext *context;
52 context = GetContextRef();
53 if(!context) return;
55 switch(capability)
57 case AL_SOURCE_DISTANCE_MODEL:
58 context->SourceDistanceModel = AL_TRUE;
59 break;
61 default:
62 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
64 /* HACK: Force sources to update by doing a listener update */
65 ReadLock(&context->PropLock);
66 UpdateListenerProps(context);
67 ReadUnlock(&context->PropLock);
69 done:
70 ALCcontext_DecRef(context);
73 AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
75 ALCcontext *context;
77 context = GetContextRef();
78 if(!context) return;
80 switch(capability)
82 case AL_SOURCE_DISTANCE_MODEL:
83 context->SourceDistanceModel = AL_FALSE;
84 break;
86 default:
87 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
89 /* HACK: Force sources to update by doing a listener update */
90 ReadLock(&context->PropLock);
91 UpdateListenerProps(context);
92 ReadUnlock(&context->PropLock);
94 done:
95 ALCcontext_DecRef(context);
98 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
100 ALCcontext *context;
101 ALboolean value=AL_FALSE;
103 context = GetContextRef();
104 if(!context) return AL_FALSE;
106 switch(capability)
108 case AL_SOURCE_DISTANCE_MODEL:
109 value = context->SourceDistanceModel;
110 break;
112 default:
113 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
116 done:
117 ALCcontext_DecRef(context);
119 return value;
122 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
124 ALCcontext *context;
125 ALboolean value=AL_FALSE;
127 context = GetContextRef();
128 if(!context) return AL_FALSE;
130 switch(pname)
132 case AL_DOPPLER_FACTOR:
133 if(context->DopplerFactor != 0.0f)
134 value = AL_TRUE;
135 break;
137 case AL_DOPPLER_VELOCITY:
138 if(context->DopplerVelocity != 0.0f)
139 value = AL_TRUE;
140 break;
142 case AL_DISTANCE_MODEL:
143 if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED)
144 value = AL_TRUE;
145 break;
147 case AL_SPEED_OF_SOUND:
148 if(context->SpeedOfSound != 0.0f)
149 value = AL_TRUE;
150 break;
152 case AL_DEFERRED_UPDATES_SOFT:
153 value = context->DeferUpdates;
154 break;
156 default:
157 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
160 done:
161 ALCcontext_DecRef(context);
163 return value;
166 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
168 ALCcontext *context;
169 ALdouble value = 0.0;
171 context = GetContextRef();
172 if(!context) return 0.0;
174 switch(pname)
176 case AL_DOPPLER_FACTOR:
177 value = (ALdouble)context->DopplerFactor;
178 break;
180 case AL_DOPPLER_VELOCITY:
181 value = (ALdouble)context->DopplerVelocity;
182 break;
184 case AL_DISTANCE_MODEL:
185 value = (ALdouble)context->DistanceModel;
186 break;
188 case AL_SPEED_OF_SOUND:
189 value = (ALdouble)context->SpeedOfSound;
190 break;
192 case AL_DEFERRED_UPDATES_SOFT:
193 value = (ALdouble)context->DeferUpdates;
194 break;
196 default:
197 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
200 done:
201 ALCcontext_DecRef(context);
203 return value;
206 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
208 ALCcontext *context;
209 ALfloat value = 0.0f;
211 context = GetContextRef();
212 if(!context) return 0.0f;
214 switch(pname)
216 case AL_DOPPLER_FACTOR:
217 value = context->DopplerFactor;
218 break;
220 case AL_DOPPLER_VELOCITY:
221 value = context->DopplerVelocity;
222 break;
224 case AL_DISTANCE_MODEL:
225 value = (ALfloat)context->DistanceModel;
226 break;
228 case AL_SPEED_OF_SOUND:
229 value = context->SpeedOfSound;
230 break;
232 case AL_DEFERRED_UPDATES_SOFT:
233 value = (ALfloat)context->DeferUpdates;
234 break;
236 default:
237 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
240 done:
241 ALCcontext_DecRef(context);
243 return value;
246 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
248 ALCcontext *context;
249 ALint value = 0;
251 context = GetContextRef();
252 if(!context) return 0;
254 switch(pname)
256 case AL_DOPPLER_FACTOR:
257 value = (ALint)context->DopplerFactor;
258 break;
260 case AL_DOPPLER_VELOCITY:
261 value = (ALint)context->DopplerVelocity;
262 break;
264 case AL_DISTANCE_MODEL:
265 value = (ALint)context->DistanceModel;
266 break;
268 case AL_SPEED_OF_SOUND:
269 value = (ALint)context->SpeedOfSound;
270 break;
272 case AL_DEFERRED_UPDATES_SOFT:
273 value = (ALint)context->DeferUpdates;
274 break;
276 default:
277 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
280 done:
281 ALCcontext_DecRef(context);
283 return value;
286 AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
288 ALCcontext *context;
289 ALint64SOFT value = 0;
291 context = GetContextRef();
292 if(!context) return 0;
294 switch(pname)
296 case AL_DOPPLER_FACTOR:
297 value = (ALint64SOFT)context->DopplerFactor;
298 break;
300 case AL_DOPPLER_VELOCITY:
301 value = (ALint64SOFT)context->DopplerVelocity;
302 break;
304 case AL_DISTANCE_MODEL:
305 value = (ALint64SOFT)context->DistanceModel;
306 break;
308 case AL_SPEED_OF_SOUND:
309 value = (ALint64SOFT)context->SpeedOfSound;
310 break;
312 case AL_DEFERRED_UPDATES_SOFT:
313 value = (ALint64SOFT)context->DeferUpdates;
314 break;
316 default:
317 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
320 done:
321 ALCcontext_DecRef(context);
323 return value;
326 AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
328 ALCcontext *context;
330 if(values)
332 switch(pname)
334 case AL_DOPPLER_FACTOR:
335 case AL_DOPPLER_VELOCITY:
336 case AL_DISTANCE_MODEL:
337 case AL_SPEED_OF_SOUND:
338 case AL_DEFERRED_UPDATES_SOFT:
339 values[0] = alGetBoolean(pname);
340 return;
344 context = GetContextRef();
345 if(!context) return;
347 if(!(values))
348 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
349 switch(pname)
351 default:
352 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
355 done:
356 ALCcontext_DecRef(context);
359 AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
361 ALCcontext *context;
363 if(values)
365 switch(pname)
367 case AL_DOPPLER_FACTOR:
368 case AL_DOPPLER_VELOCITY:
369 case AL_DISTANCE_MODEL:
370 case AL_SPEED_OF_SOUND:
371 case AL_DEFERRED_UPDATES_SOFT:
372 values[0] = alGetDouble(pname);
373 return;
377 context = GetContextRef();
378 if(!context) return;
380 if(!(values))
381 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
382 switch(pname)
384 default:
385 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
388 done:
389 ALCcontext_DecRef(context);
392 AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
394 ALCcontext *context;
396 if(values)
398 switch(pname)
400 case AL_DOPPLER_FACTOR:
401 case AL_DOPPLER_VELOCITY:
402 case AL_DISTANCE_MODEL:
403 case AL_SPEED_OF_SOUND:
404 case AL_DEFERRED_UPDATES_SOFT:
405 values[0] = alGetFloat(pname);
406 return;
410 context = GetContextRef();
411 if(!context) return;
413 if(!(values))
414 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
415 switch(pname)
417 default:
418 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
421 done:
422 ALCcontext_DecRef(context);
425 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
427 ALCcontext *context;
429 if(values)
431 switch(pname)
433 case AL_DOPPLER_FACTOR:
434 case AL_DOPPLER_VELOCITY:
435 case AL_DISTANCE_MODEL:
436 case AL_SPEED_OF_SOUND:
437 case AL_DEFERRED_UPDATES_SOFT:
438 values[0] = alGetInteger(pname);
439 return;
443 context = GetContextRef();
444 if(!context) return;
446 switch(pname)
448 default:
449 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
452 done:
453 ALCcontext_DecRef(context);
456 AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
458 ALCcontext *context;
460 if(values)
462 switch(pname)
464 case AL_DOPPLER_FACTOR:
465 case AL_DOPPLER_VELOCITY:
466 case AL_DISTANCE_MODEL:
467 case AL_SPEED_OF_SOUND:
468 case AL_DEFERRED_UPDATES_SOFT:
469 values[0] = alGetInteger64SOFT(pname);
470 return;
474 context = GetContextRef();
475 if(!context) return;
477 switch(pname)
479 default:
480 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
483 done:
484 ALCcontext_DecRef(context);
487 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
489 const ALchar *value = NULL;
490 ALCcontext *context;
492 context = GetContextRef();
493 if(!context) return NULL;
495 switch(pname)
497 case AL_VENDOR:
498 value = alVendor;
499 break;
501 case AL_VERSION:
502 value = alVersion;
503 break;
505 case AL_RENDERER:
506 value = alRenderer;
507 break;
509 case AL_EXTENSIONS:
510 value = context->ExtensionList;
511 break;
513 case AL_NO_ERROR:
514 value = alNoError;
515 break;
517 case AL_INVALID_NAME:
518 value = alErrInvalidName;
519 break;
521 case AL_INVALID_ENUM:
522 value = alErrInvalidEnum;
523 break;
525 case AL_INVALID_VALUE:
526 value = alErrInvalidValue;
527 break;
529 case AL_INVALID_OPERATION:
530 value = alErrInvalidOp;
531 break;
533 case AL_OUT_OF_MEMORY:
534 value = alErrOutOfMemory;
535 break;
537 default:
538 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
541 done:
542 ALCcontext_DecRef(context);
544 return value;
547 AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
549 ALCcontext *context;
551 context = GetContextRef();
552 if(!context) return;
554 if(!(value >= 0.0f && isfinite(value)))
555 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
557 WriteLock(&context->PropLock);
558 context->DopplerFactor = value;
559 UpdateListenerProps(context);
560 WriteUnlock(&context->PropLock);
562 done:
563 ALCcontext_DecRef(context);
566 AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
568 ALCcontext *context;
570 context = GetContextRef();
571 if(!context) return;
573 if(!(value >= 0.0f && isfinite(value)))
574 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
576 WriteLock(&context->PropLock);
577 context->DopplerVelocity = value;
578 UpdateListenerProps(context);
579 WriteUnlock(&context->PropLock);
581 done:
582 ALCcontext_DecRef(context);
585 AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
587 ALCcontext *context;
589 context = GetContextRef();
590 if(!context) return;
592 if(!(value > 0.0f && isfinite(value)))
593 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
595 WriteLock(&context->PropLock);
596 context->SpeedOfSound = value;
597 UpdateListenerProps(context);
598 WriteUnlock(&context->PropLock);
600 done:
601 ALCcontext_DecRef(context);
604 AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
606 ALCcontext *context;
608 context = GetContextRef();
609 if(!context) return;
611 if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
612 value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
613 value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
614 value == AL_NONE))
615 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
617 WriteLock(&context->PropLock);
618 context->DistanceModel = value;
619 if(!context->SourceDistanceModel)
620 UpdateListenerProps(context);
621 WriteUnlock(&context->PropLock);
623 done:
624 ALCcontext_DecRef(context);
628 AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
630 ALCcontext *context;
632 context = GetContextRef();
633 if(!context) return;
635 ALCcontext_DeferUpdates(context);
637 ALCcontext_DecRef(context);
640 AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
642 ALCcontext *context;
644 context = GetContextRef();
645 if(!context) return;
647 ALCcontext_ProcessUpdates(context);
649 ALCcontext_DecRef(context);