mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-05 15:40:10 +00:00
Reopen audio device on disconnect
This commit is contained in:
parent
754dac6103
commit
b762807dfb
@ -112,6 +112,10 @@ namespace
|
||||
LPALGETAUXILIARYEFFECTSLOTF alGetAuxiliaryEffectSlotf;
|
||||
LPALGETAUXILIARYEFFECTSLOTFV alGetAuxiliaryEffectSlotfv;
|
||||
|
||||
LPALEVENTCONTROLSOFT alEventControlSOFT;
|
||||
LPALEVENTCALLBACKSOFT alEventCallbackSOFT;
|
||||
LPALCREOPENDEVICESOFT alcReopenDeviceSOFT;
|
||||
|
||||
void LoadEffect(ALuint effect, const EFXEAXREVERBPROPERTIES& props)
|
||||
{
|
||||
ALint type = AL_NONE;
|
||||
@ -601,17 +605,40 @@ namespace MWSound
|
||||
return devlist;
|
||||
}
|
||||
|
||||
void OpenAL_Output::eventCallback(
|
||||
ALenum eventType, ALuint object, ALuint param, ALsizei length, const ALchar* message, void* userParam)
|
||||
{
|
||||
if (eventType == AL_EVENT_TYPE_DISCONNECTED_SOFT)
|
||||
static_cast<OpenAL_Output*>(userParam)->onDisconnect();
|
||||
}
|
||||
|
||||
void OpenAL_Output::onDisconnect()
|
||||
{
|
||||
if (!mInitialized)
|
||||
return;
|
||||
const std::lock_guard<std::mutex> lock(mReopenMutex);
|
||||
Log(Debug::Warning) << "Audio device disconnected, attempting to reopen...";
|
||||
ALCboolean reopened = alcReopenDeviceSOFT(mDevice, mDeviceName.c_str(), mContextAttributes.data());
|
||||
if (reopened == AL_FALSE && !mDeviceName.empty())
|
||||
reopened = alcReopenDeviceSOFT(mDevice, nullptr, mContextAttributes.data());
|
||||
if (reopened == AL_FALSE)
|
||||
Log(Debug::Error) << "Failed to reopen audio device";
|
||||
}
|
||||
|
||||
bool OpenAL_Output::init(const std::string& devname, const std::string& hrtfname, HrtfMode hrtfmode)
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(mReopenMutex);
|
||||
deinit();
|
||||
|
||||
Log(Debug::Info) << "Initializing OpenAL...";
|
||||
|
||||
mDeviceName = devname;
|
||||
mDevice = alcOpenDevice(devname.c_str());
|
||||
if (!mDevice && !devname.empty())
|
||||
{
|
||||
Log(Debug::Warning) << "Failed to open \"" << devname << "\", trying default";
|
||||
mDevice = alcOpenDevice(nullptr);
|
||||
mDeviceName.clear();
|
||||
}
|
||||
|
||||
if (!mDevice)
|
||||
@ -636,17 +663,17 @@ namespace MWSound
|
||||
ALC.EXT_EFX = alcIsExtensionPresent(mDevice, "ALC_EXT_EFX");
|
||||
ALC.SOFT_HRTF = alcIsExtensionPresent(mDevice, "ALC_SOFT_HRTF");
|
||||
|
||||
std::vector<ALCint> attrs;
|
||||
attrs.reserve(15);
|
||||
mContextAttributes.clear();
|
||||
mContextAttributes.reserve(15);
|
||||
if (ALC.SOFT_HRTF)
|
||||
{
|
||||
LPALCGETSTRINGISOFT alcGetStringiSOFT = nullptr;
|
||||
getALCFunc(alcGetStringiSOFT, mDevice, "alcGetStringiSOFT");
|
||||
|
||||
attrs.push_back(ALC_HRTF_SOFT);
|
||||
attrs.push_back(hrtfmode == HrtfMode::Disable ? ALC_FALSE
|
||||
: hrtfmode == HrtfMode::Enable ? ALC_TRUE
|
||||
:
|
||||
mContextAttributes.push_back(ALC_HRTF_SOFT);
|
||||
mContextAttributes.push_back(hrtfmode == HrtfMode::Disable ? ALC_FALSE
|
||||
: hrtfmode == HrtfMode::Enable ? ALC_TRUE
|
||||
:
|
||||
/*hrtfmode == HrtfMode::Auto ?*/ ALC_DONT_CARE_SOFT);
|
||||
if (!hrtfname.empty())
|
||||
{
|
||||
@ -667,14 +694,14 @@ namespace MWSound
|
||||
Log(Debug::Warning) << "Failed to find HRTF \"" << hrtfname << "\", using default";
|
||||
else
|
||||
{
|
||||
attrs.push_back(ALC_HRTF_ID_SOFT);
|
||||
attrs.push_back(index);
|
||||
mContextAttributes.push_back(ALC_HRTF_ID_SOFT);
|
||||
mContextAttributes.push_back(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
attrs.push_back(0);
|
||||
mContextAttributes.push_back(0);
|
||||
|
||||
mContext = alcCreateContext(mDevice, attrs.data());
|
||||
mContext = alcCreateContext(mDevice, mContextAttributes.data());
|
||||
if (!mContext || alcMakeContextCurrent(mContext) == ALC_FALSE)
|
||||
{
|
||||
Log(Debug::Error) << "Failed to setup audio context: " << alcGetString(mDevice, alcGetError(mDevice));
|
||||
@ -691,6 +718,22 @@ namespace MWSound
|
||||
<< " Version: " << alGetString(AL_VERSION) << "\n"
|
||||
<< " Extensions: " << alGetString(AL_EXTENSIONS);
|
||||
|
||||
if (alIsExtensionPresent("AL_SOFT_events"))
|
||||
{
|
||||
getALFunc(alEventControlSOFT, "alEventControlSOFT");
|
||||
getALFunc(alEventCallbackSOFT, "alEventCallbackSOFT");
|
||||
if (alcIsExtensionPresent(mDevice, "ALC_SOFT_reopen_device"))
|
||||
getALFunc(alcReopenDeviceSOFT, "alcReopenDeviceSOFT");
|
||||
}
|
||||
if (alEventControlSOFT)
|
||||
{
|
||||
static const std::array<ALenum, 1> events{ { AL_EVENT_TYPE_DISCONNECTED_SOFT } };
|
||||
alEventControlSOFT(events.size(), events.data(), AL_TRUE);
|
||||
alEventCallbackSOFT(&OpenAL_Output::eventCallback, this);
|
||||
}
|
||||
else
|
||||
Log(Debug::Warning) << "Cannot detect audio device changes";
|
||||
|
||||
if (!ALC.SOFT_HRTF)
|
||||
Log(Debug::Warning) << "HRTF status unavailable";
|
||||
else
|
||||
@ -867,6 +910,9 @@ namespace MWSound
|
||||
alDeleteFilters(1, &mWaterFilter);
|
||||
mWaterFilter = 0;
|
||||
|
||||
if (alEventCallbackSOFT)
|
||||
alEventCallbackSOFT(nullptr, nullptr);
|
||||
|
||||
alcMakeContextCurrent(nullptr);
|
||||
if (mContext)
|
||||
alcDestroyContext(mContext);
|
||||
@ -1526,6 +1572,7 @@ namespace MWSound
|
||||
|
||||
OpenAL_Output::~OpenAL_Output()
|
||||
{
|
||||
const std::lock_guard<std::mutex> lock(mReopenMutex);
|
||||
OpenAL_Output::deinit();
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -53,6 +54,10 @@ namespace MWSound
|
||||
struct StreamThread;
|
||||
std::unique_ptr<StreamThread> mStreamThread;
|
||||
|
||||
std::string mDeviceName;
|
||||
std::vector<ALCint> mContextAttributes;
|
||||
std::mutex mReopenMutex;
|
||||
|
||||
void initCommon2D(ALuint source, const osg::Vec3f& pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
|
||||
void initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist, ALfloat gain,
|
||||
ALfloat pitch, bool loop, bool useenv);
|
||||
@ -65,6 +70,11 @@ namespace MWSound
|
||||
OpenAL_Output& operator=(const OpenAL_Output& rhs);
|
||||
OpenAL_Output(const OpenAL_Output& rhs);
|
||||
|
||||
static void eventCallback(
|
||||
ALenum eventType, ALuint object, ALuint param, ALsizei length, const ALchar* message, void* userParam);
|
||||
|
||||
void onDisconnect();
|
||||
|
||||
public:
|
||||
std::vector<std::string> enumerate() override;
|
||||
bool init(const std::string& devname, const std::string& hrtfname, HrtfMode hrtfmode) override;
|
||||
|
@ -79,7 +79,7 @@ namespace MWSound
|
||||
|
||||
SoundManager::SoundManager(const VFS::Manager* vfs, bool useSound)
|
||||
: mVFS(vfs)
|
||||
, mOutput(new OpenAL_Output(*this))
|
||||
, mOutput(std::make_unique<OpenAL_Output>(*this))
|
||||
, mWaterSoundUpdater(makeWaterSoundUpdaterSettings())
|
||||
, mSoundBuffers(*vfs, *mOutput)
|
||||
, mListenerUnderwater(false)
|
||||
|
Loading…
x
Reference in New Issue
Block a user