1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
6 // Copyright (C) 2014-2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "stdsound_lowlevel.h"
23 #include "nel/sound/driver/sound_driver.h"
27 #elif defined(NL_STATIC)
28 // Driver availability for NL_STATIC compilation.
29 # undef NL_FMOD_AVAILABLE
30 # undef NL_OPENAL_AVAILABLE
31 # undef NL_DSOUND_AVAILABLE
32 # undef NL_XAUDIO2_AVAILABLE
33 # if defined( NL_OS_WINDOWS )
34 # define NL_FMOD_AVAILABLE
36 # define NL_OPENAL_AVAILABLE
38 #endif // HAVE_CONFIG_H
41 # ifndef NL_COMP_MINGW
45 #endif // NL_OS_WINDOWS
47 #include <nel/misc/debug.h>
49 # include <nel/misc/dynloadlib.h>
52 using namespace NLMISC
;
57 /// Interface version, increase when any part of sound_lowlevel is changed.
58 /// Put your name in comment to make sure you don't commit with
59 /// the same interface version number as someone else.
60 const uint32
ISoundDriver::InterfaceVersion
= 0x16; // Kaetemi
64 #define NLSOUND_DECLARE_DRIVER(__soundDriver) \
65 extern ISoundDriver* createISoundDriverInstance##__soundDriver(ISoundDriver::IStringMapperProvider *stringMapper); \
66 extern uint32 interfaceVersion##__soundDriver(); \
67 extern void outputProfile##__soundDriver(std::string &out); \
68 extern ISoundDriver::TDriver getDriverType##__soundDriver();
70 #ifdef NL_FMOD_AVAILABLE
71 NLSOUND_DECLARE_DRIVER(FMod
)
73 #ifdef NL_OPENAL_AVAILABLE
74 NLSOUND_DECLARE_DRIVER(OpenAl
)
76 #ifdef NL_DSOUND_AVAILABLE
77 NLSOUND_DECLARE_DRIVER(DSound
)
79 #ifdef NL_XAUDIO2_AVAILABLE
80 NLSOUND_DECLARE_DRIVER(XAudio2
)
85 typedef ISoundDriver
* (*ISDRV_CREATE_PROC
)(ISoundDriver::IStringMapperProvider
*stringMapper
);
86 const char *IDRV_CREATE_PROC_NAME
= "NLSOUND_createISoundDriverInstance";
88 typedef uint32 (*ISDRV_VERSION_PROC
)(void);
89 const char *IDRV_VERSION_PROC_NAME
= "NLSOUND_interfaceVersion";
93 /// Return driver name from type.
94 const char *ISoundDriver::getDriverName(TDriver driverType
)
98 case DriverAuto
: return "AUTO";
99 case DriverFMod
: return "FMod";
100 case DriverOpenAl
: return "OpenAL";
101 case DriverDSound
: return "DSound";
102 case DriverXAudio2
: return "XAudio2";
103 default: return "UNKNOWN";
108 * The static method which builds the sound driver instance
110 ISoundDriver
*ISoundDriver::createDriver(IStringMapperProvider
*stringMapper
, TDriver driverType
)
114 nlinfo("Creating statically linked sound driver %s", getDriverName(driverType
));
116 ISoundDriver
*result
= NULL
;
119 // switch between available drivers
120 # ifdef NL_FMOD_AVAILABLE
121 case DriverFMod
: result
= createISoundDriverInstanceFMod(stringMapper
); break;
123 # ifdef NL_OPENAL_AVAILABLE
124 case DriverOpenAl
: result
= createISoundDriverInstanceOpenAl(stringMapper
); break;
126 # ifdef NL_DSOUND_AVAILABLE
127 case DriverDSound
: result
= createISoundDriverInstanceDSound(stringMapper
); break;
129 # ifdef NL_XAUDIO2_AVAILABLE
130 case DriverXAudio2
: result
= createISoundDriverInstanceXAudio2(stringMapper
); break;
132 // auto driver = first available in this order: FMod, OpenAl, XAudio2, DSound
133 # if defined(NL_FMOD_AVAILABLE)
134 case DriverAuto
: result
= createISoundDriverInstanceFMod(stringMapper
); break;
135 # elif defined(NL_OPENAL_AVAILABLE)
136 case DriverAuto
: result
= createISoundDriverInstanceOpenAl(stringMapper
); break;
137 # elif defined(NL_XAUDIO2_AVAILABLE)
138 case DriverAuto
: result
= createISoundDriverInstanceXAudio2(stringMapper
); break;
139 # elif defined(NL_DSOUND_AVAILABLE)
140 case DriverAuto
: result
= createISoundDriverInstanceDSound(stringMapper
); break;
142 // unavailable driver = FAIL
143 default: throw ESoundDriverNotFound(getDriverName(driverType
));
145 if (!result
) throw ESoundDriverCantCreateDriver(getDriverName(driverType
));
150 ISDRV_CREATE_PROC createSoundDriver
= NULL
;
151 ISDRV_VERSION_PROC versionDriver
= NULL
;
160 #if defined (NL_COMP_MINGW)
161 dllName
= "libnel_drv_fmod_win";
162 #elif defined (NL_OS_WINDOWS)
163 dllName
= "nel_drv_fmod_win";
164 #elif defined (NL_OS_UNIX)
165 dllName
= "nel_drv_fmod";
167 # error "Driver name not define for this platform"
168 #endif // NL_OS_UNIX / NL_OS_WINDOWS
171 #if defined (NL_COMP_MINGW)
172 dllName
= "libnel_drv_openal_win";
173 #elif defined (NL_OS_WINDOWS)
174 dllName
= "nel_drv_openal_win";
175 #elif defined (NL_OS_UNIX)
176 dllName
= "nel_drv_openal";
178 # error "Driver name not define for this platform"
182 #if defined (NL_COMP_MINGW)
183 dllName
= "libnel_drv_dsound_win";
184 #elif defined (NL_OS_WINDOWS)
185 dllName
= "nel_drv_dsound_win";
186 #elif defined (NL_OS_UNIX)
187 nlerror("DriverDSound doesn't exist on Unix because it requires DirectX");
189 # error "Driver name not define for this platform"
193 #if defined (NL_COMP_MINGW)
194 dllName
= "libnel_drv_xaudio2_win";
195 #elif defined (NL_OS_WINDOWS)
196 dllName
= "nel_drv_xaudio2_win";
197 #elif defined (NL_OS_UNIX)
198 nlerror("DriverXAudio2 doesn't exist on Unix because it requires DirectX");
200 # error "Driver name not define for this platform"
204 #if defined (NL_COMP_MINGW)
205 dllName
= "libnel_drv_xaudio2_win";
206 #elif defined (NL_OS_WINDOWS)
207 dllName
= "nel_drv_xaudio2_win";
208 #elif defined (NL_OS_UNIX)
209 dllName
= "nel_drv_openal";
211 # error "Driver name not define for this platform"
218 #if defined(NL_OS_UNIX) && defined(NL_DRIVER_PREFIX)
219 driverLib
.addLibPath(NL_DRIVER_PREFIX
);
222 // Load it (adding standard nel pre/suffix, looking in library path and not taking ownership)
223 if (!driverLib
.loadLibrary(dllName
, true, true, false))
225 throw ESoundDriverNotFound(dllName
);
229 * MTR: Is there a way with NLMISC to replace SearchFile() ? Until then, no info for Linux.
232 wchar_t buffer
[1024], *ptr
;
233 uint len
= SearchPathW (NULL
, nlUtf8ToWide(dllName
), NULL
, 1023, buffer
, &ptr
);
235 nlinfo ("Using the library '%s' that is in the directory: '%s'", dllName
.c_str(), wideToUtf8(buffer
).c_str());
238 createSoundDriver
= (ISDRV_CREATE_PROC
) driverLib
.getSymbolAddress(IDRV_CREATE_PROC_NAME
);
239 if (createSoundDriver
== NULL
)
242 nlinfo( "Error: %u", GetLastError() );
244 nlinfo( "Error: Unable to load Sound Driver." );
246 throw ESoundDriverCorrupted(dllName
);
249 versionDriver
= (ISDRV_VERSION_PROC
) driverLib
.getSymbolAddress(IDRV_VERSION_PROC_NAME
);
250 if (versionDriver
!= NULL
)
252 if (versionDriver()<ISoundDriver::InterfaceVersion
)
253 throw ESoundDriverOldVersion(dllName
);
254 else if (versionDriver()>ISoundDriver::InterfaceVersion
)
255 throw ESoundDriverUnknownVersion(dllName
);
258 ISoundDriver
*ret
= createSoundDriver(stringMapper
);
261 throw ESoundDriverCantCreateDriver(dllName
);
266 ret
->_DllName
= driverLib
.getLibFileName();
271 #endif /* NL_STATIC */