summaryrefslogtreecommitdiff
path: root/indra/llaudio
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llaudio')
-rw-r--r--indra/llaudio/CMakeLists.txt4
-rw-r--r--[-rwxr-xr-x]indra/llaudio/llaudiodecodemgr.cpp2
-rw-r--r--[-rwxr-xr-x]indra/llaudio/llaudioengine.h0
-rw-r--r--indra/llaudio/llaudioengine_openal.cpp104
-rw-r--r--indra/llaudio/llaudioengine_openal.h19
5 files changed, 127 insertions, 2 deletions
diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt
index f36da83c69..75534a9f60 100644
--- a/indra/llaudio/CMakeLists.txt
+++ b/indra/llaudio/CMakeLists.txt
@@ -71,3 +71,7 @@ if( TARGET ll::fmodstudio )
endif()
include(LibraryInstall)
+
+if (USE_PRECOMPILED_HEADERS)
+ target_precompile_headers(llaudio REUSE_FROM llprecompiled)
+endif ()
diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index d8a6fffea6..232b429130 100755..100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -199,7 +199,7 @@ bool LLVorbisDecodeState::initDecode()
LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL;
mInFilep = new LLFileSystem(mUUID, LLAssetType::AT_SOUND);
- if (!mInFilep || !mInFilep->getSize())
+ if (!mInFilep || mInFilep->getSize() <= 0)
{
LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL;
delete mInFilep;
diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h
index a9a229c0a5..a9a229c0a5 100755..100644
--- a/indra/llaudio/llaudioengine.h
+++ b/indra/llaudio/llaudioengine.h
diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp
index 755547bfaa..4126c8ef80 100644
--- a/indra/llaudio/llaudioengine_openal.cpp
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -42,7 +42,14 @@ LLAudioEngine_OpenAL::LLAudioEngine_OpenAL()
mWindBufSamples(0),
mWindBufBytes(0),
mWindSource(AL_NONE),
- mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS)
+ mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS),
+ mALDevice(NULL),
+ mHasReopenExt(false),
+ mReopenDeviceSOFT(NULL),
+ mHasSystemEventsExt(false),
+ mEventControlSOFT(NULL),
+ mEventCallbackSOFT(NULL),
+ mDefaultDeviceChanged(false)
{
}
@@ -87,6 +94,38 @@ bool LLAudioEngine_OpenAL::init(void* userdata, const std::string &app_title)
ALC_DEFAULT_DEVICE_SPECIFIER))
<< LL_ENDL;
+ mALDevice = device;
+
+ mHasReopenExt = alcIsExtensionPresent(mALDevice, "ALC_SOFT_reopen_device");
+ if (mHasReopenExt)
+ {
+ mReopenDeviceSOFT = (LPALCREOPENDEVICESOFT)alcGetProcAddress(mALDevice, "alcReopenDeviceSOFT");
+ mHasReopenExt = (mReopenDeviceSOFT != NULL);
+ }
+ LL_INFOS() << "ALC_SOFT_reopen_device " << (mHasReopenExt ? "supported" : "NOT supported") << LL_ENDL;
+
+ mHasSystemEventsExt = alcIsExtensionPresent(mALDevice, "ALC_SOFT_system_events");
+ if (mHasSystemEventsExt)
+ {
+ mEventControlSOFT = (LPALCEVENTCONTROLSOFT)alcGetProcAddress(mALDevice, "alcEventControlSOFT");
+ mEventCallbackSOFT = (LPALCEVENTCALLBACKSOFT)alcGetProcAddress(mALDevice, "alcEventCallbackSOFT");
+ mHasSystemEventsExt = (mEventControlSOFT != NULL && mEventCallbackSOFT != NULL);
+ }
+ LL_INFOS() << "ALC_SOFT_system_events " << (mHasSystemEventsExt ? "supported" : "NOT supported") << LL_ENDL;
+
+ if (mHasReopenExt && mHasSystemEventsExt)
+ {
+ mEventCallbackSOFT(&LLAudioEngine_OpenAL::onDeviceEventSOFT, this);
+ ALCenum events[] = { ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT };
+ mEventControlSOFT(1, events, ALC_TRUE);
+ LL_INFOS() << "Registered for ALC default-device-change notifications" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS() << "Dynamic OS default output device following is not available; "
+ << "a viewer restart will be needed to pick up default device changes" << LL_ENDL;
+ }
+
return true;
}
@@ -130,9 +169,72 @@ void LLAudioEngine_OpenAL::allocateListener()
}
// virtual
+void LLAudioEngine_OpenAL::idle()
+{
+ LLAudioEngine::idle();
+
+ if (mDefaultDeviceChanged)
+ {
+ mDefaultDeviceChanged = false;
+ reopenOnDefaultDevice();
+ }
+}
+
+// static
+void ALC_APIENTRY LLAudioEngine_OpenAL::onDeviceEventSOFT(ALCenum eventType, ALCenum /*deviceType*/,
+ ALCdevice* /*device*/, ALCsizei /*length*/,
+ const ALCchar* /*message*/, void* userParam) noexcept
+{
+ // This may run on OpenAL's internal thread, so just flip the mDefaultDeviceChanged flag
+ // and handle device change in idle().
+ if (eventType == ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT)
+ {
+ LLAudioEngine_OpenAL* self = static_cast<LLAudioEngine_OpenAL*>(userParam);
+ if (self)
+ {
+ self->mDefaultDeviceChanged = true;
+ }
+ }
+}
+
+void LLAudioEngine_OpenAL::reopenOnDefaultDevice()
+{
+ if (!mHasReopenExt || !mReopenDeviceSOFT || !mALDevice)
+ {
+ return;
+ }
+
+ std::string old_name = ll_safe_string(alcGetString(mALDevice, ALC_DEVICE_SPECIFIER));
+ LL_INFOS() << "OS default audio device changed; reopening OpenAL device (was: "
+ << old_name << ")" << LL_ENDL;
+
+ // Clear any prior device error state so failures below report accurately.
+ (void)alcGetError(mALDevice);
+
+ if (mReopenDeviceSOFT(mALDevice, NULL, NULL))
+ {
+ LL_INFOS() << "OpenAL device reopened successfully, now on: "
+ << ll_safe_string(alcGetString(mALDevice, ALC_DEVICE_SPECIFIER)) << LL_ENDL;
+ }
+ else
+ {
+ ALCenum error = alcGetError(mALDevice);
+ LL_WARNS() << "alcReopenDeviceSOFT() failed: alc error " << error << LL_ENDL;
+ }
+}
+
+// virtual
void LLAudioEngine_OpenAL::shutdown()
{
LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL;
+
+ if (mHasSystemEventsExt && mEventControlSOFT && mEventCallbackSOFT)
+ {
+ ALCenum events[] = { ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT };
+ mEventControlSOFT(1, events, ALC_FALSE);
+ mEventCallbackSOFT(NULL, NULL);
+ }
+
LLAudioEngine::shutdown();
// If a subsequent error occurs while there is still an error recorded
diff --git a/indra/llaudio/llaudioengine_openal.h b/indra/llaudio/llaudioengine_openal.h
index 574bec416d..da1f376800 100644
--- a/indra/llaudio/llaudioengine_openal.h
+++ b/indra/llaudio/llaudioengine_openal.h
@@ -33,6 +33,7 @@
#include "llaudioengine.h"
#include "lllistener_openal.h"
#include "llwindgen.h"
+#include "llatomic.h"
class LLAudioEngine_OpenAL : public LLAudioEngine
{
@@ -46,6 +47,7 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
virtual void allocateListener();
virtual void shutdown();
+ virtual void idle();
void setInternalGain(F32 gain);
@@ -68,6 +70,23 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
static const int MAX_NUM_WIND_BUFFERS = 80;
static const float WIND_BUFFER_SIZE_SEC; // 1/20th sec
+
+ ALCdevice* mALDevice;
+
+ bool mHasReopenExt;
+ LPALCREOPENDEVICESOFT mReopenDeviceSOFT;
+
+ bool mHasSystemEventsExt;
+ LPALCEVENTCONTROLSOFT mEventControlSOFT;
+ LPALCEVENTCALLBACKSOFT mEventCallbackSOFT;
+
+ // Set by onDeviceEventSOFT(), consumed by idle()
+ LLAtomicBool mDefaultDeviceChanged;
+
+ static void ALC_APIENTRY onDeviceEventSOFT(ALCenum eventType, ALCenum deviceType,
+ ALCdevice* device, ALCsizei length,
+ const ALCchar* message, void* userParam) noexcept;
+ void reopenOnDefaultDevice();
};
class LLAudioChannelOpenAL : public LLAudioChannel