Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / sound / driver / sound_driver.cpp
blob378bc7ac7f41c1ac19ddf2dec3910683316ada7d
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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>
7 //
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"
25 #ifdef HAVE_CONFIG_H
26 # include "config.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
35 # else
36 # define NL_OPENAL_AVAILABLE
37 # endif
38 #endif // HAVE_CONFIG_H
40 #ifdef NL_OS_WINDOWS
41 # ifndef NL_COMP_MINGW
42 # define NOMINMAX
43 # endif
44 # include <windows.h>
45 #endif // NL_OS_WINDOWS
47 #include <nel/misc/debug.h>
48 #ifndef NL_STATIC
49 # include <nel/misc/dynloadlib.h>
50 #endif
52 using namespace NLMISC;
54 namespace NLSOUND
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
62 #ifdef NL_STATIC
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)
72 #endif
73 #ifdef NL_OPENAL_AVAILABLE
74 NLSOUND_DECLARE_DRIVER(OpenAl)
75 #endif
76 #ifdef NL_DSOUND_AVAILABLE
77 NLSOUND_DECLARE_DRIVER(DSound)
78 #endif
79 #ifdef NL_XAUDIO2_AVAILABLE
80 NLSOUND_DECLARE_DRIVER(XAudio2)
81 #endif
83 #else
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";
91 #endif
93 /// Return driver name from type.
94 const char *ISoundDriver::getDriverName(TDriver driverType)
96 switch (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)
112 #ifdef NL_STATIC
114 nlinfo("Creating statically linked sound driver %s", getDriverName(driverType));
116 ISoundDriver *result = NULL;
117 switch (driverType)
119 // switch between available drivers
120 # ifdef NL_FMOD_AVAILABLE
121 case DriverFMod: result = createISoundDriverInstanceFMod(stringMapper); break;
122 # endif
123 # ifdef NL_OPENAL_AVAILABLE
124 case DriverOpenAl: result = createISoundDriverInstanceOpenAl(stringMapper); break;
125 # endif
126 # ifdef NL_DSOUND_AVAILABLE
127 case DriverDSound: result = createISoundDriverInstanceDSound(stringMapper); break;
128 # endif
129 # ifdef NL_XAUDIO2_AVAILABLE
130 case DriverXAudio2: result = createISoundDriverInstanceXAudio2(stringMapper); break;
131 # endif
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;
141 # endif
142 // unavailable driver = FAIL
143 default: throw ESoundDriverNotFound(getDriverName(driverType));
145 if (!result) throw ESoundDriverCantCreateDriver(getDriverName(driverType));
146 return result;
148 #else
150 ISDRV_CREATE_PROC createSoundDriver = NULL;
151 ISDRV_VERSION_PROC versionDriver = NULL;
153 // dll selected
154 std::string dllName;
156 // Choose the DLL
157 switch(driverType)
159 case DriverFMod:
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";
166 #else
167 # error "Driver name not define for this platform"
168 #endif // NL_OS_UNIX / NL_OS_WINDOWS
169 break;
170 case DriverOpenAl:
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";
177 #else
178 # error "Driver name not define for this platform"
179 #endif
180 break;
181 case DriverDSound:
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");
188 #else
189 # error "Driver name not define for this platform"
190 #endif
191 break;
192 case DriverXAudio2:
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");
199 #else
200 # error "Driver name not define for this platform"
201 #endif
202 break;
203 default:
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";
210 #else
211 # error "Driver name not define for this platform"
212 #endif
213 break;
216 CLibrary driverLib;
218 #if defined(NL_OS_UNIX) && defined(NL_DRIVER_PREFIX)
219 driverLib.addLibPath(NL_DRIVER_PREFIX);
220 #endif
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.
231 #ifdef NL_OS_WINDOWS
232 wchar_t buffer[1024], *ptr;
233 uint len = SearchPathW (NULL, nlUtf8ToWide(dllName), NULL, 1023, buffer, &ptr);
234 if( len )
235 nlinfo ("Using the library '%s' that is in the directory: '%s'", dllName.c_str(), wideToUtf8(buffer).c_str());
236 #endif
238 createSoundDriver = (ISDRV_CREATE_PROC) driverLib.getSymbolAddress(IDRV_CREATE_PROC_NAME);
239 if (createSoundDriver == NULL)
241 #ifdef NL_OS_WINDOWS
242 nlinfo( "Error: %u", GetLastError() );
243 #else
244 nlinfo( "Error: Unable to load Sound Driver." );
245 #endif
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);
259 if ( ret == NULL )
261 throw ESoundDriverCantCreateDriver(dllName);
263 else
265 // Fill the DLL name
266 ret->_DllName = driverLib.getLibFileName();
269 return ret;
271 #endif /* NL_STATIC */
274 } // NLSOUND