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
26 #include "alListener.h"
29 AL_API ALvoid AL_APIENTRY
alListenerf(ALenum param
, ALfloat value
)
33 context
= GetContextRef();
36 WriteLock(&context
->PropLock
);
40 if(!(value
>= 0.0f
&& isfinite(value
)))
41 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
42 context
->Listener
->Gain
= value
;
45 case AL_METERS_PER_UNIT
:
46 if(!(value
>= 0.0f
&& isfinite(value
)))
47 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
48 context
->Listener
->MetersPerUnit
= value
;
52 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
54 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
55 UpdateListenerProps(context
);
58 WriteUnlock(&context
->PropLock
);
59 ALCcontext_DecRef(context
);
63 AL_API ALvoid AL_APIENTRY
alListener3f(ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
67 context
= GetContextRef();
70 WriteLock(&context
->PropLock
);
74 if(!(isfinite(value1
) && isfinite(value2
) && isfinite(value3
)))
75 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
76 context
->Listener
->Position
[0] = value1
;
77 context
->Listener
->Position
[1] = value2
;
78 context
->Listener
->Position
[2] = value3
;
82 if(!(isfinite(value1
) && isfinite(value2
) && isfinite(value3
)))
83 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
84 context
->Listener
->Velocity
[0] = value1
;
85 context
->Listener
->Velocity
[1] = value2
;
86 context
->Listener
->Velocity
[2] = value3
;
90 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
92 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
93 UpdateListenerProps(context
);
96 WriteUnlock(&context
->PropLock
);
97 ALCcontext_DecRef(context
);
101 AL_API ALvoid AL_APIENTRY
alListenerfv(ALenum param
, const ALfloat
*values
)
110 case AL_METERS_PER_UNIT
:
111 alListenerf(param
, values
[0]);
116 alListener3f(param
, values
[0], values
[1], values
[2]);
121 context
= GetContextRef();
124 WriteLock(&context
->PropLock
);
126 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
130 if(!(isfinite(values
[0]) && isfinite(values
[1]) && isfinite(values
[2]) &&
131 isfinite(values
[3]) && isfinite(values
[4]) && isfinite(values
[5])))
132 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
134 context
->Listener
->Forward
[0] = values
[0];
135 context
->Listener
->Forward
[1] = values
[1];
136 context
->Listener
->Forward
[2] = values
[2];
137 context
->Listener
->Up
[0] = values
[3];
138 context
->Listener
->Up
[1] = values
[4];
139 context
->Listener
->Up
[2] = values
[5];
143 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
145 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
146 UpdateListenerProps(context
);
149 WriteUnlock(&context
->PropLock
);
150 ALCcontext_DecRef(context
);
154 AL_API ALvoid AL_APIENTRY
alListeneri(ALenum param
, ALint
UNUSED(value
))
158 context
= GetContextRef();
161 WriteLock(&context
->PropLock
);
165 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
167 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
168 UpdateListenerProps(context
);
171 WriteUnlock(&context
->PropLock
);
172 ALCcontext_DecRef(context
);
176 AL_API
void AL_APIENTRY
alListener3i(ALenum param
, ALint value1
, ALint value2
, ALint value3
)
184 alListener3f(param
, (ALfloat
)value1
, (ALfloat
)value2
, (ALfloat
)value3
);
188 context
= GetContextRef();
191 WriteLock(&context
->PropLock
);
195 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
197 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
198 UpdateListenerProps(context
);
201 WriteUnlock(&context
->PropLock
);
202 ALCcontext_DecRef(context
);
206 AL_API
void AL_APIENTRY
alListeneriv(ALenum param
, const ALint
*values
)
217 alListener3f(param
, (ALfloat
)values
[0], (ALfloat
)values
[1], (ALfloat
)values
[2]);
221 fvals
[0] = (ALfloat
)values
[0];
222 fvals
[1] = (ALfloat
)values
[1];
223 fvals
[2] = (ALfloat
)values
[2];
224 fvals
[3] = (ALfloat
)values
[3];
225 fvals
[4] = (ALfloat
)values
[4];
226 fvals
[5] = (ALfloat
)values
[5];
227 alListenerfv(param
, fvals
);
232 context
= GetContextRef();
235 WriteLock(&context
->PropLock
);
237 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
241 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
243 if(!ATOMIC_LOAD(&context
->DeferUpdates
, almemory_order_acquire
))
244 UpdateListenerProps(context
);
247 WriteUnlock(&context
->PropLock
);
248 ALCcontext_DecRef(context
);
252 AL_API ALvoid AL_APIENTRY
alGetListenerf(ALenum param
, ALfloat
*value
)
256 context
= GetContextRef();
259 ReadLock(&context
->PropLock
);
261 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
265 *value
= context
->Listener
->Gain
;
268 case AL_METERS_PER_UNIT
:
269 *value
= context
->Listener
->MetersPerUnit
;
273 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
277 ReadUnlock(&context
->PropLock
);
278 ALCcontext_DecRef(context
);
282 AL_API ALvoid AL_APIENTRY
alGetListener3f(ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
286 context
= GetContextRef();
289 ReadLock(&context
->PropLock
);
290 if(!(value1
&& value2
&& value3
))
291 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
295 *value1
= context
->Listener
->Position
[0];
296 *value2
= context
->Listener
->Position
[1];
297 *value3
= context
->Listener
->Position
[2];
301 *value1
= context
->Listener
->Velocity
[0];
302 *value2
= context
->Listener
->Velocity
[1];
303 *value3
= context
->Listener
->Velocity
[2];
307 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
311 ReadUnlock(&context
->PropLock
);
312 ALCcontext_DecRef(context
);
316 AL_API ALvoid AL_APIENTRY
alGetListenerfv(ALenum param
, ALfloat
*values
)
323 case AL_METERS_PER_UNIT
:
324 alGetListenerf(param
, values
);
329 alGetListener3f(param
, values
+0, values
+1, values
+2);
333 context
= GetContextRef();
336 ReadLock(&context
->PropLock
);
338 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
343 values
[0] = context
->Listener
->Forward
[0];
344 values
[1] = context
->Listener
->Forward
[1];
345 values
[2] = context
->Listener
->Forward
[2];
346 values
[3] = context
->Listener
->Up
[0];
347 values
[4] = context
->Listener
->Up
[1];
348 values
[5] = context
->Listener
->Up
[2];
352 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
356 ReadUnlock(&context
->PropLock
);
357 ALCcontext_DecRef(context
);
361 AL_API ALvoid AL_APIENTRY
alGetListeneri(ALenum param
, ALint
*value
)
365 context
= GetContextRef();
368 ReadLock(&context
->PropLock
);
370 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
374 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
378 ReadUnlock(&context
->PropLock
);
379 ALCcontext_DecRef(context
);
383 AL_API
void AL_APIENTRY
alGetListener3i(ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
387 context
= GetContextRef();
390 ReadLock(&context
->PropLock
);
391 if(!(value1
&& value2
&& value3
))
392 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
396 *value1
= (ALint
)context
->Listener
->Position
[0];
397 *value2
= (ALint
)context
->Listener
->Position
[1];
398 *value3
= (ALint
)context
->Listener
->Position
[2];
402 *value1
= (ALint
)context
->Listener
->Velocity
[0];
403 *value2
= (ALint
)context
->Listener
->Velocity
[1];
404 *value3
= (ALint
)context
->Listener
->Velocity
[2];
408 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
412 ReadUnlock(&context
->PropLock
);
413 ALCcontext_DecRef(context
);
417 AL_API
void AL_APIENTRY
alGetListeneriv(ALenum param
, ALint
* values
)
425 alGetListener3i(param
, values
+0, values
+1, values
+2);
429 context
= GetContextRef();
432 ReadLock(&context
->PropLock
);
434 SET_ERROR_AND_GOTO(context
, AL_INVALID_VALUE
, done
);
439 values
[0] = (ALint
)context
->Listener
->Forward
[0];
440 values
[1] = (ALint
)context
->Listener
->Forward
[1];
441 values
[2] = (ALint
)context
->Listener
->Forward
[2];
442 values
[3] = (ALint
)context
->Listener
->Up
[0];
443 values
[4] = (ALint
)context
->Listener
->Up
[1];
444 values
[5] = (ALint
)context
->Listener
->Up
[2];
448 SET_ERROR_AND_GOTO(context
, AL_INVALID_ENUM
, done
);
452 ReadUnlock(&context
->PropLock
);
453 ALCcontext_DecRef(context
);
457 void UpdateListenerProps(ALCcontext
*context
)
459 ALlistener
*listener
= context
->Listener
;
460 struct ALlistenerProps
*props
;
462 /* Get an unused proprty container, or allocate a new one as needed. */
463 props
= ATOMIC_LOAD(&listener
->FreeList
, almemory_order_acquire
);
465 props
= al_calloc(16, sizeof(*props
));
468 struct ALlistenerProps
*next
;
470 next
= ATOMIC_LOAD(&props
->next
, almemory_order_relaxed
);
471 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&listener
->FreeList
, &props
, next
,
472 almemory_order_seq_cst
, almemory_order_acquire
) == 0);
475 /* Copy in current property values. */
476 props
->Position
[0] = listener
->Position
[0];
477 props
->Position
[1] = listener
->Position
[1];
478 props
->Position
[2] = listener
->Position
[2];
480 props
->Velocity
[0] = listener
->Velocity
[0];
481 props
->Velocity
[1] = listener
->Velocity
[1];
482 props
->Velocity
[2] = listener
->Velocity
[2];
484 props
->Forward
[0] = listener
->Forward
[0];
485 props
->Forward
[1] = listener
->Forward
[1];
486 props
->Forward
[2] = listener
->Forward
[2];
487 props
->Up
[0] = listener
->Up
[0];
488 props
->Up
[1] = listener
->Up
[1];
489 props
->Up
[2] = listener
->Up
[2];
491 props
->Gain
= listener
->Gain
;
492 props
->MetersPerUnit
= listener
->MetersPerUnit
;
494 props
->DopplerFactor
= context
->DopplerFactor
;
495 props
->DopplerVelocity
= context
->DopplerVelocity
;
496 props
->SpeedOfSound
= context
->SpeedOfSound
;
498 props
->SourceDistanceModel
= context
->SourceDistanceModel
;
499 props
->DistanceModel
= context
->DistanceModel
;;
501 /* Set the new container for updating internal parameters. */
502 props
= ATOMIC_EXCHANGE_PTR(&listener
->Update
, props
, almemory_order_acq_rel
);
505 /* If there was an unused update container, put it back in the
508 ATOMIC_REPLACE_HEAD(struct ALlistenerProps
*, &listener
->FreeList
, props
);