From 4a4e408e0b098238af866d3cae4950ff323324e1 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sun, 2 Jun 2019 21:19:04 +0200 Subject: [PATCH] Add output device selection for inworld sounds for FMOD Ex as well --- indra/llaudio/llaudioengine_fmodex.cpp | 128 +++++++++++++++++++------ indra/llaudio/llaudioengine_fmodex.h | 11 +++ indra/newview/llfloaterpreference.cpp | 2 +- 3 files changed, 111 insertions(+), 30 deletions(-) diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp index 1eb3676e01..db34ffc19e 100644 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -48,42 +48,77 @@ FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels); -// FIRE-11266 / BUG-3549 / MAINT-2983: Changing audio device now requires relog to restore sounds -#if LL_WINDOWS +// Output device selection +static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string); + +LLUUID FMOD_GUID_to_LLUUID(FMOD_GUID guid) +{ + return LLUUID(llformat("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", guid.Data1, guid.Data2, guid.Data3, + guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7])); +} + +void set_device(FMOD::System* system, const LLUUID& device_uuid) +{ + LL_INFOS() << "LLAudioEngine_FMODEX::setDevice with device_uuid=" << device_uuid << LL_ENDL; + + int drivercount; + if (!Check_FMOD_Error(system->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers") && drivercount > 0) + { + if (device_uuid.isNull()) + { + LL_INFOS() << "Setting driver \"Default\"" << LL_ENDL; + Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver"); + } + else + { + FMOD_GUID guid; + + for (int i = 0; i < drivercount; ++i) + { + system->getDriverInfo(i, NULL, 0, &guid); + LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid); + + if (driver_guid == device_uuid) + { + LL_INFOS() << "Setting driver " << i << ": " << driver_guid << LL_ENDL; + Check_FMOD_Error(system->setDriver(i), "FMOD::System::setDriver"); + return; + } + } + + LL_INFOS() << "Device not available (anymore) - falling back to default" << LL_ENDL; + Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver"); + } + } +} + FMOD_RESULT F_CALLBACK systemCallback(FMOD_SYSTEM *system, FMOD_SYSTEM_CALLBACKTYPE type, void *commanddata1, void *commanddata2) { - FMOD::System *sys = (FMOD::System *)system; - FMOD_RESULT result; + FMOD::System* sys = (FMOD::System*)system; + LLAudioEngine_FMODEX* audio_engine = NULL; + if (sys) + { + void* userdata = NULL; + Check_FMOD_Error(sys->getUserData(&userdata), "FMOD::System::getUserData"); + audio_engine = (LLAudioEngine_FMODEX*)userdata; + } + switch (type) { case FMOD_SYSTEM_CALLBACKTYPE_DEVICELISTCHANGED: - { - int drivers; - sys->getNumDrivers(&drivers); - - if (drivers <= 0) + LL_DEBUGS() << "FMOD system callback FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED" << LL_ENDL; + if (sys && audio_engine) { - break; - } - - for (int i = 0; i < drivers; ++i) - { - result = sys->setDriver(i); - if (result == FMOD_OK) - { - break; - } + set_device(sys, audio_engine->getSelectedDeviceUUID()); + audio_engine->OnOutputDeviceListChanged(audio_engine->getDevices()); } break; - } - default: break; } return FMOD_OK; } -#endif -// +// > FMOD::ChannelGroup *LLAudioEngine_FMODEX::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; @@ -95,6 +130,7 @@ LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler) mSystem = NULL; mEnableProfiler = enable_profiler; mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); + mSelectedDeviceUUID == LLUUID::null; // Output device selection } @@ -182,12 +218,10 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) result = mSystem->setSoftwareChannels(num_channels + 2); Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels"); - // FIRE-11266 / BUG-3549 / MAINT-2983: Changing audio device now requires relog to restore sounds - #if LL_WINDOWS - result = mSystem->setCallback(systemCallback); - Check_FMOD_Error(result, "FMOD::System::setCallback"); - #endif - // + // Output device selection + Check_FMOD_Error(mSystem->setCallback(systemCallback), "FMOD::System::setCallback"); + Check_FMOD_Error(mSystem->setUserData(this), "FMOD::System::setUserData"); + // U32 fmod_flags = FMOD_INIT_NORMAL; if(mEnableProfiler) @@ -369,9 +403,45 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::init(): initialization complete." << LL_ENDL; + // Output device selection + getDevices(); // Purely to print out available devices for debugging reasons + return true; } +// Output device selection +//virtual +LLAudioEngine_FMODEX::output_device_map_t LLAudioEngine_FMODEX::getDevices() +{ + output_device_map_t driver_map; + + int drivercount; + char r_name[512]; + FMOD_GUID guid; + + if (!Check_FMOD_Error(mSystem->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers")) + { + for (int i = 0; i < drivercount; ++i) + { + memset(r_name, 0, 512); + mSystem->getDriverInfo(i, r_name, 511, &guid); + LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid); + driver_map.insert(std::make_pair(driver_guid, r_name)); + + LL_INFOS("AppInit") << "LLAudioEngine_FMODEX::getDevices(): r_name=\"" << r_name << "\" - guid: " << driver_guid << LL_ENDL; + } + } + + return driver_map; +} + +//virtual +void LLAudioEngine_FMODEX::setDevice(const LLUUID& device_uuid) +{ + mSelectedDeviceUUID = device_uuid; + set_device(mSystem, device_uuid); +} +// std::string LLAudioEngine_FMODEX::getDriverName(bool verbose) { diff --git a/indra/llaudio/llaudioengine_fmodex.h b/indra/llaudio/llaudioengine_fmodex.h index ca389d489f..d0de2d602a 100644 --- a/indra/llaudio/llaudioengine_fmodex.h +++ b/indra/llaudio/llaudioengine_fmodex.h @@ -65,6 +65,14 @@ public: typedef F32 MIXBUFFERFORMAT; FMOD::System *getSystem() const {return mSystem;} + + // Output device selection + /*virtual*/ std::map getDevices(); + /*virtual*/ void setDevice(const LLUUID& device_uuid); + + LLUUID getSelectedDeviceUUID() const { return mSelectedDeviceUUID; } + // + protected: /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. @@ -80,6 +88,9 @@ protected: FMOD::System *mSystem; bool mEnableProfiler; + // Output device selection + LLUUID mSelectedDeviceUUID; + public: static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT]; }; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index ddc3ef675c..23f74eba39 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -5952,7 +5952,7 @@ BOOL FSPanelPreferenceSounds::postBuild() mOutputDevicePanel = findChild("output_device_settings_panel"); mOutputDeviceComboBox = findChild("sound_output_device"); -#ifdef LL_FMODSTUDIO +#if LL_FMODSTUDIO || LL_FMODEX if (gAudiop && mOutputDevicePanel && mOutputDeviceComboBox) { gSavedSettings.getControl("FSOutputDeviceUUID")->getSignal()->connect(boost::bind(&FSPanelPreferenceSounds::onOutputDeviceChanged, this, _2));