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
33 #include "alc/context.h"
34 #include "alc/inprogext.h"
36 #include "direct_defs.h"
38 #include "opthelpers.h"
43 inline void UpdateProps(ALCcontext
*context
)
45 if(!context
->mDeferUpdates
)
47 UpdateContextProps(context
);
50 context
->mPropsDirty
= true;
53 inline void CommitAndUpdateProps(ALCcontext
*context
)
55 if(!context
->mDeferUpdates
)
58 if(context
->eaxNeedsCommit())
60 context
->mPropsDirty
= true;
61 context
->applyAllUpdates();
65 UpdateContextProps(context
);
68 context
->mPropsDirty
= true;
73 AL_API
DECL_FUNC2(void, alListenerf
, ALenum
,param
, ALfloat
,value
)
74 FORCE_ALIGN
void AL_APIENTRY
alListenerfDirect(ALCcontext
*context
, ALenum param
, ALfloat value
) noexcept
76 ALlistener
&listener
= context
->mListener
;
77 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
81 if(!(value
>= 0.0f
&& std::isfinite(value
)))
82 throw al::context_error
{AL_INVALID_VALUE
, "Listener gain out of range"};
83 listener
.Gain
= value
;
87 case AL_METERS_PER_UNIT
:
88 if(!(value
>= AL_MIN_METERS_PER_UNIT
&& value
<= AL_MAX_METERS_PER_UNIT
))
89 throw al::context_error
{AL_INVALID_VALUE
, "Listener meters per unit out of range"};
90 listener
.mMetersPerUnit
= value
;
94 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float property 0x%x", param
};
96 catch(al::context_error
& e
) {
97 context
->setError(e
.errorCode(), "%s", e
.what());
100 AL_API
DECL_FUNC4(void, alListener3f
, ALenum
,param
, ALfloat
,value1
, ALfloat
,value2
, ALfloat
,value3
)
101 FORCE_ALIGN
void AL_APIENTRY
alListener3fDirect(ALCcontext
*context
, ALenum param
, ALfloat value1
,
102 ALfloat value2
, ALfloat value3
) noexcept
104 ALlistener
&listener
= context
->mListener
;
105 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
109 if(!(std::isfinite(value1
) && std::isfinite(value2
) && std::isfinite(value3
)))
110 throw al::context_error
{AL_INVALID_VALUE
, "Listener position out of range"};
111 listener
.Position
[0] = value1
;
112 listener
.Position
[1] = value2
;
113 listener
.Position
[2] = value3
;
114 CommitAndUpdateProps(context
);
118 if(!(std::isfinite(value1
) && std::isfinite(value2
) && std::isfinite(value3
)))
119 throw al::context_error
{AL_INVALID_VALUE
, "Listener velocity out of range"};
120 listener
.Velocity
[0] = value1
;
121 listener
.Velocity
[1] = value2
;
122 listener
.Velocity
[2] = value3
;
123 CommitAndUpdateProps(context
);
126 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-float property 0x%x", param
};
128 catch(al::context_error
& e
) {
129 context
->setError(e
.errorCode(), "%s", e
.what());
132 AL_API
DECL_FUNC2(void, alListenerfv
, ALenum
,param
, const ALfloat
*,values
)
133 FORCE_ALIGN
void AL_APIENTRY
alListenerfvDirect(ALCcontext
*context
, ALenum param
,
134 const ALfloat
*values
) noexcept
137 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
142 case AL_METERS_PER_UNIT
:
143 alListenerfDirect(context
, param
, *values
);
148 auto vals
= al::span
<const float,3>{values
, 3_uz
};
149 alListener3fDirect(context
, param
, vals
[0], vals
[1], vals
[2]);
153 ALlistener
&listener
= context
->mListener
;
154 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
158 auto vals
= al::span
<const float,6>{values
, 6_uz
};
159 if(!std::all_of(vals
.cbegin(), vals
.cend(), [](float f
) { return std::isfinite(f
); }))
160 return context
->setError(AL_INVALID_VALUE
, "Listener orientation out of range");
162 std::copy_n(vals
.cbegin(), 3, listener
.OrientAt
.begin());
163 std::copy_n(vals
.cbegin()+3, 3, listener
.OrientUp
.begin());
164 CommitAndUpdateProps(context
);
167 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float-vector property 0x%x", param
};
169 catch(al::context_error
& e
) {
170 context
->setError(e
.errorCode(), "%s", e
.what());
174 AL_API
DECL_FUNC2(void, alListeneri
, ALenum
,param
, ALint
,value
)
175 FORCE_ALIGN
void AL_APIENTRY
alListeneriDirect(ALCcontext
*context
, ALenum param
, ALint
/*value*/) noexcept
177 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
178 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer property 0x%x", param
};
180 catch(al::context_error
& e
) {
181 context
->setError(e
.errorCode(), "%s", e
.what());
184 AL_API
DECL_FUNC4(void, alListener3i
, ALenum
,param
, ALint
,value1
, ALint
,value2
, ALint
,value3
)
185 FORCE_ALIGN
void AL_APIENTRY
alListener3iDirect(ALCcontext
*context
, ALenum param
, ALint value1
,
186 ALint value2
, ALint value3
) noexcept
192 alListener3fDirect(context
, param
, static_cast<ALfloat
>(value1
),
193 static_cast<ALfloat
>(value2
), static_cast<ALfloat
>(value3
));
197 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
198 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-integer property 0x%x", param
};
200 catch(al::context_error
& e
) {
201 context
->setError(e
.errorCode(), "%s", e
.what());
204 AL_API
DECL_FUNC2(void, alListeneriv
, ALenum
,param
, const ALint
*,values
)
205 FORCE_ALIGN
void AL_APIENTRY
alListenerivDirect(ALCcontext
*context
, ALenum param
,
206 const ALint
*values
) noexcept
209 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
211 al::span
<const ALint
> vals
;
216 vals
= {values
, 3_uz
};
217 alListener3fDirect(context
, param
, static_cast<ALfloat
>(vals
[0]),
218 static_cast<ALfloat
>(vals
[1]), static_cast<ALfloat
>(vals
[2]));
222 vals
= {values
, 6_uz
};
223 const std::array fvals
{static_cast<ALfloat
>(vals
[0]), static_cast<ALfloat
>(vals
[1]),
224 static_cast<ALfloat
>(vals
[2]), static_cast<ALfloat
>(vals
[3]),
225 static_cast<ALfloat
>(vals
[4]), static_cast<ALfloat
>(vals
[5]),
227 alListenerfvDirect(context
, param
, fvals
.data());
231 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
232 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer-vector property 0x%x",
235 catch(al::context_error
& e
) {
236 context
->setError(e
.errorCode(), "%s", e
.what());
240 AL_API
DECL_FUNC2(void, alGetListenerf
, ALenum
,param
, ALfloat
*,value
)
241 FORCE_ALIGN
void AL_APIENTRY
alGetListenerfDirect(ALCcontext
*context
, ALenum param
,
242 ALfloat
*value
) noexcept
245 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
247 ALlistener
&listener
= context
->mListener
;
248 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
251 case AL_GAIN
: *value
= listener
.Gain
; return;
252 case AL_METERS_PER_UNIT
: *value
= listener
.mMetersPerUnit
; return;
254 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float property 0x%x", param
};
256 catch(al::context_error
& e
) {
257 context
->setError(e
.errorCode(), "%s", e
.what());
260 AL_API
DECL_FUNC4(void, alGetListener3f
, ALenum
,param
, ALfloat
*,value1
, ALfloat
*,value2
, ALfloat
*,value3
)
261 FORCE_ALIGN
void AL_APIENTRY
alGetListener3fDirect(ALCcontext
*context
, ALenum param
,
262 ALfloat
*value1
, ALfloat
*value2
, ALfloat
*value3
) noexcept
264 if(!value1
|| !value2
|| !value3
)
265 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
267 ALlistener
&listener
= context
->mListener
;
268 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
272 *value1
= listener
.Position
[0];
273 *value2
= listener
.Position
[1];
274 *value3
= listener
.Position
[2];
278 *value1
= listener
.Velocity
[0];
279 *value2
= listener
.Velocity
[1];
280 *value3
= listener
.Velocity
[2];
283 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-float property 0x%x", param
};
285 catch(al::context_error
& e
) {
286 context
->setError(e
.errorCode(), "%s", e
.what());
289 AL_API
DECL_FUNC2(void, alGetListenerfv
, ALenum
,param
, ALfloat
*,values
)
290 FORCE_ALIGN
void AL_APIENTRY
alGetListenerfvDirect(ALCcontext
*context
, ALenum param
,
291 ALfloat
*values
) noexcept
294 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
299 case AL_METERS_PER_UNIT
:
300 alGetListenerfDirect(context
, param
, values
);
305 auto vals
= al::span
<ALfloat
,3>{values
, 3_uz
};
306 alGetListener3fDirect(context
, param
, &vals
[0], &vals
[1], &vals
[2]);
310 ALlistener
&listener
= context
->mListener
;
311 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
315 al::span
<ALfloat
,6> vals
{values
, 6_uz
};
317 std::copy_n(listener
.OrientAt
.cbegin(), 3, vals
.begin());
318 std::copy_n(listener
.OrientUp
.cbegin(), 3, vals
.begin()+3);
321 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener float-vector property 0x%x", param
};
323 catch(al::context_error
& e
) {
324 context
->setError(e
.errorCode(), "%s", e
.what());
328 AL_API
DECL_FUNC2(void, alGetListeneri
, ALenum
,param
, ALint
*,value
)
329 FORCE_ALIGN
void AL_APIENTRY
alGetListeneriDirect(ALCcontext
*context
, ALenum param
, ALint
*value
) noexcept
331 if(!value
) throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
332 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
333 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer property 0x%x", param
};
335 catch(al::context_error
& e
) {
336 context
->setError(e
.errorCode(), "%s", e
.what());
339 AL_API
DECL_FUNC4(void, alGetListener3i
, ALenum
,param
, ALint
*,value1
, ALint
*,value2
, ALint
*,value3
)
340 FORCE_ALIGN
void AL_APIENTRY
alGetListener3iDirect(ALCcontext
*context
, ALenum param
,
341 ALint
*value1
, ALint
*value2
, ALint
*value3
) noexcept
343 if(!value1
|| !value2
|| !value3
)
344 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
346 ALlistener
&listener
= context
->mListener
;
347 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
351 *value1
= static_cast<ALint
>(listener
.Position
[0]);
352 *value2
= static_cast<ALint
>(listener
.Position
[1]);
353 *value3
= static_cast<ALint
>(listener
.Position
[2]);
357 *value1
= static_cast<ALint
>(listener
.Velocity
[0]);
358 *value2
= static_cast<ALint
>(listener
.Velocity
[1]);
359 *value3
= static_cast<ALint
>(listener
.Velocity
[2]);
362 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener 3-integer property 0x%x", param
};
364 catch(al::context_error
& e
) {
365 context
->setError(e
.errorCode(), "%s", e
.what());
368 AL_API
DECL_FUNC2(void, alGetListeneriv
, ALenum
,param
, ALint
*,values
)
369 FORCE_ALIGN
void AL_APIENTRY
alGetListenerivDirect(ALCcontext
*context
, ALenum param
,
370 ALint
*values
) noexcept
373 throw al::context_error
{AL_INVALID_VALUE
, "NULL pointer"};
379 auto vals
= al::span
<ALint
,3>{values
, 3_uz
};
380 alGetListener3iDirect(context
, param
, &vals
[0], &vals
[1], &vals
[2]);
384 ALlistener
&listener
= context
->mListener
;
385 std::lock_guard
<std::mutex
> proplock
{context
->mPropLock
};
387 static constexpr auto f2i
= [](const float val
) noexcept
{ return static_cast<ALint
>(val
); };
391 auto vals
= al::span
<ALint
,6>{values
, 6_uz
};
393 std::transform(listener
.OrientAt
.cbegin(), listener
.OrientAt
.cend(), vals
.begin(), f2i
);
394 std::transform(listener
.OrientUp
.cbegin(), listener
.OrientUp
.cend(), vals
.begin()+3, f2i
);
397 throw al::context_error
{AL_INVALID_ENUM
, "Invalid listener integer-vector property 0x%x",
400 catch(al::context_error
& e
) {
401 context
->setError(e
.errorCode(), "%s", e
.what());