aboutsummaryrefslogtreecommitdiffstats
path: root/alc/alc.cpp
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2021-11-21 23:22:04 -0800
committerChris Robinson <[email protected]>2021-11-21 23:22:04 -0800
commit08a4e8a6b2d3e48647f53a6c1957b94dd1a667bb (patch)
tree1384b207ba5b6b1a767232b964ce0af05fb5c43c /alc/alc.cpp
parent3ef4bffaf959d06527a247faa19cc869781745e4 (diff)
Return true from alcReopenDeviceSOFT if the new device opened
Diffstat (limited to 'alc/alc.cpp')
-rw-r--r--alc/alc.cpp33
1 files changed, 29 insertions, 4 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp
index 1b62e042..df38b22b 100644
--- a/alc/alc.cpp
+++ b/alc/alc.cpp
@@ -3815,24 +3815,36 @@ START_API_FUNC
return ALC_FALSE;
}
std::lock_guard<std::mutex> _{dev->StateLock};
- auto backend = dev->Backend.get();
/* Force the backend to stop mixing first since we're reopening. */
if(dev->Flags.test(DeviceRunning))
+ {
+ auto backend = dev->Backend.get();
backend->stop();
- dev->Flags.reset(DeviceRunning);
+ dev->Flags.reset(DeviceRunning);
+ }
+ BackendPtr newbackend;
try {
- backend->open(deviceName);
+ newbackend = PlaybackFactory->createBackend(dev.get(), BackendType::Playback);
+ newbackend->open(deviceName);
}
catch(al::backend_exception &e) {
+ listlock.unlock();
+ newbackend = nullptr;
+
WARN("Failed to reopen playback device: %s\n", e.what());
alcSetError(dev.get(), (e.errorCode() == al::backend_error::OutOfMemory)
? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE);
+
+ /* If the device is connected, not paused, and has contexts, ensure it
+ * continues playing.
+ */
if(dev->Connected.load(std::memory_order_relaxed) && !dev->Flags.test(DevicePaused)
&& !dev->mContexts.load(std::memory_order_relaxed)->empty())
{
try {
+ auto backend = dev->Backend.get();
backend->start();
dev->Flags.set(DeviceRunning);
}
@@ -3844,8 +3856,21 @@ START_API_FUNC
return ALC_FALSE;
}
listlock.unlock();
+ dev->Backend = std::move(newbackend);
TRACE("Reopened device %p, \"%s\"\n", voidp{dev.get()}, dev->DeviceName.c_str());
- return ResetDeviceParams(dev.get(), attribs) ? ALC_TRUE : ALC_FALSE;
+ /* Always return true even if resetting fails. It shouldn't fail, but this
+ * is primarily to avoid confusion by the app seeing the function return
+ * false while the device is on the new output anyway. We could try to
+ * restore the old backend if this fails, but the configuration would be
+ * changed with the new backend and would need to be reset again with the
+ * old one, and the provided attributes may not be appropriate or desirable
+ * for the old device.
+ *
+ * In this way, we essentially act as if the function succeeded, but
+ * immediately disconnects following it.
+ */
+ ResetDeviceParams(dev.get(), attribs);
+ return ALC_TRUE;
}
END_API_FUNC