Move NextPowerOf2 to alMain.h
[openal-soft.git] / Alc / ALc.c
blob46d6ac27f90bf4436528dc12fc6416ec0d2d65e8
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.
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.
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
21 #include "config.h"
23 #include <math.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <memory.h>
27 #include <ctype.h>
28 #include "alMain.h"
29 #include "alSource.h"
30 #include "AL/al.h"
31 #include "AL/alc.h"
32 #include "alThunk.h"
33 #include "alSource.h"
34 #include "alBuffer.h"
35 #include "alExtension.h"
36 #include "alAuxEffectSlot.h"
37 #include "alDatabuffer.h"
38 #include "bs2b.h"
39 #include "alu.h"
42 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
43 typedef struct BackendInfo {
44 const char *name;
45 void (*Init)(BackendFuncs*);
46 void (*Deinit)(void);
47 void (*Probe)(int);
48 BackendFuncs Funcs;
49 } BackendInfo;
50 static BackendInfo BackendList[] = {
51 #ifdef HAVE_ALSA
52 { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs },
53 #endif
54 #ifdef HAVE_OSS
55 { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs },
56 #endif
57 #ifdef HAVE_SOLARIS
58 { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs },
59 #endif
60 #ifdef HAVE_DSOUND
61 { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs },
62 #endif
63 #ifdef HAVE_WINMM
64 { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs },
65 #endif
66 #ifdef HAVE_PORTAUDIO
67 { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs },
68 #endif
69 #ifdef HAVE_PULSEAUDIO
70 { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
71 #endif
73 { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs },
75 { NULL, NULL, NULL, NULL, EmptyFuncs }
77 #undef EmptyFuncs
79 ///////////////////////////////////////////////////////
81 #define ALC_EFX_MAJOR_VERSION 0x20001
82 #define ALC_EFX_MINOR_VERSION 0x20002
83 #define ALC_MAX_AUXILIARY_SENDS 0x20003
85 ///////////////////////////////////////////////////////
86 // STRING and EXTENSIONS
88 typedef struct ALCfunction_struct
90 ALCchar *funcName;
91 ALvoid *address;
92 } ALCfunction;
94 static ALCfunction alcFunctions[] = {
95 { "alcCreateContext", (ALvoid *) alcCreateContext },
96 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
97 { "alcProcessContext", (ALvoid *) alcProcessContext },
98 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
99 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
100 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
101 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
102 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
103 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
104 { "alcGetError", (ALvoid *) alcGetError },
105 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
106 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
107 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
108 { "alcGetString", (ALvoid *) alcGetString },
109 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
110 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
111 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
112 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
113 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
114 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
116 { "alcMakeCurrent", (ALvoid *) alcMakeCurrent },
117 { "alcGetThreadContext", (ALvoid *) alcGetThreadContext },
119 { NULL, (ALvoid *) NULL }
122 static ALenums enumeration[]={
123 // Types
124 { (ALchar *)"ALC_INVALID", ALC_INVALID },
125 { (ALchar *)"ALC_FALSE", ALC_FALSE },
126 { (ALchar *)"ALC_TRUE", ALC_TRUE },
128 // ALC Properties
129 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
130 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
131 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
132 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
133 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
134 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
135 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
136 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
137 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
138 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
139 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
140 { (ALchar *)"ALC_SYNC", ALC_SYNC },
141 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
142 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
143 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
144 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
145 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
147 // EFX Properties
148 { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
149 { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
150 { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
152 // ALC Error Message
153 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
154 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
155 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
156 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
157 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
158 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
159 { (ALchar *)NULL, (ALenum)0 }
161 // Error strings
162 static const ALCchar alcNoError[] = "No Error";
163 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
164 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
165 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
166 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
167 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
169 /* Device lists. Sizes only include the first ending null character, not the
170 * second */
171 static ALCchar *alcDeviceList;
172 static ALCuint alcDeviceListSize;
173 static ALCchar *alcAllDeviceList;
174 static ALCuint alcAllDeviceListSize;
175 static ALCchar *alcCaptureDeviceList;
176 static ALCuint alcCaptureDeviceListSize;
177 // Default is always the first in the list
178 static ALCchar *alcDefaultDeviceSpecifier;
179 static ALCchar *alcDefaultAllDeviceSpecifier;
180 static ALCchar *alcCaptureDefaultDeviceSpecifier;
183 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_disconnect ALC_EXT_EFX ALC_EXTX_thread_local_context";
184 static ALCint alcMajorVersion = 1;
185 static ALCint alcMinorVersion = 1;
187 static ALCint alcEFXMajorVersion = 1;
188 static ALCint alcEFXMinorVersion = 0;
190 ///////////////////////////////////////////////////////
193 ///////////////////////////////////////////////////////
194 // Global Variables
196 static ALCdevice *g_pDeviceList = NULL;
197 static ALCuint g_ulDeviceCount = 0;
199 static CRITICAL_SECTION g_csMutex;
201 // Context List
202 static ALCcontext *g_pContextList = NULL;
203 static ALCuint g_ulContextCount = 0;
205 // Thread-local current context
206 static tls_type LocalContext;
208 // Context Error
209 static ALCenum g_eLastContextError = ALC_NO_ERROR;
211 ///////////////////////////////////////////////////////
214 ///////////////////////////////////////////////////////
215 // ALC Related helper functions
216 #ifdef _WIN32
217 static void alc_init(void);
218 static void alc_deinit(void);
220 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
222 (void)lpReserved;
224 // Perform actions based on the reason for calling.
225 switch(ul_reason_for_call)
227 case DLL_PROCESS_ATTACH:
228 DisableThreadLibraryCalls(hModule);
229 alc_init();
230 break;
232 case DLL_PROCESS_DETACH:
233 alc_deinit();
234 break;
236 return TRUE;
238 #else
239 #ifdef HAVE_GCC_DESTRUCTOR
240 static void alc_init(void) __attribute__((constructor));
241 static void alc_deinit(void) __attribute__((destructor));
242 #endif
243 #endif
245 static void alc_init(void)
247 int i;
248 const char *devs, *str;
250 InitializeCriticalSection(&g_csMutex);
251 ALTHUNK_INIT();
252 ReadALConfig();
254 tls_create(&LocalContext);
256 devs = GetConfigValue(NULL, "drivers", "");
257 if(devs[0])
259 int n;
260 size_t len;
261 const char *next = devs;
263 i = 0;
264 do {
265 devs = next;
266 next = strchr(devs, ',');
268 if(!devs[0] || devs[0] == ',')
269 continue;
271 len = (next ? ((size_t)(next-devs)) : strlen(devs));
272 for(n = i;BackendList[n].Init;n++)
274 if(len == strlen(BackendList[n].name) &&
275 strncmp(BackendList[n].name, devs, len) == 0)
277 BackendInfo Bkp = BackendList[i];
278 BackendList[i] = BackendList[n];
279 BackendList[n] = Bkp;
281 i++;
284 } while(next++);
286 BackendList[i].name = NULL;
287 BackendList[i].Init = NULL;
288 BackendList[i].Deinit = NULL;
289 BackendList[i].Probe = NULL;
292 for(i = 0;BackendList[i].Init;i++)
294 BackendList[i].Init(&BackendList[i].Funcs);
296 BackendList[i].Probe(DEVICE_PROBE);
297 BackendList[i].Probe(ALL_DEVICE_PROBE);
298 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
301 DuplicateStereo = GetConfigValueBool(NULL, "stereodup", 0);
303 str = GetConfigValue(NULL, "excludefx", "");
304 if(str[0])
306 const struct {
307 const char *name;
308 int type;
309 } EffectList[] = {
310 { "eaxreverb", EAXREVERB },
311 { "reverb", REVERB },
312 { "echo", ECHO },
313 { NULL, 0 }
315 int n;
316 size_t len;
317 const char *next = str;
319 do {
320 str = next;
321 next = strchr(str, ',');
323 if(!str[0] || next == str)
324 continue;
326 len = (next ? ((size_t)(next-str)) : strlen(str));
327 for(n = 0;EffectList[n].name;n++)
329 if(len == strlen(EffectList[n].name) &&
330 strncmp(EffectList[n].name, str, len) == 0)
331 DisabledEffects[EffectList[n].type] = AL_TRUE;
333 } while(next++);
337 static void alc_deinit(void)
339 int i;
341 ReleaseALC();
343 for(i = 0;BackendList[i].Deinit;i++)
344 BackendList[i].Deinit();
346 tls_delete(LocalContext);
348 FreeALConfig();
349 ALTHUNK_EXIT();
350 DeleteCriticalSection(&g_csMutex);
354 static void ProbeDeviceList()
356 ALint i;
358 free(alcDeviceList); alcDeviceList = NULL;
359 alcDeviceListSize = 0;
361 for(i = 0;BackendList[i].Probe;i++)
362 BackendList[i].Probe(DEVICE_PROBE);
365 static void ProbeAllDeviceList()
367 ALint i;
369 free(alcAllDeviceList); alcAllDeviceList = NULL;
370 alcAllDeviceListSize = 0;
372 for(i = 0;BackendList[i].Probe;i++)
373 BackendList[i].Probe(ALL_DEVICE_PROBE);
376 static void ProbeCaptureDeviceList()
378 ALint i;
380 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
381 alcCaptureDeviceListSize = 0;
383 for(i = 0;BackendList[i].Probe;i++)
384 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
388 #define DECL_APPEND_LIST_FUNC(type) \
389 void Append##type##List(const ALCchar *name) \
391 ALCuint len = strlen(name); \
392 void *temp; \
394 if(len == 0) \
395 return; \
397 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
398 if(!temp) \
400 AL_PRINT("Realloc failed to add %s!\n", name); \
401 return; \
403 alc##type##List = temp; \
404 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
405 alc##type##ListSize += len+1; \
406 alc##type##List[alc##type##ListSize] = 0; \
409 DECL_APPEND_LIST_FUNC(Device)
410 DECL_APPEND_LIST_FUNC(AllDevice)
411 DECL_APPEND_LIST_FUNC(CaptureDevice)
415 IsDevice
417 Check pDevice is a valid Device pointer
419 static ALCboolean IsDevice(ALCdevice *pDevice)
421 ALCdevice *pTempDevice;
423 SuspendContext(NULL);
425 pTempDevice = g_pDeviceList;
426 while(pTempDevice && pTempDevice != pDevice)
427 pTempDevice = pTempDevice->next;
429 ProcessContext(NULL);
431 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
435 IsContext
437 Check pContext is a valid Context pointer
439 static ALCboolean IsContext(ALCcontext *pContext)
441 ALCcontext *pTempContext;
443 SuspendContext(NULL);
445 pTempContext = g_pContextList;
446 while (pTempContext && pTempContext != pContext)
447 pTempContext = pTempContext->next;
449 ProcessContext(NULL);
451 return (pTempContext ? ALC_TRUE : ALC_FALSE);
456 alcSetError
458 Store latest ALC Error
460 ALCvoid alcSetError(ALenum errorCode)
462 g_eLastContextError = errorCode;
467 SuspendContext
469 Thread-safe entry
471 ALCvoid SuspendContext(ALCcontext *pContext)
473 (void)pContext;
474 EnterCriticalSection(&g_csMutex);
479 ProcessContext
481 Thread-safe exit
483 ALCvoid ProcessContext(ALCcontext *pContext)
485 (void)pContext;
486 LeaveCriticalSection(&g_csMutex);
491 GetContextSuspended
493 Returns the currently active Context, in a locked state
495 ALCcontext *GetContextSuspended(void)
497 ALCcontext *pContext = NULL;
499 SuspendContext(NULL);
501 pContext = tls_get(LocalContext);
502 if(pContext && !IsContext(pContext))
504 tls_set(LocalContext, NULL);
505 pContext = NULL;
507 if(!pContext)
509 pContext = g_pContextList;
510 while(pContext && !pContext->InUse)
511 pContext = pContext->next;
513 if(pContext)
514 SuspendContext(pContext);
516 ProcessContext(NULL);
518 return pContext;
523 InitContext
525 Initialize Context variables
527 static ALvoid InitContext(ALCcontext *pContext)
529 //Initialise listener
530 pContext->Listener.Gain = 1.0f;
531 pContext->Listener.MetersPerUnit = 1.0f;
532 pContext->Listener.Position[0] = 0.0f;
533 pContext->Listener.Position[1] = 0.0f;
534 pContext->Listener.Position[2] = 0.0f;
535 pContext->Listener.Velocity[0] = 0.0f;
536 pContext->Listener.Velocity[1] = 0.0f;
537 pContext->Listener.Velocity[2] = 0.0f;
538 pContext->Listener.Forward[0] = 0.0f;
539 pContext->Listener.Forward[1] = 0.0f;
540 pContext->Listener.Forward[2] = -1.0f;
541 pContext->Listener.Up[0] = 0.0f;
542 pContext->Listener.Up[1] = 1.0f;
543 pContext->Listener.Up[2] = 0.0f;
545 //Validate pContext
546 pContext->LastError = AL_NO_ERROR;
547 pContext->InUse = AL_FALSE;
549 //Set globals
550 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
551 pContext->DopplerFactor = 1.0f;
552 pContext->DopplerVelocity = 1.0f;
553 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
555 pContext->ExtensionList = "AL_EXTX_buffer_sub_data AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET AL_EXTX_sample_buffer_object AL_EXTX_source_distance_model AL_LOKI_quadriphonic";
557 aluInitPanning(pContext);
562 ExitContext
564 Clean up Context, destroy any remaining Sources
566 static ALCvoid ExitContext(ALCcontext *pContext)
568 //Invalidate context
569 pContext->LastError = AL_NO_ERROR;
570 pContext->InUse = AL_FALSE;
573 ///////////////////////////////////////////////////////
576 ///////////////////////////////////////////////////////
577 // ALC Functions calls
580 // This should probably move to another c file but for now ...
581 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
583 ALCboolean DeviceFound = ALC_FALSE;
584 ALCdevice *pDevice = NULL;
585 ALCint i;
587 if(SampleSize <= 0)
589 alcSetError(ALC_INVALID_VALUE);
590 return NULL;
593 if(deviceName && !deviceName[0])
594 deviceName = NULL;
596 pDevice = malloc(sizeof(ALCdevice));
597 if (pDevice)
599 //Initialise device structure
600 memset(pDevice, 0, sizeof(ALCdevice));
602 //Validate device
603 pDevice->Connected = ALC_TRUE;
604 pDevice->IsCaptureDevice = AL_TRUE;
606 pDevice->szDeviceName = NULL;
608 pDevice->Frequency = frequency;
609 pDevice->Format = format;
610 pDevice->UpdateSize = SampleSize;
611 pDevice->NumUpdates = 1;
613 SuspendContext(NULL);
614 for(i = 0;BackendList[i].Init;i++)
616 pDevice->Funcs = &BackendList[i].Funcs;
617 if(ALCdevice_OpenCapture(pDevice, deviceName))
619 pDevice->next = g_pDeviceList;
620 g_pDeviceList = pDevice;
621 g_ulDeviceCount++;
623 DeviceFound = ALC_TRUE;
624 break;
627 ProcessContext(NULL);
629 if(!DeviceFound)
631 alcSetError(ALC_INVALID_VALUE);
632 free(pDevice);
633 pDevice = NULL;
636 else
637 alcSetError(ALC_OUT_OF_MEMORY);
639 return pDevice;
642 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
644 ALCboolean bReturn = ALC_FALSE;
645 ALCdevice **list;
647 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
649 SuspendContext(NULL);
651 list = &g_pDeviceList;
652 while(*list != pDevice)
653 list = &(*list)->next;
655 *list = (*list)->next;
656 g_ulDeviceCount--;
658 ProcessContext(NULL);
660 ALCdevice_CloseCapture(pDevice);
662 free(pDevice->szDeviceName);
663 pDevice->szDeviceName = NULL;
665 free(pDevice);
667 bReturn = ALC_TRUE;
669 else
670 alcSetError(ALC_INVALID_DEVICE);
672 return bReturn;
675 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
677 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
678 ALCdevice_StartCapture(pDevice);
679 else
680 alcSetError(ALC_INVALID_DEVICE);
683 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
685 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
686 ALCdevice_StopCapture(pDevice);
687 else
688 alcSetError(ALC_INVALID_DEVICE);
691 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
693 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
694 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
695 else
696 alcSetError(ALC_INVALID_DEVICE);
700 alcGetError
702 Return last ALC generated error code
704 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
706 ALCenum errorCode;
708 (void)device;
710 errorCode = g_eLastContextError;
711 g_eLastContextError = ALC_NO_ERROR;
712 return errorCode;
717 alcSuspendContext
719 Not functional
721 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
723 // Not a lot happens here !
724 (void)pContext;
729 alcProcessContext
731 Not functional
733 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
735 // Not a lot happens here !
736 (void)pContext;
741 alcGetString
743 Returns information about the Device, and error strings
745 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
747 const ALCchar *value = NULL;
749 switch (param)
751 case ALC_NO_ERROR:
752 value = alcNoError;
753 break;
755 case ALC_INVALID_ENUM:
756 value = alcErrInvalidEnum;
757 break;
759 case ALC_INVALID_VALUE:
760 value = alcErrInvalidValue;
761 break;
763 case ALC_INVALID_DEVICE:
764 value = alcErrInvalidDevice;
765 break;
767 case ALC_INVALID_CONTEXT:
768 value = alcErrInvalidContext;
769 break;
771 case ALC_OUT_OF_MEMORY:
772 value = alcErrOutOfMemory;
773 break;
775 case ALC_DEVICE_SPECIFIER:
776 if(IsDevice(pDevice))
777 value = pDevice->szDeviceName;
778 else
780 ProbeDeviceList();
781 value = alcDeviceList;
783 break;
785 case ALC_ALL_DEVICES_SPECIFIER:
786 ProbeAllDeviceList();
787 value = alcAllDeviceList;
788 break;
790 case ALC_CAPTURE_DEVICE_SPECIFIER:
791 if(IsDevice(pDevice))
792 value = pDevice->szDeviceName;
793 else
795 ProbeCaptureDeviceList();
796 value = alcCaptureDeviceList;
798 break;
800 /* Default devices are always first in the list */
801 case ALC_DEFAULT_DEVICE_SPECIFIER:
802 free(alcDefaultDeviceSpecifier);
803 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
804 if(!alcDefaultDeviceSpecifier)
805 alcSetError(ALC_OUT_OF_MEMORY);
806 value = alcDefaultDeviceSpecifier;
807 break;
809 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
810 free(alcDefaultAllDeviceSpecifier);
811 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
812 alcAllDeviceList : "");
813 if(!alcDefaultAllDeviceSpecifier)
814 alcSetError(ALC_OUT_OF_MEMORY);
815 value = alcDefaultAllDeviceSpecifier;
816 break;
818 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
819 free(alcCaptureDefaultDeviceSpecifier);
820 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
821 alcCaptureDeviceList : "");
822 if(!alcCaptureDefaultDeviceSpecifier)
823 alcSetError(ALC_OUT_OF_MEMORY);
824 value = alcCaptureDefaultDeviceSpecifier;
825 break;
827 case ALC_EXTENSIONS:
828 value = alcExtensionList;
829 break;
831 default:
832 alcSetError(ALC_INVALID_ENUM);
833 break;
836 return value;
841 alcGetIntegerv
843 Returns information about the Device and the version of Open AL
845 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
847 if(IsDevice(device) && device->IsCaptureDevice)
849 SuspendContext(NULL);
851 // Capture device
852 switch (param)
854 case ALC_CAPTURE_SAMPLES:
855 if ((size) && (data))
856 *data = ALCdevice_AvailableSamples(device);
857 else
858 alcSetError(ALC_INVALID_VALUE);
859 break;
861 case ALC_CONNECTED:
862 if(size <= 0)
863 alcSetError(ALC_INVALID_VALUE);
864 else
865 *data = device->Connected;
866 break;
868 default:
869 alcSetError(ALC_INVALID_ENUM);
870 break;
873 ProcessContext(NULL);
875 else
877 if(data)
879 // Playback Device
880 switch (param)
882 case ALC_MAJOR_VERSION:
883 if(size <= 0)
884 alcSetError(ALC_INVALID_VALUE);
885 else
886 *data = alcMajorVersion;
887 break;
889 case ALC_MINOR_VERSION:
890 if(size <= 0)
891 alcSetError(ALC_INVALID_VALUE);
892 else
893 *data = alcMinorVersion;
894 break;
896 case ALC_EFX_MAJOR_VERSION:
897 if(size <= 0)
898 alcSetError(ALC_INVALID_VALUE);
899 else
900 *data = alcEFXMajorVersion;
901 break;
903 case ALC_EFX_MINOR_VERSION:
904 if(size <= 0)
905 alcSetError(ALC_INVALID_VALUE);
906 else
907 *data = alcEFXMinorVersion;
908 break;
910 case ALC_MAX_AUXILIARY_SENDS:
911 if(size <= 0)
912 alcSetError(ALC_INVALID_VALUE);
913 else
914 *data = (device?device->NumAuxSends:MAX_SENDS);
915 break;
917 case ALC_ATTRIBUTES_SIZE:
918 if(!IsDevice(device))
919 alcSetError(ALC_INVALID_DEVICE);
920 else if(size <= 0)
921 alcSetError(ALC_INVALID_VALUE);
922 else
923 *data = 13;
924 break;
926 case ALC_ALL_ATTRIBUTES:
927 if(!IsDevice(device))
928 alcSetError(ALC_INVALID_DEVICE);
929 else if (size < 13)
930 alcSetError(ALC_INVALID_VALUE);
931 else
933 int i = 0;
935 SuspendContext(NULL);
936 data[i++] = ALC_FREQUENCY;
937 data[i++] = device->Frequency;
939 data[i++] = ALC_REFRESH;
940 data[i++] = device->Frequency / device->UpdateSize;
942 data[i++] = ALC_SYNC;
943 data[i++] = ALC_FALSE;
945 data[i++] = ALC_MONO_SOURCES;
946 data[i++] = device->lNumMonoSources;
948 data[i++] = ALC_STEREO_SOURCES;
949 data[i++] = device->lNumStereoSources;
951 data[i++] = ALC_MAX_AUXILIARY_SENDS;
952 data[i++] = device->NumAuxSends;
954 data[i++] = 0;
955 ProcessContext(NULL);
957 break;
959 case ALC_FREQUENCY:
960 if(!IsDevice(device))
961 alcSetError(ALC_INVALID_DEVICE);
962 else if(size <= 0)
963 alcSetError(ALC_INVALID_VALUE);
964 else
965 *data = device->Frequency;
966 break;
968 case ALC_REFRESH:
969 if(!IsDevice(device))
970 alcSetError(ALC_INVALID_DEVICE);
971 else if(size <= 0)
972 alcSetError(ALC_INVALID_VALUE);
973 else
974 *data = device->Frequency / device->UpdateSize;
975 break;
977 case ALC_SYNC:
978 if(!IsDevice(device))
979 alcSetError(ALC_INVALID_DEVICE);
980 else if(size <= 0)
981 alcSetError(ALC_INVALID_VALUE);
982 else
983 *data = ALC_FALSE;
984 break;
986 case ALC_MONO_SOURCES:
987 if(!IsDevice(device))
988 alcSetError(ALC_INVALID_DEVICE);
989 else if(size <= 0)
990 alcSetError(ALC_INVALID_VALUE);
991 else
992 *data = device->lNumMonoSources;
993 break;
995 case ALC_STEREO_SOURCES:
996 if(!IsDevice(device))
997 alcSetError(ALC_INVALID_DEVICE);
998 else if(size <= 0)
999 alcSetError(ALC_INVALID_VALUE);
1000 else
1001 *data = device->lNumStereoSources;
1002 break;
1004 case ALC_CONNECTED:
1005 if(!IsDevice(device))
1006 alcSetError(ALC_INVALID_DEVICE);
1007 else if(size <= 0)
1008 alcSetError(ALC_INVALID_VALUE);
1009 else
1010 *data = device->Connected;
1011 break;
1013 default:
1014 alcSetError(ALC_INVALID_ENUM);
1015 break;
1018 else if(size)
1019 alcSetError(ALC_INVALID_VALUE);
1022 return;
1027 alcIsExtensionPresent
1029 Determines if there is support for a particular extension
1031 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1033 ALCboolean bResult = ALC_FALSE;
1035 (void)device;
1037 if (extName)
1039 const char *ptr;
1040 size_t len;
1042 len = strlen(extName);
1043 ptr = alcExtensionList;
1044 while(ptr && *ptr)
1046 if(strncasecmp(ptr, extName, len) == 0 &&
1047 (ptr[len] == '\0' || isspace(ptr[len])))
1049 bResult = ALC_TRUE;
1050 break;
1052 if((ptr=strchr(ptr, ' ')) != NULL)
1054 do {
1055 ++ptr;
1056 } while(isspace(*ptr));
1060 else
1061 alcSetError(ALC_INVALID_VALUE);
1063 return bResult;
1068 alcGetProcAddress
1070 Retrieves the function address for a particular extension function
1072 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1074 ALCvoid *pFunction = NULL;
1075 ALsizei i = 0;
1077 (void)device;
1079 if (funcName)
1081 while(alcFunctions[i].funcName &&
1082 strcmp(alcFunctions[i].funcName,funcName) != 0)
1083 i++;
1084 pFunction = alcFunctions[i].address;
1086 else
1087 alcSetError(ALC_INVALID_VALUE);
1089 return pFunction;
1094 alcGetEnumValue
1096 Get the value for a particular ALC Enumerated Value
1098 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1100 ALsizei i = 0;
1101 ALCenum val;
1103 (void)device;
1105 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1106 i++;
1107 val = enumeration[i].value;
1109 if(!enumeration[i].enumName)
1110 alcSetError(ALC_INVALID_VALUE);
1112 return val;
1117 alcCreateContext
1119 Create and attach a Context to a particular Device.
1121 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1123 ALuint attrIdx, reqStereoSources;
1124 ALCcontext *ALContext;
1125 void *temp;
1126 ALuint i;
1128 SuspendContext(NULL);
1130 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
1132 alcSetError(ALC_INVALID_DEVICE);
1133 ProcessContext(NULL);
1134 return NULL;
1137 // Reset Context Last Error code
1138 g_eLastContextError = ALC_NO_ERROR;
1140 // If a context is already running on the device, stop playback so the
1141 // device attributes can be updated
1142 if(device->NumContexts > 0)
1144 ProcessContext(NULL);
1145 ALCdevice_StopPlayback(device);
1146 SuspendContext(NULL);
1149 // Check for attributes
1150 if(attrList)
1152 ALCint level = device->Bs2bLevel;
1153 ALCuint freq = device->Frequency;
1154 ALCint numMono = device->lNumMonoSources;
1155 ALCint numStereo = device->lNumStereoSources;
1156 ALCuint numSends = device->NumAuxSends;
1158 attrIdx = 0;
1159 while(attrList[attrIdx])
1161 if(attrList[attrIdx] == ALC_FREQUENCY)
1163 freq = attrList[attrIdx + 1];
1164 if(freq == 0)
1165 freq = device->Frequency;
1168 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1170 reqStereoSources = attrList[attrIdx + 1];
1171 if(reqStereoSources > device->MaxNoOfSources)
1172 reqStereoSources = device->MaxNoOfSources;
1174 numStereo = reqStereoSources;
1175 numMono = device->MaxNoOfSources - numStereo;
1178 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1180 numSends = attrList[attrIdx + 1];
1181 if(numSends > MAX_SENDS)
1182 numSends = MAX_SENDS;
1185 attrIdx += 2;
1188 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", level);
1189 device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
1190 device->lNumMonoSources = numMono;
1191 device->lNumStereoSources = numStereo;
1192 device->NumAuxSends = GetConfigValueInt(NULL, "sends", numSends);
1195 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1197 alcSetError(ALC_INVALID_DEVICE);
1198 aluHandleDisconnect(device);
1199 ProcessContext(NULL);
1200 return NULL;
1203 for(i = 0;i < device->NumContexts;i++)
1205 ALCcontext *context = device->Contexts[i];
1206 ALeffectslot *slot;
1207 ALsource *source;
1209 SuspendContext(context);
1210 for(slot = context->AuxiliaryEffectSlot;slot != NULL;slot = slot->next)
1212 if(!slot->EffectState)
1213 continue;
1215 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1217 alcSetError(ALC_INVALID_DEVICE);
1218 aluHandleDisconnect(device);
1219 ProcessContext(context);
1220 ProcessContext(NULL);
1221 ALCdevice_StopPlayback(device);
1222 return NULL;
1224 ALEffect_Update(slot->EffectState, context, &slot->effect);
1227 for(source = context->Source;source != NULL;source = source->next)
1229 ALuint s = device->NumAuxSends;
1230 while(s < MAX_SENDS)
1232 if(source->Send[s].Slot)
1233 source->Send[s].Slot->refcount--;
1234 source->Send[s].Slot = NULL;
1235 source->Send[s].WetFilter.type = 0;
1236 source->Send[s].WetFilter.filter = 0;
1237 s++;
1240 ProcessContext(context);
1243 if(device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1245 if(!device->Bs2b)
1247 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1248 bs2b_clear(device->Bs2b);
1250 bs2b_set_srate(device->Bs2b, device->Frequency);
1251 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1253 else
1255 free(device->Bs2b);
1256 device->Bs2b = NULL;
1259 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
1260 if(!temp)
1262 alcSetError(ALC_OUT_OF_MEMORY);
1263 ProcessContext(NULL);
1264 return NULL;
1266 device->Contexts = temp;
1268 ALContext = calloc(1, sizeof(ALCcontext));
1269 if(!ALContext)
1271 alcSetError(ALC_OUT_OF_MEMORY);
1272 ProcessContext(NULL);
1273 return NULL;
1276 device->Contexts[device->NumContexts++] = ALContext;
1277 ALContext->Device = device;
1279 InitContext(ALContext);
1281 ALContext->next = g_pContextList;
1282 g_pContextList = ALContext;
1283 g_ulContextCount++;
1285 ProcessContext(NULL);
1287 return ALContext;
1292 alcDestroyContext
1294 Remove a Context
1296 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1298 ALCcontext **list;
1299 ALuint i;
1301 if (IsContext(context))
1303 ALCdevice *Device = context->Device;
1305 if(Device->NumContexts == 1)
1306 ALCdevice_StopPlayback(Device);
1308 SuspendContext(NULL);
1310 for(i = 0;i < Device->NumContexts-1;i++)
1312 if(Device->Contexts[i] == context)
1314 memmove(&Device->Contexts[i], &Device->Contexts[i+1],
1315 (Device->NumContexts-i-1) * sizeof(*Device->Contexts));
1316 break;
1319 Device->NumContexts--;
1321 // Lock context
1322 SuspendContext(context);
1324 if(context->SourceCount > 0)
1326 #ifdef _DEBUG
1327 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceCount);
1328 #endif
1329 ReleaseALSources(context);
1331 if(context->AuxiliaryEffectSlotCount > 0)
1333 #ifdef _DEBUG
1334 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->AuxiliaryEffectSlotCount);
1335 #endif
1336 ReleaseALAuxiliaryEffectSlots(context);
1339 list = &g_pContextList;
1340 while(*list != context)
1341 list = &(*list)->next;
1343 *list = (*list)->next;
1344 g_ulContextCount--;
1346 // Unlock context
1347 ProcessContext(context);
1348 ProcessContext(NULL);
1350 ExitContext(context);
1352 // Free memory (MUST do this after ProcessContext)
1353 memset(context, 0, sizeof(ALCcontext));
1354 free(context);
1356 else
1357 alcSetError(ALC_INVALID_CONTEXT);
1362 alcGetCurrentContext
1364 Returns the currently active Context
1366 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1368 ALCcontext *pContext;
1370 if((pContext=GetContextSuspended()) != NULL)
1371 ProcessContext(pContext);
1373 return pContext;
1377 alcGetThreadContext
1379 Returns the currently active thread-local Context
1381 ALCcontext * ALCAPIENTRY alcGetThreadContext(void)
1383 ALCcontext *pContext = NULL;
1385 SuspendContext(NULL);
1387 pContext = tls_get(LocalContext);
1388 if(pContext && !IsContext(pContext))
1390 tls_set(LocalContext, NULL);
1391 pContext = NULL;
1394 ProcessContext(NULL);
1396 return pContext;
1401 alcGetContextsDevice
1403 Returns the Device that a particular Context is attached to
1405 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1407 ALCdevice *pDevice = NULL;
1409 SuspendContext(NULL);
1410 if (IsContext(pContext))
1411 pDevice = pContext->Device;
1412 else
1413 alcSetError(ALC_INVALID_CONTEXT);
1414 ProcessContext(NULL);
1416 return pDevice;
1421 alcMakeContextCurrent
1423 Makes the given Context the active Context
1425 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1427 ALCcontext *ALContext;
1428 ALboolean bReturn = AL_TRUE;
1430 SuspendContext(NULL);
1432 // context must be a valid Context or NULL
1433 if(context == NULL || IsContext(context))
1435 if((ALContext=GetContextSuspended()) != NULL)
1437 ALContext->InUse=AL_FALSE;
1438 ProcessContext(ALContext);
1441 if((ALContext=context) != NULL && ALContext->Device)
1443 SuspendContext(ALContext);
1444 ALContext->InUse=AL_TRUE;
1445 ProcessContext(ALContext);
1448 tls_set(LocalContext, NULL);
1450 else
1452 alcSetError(ALC_INVALID_CONTEXT);
1453 bReturn = AL_FALSE;
1456 ProcessContext(NULL);
1458 return bReturn;
1462 alcMakeCurrent
1464 Makes the given Context the active Context for the current thread
1466 ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
1468 ALboolean bReturn = AL_TRUE;
1470 SuspendContext(NULL);
1472 // context must be a valid Context or NULL
1473 if(context == NULL || IsContext(context))
1474 tls_set(LocalContext, context);
1475 else
1477 alcSetError(ALC_INVALID_CONTEXT);
1478 bReturn = AL_FALSE;
1481 ProcessContext(NULL);
1483 return bReturn;
1487 static ALenum GetFormatFromString(const char *str)
1489 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1490 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1491 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1492 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1493 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1494 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1496 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1497 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1498 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1499 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1500 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1501 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1503 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1504 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1505 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1506 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1507 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1508 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1510 AL_PRINT("Unknown format: \"%s\"\n", str);
1511 return AL_FORMAT_STEREO16;
1515 alcOpenDevice
1517 Open the Device specified.
1519 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1521 ALboolean bDeviceFound = AL_FALSE;
1522 ALCdevice *device;
1523 ALint i;
1525 if(deviceName && !deviceName[0])
1526 deviceName = NULL;
1528 device = malloc(sizeof(ALCdevice));
1529 if (device)
1531 const char *fmt;
1533 //Initialise device structure
1534 memset(device, 0, sizeof(ALCdevice));
1536 //Validate device
1537 device->Connected = ALC_TRUE;
1538 device->IsCaptureDevice = AL_FALSE;
1540 device->Bs2b = NULL;
1541 device->szDeviceName = NULL;
1543 device->Contexts = NULL;
1544 device->NumContexts = 0;
1546 //Set output format
1547 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1548 if(device->Frequency == 0)
1549 device->Frequency = SWMIXER_OUTPUT_RATE;
1551 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1552 device->Format = GetFormatFromString(fmt);
1554 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
1555 if(device->NumUpdates < 2)
1556 device->NumUpdates = 4;
1558 i = GetConfigValueInt(NULL, "refresh", 4096);
1559 if(i <= 0) i = 4096;
1561 device->UpdateSize = GetConfigValueInt(NULL, "period_size", i/device->NumUpdates);
1562 if(device->UpdateSize <= 0)
1563 device->UpdateSize = i/device->NumUpdates;
1565 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1566 if((ALint)device->MaxNoOfSources <= 0)
1567 device->MaxNoOfSources = 256;
1569 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
1570 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
1571 device->AuxiliaryEffectSlotMax = 4;
1573 device->lNumStereoSources = 1;
1574 device->lNumMonoSources = device->MaxNoOfSources - device->lNumStereoSources;
1576 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
1577 if(device->NumAuxSends > MAX_SENDS)
1578 device->NumAuxSends = MAX_SENDS;
1580 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
1582 // Find a playback device to open
1583 SuspendContext(NULL);
1584 for(i = 0;BackendList[i].Init;i++)
1586 device->Funcs = &BackendList[i].Funcs;
1587 if(ALCdevice_OpenPlayback(device, deviceName))
1589 device->next = g_pDeviceList;
1590 g_pDeviceList = device;
1591 g_ulDeviceCount++;
1593 bDeviceFound = AL_TRUE;
1594 break;
1597 ProcessContext(NULL);
1599 if (!bDeviceFound)
1601 // No suitable output device found
1602 alcSetError(ALC_INVALID_VALUE);
1603 free(device);
1604 device = NULL;
1607 else
1608 alcSetError(ALC_OUT_OF_MEMORY);
1610 return device;
1615 alcCloseDevice
1617 Close the specified Device
1619 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1621 ALCboolean bReturn = ALC_FALSE;
1622 ALCdevice **list;
1624 if(IsDevice(pDevice) && !pDevice->IsCaptureDevice)
1626 SuspendContext(NULL);
1628 list = &g_pDeviceList;
1629 while(*list != pDevice)
1630 list = &(*list)->next;
1632 *list = (*list)->next;
1633 g_ulDeviceCount--;
1635 ProcessContext(NULL);
1637 if(pDevice->NumContexts > 0)
1639 #ifdef _DEBUG
1640 AL_PRINT("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
1641 #endif
1642 while(pDevice->NumContexts > 0)
1643 alcDestroyContext(pDevice->Contexts[0]);
1645 ALCdevice_ClosePlayback(pDevice);
1647 if(pDevice->BufferCount > 0)
1649 #ifdef _DEBUG
1650 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferCount);
1651 #endif
1652 ReleaseALBuffers(pDevice);
1654 if(pDevice->EffectCount > 0)
1656 #ifdef _DEBUG
1657 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectCount);
1658 #endif
1659 ReleaseALEffects(pDevice);
1661 if(pDevice->FilterCount > 0)
1663 #ifdef _DEBUG
1664 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterCount);
1665 #endif
1666 ReleaseALFilters(pDevice);
1668 if(pDevice->DatabufferCount > 0)
1670 #ifdef _DEBUG
1671 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferCount);
1672 #endif
1673 ReleaseALDatabuffers(pDevice);
1676 free(pDevice->Bs2b);
1677 pDevice->Bs2b = NULL;
1679 free(pDevice->szDeviceName);
1680 pDevice->szDeviceName = NULL;
1682 free(pDevice->Contexts);
1683 pDevice->Contexts = NULL;
1685 //Release device structure
1686 memset(pDevice, 0, sizeof(ALCdevice));
1687 free(pDevice);
1689 bReturn = ALC_TRUE;
1691 else
1692 alcSetError(ALC_INVALID_DEVICE);
1694 return bReturn;
1698 ALCvoid ReleaseALC(ALCvoid)
1700 free(alcDeviceList); alcDeviceList = NULL;
1701 alcDeviceListSize = 0;
1702 free(alcAllDeviceList); alcAllDeviceList = NULL;
1703 alcAllDeviceListSize = 0;
1704 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1705 alcCaptureDeviceListSize = 0;
1707 free(alcDefaultDeviceSpecifier);
1708 alcDefaultDeviceSpecifier = NULL;
1709 free(alcDefaultAllDeviceSpecifier);
1710 alcDefaultAllDeviceSpecifier = NULL;
1711 free(alcCaptureDefaultDeviceSpecifier);
1712 alcCaptureDefaultDeviceSpecifier = NULL;
1714 #ifdef _DEBUG
1715 if(g_ulDeviceCount > 0)
1716 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1717 #endif
1719 while(g_pDeviceList)
1721 if(g_pDeviceList->IsCaptureDevice)
1722 alcCaptureCloseDevice(g_pDeviceList);
1723 else
1724 alcCloseDevice(g_pDeviceList);
1728 ///////////////////////////////////////////////////////