Use RAII for device references

This commit is contained in:
Chris Robinson 2018-11-23 17:54:12 -08:00
parent df057d4118
commit a7c556f814

View File

@ -2427,39 +2427,82 @@ ALCdevice_struct::~ALCdevice_struct()
}
void ALCdevice_IncRef(ALCdevice *device)
static void ALCdevice_IncRef(ALCdevice *device)
{
auto ref = IncrementRef(&device->ref);
TRACEREF("%p increasing refcount to %u\n", device, ref);
}
void ALCdevice_DecRef(ALCdevice *device)
static void ALCdevice_DecRef(ALCdevice *device)
{
auto ref = DecrementRef(&device->ref);
TRACEREF("%p decreasing refcount to %u\n", device, ref);
if(ref == 0) delete device;
}
/* Simple RAII device reference. Takes the reference of the provided ALCdevice,
* and decrements it when leaving scope. Movable (transfer reference) but not
* copyable (no new references).
*/
class DeviceRef {
ALCdevice *mDev{nullptr};
void reset() noexcept
{
if(mDev)
ALCdevice_DecRef(mDev);
mDev = nullptr;
}
public:
DeviceRef() noexcept = default;
DeviceRef(DeviceRef&& rhs) noexcept : mDev{rhs.mDev}
{ rhs.mDev = nullptr; }
explicit DeviceRef(ALCdevice *dev) noexcept : mDev(dev) { }
~DeviceRef() { reset(); }
DeviceRef& operator=(const DeviceRef&) = delete;
DeviceRef& operator=(DeviceRef&& rhs) noexcept
{
reset();
mDev = rhs.mDev;
rhs.mDev = nullptr;
return *this;
}
operator bool() const noexcept { return mDev != nullptr; }
ALCdevice* operator->() noexcept { return mDev; }
ALCdevice* get() noexcept { return mDev; }
ALCdevice* release() noexcept
{
ALCdevice *ret{mDev};
mDev = nullptr;
return ret;
}
};
/* VerifyDevice
*
* Checks if the device handle is valid, and increments its ref count if so.
* Checks if the device handle is valid, and returns a new reference if so.
*/
static ALCboolean VerifyDevice(ALCdevice **device)
static DeviceRef VerifyDevice(ALCdevice *device)
{
std::lock_guard<std::recursive_mutex> _{ListLock};
ALCdevice *tmpDevice{DeviceList.load()};
while(tmpDevice)
{
if(tmpDevice == *device)
if(tmpDevice == device)
{
ALCdevice_IncRef(tmpDevice);
return ALC_TRUE;
return DeviceRef{tmpDevice};
}
tmpDevice = tmpDevice->next.load(std::memory_order_relaxed);
}
*device = nullptr;
return ALC_FALSE;
return DeviceRef{};
}
@ -2832,20 +2875,12 @@ void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends)
/* alcGetError
*
* Return last ALC generated error code for the given device
*/
*/
ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device)
{
ALCenum errorCode;
if(VerifyDevice(&device))
{
errorCode = device->LastError.exchange(ALC_NO_ERROR);
ALCdevice_DecRef(device);
}
else
errorCode = LastNullDeviceError.exchange(ALC_NO_ERROR);
return errorCode;
DeviceRef dev{VerifyDevice(device)};
if(dev) return dev->LastError.exchange(ALC_NO_ERROR);
return LastNullDeviceError.exchange(ALC_NO_ERROR);
}
@ -2889,6 +2924,7 @@ ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context)
ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param)
{
const ALCchar *value = nullptr;
DeviceRef dev;
switch(param)
{
@ -2921,11 +2957,9 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para
break;
case ALC_ALL_DEVICES_SPECIFIER:
if(VerifyDevice(&Device))
{
value = Device->DeviceName.c_str();
ALCdevice_DecRef(Device);
}
dev = VerifyDevice(Device);
if(dev)
value = dev->DeviceName.c_str();
else
{
ProbeAllDevicesList();
@ -2934,11 +2968,9 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para
break;
case ALC_CAPTURE_DEVICE_SPECIFIER:
if(VerifyDevice(&Device))
{
value = Device->DeviceName.c_str();
ALCdevice_DecRef(Device);
}
dev = VerifyDevice(Device);
if(dev)
value = dev->DeviceName.c_str();
else
{
ProbeCaptureDeviceList();
@ -2970,31 +3002,25 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para
break;
case ALC_EXTENSIONS:
if(!VerifyDevice(&Device))
value = alcNoDeviceExtList;
else
{
value = alcExtensionList;
ALCdevice_DecRef(Device);
}
dev = VerifyDevice(Device);
if(dev) value = alcExtensionList;
else value = alcNoDeviceExtList;
break;
case ALC_HRTF_SPECIFIER_SOFT:
if(!VerifyDevice(&Device))
dev = VerifyDevice(Device);
if(!dev)
alcSetError(nullptr, ALC_INVALID_DEVICE);
else
{
{ std::lock_guard<almtx_t> _{Device->BackendLock};
value = (Device->HrtfHandle ? Device->HrtfName.c_str() : "");
}
ALCdevice_DecRef(Device);
std::lock_guard<almtx_t> _{dev->BackendLock};
value = (dev->HrtfHandle ? dev->HrtfName.c_str() : "");
}
break;
default:
VerifyDevice(&Device);
alcSetError(Device, ALC_INVALID_ENUM);
if(Device) ALCdevice_DecRef(Device);
dev = VerifyDevice(Device);
alcSetError(dev.get(), ALC_INVALID_ENUM);
break;
}
@ -3324,23 +3350,22 @@ static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALC
*/
ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values)
{
VerifyDevice(&device);
DeviceRef dev{VerifyDevice(device)};
if(size <= 0 || values == nullptr)
alcSetError(device, ALC_INVALID_VALUE);
alcSetError(dev.get(), ALC_INVALID_VALUE);
else
GetIntegerv(device, param, size, values);
if(device) ALCdevice_DecRef(device);
GetIntegerv(dev.get(), param, size, values);
}
ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values)
{
VerifyDevice(&device);
DeviceRef dev{VerifyDevice(device)};
if(size <= 0 || values == nullptr)
alcSetError(device, ALC_INVALID_VALUE);
else if(!device || device->Type == Capture)
alcSetError(dev.get(), ALC_INVALID_VALUE);
else if(!dev || dev->Type == Capture)
{
std::vector<ALCint> ivals(size);
size = GetIntegerv(device, pname, size, ivals.data());
size = GetIntegerv(dev.get(), pname, size, ivals.data());
std::copy(ivals.begin(), ivals.begin()+size, values);
}
else /* render device */
@ -3348,67 +3373,67 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
switch(pname)
{
case ALC_ATTRIBUTES_SIZE:
*values = NumAttrsForDevice(device)+4;
*values = NumAttrsForDevice(dev.get())+4;
break;
case ALC_ALL_ATTRIBUTES:
if(size < NumAttrsForDevice(device)+4)
alcSetError(device, ALC_INVALID_VALUE);
if(size < NumAttrsForDevice(dev.get())+4)
alcSetError(dev.get(), ALC_INVALID_VALUE);
else
{
ALsizei i{0};
std::lock_guard<almtx_t> _{device->BackendLock};
std::lock_guard<almtx_t> _{dev->BackendLock};
values[i++] = ALC_FREQUENCY;
values[i++] = device->Frequency;
values[i++] = dev->Frequency;
if(device->Type != Loopback)
if(dev->Type != Loopback)
{
values[i++] = ALC_REFRESH;
values[i++] = device->Frequency / device->UpdateSize;
values[i++] = dev->Frequency / dev->UpdateSize;
values[i++] = ALC_SYNC;
values[i++] = ALC_FALSE;
}
else
{
if(device->FmtChans == DevFmtAmbi3D)
if(dev->FmtChans == DevFmtAmbi3D)
{
values[i++] = ALC_AMBISONIC_LAYOUT_SOFT;
values[i++] = static_cast<ALCint64SOFT>(device->mAmbiLayout);
values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiLayout);
values[i++] = ALC_AMBISONIC_SCALING_SOFT;
values[i++] = static_cast<ALCint64SOFT>(device->mAmbiScale);
values[i++] = static_cast<ALCint64SOFT>(dev->mAmbiScale);
values[i++] = ALC_AMBISONIC_ORDER_SOFT;
values[i++] = device->mAmbiOrder;
values[i++] = dev->mAmbiOrder;
}
values[i++] = ALC_FORMAT_CHANNELS_SOFT;
values[i++] = device->FmtChans;
values[i++] = dev->FmtChans;
values[i++] = ALC_FORMAT_TYPE_SOFT;
values[i++] = device->FmtType;
values[i++] = dev->FmtType;
}
values[i++] = ALC_MONO_SOURCES;
values[i++] = device->NumMonoSources;
values[i++] = dev->NumMonoSources;
values[i++] = ALC_STEREO_SOURCES;
values[i++] = device->NumStereoSources;
values[i++] = dev->NumStereoSources;
values[i++] = ALC_MAX_AUXILIARY_SENDS;
values[i++] = device->NumAuxSends;
values[i++] = dev->NumAuxSends;
values[i++] = ALC_HRTF_SOFT;
values[i++] = (device->HrtfHandle ? ALC_TRUE : ALC_FALSE);
values[i++] = (dev->HrtfHandle ? ALC_TRUE : ALC_FALSE);
values[i++] = ALC_HRTF_STATUS_SOFT;
values[i++] = device->HrtfStatus;
values[i++] = dev->HrtfStatus;
values[i++] = ALC_OUTPUT_LIMITER_SOFT;
values[i++] = device->Limiter ? ALC_TRUE : ALC_FALSE;
values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE;
ClockLatency clock{GetClockLatency(device)};
ClockLatency clock{GetClockLatency(dev.get())};
values[i++] = ALC_DEVICE_CLOCK_SOFT;
values[i++] = clock.ClockTime.count();
@ -3420,35 +3445,39 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
break;
case ALC_DEVICE_CLOCK_SOFT:
{ std::lock_guard<almtx_t> _{device->BackendLock};
std::chrono::nanoseconds basecount;
{ std::lock_guard<almtx_t> _{dev->BackendLock};
using std::chrono::seconds;
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
nanoseconds basecount;
ALuint samplecount;
ALuint refcount;
do {
while(((refcount=ReadRef(&device->MixCount))&1) != 0)
while(((refcount=ReadRef(&dev->MixCount))&1) != 0)
althrd_yield();
basecount = device->ClockBase;
samplecount = device->SamplesDone;
} while(refcount != ReadRef(&device->MixCount));
*values = (basecount + std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::seconds{samplecount}) / device->Frequency).count();
basecount = dev->ClockBase;
samplecount = dev->SamplesDone;
} while(refcount != ReadRef(&dev->MixCount));
*values = (duration_cast<nanoseconds>(seconds{samplecount})/dev->Frequency +
basecount).count();
}
break;
case ALC_DEVICE_LATENCY_SOFT:
{ std::lock_guard<almtx_t> _{device->BackendLock};
ClockLatency clock{GetClockLatency(device)};
{ std::lock_guard<almtx_t> _{dev->BackendLock};
ClockLatency clock{GetClockLatency(dev.get())};
*values = clock.Latency.count();
}
break;
case ALC_DEVICE_CLOCK_LATENCY_SOFT:
if(size < 2)
alcSetError(device, ALC_INVALID_VALUE);
alcSetError(dev.get(), ALC_INVALID_VALUE);
else
{
std::lock_guard<almtx_t> _{device->BackendLock};
ClockLatency clock{GetClockLatency(device)};
std::lock_guard<almtx_t> _{dev->BackendLock};
ClockLatency clock{GetClockLatency(dev.get())};
values[0] = clock.ClockTime.count();
values[1] = clock.Latency.count();
}
@ -3456,13 +3485,11 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
default:
std::vector<ALCint> ivals(size);
size = GetIntegerv(device, pname, size, ivals.data());
size = GetIntegerv(dev.get(), pname, size, ivals.data());
std::copy(ivals.begin(), ivals.begin()+size, values);
break;
}
}
if(device)
ALCdevice_DecRef(device);
}
@ -3472,24 +3499,19 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
*/
ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
{
ALCboolean bResult = ALC_FALSE;
VerifyDevice(&device);
DeviceRef dev{VerifyDevice(device)};
if(!extName)
alcSetError(device, ALC_INVALID_VALUE);
alcSetError(dev.get(), ALC_INVALID_VALUE);
else
{
size_t len = strlen(extName);
const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList);
const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList);
while(ptr && *ptr)
{
if(strncasecmp(ptr, extName, len) == 0 &&
(ptr[len] == '\0' || isspace(ptr[len])))
{
bResult = ALC_TRUE;
break;
}
return ALC_TRUE;
if((ptr=strchr(ptr, ' ')) != nullptr)
{
do {
@ -3498,9 +3520,7 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A
}
}
}
if(device)
ALCdevice_DecRef(device);
return bResult;
return ALC_FALSE;
}
@ -3510,13 +3530,10 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A
*/
ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
{
ALCvoid *ptr = nullptr;
if(!funcName)
{
VerifyDevice(&device);
alcSetError(device, ALC_INVALID_VALUE);
if(device) ALCdevice_DecRef(device);
DeviceRef dev{VerifyDevice(device)};
alcSetError(dev.get(), ALC_INVALID_VALUE);
}
else
{
@ -3524,14 +3541,11 @@ ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar
for(i = 0;i < COUNTOF(alcFunctions);i++)
{
if(strcmp(alcFunctions[i].funcName, funcName) == 0)
{
ptr = alcFunctions[i].address;
break;
}
return alcFunctions[i].address;
}
}
return ptr;
return nullptr;
}
@ -3541,13 +3555,10 @@ ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar
*/
ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
{
ALCenum val = 0;
if(!enumName)
{
VerifyDevice(&device);
alcSetError(device, ALC_INVALID_VALUE);
if(device) ALCdevice_DecRef(device);
DeviceRef dev{VerifyDevice(device)};
alcSetError(dev.get(), ALC_INVALID_VALUE);
}
else
{
@ -3555,14 +3566,11 @@ ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *e
for(i = 0;i < COUNTOF(alcEnumerations);i++)
{
if(strcmp(alcEnumerations[i].enumName, enumName) == 0)
{
val = alcEnumerations[i].value;
break;
}
return alcEnumerations[i].value;
}
}
return val;
return 0;
}
@ -3581,42 +3589,40 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
* properly cleaned up after being made.
*/
std::unique_lock<std::recursive_mutex> listlock{ListLock};
if(!VerifyDevice(&device) || device->Type == Capture ||
!device->Connected.load(std::memory_order_relaxed))
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
{
listlock.unlock();
alcSetError(device, ALC_INVALID_DEVICE);
if(device) ALCdevice_DecRef(device);
alcSetError(dev.get(), ALC_INVALID_DEVICE);
return nullptr;
}
std::unique_lock<almtx_t> backlock{device->BackendLock};
std::unique_lock<almtx_t> backlock{dev->BackendLock};
listlock.unlock();
device->LastError.store(ALC_NO_ERROR);
dev->LastError.store(ALC_NO_ERROR);
ALContext = new ALCcontext{device};
ALContext = new ALCcontext{dev.get()};
ALCdevice_IncRef(ALContext->Device);
if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR)
if((err=UpdateDeviceParams(dev.get(), attrList)) != ALC_NO_ERROR)
{
backlock.unlock();
delete ALContext;
ALContext = nullptr;
alcSetError(device, err);
alcSetError(dev.get(), err);
if(err == ALC_INVALID_DEVICE)
{
V0(device->Backend,lock)();
aluHandleDisconnect(device, "Device update failure");
V0(device->Backend,unlock)();
V0(dev->Backend,lock)();
aluHandleDisconnect(dev.get(), "Device update failure");
V0(dev->Backend,unlock)();
}
ALCdevice_DecRef(device);
return nullptr;
}
AllocateVoices(ALContext, 256, device->NumAuxSends);
AllocateVoices(ALContext, 256, dev->NumAuxSends);
if(DefaultEffect.type != AL_EFFECT_NULL && device->Type == Playback)
if(DefaultEffect.type != AL_EFFECT_NULL && dev->Type == Playback)
{
ALContext->DefaultSlot.reset(new ALeffectslot{});
if(InitEffectSlot(ALContext->DefaultSlot.get()) == AL_NO_ERROR)
@ -3630,7 +3636,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
InitContext(ALContext);
if(ConfigValueFloat(device->DeviceName.c_str(), nullptr, "volume-adjust", &valf))
if(ConfigValueFloat(dev->DeviceName.c_str(), nullptr, "volume-adjust", &valf))
{
if(!std::isfinite(valf))
ERR("volume-adjust must be finite: %f\n", valf);
@ -3646,10 +3652,10 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
UpdateListenerProps(ALContext);
{
ALCcontext *head = device->ContextList.load();
ALCcontext *head = dev->ContextList.load();
do {
ALContext->next.store(head, std::memory_order_relaxed);
} while(!device->ContextList.compare_exchange_weak(head, ALContext));
} while(!dev->ContextList.compare_exchange_weak(head, ALContext));
}
backlock.unlock();
@ -3661,8 +3667,6 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin
ERR("Failed to initialize the default effect\n");
}
ALCdevice_DecRef(device);
TRACE("Created context %p\n", ALContext);
return ALContext;
}
@ -4135,58 +4139,58 @@ ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device)
ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device)
{
if(!VerifyDevice(&device) || device->Type != Capture)
alcSetError(device, ALC_INVALID_DEVICE);
else
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type != Capture)
{
std::lock_guard<almtx_t> _{device->BackendLock};
if(!device->Connected.load(std::memory_order_acquire))
alcSetError(device, ALC_INVALID_DEVICE);
else if(!(device->Flags&DEVICE_RUNNING))
{
if(V0(device->Backend,start)())
device->Flags |= DEVICE_RUNNING;
else
{
aluHandleDisconnect(device, "Device start failure");
alcSetError(device, ALC_INVALID_DEVICE);
}
}
alcSetError(dev.get(), ALC_INVALID_DEVICE);
return;
}
if(device) ALCdevice_DecRef(device);
std::lock_guard<almtx_t> _{dev->BackendLock};
if(!dev->Connected.load(std::memory_order_acquire))
alcSetError(dev.get(), ALC_INVALID_DEVICE);
else if(!(dev->Flags&DEVICE_RUNNING))
{
if(V0(dev->Backend,start)())
dev->Flags |= DEVICE_RUNNING;
else
{
aluHandleDisconnect(dev.get(), "Device start failure");
alcSetError(dev.get(), ALC_INVALID_DEVICE);
}
}
}
ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device)
{
if(!VerifyDevice(&device) || device->Type != Capture)
alcSetError(device, ALC_INVALID_DEVICE);
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type != Capture)
alcSetError(dev.get(), ALC_INVALID_DEVICE);
else
{
std::lock_guard<almtx_t> _{device->BackendLock};
if((device->Flags&DEVICE_RUNNING))
V0(device->Backend,stop)();
device->Flags &= ~DEVICE_RUNNING;
std::lock_guard<almtx_t> _{dev->BackendLock};
if((dev->Flags&DEVICE_RUNNING))
V0(dev->Backend,stop)();
dev->Flags &= ~DEVICE_RUNNING;
}
if(device) ALCdevice_DecRef(device);
}
ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
{
if(!VerifyDevice(&device) || device->Type != Capture)
alcSetError(device, ALC_INVALID_DEVICE);
else
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type != Capture)
{
ALCenum err = ALC_INVALID_VALUE;
{ std::lock_guard<almtx_t> _{device->BackendLock};
if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples)
err = V(device->Backend,captureSamples)(buffer, samples);
}
if(err != ALC_NO_ERROR)
alcSetError(device, err);
alcSetError(dev.get(), ALC_INVALID_DEVICE);
return;
}
if(device) ALCdevice_DecRef(device);
ALCenum err{ALC_INVALID_VALUE};
{ std::lock_guard<almtx_t> _{dev->BackendLock};
if(samples >= 0 && V0(dev->Backend,availableSamples)() >= (ALCuint)samples)
err = V(dev->Backend,captureSamples)(buffer, samples);
}
if(err != ALC_NO_ERROR)
alcSetError(dev.get(), err);
}
@ -4267,20 +4271,18 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
*/
ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type)
{
ALCboolean ret{ALC_FALSE};
if(!VerifyDevice(&device) || device->Type != Loopback)
alcSetError(device, ALC_INVALID_DEVICE);
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type != Loopback)
alcSetError(dev.get(), ALC_INVALID_DEVICE);
else if(freq <= 0)
alcSetError(device, ALC_INVALID_VALUE);
alcSetError(dev.get(), ALC_INVALID_VALUE);
else
{
if(IsValidALCType(type) && IsValidALCChannels(channels) && freq >= MIN_OUTPUT_RATE)
ret = ALC_TRUE;
return ALC_TRUE;
}
if(device) ALCdevice_DecRef(device);
return ret;
return ALC_FALSE;
}
/* alcRenderSamplesSOFT
@ -4290,17 +4292,17 @@ ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device
*/
FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples)
{
if(!VerifyDevice(&device) || device->Type != Loopback)
alcSetError(device, ALC_INVALID_DEVICE);
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type != Loopback)
alcSetError(dev.get(), ALC_INVALID_DEVICE);
else if(samples < 0 || (samples > 0 && buffer == nullptr))
alcSetError(device, ALC_INVALID_VALUE);
alcSetError(dev.get(), ALC_INVALID_VALUE);
else
{
V0(device->Backend,lock)();
aluMixData(device, buffer, samples);
V0(device->Backend,unlock)();
V0(dev->Backend,lock)();
aluMixData(dev.get(), buffer, samples);
V0(dev->Backend,unlock)();
}
if(device) ALCdevice_DecRef(device);
}
@ -4314,17 +4316,17 @@ FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, AL
*/
ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
{
if(!VerifyDevice(&device) || device->Type != Playback)
alcSetError(device, ALC_INVALID_DEVICE);
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type != Playback)
alcSetError(dev.get(), ALC_INVALID_DEVICE);
else
{
std::lock_guard<almtx_t> _{device->BackendLock};
if((device->Flags&DEVICE_RUNNING))
V0(device->Backend,stop)();
device->Flags &= ~DEVICE_RUNNING;
device->Flags |= DEVICE_PAUSED;
std::lock_guard<almtx_t> _{dev->BackendLock};
if((dev->Flags&DEVICE_RUNNING))
V0(dev->Backend,stop)();
dev->Flags &= ~DEVICE_RUNNING;
dev->Flags |= DEVICE_PAUSED;
}
if(device) ALCdevice_DecRef(device);
}
/* alcDeviceResumeSOFT
@ -4333,29 +4335,29 @@ ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device)
*/
ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
{
if(!VerifyDevice(&device) || device->Type != Playback)
alcSetError(device, ALC_INVALID_DEVICE);
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type != Playback)
alcSetError(dev.get(), ALC_INVALID_DEVICE);
else
{
std::lock_guard<almtx_t> _{device->BackendLock};
if((device->Flags&DEVICE_PAUSED))
std::lock_guard<almtx_t> _{dev->BackendLock};
if((dev->Flags&DEVICE_PAUSED))
{
device->Flags &= ~DEVICE_PAUSED;
if(device->ContextList.load() != nullptr)
dev->Flags &= ~DEVICE_PAUSED;
if(dev->ContextList.load() != nullptr)
{
if(V0(device->Backend,start)() != ALC_FALSE)
device->Flags |= DEVICE_RUNNING;
if(V0(dev->Backend,start)() != ALC_FALSE)
dev->Flags |= DEVICE_RUNNING;
else
{
V0(device->Backend,lock)();
aluHandleDisconnect(device, "Device start failure");
V0(device->Backend,unlock)();
alcSetError(device, ALC_INVALID_DEVICE);
V0(dev->Backend,lock)();
aluHandleDisconnect(dev.get(), "Device start failure");
V0(dev->Backend,unlock)();
alcSetError(dev.get(), ALC_INVALID_DEVICE);
}
}
}
}
if(device) ALCdevice_DecRef(device);
}
@ -4369,26 +4371,23 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device)
*/
ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index)
{
const ALCchar *str{nullptr};
if(!VerifyDevice(&device) || device->Type == Capture)
alcSetError(device, ALC_INVALID_DEVICE);
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type == Capture)
alcSetError(dev.get(), ALC_INVALID_DEVICE);
else switch(paramName)
{
case ALC_HRTF_SPECIFIER_SOFT:
if(index >= 0 && (size_t)index < device->HrtfList.size())
str = device->HrtfList[index].name.c_str();
else
alcSetError(device, ALC_INVALID_VALUE);
if(index >= 0 && (size_t)index < dev->HrtfList.size())
return dev->HrtfList[index].name.c_str();
alcSetError(dev.get(), ALC_INVALID_VALUE);
break;
default:
alcSetError(device, ALC_INVALID_ENUM);
alcSetError(dev.get(), ALC_INVALID_ENUM);
break;
}
if(device) ALCdevice_DecRef(device);
return str;
return nullptr;
}
/* alcResetDeviceSOFT
@ -4398,33 +4397,30 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum
ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs)
{
std::unique_lock<std::recursive_mutex> listlock{ListLock};
if(!VerifyDevice(&device) || device->Type == Capture ||
!device->Connected.load(std::memory_order_relaxed))
DeviceRef dev{VerifyDevice(device)};
if(!dev || dev->Type == Capture || !dev->Connected.load(std::memory_order_relaxed))
{
listlock.unlock();
alcSetError(device, ALC_INVALID_DEVICE);
if(device) ALCdevice_DecRef(device);
alcSetError(dev.get(), ALC_INVALID_DEVICE);
return ALC_FALSE;
}
std::unique_lock<almtx_t> backlock{device->BackendLock};
std::unique_lock<almtx_t> backlock{dev->BackendLock};
listlock.unlock();
ALCenum err{UpdateDeviceParams(device, attribs)};
ALCenum err{UpdateDeviceParams(dev.get(), attribs)};
backlock.unlock();
if(err != ALC_NO_ERROR)
{
alcSetError(device, err);
alcSetError(dev.get(), err);
if(err == ALC_INVALID_DEVICE)
{
V0(device->Backend,lock)();
aluHandleDisconnect(device, "Device start failure");
V0(device->Backend,unlock)();
V0(dev->Backend,lock)();
aluHandleDisconnect(dev.get(), "Device start failure");
V0(dev->Backend,unlock)();
}
ALCdevice_DecRef(device);
return ALC_FALSE;
}
ALCdevice_DecRef(device);
return ALC_TRUE;
}