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
32 #include "alc/context.h"
35 #include "core/except.h"
36 #include "opthelpers.h"
41 inline void UpdateProps(ALCcontext
*context
)
43 if(!context
->mDeferUpdates
)
45 UpdateContextProps(context
);
48 context
->mPropsDirty
= true;
52 inline void CommitAndUpdateProps(ALCcontext
*context
)
54 if(!context
->mDeferUpdates
)
56 if(context
->has_eax())
58 context
->mHoldUpdates
.store(true, std::memory_order_release
);
59 while((context
->mUpdateCount
.load(std::memory_order_acquire
)&1) != 0) {
63 context
->eax_commit_and_update_sources();
65 UpdateContextProps(context
);
66 context
->mHoldUpdates
.store(false, std::memory_order_release
);
69 context
->mPropsDirty
= true;
74 inline void CommitAndUpdateProps(ALCcontext
*context
)
75 { UpdateProps(context
); }
80 AL_API
void AL_APIENTRY
alListenerf(ALenum param
, ALfloat value
)
83 ContextRef context
{GetContextRef()};
84 if(!context
) [[unlikely
]] return;
86 ALlistener
&listener
= context
->mListener
;
87 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
91 if(!(value
>= 0.0f
&& std::isfinite(value
)))
92 return context
->setError(AL_INVALID_VALUE
, "Listener gain out of range");
93 listener
.Gain
= value
;
94 UpdateProps(context
.get());
97 case AL_METERS_PER_UNIT
:
98 if(!(value
>= AL_MIN_METERS_PER_UNIT
&& value
<= AL_MAX_METERS_PER_UNIT
))
99 return context
->setError(AL_INVALID_VALUE
, "Listener meters per unit out of range");
100 listener
.mMetersPerUnit
= value
;
101 UpdateProps(context
.get());
105 context
->setError(AL_INVALID_ENUM
, "Invalid listener float property");
110 AL_API
void AL_APIENTRY
alListener3f(ALenum param
, ALfloat value1
, ALfloat value2
, ALfloat value3
)
113 ContextRef context
{GetContextRef()};
114 if(!context
) [[unlikely
]] return;
116 ALlistener
&listener
= context
->mListener
;
117 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
121 if(!(std::isfinite(value1
) && std::isfinite(value2
) && std::isfinite(value3
)))
122 return context
->setError(AL_INVALID_VALUE
, "Listener position out of range");
123 listener
.Position
[0] = value1
;
124 listener
.Position
[1] = value2
;
125 listener
.Position
[2] = value3
;
126 CommitAndUpdateProps(context
.get());
130 if(!(std::isfinite(value1
) && std::isfinite(value2
) && std::isfinite(value3
)))
131 return context
->setError(AL_INVALID_VALUE
, "Listener velocity out of range");
132 listener
.Velocity
[0] = value1
;
133 listener
.Velocity
[1] = value2
;
134 listener
.Velocity
[2] = value3
;
135 CommitAndUpdateProps(context
.get());
139 context
->setError(AL_INVALID_ENUM
, "Invalid listener 3-float property");
144 AL_API
void AL_APIENTRY
alListenerfv(ALenum param
, const ALfloat
*values
)
152 case AL_METERS_PER_UNIT
:
153 alListenerf(param
, values
[0]);
158 alListener3f(param
, values
[0], values
[1], values
[2]);
163 ContextRef context
{GetContextRef()};
164 if(!context
) [[unlikely
]] return;
166 if(!values
) [[unlikely
]]
167 return context
->setError(AL_INVALID_VALUE
, "NULL pointer");
169 ALlistener
&listener
= context
->mListener
;
170 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
174 if(!(std::isfinite(values
[0]) && std::isfinite(values
[1]) && std::isfinite(values
[2]) &&
175 std::isfinite(values
[3]) && std::isfinite(values
[4]) && std::isfinite(values
[5])))
176 return context
->setError(AL_INVALID_VALUE
, "Listener orientation out of range");
178 listener
.OrientAt
[0] = values
[0];
179 listener
.OrientAt
[1] = values
[1];
180 listener
.OrientAt
[2] = values
[2];
181 listener
.OrientUp
[0] = values
[3];
182 listener
.OrientUp
[1] = values
[4];
183 listener
.OrientUp
[2] = values
[5];
184 CommitAndUpdateProps(context
.get());
188 context
->setError(AL_INVALID_ENUM
, "Invalid listener float-vector property");
194 AL_API
void AL_APIENTRY
alListeneri(ALenum param
, ALint
/*value*/)
197 ContextRef context
{GetContextRef()};
198 if(!context
) [[unlikely
]] return;
200 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
204 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer property");
209 AL_API
void AL_APIENTRY
alListener3i(ALenum param
, ALint value1
, ALint value2
, ALint value3
)
216 alListener3f(param
, static_cast<ALfloat
>(value1
), static_cast<ALfloat
>(value2
),
217 static_cast<ALfloat
>(value3
));
221 ContextRef context
{GetContextRef()};
222 if(!context
) [[unlikely
]] return;
224 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
228 context
->setError(AL_INVALID_ENUM
, "Invalid listener 3-integer property");
233 AL_API
void AL_APIENTRY
alListeneriv(ALenum param
, const ALint
*values
)
243 alListener3f(param
, static_cast<ALfloat
>(values
[0]), static_cast<ALfloat
>(values
[1]),
244 static_cast<ALfloat
>(values
[2]));
248 fvals
[0] = static_cast<ALfloat
>(values
[0]);
249 fvals
[1] = static_cast<ALfloat
>(values
[1]);
250 fvals
[2] = static_cast<ALfloat
>(values
[2]);
251 fvals
[3] = static_cast<ALfloat
>(values
[3]);
252 fvals
[4] = static_cast<ALfloat
>(values
[4]);
253 fvals
[5] = static_cast<ALfloat
>(values
[5]);
254 alListenerfv(param
, fvals
);
259 ContextRef context
{GetContextRef()};
260 if(!context
) [[unlikely
]] return;
262 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
263 if(!values
) [[unlikely
]]
264 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
268 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer-vector property");
274 AL_API
void AL_APIENTRY
alGetListenerf(ALenum param
, ALfloat
*value
)
277 ContextRef context
{GetContextRef()};
278 if(!context
) [[unlikely
]] return;
280 ALlistener
&listener
= context
->mListener
;
281 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
283 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
287 *value
= listener
.Gain
;
290 case AL_METERS_PER_UNIT
:
291 *value
= listener
.mMetersPerUnit
;
295 context
->setError(AL_INVALID_ENUM
, "Invalid listener float property");
300 AL_API
void AL_APIENTRY
alGetListener3f(ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
303 ContextRef context
{GetContextRef()};
304 if(!context
) [[unlikely
]] return;
306 ALlistener
&listener
= context
->mListener
;
307 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
308 if(!value1
|| !value2
|| !value3
)
309 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
313 *value1
= listener
.Position
[0];
314 *value2
= listener
.Position
[1];
315 *value3
= listener
.Position
[2];
319 *value1
= listener
.Velocity
[0];
320 *value2
= listener
.Velocity
[1];
321 *value3
= listener
.Velocity
[2];
325 context
->setError(AL_INVALID_ENUM
, "Invalid listener 3-float property");
330 AL_API
void AL_APIENTRY
alGetListenerfv(ALenum param
, ALfloat
*values
)
336 case AL_METERS_PER_UNIT
:
337 alGetListenerf(param
, values
);
342 alGetListener3f(param
, values
+0, values
+1, values
+2);
346 ContextRef context
{GetContextRef()};
347 if(!context
) [[unlikely
]] return;
349 ALlistener
&listener
= context
->mListener
;
350 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
352 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
357 values
[0] = listener
.OrientAt
[0];
358 values
[1] = listener
.OrientAt
[1];
359 values
[2] = listener
.OrientAt
[2];
360 values
[3] = listener
.OrientUp
[0];
361 values
[4] = listener
.OrientUp
[1];
362 values
[5] = listener
.OrientUp
[2];
366 context
->setError(AL_INVALID_ENUM
, "Invalid listener float-vector property");
372 AL_API
void AL_APIENTRY
alGetListeneri(ALenum param
, ALint
*value
)
375 ContextRef context
{GetContextRef()};
376 if(!context
) [[unlikely
]] return;
378 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
380 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
384 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer property");
389 AL_API
void AL_APIENTRY
alGetListener3i(ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
392 ContextRef context
{GetContextRef()};
393 if(!context
) [[unlikely
]] return;
395 ALlistener
&listener
= context
->mListener
;
396 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
397 if(!value1
|| !value2
|| !value3
)
398 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
402 *value1
= static_cast<ALint
>(listener
.Position
[0]);
403 *value2
= static_cast<ALint
>(listener
.Position
[1]);
404 *value3
= static_cast<ALint
>(listener
.Position
[2]);
408 *value1
= static_cast<ALint
>(listener
.Velocity
[0]);
409 *value2
= static_cast<ALint
>(listener
.Velocity
[1]);
410 *value3
= static_cast<ALint
>(listener
.Velocity
[2]);
414 context
->setError(AL_INVALID_ENUM
, "Invalid listener 3-integer property");
419 AL_API
void AL_APIENTRY
alGetListeneriv(ALenum param
, ALint
* values
)
426 alGetListener3i(param
, values
+0, values
+1, values
+2);
430 ContextRef context
{GetContextRef()};
431 if(!context
) [[unlikely
]] return;
433 ALlistener
&listener
= context
->mListener
;
434 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
436 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
441 values
[0] = static_cast<ALint
>(listener
.OrientAt
[0]);
442 values
[1] = static_cast<ALint
>(listener
.OrientAt
[1]);
443 values
[2] = static_cast<ALint
>(listener
.OrientAt
[2]);
444 values
[3] = static_cast<ALint
>(listener
.OrientUp
[0]);
445 values
[4] = static_cast<ALint
>(listener
.OrientUp
[1]);
446 values
[5] = static_cast<ALint
>(listener
.OrientUp
[2]);
450 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer-vector property");