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 UNLIKELY(!context
) return;
86 ALlistener
&listener
= context
->mListener
;
87 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
91 if(!(value
>= 0.0f
&& std::isfinite(value
)))
92 SETERR_RETURN(context
, 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 SETERR_RETURN(context
, 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 UNLIKELY(!context
) 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 SETERR_RETURN(context
, 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 SETERR_RETURN(context
, 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 UNLIKELY(!context
) return;
166 ALlistener
&listener
= context
->mListener
;
167 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
168 if(!values
) SETERR_RETURN(context
, AL_INVALID_VALUE
,, "NULL pointer");
172 if(!(std::isfinite(values
[0]) && std::isfinite(values
[1]) && std::isfinite(values
[2]) &&
173 std::isfinite(values
[3]) && std::isfinite(values
[4]) && std::isfinite(values
[5])))
174 SETERR_RETURN(context
, AL_INVALID_VALUE
,, "Listener orientation out of range");
176 listener
.OrientAt
[0] = values
[0];
177 listener
.OrientAt
[1] = values
[1];
178 listener
.OrientAt
[2] = values
[2];
179 listener
.OrientUp
[0] = values
[3];
180 listener
.OrientUp
[1] = values
[4];
181 listener
.OrientUp
[2] = values
[5];
182 CommitAndUpdateProps(context
.get());
186 context
->setError(AL_INVALID_ENUM
, "Invalid listener float-vector property");
192 AL_API
void AL_APIENTRY
alListeneri(ALenum param
, ALint
/*value*/)
195 ContextRef context
{GetContextRef()};
196 if UNLIKELY(!context
) return;
198 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
202 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer property");
207 AL_API
void AL_APIENTRY
alListener3i(ALenum param
, ALint value1
, ALint value2
, ALint value3
)
214 alListener3f(param
, static_cast<ALfloat
>(value1
), static_cast<ALfloat
>(value2
), static_cast<ALfloat
>(value3
));
218 ContextRef context
{GetContextRef()};
219 if UNLIKELY(!context
) return;
221 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
225 context
->setError(AL_INVALID_ENUM
, "Invalid listener 3-integer property");
230 AL_API
void AL_APIENTRY
alListeneriv(ALenum param
, const ALint
*values
)
240 alListener3f(param
, static_cast<ALfloat
>(values
[0]), static_cast<ALfloat
>(values
[1]), static_cast<ALfloat
>(values
[2]));
244 fvals
[0] = static_cast<ALfloat
>(values
[0]);
245 fvals
[1] = static_cast<ALfloat
>(values
[1]);
246 fvals
[2] = static_cast<ALfloat
>(values
[2]);
247 fvals
[3] = static_cast<ALfloat
>(values
[3]);
248 fvals
[4] = static_cast<ALfloat
>(values
[4]);
249 fvals
[5] = static_cast<ALfloat
>(values
[5]);
250 alListenerfv(param
, fvals
);
255 ContextRef context
{GetContextRef()};
256 if UNLIKELY(!context
) return;
258 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
260 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
264 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer-vector property");
270 AL_API
void AL_APIENTRY
alGetListenerf(ALenum param
, ALfloat
*value
)
273 ContextRef context
{GetContextRef()};
274 if UNLIKELY(!context
) return;
276 ALlistener
&listener
= context
->mListener
;
277 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
279 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
283 *value
= listener
.Gain
;
286 case AL_METERS_PER_UNIT
:
287 *value
= listener
.mMetersPerUnit
;
291 context
->setError(AL_INVALID_ENUM
, "Invalid listener float property");
296 AL_API
void AL_APIENTRY
alGetListener3f(ALenum param
, ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
)
299 ContextRef context
{GetContextRef()};
300 if UNLIKELY(!context
) return;
302 ALlistener
&listener
= context
->mListener
;
303 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
304 if(!value1
|| !value2
|| !value3
)
305 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
309 *value1
= listener
.Position
[0];
310 *value2
= listener
.Position
[1];
311 *value3
= listener
.Position
[2];
315 *value1
= listener
.Velocity
[0];
316 *value2
= listener
.Velocity
[1];
317 *value3
= listener
.Velocity
[2];
321 context
->setError(AL_INVALID_ENUM
, "Invalid listener 3-float property");
326 AL_API
void AL_APIENTRY
alGetListenerfv(ALenum param
, ALfloat
*values
)
332 case AL_METERS_PER_UNIT
:
333 alGetListenerf(param
, values
);
338 alGetListener3f(param
, values
+0, values
+1, values
+2);
342 ContextRef context
{GetContextRef()};
343 if UNLIKELY(!context
) return;
345 ALlistener
&listener
= context
->mListener
;
346 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
348 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
353 values
[0] = listener
.OrientAt
[0];
354 values
[1] = listener
.OrientAt
[1];
355 values
[2] = listener
.OrientAt
[2];
356 values
[3] = listener
.OrientUp
[0];
357 values
[4] = listener
.OrientUp
[1];
358 values
[5] = listener
.OrientUp
[2];
362 context
->setError(AL_INVALID_ENUM
, "Invalid listener float-vector property");
368 AL_API
void AL_APIENTRY
alGetListeneri(ALenum param
, ALint
*value
)
371 ContextRef context
{GetContextRef()};
372 if UNLIKELY(!context
) return;
374 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
376 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
380 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer property");
385 AL_API
void AL_APIENTRY
alGetListener3i(ALenum param
, ALint
*value1
, ALint
*value2
, ALint
*value3
)
388 ContextRef context
{GetContextRef()};
389 if UNLIKELY(!context
) return;
391 ALlistener
&listener
= context
->mListener
;
392 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
393 if(!value1
|| !value2
|| !value3
)
394 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
398 *value1
= static_cast<ALint
>(listener
.Position
[0]);
399 *value2
= static_cast<ALint
>(listener
.Position
[1]);
400 *value3
= static_cast<ALint
>(listener
.Position
[2]);
404 *value1
= static_cast<ALint
>(listener
.Velocity
[0]);
405 *value2
= static_cast<ALint
>(listener
.Velocity
[1]);
406 *value3
= static_cast<ALint
>(listener
.Velocity
[2]);
410 context
->setError(AL_INVALID_ENUM
, "Invalid listener 3-integer property");
415 AL_API
void AL_APIENTRY
alGetListeneriv(ALenum param
, ALint
* values
)
422 alGetListener3i(param
, values
+0, values
+1, values
+2);
426 ContextRef context
{GetContextRef()};
427 if UNLIKELY(!context
) return;
429 ALlistener
&listener
= context
->mListener
;
430 std::lock_guard
<std::mutex
> _
{context
->mPropLock
};
432 context
->setError(AL_INVALID_VALUE
, "NULL pointer");
437 values
[0] = static_cast<ALint
>(listener
.OrientAt
[0]);
438 values
[1] = static_cast<ALint
>(listener
.OrientAt
[1]);
439 values
[2] = static_cast<ALint
>(listener
.OrientAt
[2]);
440 values
[3] = static_cast<ALint
>(listener
.OrientUp
[0]);
441 values
[4] = static_cast<ALint
>(listener
.OrientUp
[1]);
442 values
[5] = static_cast<ALint
>(listener
.OrientUp
[2]);
446 context
->setError(AL_INVALID_ENUM
, "Invalid listener integer-vector property");