Small fixups
[openal-soft.git] / Alc / ALc.c
blob7398e151f73132d54b23fe1eda35dd4985b8b3bf
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 free(pDevice->szDeviceName);
662 ALCdevice_CloseCapture(pDevice);
663 free(pDevice);
665 bReturn = ALC_TRUE;
667 else
668 alcSetError(ALC_INVALID_DEVICE);
670 return bReturn;
673 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
675 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
676 ALCdevice_StartCapture(pDevice);
677 else
678 alcSetError(ALC_INVALID_DEVICE);
681 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
683 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
684 ALCdevice_StopCapture(pDevice);
685 else
686 alcSetError(ALC_INVALID_DEVICE);
689 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
691 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
692 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
693 else
694 alcSetError(ALC_INVALID_DEVICE);
698 alcGetError
700 Return last ALC generated error code
702 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
704 ALCenum errorCode;
706 (void)device;
708 errorCode = g_eLastContextError;
709 g_eLastContextError = ALC_NO_ERROR;
710 return errorCode;
715 alcSuspendContext
717 Not functional
719 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
721 // Not a lot happens here !
722 (void)pContext;
727 alcProcessContext
729 Not functional
731 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
733 // Not a lot happens here !
734 (void)pContext;
739 alcGetString
741 Returns information about the Device, and error strings
743 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
745 const ALCchar *value = NULL;
747 switch (param)
749 case ALC_NO_ERROR:
750 value = alcNoError;
751 break;
753 case ALC_INVALID_ENUM:
754 value = alcErrInvalidEnum;
755 break;
757 case ALC_INVALID_VALUE:
758 value = alcErrInvalidValue;
759 break;
761 case ALC_INVALID_DEVICE:
762 value = alcErrInvalidDevice;
763 break;
765 case ALC_INVALID_CONTEXT:
766 value = alcErrInvalidContext;
767 break;
769 case ALC_OUT_OF_MEMORY:
770 value = alcErrOutOfMemory;
771 break;
773 case ALC_DEVICE_SPECIFIER:
774 if(IsDevice(pDevice))
775 value = pDevice->szDeviceName;
776 else
778 ProbeDeviceList();
779 value = alcDeviceList;
781 break;
783 case ALC_ALL_DEVICES_SPECIFIER:
784 ProbeAllDeviceList();
785 value = alcAllDeviceList;
786 break;
788 case ALC_CAPTURE_DEVICE_SPECIFIER:
789 if(IsDevice(pDevice))
790 value = pDevice->szDeviceName;
791 else
793 ProbeCaptureDeviceList();
794 value = alcCaptureDeviceList;
796 break;
798 /* Default devices are always first in the list */
799 case ALC_DEFAULT_DEVICE_SPECIFIER:
800 free(alcDefaultDeviceSpecifier);
801 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
802 if(!alcDefaultDeviceSpecifier)
803 alcSetError(ALC_OUT_OF_MEMORY);
804 value = alcDefaultDeviceSpecifier;
805 break;
807 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
808 free(alcDefaultAllDeviceSpecifier);
809 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
810 alcAllDeviceList : "");
811 if(!alcDefaultAllDeviceSpecifier)
812 alcSetError(ALC_OUT_OF_MEMORY);
813 value = alcDefaultAllDeviceSpecifier;
814 break;
816 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
817 free(alcCaptureDefaultDeviceSpecifier);
818 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
819 alcCaptureDeviceList : "");
820 if(!alcCaptureDefaultDeviceSpecifier)
821 alcSetError(ALC_OUT_OF_MEMORY);
822 value = alcCaptureDefaultDeviceSpecifier;
823 break;
825 case ALC_EXTENSIONS:
826 value = alcExtensionList;
827 break;
829 default:
830 alcSetError(ALC_INVALID_ENUM);
831 break;
834 return value;
839 alcGetIntegerv
841 Returns information about the Device and the version of Open AL
843 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
845 if(IsDevice(device) && device->IsCaptureDevice)
847 SuspendContext(NULL);
849 // Capture device
850 switch (param)
852 case ALC_CAPTURE_SAMPLES:
853 if ((size) && (data))
854 *data = ALCdevice_AvailableSamples(device);
855 else
856 alcSetError(ALC_INVALID_VALUE);
857 break;
859 case ALC_CONNECTED:
860 if(size <= 0)
861 alcSetError(ALC_INVALID_VALUE);
862 else
863 *data = device->Connected;
864 break;
866 default:
867 alcSetError(ALC_INVALID_ENUM);
868 break;
871 ProcessContext(NULL);
873 else
875 if(data)
877 // Playback Device
878 switch (param)
880 case ALC_MAJOR_VERSION:
881 if(size <= 0)
882 alcSetError(ALC_INVALID_VALUE);
883 else
884 *data = alcMajorVersion;
885 break;
887 case ALC_MINOR_VERSION:
888 if(size <= 0)
889 alcSetError(ALC_INVALID_VALUE);
890 else
891 *data = alcMinorVersion;
892 break;
894 case ALC_EFX_MAJOR_VERSION:
895 if(size <= 0)
896 alcSetError(ALC_INVALID_VALUE);
897 else
898 *data = alcEFXMajorVersion;
899 break;
901 case ALC_EFX_MINOR_VERSION:
902 if(size <= 0)
903 alcSetError(ALC_INVALID_VALUE);
904 else
905 *data = alcEFXMinorVersion;
906 break;
908 case ALC_MAX_AUXILIARY_SENDS:
909 if(size <= 0)
910 alcSetError(ALC_INVALID_VALUE);
911 else
912 *data = (device?device->NumAuxSends:MAX_SENDS);
913 break;
915 case ALC_ATTRIBUTES_SIZE:
916 if(!IsDevice(device))
917 alcSetError(ALC_INVALID_DEVICE);
918 else if(size <= 0)
919 alcSetError(ALC_INVALID_VALUE);
920 else
921 *data = 13;
922 break;
924 case ALC_ALL_ATTRIBUTES:
925 if(!IsDevice(device))
926 alcSetError(ALC_INVALID_DEVICE);
927 else if (size < 13)
928 alcSetError(ALC_INVALID_VALUE);
929 else
931 int i = 0;
933 SuspendContext(NULL);
934 data[i++] = ALC_FREQUENCY;
935 data[i++] = device->Frequency;
937 data[i++] = ALC_REFRESH;
938 data[i++] = device->Frequency / device->UpdateSize;
940 data[i++] = ALC_SYNC;
941 data[i++] = ALC_FALSE;
943 data[i++] = ALC_MONO_SOURCES;
944 data[i++] = device->lNumMonoSources;
946 data[i++] = ALC_STEREO_SOURCES;
947 data[i++] = device->lNumStereoSources;
949 data[i++] = ALC_MAX_AUXILIARY_SENDS;
950 data[i++] = device->NumAuxSends;
952 data[i++] = 0;
953 ProcessContext(NULL);
955 break;
957 case ALC_FREQUENCY:
958 if(!IsDevice(device))
959 alcSetError(ALC_INVALID_DEVICE);
960 else if(size <= 0)
961 alcSetError(ALC_INVALID_VALUE);
962 else
963 *data = device->Frequency;
964 break;
966 case ALC_REFRESH:
967 if(!IsDevice(device))
968 alcSetError(ALC_INVALID_DEVICE);
969 else if(size <= 0)
970 alcSetError(ALC_INVALID_VALUE);
971 else
972 *data = device->Frequency / device->UpdateSize;
973 break;
975 case ALC_SYNC:
976 if(!IsDevice(device))
977 alcSetError(ALC_INVALID_DEVICE);
978 else if(size <= 0)
979 alcSetError(ALC_INVALID_VALUE);
980 else
981 *data = ALC_FALSE;
982 break;
984 case ALC_MONO_SOURCES:
985 if(!IsDevice(device))
986 alcSetError(ALC_INVALID_DEVICE);
987 else if(size <= 0)
988 alcSetError(ALC_INVALID_VALUE);
989 else
990 *data = device->lNumMonoSources;
991 break;
993 case ALC_STEREO_SOURCES:
994 if(!IsDevice(device))
995 alcSetError(ALC_INVALID_DEVICE);
996 else if(size <= 0)
997 alcSetError(ALC_INVALID_VALUE);
998 else
999 *data = device->lNumStereoSources;
1000 break;
1002 case ALC_CONNECTED:
1003 if(!IsDevice(device))
1004 alcSetError(ALC_INVALID_DEVICE);
1005 else if(size <= 0)
1006 alcSetError(ALC_INVALID_VALUE);
1007 else
1008 *data = device->Connected;
1009 break;
1011 default:
1012 alcSetError(ALC_INVALID_ENUM);
1013 break;
1016 else if(size)
1017 alcSetError(ALC_INVALID_VALUE);
1020 return;
1025 alcIsExtensionPresent
1027 Determines if there is support for a particular extension
1029 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1031 ALCboolean bResult = ALC_FALSE;
1033 (void)device;
1035 if (extName)
1037 const char *ptr;
1038 size_t len;
1040 len = strlen(extName);
1041 ptr = alcExtensionList;
1042 while(ptr && *ptr)
1044 if(strncasecmp(ptr, extName, len) == 0 &&
1045 (ptr[len] == '\0' || isspace(ptr[len])))
1047 bResult = ALC_TRUE;
1048 break;
1050 if((ptr=strchr(ptr, ' ')) != NULL)
1052 do {
1053 ++ptr;
1054 } while(isspace(*ptr));
1058 else
1059 alcSetError(ALC_INVALID_VALUE);
1061 return bResult;
1066 alcGetProcAddress
1068 Retrieves the function address for a particular extension function
1070 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1072 ALCvoid *pFunction = NULL;
1073 ALsizei i = 0;
1075 (void)device;
1077 if (funcName)
1079 while(alcFunctions[i].funcName &&
1080 strcmp(alcFunctions[i].funcName,funcName) != 0)
1081 i++;
1082 pFunction = alcFunctions[i].address;
1084 else
1085 alcSetError(ALC_INVALID_VALUE);
1087 return pFunction;
1092 alcGetEnumValue
1094 Get the value for a particular ALC Enumerated Value
1096 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1098 ALsizei i = 0;
1099 ALCenum val;
1101 (void)device;
1103 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1104 i++;
1105 val = enumeration[i].value;
1107 if(!enumeration[i].enumName)
1108 alcSetError(ALC_INVALID_VALUE);
1110 return val;
1115 alcCreateContext
1117 Create and attach a Context to a particular Device.
1119 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1121 ALuint attrIdx, reqStereoSources;
1122 ALCcontext *ALContext;
1123 void *temp;
1124 ALuint i;
1126 SuspendContext(NULL);
1128 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
1130 alcSetError(ALC_INVALID_DEVICE);
1131 ProcessContext(NULL);
1132 return NULL;
1135 // Reset Context Last Error code
1136 g_eLastContextError = ALC_NO_ERROR;
1138 // If a context is already running on the device, stop playback so the
1139 // device attributes can be updated
1140 if(device->NumContexts > 0)
1142 ProcessContext(NULL);
1143 ALCdevice_StopPlayback(device);
1144 SuspendContext(NULL);
1147 // Check for attributes
1148 if(attrList)
1150 ALCint level = device->Bs2bLevel;
1151 ALCuint freq = device->Frequency;
1152 ALCint numMono = device->lNumMonoSources;
1153 ALCint numStereo = device->lNumStereoSources;
1154 ALCuint numSends = device->NumAuxSends;
1156 attrIdx = 0;
1157 while(attrList[attrIdx])
1159 if(attrList[attrIdx] == ALC_FREQUENCY)
1161 freq = attrList[attrIdx + 1];
1162 if(freq == 0)
1163 freq = device->Frequency;
1166 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1168 reqStereoSources = attrList[attrIdx + 1];
1169 if(reqStereoSources > device->MaxNoOfSources)
1170 reqStereoSources = device->MaxNoOfSources;
1172 numStereo = reqStereoSources;
1173 numMono = device->MaxNoOfSources - numStereo;
1176 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1178 numSends = attrList[attrIdx + 1];
1179 if(numSends > MAX_SENDS)
1180 numSends = MAX_SENDS;
1183 attrIdx += 2;
1186 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", level);
1187 device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
1188 device->lNumMonoSources = numMono;
1189 device->lNumStereoSources = numStereo;
1190 device->NumAuxSends = GetConfigValueInt(NULL, "sends", numSends);
1193 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1195 alcSetError(ALC_INVALID_DEVICE);
1196 aluHandleDisconnect(device);
1197 ProcessContext(NULL);
1198 return NULL;
1201 for(i = 0;i < device->NumContexts;i++)
1203 ALCcontext *context = device->Contexts[i];
1204 ALeffectslot *slot;
1205 ALsource *source;
1207 SuspendContext(context);
1208 for(slot = context->AuxiliaryEffectSlot;slot != NULL;slot = slot->next)
1210 if(!slot->EffectState)
1211 continue;
1213 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1215 alcSetError(ALC_INVALID_DEVICE);
1216 aluHandleDisconnect(device);
1217 ProcessContext(context);
1218 ProcessContext(NULL);
1219 ALCdevice_StopPlayback(device);
1220 return NULL;
1222 ALEffect_Update(slot->EffectState, context, &slot->effect);
1225 for(source = context->Source;source != NULL;source = source->next)
1227 ALuint s = device->NumAuxSends;
1228 while(s < MAX_SENDS)
1230 if(source->Send[s].Slot)
1231 source->Send[s].Slot->refcount--;
1232 source->Send[s].Slot = NULL;
1233 source->Send[s].WetFilter.type = 0;
1234 source->Send[s].WetFilter.filter = 0;
1235 s++;
1238 ProcessContext(context);
1241 if(device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1243 if(!device->Bs2b)
1245 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1246 bs2b_clear(device->Bs2b);
1248 bs2b_set_srate(device->Bs2b, device->Frequency);
1249 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1251 else
1253 free(device->Bs2b);
1254 device->Bs2b = NULL;
1257 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
1258 if(!temp)
1260 alcSetError(ALC_OUT_OF_MEMORY);
1261 ProcessContext(NULL);
1262 return NULL;
1264 device->Contexts = temp;
1266 ALContext = calloc(1, sizeof(ALCcontext));
1267 if(!ALContext)
1269 alcSetError(ALC_OUT_OF_MEMORY);
1270 ProcessContext(NULL);
1271 return NULL;
1274 device->Contexts[device->NumContexts++] = ALContext;
1275 ALContext->Device = device;
1277 InitContext(ALContext);
1279 ALContext->next = g_pContextList;
1280 g_pContextList = ALContext;
1281 g_ulContextCount++;
1283 ProcessContext(NULL);
1285 return ALContext;
1290 alcDestroyContext
1292 Remove a Context
1294 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1296 ALCcontext **list;
1297 ALuint i;
1299 if (IsContext(context))
1301 ALCdevice *Device = context->Device;
1303 if(Device->NumContexts == 1)
1304 ALCdevice_StopPlayback(Device);
1306 SuspendContext(NULL);
1308 for(i = 0;i < Device->NumContexts-1;i++)
1310 if(Device->Contexts[i] == context)
1312 memmove(&Device->Contexts[i], &Device->Contexts[i+1],
1313 (Device->NumContexts-i-1) * sizeof(*Device->Contexts));
1314 break;
1317 Device->NumContexts--;
1319 // Lock context
1320 SuspendContext(context);
1322 if(context->SourceCount > 0)
1324 #ifdef _DEBUG
1325 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceCount);
1326 #endif
1327 ReleaseALSources(context);
1329 if(context->AuxiliaryEffectSlotCount > 0)
1331 #ifdef _DEBUG
1332 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->AuxiliaryEffectSlotCount);
1333 #endif
1334 ReleaseALAuxiliaryEffectSlots(context);
1337 list = &g_pContextList;
1338 while(*list != context)
1339 list = &(*list)->next;
1341 *list = (*list)->next;
1342 g_ulContextCount--;
1344 // Unlock context
1345 ProcessContext(context);
1346 ProcessContext(NULL);
1348 ExitContext(context);
1350 // Free memory (MUST do this after ProcessContext)
1351 memset(context, 0, sizeof(ALCcontext));
1352 free(context);
1354 else
1355 alcSetError(ALC_INVALID_CONTEXT);
1360 alcGetCurrentContext
1362 Returns the currently active Context
1364 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1366 ALCcontext *pContext;
1368 if((pContext=GetContextSuspended()) != NULL)
1369 ProcessContext(pContext);
1371 return pContext;
1375 alcGetThreadContext
1377 Returns the currently active thread-local Context
1379 ALCcontext * ALCAPIENTRY alcGetThreadContext(void)
1381 ALCcontext *pContext = NULL;
1383 SuspendContext(NULL);
1385 pContext = tls_get(LocalContext);
1386 if(pContext && !IsContext(pContext))
1388 tls_set(LocalContext, NULL);
1389 pContext = NULL;
1392 ProcessContext(NULL);
1394 return pContext;
1399 alcGetContextsDevice
1401 Returns the Device that a particular Context is attached to
1403 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1405 ALCdevice *pDevice = NULL;
1407 SuspendContext(NULL);
1408 if (IsContext(pContext))
1409 pDevice = pContext->Device;
1410 else
1411 alcSetError(ALC_INVALID_CONTEXT);
1412 ProcessContext(NULL);
1414 return pDevice;
1419 alcMakeContextCurrent
1421 Makes the given Context the active Context
1423 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1425 ALCcontext *ALContext;
1426 ALboolean bReturn = AL_TRUE;
1428 SuspendContext(NULL);
1430 // context must be a valid Context or NULL
1431 if(context == NULL || IsContext(context))
1433 if((ALContext=GetContextSuspended()) != NULL)
1435 ALContext->InUse=AL_FALSE;
1436 ProcessContext(ALContext);
1439 if((ALContext=context) != NULL && ALContext->Device)
1441 SuspendContext(ALContext);
1442 ALContext->InUse=AL_TRUE;
1443 ProcessContext(ALContext);
1446 tls_set(LocalContext, NULL);
1448 else
1450 alcSetError(ALC_INVALID_CONTEXT);
1451 bReturn = AL_FALSE;
1454 ProcessContext(NULL);
1456 return bReturn;
1460 alcMakeCurrent
1462 Makes the given Context the active Context for the current thread
1464 ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
1466 ALboolean bReturn = AL_TRUE;
1468 SuspendContext(NULL);
1470 // context must be a valid Context or NULL
1471 if(context == NULL || IsContext(context))
1472 tls_set(LocalContext, context);
1473 else
1475 alcSetError(ALC_INVALID_CONTEXT);
1476 bReturn = AL_FALSE;
1479 ProcessContext(NULL);
1481 return bReturn;
1485 static ALenum GetFormatFromString(const char *str)
1487 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1488 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1489 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1490 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1491 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1492 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1494 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1495 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1496 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1497 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1498 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1499 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1501 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1502 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1503 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1504 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1505 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1506 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1508 AL_PRINT("Unknown format: \"%s\"\n", str);
1509 return AL_FORMAT_STEREO16;
1513 alcOpenDevice
1515 Open the Device specified.
1517 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1519 ALboolean bDeviceFound = AL_FALSE;
1520 ALCdevice *device;
1521 ALint i;
1523 if(deviceName && !deviceName[0])
1524 deviceName = NULL;
1526 device = malloc(sizeof(ALCdevice));
1527 if (device)
1529 const char *fmt;
1531 //Initialise device structure
1532 memset(device, 0, sizeof(ALCdevice));
1534 //Validate device
1535 device->Connected = ALC_TRUE;
1536 device->IsCaptureDevice = AL_FALSE;
1538 device->Bs2b = NULL;
1539 device->szDeviceName = NULL;
1541 device->Contexts = NULL;
1542 device->NumContexts = 0;
1544 //Set output format
1545 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1546 if(device->Frequency == 0)
1547 device->Frequency = SWMIXER_OUTPUT_RATE;
1549 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1550 device->Format = GetFormatFromString(fmt);
1552 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
1553 if(device->NumUpdates < 2)
1554 device->NumUpdates = 4;
1556 i = GetConfigValueInt(NULL, "refresh", 4096);
1557 if(i <= 0) i = 4096;
1559 device->UpdateSize = GetConfigValueInt(NULL, "period_size", i/device->NumUpdates);
1560 if(device->UpdateSize <= 0)
1561 device->UpdateSize = i/device->NumUpdates;
1563 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1564 if((ALint)device->MaxNoOfSources <= 0)
1565 device->MaxNoOfSources = 256;
1567 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
1568 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
1569 device->AuxiliaryEffectSlotMax = 4;
1571 device->lNumStereoSources = 1;
1572 device->lNumMonoSources = device->MaxNoOfSources - device->lNumStereoSources;
1574 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
1575 if(device->NumAuxSends > MAX_SENDS)
1576 device->NumAuxSends = MAX_SENDS;
1578 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
1580 // Find a playback device to open
1581 SuspendContext(NULL);
1582 for(i = 0;BackendList[i].Init;i++)
1584 device->Funcs = &BackendList[i].Funcs;
1585 if(ALCdevice_OpenPlayback(device, deviceName))
1587 device->next = g_pDeviceList;
1588 g_pDeviceList = device;
1589 g_ulDeviceCount++;
1591 bDeviceFound = AL_TRUE;
1592 break;
1595 ProcessContext(NULL);
1597 if (!bDeviceFound)
1599 // No suitable output device found
1600 alcSetError(ALC_INVALID_VALUE);
1601 free(device);
1602 device = NULL;
1605 else
1606 alcSetError(ALC_OUT_OF_MEMORY);
1608 return device;
1613 alcCloseDevice
1615 Close the specified Device
1617 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1619 ALCboolean bReturn = ALC_FALSE;
1620 ALCdevice **list;
1622 if(IsDevice(pDevice) && !pDevice->IsCaptureDevice)
1624 SuspendContext(NULL);
1626 list = &g_pDeviceList;
1627 while(*list != pDevice)
1628 list = &(*list)->next;
1630 *list = (*list)->next;
1631 g_ulDeviceCount--;
1633 ProcessContext(NULL);
1635 if(pDevice->NumContexts > 0)
1637 #ifdef _DEBUG
1638 AL_PRINT("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
1639 #endif
1640 while(pDevice->NumContexts > 0)
1641 alcDestroyContext(pDevice->Contexts[0]);
1643 ALCdevice_ClosePlayback(pDevice);
1645 if(pDevice->BufferCount > 0)
1647 #ifdef _DEBUG
1648 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferCount);
1649 #endif
1650 ReleaseALBuffers(pDevice);
1652 if(pDevice->EffectCount > 0)
1654 #ifdef _DEBUG
1655 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectCount);
1656 #endif
1657 ReleaseALEffects(pDevice);
1659 if(pDevice->FilterCount > 0)
1661 #ifdef _DEBUG
1662 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterCount);
1663 #endif
1664 ReleaseALFilters(pDevice);
1666 if(pDevice->DatabufferCount > 0)
1668 #ifdef _DEBUG
1669 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferCount);
1670 #endif
1671 ReleaseALDatabuffers(pDevice);
1674 free(pDevice->Bs2b);
1675 pDevice->Bs2b = NULL;
1677 free(pDevice->szDeviceName);
1678 pDevice->szDeviceName = NULL;
1680 free(pDevice->Contexts);
1681 pDevice->Contexts = NULL;
1683 //Release device structure
1684 memset(pDevice, 0, sizeof(ALCdevice));
1685 free(pDevice);
1687 bReturn = ALC_TRUE;
1689 else
1690 alcSetError(ALC_INVALID_DEVICE);
1692 return bReturn;
1696 ALCvoid ReleaseALC(ALCvoid)
1698 free(alcDeviceList); alcDeviceList = NULL;
1699 alcDeviceListSize = 0;
1700 free(alcAllDeviceList); alcAllDeviceList = NULL;
1701 alcAllDeviceListSize = 0;
1702 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1703 alcCaptureDeviceListSize = 0;
1705 free(alcDefaultDeviceSpecifier);
1706 alcDefaultDeviceSpecifier = NULL;
1707 free(alcDefaultAllDeviceSpecifier);
1708 alcDefaultAllDeviceSpecifier = NULL;
1709 free(alcCaptureDefaultDeviceSpecifier);
1710 alcCaptureDefaultDeviceSpecifier = NULL;
1712 #ifdef _DEBUG
1713 if(g_ulDeviceCount > 0)
1714 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1715 #endif
1717 while(g_pDeviceList)
1719 if(g_pDeviceList->IsCaptureDevice)
1720 alcCaptureCloseDevice(g_pDeviceList);
1721 else
1722 alcCloseDevice(g_pDeviceList);
1726 ///////////////////////////////////////////////////////