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