Runtime discovery of available sound drivers

feature/change-sound-driver-ingame
Nimetu 3 years ago committed by nimetu
parent e1139b7e8d
commit db526ef68b

@ -127,6 +127,12 @@ public:
/// Return driver name from type.
static const char *getDriverName(TDriver driverType);
/// Return driver dll filename, empty if unsupported driver
static std::string getDriverFileName(TDriver driverType);
/** Return possibly available drivers for current platform.
* If no drivers are available, return empty list.
*/
static std::vector<ISoundDriver::TDriver> getAvailableDrivers();
/** The static method which builds the sound driver instance
* In case of failure, can throw one of these ESoundDriver exception objects:
* ESoundDriverNotFound, ESoundDriverCorrupted, ESoundDriverOldVersion, ESoundDriverUnknownVersion
@ -204,7 +210,6 @@ public:
private:
std::string _DllName;
};

@ -90,6 +90,13 @@ public:
NumDrivers
};
struct TDriverInfo
{
TDriver ID;
const char *Name;
TDriverInfo(TDriver id, const char *name) : ID(id), Name(name)
{}
};
/** Structure that contain the background flags.*/
struct TBackgroundFlags
@ -162,7 +169,10 @@ public:
/// I forgot what this does, but it's fairly important.
bool AutoLoadSample;
};
/// Return list of available sound drivers
static std::vector<TDriverInfo> getDrivers();
//@{
//@name Init methods
/// Create the audio mixer singleton and return a pointer to its instance
@ -212,7 +222,7 @@ public:
* \param forceSoftware: to force the driver to load in software buffer, not hardware
*/
virtual void init(uint maxTrack = 32, bool useEax = true, bool useADPCM = true, NLMISC::IProgressCallback *progressCallBack = NULL, bool autoLoadSample = false, TDriver driverType = DriverAuto, bool forceSoftware = false, bool manualRolloff = true) = 0;
/// Initialize the NeL Sound Driver with given driverName.
virtual void initDriver(const std::string &driverName) = 0;
/// Get the available devices on the loaded driver.

