2007-11-13 18:02:18 -08:00
|
|
|
/**
|
|
|
|
* OpenAL cross platform audio library
|
|
|
|
* Copyright (C) 1999-2000 by authors.
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
2014-08-18 14:11:03 +02:00
|
|
|
* Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2007-11-13 18:02:18 -08:00
|
|
|
* Or go to http://www.gnu.org/copyleft/lgpl.html
|
|
|
|
*/
|
|
|
|
|
2008-01-16 14:09:04 -08:00
|
|
|
#include "config.h"
|
|
|
|
|
2007-11-13 18:02:18 -08:00
|
|
|
#include "alMain.h"
|
|
|
|
#include "AL/alc.h"
|
|
|
|
#include "alError.h"
|
|
|
|
#include "alListener.h"
|
2009-11-25 16:21:47 -08:00
|
|
|
#include "alSource.h"
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_GAIN:
|
|
|
|
if(!(value >= 0.0f && isfinite(value)))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
context->Listener->Gain = value;
|
|
|
|
break;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_METERS_PER_UNIT:
|
2017-08-21 00:27:52 -07:00
|
|
|
if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
|
2013-10-07 09:04:52 -07:00
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
context->Listener->MetersPerUnit = value;
|
|
|
|
break;
|
2012-04-23 21:35:05 -07:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_POSITION:
|
|
|
|
if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2016-05-11 18:40:17 -07:00
|
|
|
context->Listener->Position[0] = value1;
|
|
|
|
context->Listener->Position[1] = value2;
|
|
|
|
context->Listener->Position[2] = value3;
|
2013-10-07 09:04:52 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_VELOCITY:
|
|
|
|
if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
2016-05-11 18:40:17 -07:00
|
|
|
context->Listener->Velocity[0] = value1;
|
|
|
|
context->Listener->Velocity[1] = value2;
|
|
|
|
context->Listener->Velocity[2] = value3;
|
2013-10-07 09:04:52 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
if(values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2012-04-23 21:35:05 -07:00
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_GAIN:
|
|
|
|
case AL_METERS_PER_UNIT:
|
|
|
|
alListenerf(param, values[0]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case AL_POSITION:
|
|
|
|
case AL_VELOCITY:
|
|
|
|
alListener3f(param, values[0], values[1], values[2]);
|
|
|
|
return;
|
2011-06-16 09:14:41 -07:00
|
|
|
}
|
|
|
|
}
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2011-06-16 09:14:41 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
2011-06-16 09:14:41 -07:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_ORIENTATION:
|
|
|
|
if(!(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) &&
|
|
|
|
isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5])))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
/* AT then UP */
|
|
|
|
context->Listener->Forward[0] = values[0];
|
|
|
|
context->Listener->Forward[1] = values[1];
|
|
|
|
context->Listener->Forward[2] = values[2];
|
|
|
|
context->Listener->Up[0] = values[3];
|
|
|
|
context->Listener->Up[1] = values[4];
|
|
|
|
context->Listener->Up[2] = values[5];
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-07 07:44:09 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value))
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_POSITION:
|
|
|
|
case AL_VELOCITY:
|
|
|
|
alListener3f(param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);
|
|
|
|
return;
|
2011-06-16 09:14:41 -07:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
switch(param)
|
2011-06-16 09:14:41 -07:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
if(values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2012-04-23 21:35:05 -07:00
|
|
|
ALfloat fvals[6];
|
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_POSITION:
|
|
|
|
case AL_VELOCITY:
|
|
|
|
alListener3f(param, (ALfloat)values[0], (ALfloat)values[1], (ALfloat)values[2]);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case AL_ORIENTATION:
|
|
|
|
fvals[0] = (ALfloat)values[0];
|
|
|
|
fvals[1] = (ALfloat)values[1];
|
|
|
|
fvals[2] = (ALfloat)values[2];
|
|
|
|
fvals[3] = (ALfloat)values[3];
|
|
|
|
fvals[4] = (ALfloat)values[4];
|
|
|
|
fvals[5] = (ALfloat)values[5];
|
|
|
|
alListenerfv(param, fvals);
|
|
|
|
return;
|
2011-07-11 01:21:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
2011-07-11 01:21:29 -07:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
Provide asynchronous property updates for sources
This necessitates a change in how source updates are handled. Rather than just
being able to update sources when a dependent object state is changed (e.g. a
listener gain change), now all source updates must be proactively provided.
Consequently, apps that do not utilize any deferring (AL_SOFT_defer_updates or
alcSuspendContext/alcProcessContext) may utilize more CPU since it'll be
filling out more update containers for the mixer thread to use.
The upside is that there's less blocking between the app's calling thread and
the mixer thread, particularly for vectors and other multi-value properties
(filters and sends). Deferring behavior when used is also improved, since
updates that shouldn't be applied yet are simply not provided. And when they
are provided, the mixer doesn't have to ignore them, meaning the actual
deferring of a context doesn't have to synchrnously force an update -- the
process call will send any pending updates, which the mixer will apply even if
another deferral occurs before the mixer runs, because it'll still be there
waiting on the next mixer invocation.
There is one slight bug introduced by this commit. When a listener change is
made, or changes to multiple sources while updates are being deferred, it is
possible for the mixer to run while the sources are prepping their updates,
causing some of the source updates to be seen before the other. This will be
fixed in short order.
2016-05-14 23:43:40 -07:00
|
|
|
if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
|
|
|
|
UpdateListenerProps(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
WriteUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(value))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_GAIN:
|
|
|
|
*value = context->Listener->Gain;
|
|
|
|
break;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_METERS_PER_UNIT:
|
|
|
|
*value = context->Listener->MetersPerUnit;
|
|
|
|
break;
|
2007-12-17 19:40:43 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(value1 && value2 && value3))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_POSITION:
|
2016-05-11 18:40:17 -07:00
|
|
|
*value1 = context->Listener->Position[0];
|
|
|
|
*value2 = context->Listener->Position[1];
|
|
|
|
*value3 = context->Listener->Position[2];
|
2013-10-07 09:04:52 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_VELOCITY:
|
2016-05-11 18:40:17 -07:00
|
|
|
*value1 = context->Listener->Velocity[0];
|
|
|
|
*value2 = context->Listener->Velocity[1];
|
|
|
|
*value3 = context->Listener->Velocity[2];
|
2013-10-07 09:04:52 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
switch(param)
|
2011-06-16 09:14:41 -07:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_GAIN:
|
|
|
|
case AL_METERS_PER_UNIT:
|
|
|
|
alGetListenerf(param, values);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case AL_POSITION:
|
|
|
|
case AL_VELOCITY:
|
|
|
|
alGetListener3f(param, values+0, values+1, values+2);
|
|
|
|
return;
|
2011-06-16 09:14:41 -07:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_ORIENTATION:
|
|
|
|
// AT then UP
|
|
|
|
values[0] = context->Listener->Forward[0];
|
|
|
|
values[1] = context->Listener->Forward[1];
|
|
|
|
values[2] = context->Listener->Forward[2];
|
|
|
|
values[3] = context->Listener->Up[0];
|
|
|
|
values[4] = context->Listener->Up[1];
|
|
|
|
values[5] = context->Listener->Up[2];
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(value))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(value1 && value2 && value3))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch (param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_POSITION:
|
2016-05-11 18:40:17 -07:00
|
|
|
*value1 = (ALint)context->Listener->Position[0];
|
|
|
|
*value2 = (ALint)context->Listener->Position[1];
|
|
|
|
*value3 = (ALint)context->Listener->Position[2];
|
2013-10-07 09:04:52 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AL_VELOCITY:
|
2016-05-11 18:40:17 -07:00
|
|
|
*value1 = (ALint)context->Listener->Velocity[0];
|
|
|
|
*value2 = (ALint)context->Listener->Velocity[1];
|
|
|
|
*value3 = (ALint)context->Listener->Velocity[2];
|
2013-10-07 09:04:52 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext *context;
|
2007-11-13 18:02:18 -08:00
|
|
|
|
2012-04-23 21:35:05 -07:00
|
|
|
switch(param)
|
2011-06-16 09:14:41 -07:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_POSITION:
|
|
|
|
case AL_VELOCITY:
|
|
|
|
alGetListener3i(param, values+0, values+1, values+2);
|
|
|
|
return;
|
2011-06-16 09:14:41 -07:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
context = GetContextRef();
|
|
|
|
if(!context) return;
|
2009-08-16 16:02:13 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadLock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
if(!(values))
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
|
|
|
switch(param)
|
2007-11-13 18:02:18 -08:00
|
|
|
{
|
2013-10-07 09:04:52 -07:00
|
|
|
case AL_ORIENTATION:
|
|
|
|
// AT then UP
|
|
|
|
values[0] = (ALint)context->Listener->Forward[0];
|
|
|
|
values[1] = (ALint)context->Listener->Forward[1];
|
|
|
|
values[2] = (ALint)context->Listener->Forward[2];
|
|
|
|
values[3] = (ALint)context->Listener->Up[0];
|
|
|
|
values[4] = (ALint)context->Listener->Up[1];
|
|
|
|
values[5] = (ALint)context->Listener->Up[2];
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
|
|
|
|
2013-10-07 09:04:52 -07:00
|
|
|
done:
|
2016-05-11 18:40:17 -07:00
|
|
|
ReadUnlock(&context->PropLock);
|
2013-10-07 09:04:52 -07:00
|
|
|
ALCcontext_DecRef(context);
|
2007-11-13 18:02:18 -08:00
|
|
|
}
|
2016-05-11 18:40:17 -07:00
|
|
|
|
|
|
|
|
|
|
|
void UpdateListenerProps(ALCcontext *context)
|
|
|
|
{
|
|
|
|
ALlistener *listener = context->Listener;
|
|
|
|
struct ALlistenerProps *props;
|
|
|
|
|
|
|
|
/* Get an unused proprty container, or allocate a new one as needed. */
|
|
|
|
props = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
|
|
|
|
if(!props)
|
|
|
|
props = al_calloc(16, sizeof(*props));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct ALlistenerProps *next;
|
|
|
|
do {
|
|
|
|
next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
|
2017-04-14 17:47:55 -07:00
|
|
|
} while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&listener->FreeList, &props, next,
|
|
|
|
almemory_order_seq_cst, almemory_order_acquire) == 0);
|
2016-05-11 18:40:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy in current property values. */
|
2017-03-08 03:38:28 -08:00
|
|
|
props->Position[0] = listener->Position[0];
|
|
|
|
props->Position[1] = listener->Position[1];
|
|
|
|
props->Position[2] = listener->Position[2];
|
|
|
|
|
|
|
|
props->Velocity[0] = listener->Velocity[0];
|
|
|
|
props->Velocity[1] = listener->Velocity[1];
|
|
|
|
props->Velocity[2] = listener->Velocity[2];
|
|
|
|
|
|
|
|
props->Forward[0] = listener->Forward[0];
|
|
|
|
props->Forward[1] = listener->Forward[1];
|
|
|
|
props->Forward[2] = listener->Forward[2];
|
|
|
|
props->Up[0] = listener->Up[0];
|
|
|
|
props->Up[1] = listener->Up[1];
|
|
|
|
props->Up[2] = listener->Up[2];
|
|
|
|
|
|
|
|
props->Gain = listener->Gain;
|
|
|
|
props->MetersPerUnit = listener->MetersPerUnit;
|
|
|
|
|
|
|
|
props->DopplerFactor = context->DopplerFactor;
|
|
|
|
props->DopplerVelocity = context->DopplerVelocity;
|
|
|
|
props->SpeedOfSound = context->SpeedOfSound;
|
|
|
|
|
|
|
|
props->SourceDistanceModel = context->SourceDistanceModel;
|
|
|
|
props->DistanceModel = context->DistanceModel;;
|
2016-08-23 19:17:17 -07:00
|
|
|
|
2016-05-11 18:40:17 -07:00
|
|
|
/* Set the new container for updating internal parameters. */
|
2017-04-14 17:47:55 -07:00
|
|
|
props = ATOMIC_EXCHANGE_PTR(&listener->Update, props, almemory_order_acq_rel);
|
2016-05-11 18:40:17 -07:00
|
|
|
if(props)
|
|
|
|
{
|
|
|
|
/* If there was an unused update container, put it back in the
|
|
|
|
* freelist.
|
|
|
|
*/
|
2016-12-21 19:58:03 -08:00
|
|
|
ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &listener->FreeList, props);
|
2016-05-11 18:40:17 -07:00
|
|
|
}
|
|
|
|
}
|