Add output device selection for inworld sounds for FMOD Ex as well

master
Ansariel 2019-06-02 21:19:04 +02:00
parent 06fa762f21
commit 4a4e408e0b
3 changed files with 111 additions and 30 deletions

View File

@ -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);
// <FS> FIRE-11266 / BUG-3549 / MAINT-2983: Changing audio device now requires relog to restore sounds
#if LL_WINDOWS
// <FS:Ansariel> 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
// </FS>
// </FS:Ansariel>>
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; // <FS:Ansariel> 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");
// <FS> 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
// </FS>
// <FS:Ansariel> Output device selection
Check_FMOD_Error(mSystem->setCallback(systemCallback), "FMOD::System::setCallback");
Check_FMOD_Error(mSystem->setUserData(this), "FMOD::System::setUserData");
// </FS:Ansariel>
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;
// <FS:Ansariel> Output device selection
getDevices(); // Purely to print out available devices for debugging reasons
return true;
}
// <FS:Ansariel> 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);
}
// </FS:Ansariel>
std::string LLAudioEngine_FMODEX::getDriverName(bool verbose)
{

View File

@ -65,6 +65,14 @@ public:
typedef F32 MIXBUFFERFORMAT;
FMOD::System *getSystem() const {return mSystem;}
// <FS:Ansariel> Output device selection
/*virtual*/ std::map<LLUUID, std::string> getDevices();
/*virtual*/ void setDevice(const LLUUID& device_uuid);
LLUUID getSelectedDeviceUUID() const { return mSelectedDeviceUUID; }
// </FS:Ansariel>
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;
// <FS:Ansariel> Output device selection
LLUUID mSelectedDeviceUUID;
public:
static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT];
};

View File

@ -5952,7 +5952,7 @@ BOOL FSPanelPreferenceSounds::postBuild()
mOutputDevicePanel = findChild<LLPanel>("output_device_settings_panel");
mOutputDeviceComboBox = findChild<LLComboBox>("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));