Move (de)initialization into ALc.c and remove unneeded file
[openal-soft/openal-hmr.git] / Alc / ALc.c
blob22334ea657f43100972ad554298c4195298e3cf6
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 #define _CRT_SECURE_NO_DEPRECATE // get rid of sprintf security warnings on VS2005
23 #include "config.h"
25 #include <math.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <memory.h>
29 #include <ctype.h>
30 #include "alMain.h"
31 #include "alSource.h"
32 #include "AL/al.h"
33 #include "AL/alc.h"
34 #include "alThunk.h"
35 #include "alSource.h"
36 #include "alBuffer.h"
37 #include "alExtension.h"
38 #include "alAuxEffectSlot.h"
39 #include "bs2b.h"
41 ///////////////////////////////////////////////////////
42 // DEBUG INFORMATION
44 char _alDebug[256];
46 ///////////////////////////////////////////////////////
49 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
50 static struct {
51 const char *name;
52 void (*Init)(BackendFuncs*);
53 BackendFuncs Funcs;
54 } BackendList[] = {
55 #ifdef HAVE_ALSA
56 { "alsa", alc_alsa_init, EmptyFuncs },
57 #endif
58 #ifdef HAVE_OSS
59 { "oss", alc_oss_init, EmptyFuncs },
60 #endif
61 #ifdef HAVE_DSOUND
62 { "dsound", alcDSoundInit, EmptyFuncs },
63 #endif
64 #ifdef HAVE_WINMM
65 { "winmm", alcWinMMInit, EmptyFuncs },
66 #endif
68 { "wave", alc_wave_init, EmptyFuncs },
70 { NULL, NULL, EmptyFuncs }
72 #undef EmptyFuncs
74 ///////////////////////////////////////////////////////
76 #define ALC_EFX_MAJOR_VERSION 0x20001
77 #define ALC_EFX_MINOR_VERSION 0x20002
78 #define ALC_MAX_AUXILIARY_SENDS 0x20003
80 ///////////////////////////////////////////////////////
81 // STRING and EXTENSIONS
83 typedef struct ALCfunction_struct
85 ALCchar *funcName;
86 ALvoid *address;
87 } ALCfunction;
89 static ALCfunction alcFunctions[] = {
90 { "alcCreateContext", (ALvoid *) alcCreateContext },
91 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
92 { "alcProcessContext", (ALvoid *) alcProcessContext },
93 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
94 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
95 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
96 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
97 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
98 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
99 { "alcGetError", (ALvoid *) alcGetError },
100 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
101 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
102 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
103 { "alcGetString", (ALvoid *) alcGetString },
104 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
105 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
106 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
107 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
108 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
109 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
110 { NULL, (ALvoid *) NULL }
113 static ALenums enumeration[]={
114 // Types
115 { (ALchar *)"ALC_INVALID", ALC_INVALID },
116 { (ALchar *)"ALC_FALSE", ALC_FALSE },
117 { (ALchar *)"ALC_TRUE", ALC_TRUE },
119 // ALC Properties
120 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
121 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
122 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
123 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
124 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
125 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
126 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
127 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
128 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
129 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
130 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
131 { (ALchar *)"ALC_SYNC", ALC_SYNC },
132 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
133 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
134 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
135 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
136 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
138 // EFX Properties
139 { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
140 { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
141 { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
143 // ALC Error Message
144 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
145 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
146 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
147 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
148 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
149 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
150 { (ALchar *)NULL, (ALenum)0 }
152 // Error strings
153 static const ALCchar alcNoError[] = "No Error";
154 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
155 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
156 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
157 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
158 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
160 // Context strings
161 static ALCchar alcDeviceList[2048];
162 static ALCchar alcAllDeviceList[2048];
163 static ALCchar alcCaptureDeviceList[2048];
164 // Default is always the first in the list
165 static ALCchar *alcDefaultDeviceSpecifier = alcDeviceList;
166 static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
167 static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
170 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_EFX";
171 static ALCint alcMajorVersion = 1;
172 static ALCint alcMinorVersion = 1;
174 static ALCint alcEFXMajorVersion = 1;
175 static ALCint alcEFXMinorVersion = 0;
177 ///////////////////////////////////////////////////////
180 ///////////////////////////////////////////////////////
181 // Global Variables
183 static ALCdevice *g_pDeviceList = NULL;
184 static ALCuint g_ulDeviceCount = 0;
186 static CRITICAL_SECTION g_csMutex;
188 // Context List
189 static ALCcontext *g_pContextList = NULL;
190 static ALCuint g_ulContextCount = 0;
192 // Context Error
193 static ALCenum g_eLastContextError = ALC_NO_ERROR;
195 ///////////////////////////////////////////////////////
198 ///////////////////////////////////////////////////////
199 // ALC Related helper functions
200 #ifdef _WIN32
201 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
203 (void)lpReserved;
205 // Perform actions based on the reason for calling.
206 switch(ul_reason_for_call)
208 case DLL_PROCESS_ATTACH:
209 DisableThreadLibraryCalls(hModule);
210 break;
212 case DLL_PROCESS_DETACH:
213 ReleaseALC();
214 ReleaseALBuffers();
215 ReleaseALEffects();
216 ReleaseALFilters();
217 FreeALConfig();
218 ALTHUNK_EXIT();
219 DeleteCriticalSection(&g_csMutex);
220 break;
222 return TRUE;
224 #else
225 #ifdef HAVE_GCC_DESTRUCTOR
226 static void my_deinit() __attribute__((destructor));
227 static void my_deinit()
229 static ALenum once = AL_FALSE;
230 if(once) return;
231 once = AL_TRUE;
233 ReleaseALC();
234 ReleaseALBuffers();
235 ReleaseALEffects();
236 ReleaseALFilters();
237 FreeALConfig();
238 ALTHUNK_EXIT();
239 DeleteCriticalSection(&g_csMutex);
241 #endif
242 #endif
244 static void InitAL(void)
246 static int done = 0;
247 if(!done)
249 int i;
250 const char *devs, *str;
252 done = 1;
254 InitializeCriticalSection(&g_csMutex);
255 ALTHUNK_INIT();
256 ReadALConfig();
258 devs = GetConfigValue(NULL, "drivers", "");
259 if(devs[0])
261 int n;
262 size_t len;
263 const char *next = devs;
265 i = 0;
267 do {
268 devs = next;
269 next = strchr(devs, ',');
271 if(!devs[0] || devs[0] == ',')
272 continue;
274 len = (next ? ((size_t)(next-devs)) : strlen(devs));
275 for(n = i;BackendList[n].Init;n++)
277 if(len == strlen(BackendList[n].name) &&
278 strncmp(BackendList[n].name, devs, len) == 0)
280 const char *name = BackendList[i].name;
281 void (*Init)(BackendFuncs*) = BackendList[i].Init;
283 BackendList[i].name = BackendList[n].name;
284 BackendList[i].Init = BackendList[n].Init;
286 BackendList[n].name = name;
287 BackendList[n].Init = Init;
289 i++;
292 } while(next++);
294 BackendList[i].name = NULL;
295 BackendList[i].Init = NULL;
298 for(i = 0;BackendList[i].Init;i++)
299 BackendList[i].Init(&BackendList[i].Funcs);
301 str = GetConfigValue(NULL, "stereodup", "false");
302 DuplicateStereo = (strcasecmp(str, "true") == 0 ||
303 strcasecmp(str, "yes") == 0 ||
304 strcasecmp(str, "on") == 0 ||
305 atoi(str) != 0);
309 ALCchar *AppendDeviceList(char *name)
311 static size_t pos;
312 ALCchar *ret = alcDeviceList+pos;
313 if(pos >= sizeof(alcDeviceList))
315 AL_PRINT("Not enough room to add %s!\n", name);
316 return alcDeviceList + sizeof(alcDeviceList) - 1;
318 pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos-1, "%s", name) + 1;
319 return ret;
322 ALCchar *AppendAllDeviceList(char *name)
324 static size_t pos;
325 ALCchar *ret = alcAllDeviceList+pos;
326 if(pos >= sizeof(alcAllDeviceList))
328 AL_PRINT("Not enough room to add %s!\n", name);
329 return alcAllDeviceList + sizeof(alcAllDeviceList) - 1;
331 pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos-1, "%s", name) + 1;
332 return ret;
335 ALCchar *AppendCaptureDeviceList(char *name)
337 static size_t pos;
338 ALCchar *ret = alcCaptureDeviceList+pos;
339 if(pos >= sizeof(alcCaptureDeviceList))
341 AL_PRINT("Not enough room to add %s!\n", name);
342 return alcCaptureDeviceList + sizeof(alcCaptureDeviceList) - 1;
344 pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos-1, "%s", name) + 1;
345 return ret;
349 IsContext
351 Check pContext is a valid Context pointer
353 static ALCboolean IsContext(ALCcontext *pContext)
355 ALCcontext *pTempContext;
357 pTempContext = g_pContextList;
358 while (pTempContext && pTempContext != pContext)
359 pTempContext = pTempContext->next;
361 return (pTempContext ? ALC_TRUE : ALC_FALSE);
366 SetALCError
368 Store latest ALC Error
370 ALCvoid SetALCError(ALenum errorCode)
372 g_eLastContextError = errorCode;
377 SuspendContext
379 Thread-safe entry
381 ALCvoid SuspendContext(ALCcontext *pContext)
383 (void)pContext;
384 EnterCriticalSection(&g_csMutex);
389 ProcessContext
391 Thread-safe exit
393 ALCvoid ProcessContext(ALCcontext *pContext)
395 (void)pContext;
396 LeaveCriticalSection(&g_csMutex);
401 InitContext
403 Initialize Context variables
405 static ALvoid InitContext(ALCcontext *pContext)
407 int level;
409 //Initialise listener
410 pContext->Listener.Gain = 1.0f;
411 pContext->Listener.MetersPerUnit = 1.0f;
412 pContext->Listener.Position[0] = 0.0f;
413 pContext->Listener.Position[1] = 0.0f;
414 pContext->Listener.Position[2] = 0.0f;
415 pContext->Listener.Velocity[0] = 0.0f;
416 pContext->Listener.Velocity[1] = 0.0f;
417 pContext->Listener.Velocity[2] = 0.0f;
418 pContext->Listener.Forward[0] = 0.0f;
419 pContext->Listener.Forward[1] = 0.0f;
420 pContext->Listener.Forward[2] = -1.0f;
421 pContext->Listener.Up[0] = 0.0f;
422 pContext->Listener.Up[1] = 1.0f;
423 pContext->Listener.Up[2] = 0.0f;
425 //Validate pContext
426 pContext->LastError = AL_NO_ERROR;
427 pContext->InUse = AL_FALSE;
429 //Set output format
430 pContext->Frequency = pContext->Device->Frequency;
432 //Set globals
433 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
434 pContext->DopplerFactor = 1.0f;
435 pContext->DopplerVelocity = 1.0f;
436 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
438 pContext->lNumStereoSources = 1;
439 pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
441 strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_OFFSET AL_LOKI_quadriphonic");
443 level = GetConfigValueInt(NULL, "cf_level", 0);
444 if(level > 0 && level <= 6)
446 pContext->bs2b = calloc(1, sizeof(*pContext->bs2b));
447 bs2b_set_srate(pContext->bs2b, pContext->Frequency);
448 bs2b_set_level(pContext->bs2b, level);
454 ExitContext
456 Clean up Context, destroy any remaining Sources
458 static ALCvoid ExitContext(ALCcontext *pContext)
460 //Invalidate context
461 pContext->LastError = AL_NO_ERROR;
462 pContext->InUse = AL_FALSE;
464 free(pContext->bs2b);
465 pContext->bs2b = NULL;
468 ///////////////////////////////////////////////////////
471 ///////////////////////////////////////////////////////
472 // ALC Functions calls
475 // This should probably move to another c file but for now ...
476 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
478 ALCboolean DeviceFound = ALC_FALSE;
479 ALCdevice *pDevice = NULL;
480 ALCint i;
482 InitAL();
484 if(deviceName && !deviceName[0])
485 deviceName = NULL;
487 pDevice = malloc(sizeof(ALCdevice));
488 if (pDevice)
490 if (SampleSize > 0)
492 //Initialise device structure
493 memset(pDevice, 0, sizeof(ALCdevice));
495 //Validate device
496 pDevice->IsCaptureDevice = AL_TRUE;
498 pDevice->Frequency = frequency;
499 pDevice->Format = format;
501 for(i = 0;BackendList[i].Init;i++)
503 pDevice->Funcs = &BackendList[i].Funcs;
504 if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
506 SuspendContext(NULL);
507 pDevice->next = g_pDeviceList;
508 g_pDeviceList = pDevice;
509 g_ulDeviceCount++;
510 ProcessContext(NULL);
512 DeviceFound = ALC_TRUE;
513 break;
517 else
518 SetALCError(ALC_INVALID_VALUE);
520 if(!DeviceFound)
522 free(pDevice);
523 pDevice = NULL;
526 else
527 SetALCError(ALC_OUT_OF_MEMORY);
529 return pDevice;
532 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
534 ALCboolean bReturn = ALC_FALSE;
535 ALCdevice **list;
537 if ((pDevice)&&(pDevice->IsCaptureDevice))
539 SuspendContext(NULL);
541 list = &g_pDeviceList;
542 while(*list != pDevice)
543 list = &(*list)->next;
545 *list = (*list)->next;
546 g_ulDeviceCount--;
548 ProcessContext(NULL);
550 ALCdevice_CloseCapture(pDevice);
551 free(pDevice);
553 bReturn = ALC_TRUE;
555 else
556 SetALCError(ALC_INVALID_DEVICE);
558 return bReturn;
561 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
563 if ((pDevice)&&(pDevice->IsCaptureDevice))
564 ALCdevice_StartCapture(pDevice);
565 else
566 SetALCError(ALC_INVALID_DEVICE);
569 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
571 if ((pDevice)&&(pDevice->IsCaptureDevice))
572 ALCdevice_StopCapture(pDevice);
573 else
574 SetALCError(ALC_INVALID_DEVICE);
577 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
579 if ((pDevice) && (pDevice->IsCaptureDevice))
580 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
581 else
582 SetALCError(ALC_INVALID_DEVICE);
586 alcGetError
588 Return last ALC generated error code
590 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
592 ALCenum errorCode;
594 (void)device;
596 errorCode = g_eLastContextError;
597 g_eLastContextError = ALC_NO_ERROR;
598 return errorCode;
603 alcSuspendContext
605 Not functional
607 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
609 // Not a lot happens here !
610 (void)pContext;
615 alcProcessContext
617 Not functional
619 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
621 // Not a lot happens here !
622 (void)pContext;
627 alcGetString
629 Returns information about the Device, and error strings
631 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
633 const ALCchar *value = NULL;
635 InitAL();
637 switch (param)
639 case ALC_NO_ERROR:
640 value = alcNoError;
641 break;
643 case ALC_INVALID_ENUM:
644 value = alcErrInvalidEnum;
645 break;
647 case ALC_INVALID_VALUE:
648 value = alcErrInvalidValue;
649 break;
651 case ALC_INVALID_DEVICE:
652 value = alcErrInvalidDevice;
653 break;
655 case ALC_INVALID_CONTEXT:
656 value = alcErrInvalidContext;
657 break;
659 case ALC_OUT_OF_MEMORY:
660 value = alcErrOutOfMemory;
661 break;
663 case ALC_DEFAULT_DEVICE_SPECIFIER:
664 value = alcDefaultDeviceSpecifier;
665 break;
667 case ALC_DEVICE_SPECIFIER:
668 if (pDevice)
669 value = pDevice->szDeviceName;
670 else
671 value = alcDeviceList;
672 break;
674 case ALC_ALL_DEVICES_SPECIFIER:
675 value = alcAllDeviceList;
676 break;
678 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
679 value = alcDefaultAllDeviceSpecifier;
680 break;
682 case ALC_CAPTURE_DEVICE_SPECIFIER:
683 if (pDevice)
684 value = pDevice->szDeviceName;
685 else
686 value = alcCaptureDeviceList;
687 break;
689 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
690 value = alcCaptureDefaultDeviceSpecifier;
691 break;
693 case ALC_EXTENSIONS:
694 value = alcExtensionList;
695 break;
697 default:
698 SetALCError(ALC_INVALID_ENUM);
699 break;
702 return value;
707 alcGetIntegerv
709 Returns information about the Device and the version of Open AL
711 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
713 InitAL();
715 if ((device)&&(device->IsCaptureDevice))
717 SuspendContext(NULL);
719 // Capture device
720 switch (param)
722 case ALC_CAPTURE_SAMPLES:
723 if ((size) && (data))
724 *data = ALCdevice_AvailableSamples(device);
725 else
726 SetALCError(ALC_INVALID_VALUE);
727 break;
729 default:
730 SetALCError(ALC_INVALID_ENUM);
731 break;
734 ProcessContext(NULL);
736 else
738 if(data)
740 // Playback Device
741 switch (param)
743 case ALC_MAJOR_VERSION:
744 if(!size)
745 SetALCError(ALC_INVALID_VALUE);
746 else
747 *data = alcMajorVersion;
748 break;
750 case ALC_MINOR_VERSION:
751 if(!size)
752 SetALCError(ALC_INVALID_VALUE);
753 else
754 *data = alcMinorVersion;
755 break;
757 case ALC_EFX_MAJOR_VERSION:
758 if(!size)
759 SetALCError(ALC_INVALID_VALUE);
760 else
761 *data = alcEFXMajorVersion;
762 break;
764 case ALC_EFX_MINOR_VERSION:
765 if(!size)
766 SetALCError(ALC_INVALID_VALUE);
767 else
768 *data = alcEFXMinorVersion;
769 break;
771 case ALC_MAX_AUXILIARY_SENDS:
772 if(!size)
773 SetALCError(ALC_INVALID_VALUE);
774 else
775 *data = MAX_SENDS;
776 break;
778 case ALC_ATTRIBUTES_SIZE:
779 if(!device)
780 SetALCError(ALC_INVALID_DEVICE);
781 else if(!size)
782 SetALCError(ALC_INVALID_VALUE);
783 else
784 *data = 12;
785 break;
787 case ALC_ALL_ATTRIBUTES:
788 if(!device)
789 SetALCError(ALC_INVALID_DEVICE);
790 else if (size < 7)
791 SetALCError(ALC_INVALID_VALUE);
792 else
794 int i = 0;
796 data[i++] = ALC_FREQUENCY;
797 data[i++] = device->Frequency;
799 data[i++] = ALC_REFRESH;
800 data[i++] = device->Frequency / device->UpdateSize;
802 data[i++] = ALC_SYNC;
803 data[i++] = ALC_FALSE;
805 SuspendContext(NULL);
806 if(device->Context && size >= 12)
808 data[i++] = ALC_MONO_SOURCES;
809 data[i++] = device->Context->lNumMonoSources;
811 data[i++] = ALC_STEREO_SOURCES;
812 data[i++] = device->Context->lNumStereoSources;
814 data[i++] = ALC_MAX_AUXILIARY_SENDS;
815 data[i++] = MAX_SENDS;
817 ProcessContext(NULL);
819 data[i++] = 0;
821 break;
823 case ALC_FREQUENCY:
824 if(!device)
825 SetALCError(ALC_INVALID_DEVICE);
826 else if(!size)
827 SetALCError(ALC_INVALID_VALUE);
828 else
829 *data = device->Frequency;
830 break;
832 case ALC_REFRESH:
833 if(!device)
834 SetALCError(ALC_INVALID_DEVICE);
835 else if(!size)
836 SetALCError(ALC_INVALID_VALUE);
837 else
838 *data = device->Frequency / device->UpdateSize;
839 break;
841 case ALC_SYNC:
842 if(!device)
843 SetALCError(ALC_INVALID_DEVICE);
844 else if(!size)
845 SetALCError(ALC_INVALID_VALUE);
846 else
847 *data = ALC_FALSE;
848 break;
850 case ALC_MONO_SOURCES:
851 if(!device || !device->Context)
852 SetALCError(ALC_INVALID_DEVICE);
853 else if (size != 1)
854 SetALCError(ALC_INVALID_VALUE);
855 else
856 *data = device->Context->lNumMonoSources;
857 break;
859 case ALC_STEREO_SOURCES:
860 if(!device || !device->Context)
861 SetALCError(ALC_INVALID_DEVICE);
862 else if (size != 1)
863 SetALCError(ALC_INVALID_VALUE);
864 else
865 *data = device->Context->lNumStereoSources;
866 break;
868 default:
869 SetALCError(ALC_INVALID_ENUM);
870 break;
873 else if(size)
874 SetALCError(ALC_INVALID_VALUE);
877 return;
882 alcIsExtensionPresent
884 Determines if there is support for a particular extension
886 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
888 ALCboolean bResult = ALC_FALSE;
890 (void)device;
892 if (extName)
894 const char *ptr;
895 size_t len;
897 len = strlen(extName);
898 ptr = alcExtensionList;
899 while(ptr && *ptr)
901 if(strncasecmp(ptr, extName, len) == 0 &&
902 (ptr[len] == '\0' || isspace(ptr[len])))
904 bResult = ALC_TRUE;
905 break;
907 if((ptr=strchr(ptr, ' ')) != NULL)
909 do {
910 ++ptr;
911 } while(isspace(*ptr));
915 else
916 SetALCError(ALC_INVALID_VALUE);
918 return bResult;
923 alcGetProcAddress
925 Retrieves the function address for a particular extension function
927 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
929 ALCvoid *pFunction = NULL;
930 ALsizei i = 0;
932 (void)device;
934 if (funcName)
936 while(alcFunctions[i].funcName &&
937 strcmp(alcFunctions[i].funcName,funcName) != 0)
938 i++;
939 pFunction = alcFunctions[i].address;
941 else
942 SetALCError(ALC_INVALID_VALUE);
944 return pFunction;
949 alcGetEnumValue
951 Get the value for a particular ALC Enumerated Value
953 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
955 ALsizei i = 0;
956 ALCenum val;
958 (void)device;
960 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
961 i++;
962 val = enumeration[i].value;
964 if(!enumeration[i].enumName)
965 SetALCError(ALC_INVALID_VALUE);
967 return val;
972 alcCreateContext
974 Create and attach a Context to a particular Device.
976 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
978 ALCcontext *ALContext = NULL;
979 ALuint ulAttributeIndex, ulRequestedStereoSources;
981 if ((device)&&(!device->IsCaptureDevice))
983 // Reset Context Last Error code
984 g_eLastContextError = ALC_NO_ERROR;
986 // Current implementation only allows one Context per Device
987 if(!device->Context)
989 ALContext = calloc(1, sizeof(ALCcontext));
990 if(!ALContext)
992 SetALCError(ALC_OUT_OF_MEMORY);
993 return NULL;
996 ALContext->Device = device;
997 InitContext(ALContext);
999 device->Context = ALContext;
1001 SuspendContext(NULL);
1003 ALContext->next = g_pContextList;
1004 g_pContextList = ALContext;
1005 g_ulContextCount++;
1007 ProcessContext(NULL);
1009 // Check for Voice Count attributes
1010 if (attrList)
1012 ulAttributeIndex = 0;
1013 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
1015 if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
1017 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
1019 if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
1020 ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
1022 ALContext->lNumStereoSources = ulRequestedStereoSources;
1023 ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
1024 break;
1027 ulAttributeIndex += 2;
1031 else
1033 SetALCError(ALC_INVALID_VALUE);
1034 ALContext = NULL;
1037 else
1038 SetALCError(ALC_INVALID_DEVICE);
1040 return ALContext;
1045 alcDestroyContext
1047 Remove a Context
1049 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1051 ALCcontext **list;
1053 InitAL();
1055 // Lock context list
1056 SuspendContext(NULL);
1058 if (IsContext(context))
1060 // Lock context
1061 SuspendContext(context);
1063 ReleaseALSources(context);
1064 ReleaseALAuxiliaryEffectSlots(context);
1066 context->Device->Context = NULL;
1068 list = &g_pContextList;
1069 while(*list != context)
1070 list = &(*list)->next;
1072 *list = (*list)->next;
1073 g_ulContextCount--;
1075 // Unlock context
1076 ProcessContext(context);
1078 ExitContext(context);
1080 // Free memory (MUST do this after ProcessContext)
1081 memset(context, 0, sizeof(ALCcontext));
1082 free(context);
1084 else
1085 SetALCError(ALC_INVALID_CONTEXT);
1087 ProcessContext(NULL);
1092 alcGetCurrentContext
1094 Returns the currently active Context
1096 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1098 ALCcontext *pContext = NULL;
1100 InitAL();
1102 SuspendContext(NULL);
1104 pContext = g_pContextList;
1105 while ((pContext) && (!pContext->InUse))
1106 pContext = pContext->next;
1108 ProcessContext(NULL);
1110 return pContext;
1115 alcGetContextsDevice
1117 Returns the Device that a particular Context is attached to
1119 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1121 ALCdevice *pDevice = NULL;
1123 InitAL();
1125 SuspendContext(NULL);
1126 if (IsContext(pContext))
1127 pDevice = pContext->Device;
1128 else
1129 SetALCError(ALC_INVALID_CONTEXT);
1130 ProcessContext(NULL);
1132 return pDevice;
1137 alcMakeContextCurrent
1139 Makes the given Context the active Context
1141 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1143 ALCcontext *ALContext;
1144 ALboolean bReturn = AL_TRUE;
1146 InitAL();
1148 SuspendContext(NULL);
1150 // context must be a valid Context or NULL
1151 if ((IsContext(context)) || (context == NULL))
1153 if ((ALContext=alcGetCurrentContext()))
1155 SuspendContext(ALContext);
1156 ALContext->InUse=AL_FALSE;
1157 ProcessContext(ALContext);
1160 if ((ALContext=context) && (ALContext->Device))
1162 SuspendContext(ALContext);
1163 ALContext->InUse=AL_TRUE;
1164 ProcessContext(ALContext);
1167 else
1169 SetALCError(ALC_INVALID_CONTEXT);
1170 bReturn = AL_FALSE;
1173 ProcessContext(NULL);
1175 return bReturn;
1180 alcOpenDevice
1182 Open the Device specified.
1184 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1186 ALboolean bDeviceFound = AL_FALSE;
1187 ALCdevice *device;
1188 ALint i;
1190 InitAL();
1192 if(deviceName && !deviceName[0])
1193 deviceName = NULL;
1195 device = malloc(sizeof(ALCdevice));
1196 if (device)
1198 const char *fmt;
1200 //Initialise device structure
1201 memset(device, 0, sizeof(ALCdevice));
1203 //Validate device
1204 device->IsCaptureDevice = AL_FALSE;
1206 //Set output format
1207 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1208 if((ALint)device->Frequency <= 0)
1209 device->Frequency = SWMIXER_OUTPUT_RATE;
1211 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1212 if(fmt[0])
1213 device->Format = alGetEnumValue(fmt);
1215 if(!aluChannelsFromFormat(device->Format))
1216 device->Format = AL_FORMAT_STEREO16;
1218 device->UpdateSize = GetConfigValueInt(NULL, "refresh", 8192);
1219 if((ALint)device->UpdateSize <= 0)
1220 device->UpdateSize = 8192;
1222 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1223 if((ALint)device->MaxNoOfSources <= 0)
1224 device->MaxNoOfSources = 256;
1226 // Find a playback device to open
1227 for(i = 0;BackendList[i].Init;i++)
1229 device->Funcs = &BackendList[i].Funcs;
1230 if(ALCdevice_OpenPlayback(device, deviceName))
1232 SuspendContext(NULL);
1233 device->next = g_pDeviceList;
1234 g_pDeviceList = device;
1235 g_ulDeviceCount++;
1236 ProcessContext(NULL);
1238 bDeviceFound = AL_TRUE;
1239 break;
1243 if (!bDeviceFound)
1245 // No suitable output device found
1246 free(device);
1247 device = NULL;
1251 return device;
1256 alcCloseDevice
1258 Close the specified Device
1260 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1262 ALCboolean bReturn = ALC_FALSE;
1263 ALCdevice **list;
1265 if ((pDevice)&&(!pDevice->IsCaptureDevice))
1267 SuspendContext(NULL);
1269 list = &g_pDeviceList;
1270 while(*list != pDevice)
1271 list = &(*list)->next;
1273 *list = (*list)->next;
1274 g_ulDeviceCount--;
1276 ProcessContext(NULL);
1278 if(pDevice->Context)
1279 alcDestroyContext(pDevice->Context);
1280 ALCdevice_ClosePlayback(pDevice);
1282 //Release device structure
1283 memset(pDevice, 0, sizeof(ALCdevice));
1284 free(pDevice);
1286 bReturn = ALC_TRUE;
1288 else
1289 SetALCError(ALC_INVALID_DEVICE);
1291 return bReturn;
1295 ALCvoid ReleaseALC(ALCvoid)
1297 InitAL();
1299 #ifdef _DEBUG
1300 if(g_ulContextCount > 0)
1301 AL_PRINT("exit() %u device(s) and %u context(s) NOT deleted\n", g_ulDeviceCount, g_ulContextCount);
1302 #endif
1304 while(g_pDeviceList)
1306 if(g_pDeviceList->IsCaptureDevice)
1307 alcCaptureCloseDevice(g_pDeviceList);
1308 else
1309 alcCloseDevice(g_pDeviceList);
1313 ///////////////////////////////////////////////////////