Implement "drivers" config option
[openal-soft.git] / Alc / ALc.c
bloba721f0de44237684a96050489f43ee08ea36bc95
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 ///////////////////////////////////////////////////////
67 ///////////////////////////////////////////////////////
68 // STRING and EXTENSIONS
70 typedef struct ALCextension_struct
72 ALCchar *extName;
73 ALvoid *address;
74 } ALCextension;
76 typedef struct ALCfunction_struct
78 ALCchar *funcName;
79 ALvoid *address;
80 } ALCfunction;
82 static ALCextension alcExtensions[] = {
83 { "ALC_ENUMERATE_ALL_EXT", (ALvoid *) NULL },
84 { "ALC_ENUMERATION_EXT", (ALvoid *) NULL },
85 { "ALC_EXT_CAPTURE", (ALvoid *) NULL },
86 { NULL, (ALvoid *) NULL }
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 // ALC Error Message
139 { (ALchar *)"ALC_NO_ERROR", ALC_NO_ERROR },
140 { (ALchar *)"ALC_INVALID_DEVICE", ALC_INVALID_DEVICE },
141 { (ALchar *)"ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT },
142 { (ALchar *)"ALC_INVALID_ENUM", ALC_INVALID_ENUM },
143 { (ALchar *)"ALC_INVALID_VALUE", ALC_INVALID_VALUE },
144 { (ALchar *)"ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY },
145 { (ALchar *)NULL, (ALenum)0 }
147 // Error strings
148 static const ALCchar alcNoError[] = "No Error";
149 static const ALCchar alcErrInvalidDevice[] = "Invalid Device";
150 static const ALCchar alcErrInvalidContext[] = "Invalid Context";
151 static const ALCchar alcErrInvalidEnum[] = "Invalid Enum";
152 static const ALCchar alcErrInvalidValue[] = "Invalid Value";
153 static const ALCchar alcErrOutOfMemory[] = "Out of Memory";
155 // Context strings
156 static ALCchar alcDeviceList[2048];
157 static ALCchar alcAllDeviceList[2048];
158 static ALCchar alcCaptureDeviceList[2048];
159 // Default is always the first in the list
160 static ALCchar *alcDefaultDeviceSpecifier = alcDeviceList;
161 static ALCchar *alcDefaultAllDeviceSpecifier = alcAllDeviceList;
162 static ALCchar *alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList;
165 static ALCchar alcExtensionList[] = "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE";
166 static ALCint alcMajorVersion = 1;
167 static ALCint alcMinorVersion = 1;
169 ///////////////////////////////////////////////////////
172 ///////////////////////////////////////////////////////
173 // Global Variables
175 // Context List
176 static ALCcontext *g_pContextList = NULL;
177 static ALCuint g_ulContextCount = 0;
179 // Context Error
180 static ALCenum g_eLastContextError = ALC_NO_ERROR;
182 ///////////////////////////////////////////////////////
185 ///////////////////////////////////////////////////////
186 // ALC Related helper functions
188 static void InitAL(void)
190 static int done = 0;
191 if(!done)
193 int i;
194 const char *devs;
196 InitializeCriticalSection(&g_mutex);
197 ALTHUNK_INIT();
198 ReadALConfig();
200 devs = GetConfigValue(NULL, "drivers", "");
201 if(devs[0])
203 int n;
204 size_t len;
205 const char *next = devs;
207 i = 0;
209 do {
210 devs = next;
211 next = strchr(devs, ',');
213 if(!devs[0] || devs[0] == ',')
214 continue;
216 len = (next ? ((size_t)(next-devs)) : strlen(devs));
217 for(n = i;BackendList[n].Init;n++)
219 if(len == strlen(BackendList[n].name) &&
220 strncmp(BackendList[n].name, devs, len) == 0)
222 const char *name = BackendList[i].name;
223 void (*Init)(BackendFuncs*) = BackendList[i].Init;
225 BackendList[i].name = BackendList[n].name;
226 BackendList[i].Init = BackendList[n].Init;
228 BackendList[n].name = name;
229 BackendList[n].Init = Init;
231 i++;
234 } while(next++);
236 BackendList[i].name = NULL;
237 BackendList[i].Init = NULL;
240 for(i = 0;BackendList[i].Init;i++)
241 BackendList[i].Init(&BackendList[i].Funcs);
242 done = 1;
246 ALCchar *AppendDeviceList(char *name)
248 static int pos;
249 ALCchar *ret = alcDeviceList+pos;
250 pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos, "%s", name) + 1;
251 return ret;
254 ALCchar *AppendAllDeviceList(char *name)
256 static int pos;
257 ALCchar *ret = alcAllDeviceList+pos;
258 pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos, "%s", name) + 1;
259 return ret;
262 ALCchar *AppendCaptureDeviceList(char *name)
264 static int pos;
265 ALCchar *ret = alcCaptureDeviceList+pos;
266 pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos, "%s", name) + 1;
267 return ret;
271 IsContext
273 Check pContext is a valid Context pointer
275 static ALCboolean IsContext(ALCcontext *pContext)
277 ALCcontext *pTempContext;
279 pTempContext = g_pContextList;
280 while (pTempContext && pTempContext != pContext)
281 pTempContext = pTempContext->next;
283 return (pTempContext ? ALC_TRUE : ALC_FALSE);
288 SetALCError
290 Store latest ALC Error
292 ALCvoid SetALCError(ALenum errorCode)
294 g_eLastContextError = errorCode;
299 SuspendContext
301 Thread-safe entry
303 ALCvoid SuspendContext(ALCcontext *pContext)
305 (void)pContext;
306 EnterCriticalSection(&g_mutex);
311 ProcessContext
313 Thread-safe exit
315 ALCvoid ProcessContext(ALCcontext *pContext)
317 (void)pContext;
318 LeaveCriticalSection(&g_mutex);
323 InitContext
325 Initialize Context variables
327 static ALvoid InitContext(ALCcontext *pContext)
329 //Initialise listener
330 pContext->Listener.Gain = 1.0f;
331 pContext->Listener.Position[0] = 0.0f;
332 pContext->Listener.Position[1] = 0.0f;
333 pContext->Listener.Position[2] = 0.0f;
334 pContext->Listener.Velocity[0] = 0.0f;
335 pContext->Listener.Velocity[1] = 0.0f;
336 pContext->Listener.Velocity[2] = 0.0f;
337 pContext->Listener.Forward[0] = 0.0f;
338 pContext->Listener.Forward[1] = 0.0f;
339 pContext->Listener.Forward[2] = -1.0f;
340 pContext->Listener.Up[0] = 0.0f;
341 pContext->Listener.Up[1] = 1.0f;
342 pContext->Listener.Up[2] = 0.0f;
344 //Validate pContext
345 pContext->LastError = AL_NO_ERROR;
346 pContext->InUse = AL_FALSE;
348 //Set output format
349 pContext->Frequency = pContext->Device->Frequency;
351 //Set globals
352 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
353 pContext->DopplerFactor = 1.0f;
354 pContext->DopplerVelocity = 1.0f;
355 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
357 pContext->lNumStereoSources = 1;
358 pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
360 strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET");
365 ExitContext
367 Clean up Context, destroy any remaining Sources
369 static ALCvoid ExitContext(ALCcontext *pContext)
371 unsigned int i;
372 ALsource *ALSource;
373 ALsource *ALTempSource;
375 #ifdef _DEBUG
376 if (pContext->SourceCount>0)
377 AL_PRINT("alcDestroyContext() %d Source(s) NOT deleted\n", pContext->SourceCount);
378 #endif
380 // Free all the Sources still remaining
381 ALSource = pContext->Source;
382 for (i = 0; i < pContext->SourceCount; i++)
384 ALTempSource = ALSource->next;
385 ALTHUNK_REMOVEENTRY(ALSource->source);
386 memset(ALSource, 0, sizeof(ALsource));
387 free(ALSource);
388 ALSource = ALTempSource;
391 //Invalidate context
392 pContext->LastError = AL_NO_ERROR;
393 pContext->InUse = AL_FALSE;
396 ///////////////////////////////////////////////////////
399 ///////////////////////////////////////////////////////
400 // ALC Functions calls
403 // This should probably move to another c file but for now ...
404 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
406 ALCboolean DeviceFound = ALC_FALSE;
407 ALCdevice *pDevice = NULL;
408 ALCint i;
410 InitAL();
412 pDevice = malloc(sizeof(ALCdevice));
413 if (pDevice)
415 if (SampleSize > 0)
417 //Initialise device structure
418 memset(pDevice, 0, sizeof(ALCdevice));
420 //Validate device
421 pDevice->InUse = AL_TRUE;
422 pDevice->IsCaptureDevice = AL_TRUE;
424 pDevice->Frequency = frequency;
425 pDevice->Format = format;
426 pDevice->Channels = aluChannelsFromFormat(format);
427 pDevice->FrameSize = aluBytesFromFormat(format) *
428 pDevice->Channels;
430 for(i = 0;BackendList[i].Init;i++)
432 pDevice->Funcs = &BackendList[i].Funcs;
433 if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
435 DeviceFound = ALC_TRUE;
436 break;
440 else
441 SetALCError(ALC_INVALID_VALUE);
443 if(!DeviceFound)
445 free(pDevice);
446 pDevice = NULL;
449 else
450 SetALCError(ALC_OUT_OF_MEMORY);
452 return pDevice;
455 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
457 ALCboolean bReturn = ALC_FALSE;
459 if ((pDevice)&&(pDevice->IsCaptureDevice))
461 ALCdevice_CloseCapture(pDevice);
462 free(pDevice);
464 bReturn = ALC_TRUE;
466 else
467 SetALCError(ALC_INVALID_DEVICE);
469 return bReturn;
472 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
474 if ((pDevice)&&(pDevice->IsCaptureDevice))
475 ALCdevice_StartCapture(pDevice);
476 else
477 SetALCError(ALC_INVALID_DEVICE);
480 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
482 if ((pDevice)&&(pDevice->IsCaptureDevice))
483 ALCdevice_StopCapture(pDevice);
484 else
485 SetALCError(ALC_INVALID_DEVICE);
488 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
490 if ((pDevice) && (pDevice->IsCaptureDevice))
491 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
492 else
493 SetALCError(ALC_INVALID_DEVICE);
497 alcGetError
499 Return last ALC generated error code
501 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
503 ALCenum errorCode;
505 (void)device;
507 errorCode = g_eLastContextError;
508 g_eLastContextError = ALC_NO_ERROR;
509 return errorCode;
514 alcSuspendContext
516 Not functional
518 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
520 // Not a lot happens here !
521 (void)pContext;
526 alcProcessContext
528 Not functional
530 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
532 // Not a lot happens here !
533 (void)pContext;
538 alcGetString
540 Returns information about the Device, and error strings
542 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
544 const ALCchar *value = NULL;
546 InitAL();
548 switch (param)
550 case ALC_NO_ERROR:
551 value = alcNoError;
552 break;
554 case ALC_INVALID_ENUM:
555 value = alcErrInvalidEnum;
556 break;
558 case ALC_INVALID_VALUE:
559 value = alcErrInvalidValue;
560 break;
562 case ALC_INVALID_DEVICE:
563 value = alcErrInvalidDevice;
564 break;
566 case ALC_INVALID_CONTEXT:
567 value = alcErrInvalidContext;
568 break;
570 case ALC_OUT_OF_MEMORY:
571 value = alcErrOutOfMemory;
572 break;
574 case ALC_DEFAULT_DEVICE_SPECIFIER:
575 value = alcDefaultDeviceSpecifier;
576 break;
578 case ALC_DEVICE_SPECIFIER:
579 if (pDevice)
580 value = pDevice->szDeviceName;
581 else
582 value = alcDeviceList;
583 break;
585 case ALC_ALL_DEVICES_SPECIFIER:
586 value = alcAllDeviceList;
587 break;
589 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
590 value = alcDefaultAllDeviceSpecifier;
591 break;
593 case ALC_CAPTURE_DEVICE_SPECIFIER:
594 if (pDevice)
595 value = pDevice->szDeviceName;
596 else
597 value = alcCaptureDeviceList;
598 break;
600 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
601 value = alcCaptureDefaultDeviceSpecifier;
602 break;
604 case ALC_EXTENSIONS:
605 value = alcExtensionList;
606 break;
608 default:
609 SetALCError(ALC_INVALID_ENUM);
610 break;
613 return value;
618 alcGetIntegerv
620 Returns information about the Device and the version of Open AL
622 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
624 InitAL();
626 if ((device)&&(device->IsCaptureDevice))
628 SuspendContext(NULL);
630 // Capture device
631 switch (param)
633 case ALC_CAPTURE_SAMPLES:
634 if ((size) && (data))
635 *data = ALCdevice_AvailableSamples(device);
636 else
637 SetALCError(ALC_INVALID_VALUE);
638 break;
640 default:
641 SetALCError(ALC_INVALID_ENUM);
642 break;
645 ProcessContext(NULL);
647 else
649 if(data)
651 // Playback Device
652 switch (param)
654 case ALC_MAJOR_VERSION:
655 if(!size)
656 SetALCError(ALC_INVALID_VALUE);
657 else
658 *data = alcMajorVersion;
659 break;
661 case ALC_MINOR_VERSION:
662 if(!size)
663 SetALCError(ALC_INVALID_VALUE);
664 else
665 *data = alcMinorVersion;
666 break;
668 case ALC_ATTRIBUTES_SIZE:
669 if(!device)
670 SetALCError(ALC_INVALID_DEVICE);
671 else if(!size)
672 SetALCError(ALC_INVALID_VALUE);
673 else
674 *data = 11;
675 break;
677 case ALC_ALL_ATTRIBUTES:
678 if(!device)
679 SetALCError(ALC_INVALID_DEVICE);
680 else if (size < 7)
681 SetALCError(ALC_INVALID_VALUE);
682 else
684 int i = 0;
686 data[i++] = ALC_FREQUENCY;
687 data[i++] = device->Frequency;
689 data[i++] = ALC_REFRESH;
690 data[i++] = device->UpdateFreq;
692 data[i++] = ALC_SYNC;
693 data[i++] = ALC_FALSE;
695 SuspendContext(NULL);
696 if(device->Context && size >= 11)
698 data[i++] = ALC_MONO_SOURCES;
699 data[i++] = device->Context->lNumMonoSources;
701 data[i++] = ALC_STEREO_SOURCES;
702 data[i++] = device->Context->lNumStereoSources;
704 ProcessContext(NULL);
706 data[i++] = 0;
708 break;
710 case ALC_FREQUENCY:
711 if(!device)
712 SetALCError(ALC_INVALID_DEVICE);
713 else if(!size)
714 SetALCError(ALC_INVALID_VALUE);
715 else
716 *data = device->Frequency;
717 break;
719 case ALC_REFRESH:
720 if(!device)
721 SetALCError(ALC_INVALID_DEVICE);
722 else if(!size)
723 SetALCError(ALC_INVALID_VALUE);
724 else
725 *data = device->UpdateFreq;
726 break;
728 case ALC_SYNC:
729 if(!device)
730 SetALCError(ALC_INVALID_DEVICE);
731 else if(!size)
732 SetALCError(ALC_INVALID_VALUE);
733 else
734 *data = ALC_FALSE;
735 break;
737 default:
738 SetALCError(ALC_INVALID_ENUM);
739 break;
742 else if(size)
743 SetALCError(ALC_INVALID_VALUE);
746 return;
751 alcIsExtensionPresent
753 Determines if there is support for a particular extension
755 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
757 ALCboolean bResult = ALC_FALSE;
758 ALsizei i = 0;
760 (void)device;
762 if (extName)
764 while(alcExtensions[i].extName &&
765 strcasecmp(alcExtensions[i].extName,extName) != 0)
766 i++;
768 if (alcExtensions[i].extName)
769 bResult = ALC_TRUE;
771 else
772 SetALCError(ALC_INVALID_VALUE);
774 return bResult;
779 alcGetProcAddress
781 Retrieves the function address for a particular extension function
783 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
785 ALCvoid *pFunction = NULL;
786 ALsizei i = 0;
788 (void)device;
790 if (funcName)
792 while(alcFunctions[i].funcName &&
793 strcmp(alcFunctions[i].funcName,funcName) != 0)
794 i++;
795 pFunction = alcFunctions[i].address;
797 else
798 SetALCError(ALC_INVALID_VALUE);
800 return pFunction;
805 alcGetEnumValue
807 Get the value for a particular ALC Enumerated Value
809 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
811 ALsizei i = 0;
812 ALCenum val;
814 (void)device;
816 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
817 i++;
818 val = enumeration[i].value;
820 if(!enumeration[i].enumName)
821 SetALCError(ALC_INVALID_VALUE);
823 return val;
828 alcCreateContext
830 Create and attach a Context to a particular Device.
832 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
834 ALCcontext *ALContext = NULL;
835 ALuint ulAttributeIndex, ulRequestedStereoSources;
837 if ((device)&&(!device->IsCaptureDevice))
839 // Reset Context Last Error code
840 g_eLastContextError = ALC_NO_ERROR;
842 // Current implementation only allows one Context per Device
843 if(!device->Context)
845 ALContext = calloc(1, sizeof(ALCcontext));
846 if(!ALContext)
848 SetALCError(ALC_OUT_OF_MEMORY);
849 return NULL;
852 ALContext->Device = device;
853 InitContext(ALContext);
855 device->Context = ALContext;
857 SuspendContext(NULL);
859 ALContext->next = g_pContextList;
860 g_pContextList = ALContext;
861 g_ulContextCount++;
863 ProcessContext(NULL);
865 // Check for Voice Count attributes
866 if (attrList)
868 ulAttributeIndex = 0;
869 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
871 if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
873 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
875 if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
876 ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
878 ALContext->lNumStereoSources = ulRequestedStereoSources;
879 ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
880 break;
883 ulAttributeIndex += 2;
887 else
889 SetALCError(ALC_INVALID_VALUE);
890 ALContext = NULL;
893 else
894 SetALCError(ALC_INVALID_DEVICE);
896 return ALContext;
901 alcDestroyContext
903 Remove a Context
905 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
907 ALCcontext **list;
909 // Lock context list
910 SuspendContext(NULL);
912 if (IsContext(context))
914 // Lock context
915 SuspendContext(context);
917 context->Device->Context = NULL;
919 list = &g_pContextList;
920 while(*list != context)
921 list = &(*list)->next;
923 *list = (*list)->next;
924 g_ulContextCount--;
926 // Unlock context
927 ProcessContext(context);
929 ExitContext(context);
931 // Free memory (MUST do this after ProcessContext)
932 memset(context, 0, sizeof(ALCcontext));
933 free(context);
935 else
936 SetALCError(ALC_INVALID_CONTEXT);
938 ProcessContext(NULL);
943 alcGetCurrentContext
945 Returns the currently active Context
947 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
949 ALCcontext *pContext = NULL;
951 SuspendContext(NULL);
953 pContext = g_pContextList;
954 while ((pContext) && (!pContext->InUse))
955 pContext = pContext->next;
957 ProcessContext(NULL);
959 return pContext;
964 alcGetContextsDevice
966 Returns the Device that a particular Context is attached to
968 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
970 ALCdevice *pDevice = NULL;
972 SuspendContext(NULL);
973 if (IsContext(pContext))
974 pDevice = pContext->Device;
975 else
976 SetALCError(ALC_INVALID_CONTEXT);
977 ProcessContext(NULL);
979 return pDevice;
984 alcMakeContextCurrent
986 Makes the given Context the active Context
988 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
990 ALCcontext *ALContext;
991 ALboolean bReturn = AL_TRUE;
993 SuspendContext(NULL);
995 // context must be a valid Context or NULL
996 if ((IsContext(context)) || (context == NULL))
998 if ((ALContext=alcGetCurrentContext()))
1000 SuspendContext(ALContext);
1001 ALContext->InUse=AL_FALSE;
1002 ProcessContext(ALContext);
1005 if ((ALContext=context) && (ALContext->Device))
1007 SuspendContext(ALContext);
1008 ALContext->InUse=AL_TRUE;
1009 ProcessContext(ALContext);
1012 else
1014 SetALCError(ALC_INVALID_CONTEXT);
1015 bReturn = AL_FALSE;
1018 ProcessContext(NULL);
1020 return bReturn;
1025 alcOpenDevice
1027 Open the Device specified.
1029 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1031 ALboolean bDeviceFound = AL_FALSE;
1032 ALCdevice *device;
1033 ALint i;
1035 InitAL();
1037 device = malloc(sizeof(ALCdevice));
1038 if (device)
1040 const char *fmt;
1042 //Initialise device structure
1043 memset(device, 0, sizeof(ALCdevice));
1045 //Validate device
1046 device->InUse = AL_TRUE;
1047 device->IsCaptureDevice = AL_FALSE;
1049 //Set output format
1050 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1051 if((ALint)device->Frequency <= 0)
1052 device->Frequency = SWMIXER_OUTPUT_RATE;
1054 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1055 if(fmt[0])
1056 device->Format = alGetEnumValue(fmt);
1058 device->Channels = aluChannelsFromFormat(device->Format);
1059 if(!device->Channels)
1061 device->Format = AL_FORMAT_STEREO16;
1062 device->Channels = 2;
1063 device->FrameSize = 4;
1065 else
1066 device->FrameSize = aluBytesFromFormat(device->Format) *
1067 device->Channels;
1069 device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 0);
1070 if((ALint)device->UpdateFreq <= 0)
1071 device->UpdateFreq = 8192 * device->Frequency / 22050;
1073 // Find a playback device to open
1074 for(i = 0;BackendList[i].Init;i++)
1076 device->Funcs = &BackendList[i].Funcs;
1077 if(ALCdevice_OpenPlayback(device, deviceName))
1079 bDeviceFound = AL_TRUE;
1080 break;
1084 if (!bDeviceFound)
1086 // No suitable output device found
1087 free(device);
1088 device = NULL;
1092 return device;
1097 alcCloseDevice
1099 Close the specified Device
1101 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1103 ALCboolean bReturn = ALC_FALSE;
1105 if ((pDevice)&&(!pDevice->IsCaptureDevice))
1107 ALCdevice_ClosePlayback(pDevice);
1109 //Release device structure
1110 memset(pDevice, 0, sizeof(ALCdevice));
1111 free(pDevice);
1113 bReturn = ALC_TRUE;
1115 else
1116 SetALCError(ALC_INVALID_DEVICE);
1118 return bReturn;
1120 ///////////////////////////////////////////////////////