Mercurial > audio-send
comparison Alc/ALc.c @ 0:f9476ff7637e
initial forking of open-al to create multiple listeners
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Tue, 25 Oct 2011 13:02:31 -0700 |
parents | |
children | 96298d83959c |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f9476ff7637e |
---|---|
1 /** | |
2 * OpenAL cross platform audio library | |
3 * Copyright (C) 1999-2007 by authors. | |
4 * This library is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Library General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2 of the License, or (at your option) any later version. | |
8 * | |
9 * This library is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Library General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Library General Public | |
15 * License along with this library; if not, write to the | |
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 * Boston, MA 02111-1307, USA. | |
18 * Or go to http://www.gnu.org/copyleft/lgpl.html | |
19 */ | |
20 | |
21 #include "config.h" | |
22 | |
23 #include <math.h> | |
24 #include <stdlib.h> | |
25 #include <stdio.h> | |
26 #include <memory.h> | |
27 #include <ctype.h> | |
28 | |
29 #include "alMain.h" | |
30 #include "alSource.h" | |
31 #include "AL/al.h" | |
32 #include "AL/alc.h" | |
33 #include "alThunk.h" | |
34 #include "alSource.h" | |
35 #include "alBuffer.h" | |
36 #include "alAuxEffectSlot.h" | |
37 #include "bs2b.h" | |
38 #include "alu.h" | |
39 | |
40 // RLM: try to include the file here. | |
41 | |
42 | |
43 | |
44 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } | |
45 static struct BackendInfo BackendList[] = { | |
46 #ifdef HAVE_PULSEAUDIO | |
47 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs }, | |
48 #endif | |
49 #ifdef HAVE_ALSA | |
50 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs }, | |
51 #endif | |
52 #ifdef HAVE_COREAUDIO | |
53 { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs }, | |
54 #endif | |
55 #ifdef HAVE_OSS | |
56 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs }, | |
57 #endif | |
58 #ifdef HAVE_SOLARIS | |
59 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs }, | |
60 #endif | |
61 #ifdef HAVE_SNDIO | |
62 { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs }, | |
63 #endif | |
64 #ifdef HAVE_MMDEVAPI | |
65 { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs }, | |
66 #endif | |
67 #ifdef HAVE_DSOUND | |
68 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs }, | |
69 #endif | |
70 #ifdef HAVE_WINMM | |
71 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs }, | |
72 #endif | |
73 #ifdef HAVE_PORTAUDIO | |
74 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs }, | |
75 #endif | |
76 #ifdef HAVE_OPENSL | |
77 { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs }, | |
78 #endif | |
79 | |
80 { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs }, | |
81 #ifdef HAVE_WAVE | |
82 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs }, | |
83 #endif | |
84 { "send", alc_send_init, alc_send_deinit, alc_send_probe, EmptyFuncs }, | |
85 // this entry is so that the list is terminated by a "null" object, | |
86 // and helps things to tell when they've reached the end of the list. | |
87 { NULL, NULL, NULL, NULL, EmptyFuncs } | |
88 }; | |
89 static struct BackendInfo BackendLoopback = { | |
90 "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs | |
91 }; | |
92 #undef EmptyFuncs | |
93 | |
94 static struct BackendInfo PlaybackBackend; | |
95 static struct BackendInfo CaptureBackend; | |
96 | |
97 /////////////////////////////////////////////////////// | |
98 // STRING and EXTENSIONS | |
99 | |
100 typedef struct ALCfunction { | |
101 const ALCchar *funcName; | |
102 ALCvoid *address; | |
103 } ALCfunction; | |
104 | |
105 typedef struct ALCenums { | |
106 const ALCchar *enumName; | |
107 ALCenum value; | |
108 } ALCenums; | |
109 | |
110 | |
111 static const ALCfunction alcFunctions[] = { | |
112 { "alcCreateContext", (ALCvoid *) alcCreateContext }, | |
113 { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent }, | |
114 { "alcProcessContext", (ALCvoid *) alcProcessContext }, | |
115 { "alcSuspendContext", (ALCvoid *) alcSuspendContext }, | |
116 { "alcDestroyContext", (ALCvoid *) alcDestroyContext }, | |
117 { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext }, | |
118 { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice }, | |
119 { "alcOpenDevice", (ALCvoid *) alcOpenDevice }, | |
120 { "alcCloseDevice", (ALCvoid *) alcCloseDevice }, | |
121 { "alcGetError", (ALCvoid *) alcGetError }, | |
122 { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent }, | |
123 { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress }, | |
124 { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue }, | |
125 { "alcGetString", (ALCvoid *) alcGetString }, | |
126 { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv }, | |
127 { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice }, | |
128 { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice }, | |
129 { "alcCaptureStart", (ALCvoid *) alcCaptureStart }, | |
130 { "alcCaptureStop", (ALCvoid *) alcCaptureStop }, | |
131 { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples }, | |
132 | |
133 { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext }, | |
134 { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext }, | |
135 | |
136 { "alcLoopbackOpenDeviceSOFT", (ALCvoid *) alcLoopbackOpenDeviceSOFT}, | |
137 { "alcIsRenderFormatSupportedSOFT",(ALCvoid *) alcIsRenderFormatSupportedSOFT}, | |
138 { "alcRenderSamplesSOFT", (ALCvoid *) alcRenderSamplesSOFT }, | |
139 | |
140 { "alEnable", (ALCvoid *) alEnable }, | |
141 { "alDisable", (ALCvoid *) alDisable }, | |
142 { "alIsEnabled", (ALCvoid *) alIsEnabled }, | |
143 { "alGetString", (ALCvoid *) alGetString }, | |
144 { "alGetBooleanv", (ALCvoid *) alGetBooleanv }, | |
145 { "alGetIntegerv", (ALCvoid *) alGetIntegerv }, | |
146 { "alGetFloatv", (ALCvoid *) alGetFloatv }, | |
147 { "alGetDoublev", (ALCvoid *) alGetDoublev }, | |
148 { "alGetBoolean", (ALCvoid *) alGetBoolean }, | |
149 { "alGetInteger", (ALCvoid *) alGetInteger }, | |
150 { "alGetFloat", (ALCvoid *) alGetFloat }, | |
151 { "alGetDouble", (ALCvoid *) alGetDouble }, | |
152 { "alGetError", (ALCvoid *) alGetError }, | |
153 { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent }, | |
154 { "alGetProcAddress", (ALCvoid *) alGetProcAddress }, | |
155 { "alGetEnumValue", (ALCvoid *) alGetEnumValue }, | |
156 { "alListenerf", (ALCvoid *) alListenerf }, | |
157 { "alListener3f", (ALCvoid *) alListener3f }, | |
158 { "alListenerfv", (ALCvoid *) alListenerfv }, | |
159 { "alListeneri", (ALCvoid *) alListeneri }, | |
160 { "alListener3i", (ALCvoid *) alListener3i }, | |
161 { "alListeneriv", (ALCvoid *) alListeneriv }, | |
162 { "alGetListenerf", (ALCvoid *) alGetListenerf }, | |
163 { "alGetListener3f", (ALCvoid *) alGetListener3f }, | |
164 { "alGetListenerfv", (ALCvoid *) alGetListenerfv }, | |
165 { "alGetListeneri", (ALCvoid *) alGetListeneri }, | |
166 { "alGetListener3i", (ALCvoid *) alGetListener3i }, | |
167 { "alGetListeneriv", (ALCvoid *) alGetListeneriv }, | |
168 { "alGenSources", (ALCvoid *) alGenSources }, | |
169 { "alDeleteSources", (ALCvoid *) alDeleteSources }, | |
170 { "alIsSource", (ALCvoid *) alIsSource }, | |
171 { "alSourcef", (ALCvoid *) alSourcef }, | |
172 { "alSource3f", (ALCvoid *) alSource3f }, | |
173 { "alSourcefv", (ALCvoid *) alSourcefv }, | |
174 { "alSourcei", (ALCvoid *) alSourcei }, | |
175 { "alSource3i", (ALCvoid *) alSource3i }, | |
176 { "alSourceiv", (ALCvoid *) alSourceiv }, | |
177 { "alGetSourcef", (ALCvoid *) alGetSourcef }, | |
178 { "alGetSource3f", (ALCvoid *) alGetSource3f }, | |
179 { "alGetSourcefv", (ALCvoid *) alGetSourcefv }, | |
180 { "alGetSourcei", (ALCvoid *) alGetSourcei }, | |
181 { "alGetSource3i", (ALCvoid *) alGetSource3i }, | |
182 { "alGetSourceiv", (ALCvoid *) alGetSourceiv }, | |
183 { "alSourcePlayv", (ALCvoid *) alSourcePlayv }, | |
184 { "alSourceStopv", (ALCvoid *) alSourceStopv }, | |
185 { "alSourceRewindv", (ALCvoid *) alSourceRewindv }, | |
186 { "alSourcePausev", (ALCvoid *) alSourcePausev }, | |
187 { "alSourcePlay", (ALCvoid *) alSourcePlay }, | |
188 { "alSourceStop", (ALCvoid *) alSourceStop }, | |
189 { "alSourceRewind", (ALCvoid *) alSourceRewind }, | |
190 { "alSourcePause", (ALCvoid *) alSourcePause }, | |
191 { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers }, | |
192 { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers }, | |
193 { "alGenBuffers", (ALCvoid *) alGenBuffers }, | |
194 { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers }, | |
195 { "alIsBuffer", (ALCvoid *) alIsBuffer }, | |
196 { "alBufferData", (ALCvoid *) alBufferData }, | |
197 { "alBufferf", (ALCvoid *) alBufferf }, | |
198 { "alBuffer3f", (ALCvoid *) alBuffer3f }, | |
199 { "alBufferfv", (ALCvoid *) alBufferfv }, | |
200 { "alBufferi", (ALCvoid *) alBufferi }, | |
201 { "alBuffer3i", (ALCvoid *) alBuffer3i }, | |
202 { "alBufferiv", (ALCvoid *) alBufferiv }, | |
203 { "alGetBufferf", (ALCvoid *) alGetBufferf }, | |
204 { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f }, | |
205 { "alGetBufferfv", (ALCvoid *) alGetBufferfv }, | |
206 { "alGetBufferi", (ALCvoid *) alGetBufferi }, | |
207 { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i }, | |
208 { "alGetBufferiv", (ALCvoid *) alGetBufferiv }, | |
209 { "alDopplerFactor", (ALCvoid *) alDopplerFactor }, | |
210 { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity }, | |
211 { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound }, | |
212 { "alDistanceModel", (ALCvoid *) alDistanceModel }, | |
213 | |
214 { "alGenFilters", (ALCvoid *) alGenFilters }, | |
215 { "alDeleteFilters", (ALCvoid *) alDeleteFilters }, | |
216 { "alIsFilter", (ALCvoid *) alIsFilter }, | |
217 { "alFilteri", (ALCvoid *) alFilteri }, | |
218 { "alFilteriv", (ALCvoid *) alFilteriv }, | |
219 { "alFilterf", (ALCvoid *) alFilterf }, | |
220 { "alFilterfv", (ALCvoid *) alFilterfv }, | |
221 { "alGetFilteri", (ALCvoid *) alGetFilteri }, | |
222 { "alGetFilteriv", (ALCvoid *) alGetFilteriv }, | |
223 { "alGetFilterf", (ALCvoid *) alGetFilterf }, | |
224 { "alGetFilterfv", (ALCvoid *) alGetFilterfv }, | |
225 { "alGenEffects", (ALCvoid *) alGenEffects }, | |
226 { "alDeleteEffects", (ALCvoid *) alDeleteEffects }, | |
227 { "alIsEffect", (ALCvoid *) alIsEffect }, | |
228 { "alEffecti", (ALCvoid *) alEffecti }, | |
229 { "alEffectiv", (ALCvoid *) alEffectiv }, | |
230 { "alEffectf", (ALCvoid *) alEffectf }, | |
231 { "alEffectfv", (ALCvoid *) alEffectfv }, | |
232 { "alGetEffecti", (ALCvoid *) alGetEffecti }, | |
233 { "alGetEffectiv", (ALCvoid *) alGetEffectiv }, | |
234 { "alGetEffectf", (ALCvoid *) alGetEffectf }, | |
235 { "alGetEffectfv", (ALCvoid *) alGetEffectfv }, | |
236 { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots}, | |
237 { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots}, | |
238 { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot }, | |
239 { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti }, | |
240 { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv }, | |
241 { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf }, | |
242 { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv }, | |
243 { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti}, | |
244 { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv}, | |
245 { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf}, | |
246 { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv}, | |
247 | |
248 { "alBufferSubDataSOFT", (ALCvoid *) alBufferSubDataSOFT }, | |
249 | |
250 { "alBufferSamplesSOFT", (ALCvoid *) alBufferSamplesSOFT }, | |
251 { "alBufferSubSamplesSOFT", (ALCvoid *) alBufferSubSamplesSOFT }, | |
252 { "alGetBufferSamplesSOFT", (ALCvoid *) alGetBufferSamplesSOFT }, | |
253 { "alIsBufferFormatSupportedSOFT",(ALCvoid *) alIsBufferFormatSupportedSOFT}, | |
254 | |
255 { "alDeferUpdatesSOFT", (ALCvoid *) alDeferUpdatesSOFT }, | |
256 { "alProcessUpdatesSOFT", (ALCvoid *) alProcessUpdatesSOFT }, | |
257 | |
258 { NULL, (ALCvoid *) NULL } | |
259 }; | |
260 | |
261 static const ALCenums enumeration[] = { | |
262 // Types | |
263 { "ALC_INVALID", ALC_INVALID }, | |
264 { "ALC_FALSE", ALC_FALSE }, | |
265 { "ALC_TRUE", ALC_TRUE }, | |
266 | |
267 // ALC Properties | |
268 { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION }, | |
269 { "ALC_MINOR_VERSION", ALC_MINOR_VERSION }, | |
270 { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE }, | |
271 { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES }, | |
272 { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER }, | |
273 { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER }, | |
274 { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER }, | |
275 { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER }, | |
276 { "ALC_EXTENSIONS", ALC_EXTENSIONS }, | |
277 { "ALC_FREQUENCY", ALC_FREQUENCY }, | |
278 { "ALC_REFRESH", ALC_REFRESH }, | |
279 { "ALC_SYNC", ALC_SYNC }, | |
280 { "ALC_MONO_SOURCES", ALC_MONO_SOURCES }, | |
281 { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES }, | |
282 { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER }, | |
283 { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER}, | |
284 { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES }, | |
285 { "ALC_CONNECTED", ALC_CONNECTED }, | |
286 | |
287 // EFX Properties | |
288 { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION }, | |
289 { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION }, | |
290 { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS }, | |
291 | |
292 // Loopback device Properties | |
293 { "ALC_FORMAT_CHANNELS_SOFT", ALC_FORMAT_CHANNELS_SOFT }, | |
294 { "ALC_FORMAT_TYPE_SOFT", ALC_FORMAT_TYPE_SOFT }, | |
295 | |
296 // Buffer Channel Configurations | |
297 { "ALC_MONO", ALC_MONO }, | |
298 { "ALC_STEREO", ALC_STEREO }, | |
299 { "ALC_QUAD", ALC_QUAD }, | |
300 { "ALC_5POINT1", ALC_5POINT1 }, | |
301 { "ALC_6POINT1", ALC_6POINT1 }, | |
302 { "ALC_7POINT1", ALC_7POINT1 }, | |
303 | |
304 // Buffer Sample Types | |
305 { "ALC_BYTE", ALC_BYTE }, | |
306 { "ALC_UNSIGNED_BYTE", ALC_UNSIGNED_BYTE }, | |
307 { "ALC_SHORT", ALC_SHORT }, | |
308 { "ALC_UNSIGNED_SHORT", ALC_UNSIGNED_SHORT }, | |
309 { "ALC_INT", ALC_INT }, | |
310 { "ALC_UNSIGNED_INT", ALC_UNSIGNED_INT }, | |
311 { "ALC_FLOAT", ALC_FLOAT }, | |
312 | |
313 // ALC Error Message | |
314 { "ALC_NO_ERROR", ALC_NO_ERROR }, | |
315 { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE }, | |
316 { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT }, | |
317 { "ALC_INVALID_ENUM", ALC_INVALID_ENUM }, | |
318 { "ALC_INVALID_VALUE", ALC_INVALID_VALUE }, | |
319 { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY }, | |
320 | |
321 { NULL, (ALCenum)0 } | |
322 }; | |
323 // Error strings | |
324 static const ALCchar alcNoError[] = "No Error"; | |
325 static const ALCchar alcErrInvalidDevice[] = "Invalid Device"; | |
326 static const ALCchar alcErrInvalidContext[] = "Invalid Context"; | |
327 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum"; | |
328 static const ALCchar alcErrInvalidValue[] = "Invalid Value"; | |
329 static const ALCchar alcErrOutOfMemory[] = "Out of Memory"; | |
330 | |
331 /* Device lists. Sizes only include the first ending null character, not the | |
332 * second */ | |
333 static ALCchar *alcDeviceList; | |
334 static size_t alcDeviceListSize; | |
335 static ALCchar *alcAllDeviceList; | |
336 static size_t alcAllDeviceListSize; | |
337 static ALCchar *alcCaptureDeviceList; | |
338 static size_t alcCaptureDeviceListSize; | |
339 /* Default is always the first in the list */ | |
340 static ALCchar *alcDefaultDeviceSpecifier; | |
341 static ALCchar *alcDefaultAllDeviceSpecifier; | |
342 static ALCchar *alcCaptureDefaultDeviceSpecifier; | |
343 | |
344 | |
345 static const ALCchar alcNoDeviceExtList[] = | |
346 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE " | |
347 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device"; | |
348 static const ALCchar alcExtensionList[] = | |
349 "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE " | |
350 "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX " | |
351 "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device"; | |
352 static const ALCint alcMajorVersion = 1; | |
353 static const ALCint alcMinorVersion = 1; | |
354 | |
355 static const ALCint alcEFXMajorVersion = 1; | |
356 static const ALCint alcEFXMinorVersion = 0; | |
357 | |
358 /////////////////////////////////////////////////////// | |
359 | |
360 | |
361 /////////////////////////////////////////////////////// | |
362 // Global Variables | |
363 | |
364 static CRITICAL_SECTION ListLock; | |
365 | |
366 /* Device List */ | |
367 static ALCdevice *g_pDeviceList = NULL; | |
368 static ALCuint g_ulDeviceCount = 0; | |
369 | |
370 // Context List | |
371 static ALCcontext *g_pContextList = NULL; | |
372 static ALCuint g_ulContextCount = 0; | |
373 | |
374 // Thread-local current context | |
375 static tls_type LocalContext; | |
376 // Process-wide current context | |
377 static ALCcontext *GlobalContext; | |
378 | |
379 // Context Error | |
380 static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR; | |
381 | |
382 // Default context extensions | |
383 static const ALchar alExtList[] = | |
384 "AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 " | |
385 "AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW " | |
386 "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model " | |
387 "AL_LOKI_quadriphonic AL_SOFTX_buffer_samples AL_SOFT_buffer_sub_data " | |
388 "AL_SOFTX_deferred_updates AL_SOFT_loop_points " | |
389 "AL_SOFTX_non_virtual_channels"; | |
390 | |
391 // Mixing Priority Level | |
392 ALint RTPrioLevel; | |
393 | |
394 // Output Log File | |
395 FILE *LogFile; | |
396 | |
397 // Output Log Level | |
398 #ifdef _DEBUG | |
399 enum LogLevel LogLevel = LogWarning; | |
400 #else | |
401 enum LogLevel LogLevel = LogError; | |
402 #endif | |
403 | |
404 // Cone scalar | |
405 ALdouble ConeScale = 0.5; | |
406 | |
407 // Localized Z scalar for mono sources | |
408 ALdouble ZScale = 1.0; | |
409 | |
410 /* One-time configuration init control */ | |
411 static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT; | |
412 | |
413 /////////////////////////////////////////////////////// | |
414 | |
415 | |
416 /////////////////////////////////////////////////////// | |
417 // ALC Related helper functions | |
418 static void ReleaseALC(ALCboolean doclose); | |
419 | |
420 static void alc_initconfig(void); | |
421 #define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig) | |
422 | |
423 #if defined(_WIN32) | |
424 static void alc_init(void); | |
425 static void alc_deinit(void); | |
426 static void alc_deinit_safe(void); | |
427 | |
428 #ifndef AL_LIBTYPE_STATIC | |
429 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) | |
430 { | |
431 // Perform actions based on the reason for calling. | |
432 switch(ul_reason_for_call) | |
433 { | |
434 case DLL_PROCESS_ATTACH: | |
435 DisableThreadLibraryCalls(hModule); | |
436 alc_init(); | |
437 break; | |
438 | |
439 case DLL_PROCESS_DETACH: | |
440 if(!lpReserved) | |
441 alc_deinit(); | |
442 else | |
443 alc_deinit_safe(); | |
444 break; | |
445 } | |
446 return TRUE; | |
447 } | |
448 #elif defined(_MSC_VER) | |
449 #pragma section(".CRT$XCU",read) | |
450 static void alc_constructor(void); | |
451 static void alc_destructor(void); | |
452 __declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor; | |
453 | |
454 static void alc_constructor(void) | |
455 { | |
456 atexit(alc_destructor); | |
457 alc_init(); | |
458 } | |
459 | |
460 static void alc_destructor(void) | |
461 { | |
462 alc_deinit(); | |
463 } | |
464 #elif defined(HAVE_GCC_DESTRUCTOR) | |
465 static void alc_init(void) __attribute__((constructor)); | |
466 static void alc_deinit(void) __attribute__((destructor)); | |
467 #else | |
468 #error "No static initialization available on this platform!" | |
469 #endif | |
470 #elif defined(HAVE_GCC_DESTRUCTOR) | |
471 static void alc_init(void) __attribute__((constructor)); | |
472 static void alc_deinit(void) __attribute__((destructor)); | |
473 #else | |
474 #error "No global initialization available on this platform!" | |
475 #endif | |
476 | |
477 static void alc_init(void) | |
478 { | |
479 const char *str; | |
480 | |
481 LogFile = stderr; | |
482 | |
483 str = getenv("__ALSOFT_HALF_ANGLE_CONES"); | |
484 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) | |
485 ConeScale = 1.0; | |
486 | |
487 str = getenv("__ALSOFT_REVERSE_Z"); | |
488 if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) | |
489 ZScale = -1.0; | |
490 | |
491 tls_create(&LocalContext); | |
492 InitializeCriticalSection(&ListLock); | |
493 ThunkInit(); | |
494 } | |
495 | |
496 static void alc_deinit_safe(void) | |
497 { | |
498 ReleaseALC(ALC_FALSE); | |
499 | |
500 FreeALConfig(); | |
501 | |
502 ThunkExit(); | |
503 DeleteCriticalSection(&ListLock); | |
504 tls_delete(LocalContext); | |
505 | |
506 if(LogFile != stderr) | |
507 fclose(LogFile); | |
508 LogFile = NULL; | |
509 } | |
510 | |
511 static void alc_deinit(void) | |
512 { | |
513 int i; | |
514 | |
515 ReleaseALC(ALC_TRUE); | |
516 | |
517 memset(&PlaybackBackend, 0, sizeof(PlaybackBackend)); | |
518 memset(&CaptureBackend, 0, sizeof(CaptureBackend)); | |
519 | |
520 for(i = 0;BackendList[i].Deinit;i++) | |
521 BackendList[i].Deinit(); | |
522 BackendLoopback.Deinit(); | |
523 | |
524 alc_deinit_safe(); | |
525 } | |
526 | |
527 static void alc_initconfig(void) | |
528 { | |
529 printf("OPENAL-AURELLEM: alc_init_config!!\n"); | |
530 const char *devs, *str; | |
531 int i, n; | |
532 | |
533 str = getenv("ALSOFT_LOGLEVEL"); | |
534 if(str) | |
535 { | |
536 long lvl = strtol(str, NULL, 0); | |
537 if(lvl >= NoLog && lvl <= LogTrace) | |
538 LogLevel = lvl; | |
539 } | |
540 | |
541 str = getenv("ALSOFT_LOGFILE"); | |
542 if(str && str[0]) | |
543 { | |
544 FILE *logfile = fopen(str, "wat"); | |
545 if(logfile) LogFile = logfile; | |
546 else ERR("Failed to open log file '%s'\n", str); | |
547 } | |
548 | |
549 ReadALConfig(); | |
550 | |
551 InitHrtf(); | |
552 | |
553 #ifdef _WIN32 | |
554 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 1); | |
555 #else | |
556 RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0); | |
557 #endif | |
558 | |
559 DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT); | |
560 if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN) | |
561 DefaultResampler = RESAMPLER_DEFAULT; | |
562 | |
563 ReverbBoost *= aluPow(10.0f, GetConfigValueFloat("reverb", "boost", 0.0f) / | |
564 20.0f); | |
565 EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE); | |
566 | |
567 devs = GetConfigValue(NULL, "drivers", ""); | |
568 //printf("these are the devices: %s\n", devs); | |
569 | |
570 if(devs[0]) | |
571 { | |
572 int n; | |
573 size_t len; | |
574 const char *next = devs; | |
575 int endlist, delitem; | |
576 | |
577 i = 0; | |
578 do { | |
579 devs = next; | |
580 //printf("AURELLEM: devs is %s\n",devs); | |
581 next = strchr(devs, ','); | |
582 | |
583 delitem = (devs[0] == '-'); | |
584 if(devs[0] == '-') devs++; | |
585 | |
586 if(!devs[0] || devs[0] == ',') | |
587 { | |
588 endlist = 0; | |
589 continue; | |
590 } | |
591 endlist = 1; | |
592 | |
593 len = (next ? ((size_t)(next-devs)) : strlen(devs)); | |
594 for(n = i;BackendList[n].Init;n++) | |
595 { | |
596 //printf("AURELLEM: device-name -- %s\n",BackendList[n].name); | |
597 if(len == strlen(BackendList[n].name) && | |
598 strncmp(BackendList[n].name, devs, len) == 0) | |
599 { | |
600 if(delitem) | |
601 { | |
602 do { | |
603 BackendList[n] = BackendList[n+1]; | |
604 ++n; | |
605 } | |
606 // this relies on the last entry being terminated by an | |
607 // entry with all nulls. | |
608 while(BackendList[n].Init); | |
609 } | |
610 else | |
611 { | |
612 struct BackendInfo Bkp = BackendList[n]; | |
613 while(n > i) | |
614 { | |
615 BackendList[n] = BackendList[n-1]; | |
616 --n; | |
617 } | |
618 BackendList[n] = Bkp; | |
619 | |
620 i++; | |
621 } | |
622 break; | |
623 } | |
624 } | |
625 } while(next++); | |
626 | |
627 if(endlist) | |
628 { | |
629 BackendList[i].name = NULL; | |
630 BackendList[i].Init = NULL; | |
631 BackendList[i].Deinit = NULL; | |
632 BackendList[i].Probe = NULL; | |
633 } | |
634 } | |
635 | |
636 for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++) | |
637 { | |
638 if(!BackendList[i].Init(&BackendList[i].Funcs)) | |
639 { | |
640 WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); | |
641 continue; | |
642 } | |
643 | |
644 TRACE("Initialized backend \"%s\"\n", BackendList[i].name); | |
645 if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name) | |
646 { | |
647 PlaybackBackend = BackendList[i]; | |
648 TRACE("Added \"%s\" for playback\n", PlaybackBackend.name); | |
649 } | |
650 if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name) | |
651 { | |
652 CaptureBackend = BackendList[i]; | |
653 TRACE("Added \"%s\" for capture\n", CaptureBackend.name); | |
654 } | |
655 } | |
656 BackendLoopback.Init(&BackendLoopback.Funcs); | |
657 | |
658 str = GetConfigValue(NULL, "excludefx", ""); | |
659 if(str[0]) | |
660 { | |
661 size_t len; | |
662 const char *next = str; | |
663 | |
664 do { | |
665 str = next; | |
666 next = strchr(str, ','); | |
667 | |
668 if(!str[0] || next == str) | |
669 continue; | |
670 | |
671 len = (next ? ((size_t)(next-str)) : strlen(str)); | |
672 for(n = 0;EffectList[n].name;n++) | |
673 { | |
674 if(len == strlen(EffectList[n].name) && | |
675 strncmp(EffectList[n].name, str, len) == 0) | |
676 DisabledEffects[EffectList[n].type] = AL_TRUE; | |
677 } | |
678 } while(next++); | |
679 } | |
680 } | |
681 | |
682 | |
683 static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type) | |
684 { | |
685 free(*list); | |
686 *list = NULL; | |
687 *listsize = 0; | |
688 | |
689 DO_INITCONFIG(); | |
690 if(type == CAPTURE_DEVICE_PROBE) | |
691 CaptureBackend.Probe(type); | |
692 else | |
693 PlaybackBackend.Probe(type); | |
694 } | |
695 | |
696 static void ProbeDeviceList(void) | |
697 { ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); } | |
698 static void ProbeAllDeviceList(void) | |
699 { ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); } | |
700 static void ProbeCaptureDeviceList(void) | |
701 { ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); } | |
702 | |
703 | |
704 static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize) | |
705 { | |
706 size_t len = strlen(name); | |
707 void *temp; | |
708 | |
709 if(len == 0) | |
710 return; | |
711 | |
712 temp = realloc(*List, (*ListSize) + len + 2); | |
713 if(!temp) | |
714 { | |
715 ERR("Realloc failed to add %s!\n", name); | |
716 return; | |
717 } | |
718 *List = temp; | |
719 | |
720 memcpy((*List)+(*ListSize), name, len+1); | |
721 *ListSize += len+1; | |
722 (*List)[*ListSize] = 0; | |
723 } | |
724 | |
725 #define DECL_APPEND_LIST_FUNC(type) \ | |
726 void Append##type##List(const ALCchar *name) \ | |
727 { AppendList(name, &alc##type##List, &alc##type##ListSize); } | |
728 | |
729 DECL_APPEND_LIST_FUNC(Device) | |
730 DECL_APPEND_LIST_FUNC(AllDevice) | |
731 DECL_APPEND_LIST_FUNC(CaptureDevice) | |
732 | |
733 #undef DECL_APPEND_LIST_FUNC | |
734 | |
735 | |
736 /* Sets the default channel order used by most non-WaveFormatEx-based APIs */ | |
737 void SetDefaultChannelOrder(ALCdevice *device) | |
738 { | |
739 switch(device->FmtChans) | |
740 { | |
741 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT; | |
742 device->DevChannels[1] = FRONT_RIGHT; | |
743 device->DevChannels[2] = BACK_LEFT; | |
744 device->DevChannels[3] = BACK_RIGHT; | |
745 device->DevChannels[4] = FRONT_CENTER; | |
746 device->DevChannels[5] = LFE; | |
747 return; | |
748 | |
749 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT; | |
750 device->DevChannels[1] = FRONT_RIGHT; | |
751 device->DevChannels[2] = BACK_LEFT; | |
752 device->DevChannels[3] = BACK_RIGHT; | |
753 device->DevChannels[4] = FRONT_CENTER; | |
754 device->DevChannels[5] = LFE; | |
755 device->DevChannels[6] = SIDE_LEFT; | |
756 device->DevChannels[7] = SIDE_RIGHT; | |
757 return; | |
758 | |
759 /* Same as WFX order */ | |
760 case DevFmtMono: | |
761 case DevFmtStereo: | |
762 case DevFmtQuad: | |
763 case DevFmtX51Side: | |
764 case DevFmtX61: | |
765 break; | |
766 } | |
767 SetDefaultWFXChannelOrder(device); | |
768 } | |
769 /* Sets the default order used by WaveFormatEx */ | |
770 void SetDefaultWFXChannelOrder(ALCdevice *device) | |
771 { | |
772 switch(device->FmtChans) | |
773 { | |
774 case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break; | |
775 | |
776 case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT; | |
777 device->DevChannels[1] = FRONT_RIGHT; break; | |
778 | |
779 case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT; | |
780 device->DevChannels[1] = FRONT_RIGHT; | |
781 device->DevChannels[2] = BACK_LEFT; | |
782 device->DevChannels[3] = BACK_RIGHT; break; | |
783 | |
784 case DevFmtX51: device->DevChannels[0] = FRONT_LEFT; | |
785 device->DevChannels[1] = FRONT_RIGHT; | |
786 device->DevChannels[2] = FRONT_CENTER; | |
787 device->DevChannels[3] = LFE; | |
788 device->DevChannels[4] = BACK_LEFT; | |
789 device->DevChannels[5] = BACK_RIGHT; break; | |
790 | |
791 case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT; | |
792 device->DevChannels[1] = FRONT_RIGHT; | |
793 device->DevChannels[2] = FRONT_CENTER; | |
794 device->DevChannels[3] = LFE; | |
795 device->DevChannels[4] = SIDE_LEFT; | |
796 device->DevChannels[5] = SIDE_RIGHT; break; | |
797 | |
798 case DevFmtX61: device->DevChannels[0] = FRONT_LEFT; | |
799 device->DevChannels[1] = FRONT_RIGHT; | |
800 device->DevChannels[2] = FRONT_CENTER; | |
801 device->DevChannels[3] = LFE; | |
802 device->DevChannels[4] = BACK_CENTER; | |
803 device->DevChannels[5] = SIDE_LEFT; | |
804 device->DevChannels[6] = SIDE_RIGHT; break; | |
805 | |
806 case DevFmtX71: device->DevChannels[0] = FRONT_LEFT; | |
807 device->DevChannels[1] = FRONT_RIGHT; | |
808 device->DevChannels[2] = FRONT_CENTER; | |
809 device->DevChannels[3] = LFE; | |
810 device->DevChannels[4] = BACK_LEFT; | |
811 device->DevChannels[5] = BACK_RIGHT; | |
812 device->DevChannels[6] = SIDE_LEFT; | |
813 device->DevChannels[7] = SIDE_RIGHT; break; | |
814 } | |
815 } | |
816 | |
817 | |
818 const ALCchar *DevFmtTypeString(enum DevFmtType type) | |
819 { | |
820 switch(type) | |
821 { | |
822 case DevFmtByte: return "Signed Byte"; | |
823 case DevFmtUByte: return "Unsigned Byte"; | |
824 case DevFmtShort: return "Signed Short"; | |
825 case DevFmtUShort: return "Unsigned Short"; | |
826 case DevFmtFloat: return "Float"; | |
827 } | |
828 return "(unknown type)"; | |
829 } | |
830 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) | |
831 { | |
832 switch(chans) | |
833 { | |
834 case DevFmtMono: return "Mono"; | |
835 case DevFmtStereo: return "Stereo"; | |
836 case DevFmtQuad: return "Quadraphonic"; | |
837 case DevFmtX51: return "5.1 Surround"; | |
838 case DevFmtX51Side: return "5.1 Side"; | |
839 case DevFmtX61: return "6.1 Surround"; | |
840 case DevFmtX71: return "7.1 Surround"; | |
841 } | |
842 return "(unknown channels)"; | |
843 } | |
844 | |
845 ALuint BytesFromDevFmt(enum DevFmtType type) | |
846 { | |
847 switch(type) | |
848 { | |
849 case DevFmtByte: return sizeof(ALbyte); | |
850 case DevFmtUByte: return sizeof(ALubyte); | |
851 case DevFmtShort: return sizeof(ALshort); | |
852 case DevFmtUShort: return sizeof(ALushort); | |
853 case DevFmtFloat: return sizeof(ALfloat); | |
854 } | |
855 return 0; | |
856 } | |
857 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) | |
858 { | |
859 switch(chans) | |
860 { | |
861 case DevFmtMono: return 1; | |
862 case DevFmtStereo: return 2; | |
863 case DevFmtQuad: return 4; | |
864 case DevFmtX51: return 6; | |
865 case DevFmtX51Side: return 6; | |
866 case DevFmtX61: return 7; | |
867 case DevFmtX71: return 8; | |
868 } | |
869 return 0; | |
870 } | |
871 ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans, | |
872 enum DevFmtType *type) | |
873 { | |
874 switch(format) | |
875 { | |
876 case AL_FORMAT_MONO8: | |
877 *chans = DevFmtMono; | |
878 *type = DevFmtUByte; | |
879 return AL_TRUE; | |
880 case AL_FORMAT_MONO16: | |
881 *chans = DevFmtMono; | |
882 *type = DevFmtShort; | |
883 return AL_TRUE; | |
884 case AL_FORMAT_MONO_FLOAT32: | |
885 *chans = DevFmtMono; | |
886 *type = DevFmtFloat; | |
887 return AL_TRUE; | |
888 case AL_FORMAT_STEREO8: | |
889 *chans = DevFmtStereo; | |
890 *type = DevFmtUByte; | |
891 return AL_TRUE; | |
892 case AL_FORMAT_STEREO16: | |
893 *chans = DevFmtStereo; | |
894 *type = DevFmtShort; | |
895 return AL_TRUE; | |
896 case AL_FORMAT_STEREO_FLOAT32: | |
897 *chans = DevFmtStereo; | |
898 *type = DevFmtFloat; | |
899 return AL_TRUE; | |
900 case AL_FORMAT_QUAD8: | |
901 *chans = DevFmtQuad; | |
902 *type = DevFmtUByte; | |
903 return AL_TRUE; | |
904 case AL_FORMAT_QUAD16: | |
905 *chans = DevFmtQuad; | |
906 *type = DevFmtShort; | |
907 return AL_TRUE; | |
908 case AL_FORMAT_QUAD32: | |
909 *chans = DevFmtQuad; | |
910 *type = DevFmtFloat; | |
911 return AL_TRUE; | |
912 case AL_FORMAT_51CHN8: | |
913 *chans = DevFmtX51; | |
914 *type = DevFmtUByte; | |
915 return AL_TRUE; | |
916 case AL_FORMAT_51CHN16: | |
917 *chans = DevFmtX51; | |
918 *type = DevFmtShort; | |
919 return AL_TRUE; | |
920 case AL_FORMAT_51CHN32: | |
921 *chans = DevFmtX51; | |
922 *type = DevFmtFloat; | |
923 return AL_TRUE; | |
924 case AL_FORMAT_61CHN8: | |
925 *chans = DevFmtX61; | |
926 *type = DevFmtUByte; | |
927 return AL_TRUE; | |
928 case AL_FORMAT_61CHN16: | |
929 *chans = DevFmtX61; | |
930 *type = DevFmtShort; | |
931 return AL_TRUE; | |
932 case AL_FORMAT_61CHN32: | |
933 *chans = DevFmtX61; | |
934 *type = DevFmtFloat; | |
935 return AL_TRUE; | |
936 case AL_FORMAT_71CHN8: | |
937 *chans = DevFmtX71; | |
938 *type = DevFmtUByte; | |
939 return AL_TRUE; | |
940 case AL_FORMAT_71CHN16: | |
941 *chans = DevFmtX71; | |
942 *type = DevFmtShort; | |
943 return AL_TRUE; | |
944 case AL_FORMAT_71CHN32: | |
945 *chans = DevFmtX71; | |
946 *type = DevFmtFloat; | |
947 return AL_TRUE; | |
948 } | |
949 return AL_FALSE; | |
950 } | |
951 | |
952 static ALCboolean IsValidALCType(ALCenum type) | |
953 { | |
954 switch(type) | |
955 { | |
956 case ALC_BYTE: | |
957 case ALC_UNSIGNED_BYTE: | |
958 case ALC_SHORT: | |
959 case ALC_UNSIGNED_SHORT: | |
960 case ALC_INT: | |
961 case ALC_UNSIGNED_INT: | |
962 case ALC_FLOAT: | |
963 return ALC_TRUE; | |
964 } | |
965 return ALC_FALSE; | |
966 } | |
967 | |
968 static ALCboolean IsValidALCChannels(ALCenum channels) | |
969 { | |
970 switch(channels) | |
971 { | |
972 case ALC_MONO: | |
973 case ALC_STEREO: | |
974 case ALC_QUAD: | |
975 case ALC_5POINT1: | |
976 case ALC_6POINT1: | |
977 case ALC_7POINT1: | |
978 return ALC_TRUE; | |
979 } | |
980 return ALC_FALSE; | |
981 } | |
982 | |
983 | |
984 static void LockLists(void) | |
985 { | |
986 EnterCriticalSection(&ListLock); | |
987 } | |
988 | |
989 static void UnlockLists(void) | |
990 { | |
991 LeaveCriticalSection(&ListLock); | |
992 } | |
993 | |
994 /* | |
995 IsDevice | |
996 | |
997 Check pDevice is a valid Device pointer | |
998 */ | |
999 static ALCboolean IsDevice(ALCdevice *pDevice) | |
1000 { | |
1001 ALCdevice *pTempDevice; | |
1002 | |
1003 pTempDevice = g_pDeviceList; | |
1004 while(pTempDevice && pTempDevice != pDevice) | |
1005 pTempDevice = pTempDevice->next; | |
1006 | |
1007 return (pTempDevice ? ALC_TRUE : ALC_FALSE); | |
1008 } | |
1009 | |
1010 /* | |
1011 IsContext | |
1012 | |
1013 Check pContext is a valid Context pointer | |
1014 */ | |
1015 static ALCboolean IsContext(ALCcontext *pContext) | |
1016 { | |
1017 ALCcontext *pTempContext; | |
1018 | |
1019 pTempContext = g_pContextList; | |
1020 while (pTempContext && pTempContext != pContext) | |
1021 pTempContext = pTempContext->next; | |
1022 | |
1023 return (pTempContext ? ALC_TRUE : ALC_FALSE); | |
1024 } | |
1025 | |
1026 | |
1027 /* | |
1028 alcSetError | |
1029 | |
1030 Store latest ALC Error | |
1031 */ | |
1032 ALCvoid alcSetError(ALCdevice *device, ALenum errorCode) | |
1033 { | |
1034 LockLists(); | |
1035 if(IsDevice(device)) | |
1036 device->LastError = errorCode; | |
1037 else | |
1038 g_eLastNullDeviceError = errorCode; | |
1039 UnlockLists(); | |
1040 } | |
1041 | |
1042 | |
1043 /* UpdateDeviceParams: | |
1044 * | |
1045 * Updates device parameters according to the attribute list. | |
1046 */ | |
1047 static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) | |
1048 { | |
1049 ALuint i; | |
1050 | |
1051 // Check for attributes | |
1052 if(attrList && attrList[0]) | |
1053 { | |
1054 ALCuint freq, numMono, numStereo, numSends; | |
1055 enum DevFmtChannels schans; | |
1056 enum DevFmtType stype; | |
1057 ALuint attrIdx; | |
1058 | |
1059 // If a context is already running on the device, stop playback so the | |
1060 // device attributes can be updated | |
1061 if((device->Flags&DEVICE_RUNNING)) | |
1062 ALCdevice_StopPlayback(device); | |
1063 device->Flags &= ~DEVICE_RUNNING; | |
1064 | |
1065 freq = device->Frequency; | |
1066 schans = device->FmtChans; | |
1067 stype = device->FmtType; | |
1068 numMono = device->NumMonoSources; | |
1069 numStereo = device->NumStereoSources; | |
1070 numSends = device->NumAuxSends; | |
1071 | |
1072 freq = GetConfigValueInt(NULL, "frequency", freq); | |
1073 if(freq < 8000) freq = 8000; | |
1074 | |
1075 attrIdx = 0; | |
1076 while(attrList[attrIdx]) | |
1077 { | |
1078 if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT && | |
1079 device->IsLoopbackDevice) | |
1080 { | |
1081 ALCint val = attrList[attrIdx + 1]; | |
1082 if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val)) | |
1083 { | |
1084 alcSetError(device, ALC_INVALID_VALUE); | |
1085 return ALC_FALSE; | |
1086 } | |
1087 schans = val; | |
1088 } | |
1089 | |
1090 if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT && | |
1091 device->IsLoopbackDevice) | |
1092 { | |
1093 ALCint val = attrList[attrIdx + 1]; | |
1094 if(!IsValidALCType(val) || !BytesFromDevFmt(val)) | |
1095 { | |
1096 alcSetError(device, ALC_INVALID_VALUE); | |
1097 return ALC_FALSE; | |
1098 } | |
1099 stype = val; | |
1100 } | |
1101 | |
1102 if(attrList[attrIdx] == ALC_FREQUENCY) | |
1103 { | |
1104 if(device->IsLoopbackDevice) | |
1105 { | |
1106 freq = attrList[attrIdx + 1]; | |
1107 if(freq < 8000) | |
1108 { | |
1109 alcSetError(device, ALC_INVALID_VALUE); | |
1110 return ALC_FALSE; | |
1111 } | |
1112 } | |
1113 else if(!ConfigValueExists(NULL, "frequency")) | |
1114 { | |
1115 freq = attrList[attrIdx + 1]; | |
1116 if(freq < 8000) freq = 8000; | |
1117 device->Flags |= DEVICE_FREQUENCY_REQUEST; | |
1118 } | |
1119 } | |
1120 | |
1121 if(attrList[attrIdx] == ALC_STEREO_SOURCES) | |
1122 { | |
1123 numStereo = attrList[attrIdx + 1]; | |
1124 if(numStereo > device->MaxNoOfSources) | |
1125 numStereo = device->MaxNoOfSources; | |
1126 | |
1127 numMono = device->MaxNoOfSources - numStereo; | |
1128 } | |
1129 | |
1130 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS && | |
1131 !ConfigValueExists(NULL, "sends")) | |
1132 { | |
1133 numSends = attrList[attrIdx + 1]; | |
1134 if(numSends > MAX_SENDS) | |
1135 numSends = MAX_SENDS; | |
1136 } | |
1137 | |
1138 attrIdx += 2; | |
1139 } | |
1140 | |
1141 device->UpdateSize = (ALuint64)device->UpdateSize * freq / | |
1142 device->Frequency; | |
1143 | |
1144 device->Frequency = freq; | |
1145 device->FmtChans = schans; | |
1146 device->FmtType = stype; | |
1147 device->NumMonoSources = numMono; | |
1148 device->NumStereoSources = numStereo; | |
1149 device->NumAuxSends = numSends; | |
1150 } | |
1151 | |
1152 if((device->Flags&DEVICE_RUNNING)) | |
1153 return ALC_TRUE; | |
1154 | |
1155 LockDevice(device); | |
1156 TRACE("Format pre-setup: %s%s, %s, %uhz%s, %u update size x%d\n", | |
1157 DevFmtChannelsString(device->FmtChans), | |
1158 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"", | |
1159 DevFmtTypeString(device->FmtType), device->Frequency, | |
1160 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"", | |
1161 device->UpdateSize, device->NumUpdates); | |
1162 if(ALCdevice_ResetPlayback(device) == ALC_FALSE) | |
1163 { | |
1164 UnlockDevice(device); | |
1165 return ALC_FALSE; | |
1166 } | |
1167 device->Flags |= DEVICE_RUNNING; | |
1168 TRACE("Format post-setup: %s%s, %s, %uhz%s, %u update size x%d\n", | |
1169 DevFmtChannelsString(device->FmtChans), | |
1170 (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"", | |
1171 DevFmtTypeString(device->FmtType), device->Frequency, | |
1172 (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"", | |
1173 device->UpdateSize, device->NumUpdates); | |
1174 | |
1175 aluInitPanning(device); | |
1176 | |
1177 for(i = 0;i < MAXCHANNELS;i++) | |
1178 { | |
1179 device->ClickRemoval[i] = 0.0f; | |
1180 device->PendingClicks[i] = 0.0f; | |
1181 } | |
1182 | |
1183 if(!device->IsLoopbackDevice && GetConfigValueBool(NULL, "hrtf", AL_FALSE)) | |
1184 device->Flags |= DEVICE_USE_HRTF; | |
1185 if((device->Flags&DEVICE_USE_HRTF) && !IsHrtfCompatible(device)) | |
1186 device->Flags &= ~DEVICE_USE_HRTF; | |
1187 TRACE("HRTF %s\n", (device->Flags&DEVICE_USE_HRTF)?"enabled":"disabled"); | |
1188 | |
1189 if(!(device->Flags&DEVICE_USE_HRTF) && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6) | |
1190 { | |
1191 if(!device->Bs2b) | |
1192 { | |
1193 device->Bs2b = calloc(1, sizeof(*device->Bs2b)); | |
1194 bs2b_clear(device->Bs2b); | |
1195 } | |
1196 bs2b_set_srate(device->Bs2b, device->Frequency); | |
1197 bs2b_set_level(device->Bs2b, device->Bs2bLevel); | |
1198 TRACE("BS2B level %d\n", device->Bs2bLevel); | |
1199 } | |
1200 else | |
1201 { | |
1202 free(device->Bs2b); | |
1203 device->Bs2b = NULL; | |
1204 TRACE("BS2B disabled\n"); | |
1205 } | |
1206 | |
1207 device->Flags &= ~DEVICE_DUPLICATE_STEREO; | |
1208 switch(device->FmtChans) | |
1209 { | |
1210 case DevFmtMono: | |
1211 case DevFmtStereo: | |
1212 break; | |
1213 case DevFmtQuad: | |
1214 case DevFmtX51: | |
1215 case DevFmtX51Side: | |
1216 case DevFmtX61: | |
1217 case DevFmtX71: | |
1218 if(GetConfigValueBool(NULL, "stereodup", AL_TRUE)) | |
1219 device->Flags |= DEVICE_DUPLICATE_STEREO; | |
1220 break; | |
1221 } | |
1222 TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled"); | |
1223 | |
1224 for(i = 0;i < device->NumContexts;i++) | |
1225 { | |
1226 ALCcontext *context = device->Contexts[i]; | |
1227 ALsizei pos; | |
1228 | |
1229 context->UpdateSources = AL_FALSE; | |
1230 for(pos = 0;pos < context->EffectSlotMap.size;pos++) | |
1231 { | |
1232 ALeffectslot *slot = context->EffectSlotMap.array[pos].value; | |
1233 | |
1234 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE) | |
1235 { | |
1236 UnlockDevice(device); | |
1237 ALCdevice_StopPlayback(device); | |
1238 device->Flags &= ~DEVICE_RUNNING; | |
1239 return ALC_FALSE; | |
1240 } | |
1241 slot->NeedsUpdate = AL_FALSE; | |
1242 ALEffect_Update(slot->EffectState, context, slot); | |
1243 } | |
1244 | |
1245 for(pos = 0;pos < context->SourceMap.size;pos++) | |
1246 { | |
1247 ALsource *source = context->SourceMap.array[pos].value; | |
1248 ALuint s = device->NumAuxSends; | |
1249 while(s < MAX_SENDS) | |
1250 { | |
1251 if(source->Send[s].Slot) | |
1252 source->Send[s].Slot->refcount--; | |
1253 source->Send[s].Slot = NULL; | |
1254 source->Send[s].WetFilter.type = 0; | |
1255 source->Send[s].WetFilter.filter = 0; | |
1256 s++; | |
1257 } | |
1258 source->NeedsUpdate = AL_FALSE; | |
1259 ALsource_Update(source, context); | |
1260 } | |
1261 } | |
1262 UnlockDevice(device); | |
1263 | |
1264 return ALC_TRUE; | |
1265 } | |
1266 | |
1267 | |
1268 ALCvoid LockDevice(ALCdevice *device) | |
1269 { | |
1270 EnterCriticalSection(&device->Mutex); | |
1271 } | |
1272 | |
1273 ALCvoid UnlockDevice(ALCdevice *device) | |
1274 { | |
1275 LeaveCriticalSection(&device->Mutex); | |
1276 } | |
1277 | |
1278 /* | |
1279 LockContext | |
1280 | |
1281 Thread-safe entry | |
1282 */ | |
1283 ALCvoid LockContext(ALCcontext *context) | |
1284 { | |
1285 EnterCriticalSection(&context->Device->Mutex); | |
1286 } | |
1287 | |
1288 | |
1289 /* | |
1290 UnlockContext | |
1291 | |
1292 Thread-safe exit | |
1293 */ | |
1294 ALCvoid UnlockContext(ALCcontext *context) | |
1295 { | |
1296 LeaveCriticalSection(&context->Device->Mutex); | |
1297 } | |
1298 | |
1299 | |
1300 /* | |
1301 GetLockedContext | |
1302 | |
1303 Returns the currently active Context, in a locked state | |
1304 */ | |
1305 ALCcontext *GetLockedContext(void) | |
1306 { | |
1307 ALCcontext *pContext = NULL; | |
1308 | |
1309 LockLists(); | |
1310 | |
1311 pContext = tls_get(LocalContext); | |
1312 if(pContext && !IsContext(pContext)) | |
1313 { | |
1314 tls_set(LocalContext, NULL); | |
1315 pContext = NULL; | |
1316 } | |
1317 if(!pContext) | |
1318 pContext = GlobalContext; | |
1319 if(pContext) | |
1320 LockContext(pContext); | |
1321 | |
1322 UnlockLists(); | |
1323 | |
1324 return pContext; | |
1325 } | |
1326 | |
1327 | |
1328 /* | |
1329 InitContext | |
1330 | |
1331 Initialize Context variables | |
1332 */ | |
1333 static ALvoid InitContext(ALCcontext *pContext) | |
1334 { | |
1335 //Initialise listener | |
1336 pContext->Listener.Gain = 1.0f; | |
1337 pContext->Listener.MetersPerUnit = 1.0f; | |
1338 pContext->Listener.Position[0] = 0.0f; | |
1339 pContext->Listener.Position[1] = 0.0f; | |
1340 pContext->Listener.Position[2] = 0.0f; | |
1341 pContext->Listener.Velocity[0] = 0.0f; | |
1342 pContext->Listener.Velocity[1] = 0.0f; | |
1343 pContext->Listener.Velocity[2] = 0.0f; | |
1344 pContext->Listener.Forward[0] = 0.0f; | |
1345 pContext->Listener.Forward[1] = 0.0f; | |
1346 pContext->Listener.Forward[2] = -1.0f; | |
1347 pContext->Listener.Up[0] = 0.0f; | |
1348 pContext->Listener.Up[1] = 1.0f; | |
1349 pContext->Listener.Up[2] = 0.0f; | |
1350 | |
1351 //Validate pContext | |
1352 pContext->LastError = AL_NO_ERROR; | |
1353 pContext->UpdateSources = AL_FALSE; | |
1354 pContext->ActiveSourceCount = 0; | |
1355 InitUIntMap(&pContext->SourceMap); | |
1356 InitUIntMap(&pContext->EffectSlotMap); | |
1357 | |
1358 //Set globals | |
1359 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED; | |
1360 pContext->SourceDistanceModel = AL_FALSE; | |
1361 pContext->DopplerFactor = 1.0f; | |
1362 pContext->DopplerVelocity = 1.0f; | |
1363 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC; | |
1364 pContext->DeferUpdates = AL_FALSE; | |
1365 | |
1366 pContext->ExtensionList = alExtList; | |
1367 } | |
1368 | |
1369 | |
1370 /* | |
1371 FreeContext | |
1372 | |
1373 Clean up Context, destroy any remaining Sources | |
1374 */ | |
1375 static ALCvoid FreeContext(ALCcontext *context) | |
1376 { | |
1377 //Invalidate context | |
1378 memset(context, 0, sizeof(ALCcontext)); | |
1379 free(context); | |
1380 } | |
1381 | |
1382 /////////////////////////////////////////////////////// | |
1383 | |
1384 | |
1385 /////////////////////////////////////////////////////// | |
1386 // ALC Functions calls | |
1387 | |
1388 | |
1389 // This should probably move to another c file but for now ... | |
1390 ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize) | |
1391 { | |
1392 ALCdevice *device = NULL; | |
1393 | |
1394 DO_INITCONFIG(); | |
1395 | |
1396 if(!CaptureBackend.name) | |
1397 { | |
1398 alcSetError(NULL, ALC_INVALID_VALUE); | |
1399 return NULL; | |
1400 } | |
1401 | |
1402 if(SampleSize <= 0) | |
1403 { | |
1404 alcSetError(NULL, ALC_INVALID_VALUE); | |
1405 return NULL; | |
1406 } | |
1407 | |
1408 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0)) | |
1409 deviceName = NULL; | |
1410 | |
1411 device = calloc(1, sizeof(ALCdevice)); | |
1412 if(!device) | |
1413 { | |
1414 alcSetError(NULL, ALC_OUT_OF_MEMORY); | |
1415 return NULL; | |
1416 } | |
1417 | |
1418 //Validate device | |
1419 device->Funcs = &CaptureBackend.Funcs; | |
1420 device->Connected = ALC_TRUE; | |
1421 device->IsCaptureDevice = AL_TRUE; | |
1422 device->IsLoopbackDevice = AL_FALSE; | |
1423 InitializeCriticalSection(&device->Mutex); | |
1424 | |
1425 device->szDeviceName = NULL; | |
1426 | |
1427 device->Flags |= DEVICE_FREQUENCY_REQUEST; | |
1428 device->Frequency = frequency; | |
1429 | |
1430 device->Flags |= DEVICE_CHANNELS_REQUEST; | |
1431 if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE) | |
1432 { | |
1433 free(device); | |
1434 alcSetError(NULL, ALC_INVALID_ENUM); | |
1435 return NULL; | |
1436 } | |
1437 | |
1438 device->UpdateSize = SampleSize; | |
1439 device->NumUpdates = 1; | |
1440 | |
1441 LockLists(); | |
1442 if(ALCdevice_OpenCapture(device, deviceName)) | |
1443 { | |
1444 device->next = g_pDeviceList; | |
1445 g_pDeviceList = device; | |
1446 g_ulDeviceCount++; | |
1447 } | |
1448 else | |
1449 { | |
1450 DeleteCriticalSection(&device->Mutex); | |
1451 free(device); | |
1452 device = NULL; | |
1453 alcSetError(NULL, ALC_INVALID_VALUE); | |
1454 } | |
1455 UnlockLists(); | |
1456 | |
1457 return device; | |
1458 } | |
1459 | |
1460 ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice) | |
1461 { | |
1462 ALCdevice **list; | |
1463 | |
1464 LockLists(); | |
1465 list = &g_pDeviceList; | |
1466 while(*list && *list != pDevice) | |
1467 list = &(*list)->next; | |
1468 | |
1469 if(!*list || !(*list)->IsCaptureDevice) | |
1470 { | |
1471 alcSetError(*list, ALC_INVALID_DEVICE); | |
1472 UnlockLists(); | |
1473 return ALC_FALSE; | |
1474 } | |
1475 | |
1476 *list = (*list)->next; | |
1477 g_ulDeviceCount--; | |
1478 | |
1479 UnlockLists(); | |
1480 | |
1481 LockDevice(pDevice); | |
1482 ALCdevice_CloseCapture(pDevice); | |
1483 UnlockDevice(pDevice); | |
1484 | |
1485 free(pDevice->szDeviceName); | |
1486 pDevice->szDeviceName = NULL; | |
1487 | |
1488 DeleteCriticalSection(&pDevice->Mutex); | |
1489 | |
1490 free(pDevice); | |
1491 | |
1492 return ALC_TRUE; | |
1493 } | |
1494 | |
1495 ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) | |
1496 { | |
1497 LockLists(); | |
1498 if(!IsDevice(device) || !device->IsCaptureDevice) | |
1499 { | |
1500 alcSetError(device, ALC_INVALID_DEVICE); | |
1501 UnlockLists(); | |
1502 return; | |
1503 } | |
1504 LockDevice(device); | |
1505 UnlockLists(); | |
1506 if(device->Connected) | |
1507 ALCdevice_StartCapture(device); | |
1508 UnlockDevice(device); | |
1509 } | |
1510 | |
1511 ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) | |
1512 { | |
1513 LockLists(); | |
1514 if(!IsDevice(device) || !device->IsCaptureDevice) | |
1515 { | |
1516 alcSetError(device, ALC_INVALID_DEVICE); | |
1517 UnlockLists(); | |
1518 return; | |
1519 } | |
1520 LockDevice(device); | |
1521 UnlockLists(); | |
1522 if(device->Connected) | |
1523 ALCdevice_StopCapture(device); | |
1524 UnlockDevice(device); | |
1525 } | |
1526 | |
1527 ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) | |
1528 { | |
1529 LockLists(); | |
1530 if(!IsDevice(device) || !device->IsCaptureDevice) | |
1531 { | |
1532 alcSetError(device, ALC_INVALID_DEVICE); | |
1533 UnlockLists(); | |
1534 return; | |
1535 } | |
1536 LockDevice(device); | |
1537 UnlockLists(); | |
1538 if(device->Connected) | |
1539 ALCdevice_CaptureSamples(device, buffer, samples); | |
1540 UnlockDevice(device); | |
1541 } | |
1542 | |
1543 /* | |
1544 alcGetError | |
1545 | |
1546 Return last ALC generated error code | |
1547 */ | |
1548 ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) | |
1549 { | |
1550 ALCenum errorCode; | |
1551 | |
1552 LockLists(); | |
1553 if(IsDevice(device)) | |
1554 { | |
1555 errorCode = device->LastError; | |
1556 device->LastError = ALC_NO_ERROR; | |
1557 } | |
1558 else | |
1559 { | |
1560 errorCode = g_eLastNullDeviceError; | |
1561 g_eLastNullDeviceError = ALC_NO_ERROR; | |
1562 } | |
1563 UnlockLists(); | |
1564 return errorCode; | |
1565 } | |
1566 | |
1567 | |
1568 /* | |
1569 alcSuspendContext | |
1570 | |
1571 Not functional | |
1572 */ | |
1573 ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context) | |
1574 { | |
1575 (void)Context; | |
1576 } | |
1577 | |
1578 | |
1579 /* | |
1580 alcProcessContext | |
1581 | |
1582 Not functional | |
1583 */ | |
1584 ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context) | |
1585 { | |
1586 (void)Context; | |
1587 } | |
1588 | |
1589 | |
1590 /* | |
1591 alcGetString | |
1592 | |
1593 Returns information about the Device, and error strings | |
1594 */ | |
1595 ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param) | |
1596 { | |
1597 const ALCchar *value = NULL; | |
1598 | |
1599 switch(param) | |
1600 { | |
1601 case ALC_NO_ERROR: | |
1602 value = alcNoError; | |
1603 break; | |
1604 | |
1605 case ALC_INVALID_ENUM: | |
1606 value = alcErrInvalidEnum; | |
1607 break; | |
1608 | |
1609 case ALC_INVALID_VALUE: | |
1610 value = alcErrInvalidValue; | |
1611 break; | |
1612 | |
1613 case ALC_INVALID_DEVICE: | |
1614 value = alcErrInvalidDevice; | |
1615 break; | |
1616 | |
1617 case ALC_INVALID_CONTEXT: | |
1618 value = alcErrInvalidContext; | |
1619 break; | |
1620 | |
1621 case ALC_OUT_OF_MEMORY: | |
1622 value = alcErrOutOfMemory; | |
1623 break; | |
1624 | |
1625 case ALC_DEVICE_SPECIFIER: | |
1626 LockLists(); | |
1627 if(IsDevice(pDevice)) | |
1628 value = pDevice->szDeviceName; | |
1629 else | |
1630 { | |
1631 ProbeDeviceList(); | |
1632 value = alcDeviceList; | |
1633 } | |
1634 UnlockLists(); | |
1635 break; | |
1636 | |
1637 case ALC_ALL_DEVICES_SPECIFIER: | |
1638 ProbeAllDeviceList(); | |
1639 value = alcAllDeviceList; | |
1640 break; | |
1641 | |
1642 case ALC_CAPTURE_DEVICE_SPECIFIER: | |
1643 LockLists(); | |
1644 if(IsDevice(pDevice)) | |
1645 value = pDevice->szDeviceName; | |
1646 else | |
1647 { | |
1648 ProbeCaptureDeviceList(); | |
1649 value = alcCaptureDeviceList; | |
1650 } | |
1651 UnlockLists(); | |
1652 break; | |
1653 | |
1654 /* Default devices are always first in the list */ | |
1655 case ALC_DEFAULT_DEVICE_SPECIFIER: | |
1656 if(!alcDeviceList) | |
1657 ProbeDeviceList(); | |
1658 | |
1659 free(alcDefaultDeviceSpecifier); | |
1660 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : ""); | |
1661 if(!alcDefaultDeviceSpecifier) | |
1662 alcSetError(pDevice, ALC_OUT_OF_MEMORY); | |
1663 value = alcDefaultDeviceSpecifier; | |
1664 break; | |
1665 | |
1666 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: | |
1667 if(!alcAllDeviceList) | |
1668 ProbeAllDeviceList(); | |
1669 | |
1670 free(alcDefaultAllDeviceSpecifier); | |
1671 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ? | |
1672 alcAllDeviceList : ""); | |
1673 if(!alcDefaultAllDeviceSpecifier) | |
1674 alcSetError(pDevice, ALC_OUT_OF_MEMORY); | |
1675 value = alcDefaultAllDeviceSpecifier; | |
1676 break; | |
1677 | |
1678 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: | |
1679 if(!alcCaptureDeviceList) | |
1680 ProbeCaptureDeviceList(); | |
1681 | |
1682 free(alcCaptureDefaultDeviceSpecifier); | |
1683 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ? | |
1684 alcCaptureDeviceList : ""); | |
1685 if(!alcCaptureDefaultDeviceSpecifier) | |
1686 alcSetError(pDevice, ALC_OUT_OF_MEMORY); | |
1687 value = alcCaptureDefaultDeviceSpecifier; | |
1688 break; | |
1689 | |
1690 case ALC_EXTENSIONS: | |
1691 LockLists(); | |
1692 if(IsDevice(pDevice)) | |
1693 value = alcExtensionList; | |
1694 else | |
1695 value = alcNoDeviceExtList; | |
1696 UnlockLists(); | |
1697 break; | |
1698 | |
1699 default: | |
1700 alcSetError(pDevice, ALC_INVALID_ENUM); | |
1701 break; | |
1702 } | |
1703 | |
1704 return value; | |
1705 } | |
1706 | |
1707 | |
1708 /* | |
1709 alcGetIntegerv | |
1710 | |
1711 Returns information about the Device and the version of Open AL | |
1712 */ | |
1713 ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data) | |
1714 { | |
1715 if(size == 0 || data == NULL) | |
1716 { | |
1717 alcSetError(device, ALC_INVALID_VALUE); | |
1718 return; | |
1719 } | |
1720 | |
1721 LockLists(); | |
1722 if(!IsDevice(device)) | |
1723 { | |
1724 switch(param) | |
1725 { | |
1726 case ALC_MAJOR_VERSION: | |
1727 *data = alcMajorVersion; | |
1728 break; | |
1729 case ALC_MINOR_VERSION: | |
1730 *data = alcMinorVersion; | |
1731 break; | |
1732 | |
1733 case ALC_ATTRIBUTES_SIZE: | |
1734 case ALC_ALL_ATTRIBUTES: | |
1735 case ALC_FREQUENCY: | |
1736 case ALC_REFRESH: | |
1737 case ALC_SYNC: | |
1738 case ALC_MONO_SOURCES: | |
1739 case ALC_STEREO_SOURCES: | |
1740 case ALC_CAPTURE_SAMPLES: | |
1741 case ALC_FORMAT_CHANNELS_SOFT: | |
1742 case ALC_FORMAT_TYPE_SOFT: | |
1743 alcSetError(NULL, ALC_INVALID_DEVICE); | |
1744 break; | |
1745 | |
1746 default: | |
1747 alcSetError(NULL, ALC_INVALID_ENUM); | |
1748 break; | |
1749 } | |
1750 } | |
1751 else if(device->IsCaptureDevice) | |
1752 { | |
1753 switch(param) | |
1754 { | |
1755 case ALC_CAPTURE_SAMPLES: | |
1756 LockDevice(device); | |
1757 *data = ALCdevice_AvailableSamples(device); | |
1758 UnlockDevice(device); | |
1759 break; | |
1760 | |
1761 case ALC_CONNECTED: | |
1762 *data = device->Connected; | |
1763 break; | |
1764 | |
1765 default: | |
1766 alcSetError(device, ALC_INVALID_ENUM); | |
1767 break; | |
1768 } | |
1769 } | |
1770 else /* render device */ | |
1771 { | |
1772 switch(param) | |
1773 { | |
1774 case ALC_MAJOR_VERSION: | |
1775 *data = alcMajorVersion; | |
1776 break; | |
1777 | |
1778 case ALC_MINOR_VERSION: | |
1779 *data = alcMinorVersion; | |
1780 break; | |
1781 | |
1782 case ALC_EFX_MAJOR_VERSION: | |
1783 *data = alcEFXMajorVersion; | |
1784 break; | |
1785 | |
1786 case ALC_EFX_MINOR_VERSION: | |
1787 *data = alcEFXMinorVersion; | |
1788 break; | |
1789 | |
1790 case ALC_ATTRIBUTES_SIZE: | |
1791 *data = 13; | |
1792 break; | |
1793 | |
1794 case ALC_ALL_ATTRIBUTES: | |
1795 if(size < 13) | |
1796 alcSetError(device, ALC_INVALID_VALUE); | |
1797 else | |
1798 { | |
1799 int i = 0; | |
1800 | |
1801 data[i++] = ALC_FREQUENCY; | |
1802 data[i++] = device->Frequency; | |
1803 | |
1804 if(!device->IsLoopbackDevice) | |
1805 { | |
1806 data[i++] = ALC_REFRESH; | |
1807 data[i++] = device->Frequency / device->UpdateSize; | |
1808 | |
1809 data[i++] = ALC_SYNC; | |
1810 data[i++] = ALC_FALSE; | |
1811 } | |
1812 else | |
1813 { | |
1814 data[i++] = ALC_FORMAT_CHANNELS_SOFT; | |
1815 data[i++] = device->FmtChans; | |
1816 | |
1817 data[i++] = ALC_FORMAT_TYPE_SOFT; | |
1818 data[i++] = device->FmtType; | |
1819 } | |
1820 | |
1821 data[i++] = ALC_MONO_SOURCES; | |
1822 data[i++] = device->NumMonoSources; | |
1823 | |
1824 data[i++] = ALC_STEREO_SOURCES; | |
1825 data[i++] = device->NumStereoSources; | |
1826 | |
1827 data[i++] = ALC_MAX_AUXILIARY_SENDS; | |
1828 data[i++] = device->NumAuxSends; | |
1829 | |
1830 data[i++] = 0; | |
1831 } | |
1832 break; | |
1833 | |
1834 case ALC_FREQUENCY: | |
1835 *data = device->Frequency; | |
1836 break; | |
1837 | |
1838 case ALC_REFRESH: | |
1839 if(device->IsLoopbackDevice) | |
1840 alcSetError(device, ALC_INVALID_DEVICE); | |
1841 else | |
1842 *data = device->Frequency / device->UpdateSize; | |
1843 break; | |
1844 | |
1845 case ALC_SYNC: | |
1846 if(device->IsLoopbackDevice) | |
1847 alcSetError(device, ALC_INVALID_DEVICE); | |
1848 else | |
1849 *data = ALC_FALSE; | |
1850 break; | |
1851 | |
1852 case ALC_FORMAT_CHANNELS_SOFT: | |
1853 if(!device->IsLoopbackDevice) | |
1854 alcSetError(device, ALC_INVALID_DEVICE); | |
1855 else | |
1856 *data = device->FmtChans; | |
1857 break; | |
1858 | |
1859 case ALC_FORMAT_TYPE_SOFT: | |
1860 if(!device->IsLoopbackDevice) | |
1861 alcSetError(device, ALC_INVALID_DEVICE); | |
1862 else | |
1863 *data = device->FmtType; | |
1864 break; | |
1865 | |
1866 case ALC_MONO_SOURCES: | |
1867 *data = device->NumMonoSources; | |
1868 break; | |
1869 | |
1870 case ALC_STEREO_SOURCES: | |
1871 *data = device->NumStereoSources; | |
1872 break; | |
1873 | |
1874 case ALC_MAX_AUXILIARY_SENDS: | |
1875 *data = device->NumAuxSends; | |
1876 break; | |
1877 | |
1878 case ALC_CONNECTED: | |
1879 *data = device->Connected; | |
1880 break; | |
1881 | |
1882 default: | |
1883 alcSetError(device, ALC_INVALID_ENUM); | |
1884 break; | |
1885 } | |
1886 } | |
1887 UnlockLists(); | |
1888 } | |
1889 | |
1890 | |
1891 /* | |
1892 alcIsExtensionPresent | |
1893 | |
1894 Determines if there is support for a particular extension | |
1895 */ | |
1896 ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName) | |
1897 { | |
1898 ALCboolean bResult = ALC_FALSE; | |
1899 const char *ptr; | |
1900 size_t len; | |
1901 | |
1902 if(!extName) | |
1903 { | |
1904 alcSetError(device, ALC_INVALID_VALUE); | |
1905 return ALC_FALSE; | |
1906 } | |
1907 | |
1908 len = strlen(extName); | |
1909 LockLists(); | |
1910 ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList); | |
1911 UnlockLists(); | |
1912 while(ptr && *ptr) | |
1913 { | |
1914 if(strncasecmp(ptr, extName, len) == 0 && | |
1915 (ptr[len] == '\0' || isspace(ptr[len]))) | |
1916 { | |
1917 bResult = ALC_TRUE; | |
1918 break; | |
1919 } | |
1920 if((ptr=strchr(ptr, ' ')) != NULL) | |
1921 { | |
1922 do { | |
1923 ++ptr; | |
1924 } while(isspace(*ptr)); | |
1925 } | |
1926 } | |
1927 | |
1928 return bResult; | |
1929 } | |
1930 | |
1931 | |
1932 /* | |
1933 alcGetProcAddress | |
1934 | |
1935 Retrieves the function address for a particular extension function | |
1936 */ | |
1937 ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName) | |
1938 { | |
1939 ALsizei i = 0; | |
1940 | |
1941 if(!funcName) | |
1942 { | |
1943 alcSetError(device, ALC_INVALID_VALUE); | |
1944 return NULL; | |
1945 } | |
1946 | |
1947 while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0) | |
1948 i++; | |
1949 return alcFunctions[i].address; | |
1950 } | |
1951 | |
1952 | |
1953 /* | |
1954 alcGetEnumValue | |
1955 | |
1956 Get the value for a particular ALC Enumerated Value | |
1957 */ | |
1958 ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName) | |
1959 { | |
1960 ALsizei i = 0; | |
1961 | |
1962 if(!enumName) | |
1963 { | |
1964 alcSetError(device, ALC_INVALID_VALUE); | |
1965 return (ALCenum)0; | |
1966 } | |
1967 | |
1968 while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0) | |
1969 i++; | |
1970 return enumeration[i].value; | |
1971 } | |
1972 | |
1973 | |
1974 /* | |
1975 alcCreateContext | |
1976 | |
1977 Create and attach a Context to a particular Device. | |
1978 */ | |
1979 ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList) | |
1980 { | |
1981 ALCcontext *ALContext; | |
1982 void *temp; | |
1983 | |
1984 LockLists(); | |
1985 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected) | |
1986 { | |
1987 alcSetError(device, ALC_INVALID_DEVICE); | |
1988 UnlockLists(); | |
1989 return NULL; | |
1990 } | |
1991 | |
1992 // Reset Context Last Error code | |
1993 device->LastError = ALC_NO_ERROR; | |
1994 | |
1995 if(UpdateDeviceParams(device, attrList) == ALC_FALSE) | |
1996 { | |
1997 alcSetError(device, ALC_INVALID_DEVICE); | |
1998 aluHandleDisconnect(device); | |
1999 UnlockLists(); | |
2000 return NULL; | |
2001 } | |
2002 | |
2003 LockDevice(device); | |
2004 ALContext = NULL; | |
2005 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts)); | |
2006 if(temp) | |
2007 { | |
2008 device->Contexts = temp; | |
2009 | |
2010 ALContext = calloc(1, sizeof(ALCcontext)); | |
2011 if(ALContext) | |
2012 { | |
2013 ALContext->MaxActiveSources = 256; | |
2014 ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) * | |
2015 ALContext->MaxActiveSources); | |
2016 } | |
2017 } | |
2018 if(!ALContext || !ALContext->ActiveSources) | |
2019 { | |
2020 free(ALContext); | |
2021 alcSetError(device, ALC_OUT_OF_MEMORY); | |
2022 UnlockDevice(device); | |
2023 if(device->NumContexts == 0) | |
2024 { | |
2025 ALCdevice_StopPlayback(device); | |
2026 device->Flags &= ~DEVICE_RUNNING; | |
2027 } | |
2028 UnlockLists(); | |
2029 return NULL; | |
2030 } | |
2031 | |
2032 device->Contexts[device->NumContexts++] = ALContext; | |
2033 ALContext->Device = device; | |
2034 | |
2035 InitContext(ALContext); | |
2036 UnlockDevice(device); | |
2037 | |
2038 ALContext->next = g_pContextList; | |
2039 g_pContextList = ALContext; | |
2040 g_ulContextCount++; | |
2041 | |
2042 UnlockLists(); | |
2043 | |
2044 return ALContext; | |
2045 } | |
2046 | |
2047 | |
2048 /* | |
2049 alcDestroyContext | |
2050 | |
2051 Remove a Context | |
2052 */ | |
2053 ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context) | |
2054 { | |
2055 ALCdevice *Device; | |
2056 ALCcontext **list; | |
2057 ALuint i; | |
2058 | |
2059 LockLists(); | |
2060 list = &g_pContextList; | |
2061 while(*list && *list != context) | |
2062 list = &(*list)->next; | |
2063 | |
2064 if(!*list) | |
2065 { | |
2066 alcSetError(NULL, ALC_INVALID_CONTEXT); | |
2067 UnlockLists(); | |
2068 return; | |
2069 } | |
2070 | |
2071 *list = (*list)->next; | |
2072 g_ulContextCount--; | |
2073 | |
2074 if(context == tls_get(LocalContext)) | |
2075 tls_set(LocalContext, NULL); | |
2076 if(context == GlobalContext) | |
2077 GlobalContext = NULL; | |
2078 | |
2079 Device = context->Device; | |
2080 LockDevice(Device); | |
2081 for(i = 0;i < Device->NumContexts;i++) | |
2082 { | |
2083 if(Device->Contexts[i] == context) | |
2084 { | |
2085 Device->Contexts[i] = Device->Contexts[Device->NumContexts-1]; | |
2086 Device->NumContexts--; | |
2087 break; | |
2088 } | |
2089 } | |
2090 UnlockDevice(Device); | |
2091 | |
2092 if(Device->NumContexts == 0) | |
2093 { | |
2094 ALCdevice_StopPlayback(Device); | |
2095 Device->Flags &= ~DEVICE_RUNNING; | |
2096 } | |
2097 UnlockLists(); | |
2098 | |
2099 if(context->SourceMap.size > 0) | |
2100 { | |
2101 ERR("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size); | |
2102 ReleaseALSources(context); | |
2103 } | |
2104 ResetUIntMap(&context->SourceMap); | |
2105 | |
2106 if(context->EffectSlotMap.size > 0) | |
2107 { | |
2108 ERR("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size); | |
2109 ReleaseALAuxiliaryEffectSlots(context); | |
2110 } | |
2111 ResetUIntMap(&context->EffectSlotMap); | |
2112 | |
2113 free(context->ActiveSources); | |
2114 context->ActiveSources = NULL; | |
2115 context->MaxActiveSources = 0; | |
2116 context->ActiveSourceCount = 0; | |
2117 | |
2118 FreeContext(context); | |
2119 } | |
2120 | |
2121 | |
2122 /* | |
2123 alcGetCurrentContext | |
2124 | |
2125 Returns the currently active Context | |
2126 */ | |
2127 ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid) | |
2128 { | |
2129 ALCcontext *Context; | |
2130 | |
2131 LockLists(); | |
2132 Context = tls_get(LocalContext); | |
2133 if(Context && !IsContext(Context)) | |
2134 { | |
2135 tls_set(LocalContext, NULL); | |
2136 Context = NULL; | |
2137 } | |
2138 if(!Context) | |
2139 Context = GlobalContext; | |
2140 UnlockLists(); | |
2141 | |
2142 return Context; | |
2143 } | |
2144 | |
2145 /* | |
2146 alcGetThreadContext | |
2147 | |
2148 Returns the currently active thread-local Context | |
2149 */ | |
2150 ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) | |
2151 { | |
2152 ALCcontext *pContext = NULL; | |
2153 | |
2154 LockLists(); | |
2155 | |
2156 pContext = tls_get(LocalContext); | |
2157 if(pContext && !IsContext(pContext)) | |
2158 { | |
2159 tls_set(LocalContext, NULL); | |
2160 pContext = NULL; | |
2161 } | |
2162 | |
2163 UnlockLists(); | |
2164 | |
2165 return pContext; | |
2166 } | |
2167 | |
2168 | |
2169 /* | |
2170 alcGetContextsDevice | |
2171 | |
2172 Returns the Device that a particular Context is attached to | |
2173 */ | |
2174 ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext) | |
2175 { | |
2176 ALCdevice *pDevice = NULL; | |
2177 | |
2178 LockLists(); | |
2179 if(IsContext(pContext)) | |
2180 pDevice = pContext->Device; | |
2181 else | |
2182 alcSetError(NULL, ALC_INVALID_CONTEXT); | |
2183 UnlockLists(); | |
2184 | |
2185 return pDevice; | |
2186 } | |
2187 | |
2188 | |
2189 /* | |
2190 alcMakeContextCurrent | |
2191 | |
2192 Makes the given Context the active Context | |
2193 */ | |
2194 ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) | |
2195 { | |
2196 ALboolean bReturn = AL_TRUE; | |
2197 | |
2198 LockLists(); | |
2199 | |
2200 // context must be a valid Context or NULL | |
2201 if(context == NULL || IsContext(context)) | |
2202 { | |
2203 GlobalContext = context; | |
2204 tls_set(LocalContext, NULL); | |
2205 } | |
2206 else | |
2207 { | |
2208 alcSetError(NULL, ALC_INVALID_CONTEXT); | |
2209 bReturn = AL_FALSE; | |
2210 } | |
2211 | |
2212 UnlockLists(); | |
2213 | |
2214 return bReturn; | |
2215 } | |
2216 | |
2217 /* | |
2218 alcSetThreadContext | |
2219 | |
2220 Makes the given Context the active Context for the current thread | |
2221 */ | |
2222 ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) | |
2223 { | |
2224 ALboolean bReturn = AL_TRUE; | |
2225 | |
2226 LockLists(); | |
2227 | |
2228 // context must be a valid Context or NULL | |
2229 if(context == NULL || IsContext(context)) | |
2230 tls_set(LocalContext, context); | |
2231 else | |
2232 { | |
2233 alcSetError(NULL, ALC_INVALID_CONTEXT); | |
2234 bReturn = AL_FALSE; | |
2235 } | |
2236 | |
2237 UnlockLists(); | |
2238 | |
2239 return bReturn; | |
2240 } | |
2241 | |
2242 | |
2243 static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type) | |
2244 { | |
2245 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) | |
2246 { | |
2247 *chans = DevFmtMono; | |
2248 *type = DevFmtFloat; | |
2249 return; | |
2250 } | |
2251 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) | |
2252 { | |
2253 *chans = DevFmtStereo; | |
2254 *type = DevFmtFloat; | |
2255 return; | |
2256 } | |
2257 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) | |
2258 { | |
2259 *chans = DevFmtQuad; | |
2260 *type = DevFmtFloat; | |
2261 return; | |
2262 } | |
2263 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) | |
2264 { | |
2265 *chans = DevFmtX51; | |
2266 *type = DevFmtFloat; | |
2267 return; | |
2268 } | |
2269 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) | |
2270 { | |
2271 *chans = DevFmtX61; | |
2272 *type = DevFmtFloat; | |
2273 return; | |
2274 } | |
2275 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) | |
2276 { | |
2277 *chans = DevFmtX71; | |
2278 *type = DevFmtFloat; | |
2279 return; | |
2280 } | |
2281 | |
2282 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) | |
2283 { | |
2284 *chans = DevFmtMono; | |
2285 *type = DevFmtShort; | |
2286 return; | |
2287 } | |
2288 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) | |
2289 { | |
2290 *chans = DevFmtStereo; | |
2291 *type = DevFmtShort; | |
2292 return; | |
2293 } | |
2294 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) | |
2295 { | |
2296 *chans = DevFmtQuad; | |
2297 *type = DevFmtShort; | |
2298 return; | |
2299 } | |
2300 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) | |
2301 { | |
2302 *chans = DevFmtX51; | |
2303 *type = DevFmtShort; | |
2304 return; | |
2305 } | |
2306 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) | |
2307 { | |
2308 *chans = DevFmtX61; | |
2309 *type = DevFmtShort; | |
2310 return; | |
2311 } | |
2312 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) | |
2313 { | |
2314 *chans = DevFmtX71; | |
2315 *type = DevFmtShort; | |
2316 return; | |
2317 } | |
2318 | |
2319 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) | |
2320 { | |
2321 *chans = DevFmtMono; | |
2322 *type = DevFmtByte; | |
2323 return; | |
2324 } | |
2325 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) | |
2326 { | |
2327 *chans = DevFmtStereo; | |
2328 *type = DevFmtByte; | |
2329 return; | |
2330 } | |
2331 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) | |
2332 { | |
2333 *chans = DevFmtQuad; | |
2334 *type = DevFmtByte; | |
2335 return; | |
2336 } | |
2337 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) | |
2338 { | |
2339 *chans = DevFmtX51; | |
2340 *type = DevFmtByte; | |
2341 return; | |
2342 } | |
2343 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) | |
2344 { | |
2345 *chans = DevFmtX61; | |
2346 *type = DevFmtByte; | |
2347 return; | |
2348 } | |
2349 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) | |
2350 { | |
2351 *chans = DevFmtX71; | |
2352 *type = DevFmtByte; | |
2353 return; | |
2354 } | |
2355 | |
2356 ERR("Unknown format: \"%s\"\n", str); | |
2357 *chans = DevFmtStereo; | |
2358 *type = DevFmtShort; | |
2359 } | |
2360 | |
2361 /* | |
2362 alcOpenDevice | |
2363 | |
2364 Open the Device specified. | |
2365 */ | |
2366 ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) | |
2367 { | |
2368 const ALCchar *fmt; | |
2369 ALCdevice *device; | |
2370 | |
2371 DO_INITCONFIG(); | |
2372 | |
2373 if(!PlaybackBackend.name) | |
2374 { | |
2375 alcSetError(NULL, ALC_INVALID_VALUE); | |
2376 return NULL; | |
2377 } | |
2378 | |
2379 if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0)) | |
2380 deviceName = NULL; | |
2381 | |
2382 device = calloc(1, sizeof(ALCdevice)); | |
2383 if(!device) | |
2384 { | |
2385 alcSetError(NULL, ALC_OUT_OF_MEMORY); | |
2386 return NULL; | |
2387 } | |
2388 | |
2389 //Validate device | |
2390 device->Funcs = &PlaybackBackend.Funcs; | |
2391 device->Connected = ALC_TRUE; | |
2392 device->IsCaptureDevice = AL_FALSE; | |
2393 device->IsLoopbackDevice = AL_FALSE; | |
2394 InitializeCriticalSection(&device->Mutex); | |
2395 device->LastError = ALC_NO_ERROR; | |
2396 | |
2397 device->Flags = 0; | |
2398 device->Bs2b = NULL; | |
2399 device->szDeviceName = NULL; | |
2400 | |
2401 device->Contexts = NULL; | |
2402 device->NumContexts = 0; | |
2403 | |
2404 InitUIntMap(&device->BufferMap); | |
2405 InitUIntMap(&device->EffectMap); | |
2406 InitUIntMap(&device->FilterMap); | |
2407 | |
2408 //Set output format | |
2409 if(ConfigValueExists(NULL, "frequency")) | |
2410 device->Flags |= DEVICE_FREQUENCY_REQUEST; | |
2411 device->Frequency = GetConfigValueInt(NULL, "frequency", DEFAULT_OUTPUT_RATE); | |
2412 if(device->Frequency < 8000) | |
2413 device->Frequency = 8000; | |
2414 | |
2415 if(ConfigValueExists(NULL, "format")) | |
2416 device->Flags |= DEVICE_CHANNELS_REQUEST; | |
2417 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16"); | |
2418 GetFormatFromString(fmt, &device->FmtChans, &device->FmtType); | |
2419 | |
2420 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4); | |
2421 if(device->NumUpdates < 2) | |
2422 device->NumUpdates = 4; | |
2423 | |
2424 device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024); | |
2425 if(device->UpdateSize <= 0) | |
2426 device->UpdateSize = 1024; | |
2427 | |
2428 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256); | |
2429 if(device->MaxNoOfSources <= 0) | |
2430 device->MaxNoOfSources = 256; | |
2431 | |
2432 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4); | |
2433 if(device->AuxiliaryEffectSlotMax <= 0) | |
2434 device->AuxiliaryEffectSlotMax = 4; | |
2435 | |
2436 device->NumStereoSources = 1; | |
2437 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources; | |
2438 | |
2439 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS); | |
2440 if(device->NumAuxSends > MAX_SENDS) | |
2441 device->NumAuxSends = MAX_SENDS; | |
2442 | |
2443 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0); | |
2444 | |
2445 // Find a playback device to open | |
2446 LockLists(); | |
2447 if(ALCdevice_OpenPlayback(device, deviceName)) | |
2448 { | |
2449 device->next = g_pDeviceList; | |
2450 g_pDeviceList = device; | |
2451 g_ulDeviceCount++; | |
2452 } | |
2453 else | |
2454 { | |
2455 // No suitable output device found | |
2456 DeleteCriticalSection(&device->Mutex); | |
2457 free(device); | |
2458 device = NULL; | |
2459 alcSetError(NULL, ALC_INVALID_VALUE); | |
2460 } | |
2461 UnlockLists(); | |
2462 | |
2463 return device; | |
2464 } | |
2465 | |
2466 | |
2467 /* | |
2468 alcCloseDevice | |
2469 | |
2470 Close the specified Device | |
2471 */ | |
2472 ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice) | |
2473 { | |
2474 ALCdevice **list; | |
2475 | |
2476 LockLists(); | |
2477 list = &g_pDeviceList; | |
2478 while(*list && *list != pDevice) | |
2479 list = &(*list)->next; | |
2480 | |
2481 if(!*list || (*list)->IsCaptureDevice) | |
2482 { | |
2483 alcSetError(*list, ALC_INVALID_DEVICE); | |
2484 UnlockLists(); | |
2485 return ALC_FALSE; | |
2486 } | |
2487 | |
2488 *list = (*list)->next; | |
2489 g_ulDeviceCount--; | |
2490 | |
2491 UnlockLists(); | |
2492 | |
2493 if(pDevice->NumContexts > 0) | |
2494 { | |
2495 WARN("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts); | |
2496 while(pDevice->NumContexts > 0) | |
2497 alcDestroyContext(pDevice->Contexts[0]); | |
2498 } | |
2499 ALCdevice_ClosePlayback(pDevice); | |
2500 | |
2501 if(pDevice->BufferMap.size > 0) | |
2502 { | |
2503 WARN("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size); | |
2504 ReleaseALBuffers(pDevice); | |
2505 } | |
2506 ResetUIntMap(&pDevice->BufferMap); | |
2507 | |
2508 if(pDevice->EffectMap.size > 0) | |
2509 { | |
2510 WARN("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size); | |
2511 ReleaseALEffects(pDevice); | |
2512 } | |
2513 ResetUIntMap(&pDevice->EffectMap); | |
2514 | |
2515 if(pDevice->FilterMap.size > 0) | |
2516 { | |
2517 WARN("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size); | |
2518 ReleaseALFilters(pDevice); | |
2519 } | |
2520 ResetUIntMap(&pDevice->FilterMap); | |
2521 | |
2522 free(pDevice->Bs2b); | |
2523 pDevice->Bs2b = NULL; | |
2524 | |
2525 free(pDevice->szDeviceName); | |
2526 pDevice->szDeviceName = NULL; | |
2527 | |
2528 free(pDevice->Contexts); | |
2529 pDevice->Contexts = NULL; | |
2530 | |
2531 DeleteCriticalSection(&pDevice->Mutex); | |
2532 | |
2533 //Release device structure | |
2534 memset(pDevice, 0, sizeof(ALCdevice)); | |
2535 free(pDevice); | |
2536 | |
2537 return ALC_TRUE; | |
2538 } | |
2539 | |
2540 | |
2541 ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void) | |
2542 { | |
2543 ALCdevice *device; | |
2544 | |
2545 DO_INITCONFIG(); | |
2546 | |
2547 device = calloc(1, sizeof(ALCdevice)); | |
2548 if(!device) | |
2549 { | |
2550 alcSetError(NULL, ALC_OUT_OF_MEMORY); | |
2551 return NULL; | |
2552 } | |
2553 | |
2554 //Validate device | |
2555 device->Funcs = &BackendLoopback.Funcs; | |
2556 device->Connected = ALC_TRUE; | |
2557 device->IsCaptureDevice = AL_FALSE; | |
2558 device->IsLoopbackDevice = AL_TRUE; | |
2559 InitializeCriticalSection(&device->Mutex); | |
2560 device->LastError = ALC_NO_ERROR; | |
2561 | |
2562 device->Flags = 0; | |
2563 device->Bs2b = NULL; | |
2564 device->szDeviceName = NULL; | |
2565 | |
2566 device->Contexts = NULL; | |
2567 device->NumContexts = 0; | |
2568 | |
2569 InitUIntMap(&device->BufferMap); | |
2570 InitUIntMap(&device->EffectMap); | |
2571 InitUIntMap(&device->FilterMap); | |
2572 | |
2573 //Set output format | |
2574 device->Frequency = 44100; | |
2575 device->FmtChans = DevFmtStereo; | |
2576 device->FmtType = DevFmtShort; | |
2577 | |
2578 device->NumUpdates = 0; | |
2579 device->UpdateSize = 0; | |
2580 | |
2581 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256); | |
2582 if(device->MaxNoOfSources <= 0) | |
2583 device->MaxNoOfSources = 256; | |
2584 | |
2585 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4); | |
2586 if(device->AuxiliaryEffectSlotMax <= 0) | |
2587 device->AuxiliaryEffectSlotMax = 4; | |
2588 | |
2589 device->NumStereoSources = 1; | |
2590 device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources; | |
2591 | |
2592 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS); | |
2593 if(device->NumAuxSends > MAX_SENDS) | |
2594 device->NumAuxSends = MAX_SENDS; | |
2595 | |
2596 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0); | |
2597 | |
2598 // Open the "backend" | |
2599 LockLists(); | |
2600 ALCdevice_OpenPlayback(device, "Loopback"); | |
2601 | |
2602 device->next = g_pDeviceList; | |
2603 g_pDeviceList = device; | |
2604 g_ulDeviceCount++; | |
2605 UnlockLists(); | |
2606 | |
2607 return device; | |
2608 } | |
2609 | |
2610 ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) | |
2611 { | |
2612 ALCboolean ret = ALC_FALSE; | |
2613 | |
2614 LockLists(); | |
2615 if(!IsDevice(device) || !device->IsLoopbackDevice) | |
2616 alcSetError(device, ALC_INVALID_DEVICE); | |
2617 else if(freq <= 0) | |
2618 alcSetError(device, ALC_INVALID_VALUE); | |
2619 else if(!IsValidALCType(type) || !IsValidALCChannels(channels)) | |
2620 alcSetError(device, ALC_INVALID_ENUM); | |
2621 else | |
2622 { | |
2623 if(BytesFromDevFmt(type) > 0 && ChannelsFromDevFmt(channels) > 0 && | |
2624 freq >= 8000) | |
2625 ret = ALC_TRUE; | |
2626 } | |
2627 UnlockLists(); | |
2628 | |
2629 return ret; | |
2630 } | |
2631 | |
2632 ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) | |
2633 { | |
2634 LockLists(); | |
2635 if(!IsDevice(device) || !device->IsLoopbackDevice) | |
2636 alcSetError(device, ALC_INVALID_DEVICE); | |
2637 else if(samples < 0 || (samples > 0 && buffer == NULL)) | |
2638 alcSetError(device, ALC_INVALID_VALUE); | |
2639 else | |
2640 aluMixData(device, buffer, samples); | |
2641 UnlockLists(); | |
2642 } | |
2643 | |
2644 | |
2645 static void ReleaseALC(ALCboolean doclose) | |
2646 { | |
2647 free(alcDeviceList); alcDeviceList = NULL; | |
2648 alcDeviceListSize = 0; | |
2649 free(alcAllDeviceList); alcAllDeviceList = NULL; | |
2650 alcAllDeviceListSize = 0; | |
2651 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL; | |
2652 alcCaptureDeviceListSize = 0; | |
2653 | |
2654 free(alcDefaultDeviceSpecifier); | |
2655 alcDefaultDeviceSpecifier = NULL; | |
2656 free(alcDefaultAllDeviceSpecifier); | |
2657 alcDefaultAllDeviceSpecifier = NULL; | |
2658 free(alcCaptureDefaultDeviceSpecifier); | |
2659 alcCaptureDefaultDeviceSpecifier = NULL; | |
2660 | |
2661 if(doclose) | |
2662 { | |
2663 if(g_ulDeviceCount > 0) | |
2664 WARN("ReleaseALC(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":""); | |
2665 | |
2666 while(g_pDeviceList) | |
2667 { | |
2668 if(g_pDeviceList->IsCaptureDevice) | |
2669 alcCaptureCloseDevice(g_pDeviceList); | |
2670 else | |
2671 alcCloseDevice(g_pDeviceList); | |
2672 } | |
2673 } | |
2674 else | |
2675 { | |
2676 if(g_ulDeviceCount > 0) | |
2677 WARN("ReleaseALC(): %u Device%s not closed\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":""); | |
2678 } | |
2679 } | |
2680 | |
2681 /////////////////////////////////////////////////////// |