Implement ALC properties
[openal-soft.git] / Alc / ALc.c
blob80a5a35f484b4bf02a0d00cc52d34e7d8cb44b9c
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 "alMain.h"
30 #include "AL/al.h"
31 #include "AL/alc.h"
33 ///////////////////////////////////////////////////////
34 // DEBUG INFORMATION
36 char szDebug[256];
38 ///////////////////////////////////////////////////////
41 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
42 struct {
43 const char *name;
44 void (*Init)(BackendFuncs*);
45 BackendFuncs Funcs;
46 } BackendList[] = {
47 #ifdef HAVE_ALSA
48 { "alsa", alc_alsa_init, EmptyFuncs },
49 #endif
50 #ifdef HAVE_OSS
51 { "oss", alc_oss_init, EmptyFuncs },
52 #endif
53 #ifdef HAVE_DSOUND
54 { "dsound", alcDSoundInit, EmptyFuncs },
55 #endif
56 #ifdef HAVE_WINMM
57 { "winmm", alcWinMMInit, EmptyFuncs },
58 #endif
60 { NULL, NULL, EmptyFuncs }
62 #undef EmptyFuncs
64 ///////////////////////////////////////////////////////
66 #define ALC_EFX_MAJOR_VERSION 0x20001
67 #define ALC_EFX_MINOR_VERSION 0x20002
68 #define ALC_MAX_AUXILIARY_SENDS 0x20003
70 ///////////////////////////////////////////////////////
71 // STRING and EXTENSIONS
73 typedef struct ALCextension_struct
75 ALCchar *extName;
76 ALvoid *address;
77 } ALCextension;
79 typedef struct ALCfunction_struct
81 ALCchar *funcName;
82 ALvoid *address;
83 } ALCfunction;
85 static ALCextension alcExtensions[] = {
86 { "ALC_ENUMERATE_ALL_EXT", (ALvoid *) NULL },
87 { "ALC_ENUMERATION_EXT", (ALvoid *) NULL },
88 { "ALC_EXT_CAPTURE", (ALvoid *) NULL },
89 { NULL, (ALvoid *) NULL }
92 static ALCfunction alcFunctions[] = {
93 { "alcCreateContext", (ALvoid *) alcCreateContext },
94 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
95 { "alcProcessContext", (ALvoid *) alcProcessContext },
96 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
97 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
98 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
99 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
100 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
101 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
102 { "alcGetError", (ALvoid *) alcGetError },
103 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
104 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
105 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
106 { "alcGetString", (ALvoid *) alcGetString },
107 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
108 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
109 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
110 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
111 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
112 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
113 { NULL, (ALvoid *) NULL }
116 static ALenums enumeration[]={
117 // Types
118 { (ALchar *)"ALC_INVALID", ALC_INVALID },
119 { (ALchar *)"ALC_FALSE", ALC_FALSE },
120 { (ALchar *)"ALC_TRUE", ALC_TRUE },
122 // ALC Properties
123 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
124 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
125 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
126 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
127 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
128 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
129 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
130 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
131 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
132 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
133 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
134 { (ALchar *)"ALC_SYNC", ALC_SYNC },
135 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
136 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
137 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
138 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER},
139 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
141 // EFX Properties
142 { (ALchar *)"ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION },
143 { (ALchar *)"ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION },
144 { (ALchar *)"ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS },
146 // ALC Error Message
147 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
148 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
149 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
150 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
151 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
152 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
153 { (ALchar *)NULL, (ALenum)0 }
155 // Error strings
156 static const ALCchar alcNoError[] = "No Error";
157 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
158 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
159 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
160 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
161 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
163 // Context strings
164 static ALCchar alcDeviceList[2048];
165 static ALCchar alcAllDeviceList[2048];
166 static ALCchar alcCaptureDeviceList[2048];
167 // Default is always the first in the list
168 static ALCchar *alcDefaultDeviceSpecifier = alcDeviceList;
169 static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
170 static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
173 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE";
174 static ALCint alcMajorVersion = 1;
175 static ALCint alcMinorVersion = 1;
177 static ALCint alcEFXMajorVersion = 1;
178 static ALCint alcEFXMinorVersion = 0;
180 ///////////////////////////////////////////////////////
183 ///////////////////////////////////////////////////////
184 // Global Variables
186 // Context List
187 static ALCcontext *g_pContextList = NULL;
188 static ALCuint g_ulContextCount = 0;
190 // Context Error
191 static ALCenum g_eLastContextError = ALC_NO_ERROR;
193 ///////////////////////////////////////////////////////
196 ///////////////////////////////////////////////////////
197 // ALC Related helper functions
199 static void InitAL(void)
201 static int done = 0;
202 if(!done)
204 int i;
205 const char *devs;
207 InitializeCriticalSection(&g_mutex);
208 ALTHUNK_INIT();
209 ReadALConfig();
211 devs = GetConfigValue(NULL, "drivers", "");
212 if(devs[0])
214 int n;
215 size_t len;
216 const char *next = devs;
218 i = 0;
220 do {
221 devs = next;
222 next = strchr(devs, ',');
224 if(!devs[0] || devs[0] == ',')
225 continue;
227 len = (next ? ((size_t)(next-devs)) : strlen(devs));
228 for(n = i;BackendList[n].Init;n++)
230 if(len == strlen(BackendList[n].name) &&
231 strncmp(BackendList[n].name, devs, len) == 0)
233 const char *name = BackendList[i].name;
234 void (*Init)(BackendFuncs*) = BackendList[i].Init;
236 BackendList[i].name = BackendList[n].name;
237 BackendList[i].Init = BackendList[n].Init;
239 BackendList[n].name = name;
240 BackendList[n].Init = Init;
242 i++;
245 } while(next++);
247 BackendList[i].name = NULL;
248 BackendList[i].Init = NULL;
251 for(i = 0;BackendList[i].Init;i++)
252 BackendList[i].Init(&BackendList[i].Funcs);
253 done = 1;
257 ALCchar *AppendDeviceList(char *name)
259 static int pos;
260 ALCchar *ret = alcDeviceList+pos;
261 pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos, "%s", name) + 1;
262 return ret;
265 ALCchar *AppendAllDeviceList(char *name)
267 static int pos;
268 ALCchar *ret = alcAllDeviceList+pos;
269 pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos, "%s", name) + 1;
270 return ret;
273 ALCchar *AppendCaptureDeviceList(char *name)
275 static int pos;
276 ALCchar *ret = alcCaptureDeviceList+pos;
277 pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos, "%s", name) + 1;
278 return ret;
282 IsContext
284 Check pContext is a valid Context pointer
286 static ALCboolean IsContext(ALCcontext *pContext)
288 ALCcontext *pTempContext;
290 pTempContext = g_pContextList;
291 while (pTempContext && pTempContext != pContext)
292 pTempContext = pTempContext->next;
294 return (pTempContext ? ALC_TRUE : ALC_FALSE);
299 SetALCError
301 Store latest ALC Error
303 ALCvoid SetALCError(ALenum errorCode)
305 g_eLastContextError = errorCode;
310 SuspendContext
312 Thread-safe entry
314 ALCvoid SuspendContext(ALCcontext *pContext)
316 (void)pContext;
317 EnterCriticalSection(&g_mutex);
322 ProcessContext
324 Thread-safe exit
326 ALCvoid ProcessContext(ALCcontext *pContext)
328 (void)pContext;
329 LeaveCriticalSection(&g_mutex);
334 InitContext
336 Initialize Context variables
338 static ALvoid InitContext(ALCcontext *pContext)
340 //Initialise listener
341 pContext->Listener.Gain = 1.0f;
342 pContext->Listener.Position[0] = 0.0f;
343 pContext->Listener.Position[1] = 0.0f;
344 pContext->Listener.Position[2] = 0.0f;
345 pContext->Listener.Velocity[0] = 0.0f;
346 pContext->Listener.Velocity[1] = 0.0f;
347 pContext->Listener.Velocity[2] = 0.0f;
348 pContext->Listener.Forward[0] = 0.0f;
349 pContext->Listener.Forward[1] = 0.0f;
350 pContext->Listener.Forward[2] = -1.0f;
351 pContext->Listener.Up[0] = 0.0f;
352 pContext->Listener.Up[1] = 1.0f;
353 pContext->Listener.Up[2] = 0.0f;
355 //Validate pContext
356 pContext->LastError = AL_NO_ERROR;
357 pContext->InUse = AL_FALSE;
359 //Set output format
360 pContext->Frequency = pContext->Device->Frequency;
362 //Set globals
363 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
364 pContext->DopplerFactor = 1.0f;
365 pContext->DopplerVelocity = 1.0f;
366 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
368 pContext->lNumStereoSources = 1;
369 pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
371 strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET");
376 ExitContext
378 Clean up Context, destroy any remaining Sources
380 static ALCvoid ExitContext(ALCcontext *pContext)
382 unsigned int i;
383 ALsource *ALSource;
384 ALsource *ALTempSource;
386 #ifdef _DEBUG
387 if (pContext->SourceCount>0)
388 AL_PRINT("alcDestroyContext() %d Source(s) NOT deleted\n", pContext->SourceCount);
389 #endif
391 // Free all the Sources still remaining
392 ALSource = pContext->Source;
393 for (i = 0; i < pContext->SourceCount; i++)
395 ALTempSource = ALSource->next;
396 ALTHUNK_REMOVEENTRY(ALSource->source);
397 memset(ALSource, 0, sizeof(ALsource));
398 free(ALSource);
399 ALSource = ALTempSource;
402 //Invalidate context
403 pContext->LastError = AL_NO_ERROR;
404 pContext->InUse = AL_FALSE;
407 ///////////////////////////////////////////////////////
410 ///////////////////////////////////////////////////////
411 // ALC Functions calls
414 // This should probably move to another c file but for now ...
415 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
417 ALCboolean DeviceFound = ALC_FALSE;
418 ALCdevice *pDevice = NULL;
419 ALCint i;
421 InitAL();
423 pDevice = malloc(sizeof(ALCdevice));
424 if (pDevice)
426 if (SampleSize > 0)
428 //Initialise device structure
429 memset(pDevice, 0, sizeof(ALCdevice));
431 //Validate device
432 pDevice->InUse = AL_TRUE;
433 pDevice->IsCaptureDevice = AL_TRUE;
435 pDevice->Frequency = frequency;
436 pDevice->Format = format;
437 pDevice->Channels = aluChannelsFromFormat(format);
438 pDevice->FrameSize = aluBytesFromFormat(format) *
439 pDevice->Channels;
441 for(i = 0;BackendList[i].Init;i++)
443 pDevice->Funcs = &BackendList[i].Funcs;
444 if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
446 DeviceFound = ALC_TRUE;
447 break;
451 else
452 SetALCError(ALC_INVALID_VALUE);
454 if(!DeviceFound)
456 free(pDevice);
457 pDevice = NULL;
460 else
461 SetALCError(ALC_OUT_OF_MEMORY);
463 return pDevice;
466 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
468 ALCboolean bReturn = ALC_FALSE;
470 if ((pDevice)&&(pDevice->IsCaptureDevice))
472 ALCdevice_CloseCapture(pDevice);
473 free(pDevice);
475 bReturn = ALC_TRUE;
477 else
478 SetALCError(ALC_INVALID_DEVICE);
480 return bReturn;
483 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
485 if ((pDevice)&&(pDevice->IsCaptureDevice))
486 ALCdevice_StartCapture(pDevice);
487 else
488 SetALCError(ALC_INVALID_DEVICE);
491 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
493 if ((pDevice)&&(pDevice->IsCaptureDevice))
494 ALCdevice_StopCapture(pDevice);
495 else
496 SetALCError(ALC_INVALID_DEVICE);
499 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
501 if ((pDevice) && (pDevice->IsCaptureDevice))
502 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
503 else
504 SetALCError(ALC_INVALID_DEVICE);
508 alcGetError
510 Return last ALC generated error code
512 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
514 ALCenum errorCode;
516 (void)device;
518 errorCode = g_eLastContextError;
519 g_eLastContextError = ALC_NO_ERROR;
520 return errorCode;
525 alcSuspendContext
527 Not functional
529 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
531 // Not a lot happens here !
532 (void)pContext;
537 alcProcessContext
539 Not functional
541 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
543 // Not a lot happens here !
544 (void)pContext;
549 alcGetString
551 Returns information about the Device, and error strings
553 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
555 const ALCchar *value = NULL;
557 InitAL();
559 switch (param)
561 case ALC_NO_ERROR:
562 value = alcNoError;
563 break;
565 case ALC_INVALID_ENUM:
566 value = alcErrInvalidEnum;
567 break;
569 case ALC_INVALID_VALUE:
570 value = alcErrInvalidValue;
571 break;
573 case ALC_INVALID_DEVICE:
574 value = alcErrInvalidDevice;
575 break;
577 case ALC_INVALID_CONTEXT:
578 value = alcErrInvalidContext;
579 break;
581 case ALC_OUT_OF_MEMORY:
582 value = alcErrOutOfMemory;
583 break;
585 case ALC_DEFAULT_DEVICE_SPECIFIER:
586 value = alcDefaultDeviceSpecifier;
587 break;
589 case ALC_DEVICE_SPECIFIER:
590 if (pDevice)
591 value = pDevice->szDeviceName;
592 else
593 value = alcDeviceList;
594 break;
596 case ALC_ALL_DEVICES_SPECIFIER:
597 value = alcAllDeviceList;
598 break;
600 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
601 value = alcDefaultAllDeviceSpecifier;
602 break;
604 case ALC_CAPTURE_DEVICE_SPECIFIER:
605 if (pDevice)
606 value = pDevice->szDeviceName;
607 else
608 value = alcCaptureDeviceList;
609 break;
611 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
612 value = alcCaptureDefaultDeviceSpecifier;
613 break;
615 case ALC_EXTENSIONS:
616 value = alcExtensionList;
617 break;
619 default:
620 SetALCError(ALC_INVALID_ENUM);
621 break;
624 return value;
629 alcGetIntegerv
631 Returns information about the Device and the version of Open AL
633 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
635 InitAL();
637 if ((device)&&(device->IsCaptureDevice))
639 SuspendContext(NULL);
641 // Capture device
642 switch (param)
644 case ALC_CAPTURE_SAMPLES:
645 if ((size) && (data))
646 *data = ALCdevice_AvailableSamples(device);
647 else
648 SetALCError(ALC_INVALID_VALUE);
649 break;
651 default:
652 SetALCError(ALC_INVALID_ENUM);
653 break;
656 ProcessContext(NULL);
658 else
660 if(data)
662 // Playback Device
663 switch (param)
665 case ALC_MAJOR_VERSION:
666 if(!size)
667 SetALCError(ALC_INVALID_VALUE);
668 else
669 *data = alcMajorVersion;
670 break;
672 case ALC_MINOR_VERSION:
673 if(!size)
674 SetALCError(ALC_INVALID_VALUE);
675 else
676 *data = alcMinorVersion;
677 break;
679 case ALC_EFX_MAJOR_VERSION:
680 if(!size)
681 SetALCError(ALC_INVALID_VALUE);
682 else
683 *data = alcEFXMajorVersion;
684 break;
686 case ALC_EFX_MINOR_VERSION:
687 if(!size)
688 SetALCError(ALC_INVALID_VALUE);
689 else
690 *data = alcEFXMinorVersion;
691 break;
693 case ALC_MAX_AUXILIARY_SENDS:
694 if(!size)
695 SetALCError(ALC_INVALID_VALUE);
696 else
697 *data = 0; /* FIXME: Should be 1 or more */
698 break;
700 case ALC_ATTRIBUTES_SIZE:
701 if(!device)
702 SetALCError(ALC_INVALID_DEVICE);
703 else if(!size)
704 SetALCError(ALC_INVALID_VALUE);
705 else
706 *data = 12;
707 break;
709 case ALC_ALL_ATTRIBUTES:
710 if(!device)
711 SetALCError(ALC_INVALID_DEVICE);
712 else if (size < 7)
713 SetALCError(ALC_INVALID_VALUE);
714 else
716 int i = 0;
718 data[i++] = ALC_FREQUENCY;
719 data[i++] = device->Frequency;
721 data[i++] = ALC_REFRESH;
722 data[i++] = device->UpdateFreq;
724 data[i++] = ALC_SYNC;
725 data[i++] = ALC_FALSE;
727 SuspendContext(NULL);
728 if(device->Context && size >= 12)
730 data[i++] = ALC_MONO_SOURCES;
731 data[i++] = device->Context->lNumMonoSources;
733 data[i++] = ALC_STEREO_SOURCES;
734 data[i++] = device->Context->lNumStereoSources;
736 data[i++] = ALC_MAX_AUXILIARY_SENDS;
737 data[i++] = 0; /* FIXME */
739 ProcessContext(NULL);
741 data[i++] = 0;
743 break;
745 case ALC_FREQUENCY:
746 if(!device)
747 SetALCError(ALC_INVALID_DEVICE);
748 else if(!size)
749 SetALCError(ALC_INVALID_VALUE);
750 else
751 *data = device->Frequency;
752 break;
754 case ALC_REFRESH:
755 if(!device)
756 SetALCError(ALC_INVALID_DEVICE);
757 else if(!size)
758 SetALCError(ALC_INVALID_VALUE);
759 else
760 *data = device->UpdateFreq;
761 break;
763 case ALC_SYNC:
764 if(!device)
765 SetALCError(ALC_INVALID_DEVICE);
766 else if(!size)
767 SetALCError(ALC_INVALID_VALUE);
768 else
769 *data = ALC_FALSE;
770 break;
772 default:
773 SetALCError(ALC_INVALID_ENUM);
774 break;
777 else if(size)
778 SetALCError(ALC_INVALID_VALUE);
781 return;
786 alcIsExtensionPresent
788 Determines if there is support for a particular extension
790 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
792 ALCboolean bResult = ALC_FALSE;
793 ALsizei i = 0;
795 (void)device;
797 if (extName)
799 while(alcExtensions[i].extName &&
800 strcasecmp(alcExtensions[i].extName,extName) != 0)
801 i++;
803 if (alcExtensions[i].extName)
804 bResult = ALC_TRUE;
806 else
807 SetALCError(ALC_INVALID_VALUE);
809 return bResult;
814 alcGetProcAddress
816 Retrieves the function address for a particular extension function
818 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
820 ALCvoid *pFunction = NULL;
821 ALsizei i = 0;
823 (void)device;
825 if (funcName)
827 while(alcFunctions[i].funcName &&
828 strcmp(alcFunctions[i].funcName,funcName) != 0)
829 i++;
830 pFunction = alcFunctions[i].address;
832 else
833 SetALCError(ALC_INVALID_VALUE);
835 return pFunction;
840 alcGetEnumValue
842 Get the value for a particular ALC Enumerated Value
844 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
846 ALsizei i = 0;
847 ALCenum val;
849 (void)device;
851 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
852 i++;
853 val = enumeration[i].value;
855 if(!enumeration[i].enumName)
856 SetALCError(ALC_INVALID_VALUE);
858 return val;
863 alcCreateContext
865 Create and attach a Context to a particular Device.
867 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
869 ALCcontext *ALContext = NULL;
870 ALuint ulAttributeIndex, ulRequestedStereoSources;
872 if ((device)&&(!device->IsCaptureDevice))
874 // Reset Context Last Error code
875 g_eLastContextError = ALC_NO_ERROR;
877 // Current implementation only allows one Context per Device
878 if(!device->Context)
880 ALContext = calloc(1, sizeof(ALCcontext));
881 if(!ALContext)
883 SetALCError(ALC_OUT_OF_MEMORY);
884 return NULL;
887 ALContext->Device = device;
888 InitContext(ALContext);
890 device->Context = ALContext;
892 SuspendContext(NULL);
894 ALContext->next = g_pContextList;
895 g_pContextList = ALContext;
896 g_ulContextCount++;
898 ProcessContext(NULL);
900 // Check for Voice Count attributes
901 if (attrList)
903 ulAttributeIndex = 0;
904 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
906 if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
908 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
910 if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
911 ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
913 ALContext->lNumStereoSources = ulRequestedStereoSources;
914 ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
915 break;
918 ulAttributeIndex += 2;
922 else
924 SetALCError(ALC_INVALID_VALUE);
925 ALContext = NULL;
928 else
929 SetALCError(ALC_INVALID_DEVICE);
931 return ALContext;
936 alcDestroyContext
938 Remove a Context
940 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
942 ALCcontext **list;
944 // Lock context list
945 SuspendContext(NULL);
947 if (IsContext(context))
949 // Lock context
950 SuspendContext(context);
952 context->Device->Context = NULL;
954 list = &g_pContextList;
955 while(*list != context)
956 list = &(*list)->next;
958 *list = (*list)->next;
959 g_ulContextCount--;
961 // Unlock context
962 ProcessContext(context);
964 ExitContext(context);
966 // Free memory (MUST do this after ProcessContext)
967 memset(context, 0, sizeof(ALCcontext));
968 free(context);
970 else
971 SetALCError(ALC_INVALID_CONTEXT);
973 ProcessContext(NULL);
978 alcGetCurrentContext
980 Returns the currently active Context
982 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
984 ALCcontext *pContext = NULL;
986 SuspendContext(NULL);
988 pContext = g_pContextList;
989 while ((pContext) && (!pContext->InUse))
990 pContext = pContext->next;
992 ProcessContext(NULL);
994 return pContext;
999 alcGetContextsDevice
1001 Returns the Device that a particular Context is attached to
1003 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
1005 ALCdevice *pDevice = NULL;
1007 SuspendContext(NULL);
1008 if (IsContext(pContext))
1009 pDevice = pContext->Device;
1010 else
1011 SetALCError(ALC_INVALID_CONTEXT);
1012 ProcessContext(NULL);
1014 return pDevice;
1019 alcMakeContextCurrent
1021 Makes the given Context the active Context
1023 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
1025 ALCcontext *ALContext;
1026 ALboolean bReturn = AL_TRUE;
1028 SuspendContext(NULL);
1030 // context must be a valid Context or NULL
1031 if ((IsContext(context)) || (context == NULL))
1033 if ((ALContext=alcGetCurrentContext()))
1035 SuspendContext(ALContext);
1036 ALContext->InUse=AL_FALSE;
1037 ProcessContext(ALContext);
1040 if ((ALContext=context) && (ALContext->Device))
1042 SuspendContext(ALContext);
1043 ALContext->InUse=AL_TRUE;
1044 ProcessContext(ALContext);
1047 else
1049 SetALCError(ALC_INVALID_CONTEXT);
1050 bReturn = AL_FALSE;
1053 ProcessContext(NULL);
1055 return bReturn;
1060 alcOpenDevice
1062 Open the Device specified.
1064 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1066 ALboolean bDeviceFound = AL_FALSE;
1067 ALCdevice *device;
1068 ALint i;
1070 InitAL();
1072 device = malloc(sizeof(ALCdevice));
1073 if (device)
1075 const char *fmt;
1077 //Initialise device structure
1078 memset(device, 0, sizeof(ALCdevice));
1080 //Validate device
1081 device->InUse = AL_TRUE;
1082 device->IsCaptureDevice = AL_FALSE;
1084 //Set output format
1085 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1086 if((ALint)device->Frequency <= 0)
1087 device->Frequency = SWMIXER_OUTPUT_RATE;
1089 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1090 if(fmt[0])
1091 device->Format = alGetEnumValue(fmt);
1093 device->Channels = aluChannelsFromFormat(device->Format);
1094 if(!device->Channels)
1096 device->Format = AL_FORMAT_STEREO16;
1097 device->Channels = 2;
1098 device->FrameSize = 4;
1100 else
1101 device->FrameSize = aluBytesFromFormat(device->Format) *
1102 device->Channels;
1104 device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 0);
1105 if((ALint)device->UpdateFreq <= 0)
1106 device->UpdateFreq = 8192 * device->Frequency / 22050;
1108 // Find a playback device to open
1109 for(i = 0;BackendList[i].Init;i++)
1111 device->Funcs = &BackendList[i].Funcs;
1112 if(ALCdevice_OpenPlayback(device, deviceName))
1114 bDeviceFound = AL_TRUE;
1115 break;
1119 if (!bDeviceFound)
1121 // No suitable output device found
1122 free(device);
1123 device = NULL;
1127 return device;
1132 alcCloseDevice
1134 Close the specified Device
1136 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1138 ALCboolean bReturn = ALC_FALSE;
1140 if ((pDevice)&&(!pDevice->IsCaptureDevice))
1142 ALCdevice_ClosePlayback(pDevice);
1144 //Release device structure
1145 memset(pDevice, 0, sizeof(ALCdevice));
1146 free(pDevice);
1148 bReturn = ALC_TRUE;
1150 else
1151 SetALCError(ALC_INVALID_DEVICE);
1153 return bReturn;
1155 ///////////////////////////////////////////////////////