@ -67,16 +67,23 @@ void Init()
AudioMixer->setPackedSheetOption("data", true);
printf("Select NLSOUND Driver:\n");
printf(" [1] FMod\n");
printf(" [2] OpenAl\n");
printf(" [3] DSound\n");
printf(" [4] XAudio2\n");
std::vector<UAudioMixer::TDriverInfo> drivers = UAudioMixer::getDrivers();
if (drivers.size() == 0)
nlerror("No sound drivers available");
for(uint i = 0; i < drivers.size(); ++i)
printf(" [%d] %s\n", i, drivers[i].Name);
printf("> ");
int selection = getchar();
int selection = getchar() - '0';
printf("\n");
UAudioMixer::TDriver selectedDriver = UAudioMixer::DriverAuto;
if (selection >= 0 && selection < drivers.size())
selectedDriver = drivers[selection].ID;
// init with 32 tracks, EAX enabled, no ADPCM, and activate automatic sample bank loading
AudioMixer->init(32, true, false, NULL, true, (UAudioMixer::TDriver)(selection - '0')/*UAudioMixer::DriverFMod*/);
AudioMixer->init(32, true, false, NULL, true, selectedDriver);
/*
* 2. Initialize listener's position and orientation (in NeL coordinate system).

@ -131,6 +131,39 @@ CAudioMixerUser::CAudioMixerUser() : _AutoLoadSample(false),
}
}
// ******************************************************************
std::vector<UAudioMixer::TDriverInfo> UAudioMixer::getDrivers()
{
std::vector<TDriverInfo> drivers;
std::vector<ISoundDriver::TDriver> drv = ISoundDriver::getAvailableDrivers();
for(uint i = 0; i < drv.size(); ++i)
{
switch(drv[i])
{
case ISoundDriver::DriverAuto:
drivers.push_back(TDriverInfo(DriverAuto, ISoundDriver::getDriverName(drv[i])));
break;
case ISoundDriver::DriverFMod:
drivers.push_back(TDriverInfo(DriverFMod, ISoundDriver::getDriverName(drv[i])));
break;
case ISoundDriver::DriverDSound:
drivers.push_back(TDriverInfo(DriverDSound, ISoundDriver::getDriverName(drv[i])));
break;
case ISoundDriver::DriverOpenAl:
drivers.push_back(TDriverInfo(DriverOpenAl, ISoundDriver::getDriverName(drv[i])));
break;
case ISoundDriver::DriverXAudio2:
drivers.push_back(TDriverInfo(DriverXAudio2, ISoundDriver::getDriverName(drv[i])));
break;
default:
nlwarning("Unknown driver id %d, name '%s'", drv[i], ISoundDriver::getDriverName(drv[i]));
break;
}
}
return drivers;
}
// ******************************************************************
@ -374,16 +407,42 @@ void CAudioMixerUser::initDriver(const std::string &driverName)
std::string dn = NLMISC::toLowerAscii(driverName);
nldebug("AM: Init Driver '%s' ('%s')...", driverName.c_str(), dn.c_str());
ISoundDriver::TDriver driverType;
if (dn == "auto") driverType = ISoundDriver::DriverAuto;
else if (dn == "fmod") driverType = ISoundDriver::DriverFMod;
else if (dn == "dsound") driverType = ISoundDriver::DriverDSound;
else if (dn == "openal") driverType = ISoundDriver::DriverOpenAl;
else if (dn == "xaudio2") driverType = ISoundDriver::DriverXAudio2;
else
TDriver driverId = dn == "auto" ? DriverAuto : NumDrivers;
if (driverId == NumDrivers)
{
driverType = ISoundDriver::DriverAuto;
nlwarning("AM: driverName value '%s' ('%s') is invalid.", driverName.c_str(), dn.c_str());
std::vector<TDriverInfo> drivers = UAudioMixer::getDrivers();
for(uint i = 0; i < drivers.size(); ++i)
{
if (nlstricmp(drivers[i].Name, dn.c_str()) == 0)
{
driverId = drivers[i].ID;
break;
}
}
}
ISoundDriver::TDriver driverType;
switch(driverId)
{
case DriverAuto:
driverType = ISoundDriver::DriverAuto;
break;
case DriverFMod:
driverType = ISoundDriver::DriverFMod;
break;
case DriverDSound:
driverType = ISoundDriver::DriverDSound;
break;
case DriverOpenAl:
driverType = ISoundDriver::DriverOpenAl;
break;
case DriverXAudio2:
driverType = ISoundDriver::DriverXAudio2;
break;
case NumDrivers:
driverType = ISoundDriver::DriverAuto;
nlwarning("AM: driverName value '%s' ('%s') is not available.", driverName.c_str(), dn.c_str());
break;
}
try

@ -57,7 +57,7 @@ namespace NLSOUND
/// Interface version, increase when any part of sound_lowlevel is changed.
/// Put your name in comment to make sure you don't commit with
/// the same interface version number as someone else.
const uint32 ISoundDriver::InterfaceVersion = 0x16; // Kaetemi
const uint32 ISoundDriver::InterfaceVersion = 0x17; // Nimetu
#ifdef NL_STATIC
@ -104,6 +104,138 @@ const char *ISoundDriver::getDriverName(TDriver driverType)
}
}
/// Return driver filename from type.
std::string ISoundDriver::getDriverFileName(TDriver driverType)
{
switch(driverType)
{
case DriverFMod:
#if defined (NL_COMP_MINGW)
return "libnel_drv_fmod_win";
#elif defined (NL_OS_WINDOWS)
return "nel_drv_fmod_win";
#elif defined (NL_OS_UNIX)
return "nel_drv_fmod";
#else
# error "Driver name not define for this platform"
#endif // NL_OS_UNIX / NL_OS_WINDOWS
break;
case DriverOpenAl:
#if defined (NL_COMP_MINGW)
return "libnel_drv_openal_win";
#elif defined (NL_OS_WINDOWS)
return "nel_drv_openal_win";
#elif defined (NL_OS_UNIX)
return "nel_drv_openal";
#else
# error "Driver name not define for this platform"
#endif
break;
case DriverDSound:
#if defined (NL_COMP_MINGW)
return "libnel_drv_dsound_win";
#elif defined (NL_OS_WINDOWS)
return "nel_drv_dsound_win";
#elif defined (NL_OS_UNIX)
return "";
#else
# error "Driver name not define for this platform"
#endif
break;
case DriverXAudio2:
#if defined (NL_COMP_MINGW)
return "libnel_drv_xaudio2_win";
#elif defined (NL_OS_WINDOWS)
return "nel_drv_xaudio2_win";
#elif defined (NL_OS_UNIX)
return "";
#else
# error "Driver name not define for this platform"
#endif
break;
case DriverAuto:
#if defined (NL_COMP_MINGW)
return "libnel_drv_xaudio2_win";
#elif defined (NL_OS_WINDOWS)
return "nel_drv_xaudio2_win";
#elif defined (NL_OS_UNIX)
return "nel_drv_openal";
#else
# error "Driver name not define for this platform"
#endif
break;
default:
break;
}
return "";
}
///
std::vector<ISoundDriver::TDriver> ISoundDriver::getAvailableDrivers()
{
static std::vector<TDriver> m_AvailableDrivers;
if (!m_AvailableDrivers.empty())
return m_AvailableDrivers;
#ifdef NL_STATIC
# ifdef NL_FMOD_AVAILABLE
m_AvailableDrivers.push_back(DriverFMod);
# endif
# ifdef NL_OPENAL_AVAILABLE
m_AvailableDrivers.push_back(DriverOpenAl);
# endif
# ifdef NL_DSOUND_AVAILABLE
m_AvailableDrivers.push_back(DriverDSound);
# endif
# ifdef NL_XAUDIO2_AVAILABLE
m_AvailableDrivers.push_back(DriverXAudio2);
# endif
#else // NL_STATIC
const std::vector<TDriver> vec = {
DriverFMod,
DriverOpenAl,
DriverDSound,
DriverXAudio2,
};
#if 0
// if platform has dynamic driver name set, consider it as available
for(uint i = 0; i < vec.size(); i++)
{
std::string dllName = getDriverFileName(vec[i]);
if(!dllName.empty())
m_AvailableDrivers.push_back(vec[i]);
}
#else
CLibrary driverLib;
#if defined(NL_OS_UNIX) && defined(NL_DRIVER_PREFIX)
driverLib.addLibPath(NL_DRIVER_PREFIX);
#endif
nlinfo("Detecting available sound drivers");
for(uint i = 0; i < vec.size(); i++)
{
std::string dllName = getDriverFileName(vec[i]);
if(!dllName.empty())
{
// Load it (adding standard nel pre/suffix, looking in library path and taking ownership)
if (driverLib.loadLibrary(dllName, true, true, true))
{
m_AvailableDrivers.push_back(vec[i]);
driverLib.freeLibrary();
}
}
}
#endif
#endif
return m_AvailableDrivers;
}
/*
* The static method which builds the sound driver instance
*/
@ -151,67 +283,9 @@ ISoundDriver *ISoundDriver::createDriver(IStringMapperProvider *stringMapper, TD
ISDRV_VERSION_PROC versionDriver = NULL;
// dll selected
std::string dllName;
// Choose the DLL
switch(driverType)
{
case DriverFMod:
#if defined (NL_COMP_MINGW)
dllName = "libnel_drv_fmod_win";
#elif defined (NL_OS_WINDOWS)
dllName = "nel_drv_fmod_win";
#elif defined (NL_OS_UNIX)
dllName = "nel_drv_fmod";
#else
# error "Driver name not define for this platform"
#endif // NL_OS_UNIX / NL_OS_WINDOWS
break;
case DriverOpenAl:
#if defined (NL_COMP_MINGW)
dllName = "libnel_drv_openal_win";
#elif defined (NL_OS_WINDOWS)
dllName = "nel_drv_openal_win";
#elif defined (NL_OS_UNIX)
dllName = "nel_drv_openal";
#else
# error "Driver name not define for this platform"
#endif
break;
case DriverDSound:
#if defined (NL_COMP_MINGW)
dllName = "libnel_drv_dsound_win";
#elif defined (NL_OS_WINDOWS)
dllName = "nel_drv_dsound_win";
#elif defined (NL_OS_UNIX)
nlerror("DriverDSound doesn't exist on Unix because it requires DirectX");
#else
# error "Driver name not define for this platform"
#endif
break;
case DriverXAudio2:
#if defined (NL_COMP_MINGW)
dllName = "libnel_drv_xaudio2_win";
#elif defined (NL_OS_WINDOWS)
dllName = "nel_drv_xaudio2_win";
#elif defined (NL_OS_UNIX)
nlerror("DriverXAudio2 doesn't exist on Unix because it requires DirectX");
#else
# error "Driver name not define for this platform"
#endif
break;
default:
#if defined (NL_COMP_MINGW)
dllName = "libnel_drv_xaudio2_win";
#elif defined (NL_OS_WINDOWS)
dllName = "nel_drv_xaudio2_win";
#elif defined (NL_OS_UNIX)
dllName = "nel_drv_openal";
#else
# error "Driver name not define for this platform"
#endif
break;
}
std::string dllName = getDriverFileName(driverType);
if (dllName.empty())
throw ESoundDriverCantCreateDriver(("Driver '%s' not available for this platform", ISoundDriver::getDriverName(driverType)));
CLibrary driverLib;

Loading…
Cancel
Save