// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdsound_lowlevel.h" #include "nel/sound/driver/sound_driver.h" #ifdef HAVE_CONFIG_H # include "config.h" #elif defined(NL_STATIC) // Driver availability for NL_STATIC compilation. # undef NL_FMOD_AVAILABLE # undef NL_OPENAL_AVAILABLE # undef NL_DSOUND_AVAILABLE # undef NL_XAUDIO2_AVAILABLE # if defined( NL_OS_WINDOWS ) # define NL_FMOD_AVAILABLE # else # define NL_OPENAL_AVAILABLE # endif #endif // HAVE_CONFIG_H #ifdef NL_OS_WINDOWS # define NOMINMAX # include #endif // NL_OS_WINDOWS #include #ifndef NL_STATIC # include #endif using namespace NLMISC; 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 #ifdef NL_STATIC #define NLSOUND_DECLARE_DRIVER(__soundDriver) \ extern ISoundDriver* createISoundDriverInstance##__soundDriver(ISoundDriver::IStringMapperProvider *stringMapper); \ extern uint32 interfaceVersion##__soundDriver(); \ extern void outputProfile##__soundDriver(std::string &out); \ extern ISoundDriver::TDriver getDriverType##__soundDriver(); #ifdef NL_FMOD_AVAILABLE NLSOUND_DECLARE_DRIVER(FMod) #endif #ifdef NL_OPENAL_AVAILABLE NLSOUND_DECLARE_DRIVER(OpenAl) #endif #ifdef NL_DSOUND_AVAILABLE NLSOUND_DECLARE_DRIVER(DSound) #endif #ifdef NL_XAUDIO2_AVAILABLE NLSOUND_DECLARE_DRIVER(XAudio2) #endif #else typedef ISoundDriver* (*ISDRV_CREATE_PROC)(ISoundDriver::IStringMapperProvider *stringMapper); const char *IDRV_CREATE_PROC_NAME = "NLSOUND_createISoundDriverInstance"; typedef uint32 (*ISDRV_VERSION_PROC)(void); const char *IDRV_VERSION_PROC_NAME = "NLSOUND_interfaceVersion"; #endif /// Return driver name from type. const char *ISoundDriver::getDriverName(TDriver driverType) { switch (driverType) { case DriverAuto: return "AUTO"; case DriverFMod: return "FMod"; case DriverOpenAl: return "OpenAL"; case DriverDSound: return "DSound"; case DriverXAudio2: return "XAudio2"; default: return "UNKNOWN"; } } /* * The static method which builds the sound driver instance */ ISoundDriver *ISoundDriver::createDriver(IStringMapperProvider *stringMapper, TDriver driverType) { #ifdef NL_STATIC nlinfo("Creating statically linked sound driver %s", getDriverName(driverType)); ISoundDriver *result = NULL; switch (driverType) { // switch between available drivers # ifdef NL_FMOD_AVAILABLE case DriverFMod: result = createISoundDriverInstanceFMod(stringMapper); break; # endif # ifdef NL_OPENAL_AVAILABLE case DriverOpenAl: result = createISoundDriverInstanceOpenAl(stringMapper); break; # endif # ifdef NL_DSOUND_AVAILABLE case DriverDSound: result = createISoundDriverInstanceDSound(stringMapper); break; # endif # ifdef NL_XAUDIO2_AVAILABLE case DriverXAudio2: result = createISoundDriverInstanceXAudio2(stringMapper); break; # endif // auto driver = first available in this order: FMod, OpenAl, XAudio2, DSound # if defined(NL_FMOD_AVAILABLE) case DriverAuto: result = createISoundDriverInstanceFMod(stringMapper); break; # elif defined(NL_OPENAL_AVAILABLE) case DriverAuto: result = createISoundDriverInstanceOpenAl(stringMapper); break; # elif defined(NL_XAUDIO2_AVAILABLE) case DriverAuto: result = createISoundDriverInstanceXAudio2(stringMapper); break; # elif defined(NL_DSOUND_AVAILABLE) case DriverAuto: result = createISoundDriverInstanceDSound(stringMapper); break; # endif // unavailable driver = FAIL default: throw ESoundDriverNotFound(getDriverName(driverType)); } if (!result) throw ESoundDriverCantCreateDriver(getDriverName(driverType)); return result; #else ISDRV_CREATE_PROC createSoundDriver = NULL; ISDRV_VERSION_PROC versionDriver = NULL; // dll selected std::string dllName; // Choose the DLL switch(driverType) { case DriverFMod: #if 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: #ifdef 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: #ifdef 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: #ifdef 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: #ifdef 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; } CLibrary driverLib; #if defined(NL_OS_UNIX) && defined(NL_DRIVER_PREFIX) driverLib.addLibPath(NL_DRIVER_PREFIX); #endif // Load it (adding standard nel pre/suffix, looking in library path and not taking ownership) if (!driverLib.loadLibrary(dllName, true, true, false)) { throw ESoundDriverNotFound(dllName); } /** * MTR: Is there a way with NLMISC to replace SearchFile() ? Until then, no info for Linux. */ #ifdef NL_OS_WINDOWS char buffer[1024], *ptr; uint len = SearchPath (NULL, dllName.c_str(), NULL, 1023, buffer, &ptr); if( len ) nlinfo ("Using the library '%s' that is in the directory: '%s'", dllName.c_str(), buffer); #endif createSoundDriver = (ISDRV_CREATE_PROC) driverLib.getSymbolAddress(IDRV_CREATE_PROC_NAME); if (createSoundDriver == NULL) { #ifdef NL_OS_WINDOWS nlinfo( "Error: %u", GetLastError() ); #else nlinfo( "Error: Unable to load Sound Driver." ); #endif throw ESoundDriverCorrupted(dllName); } versionDriver = (ISDRV_VERSION_PROC) driverLib.getSymbolAddress(IDRV_VERSION_PROC_NAME); if (versionDriver != NULL) { if (versionDriver()ISoundDriver::InterfaceVersion) throw ESoundDriverUnknownVersion(dllName); } ISoundDriver *ret = createSoundDriver(stringMapper); if ( ret == NULL ) { throw ESoundDriverCantCreateDriver(dllName); } else { // Fill the DLL name ret->_DllName = driverLib.getLibFileName(); } return ret; #endif /* NL_STATIC */ } } // NLSOUND