Fix retrieved update size from pulseaudio
[openal-soft.git] / Alc / ALc.c
blob9225f3305c4326a9612c7852a77a7d31110c4684
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;
262 int endlist;
264 i = 0;
265 do {
266 devs = next;
267 next = strchr(devs, ',');
269 if(!devs[0] || devs[0] == ',')
271 endlist = 0;
272 continue;
274 endlist = 1;
276 len = (next ? ((size_t)(next-devs)) : strlen(devs));
277 for(n = i;BackendList[n].Init;n++)
279 if(len == strlen(BackendList[n].name) &&
280 strncmp(BackendList[n].name, devs, len) == 0)
282 BackendInfo Bkp = BackendList[n];
283 while(n > i)
285 BackendList[n] = BackendList[n-1];
286 --n;
288 BackendList[n] = Bkp;
290 i++;
291 break;
294 } while(next++);
296 if(endlist)
298 BackendList[i].name = NULL;
299 BackendList[i].Init = NULL;
300 BackendList[i].Deinit = NULL;
301 BackendList[i].Probe = NULL;
305 for(i = 0;BackendList[i].Init;i++)
307 BackendList[i].Init(&BackendList[i].Funcs);
309 BackendList[i].Probe(DEVICE_PROBE);
310 BackendList[i].Probe(ALL_DEVICE_PROBE);
311 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
314 DuplicateStereo = GetConfigValueBool(NULL, "stereodup", 0);
316 str = GetConfigValue(NULL, "excludefx", "");
317 if(str[0])
319 const struct {
320 const char *name;
321 int type;
322 } EffectList[] = {
323 { "eaxreverb", EAXREVERB },
324 { "reverb", REVERB },
325 { "echo", ECHO },
326 { NULL, 0 }
328 int n;
329 size_t len;
330 const char *next = str;
332 do {
333 str = next;
334 next = strchr(str, ',');
336 if(!str[0] || next == str)
337 continue;
339 len = (next ? ((size_t)(next-str)) : strlen(str));
340 for(n = 0;EffectList[n].name;n++)
342 if(len == strlen(EffectList[n].name) &&
343 strncmp(EffectList[n].name, str, len) == 0)
344 DisabledEffects[EffectList[n].type] = AL_TRUE;
346 } while(next++);
350 static void alc_deinit(void)
352 int i;
354 ReleaseALC();
356 for(i = 0;BackendList[i].Deinit;i++)
357 BackendList[i].Deinit();
359 tls_delete(LocalContext);
361 FreeALConfig();
362 ALTHUNK_EXIT();
363 DeleteCriticalSection(&g_csMutex);
367 static void ProbeDeviceList()
369 ALint i;
371 free(alcDeviceList); alcDeviceList = NULL;
372 alcDeviceListSize = 0;
374 for(i = 0;BackendList[i].Probe;i++)
375 BackendList[i].Probe(DEVICE_PROBE);
378 static void ProbeAllDeviceList()
380 ALint i;
382 free(alcAllDeviceList); alcAllDeviceList = NULL;
383 alcAllDeviceListSize = 0;
385 for(i = 0;BackendList[i].Probe;i++)
386 BackendList[i].Probe(ALL_DEVICE_PROBE);
389 static void ProbeCaptureDeviceList()
391 ALint i;
393 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
394 alcCaptureDeviceListSize = 0;
396 for(i = 0;BackendList[i].Probe;i++)
397 BackendList[i].Probe(CAPTURE_DEVICE_PROBE);
401 #define DECL_APPEND_LIST_FUNC(type) \
402 void Append##type##List(const ALCchar *name) \
404 ALCuint len = strlen(name); \
405 void *temp; \
407 if(len == 0) \
408 return; \
410 temp = realloc(alc##type##List, alc##type##ListSize + len + 2); \
411 if(!temp) \
413 AL_PRINT("Realloc failed to add %s!\n", name); \
414 return; \
416 alc##type##List = temp; \
417 sprintf(alc##type##List+alc##type##ListSize, "%s", name); \
418 alc##type##ListSize += len+1; \
419 alc##type##List[alc##type##ListSize] = 0; \
422 DECL_APPEND_LIST_FUNC(Device)
423 DECL_APPEND_LIST_FUNC(AllDevice)
424 DECL_APPEND_LIST_FUNC(CaptureDevice)
428 IsDevice
430 Check pDevice is a valid Device pointer
432 static ALCboolean IsDevice(ALCdevice *pDevice)
434 ALCdevice *pTempDevice;
436 SuspendContext(NULL);
438 pTempDevice = g_pDeviceList;
439 while(pTempDevice && pTempDevice != pDevice)
440 pTempDevice = pTempDevice->next;
442 ProcessContext(NULL);
444 return (pTempDevice ? ALC_TRUE : ALC_FALSE);
448 IsContext
450 Check pContext is a valid Context pointer
452 static ALCboolean IsContext(ALCcontext *pContext)
454 ALCcontext *pTempContext;
456 SuspendContext(NULL);
458 pTempContext = g_pContextList;
459 while (pTempContext && pTempContext != pContext)
460 pTempContext = pTempContext->next;
462 ProcessContext(NULL);
464 return (pTempContext ? ALC_TRUE : ALC_FALSE);
469 alcSetError
471 Store latest ALC Error
473 ALCvoid alcSetError(ALenum errorCode)
475 g_eLastContextError = errorCode;
480 SuspendContext
482 Thread-safe entry
484 ALCvoid SuspendContext(ALCcontext *pContext)
486 (void)pContext;
487 EnterCriticalSection(&g_csMutex);
492 ProcessContext
494 Thread-safe exit
496 ALCvoid ProcessContext(ALCcontext *pContext)
498 (void)pContext;
499 LeaveCriticalSection(&g_csMutex);
504 GetContextSuspended
506 Returns the currently active Context, in a locked state
508 ALCcontext *GetContextSuspended(void)
510 ALCcontext *pContext = NULL;
512 SuspendContext(NULL);
514 pContext = tls_get(LocalContext);
515 if(pContext && !IsContext(pContext))
517 tls_set(LocalContext, NULL);
518 pContext = NULL;
520 if(!pContext)
522 pContext = g_pContextList;
523 while(pContext && !pContext->InUse)
524 pContext = pContext->next;
526 if(pContext)
527 SuspendContext(pContext);
529 ProcessContext(NULL);
531 return pContext;
536 InitContext
538 Initialize Context variables
540 static ALvoid InitContext(ALCcontext *pContext)
542 //Initialise listener
543 pContext->Listener.Gain = 1.0f;
544 pContext->Listener.MetersPerUnit = 1.0f;
545 pContext->Listener.Position[0] = 0.0f;
546 pContext->Listener.Position[1] = 0.0f;
547 pContext->Listener.Position[2] = 0.0f;
548 pContext->Listener.Velocity[0] = 0.0f;
549 pContext->Listener.Velocity[1] = 0.0f;
550 pContext->Listener.Velocity[2] = 0.0f;
551 pContext->Listener.Forward[0] = 0.0f;
552 pContext->Listener.Forward[1] = 0.0f;
553 pContext->Listener.Forward[2] = -1.0f;
554 pContext->Listener.Up[0] = 0.0f;
555 pContext->Listener.Up[1] = 1.0f;
556 pContext->Listener.Up[2] = 0.0f;
558 //Validate pContext
559 pContext->LastError = AL_NO_ERROR;
560 pContext->InUse = AL_FALSE;
562 //Set globals
563 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
564 pContext->SourceDistanceModel = AL_FALSE;
565 pContext->DopplerFactor = 1.0f;
566 pContext->DopplerVelocity = 1.0f;
567 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
569 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";
571 aluInitPanning(pContext);
576 ExitContext
578 Clean up Context, destroy any remaining Sources
580 static ALCvoid ExitContext(ALCcontext *pContext)
582 //Invalidate context
583 pContext->LastError = AL_NO_ERROR;
584 pContext->InUse = AL_FALSE;
587 ///////////////////////////////////////////////////////
590 ///////////////////////////////////////////////////////
591 // ALC Functions calls
594 // This should probably move to another c file but for now ...
595 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
597 ALCboolean DeviceFound = ALC_FALSE;
598 ALCdevice *pDevice = NULL;
599 ALCint i;
601 if(SampleSize <= 0)
603 alcSetError(ALC_INVALID_VALUE);
604 return NULL;
607 if(deviceName && !deviceName[0])
608 deviceName = NULL;
610 pDevice = malloc(sizeof(ALCdevice));
611 if (pDevice)
613 //Initialise device structure
614 memset(pDevice, 0, sizeof(ALCdevice));
616 //Validate device
617 pDevice->Connected = ALC_TRUE;
618 pDevice->IsCaptureDevice = AL_TRUE;
620 pDevice->szDeviceName = NULL;
622 pDevice->Frequency = frequency;
623 pDevice->Format = format;
624 pDevice->UpdateSize = SampleSize;
625 pDevice->NumUpdates = 1;
627 SuspendContext(NULL);
628 for(i = 0;BackendList[i].Init;i++)
630 pDevice->Funcs = &BackendList[i].Funcs;
631 if(ALCdevice_OpenCapture(pDevice, deviceName))
633 pDevice->next = g_pDeviceList;
634 g_pDeviceList = pDevice;
635 g_ulDeviceCount++;
637 DeviceFound = ALC_TRUE;
638 break;
641 ProcessContext(NULL);
643 if(!DeviceFound)
645 alcSetError(ALC_INVALID_VALUE);
646 free(pDevice);
647 pDevice = NULL;
650 else
651 alcSetError(ALC_OUT_OF_MEMORY);
653 return pDevice;
656 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
658 ALCboolean bReturn = ALC_FALSE;
659 ALCdevice **list;
661 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
663 SuspendContext(NULL);
665 list = &g_pDeviceList;
666 while(*list != pDevice)
667 list = &(*list)->next;
669 *list = (*list)->next;
670 g_ulDeviceCount--;
672 ProcessContext(NULL);
674 ALCdevice_CloseCapture(pDevice);
676 free(pDevice->szDeviceName);
677 pDevice->szDeviceName = NULL;
679 free(pDevice);
681 bReturn = ALC_TRUE;
683 else
684 alcSetError(ALC_INVALID_DEVICE);
686 return bReturn;
689 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
691 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
692 ALCdevice_StartCapture(pDevice);
693 else
694 alcSetError(ALC_INVALID_DEVICE);
697 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
699 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
700 ALCdevice_StopCapture(pDevice);
701 else
702 alcSetError(ALC_INVALID_DEVICE);
705 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
707 if(IsDevice(pDevice) && pDevice->IsCaptureDevice)
708 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
709 else
710 alcSetError(ALC_INVALID_DEVICE);
714 alcGetError
716 Return last ALC generated error code
718 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
720 ALCenum errorCode;
722 (void)device;
724 errorCode = g_eLastContextError;
725 g_eLastContextError = ALC_NO_ERROR;
726 return errorCode;
731 alcSuspendContext
733 Not functional
735 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
737 // Not a lot happens here !
738 (void)pContext;
743 alcProcessContext
745 Not functional
747 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
749 // Not a lot happens here !
750 (void)pContext;
755 alcGetString
757 Returns information about the Device, and error strings
759 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
761 const ALCchar *value = NULL;
763 switch (param)
765 case ALC_NO_ERROR:
766 value = alcNoError;
767 break;
769 case ALC_INVALID_ENUM:
770 value = alcErrInvalidEnum;
771 break;
773 case ALC_INVALID_VALUE:
774 value = alcErrInvalidValue;
775 break;
777 case ALC_INVALID_DEVICE:
778 value = alcErrInvalidDevice;
779 break;
781 case ALC_INVALID_CONTEXT:
782 value = alcErrInvalidContext;
783 break;
785 case ALC_OUT_OF_MEMORY:
786 value = alcErrOutOfMemory;
787 break;
789 case ALC_DEVICE_SPECIFIER:
790 if(IsDevice(pDevice))
791 value = pDevice->szDeviceName;
792 else
794 ProbeDeviceList();
795 value = alcDeviceList;
797 break;
799 case ALC_ALL_DEVICES_SPECIFIER:
800 ProbeAllDeviceList();
801 value = alcAllDeviceList;
802 break;
804 case ALC_CAPTURE_DEVICE_SPECIFIER:
805 if(IsDevice(pDevice))
806 value = pDevice->szDeviceName;
807 else
809 ProbeCaptureDeviceList();
810 value = alcCaptureDeviceList;
812 break;
814 /* Default devices are always first in the list */
815 case ALC_DEFAULT_DEVICE_SPECIFIER:
816 free(alcDefaultDeviceSpecifier);
817 alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : "");
818 if(!alcDefaultDeviceSpecifier)
819 alcSetError(ALC_OUT_OF_MEMORY);
820 value = alcDefaultDeviceSpecifier;
821 break;
823 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
824 free(alcDefaultAllDeviceSpecifier);
825 alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ?
826 alcAllDeviceList : "");
827 if(!alcDefaultAllDeviceSpecifier)
828 alcSetError(ALC_OUT_OF_MEMORY);
829 value = alcDefaultAllDeviceSpecifier;
830 break;
832 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
833 free(alcCaptureDefaultDeviceSpecifier);
834 alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ?
835 alcCaptureDeviceList : "");
836 if(!alcCaptureDefaultDeviceSpecifier)
837 alcSetError(ALC_OUT_OF_MEMORY);
838 value = alcCaptureDefaultDeviceSpecifier;
839 break;
841 case ALC_EXTENSIONS:
842 value = alcExtensionList;
843 break;
845 default:
846 alcSetError(ALC_INVALID_ENUM);
847 break;
850 return value;
855 alcGetIntegerv
857 Returns information about the Device and the version of Open AL
859 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
861 if(IsDevice(device) && device->IsCaptureDevice)
863 SuspendContext(NULL);
865 // Capture device
866 switch (param)
868 case ALC_CAPTURE_SAMPLES:
869 if ((size) && (data))
870 *data = ALCdevice_AvailableSamples(device);
871 else
872 alcSetError(ALC_INVALID_VALUE);
873 break;
875 case ALC_CONNECTED:
876 if(size <= 0)
877 alcSetError(ALC_INVALID_VALUE);
878 else
879 *data = device->Connected;
880 break;
882 default:
883 alcSetError(ALC_INVALID_ENUM);
884 break;
887 ProcessContext(NULL);
889 else
891 if(data)
893 // Playback Device
894 switch (param)
896 case ALC_MAJOR_VERSION:
897 if(size <= 0)
898 alcSetError(ALC_INVALID_VALUE);
899 else
900 *data = alcMajorVersion;
901 break;
903 case ALC_MINOR_VERSION:
904 if(size <= 0)
905 alcSetError(ALC_INVALID_VALUE);
906 else
907 *data = alcMinorVersion;
908 break;
910 case ALC_EFX_MAJOR_VERSION:
911 if(size <= 0)
912 alcSetError(ALC_INVALID_VALUE);
913 else
914 *data = alcEFXMajorVersion;
915 break;
917 case ALC_EFX_MINOR_VERSION:
918 if(size <= 0)
919 alcSetError(ALC_INVALID_VALUE);
920 else
921 *data = alcEFXMinorVersion;
922 break;
924 case ALC_MAX_AUXILIARY_SENDS:
925 if(size <= 0)
926 alcSetError(ALC_INVALID_VALUE);
927 else
928 *data = (device?device->NumAuxSends:MAX_SENDS);
929 break;
931 case ALC_ATTRIBUTES_SIZE:
932 if(!IsDevice(device))
933 alcSetError(ALC_INVALID_DEVICE);
934 else if(size <= 0)
935 alcSetError(ALC_INVALID_VALUE);
936 else
937 *data = 13;
938 break;
940 case ALC_ALL_ATTRIBUTES:
941 if(!IsDevice(device))
942 alcSetError(ALC_INVALID_DEVICE);
943 else if (size < 13)
944 alcSetError(ALC_INVALID_VALUE);
945 else
947 int i = 0;
949 SuspendContext(NULL);
950 data[i++] = ALC_FREQUENCY;
951 data[i++] = device->Frequency;
953 data[i++] = ALC_REFRESH;
954 data[i++] = device->Frequency / device->UpdateSize;
956 data[i++] = ALC_SYNC;
957 data[i++] = ALC_FALSE;
959 data[i++] = ALC_MONO_SOURCES;
960 data[i++] = device->lNumMonoSources;
962 data[i++] = ALC_STEREO_SOURCES;
963 data[i++] = device->lNumStereoSources;
965 data[i++] = ALC_MAX_AUXILIARY_SENDS;
966 data[i++] = device->NumAuxSends;
968 data[i++] = 0;
969 ProcessContext(NULL);
971 break;
973 case ALC_FREQUENCY:
974 if(!IsDevice(device))
975 alcSetError(ALC_INVALID_DEVICE);
976 else if(size <= 0)
977 alcSetError(ALC_INVALID_VALUE);
978 else
979 *data = device->Frequency;
980 break;
982 case ALC_REFRESH:
983 if(!IsDevice(device))
984 alcSetError(ALC_INVALID_DEVICE);
985 else if(size <= 0)
986 alcSetError(ALC_INVALID_VALUE);
987 else
988 *data = device->Frequency / device->UpdateSize;
989 break;
991 case ALC_SYNC:
992 if(!IsDevice(device))
993 alcSetError(ALC_INVALID_DEVICE);
994 else if(size <= 0)
995 alcSetError(ALC_INVALID_VALUE);
996 else
997 *data = ALC_FALSE;
998 break;
1000 case ALC_MONO_SOURCES:
1001 if(!IsDevice(device))
1002 alcSetError(ALC_INVALID_DEVICE);
1003 else if(size <= 0)
1004 alcSetError(ALC_INVALID_VALUE);
1005 else
1006 *data = device->lNumMonoSources;
1007 break;
1009 case ALC_STEREO_SOURCES:
1010 if(!IsDevice(device))
1011 alcSetError(ALC_INVALID_DEVICE);
1012 else if(size <= 0)
1013 alcSetError(ALC_INVALID_VALUE);
1014 else
1015 *data = device->lNumStereoSources;
1016 break;
1018 case ALC_CONNECTED:
1019 if(!IsDevice(device))
1020 alcSetError(ALC_INVALID_DEVICE);
1021 else if(size <= 0)
1022 alcSetError(ALC_INVALID_VALUE);
1023 else
1024 *data = device->Connected;
1025 break;
1027 default:
1028 alcSetError(ALC_INVALID_ENUM);
1029 break;
1032 else if(size)
1033 alcSetError(ALC_INVALID_VALUE);
1036 return;
1041 alcIsExtensionPresent
1043 Determines if there is support for a particular extension
1045 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
1047 ALCboolean bResult = ALC_FALSE;
1049 (void)device;
1051 if (extName)
1053 const char *ptr;
1054 size_t len;
1056 len = strlen(extName);
1057 ptr = alcExtensionList;
1058 while(ptr && *ptr)
1060 if(strncasecmp(ptr, extName, len) == 0 &&
1061 (ptr[len] == '\0' || isspace(ptr[len])))
1063 bResult = ALC_TRUE;
1064 break;
1066 if((ptr=strchr(ptr, ' ')) != NULL)
1068 do {
1069 ++ptr;
1070 } while(isspace(*ptr));
1074 else
1075 alcSetError(ALC_INVALID_VALUE);
1077 return bResult;
1082 alcGetProcAddress
1084 Retrieves the function address for a particular extension function
1086 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
1088 ALCvoid *pFunction = NULL;
1089 ALsizei i = 0;
1091 (void)device;
1093 if (funcName)
1095 while(alcFunctions[i].funcName &&
1096 strcmp(alcFunctions[i].funcName,funcName) != 0)
1097 i++;
1098 pFunction = alcFunctions[i].address;
1100 else
1101 alcSetError(ALC_INVALID_VALUE);
1103 return pFunction;
1108 alcGetEnumValue
1110 Get the value for a particular ALC Enumerated Value
1112 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1114 ALsizei i = 0;
1115 ALCenum val;
1117 (void)device;
1119 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1120 i++;
1121 val = enumeration[i].value;
1123 if(!enumeration[i].enumName)
1124 alcSetError(ALC_INVALID_VALUE);
1126 return val;
1131 alcCreateContext
1133 Create and attach a Context to a particular Device.
1135 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1137 ALuint attrIdx, reqStereoSources;
1138 ALCcontext *ALContext;
1139 void *temp;
1140 ALuint i;
1142 SuspendContext(NULL);
1144 if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected)
1146 alcSetError(ALC_INVALID_DEVICE);
1147 ProcessContext(NULL);
1148 return NULL;
1151 // Reset Context Last Error code
1152 g_eLastContextError = ALC_NO_ERROR;
1154 // If a context is already running on the device, stop playback so the
1155 // device attributes can be updated
1156 if(device->NumContexts > 0)
1158 ProcessContext(NULL);
1159 ALCdevice_StopPlayback(device);
1160 SuspendContext(NULL);
1163 // Check for attributes
1164 if(attrList)
1166 ALCint level = device->Bs2bLevel;
1167 ALCuint freq = device->Frequency;
1168 ALCint numMono = device->lNumMonoSources;
1169 ALCint numStereo = device->lNumStereoSources;
1170 ALCuint numSends = device->NumAuxSends;
1172 attrIdx = 0;
1173 while(attrList[attrIdx])
1175 if(attrList[attrIdx] == ALC_FREQUENCY)
1177 freq = attrList[attrIdx + 1];
1178 if(freq == 0)
1179 freq = device->Frequency;
1182 if(attrList[attrIdx] == ALC_STEREO_SOURCES)
1184 reqStereoSources = attrList[attrIdx + 1];
1185 if(reqStereoSources > device->MaxNoOfSources)
1186 reqStereoSources = device->MaxNoOfSources;
1188 numStereo = reqStereoSources;
1189 numMono = device->MaxNoOfSources - numStereo;
1192 if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS)
1194 numSends = attrList[attrIdx + 1];
1195 if(numSends > MAX_SENDS)
1196 numSends = MAX_SENDS;
1199 attrIdx += 2;
1202 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", level);
1203 device->Frequency = GetConfigValueInt(NULL, "frequency", freq);
1204 device->lNumMonoSources = numMono;
1205 device->lNumStereoSources = numStereo;
1206 device->NumAuxSends = GetConfigValueInt(NULL, "sends", numSends);
1209 if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
1211 alcSetError(ALC_INVALID_DEVICE);
1212 aluHandleDisconnect(device);
1213 ProcessContext(NULL);
1214 return NULL;
1217 for(i = 0;i < device->NumContexts;i++)
1219 ALCcontext *context = device->Contexts[i];
1220 ALeffectslot *slot;
1221 ALsource *source;
1223 SuspendContext(context);
1224 for(slot = context->AuxiliaryEffectSlot;slot != NULL;slot = slot->next)
1226 if(!slot->EffectState)
1227 continue;
1229 if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
1231 alcSetError(ALC_INVALID_DEVICE);
1232 aluHandleDisconnect(device);
1233 ProcessContext(context);
1234 ProcessContext(NULL);
1235 ALCdevice_StopPlayback(device);
1236 return NULL;
1238 ALEffect_Update(slot->EffectState, context, &slot->effect);
1241 for(source = context->Source;source != NULL;source = source->next)
1243 ALuint s = device->NumAuxSends;
1244 while(s < MAX_SENDS)
1246 if(source->Send[s].Slot)
1247 source->Send[s].Slot->refcount--;
1248 source->Send[s].Slot = NULL;
1249 source->Send[s].WetFilter.type = 0;
1250 source->Send[s].WetFilter.filter = 0;
1251 s++;
1253 source->NeedsUpdate = AL_TRUE;
1255 ProcessContext(context);
1258 if(device->Bs2bLevel > 0 && device->Bs2bLevel <= 6)
1260 if(!device->Bs2b)
1262 device->Bs2b = calloc(1, sizeof(*device->Bs2b));
1263 bs2b_clear(device->Bs2b);
1265 bs2b_set_srate(device->Bs2b, device->Frequency);
1266 bs2b_set_level(device->Bs2b, device->Bs2bLevel);
1268 else
1270 free(device->Bs2b);
1271 device->Bs2b = NULL;
1274 temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts));
1275 if(!temp)
1277 alcSetError(ALC_OUT_OF_MEMORY);
1278 ProcessContext(NULL);
1279 return NULL;
1281 device->Contexts = temp;
1283 ALContext = calloc(1, sizeof(ALCcontext));
1284 if(!ALContext)
1286 alcSetError(ALC_OUT_OF_MEMORY);
1287 ProcessContext(NULL);
1288 return NULL;
1291 device->Contexts[device->NumContexts++] = ALContext;
1292 ALContext->Device = device;
1294 InitContext(ALContext);
1296 ALContext->next = g_pContextList;
1297 g_pContextList = ALContext;
1298 g_ulContextCount++;
1300 ProcessContext(NULL);
1302 return ALContext;
1307 alcDestroyContext
1309 Remove a Context
1311 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1313 ALCcontext **list;
1314 ALuint i;
1316 if (IsContext(context))
1318 ALCdevice *Device = context->Device;
1320 if(Device->NumContexts == 1)
1321 ALCdevice_StopPlayback(Device);
1323 SuspendContext(NULL);
1325 for(i = 0;i < Device->NumContexts-1;i++)
1327 if(Device->Contexts[i] == context)
1329 memmove(&Device->Contexts[i], &Device->Contexts[i+1],
1330 (Device->NumContexts-i-1) * sizeof(*Device->Contexts));
1331 break;
1334 Device->NumContexts--;
1336 // Lock context
1337 SuspendContext(context);
1339 if(context->SourceCount > 0)
1341 #ifdef _DEBUG
1342 AL_PRINT("alcDestroyContext(): deleting %d Source(s)\n", context->SourceCount);
1343 #endif
1344 ReleaseALSources(context);
1346 if(context->AuxiliaryEffectSlotCount > 0)
1348 #ifdef _DEBUG
1349 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->AuxiliaryEffectSlotCount);
1350 #endif
1351 ReleaseALAuxiliaryEffectSlots(context);
1354 list = &g_pContextList;
1355 while(*list != context)
1356 list = &(*list)->next;
1358 *list = (*list)->next;
1359 g_ulContextCount--;
1361 // Unlock context
1362 ProcessContext(context);
1363 ProcessContext(NULL);
1365 ExitContext(context);
1367 // Free memory (MUST do this after ProcessContext)
1368 memset(context, 0, sizeof(ALCcontext));
1369 free(context);
1371 else
1372 alcSetError(ALC_INVALID_CONTEXT);
1377 alcGetCurrentContext
1379 Returns the currently active Context
1381 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1383 ALCcontext *pContext;
1385 if((pContext=GetContextSuspended()) != NULL)
1386 ProcessContext(pContext);
1388 return pContext;
1392 alcGetThreadContext
1394 Returns the currently active thread-local Context
1396 ALCcontext * ALCAPIENTRY alcGetThreadContext(void)
1398 ALCcontext *pContext = NULL;
1400 SuspendContext(NULL);
1402 pContext = tls_get(LocalContext);
1403 if(pContext && !IsContext(pContext))
1405 tls_set(LocalContext, NULL);
1406 pContext = NULL;
1409 ProcessContext(NULL);
1411 return pContext;
1416 alcGetContextsDevice
1418 Returns the Device that a particular Context is attached to
1420 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1422 ALCdevice *pDevice = NULL;
1424 SuspendContext(NULL);
1425 if (IsContext(pContext))
1426 pDevice = pContext->Device;
1427 else
1428 alcSetError(ALC_INVALID_CONTEXT);
1429 ProcessContext(NULL);
1431 return pDevice;
1436 alcMakeContextCurrent
1438 Makes the given Context the active Context
1440 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1442 ALCcontext *ALContext;
1443 ALboolean bReturn = AL_TRUE;
1445 SuspendContext(NULL);
1447 // context must be a valid Context or NULL
1448 if(context == NULL || IsContext(context))
1450 if((ALContext=GetContextSuspended()) != NULL)
1452 ALContext->InUse=AL_FALSE;
1453 ProcessContext(ALContext);
1456 if((ALContext=context) != NULL && ALContext->Device)
1458 SuspendContext(ALContext);
1459 ALContext->InUse=AL_TRUE;
1460 ProcessContext(ALContext);
1463 tls_set(LocalContext, NULL);
1465 else
1467 alcSetError(ALC_INVALID_CONTEXT);
1468 bReturn = AL_FALSE;
1471 ProcessContext(NULL);
1473 return bReturn;
1477 alcMakeCurrent
1479 Makes the given Context the active Context for the current thread
1481 ALCboolean ALCAPIENTRY alcMakeCurrent(ALCcontext *context)
1483 ALboolean bReturn = AL_TRUE;
1485 SuspendContext(NULL);
1487 // context must be a valid Context or NULL
1488 if(context == NULL || IsContext(context))
1489 tls_set(LocalContext, context);
1490 else
1492 alcSetError(ALC_INVALID_CONTEXT);
1493 bReturn = AL_FALSE;
1496 ProcessContext(NULL);
1498 return bReturn;
1502 static ALenum GetFormatFromString(const char *str)
1504 if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32;
1505 if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32;
1506 if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32;
1507 if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32;
1508 if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32;
1509 if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32;
1511 if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16;
1512 if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16;
1513 if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16;
1514 if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16;
1515 if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16;
1516 if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16;
1518 if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8;
1519 if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8;
1520 if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8;
1521 if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8;
1522 if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8;
1523 if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8;
1525 AL_PRINT("Unknown format: \"%s\"\n", str);
1526 return AL_FORMAT_STEREO16;
1530 alcOpenDevice
1532 Open the Device specified.
1534 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1536 ALboolean bDeviceFound = AL_FALSE;
1537 ALCdevice *device;
1538 ALint i;
1540 if(deviceName && !deviceName[0])
1541 deviceName = NULL;
1543 device = malloc(sizeof(ALCdevice));
1544 if (device)
1546 const char *fmt;
1548 //Initialise device structure
1549 memset(device, 0, sizeof(ALCdevice));
1551 //Validate device
1552 device->Connected = ALC_TRUE;
1553 device->IsCaptureDevice = AL_FALSE;
1555 device->Bs2b = NULL;
1556 device->szDeviceName = NULL;
1558 device->Contexts = NULL;
1559 device->NumContexts = 0;
1561 //Set output format
1562 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1563 if(device->Frequency == 0)
1564 device->Frequency = SWMIXER_OUTPUT_RATE;
1566 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1567 device->Format = GetFormatFromString(fmt);
1569 device->NumUpdates = GetConfigValueInt(NULL, "periods", 4);
1570 if(device->NumUpdates < 2)
1571 device->NumUpdates = 4;
1573 i = GetConfigValueInt(NULL, "refresh", 4096);
1574 if(i <= 0) i = 4096;
1576 device->UpdateSize = GetConfigValueInt(NULL, "period_size", i/device->NumUpdates);
1577 if(device->UpdateSize <= 0)
1578 device->UpdateSize = i/device->NumUpdates;
1580 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1581 if((ALint)device->MaxNoOfSources <= 0)
1582 device->MaxNoOfSources = 256;
1584 device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4);
1585 if((ALint)device->AuxiliaryEffectSlotMax <= 0)
1586 device->AuxiliaryEffectSlotMax = 4;
1588 device->lNumStereoSources = 1;
1589 device->lNumMonoSources = device->MaxNoOfSources - device->lNumStereoSources;
1591 device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS);
1592 if(device->NumAuxSends > MAX_SENDS)
1593 device->NumAuxSends = MAX_SENDS;
1595 device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0);
1597 // Find a playback device to open
1598 SuspendContext(NULL);
1599 for(i = 0;BackendList[i].Init;i++)
1601 device->Funcs = &BackendList[i].Funcs;
1602 if(ALCdevice_OpenPlayback(device, deviceName))
1604 device->next = g_pDeviceList;
1605 g_pDeviceList = device;
1606 g_ulDeviceCount++;
1608 bDeviceFound = AL_TRUE;
1609 break;
1612 ProcessContext(NULL);
1614 if (!bDeviceFound)
1616 // No suitable output device found
1617 alcSetError(ALC_INVALID_VALUE);
1618 free(device);
1619 device = NULL;
1622 else
1623 alcSetError(ALC_OUT_OF_MEMORY);
1625 return device;
1630 alcCloseDevice
1632 Close the specified Device
1634 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1636 ALCboolean bReturn = ALC_FALSE;
1637 ALCdevice **list;
1639 if(IsDevice(pDevice) && !pDevice->IsCaptureDevice)
1641 SuspendContext(NULL);
1643 list = &g_pDeviceList;
1644 while(*list != pDevice)
1645 list = &(*list)->next;
1647 *list = (*list)->next;
1648 g_ulDeviceCount--;
1650 ProcessContext(NULL);
1652 if(pDevice->NumContexts > 0)
1654 #ifdef _DEBUG
1655 AL_PRINT("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts);
1656 #endif
1657 while(pDevice->NumContexts > 0)
1658 alcDestroyContext(pDevice->Contexts[0]);
1660 ALCdevice_ClosePlayback(pDevice);
1662 if(pDevice->BufferCount > 0)
1664 #ifdef _DEBUG
1665 AL_PRINT("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferCount);
1666 #endif
1667 ReleaseALBuffers(pDevice);
1669 if(pDevice->EffectCount > 0)
1671 #ifdef _DEBUG
1672 AL_PRINT("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectCount);
1673 #endif
1674 ReleaseALEffects(pDevice);
1676 if(pDevice->FilterCount > 0)
1678 #ifdef _DEBUG
1679 AL_PRINT("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterCount);
1680 #endif
1681 ReleaseALFilters(pDevice);
1683 if(pDevice->DatabufferCount > 0)
1685 #ifdef _DEBUG
1686 AL_PRINT("alcCloseDevice(): deleting %d Databuffer(s)\n", pDevice->DatabufferCount);
1687 #endif
1688 ReleaseALDatabuffers(pDevice);
1691 free(pDevice->Bs2b);
1692 pDevice->Bs2b = NULL;
1694 free(pDevice->szDeviceName);
1695 pDevice->szDeviceName = NULL;
1697 free(pDevice->Contexts);
1698 pDevice->Contexts = NULL;
1700 //Release device structure
1701 memset(pDevice, 0, sizeof(ALCdevice));
1702 free(pDevice);
1704 bReturn = ALC_TRUE;
1706 else
1707 alcSetError(ALC_INVALID_DEVICE);
1709 return bReturn;
1713 ALCvoid ReleaseALC(ALCvoid)
1715 free(alcDeviceList); alcDeviceList = NULL;
1716 alcDeviceListSize = 0;
1717 free(alcAllDeviceList); alcAllDeviceList = NULL;
1718 alcAllDeviceListSize = 0;
1719 free(alcCaptureDeviceList); alcCaptureDeviceList = NULL;
1720 alcCaptureDeviceListSize = 0;
1722 free(alcDefaultDeviceSpecifier);
1723 alcDefaultDeviceSpecifier = NULL;
1724 free(alcDefaultAllDeviceSpecifier);
1725 alcDefaultAllDeviceSpecifier = NULL;
1726 free(alcCaptureDefaultDeviceSpecifier);
1727 alcCaptureDefaultDeviceSpecifier = NULL;
1729 #ifdef _DEBUG
1730 if(g_ulDeviceCount > 0)
1731 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1732 #endif
1734 while(g_pDeviceList)
1736 if(g_pDeviceList->IsCaptureDevice)
1737 alcCaptureCloseDevice(g_pDeviceList);
1738 else
1739 alcCloseDevice(g_pDeviceList);
1743 ///////////////////////////////////////////////////////