Allow empty device specifiers when opening; treat them like NULL
[openal-soft.git] / Alc / ALc.c
blobfa591174a918fc72d858cb2103eef48f8ae1050e
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 _alDebug[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(&_alMutex);
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(&_alMutex);
311 ProcessContext
313 Thread-safe exit
315 ALCvoid ProcessContext(ALCcontext *pContext)
317 (void)pContext;
318 LeaveCriticalSection(&_alMutex);
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 if(deviceName && !deviceName[0])
413 deviceName = NULL;
415 pDevice = malloc(sizeof(ALCdevice));
416 if (pDevice)
418 if (SampleSize > 0)
420 //Initialise device structure
421 memset(pDevice, 0, sizeof(ALCdevice));
423 //Validate device
424 pDevice->InUse = AL_TRUE;
425 pDevice->IsCaptureDevice = AL_TRUE;
427 pDevice->Frequency = frequency;
428 pDevice->Format = format;
429 pDevice->Channels = aluChannelsFromFormat(format);
430 pDevice->FrameSize = aluBytesFromFormat(format) *
431 pDevice->Channels;
433 for(i = 0;BackendList[i].Init;i++)
435 pDevice->Funcs = &BackendList[i].Funcs;
436 if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
438 DeviceFound = ALC_TRUE;
439 break;
443 else
444 SetALCError(ALC_INVALID_VALUE);
446 if(!DeviceFound)
448 free(pDevice);
449 pDevice = NULL;
452 else
453 SetALCError(ALC_OUT_OF_MEMORY);
455 return pDevice;
458 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
460 ALCboolean bReturn = ALC_FALSE;
462 if ((pDevice)&&(pDevice->IsCaptureDevice))
464 ALCdevice_CloseCapture(pDevice);
465 free(pDevice);
467 bReturn = ALC_TRUE;
469 else
470 SetALCError(ALC_INVALID_DEVICE);
472 return bReturn;
475 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
477 if ((pDevice)&&(pDevice->IsCaptureDevice))
478 ALCdevice_StartCapture(pDevice);
479 else
480 SetALCError(ALC_INVALID_DEVICE);
483 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
485 if ((pDevice)&&(pDevice->IsCaptureDevice))
486 ALCdevice_StopCapture(pDevice);
487 else
488 SetALCError(ALC_INVALID_DEVICE);
491 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
493 if ((pDevice) && (pDevice->IsCaptureDevice))
494 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
495 else
496 SetALCError(ALC_INVALID_DEVICE);
500 alcGetError
502 Return last ALC generated error code
504 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
506 ALCenum errorCode;
508 (void)device;
510 errorCode = g_eLastContextError;
511 g_eLastContextError = ALC_NO_ERROR;
512 return errorCode;
517 alcSuspendContext
519 Not functional
521 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
523 // Not a lot happens here !
524 (void)pContext;
529 alcProcessContext
531 Not functional
533 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
535 // Not a lot happens here !
536 (void)pContext;
541 alcGetString
543 Returns information about the Device, and error strings
545 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
547 const ALCchar *value = NULL;
549 InitAL();
551 switch (param)
553 case ALC_NO_ERROR:
554 value = alcNoError;
555 break;
557 case ALC_INVALID_ENUM:
558 value = alcErrInvalidEnum;
559 break;
561 case ALC_INVALID_VALUE:
562 value = alcErrInvalidValue;
563 break;
565 case ALC_INVALID_DEVICE:
566 value = alcErrInvalidDevice;
567 break;
569 case ALC_INVALID_CONTEXT:
570 value = alcErrInvalidContext;
571 break;
573 case ALC_OUT_OF_MEMORY:
574 value = alcErrOutOfMemory;
575 break;
577 case ALC_DEFAULT_DEVICE_SPECIFIER:
578 value = alcDefaultDeviceSpecifier;
579 break;
581 case ALC_DEVICE_SPECIFIER:
582 if (pDevice)
583 value = pDevice->szDeviceName;
584 else
585 value = alcDeviceList;
586 break;
588 case ALC_ALL_DEVICES_SPECIFIER:
589 value = alcAllDeviceList;
590 break;
592 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
593 value = alcDefaultAllDeviceSpecifier;
594 break;
596 case ALC_CAPTURE_DEVICE_SPECIFIER:
597 if (pDevice)
598 value = pDevice->szDeviceName;
599 else
600 value = alcCaptureDeviceList;
601 break;
603 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
604 value = alcCaptureDefaultDeviceSpecifier;
605 break;
607 case ALC_EXTENSIONS:
608 value = alcExtensionList;
609 break;
611 default:
612 SetALCError(ALC_INVALID_ENUM);
613 break;
616 return value;
621 alcGetIntegerv
623 Returns information about the Device and the version of Open AL
625 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
627 InitAL();
629 if ((device)&&(device->IsCaptureDevice))
631 SuspendContext(NULL);
633 // Capture device
634 switch (param)
636 case ALC_CAPTURE_SAMPLES:
637 if ((size) && (data))
638 *data = ALCdevice_AvailableSamples(device);
639 else
640 SetALCError(ALC_INVALID_VALUE);
641 break;
643 default:
644 SetALCError(ALC_INVALID_ENUM);
645 break;
648 ProcessContext(NULL);
650 else
652 if(data)
654 // Playback Device
655 switch (param)
657 case ALC_MAJOR_VERSION:
658 if(!size)
659 SetALCError(ALC_INVALID_VALUE);
660 else
661 *data = alcMajorVersion;
662 break;
664 case ALC_MINOR_VERSION:
665 if(!size)
666 SetALCError(ALC_INVALID_VALUE);
667 else
668 *data = alcMinorVersion;
669 break;
671 case ALC_ATTRIBUTES_SIZE:
672 if(!device)
673 SetALCError(ALC_INVALID_DEVICE);
674 else if(!size)
675 SetALCError(ALC_INVALID_VALUE);
676 else
677 *data = 11;
678 break;
680 case ALC_ALL_ATTRIBUTES:
681 if(!device)
682 SetALCError(ALC_INVALID_DEVICE);
683 else if (size < 7)
684 SetALCError(ALC_INVALID_VALUE);
685 else
687 int i = 0;
689 data[i++] = ALC_FREQUENCY;
690 data[i++] = device->Frequency;
692 data[i++] = ALC_REFRESH;
693 data[i++] = device->UpdateFreq;
695 data[i++] = ALC_SYNC;
696 data[i++] = ALC_FALSE;
698 SuspendContext(NULL);
699 if(device->Context && size >= 11)
701 data[i++] = ALC_MONO_SOURCES;
702 data[i++] = device->Context->lNumMonoSources;
704 data[i++] = ALC_STEREO_SOURCES;
705 data[i++] = device->Context->lNumStereoSources;
707 ProcessContext(NULL);
709 data[i++] = 0;
711 break;
713 case ALC_FREQUENCY:
714 if(!device)
715 SetALCError(ALC_INVALID_DEVICE);
716 else if(!size)
717 SetALCError(ALC_INVALID_VALUE);
718 else
719 *data = device->Frequency;
720 break;
722 case ALC_REFRESH:
723 if(!device)
724 SetALCError(ALC_INVALID_DEVICE);
725 else if(!size)
726 SetALCError(ALC_INVALID_VALUE);
727 else
728 *data = device->UpdateFreq;
729 break;
731 case ALC_SYNC:
732 if(!device)
733 SetALCError(ALC_INVALID_DEVICE);
734 else if(!size)
735 SetALCError(ALC_INVALID_VALUE);
736 else
737 *data = ALC_FALSE;
738 break;
740 default:
741 SetALCError(ALC_INVALID_ENUM);
742 break;
745 else if(size)
746 SetALCError(ALC_INVALID_VALUE);
749 return;
754 alcIsExtensionPresent
756 Determines if there is support for a particular extension
758 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
760 ALCboolean bResult = ALC_FALSE;
761 ALsizei i = 0;
763 (void)device;
765 if (extName)
767 while(alcExtensions[i].extName &&
768 strcasecmp(alcExtensions[i].extName,extName) != 0)
769 i++;
771 if (alcExtensions[i].extName)
772 bResult = ALC_TRUE;
774 else
775 SetALCError(ALC_INVALID_VALUE);
777 return bResult;
782 alcGetProcAddress
784 Retrieves the function address for a particular extension function
786 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
788 ALCvoid *pFunction = NULL;
789 ALsizei i = 0;
791 (void)device;
793 if (funcName)
795 while(alcFunctions[i].funcName &&
796 strcmp(alcFunctions[i].funcName,funcName) != 0)
797 i++;
798 pFunction = alcFunctions[i].address;
800 else
801 SetALCError(ALC_INVALID_VALUE);
803 return pFunction;
808 alcGetEnumValue
810 Get the value for a particular ALC Enumerated Value
812 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
814 ALsizei i = 0;
815 ALCenum val;
817 (void)device;
819 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
820 i++;
821 val = enumeration[i].value;
823 if(!enumeration[i].enumName)
824 SetALCError(ALC_INVALID_VALUE);
826 return val;
831 alcCreateContext
833 Create and attach a Context to a particular Device.
835 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
837 ALCcontext *ALContext = NULL;
838 ALuint ulAttributeIndex, ulRequestedStereoSources;
840 if ((device)&&(!device->IsCaptureDevice))
842 // Reset Context Last Error code
843 g_eLastContextError = ALC_NO_ERROR;
845 // Current implementation only allows one Context per Device
846 if(!device->Context)
848 ALContext = calloc(1, sizeof(ALCcontext));
849 if(!ALContext)
851 SetALCError(ALC_OUT_OF_MEMORY);
852 return NULL;
855 ALContext->Device = device;
856 InitContext(ALContext);
858 device->Context = ALContext;
860 SuspendContext(NULL);
862 ALContext->next = g_pContextList;
863 g_pContextList = ALContext;
864 g_ulContextCount++;
866 ProcessContext(NULL);
868 // Check for Voice Count attributes
869 if (attrList)
871 ulAttributeIndex = 0;
872 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
874 if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
876 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
878 if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
879 ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
881 ALContext->lNumStereoSources = ulRequestedStereoSources;
882 ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
883 break;
886 ulAttributeIndex += 2;
890 else
892 SetALCError(ALC_INVALID_VALUE);
893 ALContext = NULL;
896 else
897 SetALCError(ALC_INVALID_DEVICE);
899 return ALContext;
904 alcDestroyContext
906 Remove a Context
908 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
910 ALCcontext **list;
912 // Lock context list
913 SuspendContext(NULL);
915 if (IsContext(context))
917 // Lock context
918 SuspendContext(context);
920 context->Device->Context = NULL;
922 list = &g_pContextList;
923 while(*list != context)
924 list = &(*list)->next;
926 *list = (*list)->next;
927 g_ulContextCount--;
929 // Unlock context
930 ProcessContext(context);
932 ExitContext(context);
934 // Free memory (MUST do this after ProcessContext)
935 memset(context, 0, sizeof(ALCcontext));
936 free(context);
938 else
939 SetALCError(ALC_INVALID_CONTEXT);
941 ProcessContext(NULL);
946 alcGetCurrentContext
948 Returns the currently active Context
950 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
952 ALCcontext *pContext = NULL;
954 SuspendContext(NULL);
956 pContext = g_pContextList;
957 while ((pContext) && (!pContext->InUse))
958 pContext = pContext->next;
960 ProcessContext(NULL);
962 return pContext;
967 alcGetContextsDevice
969 Returns the Device that a particular Context is attached to
971 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
973 ALCdevice *pDevice = NULL;
975 SuspendContext(NULL);
976 if (IsContext(pContext))
977 pDevice = pContext->Device;
978 else
979 SetALCError(ALC_INVALID_CONTEXT);
980 ProcessContext(NULL);
982 return pDevice;
987 alcMakeContextCurrent
989 Makes the given Context the active Context
991 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
993 ALCcontext *ALContext;
994 ALboolean bReturn = AL_TRUE;
996 SuspendContext(NULL);
998 // context must be a valid Context or NULL
999 if ((IsContext(context)) || (context == NULL))
1001 if ((ALContext=alcGetCurrentContext()))
1003 SuspendContext(ALContext);
1004 ALContext->InUse=AL_FALSE;
1005 ProcessContext(ALContext);
1008 if ((ALContext=context) && (ALContext->Device))
1010 SuspendContext(ALContext);
1011 ALContext->InUse=AL_TRUE;
1012 ProcessContext(ALContext);
1015 else
1017 SetALCError(ALC_INVALID_CONTEXT);
1018 bReturn = AL_FALSE;
1021 ProcessContext(NULL);
1023 return bReturn;
1028 alcOpenDevice
1030 Open the Device specified.
1032 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1034 ALboolean bDeviceFound = AL_FALSE;
1035 ALCdevice *device;
1036 ALint i;
1038 InitAL();
1040 if(deviceName && !deviceName[0])
1041 deviceName = NULL;
1043 device = malloc(sizeof(ALCdevice));
1044 if (device)
1046 const char *fmt;
1048 //Initialise device structure
1049 memset(device, 0, sizeof(ALCdevice));
1051 //Validate device
1052 device->InUse = AL_TRUE;
1053 device->IsCaptureDevice = AL_FALSE;
1055 //Set output format
1056 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1057 if((ALint)device->Frequency <= 0)
1058 device->Frequency = SWMIXER_OUTPUT_RATE;
1060 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1061 if(fmt[0])
1062 device->Format = alGetEnumValue(fmt);
1064 device->Channels = aluChannelsFromFormat(device->Format);
1065 if(!device->Channels)
1067 device->Format = AL_FORMAT_STEREO16;
1068 device->Channels = 2;
1069 device->FrameSize = 4;
1071 else
1072 device->FrameSize = aluBytesFromFormat(device->Format) *
1073 device->Channels;
1075 device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 0);
1076 if((ALint)device->UpdateFreq <= 0)
1077 device->UpdateFreq = 8192 * device->Frequency / 22050;
1079 // Find a playback device to open
1080 for(i = 0;BackendList[i].Init;i++)
1082 device->Funcs = &BackendList[i].Funcs;
1083 if(ALCdevice_OpenPlayback(device, deviceName))
1085 bDeviceFound = AL_TRUE;
1086 break;
1090 if (!bDeviceFound)
1092 // No suitable output device found
1093 free(device);
1094 device = NULL;
1098 return device;
1103 alcCloseDevice
1105 Close the specified Device
1107 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1109 ALCboolean bReturn = ALC_FALSE;
1111 if ((pDevice)&&(!pDevice->IsCaptureDevice))
1113 ALCdevice_ClosePlayback(pDevice);
1115 //Release device structure
1116 memset(pDevice, 0, sizeof(ALCdevice));
1117 free(pDevice);
1119 bReturn = ALC_TRUE;
1121 else
1122 SetALCError(ALC_INVALID_DEVICE);
1124 return bReturn;
1126 ///////////////////////////////////////////////////////