Use an AL_PRINT macro for printing lib messages/errors to the console
[openal-soft/openbsd.git] / Alc / ALc.c
blob2b1c4ba6bd93cb8889f92f87d71617948e0b0786
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 ///////////////////////////////////////////////////////
42 // FUNCTION PROTOTYPES
44 void alc_alsa_init(BackendFuncs *func_list);
45 void alc_oss_init(BackendFuncs *func_list);
46 void alcDSoundInit(BackendFuncs *func_list);
47 void alcWinMMInit(BackendFuncs *FuncList);
49 #define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
50 struct {
51 const char *name;
52 void (*Init)(BackendFuncs*);
53 BackendFuncs Funcs;
54 } BackendList[] = {
55 #ifdef HAVE_ALSA
56 { "alsa", alc_alsa_init, EmptyFuncs },
57 #endif
58 #ifdef HAVE_OSS
59 { "oss", alc_oss_init, EmptyFuncs },
60 #endif
61 #ifdef HAVE_DSOUND
62 { "dsound", alcDSoundInit, EmptyFuncs },
63 #endif
64 #ifdef HAVE_WINMM
65 { "winmm", alcWinMMInit, EmptyFuncs },
66 #endif
68 { NULL, NULL, EmptyFuncs }
70 #undef EmptyFuncs
72 ///////////////////////////////////////////////////////
75 ///////////////////////////////////////////////////////
76 // STRING and EXTENSIONS
78 typedef struct ALCextension_struct
80 ALCchar *extName;
81 ALvoid *address;
82 } ALCextension;
84 typedef struct ALCfunction_struct
86 ALCchar *funcName;
87 ALvoid *address;
88 } ALCfunction;
90 static ALCextension alcExtensions[] = {
91 { "ALC_ENUMERATE_ALL_EXT", (ALvoid *) NULL },
92 { "ALC_ENUMERATION_EXT", (ALvoid *) NULL },
93 { "ALC_EXT_CAPTURE", (ALvoid *) NULL },
94 { NULL, (ALvoid *) NULL }
97 static ALCfunction alcFunctions[] = {
98 { "alcCreateContext", (ALvoid *) alcCreateContext },
99 { "alcMakeContextCurrent", (ALvoid *) alcMakeContextCurrent },
100 { "alcProcessContext", (ALvoid *) alcProcessContext },
101 { "alcSuspendContext", (ALvoid *) alcSuspendContext },
102 { "alcDestroyContext", (ALvoid *) alcDestroyContext },
103 { "alcGetCurrentContext", (ALvoid *) alcGetCurrentContext },
104 { "alcGetContextsDevice", (ALvoid *) alcGetContextsDevice },
105 { "alcOpenDevice", (ALvoid *) alcOpenDevice },
106 { "alcCloseDevice", (ALvoid *) alcCloseDevice },
107 { "alcGetError", (ALvoid *) alcGetError },
108 { "alcIsExtensionPresent", (ALvoid *) alcIsExtensionPresent },
109 { "alcGetProcAddress", (ALvoid *) alcGetProcAddress },
110 { "alcGetEnumValue", (ALvoid *) alcGetEnumValue },
111 { "alcGetString", (ALvoid *) alcGetString },
112 { "alcGetIntegerv", (ALvoid *) alcGetIntegerv },
113 { "alcCaptureOpenDevice", (ALvoid *) alcCaptureOpenDevice },
114 { "alcCaptureCloseDevice", (ALvoid *) alcCaptureCloseDevice },
115 { "alcCaptureStart", (ALvoid *) alcCaptureStart },
116 { "alcCaptureStop", (ALvoid *) alcCaptureStop },
117 { "alcCaptureSamples", (ALvoid *) alcCaptureSamples },
118 { NULL, (ALvoid *) NULL }
121 static ALenums enumeration[]={
122 // Types
123 { (ALchar *)"ALC_INVALID", ALC_INVALID },
124 { (ALchar *)"ALC_FALSE", ALC_FALSE },
125 { (ALchar *)"ALC_TRUE", ALC_TRUE },
127 // ALC Properties
128 { (ALchar *)"ALC_MAJOR_VERSION", ALC_MAJOR_VERSION },
129 { (ALchar *)"ALC_MINOR_VERSION", ALC_MINOR_VERSION },
130 { (ALchar *)"ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE },
131 { (ALchar *)"ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES },
132 { (ALchar *)"ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER },
133 { (ALchar *)"ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER },
134 { (ALchar *)"ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER },
135 { (ALchar *)"ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER },
136 { (ALchar *)"ALC_EXTENSIONS", ALC_EXTENSIONS },
137 { (ALchar *)"ALC_FREQUENCY", ALC_FREQUENCY },
138 { (ALchar *)"ALC_REFRESH", ALC_REFRESH },
139 { (ALchar *)"ALC_SYNC", ALC_SYNC },
140 { (ALchar *)"ALC_MONO_SOURCES", ALC_MONO_SOURCES },
141 { (ALchar *)"ALC_STEREO_SOURCES", ALC_STEREO_SOURCES },
142 { (ALchar *)"ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER },
143 { (ALchar *)"ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER },
144 { (ALchar *)"ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES },
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 ///////////////////////////////////////////////////////
180 ///////////////////////////////////////////////////////
181 // Global Variables
183 // Critical Section data
184 extern CRITICAL_SECTION g_mutex;
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;
206 InitializeCriticalSection(&g_mutex);
207 ALTHUNK_INIT();
208 ReadALConfig();
210 for(i = 0;BackendList[i].Init;i++)
211 BackendList[i].Init(&BackendList[i].Funcs);
212 done = 1;
216 ALCchar *AppendDeviceList(char *name)
218 static int pos;
219 ALCchar *ret = alcDeviceList+pos;
220 pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos, "%s", name) + 1;
221 return ret;
224 ALCchar *AppendAllDeviceList(char *name)
226 static int pos;
227 ALCchar *ret = alcAllDeviceList+pos;
228 pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos, "%s", name) + 1;
229 return ret;
232 ALCchar *AppendCaptureDeviceList(char *name)
234 static int pos;
235 ALCchar *ret = alcCaptureDeviceList+pos;
236 pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos, "%s", name) + 1;
237 return ret;
241 IsContext
243 Check pContext is a valid Context pointer
245 ALCboolean IsContext(ALCcontext *pContext)
247 ALCcontext *pTempContext;
249 pTempContext = g_pContextList;
250 while (pTempContext && pTempContext != pContext)
251 pTempContext = pTempContext->next;
253 return (pTempContext ? ALC_TRUE : ALC_FALSE);
258 SetALCError
260 Store latest ALC Error
262 ALCvoid SetALCError(ALenum errorCode)
264 g_eLastContextError = errorCode;
269 SuspendContext
271 Thread-safe entry
273 ALCvoid SuspendContext(ALCcontext *pContext)
275 (void)pContext;
276 EnterCriticalSection(&g_mutex);
281 ProcessContext
283 Thread-safe exit
285 ALCvoid ProcessContext(ALCcontext *pContext)
287 (void)pContext;
288 LeaveCriticalSection(&g_mutex);
293 InitContext
295 Initialize Context variables
297 static ALvoid InitContext(ALCcontext *pContext)
299 //Initialise listener
300 pContext->Listener.Gain = 1.0f;
301 pContext->Listener.Position[0] = 0.0f;
302 pContext->Listener.Position[1] = 0.0f;
303 pContext->Listener.Position[2] = 0.0f;
304 pContext->Listener.Velocity[0] = 0.0f;
305 pContext->Listener.Velocity[1] = 0.0f;
306 pContext->Listener.Velocity[2] = 0.0f;
307 pContext->Listener.Forward[0] = 0.0f;
308 pContext->Listener.Forward[1] = 0.0f;
309 pContext->Listener.Forward[2] = -1.0f;
310 pContext->Listener.Up[0] = 0.0f;
311 pContext->Listener.Up[1] = 1.0f;
312 pContext->Listener.Up[2] = 0.0f;
314 //Validate pContext
315 pContext->LastError = AL_NO_ERROR;
316 pContext->InUse = AL_FALSE;
318 //Set output format
319 pContext->Frequency = pContext->Device->Frequency;
321 //Set globals
322 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
323 pContext->DopplerFactor = 1.0f;
324 pContext->DopplerVelocity = 1.0f;
325 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
327 pContext->lNumStereoSources = 1;
328 pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
330 strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET");
335 ExitContext
337 Clean up Context, destroy any remaining Sources
339 static ALCvoid ExitContext(ALCcontext *pContext)
341 unsigned int i;
342 ALsource *ALSource;
343 ALsource *ALTempSource;
345 #ifdef _DEBUG
346 if (pContext->SourceCount>0)
347 AL_PRINT("alcDestroyContext() %d Source(s) NOT deleted\n", pContext->SourceCount);
348 #endif
350 // Free all the Sources still remaining
351 ALSource = pContext->Source;
352 for (i = 0; i < pContext->SourceCount; i++)
354 ALTempSource = ALSource->next;
355 ALTHUNK_REMOVEENTRY(ALSource->source);
356 memset(ALSource, 0, sizeof(ALsource));
357 free(ALSource);
358 ALSource = ALTempSource;
361 //Invalidate context
362 pContext->LastError = AL_NO_ERROR;
363 pContext->InUse = AL_FALSE;
366 ///////////////////////////////////////////////////////
369 ///////////////////////////////////////////////////////
370 // ALC Functions calls
373 // This should probably move to another c file but for now ...
374 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
376 ALCboolean DeviceFound = ALC_FALSE;
377 ALCdevice *pDevice = NULL;
378 ALCint i;
380 InitAL();
382 pDevice = malloc(sizeof(ALCdevice));
383 if (pDevice)
385 if (SampleSize > 0)
387 //Initialise device structure
388 memset(pDevice, 0, sizeof(ALCdevice));
390 //Validate device
391 pDevice->InUse = AL_TRUE;
392 pDevice->IsCaptureDevice = AL_TRUE;
394 pDevice->Frequency = frequency;
395 pDevice->Format = format;
396 pDevice->Channels = aluChannelsFromFormat(format);
397 pDevice->FrameSize = aluBytesFromFormat(format) *
398 pDevice->Channels;
400 for(i = 0;BackendList[i].Init;i++)
402 pDevice->Funcs = &BackendList[i].Funcs;
403 if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
405 DeviceFound = ALC_TRUE;
406 break;
410 else
411 SetALCError(ALC_INVALID_VALUE);
413 if(!DeviceFound)
415 free(pDevice);
416 pDevice = NULL;
419 else
420 SetALCError(ALC_OUT_OF_MEMORY);
422 return pDevice;
425 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
427 ALCboolean bReturn = ALC_FALSE;
429 if ((pDevice)&&(pDevice->IsCaptureDevice))
431 ALCdevice_CloseCapture(pDevice);
432 free(pDevice);
434 bReturn = ALC_TRUE;
436 else
437 SetALCError(ALC_INVALID_DEVICE);
439 return bReturn;
442 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
444 if ((pDevice)&&(pDevice->IsCaptureDevice))
445 ALCdevice_StartCapture(pDevice);
446 else
447 SetALCError(ALC_INVALID_DEVICE);
450 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
452 if ((pDevice)&&(pDevice->IsCaptureDevice))
453 ALCdevice_StopCapture(pDevice);
454 else
455 SetALCError(ALC_INVALID_DEVICE);
458 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
460 if ((pDevice) && (pDevice->IsCaptureDevice))
461 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
462 else
463 SetALCError(ALC_INVALID_DEVICE);
467 alcGetError
469 Return last ALC generated error code
471 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
473 ALCenum errorCode;
475 (void)device;
477 errorCode = g_eLastContextError;
478 g_eLastContextError = ALC_NO_ERROR;
479 return errorCode;
484 alcSuspendContext
486 Not functional
488 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
490 // Not a lot happens here !
491 (void)pContext;
496 alcProcessContext
498 Not functional
500 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
502 // Not a lot happens here !
503 (void)pContext;
508 alcGetString
510 Returns information about the Device, and error strings
512 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
514 const ALCchar *value = NULL;
516 InitAL();
518 switch (param)
520 case ALC_NO_ERROR:
521 value = alcNoError;
522 break;
524 case ALC_INVALID_ENUM:
525 value = alcErrInvalidEnum;
526 break;
528 case ALC_INVALID_VALUE:
529 value = alcErrInvalidValue;
530 break;
532 case ALC_INVALID_DEVICE:
533 value = alcErrInvalidDevice;
534 break;
536 case ALC_INVALID_CONTEXT:
537 value = alcErrInvalidContext;
538 break;
540 case ALC_OUT_OF_MEMORY:
541 value = alcErrOutOfMemory;
542 break;
544 case ALC_DEFAULT_DEVICE_SPECIFIER:
545 value = alcDefaultDeviceSpecifier;
546 break;
548 case ALC_DEVICE_SPECIFIER:
549 if (pDevice)
550 value = pDevice->szDeviceName;
551 else
552 value = alcDeviceList;
553 break;
555 case ALC_ALL_DEVICES_SPECIFIER:
556 value = alcAllDeviceList;
557 break;
559 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
560 value = alcDefaultAllDeviceSpecifier;
561 break;
563 case ALC_CAPTURE_DEVICE_SPECIFIER:
564 if (pDevice)
565 value = pDevice->szDeviceName;
566 else
567 value = alcCaptureDeviceList;
568 break;
570 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
571 value = alcCaptureDefaultDeviceSpecifier;
572 break;
574 case ALC_EXTENSIONS:
575 value = alcExtensionList;
576 break;
578 default:
579 SetALCError(ALC_INVALID_ENUM);
580 break;
583 return value;
588 alcGetIntegerv
590 Returns information about the Device and the version of Open AL
592 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
594 InitAL();
596 if ((device)&&(device->IsCaptureDevice))
598 SuspendContext(NULL);
600 // Capture device
601 switch (param)
603 case ALC_CAPTURE_SAMPLES:
604 if ((size) && (data))
605 *data = ALCdevice_AvailableSamples(device);
606 else
607 SetALCError(ALC_INVALID_VALUE);
608 break;
610 default:
611 SetALCError(ALC_INVALID_ENUM);
612 break;
615 ProcessContext(NULL);
617 else
619 if(data)
621 // Playback Device
622 switch (param)
624 case ALC_MAJOR_VERSION:
625 if(!size)
626 SetALCError(ALC_INVALID_VALUE);
627 else
628 *data = alcMajorVersion;
629 break;
631 case ALC_MINOR_VERSION:
632 if(!size)
633 SetALCError(ALC_INVALID_VALUE);
634 else
635 *data = alcMinorVersion;
636 break;
638 case ALC_ATTRIBUTES_SIZE:
639 if(!device)
640 SetALCError(ALC_INVALID_DEVICE);
641 else if(!size)
642 SetALCError(ALC_INVALID_VALUE);
643 else
644 *data = 11;
645 break;
647 case ALC_ALL_ATTRIBUTES:
648 if(!device)
649 SetALCError(ALC_INVALID_DEVICE);
650 else if (size < 7)
651 SetALCError(ALC_INVALID_VALUE);
652 else
654 int i = 0;
656 data[i++] = ALC_FREQUENCY;
657 data[i++] = device->Frequency;
659 data[i++] = ALC_REFRESH;
660 data[i++] = device->UpdateFreq;
662 data[i++] = ALC_SYNC;
663 data[i++] = ALC_FALSE;
665 SuspendContext(NULL);
666 if(device->Context && size >= 11)
668 data[i++] = ALC_MONO_SOURCES;
669 data[i++] = device->Context->lNumMonoSources;
671 data[i++] = ALC_STEREO_SOURCES;
672 data[i++] = device->Context->lNumStereoSources;
674 ProcessContext(NULL);
676 data[i++] = 0;
678 break;
680 case ALC_FREQUENCY:
681 if(!device)
682 SetALCError(ALC_INVALID_DEVICE);
683 else if(!size)
684 SetALCError(ALC_INVALID_VALUE);
685 else
686 *data = device->Frequency;
687 break;
689 case ALC_REFRESH:
690 if(!device)
691 SetALCError(ALC_INVALID_DEVICE);
692 else if(!size)
693 SetALCError(ALC_INVALID_VALUE);
694 else
695 *data = device->UpdateFreq;
696 break;
698 case ALC_SYNC:
699 if(!device)
700 SetALCError(ALC_INVALID_DEVICE);
701 else if(!size)
702 SetALCError(ALC_INVALID_VALUE);
703 else
704 *data = ALC_FALSE;
705 break;
707 default:
708 SetALCError(ALC_INVALID_ENUM);
709 break;
712 else if(size)
713 SetALCError(ALC_INVALID_VALUE);
716 return;
721 alcIsExtensionPresent
723 Determines if there is support for a particular extension
725 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
727 ALCboolean bResult = ALC_FALSE;
728 ALsizei i = 0;
730 (void)device;
732 if (extName)
734 while(alcExtensions[i].extName &&
735 strcasecmp(alcExtensions[i].extName,extName) != 0)
736 i++;
738 if (alcExtensions[i].extName)
739 bResult = ALC_TRUE;
741 else
742 SetALCError(ALC_INVALID_VALUE);
744 return bResult;
749 alcGetProcAddress
751 Retrieves the function address for a particular extension function
753 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
755 ALCvoid *pFunction = NULL;
756 ALsizei i = 0;
758 (void)device;
760 if (funcName)
762 while(alcFunctions[i].funcName &&
763 strcmp(alcFunctions[i].funcName,funcName) != 0)
764 i++;
765 pFunction = alcFunctions[i].address;
767 else
768 SetALCError(ALC_INVALID_VALUE);
770 return pFunction;
775 alcGetEnumValue
777 Get the value for a particular ALC Enumerated Value
779 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
781 ALsizei i = 0;
782 ALCenum val;
784 (void)device;
786 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
787 i++;
788 val = enumeration[i].value;
790 if(!enumeration[i].enumName)
791 SetALCError(ALC_INVALID_VALUE);
793 return val;
798 alcCreateContext
800 Create and attach a Context to a particular Device.
802 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
804 ALCcontext *ALContext = NULL;
805 ALuint ulAttributeIndex, ulRequestedStereoSources;
807 if ((device)&&(!device->IsCaptureDevice))
809 // Reset Context Last Error code
810 g_eLastContextError = ALC_NO_ERROR;
812 // Current implementation only allows one Context per Device
813 if(!device->Context)
815 ALContext = calloc(1, sizeof(ALCcontext));
816 if(!ALContext)
818 SetALCError(ALC_OUT_OF_MEMORY);
819 return NULL;
822 ALContext->Device = device;
823 InitContext(ALContext);
825 device->Context = ALContext;
827 SuspendContext(NULL);
829 ALContext->next = g_pContextList;
830 g_pContextList = ALContext;
831 g_ulContextCount++;
833 ProcessContext(NULL);
835 // Check for Voice Count attributes
836 if (attrList)
838 ulAttributeIndex = 0;
839 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
841 if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
843 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
845 if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
846 ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
848 ALContext->lNumStereoSources = ulRequestedStereoSources;
849 ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
850 break;
853 ulAttributeIndex += 2;
857 else
859 SetALCError(ALC_INVALID_VALUE);
860 ALContext = NULL;
863 else
864 SetALCError(ALC_INVALID_DEVICE);
866 return ALContext;
871 alcDestroyContext
873 Remove a Context
875 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
877 ALCcontext **list;
879 // Lock context list
880 SuspendContext(NULL);
882 if (IsContext(context))
884 // Lock context
885 SuspendContext(context);
887 context->Device->Context = NULL;
889 list = &g_pContextList;
890 while(*list != context)
891 list = &(*list)->next;
893 *list = (*list)->next;
894 g_ulContextCount--;
896 // Unlock context
897 ProcessContext(context);
899 ExitContext(context);
901 // Free memory (MUST do this after ProcessContext)
902 memset(context, 0, sizeof(ALCcontext));
903 free(context);
905 else
906 SetALCError(ALC_INVALID_CONTEXT);
908 ProcessContext(NULL);
913 alcGetCurrentContext
915 Returns the currently active Context
917 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
919 ALCcontext *pContext = NULL;
921 SuspendContext(NULL);
923 pContext = g_pContextList;
924 while ((pContext) && (!pContext->InUse))
925 pContext = pContext->next;
927 ProcessContext(NULL);
929 return pContext;
934 alcGetContextsDevice
936 Returns the Device that a particular Context is attached to
938 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
940 ALCdevice *pDevice = NULL;
942 SuspendContext(NULL);
943 if (IsContext(pContext))
944 pDevice = pContext->Device;
945 else
946 SetALCError(ALC_INVALID_CONTEXT);
947 ProcessContext(NULL);
949 return pDevice;
954 alcMakeContextCurrent
956 Makes the given Context the active Context
958 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
960 ALCcontext *ALContext;
961 ALboolean bReturn = AL_TRUE;
963 SuspendContext(NULL);
965 // context must be a valid Context or NULL
966 if ((IsContext(context)) || (context == NULL))
968 if ((ALContext=alcGetCurrentContext()))
970 SuspendContext(ALContext);
971 ALContext->InUse=AL_FALSE;
972 ProcessContext(ALContext);
975 if ((ALContext=context) && (ALContext->Device))
977 SuspendContext(ALContext);
978 ALContext->InUse=AL_TRUE;
979 ProcessContext(ALContext);
982 else
984 SetALCError(ALC_INVALID_CONTEXT);
985 bReturn = AL_FALSE;
988 ProcessContext(NULL);
990 return bReturn;
995 alcOpenDevice
997 Open the Device specified.
999 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
1001 ALboolean bDeviceFound = AL_FALSE;
1002 ALCdevice *device;
1003 ALint i;
1005 InitAL();
1007 device = malloc(sizeof(ALCdevice));
1008 if (device)
1010 const char *fmt;
1012 //Initialise device structure
1013 memset(device, 0, sizeof(ALCdevice));
1015 //Validate device
1016 device->InUse = AL_TRUE;
1017 device->IsCaptureDevice = AL_FALSE;
1019 //Set output format
1020 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1021 if((ALint)device->Frequency <= 0)
1022 device->Frequency = SWMIXER_OUTPUT_RATE;
1024 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1025 if(fmt[0])
1026 device->Format = alGetEnumValue(fmt);
1028 device->Channels = aluChannelsFromFormat(device->Format);
1029 if(!device->Channels)
1031 device->Format = AL_FORMAT_STEREO16;
1032 device->Channels = 2;
1033 device->FrameSize = 4;
1035 else
1036 device->FrameSize = aluBytesFromFormat(device->Format) *
1037 device->Channels;
1039 device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 0);
1040 if((ALint)device->UpdateFreq <= 0)
1041 device->UpdateFreq = 8192 * device->Frequency / 22050;
1043 // Find a playback device to open
1044 for(i = 0;BackendList[i].Init;i++)
1046 device->Funcs = &BackendList[i].Funcs;
1047 if(ALCdevice_OpenPlayback(device, deviceName))
1049 bDeviceFound = AL_TRUE;
1050 break;
1054 if (!bDeviceFound)
1056 // No suitable output device found
1057 free(device);
1058 device = NULL;
1062 return device;
1067 alcCloseDevice
1069 Close the specified Device
1071 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1073 ALCboolean bReturn = ALC_FALSE;
1075 if ((pDevice)&&(!pDevice->IsCaptureDevice))
1077 ALCdevice_ClosePlayback(pDevice);
1079 //Release device structure
1080 memset(pDevice, 0, sizeof(ALCdevice));
1081 free(pDevice);
1083 bReturn = ALC_TRUE;
1085 else
1086 SetALCError(ALC_INVALID_DEVICE);
1088 return bReturn;
1090 ///////////////////////////////////////////////////////