Add a PortAudio backend
[openal-soft.git] / Alc / ALc.c
blob13b2fa310eafa0bcfeac69259056847e44bc4d37
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"
40 #include "alu.h"
42 ///////////////////////////////////////////////////////
43 // DEBUG INFORMATION
45 char _alDebug[256];
47 ///////////////////////////////////////////////////////
50 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
51 static struct {
52 const char *name;
53 void (*Init)(BackendFuncs*);
54 BackendFuncs Funcs;
55 } BackendList[] = {
56 #ifdef HAVE_ALSA
57 { "alsa", alc_alsa_init, EmptyFuncs },
58 #endif
59 #ifdef HAVE_OSS
60 { "oss", alc_oss_init, EmptyFuncs },
61 #endif
62 #ifdef HAVE_SOLARIS
63 { "solaris", alc_solaris_init, EmptyFuncs },
64 #endif
65 #ifdef HAVE_DSOUND
66 { "dsound", alcDSoundInit, EmptyFuncs },
67 #endif
68 #ifdef HAVE_WINMM
69 { "winmm", alcWinMMInit, EmptyFuncs },
70 #endif
71 #ifdef HAVE_PORTAUDIO
72 { "port", alc_pa_init, EmptyFuncs },
73 #endif
74 #ifdef HAVE_SDL
75 { "sdl", alc_sdl_init, EmptyFuncs },
76 #endif
78 { "wave", alc_wave_init, EmptyFuncs },
80 { NULL, NULL, EmptyFuncs }
82 #undef EmptyFuncs
84 ///////////////////////////////////////////////////////
86 #define ALC_EFX_MAJOR_VERSION 0x20001
87 #define ALC_EFX_MINOR_VERSION 0x20002
88 #define ALC_MAX_AUXILIARY_SENDS 0x20003
90 ///////////////////////////////////////////////////////
91 // STRING and EXTENSIONS
93 typedef struct ALCfunction_struct
95 ALCchar *funcName;
96 ALvoid *address;
97 } ALCfunction;
99 static ALCfunction alcFunctions[] = {
100 { "alcCreateContext", (ALvoid *) alcCreateContext },
101 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
102 { "alcProcessContext", (ALvoid *) alcProcessContext },
103 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
104 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
105 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
106 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
107 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
108 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
109 { "alcGetError", (ALvoid *) alcGetError },
110 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
111 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
112 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
113 { "alcGetString", (ALvoid *) alcGetString },
114 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
115 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
116 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
117 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
118 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
119 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
120 { NULL, (ALvoid *) NULL }
123 static ALenums enumeration[]={
124 // Types
125 { (ALchar *)"ALC_INVALID", ALC_INVALID },
126 { (ALchar *)"ALC_FALSE", ALC_FALSE },
127 { (ALchar *)"ALC_TRUE", ALC_TRUE },
129 // ALC Properties
130 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
131 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
132 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
133 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
134 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
135 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
136 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
137 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
138 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
139 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
140 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
141 { (ALchar *)"ALC_SYNC", ALC_SYNC },
142 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
143 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
144 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
145 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
146 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
148 // EFX Properties
149 { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
150 { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
151 { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
153 // ALC Error Message
154 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
155 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
156 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
157 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
158 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
159 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
160 { (ALchar *)NULL, (ALenum)0 }
162 // Error strings
163 static const ALCchar alcNoError[] = "No Error";
164 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
165 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
166 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
167 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
168 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
170 // Context strings
171 static ALCchar alcDeviceList[2048];
172 static ALCchar alcAllDeviceList[2048];
173 static ALCchar alcCaptureDeviceList[2048];
174 // Default is always the first in the list
175 static ALCchar *alcDefaultDeviceSpecifier = alcDeviceList;
176 static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
177 static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
180 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_EFX";
181 static ALCint alcMajorVersion = 1;
182 static ALCint alcMinorVersion = 1;
184 static ALCint alcEFXMajorVersion = 1;
185 static ALCint alcEFXMinorVersion = 0;
187 ///////////////////////////////////////////////////////
190 ///////////////////////////////////////////////////////
191 // Global Variables
193 static ALCdevice *g_pDeviceList = NULL;
194 static ALCuint g_ulDeviceCount = 0;
196 static CRITICAL_SECTION g_csMutex;
198 // Context List
199 static ALCcontext *g_pContextList = NULL;
200 static ALCuint g_ulContextCount = 0;
202 // Context Error
203 static ALCenum g_eLastContextError = ALC_NO_ERROR;
205 static ALboolean init_done = AL_FALSE;
207 ///////////////////////////////////////////////////////
210 ///////////////////////////////////////////////////////
211 // ALC Related helper functions
212 #ifdef _WIN32
213 BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
215 (void)lpReserved;
217 // Perform actions based on the reason for calling.
218 switch(ul_reason_for_call)
220 case DLL_PROCESS_ATTACH:
221 DisableThreadLibraryCalls(hModule);
222 break;
224 case DLL_PROCESS_DETACH:
225 if(!init_done)
226 break;
227 ReleaseALC();
228 ReleaseALBuffers();
229 ReleaseALEffects();
230 ReleaseALFilters();
231 FreeALConfig();
232 ALTHUNK_EXIT();
233 DeleteCriticalSection(&g_csMutex);
234 break;
236 return TRUE;
238 #else
239 #ifdef HAVE_GCC_DESTRUCTOR
240 static void my_deinit() __attribute__((destructor));
241 static void my_deinit()
243 static ALenum once = AL_FALSE;
244 if(once || !init_done) return;
245 once = AL_TRUE;
247 ReleaseALC();
248 ReleaseALBuffers();
249 ReleaseALEffects();
250 ReleaseALFilters();
251 FreeALConfig();
252 ALTHUNK_EXIT();
253 DeleteCriticalSection(&g_csMutex);
255 #endif
256 #endif
258 static void InitAL(void)
260 if(!init_done)
262 int i;
263 const char *devs, *str;
265 init_done = AL_TRUE;
267 InitializeCriticalSection(&g_csMutex);
268 ALTHUNK_INIT();
269 ReadALConfig();
271 devs = GetConfigValue(NULL, "drivers", "");
272 if(devs[0])
274 int n;
275 size_t len;
276 const char *next = devs;
278 i = 0;
280 do {
281 devs = next;
282 next = strchr(devs, ',');
284 if(!devs[0] || devs[0] == ',')
285 continue;
287 len = (next ? ((size_t)(next-devs)) : strlen(devs));
288 for(n = i;BackendList[n].Init;n++)
290 if(len == strlen(BackendList[n].name) &&
291 strncmp(BackendList[n].name, devs, len) == 0)
293 const char *name = BackendList[i].name;
294 void (*Init)(BackendFuncs*) = BackendList[i].Init;
296 BackendList[i].name = BackendList[n].name;
297 BackendList[i].Init = BackendList[n].Init;
299 BackendList[n].name = name;
300 BackendList[n].Init = Init;
302 i++;
305 } while(next++);
307 BackendList[i].name = NULL;
308 BackendList[i].Init = NULL;
311 for(i = 0;BackendList[i].Init;i++)
312 BackendList[i].Init(&BackendList[i].Funcs);
314 str = GetConfigValue(NULL, "stereodup", "false");
315 DuplicateStereo = (strcasecmp(str, "true") == 0 ||
316 strcasecmp(str, "yes") == 0 ||
317 strcasecmp(str, "on") == 0 ||
318 atoi(str) != 0);
320 str = GetConfigValue(NULL, "excludefx", "");
321 if(str[0])
323 const struct {
324 const char *name;
325 int type;
326 } EffectList[] = {
327 { "reverb", REVERB },
328 { NULL, 0 }
330 int n;
331 size_t len;
332 const char *next = str;
334 do {
335 str = next;
336 next = strchr(str, ',');
338 if(!str[0] || next == str)
339 continue;
341 len = (next ? ((size_t)(next-str)) : strlen(str));
342 for(n = 0;EffectList[n].name;n++)
344 if(len == strlen(EffectList[n].name) &&
345 strncmp(EffectList[n].name, str, len) == 0)
346 DisabledEffects[EffectList[n].type] = AL_TRUE;
348 } while(next++);
353 ALCchar *AppendDeviceList(char *name)
355 static size_t pos;
356 ALCchar *ret = alcDeviceList+pos;
357 if(pos >= sizeof(alcDeviceList))
359 AL_PRINT("Not enough room to add %s!\n", name);
360 return alcDeviceList + sizeof(alcDeviceList) - 1;
362 pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos-1, "%s", name) + 1;
363 return ret;
366 ALCchar *AppendAllDeviceList(char *name)
368 static size_t pos;
369 ALCchar *ret = alcAllDeviceList+pos;
370 if(pos >= sizeof(alcAllDeviceList))
372 AL_PRINT("Not enough room to add %s!\n", name);
373 return alcAllDeviceList + sizeof(alcAllDeviceList) - 1;
375 pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos-1, "%s", name) + 1;
376 return ret;
379 ALCchar *AppendCaptureDeviceList(char *name)
381 static size_t pos;
382 ALCchar *ret = alcCaptureDeviceList+pos;
383 if(pos >= sizeof(alcCaptureDeviceList))
385 AL_PRINT("Not enough room to add %s!\n", name);
386 return alcCaptureDeviceList + sizeof(alcCaptureDeviceList) - 1;
388 pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos-1, "%s", name) + 1;
389 return ret;
393 IsContext
395 Check pContext is a valid Context pointer
397 static ALCboolean IsContext(ALCcontext *pContext)
399 ALCcontext *pTempContext;
401 pTempContext = g_pContextList;
402 while (pTempContext && pTempContext != pContext)
403 pTempContext = pTempContext->next;
405 return (pTempContext ? ALC_TRUE : ALC_FALSE);
410 SetALCError
412 Store latest ALC Error
414 ALCvoid SetALCError(ALenum errorCode)
416 g_eLastContextError = errorCode;
421 SuspendContext
423 Thread-safe entry
425 ALCvoid SuspendContext(ALCcontext *pContext)
427 (void)pContext;
428 EnterCriticalSection(&g_csMutex);
433 ProcessContext
435 Thread-safe exit
437 ALCvoid ProcessContext(ALCcontext *pContext)
439 (void)pContext;
440 LeaveCriticalSection(&g_csMutex);
445 InitContext
447 Initialize Context variables
449 static ALvoid InitContext(ALCcontext *pContext)
451 int level;
453 //Initialise listener
454 pContext->Listener.Gain = 1.0f;
455 pContext->Listener.MetersPerUnit = 1.0f;
456 pContext->Listener.Position[0] = 0.0f;
457 pContext->Listener.Position[1] = 0.0f;
458 pContext->Listener.Position[2] = 0.0f;
459 pContext->Listener.Velocity[0] = 0.0f;
460 pContext->Listener.Velocity[1] = 0.0f;
461 pContext->Listener.Velocity[2] = 0.0f;
462 pContext->Listener.Forward[0] = 0.0f;
463 pContext->Listener.Forward[1] = 0.0f;
464 pContext->Listener.Forward[2] = -1.0f;
465 pContext->Listener.Up[0] = 0.0f;
466 pContext->Listener.Up[1] = 1.0f;
467 pContext->Listener.Up[2] = 0.0f;
469 //Validate pContext
470 pContext->LastError = AL_NO_ERROR;
471 pContext->InUse = AL_FALSE;
473 //Set output format
474 pContext->Frequency = pContext->Device->Frequency;
476 //Set globals
477 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
478 pContext->DopplerFactor = 1.0f;
479 pContext->DopplerVelocity = 1.0f;
480 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
482 pContext->lNumStereoSources = 1;
483 pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
485 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_source_distance_model AL_LOKI_quadriphonic";
487 level = GetConfigValueInt(NULL, "cf_level", 0);
488 if(level > 0 && level <= 6)
490 pContext->bs2b = calloc(1, sizeof(*pContext->bs2b));
491 bs2b_set_srate(pContext->bs2b, pContext->Frequency);
492 bs2b_set_level(pContext->bs2b, level);
495 aluInitPanning(pContext);
500 ExitContext
502 Clean up Context, destroy any remaining Sources
504 static ALCvoid ExitContext(ALCcontext *pContext)
506 //Invalidate context
507 pContext->LastError = AL_NO_ERROR;
508 pContext->InUse = AL_FALSE;
510 free(pContext->bs2b);
511 pContext->bs2b = NULL;
514 ///////////////////////////////////////////////////////
517 ///////////////////////////////////////////////////////
518 // ALC Functions calls
521 // This should probably move to another c file but for now ...
522 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
524 ALCboolean DeviceFound = ALC_FALSE;
525 ALCdevice *pDevice = NULL;
526 ALCint i;
528 InitAL();
530 if(SampleSize <= 0)
532 SetALCError(ALC_INVALID_VALUE);
533 return NULL;
536 if(deviceName && !deviceName[0])
537 deviceName = NULL;
539 pDevice = malloc(sizeof(ALCdevice));
540 if (pDevice)
542 //Initialise device structure
543 memset(pDevice, 0, sizeof(ALCdevice));
545 //Validate device
546 pDevice->IsCaptureDevice = AL_TRUE;
548 pDevice->Frequency = frequency;
549 pDevice->Format = format;
551 for(i = 0;BackendList[i].Init;i++)
553 pDevice->Funcs = &BackendList[i].Funcs;
554 if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
556 SuspendContext(NULL);
557 pDevice->next = g_pDeviceList;
558 g_pDeviceList = pDevice;
559 g_ulDeviceCount++;
560 ProcessContext(NULL);
562 DeviceFound = ALC_TRUE;
563 break;
567 if(!DeviceFound)
569 SetALCError(ALC_INVALID_VALUE);
570 free(pDevice);
571 pDevice = NULL;
574 else
575 SetALCError(ALC_OUT_OF_MEMORY);
577 return pDevice;
580 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
582 ALCboolean bReturn = ALC_FALSE;
583 ALCdevice **list;
585 if ((pDevice)&&(pDevice->IsCaptureDevice))
587 SuspendContext(NULL);
589 list = &g_pDeviceList;
590 while(*list != pDevice)
591 list = &(*list)->next;
593 *list = (*list)->next;
594 g_ulDeviceCount--;
596 ProcessContext(NULL);
598 ALCdevice_CloseCapture(pDevice);
599 free(pDevice);
601 bReturn = ALC_TRUE;
603 else
604 SetALCError(ALC_INVALID_DEVICE);
606 return bReturn;
609 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
611 if ((pDevice)&&(pDevice->IsCaptureDevice))
612 ALCdevice_StartCapture(pDevice);
613 else
614 SetALCError(ALC_INVALID_DEVICE);
617 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
619 if ((pDevice)&&(pDevice->IsCaptureDevice))
620 ALCdevice_StopCapture(pDevice);
621 else
622 SetALCError(ALC_INVALID_DEVICE);
625 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
627 if ((pDevice) && (pDevice->IsCaptureDevice))
628 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
629 else
630 SetALCError(ALC_INVALID_DEVICE);
634 alcGetError
636 Return last ALC generated error code
638 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
640 ALCenum errorCode;
642 (void)device;
644 errorCode = g_eLastContextError;
645 g_eLastContextError = ALC_NO_ERROR;
646 return errorCode;
651 alcSuspendContext
653 Not functional
655 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
657 // Not a lot happens here !
658 (void)pContext;
663 alcProcessContext
665 Not functional
667 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
669 // Not a lot happens here !
670 (void)pContext;
675 alcGetString
677 Returns information about the Device, and error strings
679 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
681 const ALCchar *value = NULL;
683 InitAL();
685 switch (param)
687 case ALC_NO_ERROR:
688 value = alcNoError;
689 break;
691 case ALC_INVALID_ENUM:
692 value = alcErrInvalidEnum;
693 break;
695 case ALC_INVALID_VALUE:
696 value = alcErrInvalidValue;
697 break;
699 case ALC_INVALID_DEVICE:
700 value = alcErrInvalidDevice;
701 break;
703 case ALC_INVALID_CONTEXT:
704 value = alcErrInvalidContext;
705 break;
707 case ALC_OUT_OF_MEMORY:
708 value = alcErrOutOfMemory;
709 break;
711 case ALC_DEFAULT_DEVICE_SPECIFIER:
712 value = alcDefaultDeviceSpecifier;
713 break;
715 case ALC_DEVICE_SPECIFIER:
716 if (pDevice)
717 value = pDevice->szDeviceName;
718 else
719 value = alcDeviceList;
720 break;
722 case ALC_ALL_DEVICES_SPECIFIER:
723 value = alcAllDeviceList;
724 break;
726 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
727 value = alcDefaultAllDeviceSpecifier;
728 break;
730 case ALC_CAPTURE_DEVICE_SPECIFIER:
731 if (pDevice)
732 value = pDevice->szDeviceName;
733 else
734 value = alcCaptureDeviceList;
735 break;
737 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
738 value = alcCaptureDefaultDeviceSpecifier;
739 break;
741 case ALC_EXTENSIONS:
742 value = alcExtensionList;
743 break;
745 default:
746 SetALCError(ALC_INVALID_ENUM);
747 break;
750 return value;
755 alcGetIntegerv
757 Returns information about the Device and the version of Open AL
759 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
761 InitAL();
763 if ((device)&&(device->IsCaptureDevice))
765 SuspendContext(NULL);
767 // Capture device
768 switch (param)
770 case ALC_CAPTURE_SAMPLES:
771 if ((size) && (data))
772 *data = ALCdevice_AvailableSamples(device);
773 else
774 SetALCError(ALC_INVALID_VALUE);
775 break;
777 default:
778 SetALCError(ALC_INVALID_ENUM);
779 break;
782 ProcessContext(NULL);
784 else
786 if(data)
788 // Playback Device
789 switch (param)
791 case ALC_MAJOR_VERSION:
792 if(!size)
793 SetALCError(ALC_INVALID_VALUE);
794 else
795 *data = alcMajorVersion;
796 break;
798 case ALC_MINOR_VERSION:
799 if(!size)
800 SetALCError(ALC_INVALID_VALUE);
801 else
802 *data = alcMinorVersion;
803 break;
805 case ALC_EFX_MAJOR_VERSION:
806 if(!size)
807 SetALCError(ALC_INVALID_VALUE);
808 else
809 *data = alcEFXMajorVersion;
810 break;
812 case ALC_EFX_MINOR_VERSION:
813 if(!size)
814 SetALCError(ALC_INVALID_VALUE);
815 else
816 *data = alcEFXMinorVersion;
817 break;
819 case ALC_MAX_AUXILIARY_SENDS:
820 if(!size)
821 SetALCError(ALC_INVALID_VALUE);
822 else
823 *data = MAX_SENDS;
824 break;
826 case ALC_ATTRIBUTES_SIZE:
827 if(!device)
828 SetALCError(ALC_INVALID_DEVICE);
829 else if(!size)
830 SetALCError(ALC_INVALID_VALUE);
831 else
832 *data = 12;
833 break;
835 case ALC_ALL_ATTRIBUTES:
836 if(!device)
837 SetALCError(ALC_INVALID_DEVICE);
838 else if (size < 7)
839 SetALCError(ALC_INVALID_VALUE);
840 else
842 int i = 0;
844 data[i++] = ALC_FREQUENCY;
845 data[i++] = device->Frequency;
847 data[i++] = ALC_REFRESH;
848 data[i++] = device->Frequency / device->UpdateSize;
850 data[i++] = ALC_SYNC;
851 data[i++] = ALC_FALSE;
853 SuspendContext(NULL);
854 if(device->Context && size >= 12)
856 data[i++] = ALC_MONO_SOURCES;
857 data[i++] = device->Context->lNumMonoSources;
859 data[i++] = ALC_STEREO_SOURCES;
860 data[i++] = device->Context->lNumStereoSources;
862 data[i++] = ALC_MAX_AUXILIARY_SENDS;
863 data[i++] = MAX_SENDS;
865 ProcessContext(NULL);
867 data[i++] = 0;
869 break;
871 case ALC_FREQUENCY:
872 if(!device)
873 SetALCError(ALC_INVALID_DEVICE);
874 else if(!size)
875 SetALCError(ALC_INVALID_VALUE);
876 else
877 *data = device->Frequency;
878 break;
880 case ALC_REFRESH:
881 if(!device)
882 SetALCError(ALC_INVALID_DEVICE);
883 else if(!size)
884 SetALCError(ALC_INVALID_VALUE);
885 else
886 *data = device->Frequency / device->UpdateSize;
887 break;
889 case ALC_SYNC:
890 if(!device)
891 SetALCError(ALC_INVALID_DEVICE);
892 else if(!size)
893 SetALCError(ALC_INVALID_VALUE);
894 else
895 *data = ALC_FALSE;
896 break;
898 case ALC_MONO_SOURCES:
899 if(!device || !device->Context)
900 SetALCError(ALC_INVALID_DEVICE);
901 else if (size != 1)
902 SetALCError(ALC_INVALID_VALUE);
903 else
904 *data = device->Context->lNumMonoSources;
905 break;
907 case ALC_STEREO_SOURCES:
908 if(!device || !device->Context)
909 SetALCError(ALC_INVALID_DEVICE);
910 else if (size != 1)
911 SetALCError(ALC_INVALID_VALUE);
912 else
913 *data = device->Context->lNumStereoSources;
914 break;
916 default:
917 SetALCError(ALC_INVALID_ENUM);
918 break;
921 else if(size)
922 SetALCError(ALC_INVALID_VALUE);
925 return;
930 alcIsExtensionPresent
932 Determines if there is support for a particular extension
934 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
936 ALCboolean bResult = ALC_FALSE;
938 (void)device;
940 if (extName)
942 const char *ptr;
943 size_t len;
945 len = strlen(extName);
946 ptr = alcExtensionList;
947 while(ptr && *ptr)
949 if(strncasecmp(ptr, extName, len) == 0 &&
950 (ptr[len] == '\0' || isspace(ptr[len])))
952 bResult = ALC_TRUE;
953 break;
955 if((ptr=strchr(ptr, ' ')) != NULL)
957 do {
958 ++ptr;
959 } while(isspace(*ptr));
963 else
964 SetALCError(ALC_INVALID_VALUE);
966 return bResult;
971 alcGetProcAddress
973 Retrieves the function address for a particular extension function
975 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
977 ALCvoid *pFunction = NULL;
978 ALsizei i = 0;
980 (void)device;
982 if (funcName)
984 while(alcFunctions[i].funcName &&
985 strcmp(alcFunctions[i].funcName,funcName) != 0)
986 i++;
987 pFunction = alcFunctions[i].address;
989 else
990 SetALCError(ALC_INVALID_VALUE);
992 return pFunction;
997 alcGetEnumValue
999 Get the value for a particular ALC Enumerated Value
1001 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
1003 ALsizei i = 0;
1004 ALCenum val;
1006 (void)device;
1008 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
1009 i++;
1010 val = enumeration[i].value;
1012 if(!enumeration[i].enumName)
1013 SetALCError(ALC_INVALID_VALUE);
1015 return val;
1020 alcCreateContext
1022 Create and attach a Context to a particular Device.
1024 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
1026 ALCcontext *ALContext = NULL;
1027 ALuint ulAttributeIndex, ulRequestedStereoSources;
1029 if ((device)&&(!device->IsCaptureDevice))
1031 // Reset Context Last Error code
1032 g_eLastContextError = ALC_NO_ERROR;
1034 // Current implementation only allows one Context per Device
1035 if(!device->Context)
1037 ALContext = calloc(1, sizeof(ALCcontext));
1038 if(!ALContext)
1040 SetALCError(ALC_OUT_OF_MEMORY);
1041 return NULL;
1044 ALContext->Device = device;
1045 InitContext(ALContext);
1047 device->Context = ALContext;
1049 SuspendContext(NULL);
1051 ALContext->next = g_pContextList;
1052 g_pContextList = ALContext;
1053 g_ulContextCount++;
1055 ProcessContext(NULL);
1057 // Check for Voice Count attributes
1058 if (attrList)
1060 ulAttributeIndex = 0;
1061 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
1063 if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
1065 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
1067 if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
1068 ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
1070 ALContext->lNumStereoSources = ulRequestedStereoSources;
1071 ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
1072 break;
1075 ulAttributeIndex += 2;
1079 else
1081 SetALCError(ALC_INVALID_VALUE);
1082 ALContext = NULL;
1085 else
1086 SetALCError(ALC_INVALID_DEVICE);
1088 return ALContext;
1093 alcDestroyContext
1095 Remove a Context
1097 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
1099 ALCcontext **list;
1101 InitAL();
1103 // Lock context list
1104 SuspendContext(NULL);
1106 if (IsContext(context))
1108 // Lock context
1109 SuspendContext(context);
1111 ReleaseALSources(context);
1112 ReleaseALAuxiliaryEffectSlots(context);
1114 context->Device->Context = NULL;
1116 list = &g_pContextList;
1117 while(*list != context)
1118 list = &(*list)->next;
1120 *list = (*list)->next;
1121 g_ulContextCount--;
1123 // Unlock context
1124 ProcessContext(context);
1126 ExitContext(context);
1128 // Free memory (MUST do this after ProcessContext)
1129 memset(context, 0, sizeof(ALCcontext));
1130 free(context);
1132 else
1133 SetALCError(ALC_INVALID_CONTEXT);
1135 ProcessContext(NULL);
1140 alcGetCurrentContext
1142 Returns the currently active Context
1144 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
1146 ALCcontext *pContext = NULL;
1148 InitAL();
1150 SuspendContext(NULL);
1152 pContext = g_pContextList;
1153 while ((pContext) && (!pContext->InUse))
1154 pContext = pContext->next;
1156 ProcessContext(NULL);
1158 return pContext;
1163 alcGetContextsDevice
1165 Returns the Device that a particular Context is attached to
1167 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1169 ALCdevice *pDevice = NULL;
1171 InitAL();
1173 SuspendContext(NULL);
1174 if (IsContext(pContext))
1175 pDevice = pContext->Device;
1176 else
1177 SetALCError(ALC_INVALID_CONTEXT);
1178 ProcessContext(NULL);
1180 return pDevice;
1185 alcMakeContextCurrent
1187 Makes the given Context the active Context
1189 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1191 ALCcontext *ALContext;
1192 ALboolean bReturn = AL_TRUE;
1194 InitAL();
1196 SuspendContext(NULL);
1198 // context must be a valid Context or NULL
1199 if ((IsContext(context)) || (context == NULL))
1201 if ((ALContext=alcGetCurrentContext()))
1203 SuspendContext(ALContext);
1204 ALContext->InUse=AL_FALSE;
1205 ProcessContext(ALContext);
1208 if ((ALContext=context) && (ALContext->Device))
1210 SuspendContext(ALContext);
1211 ALContext->InUse=AL_TRUE;
1212 ProcessContext(ALContext);
1215 else
1217 SetALCError(ALC_INVALID_CONTEXT);
1218 bReturn = AL_FALSE;
1221 ProcessContext(NULL);
1223 return bReturn;
1228 alcOpenDevice
1230 Open the Device specified.
1232 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1234 ALboolean bDeviceFound = AL_FALSE;
1235 ALCdevice *device;
1236 ALint i;
1238 InitAL();
1240 if(deviceName && !deviceName[0])
1241 deviceName = NULL;
1243 device = malloc(sizeof(ALCdevice));
1244 if (device)
1246 const char *fmt;
1248 //Initialise device structure
1249 memset(device, 0, sizeof(ALCdevice));
1251 //Validate device
1252 device->IsCaptureDevice = AL_FALSE;
1254 //Set output format
1255 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1256 if((ALint)device->Frequency <= 0)
1257 device->Frequency = SWMIXER_OUTPUT_RATE;
1259 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1260 if(fmt[0])
1261 device->Format = alGetEnumValue(fmt);
1263 if(!aluChannelsFromFormat(device->Format))
1264 device->Format = AL_FORMAT_STEREO16;
1266 device->UpdateSize = GetConfigValueInt(NULL, "refresh", 4096);
1267 if((ALint)device->UpdateSize <= 0)
1268 device->UpdateSize = 4096;
1270 device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256);
1271 if((ALint)device->MaxNoOfSources <= 0)
1272 device->MaxNoOfSources = 256;
1274 // Find a playback device to open
1275 SuspendContext(NULL);
1276 for(i = 0;BackendList[i].Init;i++)
1278 device->Funcs = &BackendList[i].Funcs;
1279 if(ALCdevice_OpenPlayback(device, deviceName))
1281 device->next = g_pDeviceList;
1282 g_pDeviceList = device;
1283 g_ulDeviceCount++;
1285 bDeviceFound = AL_TRUE;
1286 break;
1289 ProcessContext(NULL);
1291 if (!bDeviceFound)
1293 // No suitable output device found
1294 SetALCError(ALC_INVALID_VALUE);
1295 free(device);
1296 device = NULL;
1299 else
1300 SetALCError(ALC_OUT_OF_MEMORY);
1302 return device;
1307 alcCloseDevice
1309 Close the specified Device
1311 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1313 ALCboolean bReturn = ALC_FALSE;
1314 ALCdevice **list;
1316 if ((pDevice)&&(!pDevice->IsCaptureDevice))
1318 SuspendContext(NULL);
1320 list = &g_pDeviceList;
1321 while(*list != pDevice)
1322 list = &(*list)->next;
1324 *list = (*list)->next;
1325 g_ulDeviceCount--;
1327 ProcessContext(NULL);
1329 if(pDevice->Context)
1331 #ifdef _DEBUG
1332 AL_PRINT("alcCloseDevice(): destroying 1 Context\n");
1333 #endif
1334 alcDestroyContext(pDevice->Context);
1336 ALCdevice_ClosePlayback(pDevice);
1338 //Release device structure
1339 memset(pDevice, 0, sizeof(ALCdevice));
1340 free(pDevice);
1342 bReturn = ALC_TRUE;
1344 else
1345 SetALCError(ALC_INVALID_DEVICE);
1347 return bReturn;
1351 ALCvoid ReleaseALC(ALCvoid)
1353 #ifdef _DEBUG
1354 if(g_ulDeviceCount > 0)
1355 AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":"");
1356 #endif
1358 while(g_pDeviceList)
1360 if(g_pDeviceList->IsCaptureDevice)
1361 alcCaptureCloseDevice(g_pDeviceList);
1362 else
1363 alcCloseDevice(g_pDeviceList);
1367 ///////////////////////////////////////////////////////