extra fixes for options menu and setting up from device name

This commit is contained in:
marauder2k7 2026-05-07 17:58:33 +01:00
parent d56bf257c7
commit 15a7b8cce0
7 changed files with 183 additions and 44 deletions

View file

@ -82,9 +82,6 @@ class SFXDevice
typedef BufferVector::iterator BufferIterator; typedef BufferVector::iterator BufferIterator;
typedef VoiceVector::iterator VoiceIterator; typedef VoiceVector::iterator VoiceIterator;
/// The name of this device.
String mName;
/// The provider which created this device. /// The provider which created this device.
SFXProvider mProvider; SFXProvider mProvider;
@ -146,7 +143,7 @@ public:
S32 getMaxBuffers() const { return mMaxBuffers; } S32 getMaxBuffers() const { return mMaxBuffers; }
/// Returns the name of this device. /// Returns the name of this device.
const String& getName() const { return mName; } const String& getName() const { return mProvider.getName(); }
/// Return the device capability flags. /// Return the device capability flags.
U32 getCaps() const { return mCaps; } U32 getCaps() const { return mCaps; }

View file

@ -263,6 +263,46 @@ const char* SFXSystem::getProviderNameFromType(SFXProviderType type)
return _names[type]; return _names[type];
} }
SFXProviderType SFXSystem::getProviderTypeFromName(const char* name)
{
for (U32 i = 0; i < SFXProviderType_Count; i++)
{
if (dStrcmp(getProviderNameFromType((SFXProviderType)i), name) == 0)
return (SFXProviderType)i;
}
// Default to NullProvider if no match rather than silently falling through
Con::warnf("SFXSystem::getProviderTypeFromName - unknown provider '%s', defaulting to NullProvider", name);
return SFXProviderType::NullProvider;
}
SFXProvider* SFXSystem::getProviderByTypeAndName(SFXProviderType type, const char* deviceName)
{
// First try exact type+name match
for (U32 i = 0; i < smProviders.size(); i++)
{
if (smProviders[i]->mType == type &&
String::compare(smProviders[i]->getName(), deviceName) == 0)
return smProviders[i];
}
// Fall back to default device for that type
for (U32 i = 0; i < smProviders.size(); i++)
{
if (smProviders[i]->mType == type && smProviders[i]->mDefault)
return smProviders[i];
}
// Last resort: any device of that type
for (U32 i = 0; i < smProviders.size(); i++)
{
if (smProviders[i]->mType == type)
return smProviders[i];
}
return NULL;
}
SFXProvider* SFXSystem::getBestProviderChoice() SFXProvider* SFXSystem::getBestProviderChoice()
{ {
const String provider = Con::getVariable("$pref::SFX::provider"); const String provider = Con::getVariable("$pref::SFX::provider");
@ -572,13 +612,36 @@ void SFXSystem::removePlugin( SFXSystemPlugin* plugin )
} }
} }
bool SFXSystem::createDeviceByName(const char* providerName, const char* deviceName)
{
SFXProviderType type = getProviderTypeFromName(providerName);
SFXProvider* provider = getProviderByTypeAndName(type, deviceName);
if (!provider)
{
Con::errorf("SFXSystem::createDeviceByName - could not find provider '%s' device '%s'",
providerName, deviceName);
return false;
}
return createDevice(provider);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool SFXSystem::createDevice(SFXProvider* provider) bool SFXSystem::createDevice(SFXProvider* provider)
{ {
// this should probably just happen tbh. // this should probably just happen tbh.
if (mDevice) if (mDevice)
{
// called to create the same device bug out.
// this may need to be changed later to check if
// the provider names also match.
if (String::compare(mDevice->getName(), provider->getName()) == 0)
return false;
deleteDevice(); deleteDevice();
}
mDevice = provider->mCreateDeviceInstanceDelegate(provider->mIndex); mDevice = provider->mCreateDeviceInstanceDelegate(provider->mIndex);
if( !mDevice ) if( !mDevice )
@ -613,7 +676,7 @@ bool SFXSystem::createDevice(SFXProvider* provider)
mDevice->setDistanceModel( mDistanceModel ); mDevice->setDistanceModel( mDistanceModel );
mDevice->setDopplerFactor( mDopplerFactor ); mDevice->setDopplerFactor( mDopplerFactor );
mDevice->setRolloffFactor( mRolloffFactor ); mDevice->setRolloffFactor( mRolloffFactor );
mDevice->setSpeedOfSound(mSpeedOfSound); mDevice->setSpeedOfSound( mSpeedOfSound );
//OpenAL requires slots for effects, this creates an empty function //OpenAL requires slots for effects, this creates an empty function
//that will run when a sfxdevice is created. //that will run when a sfxdevice is created.
mDevice->openSlots(); mDevice->openSlots();
@ -1492,6 +1555,26 @@ DefineEngineFunction( sfxCreateDevice, bool, (),,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
DefineEngineFunction(sfxCreateDeviceFromName, bool, (const char* providerName, const char* deviceName), ("", ""),
"Create a sound device. Optionally specify provider and device name directly.\n"
"@param providerName Optional provider type name (e.g. \"OpenAL\", \"NullProvider\").\n"
"@param deviceName Optional device name to match against.\n"
"@ingroup SFX")
{
// If explicit names were provided, use them directly
if (providerName[0] != '\0' && deviceName[0] != '\0')
return SFX->createDeviceByName(providerName, deviceName);
// Otherwise fall back to autodetect via prefs
SFXProvider* p = SFXSystem::getBestProviderChoice();
if (p)
return SFX->createDevice(p);
return false;
}
//-----------------------------------------------------------------------------
DefineEngineFunction( sfxDeleteDevice, void, (),, DefineEngineFunction( sfxDeleteDevice, void, (),,
"Delete the currently active sound device and release all its resources.\n" "Delete the currently active sound device and release all its resources.\n"
"SFXSources that are still playing will be transitioned to virtualized playback mode. " "SFXSources that are still playing will be transitioned to virtualized playback mode. "

View file

@ -115,6 +115,8 @@ public:
static const char* getProviderNameFromType(SFXProviderType type); static const char* getProviderNameFromType(SFXProviderType type);
static SFXProvider* getBestProviderChoice(); static SFXProvider* getBestProviderChoice();
static SFXProvider* getProvider(U32 index); static SFXProvider* getProvider(U32 index);
static SFXProviderType getProviderTypeFromName(const char* name);
static SFXProvider* getProviderByTypeAndName(SFXProviderType type, const char* deviceName);
typedef Signal< void( SFXSystemEventType event ) > EventSignalType; typedef Signal< void( SFXSystemEventType event ) > EventSignalType;
typedef Vector< SFXSource* > SFXSourceVector; typedef Vector< SFXSource* > SFXSourceVector;
@ -278,6 +280,8 @@ public:
/// @name Device Management /// @name Device Management
/// @{ /// @{
bool createDeviceByName(const char* providerName, const char* deviceName);
/// This initializes a new device. /// This initializes a new device.
/// ///
/// @return Returns true if the device was created. /// @return Returns true if the device was created.

View file

@ -25,6 +25,7 @@ function createCanvas(%windowTitle)
if ($isDedicated) if ($isDedicated)
{ {
GFXInit::createNullDevice(); GFXInit::createNullDevice();
sfxCreateDevice("Null","Null Device", false, 8);
return true; return true;
} }

View file

@ -13,3 +13,11 @@ function Core_SFX::onCreate(%this)
function Core_SFX::onDestroy(%this) function Core_SFX::onDestroy(%this)
{ {
} }
function Core_SFX::initClient(%this)
{
if($pref::SFX::autoDetect)
{
AutodetectSound();
}
}

View file

@ -26,55 +26,92 @@ new SimGroup(AudioSettingsGroup)
}; };
}; };
function getDeviceDisplayName(%fullName)
{
%openPos = strstr(%fullName, "(");
%closePos = strstr(%fullName, ")");
if (%openPos == -1 || %closePos == -1)
return %fullName;
// +1 to skip past the "(" itself
return trim(getSubStr(%fullName, %openPos + 1, %closePos - %openPos - 1));
}
function AudioSettingsGroup::populateSettings(%this) function AudioSettingsGroup::populateSettings(%this)
{ {
AudioSettingsProviderGroup.clear(); AudioSettingsProviderGroup.clear();
AudioSettingsDeviceGroup.clear(); AudioSettingsDeviceGroup.clear();
%pCount = sfxGetProviderCount(); %pCount = sfxGetProviderCount();
for(%i = 0; %i < %pCount; %i++)
{
%provider = sfxGetProviderType(%i);
if(%provider !$= "NullProvider")
{
//We can't have duplicate providers, so double check for uniqueness
%foundProvider = false;
foreach(%registeredProviders in AudioSettingsProviderGroup)
{
if(%registeredProviders.displayName $= %provider)
{
%foundProvider = true;
break;
}
}
if(!%foundProvider) // --- First pass: build deduplicated provider list ---
for (%i = 0; %i < %pCount; %i++)
{
%providerType = sfxGetProviderType(%i);
if (%providerType $= "NullProvider")
continue;
%alreadyAdded = false;
foreach (%entry in AudioSettingsProviderGroup)
{
if (%entry.displayName $= %providerType)
{ {
//Provider entry %alreadyAdded = true;
%providerEntry = new ArrayObject() break;
{
class = "OptionsQualityLevel";
displayName = %provider;
key["$pref::SFX::provider"] = %provider;
};
AudioSettingsProviderGroup.add(%providerEntry);
} }
} }
if (!%alreadyAdded)
{
%providerEntry = new ArrayObject()
{
class = "OptionsQualityLevel";
displayName = %providerType;
key["$pref::SFX::provider"] = %providerType;
};
AudioSettingsProviderGroup.add(%providerEntry);
}
} }
for(%i = 0; %i < %pCount; %i++) // --- Second pass: for each provider, collect its devices ---
foreach (%providerEntry in AudioSettingsProviderGroup)
{ {
%device = sfxGetProviderDevice(%i); %providerType = %providerEntry.displayName;
//Device Entry
%deviceEntry = new ArrayObject()
{
class = "OptionsQualityLevel";
displayName = %device;
provider = %provider; //this is for filtering later, if we need to
key["$pref::SFX::device"] = %device;
};
AudioSettingsDeviceGroup.add(%deviceEntry); for (%i = 0; %i < %pCount; %i++)
{
if (sfxGetProviderType(%i) !$= %providerType)
continue;
%deviceName = sfxGetProviderDevice(%i);
%deviceEntry = new ArrayObject()
{
class = "OptionsQualityLevel";
displayName = getDeviceDisplayName(%deviceName);
providerType = %providerType;
key["$pref::SFX::device"] = %deviceName;
};
AudioSettingsDeviceGroup.add(%deviceEntry);
}
}
// Highlight the currently active entries
%activeProvider = $pref::SFX::provider;
%activeDevice = $pref::SFX::device;
foreach (%entry in AudioSettingsProviderGroup)
{
if (%entry.displayName $= %activeProvider)
AudioSettingsProviderGroup.currentValue = %activeProvider;
}
foreach (%entry in AudioSettingsDeviceGroup)
{
if (%entry.displayName $= %activeDevice && %entry.providerType $= %activeProvider)
AudioSettingsDeviceGroup.currentValue = %activeDevice;
} }
} }
@ -90,8 +127,15 @@ function AudioSettingsDeviceGroup::onApply(%this)
function updateAudioOptionsSettings() function updateAudioOptionsSettings()
{ {
if ( !sfxCreateDevice() ) if ( !sfxCreateDeviceFromName($pref::SFX::provider, $pref::SFX::device) )
error( "Unable to create SFX device: " @ $pref::SFX::provider error( "Unable to create SFX device: " @ $pref::SFX::provider
SPC $pref::SFX::device SPC $pref::SFX::device
SPC $pref::SFX::useHardware ); SPC $pref::SFX::useHardware );
} }
function AutodetectSound()
{
// Nothing to actually do in here?
// function here for convenience.
$pref::SFX::autoDetect = false;
}

View file

@ -855,6 +855,8 @@ function OptionsMenu::resetSettings(%this)
function OptionsMenu::populateAudioSettings(%this) function OptionsMenu::populateAudioSettings(%this)
{ {
AudioSettingsList.clear(); AudioSettingsList.clear();
OptionsMenu.optsListCount = -1;
AudioSettingsGroup.populateSettings(); AudioSettingsGroup.populateSettings();
//Process the lists //Process the lists