]> git.tdb.fi Git - ext/openal.git/blob - al/listener.cpp
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / al / listener.cpp
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.
8  *
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.
13  *
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
19  */
20
21 #include "config.h"
22
23 #include "listener.h"
24
25 #include <cmath>
26 #include <mutex>
27
28 #include "AL/al.h"
29 #include "AL/alc.h"
30 #include "AL/efx.h"
31
32 #include "alc/context.h"
33 #include "almalloc.h"
34 #include "atomic.h"
35 #include "core/except.h"
36 #include "opthelpers.h"
37
38
39 namespace {
40
41 inline void UpdateProps(ALCcontext *context)
42 {
43     if(!context->mDeferUpdates)
44     {
45         UpdateContextProps(context);
46         return;
47     }
48     context->mPropsDirty = true;
49 }
50
51 inline void CommitAndUpdateProps(ALCcontext *context)
52 {
53     if(!context->mDeferUpdates)
54     {
55 #ifdef ALSOFT_EAX
56         if(context->eaxNeedsCommit())
57         {
58             context->mPropsDirty = true;
59             context->applyAllUpdates();
60             return;
61         }
62 #endif
63         UpdateContextProps(context);
64         return;
65     }
66     context->mPropsDirty = true;
67 }
68
69 } // namespace
70
71 AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value)
72 START_API_FUNC
73 {
74     ContextRef context{GetContextRef()};
75     if(!context) UNLIKELY return;
76
77     ALlistener &listener = context->mListener;
78     std::lock_guard<std::mutex> _{context->mPropLock};
79     switch(param)
80     {
81     case AL_GAIN:
82         if(!(value >= 0.0f && std::isfinite(value)))
83             return context->setError(AL_INVALID_VALUE, "Listener gain out of range");
84         listener.Gain = value;
85         UpdateProps(context.get());
86         break;
87
88     case AL_METERS_PER_UNIT:
89         if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
90             return context->setError(AL_INVALID_VALUE, "Listener meters per unit out of range");
91         listener.mMetersPerUnit = value;
92         UpdateProps(context.get());
93         break;
94
95     default:
96         context->setError(AL_INVALID_ENUM, "Invalid listener float property");
97     }
98 }
99 END_API_FUNC
100
101 AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
102 START_API_FUNC
103 {
104     ContextRef context{GetContextRef()};
105     if(!context) UNLIKELY return;
106
107     ALlistener &listener = context->mListener;
108     std::lock_guard<std::mutex> _{context->mPropLock};
109     switch(param)
110     {
111     case AL_POSITION:
112         if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
113             return context->setError(AL_INVALID_VALUE, "Listener position out of range");
114         listener.Position[0] = value1;
115         listener.Position[1] = value2;
116         listener.Position[2] = value3;
117         CommitAndUpdateProps(context.get());
118         break;
119
120     case AL_VELOCITY:
121         if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3)))
122             return context->setError(AL_INVALID_VALUE, "Listener velocity out of range");
123         listener.Velocity[0] = value1;
124         listener.Velocity[1] = value2;
125         listener.Velocity[2] = value3;
126         CommitAndUpdateProps(context.get());
127         break;
128
129     default:
130         context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property");
131     }
132 }
133 END_API_FUNC
134
135 AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
136 START_API_FUNC
137 {
138     if(values)
139     {
140         switch(param)
141         {
142         case AL_GAIN:
143         case AL_METERS_PER_UNIT:
144             alListenerf(param, values[0]);
145             return;
146
147         case AL_POSITION:
148         case AL_VELOCITY:
149             alListener3f(param, values[0], values[1], values[2]);
150             return;
151         }
152     }
153
154     ContextRef context{GetContextRef()};
155     if(!context) UNLIKELY return;
156
157     if(!values) UNLIKELY
158         return context->setError(AL_INVALID_VALUE, "NULL pointer");
159
160     ALlistener &listener = context->mListener;
161     std::lock_guard<std::mutex> _{context->mPropLock};
162     switch(param)
163     {
164     case AL_ORIENTATION:
165         if(!(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) &&
166              std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5])))
167             return context->setError(AL_INVALID_VALUE, "Listener orientation out of range");
168         /* AT then UP */
169         listener.OrientAt[0] = values[0];
170         listener.OrientAt[1] = values[1];
171         listener.OrientAt[2] = values[2];
172         listener.OrientUp[0] = values[3];
173         listener.OrientUp[1] = values[4];
174         listener.OrientUp[2] = values[5];
175         CommitAndUpdateProps(context.get());
176         break;
177
178     default:
179         context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property");
180     }
181 }
182 END_API_FUNC
183
184
185 AL_API void AL_APIENTRY alListeneri(ALenum param, ALint /*value*/)
186 START_API_FUNC
187 {
188     ContextRef context{GetContextRef()};
189     if(!context) UNLIKELY return;
190
191     std::lock_guard<std::mutex> _{context->mPropLock};
192     switch(param)
193     {
194     default:
195         context->setError(AL_INVALID_ENUM, "Invalid listener integer property");
196     }
197 }
198 END_API_FUNC
199
200 AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3)
201 START_API_FUNC
202 {
203     switch(param)
204     {
205     case AL_POSITION:
206     case AL_VELOCITY:
207         alListener3f(param, static_cast<ALfloat>(value1), static_cast<ALfloat>(value2),
208             static_cast<ALfloat>(value3));
209         return;
210     }
211
212     ContextRef context{GetContextRef()};
213     if(!context) UNLIKELY return;
214
215     std::lock_guard<std::mutex> _{context->mPropLock};
216     switch(param)
217     {
218     default:
219         context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property");
220     }
221 }
222 END_API_FUNC
223
224 AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
225 START_API_FUNC
226 {
227     if(values)
228     {
229         ALfloat fvals[6];
230         switch(param)
231         {
232         case AL_POSITION:
233         case AL_VELOCITY:
234             alListener3f(param, static_cast<ALfloat>(values[0]), static_cast<ALfloat>(values[1]),
235                 static_cast<ALfloat>(values[2]));
236             return;
237
238         case AL_ORIENTATION:
239             fvals[0] = static_cast<ALfloat>(values[0]);
240             fvals[1] = static_cast<ALfloat>(values[1]);
241             fvals[2] = static_cast<ALfloat>(values[2]);
242             fvals[3] = static_cast<ALfloat>(values[3]);
243             fvals[4] = static_cast<ALfloat>(values[4]);
244             fvals[5] = static_cast<ALfloat>(values[5]);
245             alListenerfv(param, fvals);
246             return;
247         }
248     }
249
250     ContextRef context{GetContextRef()};
251     if(!context) UNLIKELY return;
252
253     std::lock_guard<std::mutex> _{context->mPropLock};
254     if(!values) UNLIKELY
255         context->setError(AL_INVALID_VALUE, "NULL pointer");
256     else switch(param)
257     {
258     default:
259         context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property");
260     }
261 }
262 END_API_FUNC
263
264
265 AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
266 START_API_FUNC
267 {
268     ContextRef context{GetContextRef()};
269     if(!context) UNLIKELY return;
270
271     ALlistener &listener = context->mListener;
272     std::lock_guard<std::mutex> _{context->mPropLock};
273     if(!value)
274         context->setError(AL_INVALID_VALUE, "NULL pointer");
275     else switch(param)
276     {
277     case AL_GAIN:
278         *value = listener.Gain;
279         break;
280
281     case AL_METERS_PER_UNIT:
282         *value = listener.mMetersPerUnit;
283         break;
284
285     default:
286         context->setError(AL_INVALID_ENUM, "Invalid listener float property");
287     }
288 }
289 END_API_FUNC
290
291 AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
292 START_API_FUNC
293 {
294     ContextRef context{GetContextRef()};
295     if(!context) UNLIKELY return;
296
297     ALlistener &listener = context->mListener;
298     std::lock_guard<std::mutex> _{context->mPropLock};
299     if(!value1 || !value2 || !value3)
300         context->setError(AL_INVALID_VALUE, "NULL pointer");
301     else switch(param)
302     {
303     case AL_POSITION:
304         *value1 = listener.Position[0];
305         *value2 = listener.Position[1];
306         *value3 = listener.Position[2];
307         break;
308
309     case AL_VELOCITY:
310         *value1 = listener.Velocity[0];
311         *value2 = listener.Velocity[1];
312         *value3 = listener.Velocity[2];
313         break;
314
315     default:
316         context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property");
317     }
318 }
319 END_API_FUNC
320
321 AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
322 START_API_FUNC
323 {
324     switch(param)
325     {
326     case AL_GAIN:
327     case AL_METERS_PER_UNIT:
328         alGetListenerf(param, values);
329         return;
330
331     case AL_POSITION:
332     case AL_VELOCITY:
333         alGetListener3f(param, values+0, values+1, values+2);
334         return;
335     }
336
337     ContextRef context{GetContextRef()};
338     if(!context) UNLIKELY return;
339
340     ALlistener &listener = context->mListener;
341     std::lock_guard<std::mutex> _{context->mPropLock};
342     if(!values)
343         context->setError(AL_INVALID_VALUE, "NULL pointer");
344     else switch(param)
345     {
346     case AL_ORIENTATION:
347         // AT then UP
348         values[0] = listener.OrientAt[0];
349         values[1] = listener.OrientAt[1];
350         values[2] = listener.OrientAt[2];
351         values[3] = listener.OrientUp[0];
352         values[4] = listener.OrientUp[1];
353         values[5] = listener.OrientUp[2];
354         break;
355
356     default:
357         context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property");
358     }
359 }
360 END_API_FUNC
361
362
363 AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
364 START_API_FUNC
365 {
366     ContextRef context{GetContextRef()};
367     if(!context) UNLIKELY return;
368
369     std::lock_guard<std::mutex> _{context->mPropLock};
370     if(!value)
371         context->setError(AL_INVALID_VALUE, "NULL pointer");
372     else switch(param)
373     {
374     default:
375         context->setError(AL_INVALID_ENUM, "Invalid listener integer property");
376     }
377 }
378 END_API_FUNC
379
380 AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3)
381 START_API_FUNC
382 {
383     ContextRef context{GetContextRef()};
384     if(!context) UNLIKELY return;
385
386     ALlistener &listener = context->mListener;
387     std::lock_guard<std::mutex> _{context->mPropLock};
388     if(!value1 || !value2 || !value3)
389         context->setError(AL_INVALID_VALUE, "NULL pointer");
390     else switch(param)
391     {
392     case AL_POSITION:
393         *value1 = static_cast<ALint>(listener.Position[0]);
394         *value2 = static_cast<ALint>(listener.Position[1]);
395         *value3 = static_cast<ALint>(listener.Position[2]);
396         break;
397
398     case AL_VELOCITY:
399         *value1 = static_cast<ALint>(listener.Velocity[0]);
400         *value2 = static_cast<ALint>(listener.Velocity[1]);
401         *value3 = static_cast<ALint>(listener.Velocity[2]);
402         break;
403
404     default:
405         context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property");
406     }
407 }
408 END_API_FUNC
409
410 AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
411 START_API_FUNC
412 {
413     switch(param)
414     {
415     case AL_POSITION:
416     case AL_VELOCITY:
417         alGetListener3i(param, values+0, values+1, values+2);
418         return;
419     }
420
421     ContextRef context{GetContextRef()};
422     if(!context) UNLIKELY return;
423
424     ALlistener &listener = context->mListener;
425     std::lock_guard<std::mutex> _{context->mPropLock};
426     if(!values)
427         context->setError(AL_INVALID_VALUE, "NULL pointer");
428     else switch(param)
429     {
430     case AL_ORIENTATION:
431         // AT then UP
432         values[0] = static_cast<ALint>(listener.OrientAt[0]);
433         values[1] = static_cast<ALint>(listener.OrientAt[1]);
434         values[2] = static_cast<ALint>(listener.OrientAt[2]);
435         values[3] = static_cast<ALint>(listener.OrientUp[0]);
436         values[4] = static_cast<ALint>(listener.OrientUp[1]);
437         values[5] = static_cast<ALint>(listener.OrientUp[2]);
438         break;
439
440     default:
441         context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property");
442     }
443 }
444 END_API_FUNC