Make another function static
[openal-soft.git] / Alc / ALc.c
blobd7d8f493ada10b129cc38bec901e93ee2370a7c5
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;
195 InitializeCriticalSection(&g_mutex);
196 ALTHUNK_INIT();
197 ReadALConfig();
199 for(i = 0;BackendList[i].Init;i++)
200 BackendList[i].Init(&BackendList[i].Funcs);
201 done = 1;
205 ALCchar *AppendDeviceList(char *name)
207 static int pos;
208 ALCchar *ret = alcDeviceList+pos;
209 pos += snprintf(alcDeviceList+pos, sizeof(alcDeviceList)-pos, "%s", name) + 1;
210 return ret;
213 ALCchar *AppendAllDeviceList(char *name)
215 static int pos;
216 ALCchar *ret = alcAllDeviceList+pos;
217 pos += snprintf(alcAllDeviceList+pos, sizeof(alcAllDeviceList)-pos, "%s", name) + 1;
218 return ret;
221 ALCchar *AppendCaptureDeviceList(char *name)
223 static int pos;
224 ALCchar *ret = alcCaptureDeviceList+pos;
225 pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos, "%s", name) + 1;
226 return ret;
230 IsContext
232 Check pContext is a valid Context pointer
234 static ALCboolean IsContext(ALCcontext *pContext)
236 ALCcontext *pTempContext;
238 pTempContext = g_pContextList;
239 while (pTempContext && pTempContext != pContext)
240 pTempContext = pTempContext->next;
242 return (pTempContext ? ALC_TRUE : ALC_FALSE);
247 SetALCError
249 Store latest ALC Error
251 ALCvoid SetALCError(ALenum errorCode)
253 g_eLastContextError = errorCode;
258 SuspendContext
260 Thread-safe entry
262 ALCvoid SuspendContext(ALCcontext *pContext)
264 (void)pContext;
265 EnterCriticalSection(&g_mutex);
270 ProcessContext
272 Thread-safe exit
274 ALCvoid ProcessContext(ALCcontext *pContext)
276 (void)pContext;
277 LeaveCriticalSection(&g_mutex);
282 InitContext
284 Initialize Context variables
286 static ALvoid InitContext(ALCcontext *pContext)
288 //Initialise listener
289 pContext->Listener.Gain = 1.0f;
290 pContext->Listener.Position[0] = 0.0f;
291 pContext->Listener.Position[1] = 0.0f;
292 pContext->Listener.Position[2] = 0.0f;
293 pContext->Listener.Velocity[0] = 0.0f;
294 pContext->Listener.Velocity[1] = 0.0f;
295 pContext->Listener.Velocity[2] = 0.0f;
296 pContext->Listener.Forward[0] = 0.0f;
297 pContext->Listener.Forward[1] = 0.0f;
298 pContext->Listener.Forward[2] = -1.0f;
299 pContext->Listener.Up[0] = 0.0f;
300 pContext->Listener.Up[1] = 1.0f;
301 pContext->Listener.Up[2] = 0.0f;
303 //Validate pContext
304 pContext->LastError = AL_NO_ERROR;
305 pContext->InUse = AL_FALSE;
307 //Set output format
308 pContext->Frequency = pContext->Device->Frequency;
310 //Set globals
311 pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED;
312 pContext->DopplerFactor = 1.0f;
313 pContext->DopplerVelocity = 1.0f;
314 pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC;
316 pContext->lNumStereoSources = 1;
317 pContext->lNumMonoSources = pContext->Device->MaxNoOfSources - pContext->lNumStereoSources;
319 strcpy(pContext->ExtensionList, "AL_EXT_EXPONENT_DISTANCE AL_EXT_LINEAR_DISTANCE AL_EXT_OFFSET");
324 ExitContext
326 Clean up Context, destroy any remaining Sources
328 static ALCvoid ExitContext(ALCcontext *pContext)
330 unsigned int i;
331 ALsource *ALSource;
332 ALsource *ALTempSource;
334 #ifdef _DEBUG
335 if (pContext->SourceCount>0)
336 AL_PRINT("alcDestroyContext() %d Source(s) NOT deleted\n", pContext->SourceCount);
337 #endif
339 // Free all the Sources still remaining
340 ALSource = pContext->Source;
341 for (i = 0; i < pContext->SourceCount; i++)
343 ALTempSource = ALSource->next;
344 ALTHUNK_REMOVEENTRY(ALSource->source);
345 memset(ALSource, 0, sizeof(ALsource));
346 free(ALSource);
347 ALSource = ALTempSource;
350 //Invalidate context
351 pContext->LastError = AL_NO_ERROR;
352 pContext->InUse = AL_FALSE;
355 ///////////////////////////////////////////////////////
358 ///////////////////////////////////////////////////////
359 // ALC Functions calls
362 // This should probably move to another c file but for now ...
363 ALCAPI ALCdevice* ALCAPIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize)
365 ALCboolean DeviceFound = ALC_FALSE;
366 ALCdevice *pDevice = NULL;
367 ALCint i;
369 InitAL();
371 pDevice = malloc(sizeof(ALCdevice));
372 if (pDevice)
374 if (SampleSize > 0)
376 //Initialise device structure
377 memset(pDevice, 0, sizeof(ALCdevice));
379 //Validate device
380 pDevice->InUse = AL_TRUE;
381 pDevice->IsCaptureDevice = AL_TRUE;
383 pDevice->Frequency = frequency;
384 pDevice->Format = format;
385 pDevice->Channels = aluChannelsFromFormat(format);
386 pDevice->FrameSize = aluBytesFromFormat(format) *
387 pDevice->Channels;
389 for(i = 0;BackendList[i].Init;i++)
391 pDevice->Funcs = &BackendList[i].Funcs;
392 if(ALCdevice_OpenCapture(pDevice, deviceName, frequency, format, SampleSize))
394 DeviceFound = ALC_TRUE;
395 break;
399 else
400 SetALCError(ALC_INVALID_VALUE);
402 if(!DeviceFound)
404 free(pDevice);
405 pDevice = NULL;
408 else
409 SetALCError(ALC_OUT_OF_MEMORY);
411 return pDevice;
414 ALCAPI ALCboolean ALCAPIENTRY alcCaptureCloseDevice(ALCdevice *pDevice)
416 ALCboolean bReturn = ALC_FALSE;
418 if ((pDevice)&&(pDevice->IsCaptureDevice))
420 ALCdevice_CloseCapture(pDevice);
421 free(pDevice);
423 bReturn = ALC_TRUE;
425 else
426 SetALCError(ALC_INVALID_DEVICE);
428 return bReturn;
431 ALCAPI void ALCAPIENTRY alcCaptureStart(ALCdevice *pDevice)
433 if ((pDevice)&&(pDevice->IsCaptureDevice))
434 ALCdevice_StartCapture(pDevice);
435 else
436 SetALCError(ALC_INVALID_DEVICE);
439 ALCAPI void ALCAPIENTRY alcCaptureStop(ALCdevice *pDevice)
441 if ((pDevice)&&(pDevice->IsCaptureDevice))
442 ALCdevice_StopCapture(pDevice);
443 else
444 SetALCError(ALC_INVALID_DEVICE);
447 ALCAPI void ALCAPIENTRY alcCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCsizei lSamples)
449 if ((pDevice) && (pDevice->IsCaptureDevice))
450 ALCdevice_CaptureSamples(pDevice, pBuffer, lSamples);
451 else
452 SetALCError(ALC_INVALID_DEVICE);
456 alcGetError
458 Return last ALC generated error code
460 ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device)
462 ALCenum errorCode;
464 (void)device;
466 errorCode = g_eLastContextError;
467 g_eLastContextError = ALC_NO_ERROR;
468 return errorCode;
473 alcSuspendContext
475 Not functional
477 ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *pContext)
479 // Not a lot happens here !
480 (void)pContext;
485 alcProcessContext
487 Not functional
489 ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *pContext)
491 // Not a lot happens here !
492 (void)pContext;
497 alcGetString
499 Returns information about the Device, and error strings
501 ALCAPI const ALCchar* ALCAPIENTRY alcGetString(ALCdevice *pDevice,ALCenum param)
503 const ALCchar *value = NULL;
505 InitAL();
507 switch (param)
509 case ALC_NO_ERROR:
510 value = alcNoError;
511 break;
513 case ALC_INVALID_ENUM:
514 value = alcErrInvalidEnum;
515 break;
517 case ALC_INVALID_VALUE:
518 value = alcErrInvalidValue;
519 break;
521 case ALC_INVALID_DEVICE:
522 value = alcErrInvalidDevice;
523 break;
525 case ALC_INVALID_CONTEXT:
526 value = alcErrInvalidContext;
527 break;
529 case ALC_OUT_OF_MEMORY:
530 value = alcErrOutOfMemory;
531 break;
533 case ALC_DEFAULT_DEVICE_SPECIFIER:
534 value = alcDefaultDeviceSpecifier;
535 break;
537 case ALC_DEVICE_SPECIFIER:
538 if (pDevice)
539 value = pDevice->szDeviceName;
540 else
541 value = alcDeviceList;
542 break;
544 case ALC_ALL_DEVICES_SPECIFIER:
545 value = alcAllDeviceList;
546 break;
548 case ALC_DEFAULT_ALL_DEVICES_SPECIFIER:
549 value = alcDefaultAllDeviceSpecifier;
550 break;
552 case ALC_CAPTURE_DEVICE_SPECIFIER:
553 if (pDevice)
554 value = pDevice->szDeviceName;
555 else
556 value = alcCaptureDeviceList;
557 break;
559 case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER:
560 value = alcCaptureDefaultDeviceSpecifier;
561 break;
563 case ALC_EXTENSIONS:
564 value = alcExtensionList;
565 break;
567 default:
568 SetALCError(ALC_INVALID_ENUM);
569 break;
572 return value;
577 alcGetIntegerv
579 Returns information about the Device and the version of Open AL
581 ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data)
583 InitAL();
585 if ((device)&&(device->IsCaptureDevice))
587 SuspendContext(NULL);
589 // Capture device
590 switch (param)
592 case ALC_CAPTURE_SAMPLES:
593 if ((size) && (data))
594 *data = ALCdevice_AvailableSamples(device);
595 else
596 SetALCError(ALC_INVALID_VALUE);
597 break;
599 default:
600 SetALCError(ALC_INVALID_ENUM);
601 break;
604 ProcessContext(NULL);
606 else
608 if(data)
610 // Playback Device
611 switch (param)
613 case ALC_MAJOR_VERSION:
614 if(!size)
615 SetALCError(ALC_INVALID_VALUE);
616 else
617 *data = alcMajorVersion;
618 break;
620 case ALC_MINOR_VERSION:
621 if(!size)
622 SetALCError(ALC_INVALID_VALUE);
623 else
624 *data = alcMinorVersion;
625 break;
627 case ALC_ATTRIBUTES_SIZE:
628 if(!device)
629 SetALCError(ALC_INVALID_DEVICE);
630 else if(!size)
631 SetALCError(ALC_INVALID_VALUE);
632 else
633 *data = 11;
634 break;
636 case ALC_ALL_ATTRIBUTES:
637 if(!device)
638 SetALCError(ALC_INVALID_DEVICE);
639 else if (size < 7)
640 SetALCError(ALC_INVALID_VALUE);
641 else
643 int i = 0;
645 data[i++] = ALC_FREQUENCY;
646 data[i++] = device->Frequency;
648 data[i++] = ALC_REFRESH;
649 data[i++] = device->UpdateFreq;
651 data[i++] = ALC_SYNC;
652 data[i++] = ALC_FALSE;
654 SuspendContext(NULL);
655 if(device->Context && size >= 11)
657 data[i++] = ALC_MONO_SOURCES;
658 data[i++] = device->Context->lNumMonoSources;
660 data[i++] = ALC_STEREO_SOURCES;
661 data[i++] = device->Context->lNumStereoSources;
663 ProcessContext(NULL);
665 data[i++] = 0;
667 break;
669 case ALC_FREQUENCY:
670 if(!device)
671 SetALCError(ALC_INVALID_DEVICE);
672 else if(!size)
673 SetALCError(ALC_INVALID_VALUE);
674 else
675 *data = device->Frequency;
676 break;
678 case ALC_REFRESH:
679 if(!device)
680 SetALCError(ALC_INVALID_DEVICE);
681 else if(!size)
682 SetALCError(ALC_INVALID_VALUE);
683 else
684 *data = device->UpdateFreq;
685 break;
687 case ALC_SYNC:
688 if(!device)
689 SetALCError(ALC_INVALID_DEVICE);
690 else if(!size)
691 SetALCError(ALC_INVALID_VALUE);
692 else
693 *data = ALC_FALSE;
694 break;
696 default:
697 SetALCError(ALC_INVALID_ENUM);
698 break;
701 else if(size)
702 SetALCError(ALC_INVALID_VALUE);
705 return;
710 alcIsExtensionPresent
712 Determines if there is support for a particular extension
714 ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName)
716 ALCboolean bResult = ALC_FALSE;
717 ALsizei i = 0;
719 (void)device;
721 if (extName)
723 while(alcExtensions[i].extName &&
724 strcasecmp(alcExtensions[i].extName,extName) != 0)
725 i++;
727 if (alcExtensions[i].extName)
728 bResult = ALC_TRUE;
730 else
731 SetALCError(ALC_INVALID_VALUE);
733 return bResult;
738 alcGetProcAddress
740 Retrieves the function address for a particular extension function
742 ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName)
744 ALCvoid *pFunction = NULL;
745 ALsizei i = 0;
747 (void)device;
749 if (funcName)
751 while(alcFunctions[i].funcName &&
752 strcmp(alcFunctions[i].funcName,funcName) != 0)
753 i++;
754 pFunction = alcFunctions[i].address;
756 else
757 SetALCError(ALC_INVALID_VALUE);
759 return pFunction;
764 alcGetEnumValue
766 Get the value for a particular ALC Enumerated Value
768 ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName)
770 ALsizei i = 0;
771 ALCenum val;
773 (void)device;
775 while ((enumeration[i].enumName)&&(strcmp(enumeration[i].enumName,enumName)))
776 i++;
777 val = enumeration[i].value;
779 if(!enumeration[i].enumName)
780 SetALCError(ALC_INVALID_VALUE);
782 return val;
787 alcCreateContext
789 Create and attach a Context to a particular Device.
791 ALCAPI ALCcontext* ALCAPIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList)
793 ALCcontext *ALContext = NULL;
794 ALuint ulAttributeIndex, ulRequestedStereoSources;
796 if ((device)&&(!device->IsCaptureDevice))
798 // Reset Context Last Error code
799 g_eLastContextError = ALC_NO_ERROR;
801 // Current implementation only allows one Context per Device
802 if(!device->Context)
804 ALContext = calloc(1, sizeof(ALCcontext));
805 if(!ALContext)
807 SetALCError(ALC_OUT_OF_MEMORY);
808 return NULL;
811 ALContext->Device = device;
812 InitContext(ALContext);
814 device->Context = ALContext;
816 SuspendContext(NULL);
818 ALContext->next = g_pContextList;
819 g_pContextList = ALContext;
820 g_ulContextCount++;
822 ProcessContext(NULL);
824 // Check for Voice Count attributes
825 if (attrList)
827 ulAttributeIndex = 0;
828 while ((ulAttributeIndex < 10) && (attrList[ulAttributeIndex]))
830 if (attrList[ulAttributeIndex] == ALC_STEREO_SOURCES)
832 ulRequestedStereoSources = attrList[ulAttributeIndex + 1];
834 if (ulRequestedStereoSources > ALContext->Device->MaxNoOfSources)
835 ulRequestedStereoSources = ALContext->Device->MaxNoOfSources;
837 ALContext->lNumStereoSources = ulRequestedStereoSources;
838 ALContext->lNumMonoSources = ALContext->Device->MaxNoOfSources - ALContext->lNumStereoSources;
839 break;
842 ulAttributeIndex += 2;
846 else
848 SetALCError(ALC_INVALID_VALUE);
849 ALContext = NULL;
852 else
853 SetALCError(ALC_INVALID_DEVICE);
855 return ALContext;
860 alcDestroyContext
862 Remove a Context
864 ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context)
866 ALCcontext **list;
868 // Lock context list
869 SuspendContext(NULL);
871 if (IsContext(context))
873 // Lock context
874 SuspendContext(context);
876 context->Device->Context = NULL;
878 list = &g_pContextList;
879 while(*list != context)
880 list = &(*list)->next;
882 *list = (*list)->next;
883 g_ulContextCount--;
885 // Unlock context
886 ProcessContext(context);
888 ExitContext(context);
890 // Free memory (MUST do this after ProcessContext)
891 memset(context, 0, sizeof(ALCcontext));
892 free(context);
894 else
895 SetALCError(ALC_INVALID_CONTEXT);
897 ProcessContext(NULL);
902 alcGetCurrentContext
904 Returns the currently active Context
906 ALCAPI ALCcontext * ALCAPIENTRY alcGetCurrentContext(ALCvoid)
908 ALCcontext *pContext = NULL;
910 SuspendContext(NULL);
912 pContext = g_pContextList;
913 while ((pContext) && (!pContext->InUse))
914 pContext = pContext->next;
916 ProcessContext(NULL);
918 return pContext;
923 alcGetContextsDevice
925 Returns the Device that a particular Context is attached to
927 ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *pContext)
929 ALCdevice *pDevice = NULL;
931 SuspendContext(NULL);
932 if (IsContext(pContext))
933 pDevice = pContext->Device;
934 else
935 SetALCError(ALC_INVALID_CONTEXT);
936 ProcessContext(NULL);
938 return pDevice;
943 alcMakeContextCurrent
945 Makes the given Context the active Context
947 ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context)
949 ALCcontext *ALContext;
950 ALboolean bReturn = AL_TRUE;
952 SuspendContext(NULL);
954 // context must be a valid Context or NULL
955 if ((IsContext(context)) || (context == NULL))
957 if ((ALContext=alcGetCurrentContext()))
959 SuspendContext(ALContext);
960 ALContext->InUse=AL_FALSE;
961 ProcessContext(ALContext);
964 if ((ALContext=context) && (ALContext->Device))
966 SuspendContext(ALContext);
967 ALContext->InUse=AL_TRUE;
968 ProcessContext(ALContext);
971 else
973 SetALCError(ALC_INVALID_CONTEXT);
974 bReturn = AL_FALSE;
977 ProcessContext(NULL);
979 return bReturn;
984 alcOpenDevice
986 Open the Device specified.
988 ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(const ALCchar *deviceName)
990 ALboolean bDeviceFound = AL_FALSE;
991 ALCdevice *device;
992 ALint i;
994 InitAL();
996 device = malloc(sizeof(ALCdevice));
997 if (device)
999 const char *fmt;
1001 //Initialise device structure
1002 memset(device, 0, sizeof(ALCdevice));
1004 //Validate device
1005 device->InUse = AL_TRUE;
1006 device->IsCaptureDevice = AL_FALSE;
1008 //Set output format
1009 device->Frequency = GetConfigValueInt(NULL, "frequency", SWMIXER_OUTPUT_RATE);
1010 if((ALint)device->Frequency <= 0)
1011 device->Frequency = SWMIXER_OUTPUT_RATE;
1013 fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16");
1014 if(fmt[0])
1015 device->Format = alGetEnumValue(fmt);
1017 device->Channels = aluChannelsFromFormat(device->Format);
1018 if(!device->Channels)
1020 device->Format = AL_FORMAT_STEREO16;
1021 device->Channels = 2;
1022 device->FrameSize = 4;
1024 else
1025 device->FrameSize = aluBytesFromFormat(device->Format) *
1026 device->Channels;
1028 device->UpdateFreq = GetConfigValueInt(NULL, "refresh", 0);
1029 if((ALint)device->UpdateFreq <= 0)
1030 device->UpdateFreq = 8192 * device->Frequency / 22050;
1032 // Find a playback device to open
1033 for(i = 0;BackendList[i].Init;i++)
1035 device->Funcs = &BackendList[i].Funcs;
1036 if(ALCdevice_OpenPlayback(device, deviceName))
1038 bDeviceFound = AL_TRUE;
1039 break;
1043 if (!bDeviceFound)
1045 // No suitable output device found
1046 free(device);
1047 device = NULL;
1051 return device;
1056 alcCloseDevice
1058 Close the specified Device
1060 ALCAPI ALCboolean ALCAPIENTRY alcCloseDevice(ALCdevice *pDevice)
1062 ALCboolean bReturn = ALC_FALSE;
1064 if ((pDevice)&&(!pDevice->IsCaptureDevice))
1066 ALCdevice_ClosePlayback(pDevice);
1068 //Release device structure
1069 memset(pDevice, 0, sizeof(ALCdevice));
1070 free(pDevice);
1072 bReturn = ALC_TRUE;
1074 else
1075 SetALCError(ALC_INVALID_DEVICE);
1077 return bReturn;
1079 ///////////////////////////////////////////////////////