Store the max number of auxiliary slots in the device
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob805bdb4bdfba0f15ed3c46a790637b7ef9a6b9e6
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 #include "config.h"
23 #include <stdlib.h>
24 #include <math.h>
26 #include "AL/al.h"
27 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alAuxEffectSlot.h"
30 #include "alThunk.h"
31 #include "alError.h"
34 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
37 ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
39 ALCcontext *Context;
40 ALsizei i, j;
42 Context = alcGetCurrentContext();
43 if(!Context)
45 alSetError(AL_INVALID_OPERATION);
46 return;
48 SuspendContext(Context);
50 if (n > 0)
52 ALCdevice *Device = alcGetContextsDevice(Context);
54 if(Context->AuxiliaryEffectSlotCount+n <= Device->AuxiliaryEffectSlotMax)
56 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
57 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
59 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
60 while(*list)
61 list = &(*list)->next;
63 i = 0;
64 while(i < n)
66 *list = calloc(1, sizeof(ALeffectslot));
67 if(!(*list))
69 // We must have run out or memory
70 alDeleteAuxiliaryEffectSlots(i, effectslots);
71 alSetError(AL_OUT_OF_MEMORY);
72 break;
75 (*list)->Gain = 1.0;
76 (*list)->AuxSendAuto = AL_TRUE;
77 for(j = 0;j < BUFFERSIZE;j++)
78 (*list)->WetBuffer[j] = 0.0f;
79 (*list)->refcount = 0;
81 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
82 (*list)->effectslot = effectslots[i];
84 Context->AuxiliaryEffectSlotCount++;
85 i++;
87 list = &(*list)->next;
91 else
92 alSetError(AL_INVALID_OPERATION);
95 ProcessContext(Context);
98 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
100 ALCcontext *Context;
101 ALeffectslot *ALAuxiliaryEffectSlot;
102 ALsizei i;
104 Context = alcGetCurrentContext();
105 if(!Context)
107 alSetError(AL_INVALID_OPERATION);
108 return;
110 SuspendContext(Context);
112 if (n >= 0)
114 // Check that all effectslots are valid
115 for (i = 0; i < n; i++)
117 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
119 alSetError(AL_INVALID_NAME);
120 break;
122 else
124 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
125 if(ALAuxiliaryEffectSlot->refcount > 0)
127 alSetError(AL_INVALID_NAME);
128 break;
133 if (i == n)
135 // All effectslots are valid
136 for (i = 0; i < n; i++)
138 // Recheck that the effectslot is valid, because there could be duplicated names
139 if (alIsAuxiliaryEffectSlot(effectslots[i]))
141 ALeffectslot **list;
143 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
145 // Remove Source from list of Sources
146 list = &Context->AuxiliaryEffectSlot;
147 while(*list && *list != ALAuxiliaryEffectSlot)
148 list = &(*list)->next;
150 if(*list)
151 *list = (*list)->next;
152 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
154 if(ALAuxiliaryEffectSlot->EffectState)
155 ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
157 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
158 free(ALAuxiliaryEffectSlot);
160 Context->AuxiliaryEffectSlotCount--;
165 else
166 alSetError(AL_INVALID_VALUE);
168 ProcessContext(Context);
171 ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
173 ALCcontext *Context;
174 ALeffectslot **list;
176 Context = alcGetCurrentContext();
177 if(!Context)
179 alSetError(AL_INVALID_OPERATION);
180 return AL_FALSE;
182 SuspendContext(Context);
184 list = &Context->AuxiliaryEffectSlot;
185 while(*list && (*list)->effectslot != effectslot)
186 list = &(*list)->next;
188 ProcessContext(Context);
190 return (*list ? AL_TRUE : AL_FALSE);
193 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
195 ALCcontext *Context;
197 Context = alcGetCurrentContext();
198 if(!Context)
200 alSetError(AL_INVALID_OPERATION);
201 return;
203 SuspendContext(Context);
205 if (alIsAuxiliaryEffectSlot(effectslot))
207 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
209 switch(param)
211 case AL_EFFECTSLOT_EFFECT:
212 if(alIsEffect(iValue))
214 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
215 InitializeEffect(Context, ALEffectSlot, effect);
217 else
218 alSetError(AL_INVALID_VALUE);
219 break;
221 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
222 if(iValue == AL_TRUE || iValue == AL_FALSE)
223 ALEffectSlot->AuxSendAuto = iValue;
224 else
225 alSetError(AL_INVALID_VALUE);
226 break;
228 default:
229 alSetError(AL_INVALID_ENUM);
230 break;
233 else
234 alSetError(AL_INVALID_NAME);
236 ProcessContext(Context);
239 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
241 ALCcontext *Context;
243 Context = alcGetCurrentContext();
244 if(!Context)
246 alSetError(AL_INVALID_OPERATION);
247 return;
249 SuspendContext(Context);
251 if (alIsAuxiliaryEffectSlot(effectslot))
253 switch(param)
255 case AL_EFFECTSLOT_EFFECT:
256 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
257 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
258 break;
260 default:
261 alSetError(AL_INVALID_ENUM);
262 break;
265 else
266 alSetError(AL_INVALID_NAME);
268 ProcessContext(Context);
271 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
273 ALCcontext *Context;
275 Context = alcGetCurrentContext();
276 if(!Context)
278 alSetError(AL_INVALID_OPERATION);
279 return;
281 SuspendContext(Context);
283 if (alIsAuxiliaryEffectSlot(effectslot))
285 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
287 switch(param)
289 case AL_EFFECTSLOT_GAIN:
290 if(flValue >= 0.0f && flValue <= 1.0f)
291 ALEffectSlot->Gain = flValue;
292 else
293 alSetError(AL_INVALID_VALUE);
294 break;
296 default:
297 alSetError(AL_INVALID_ENUM);
298 break;
301 else
302 alSetError(AL_INVALID_NAME);
304 ProcessContext(Context);
307 ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
309 ALCcontext *Context;
311 Context = alcGetCurrentContext();
312 if(!Context)
314 alSetError(AL_INVALID_OPERATION);
315 return;
317 SuspendContext(Context);
319 if (alIsAuxiliaryEffectSlot(effectslot))
321 switch(param)
323 case AL_EFFECTSLOT_GAIN:
324 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
325 break;
327 default:
328 alSetError(AL_INVALID_ENUM);
329 break;
332 else
333 alSetError(AL_INVALID_NAME);
335 ProcessContext(Context);
338 ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
340 ALCcontext *Context;
342 Context = alcGetCurrentContext();
343 if(!Context)
345 alSetError(AL_INVALID_OPERATION);
346 return;
348 SuspendContext(Context);
350 if (alIsAuxiliaryEffectSlot(effectslot))
352 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
354 switch(param)
356 case AL_EFFECTSLOT_EFFECT:
357 *piValue = ALEffectSlot->effect.effect;
358 break;
360 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
361 *piValue = ALEffectSlot->AuxSendAuto;
362 break;
364 default:
365 alSetError(AL_INVALID_ENUM);
366 break;
369 else
370 alSetError(AL_INVALID_NAME);
372 ProcessContext(Context);
375 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
377 ALCcontext *Context;
379 Context = alcGetCurrentContext();
380 if(!Context)
382 alSetError(AL_INVALID_OPERATION);
383 return;
385 SuspendContext(Context);
387 if (alIsAuxiliaryEffectSlot(effectslot))
389 switch(param)
391 case AL_EFFECTSLOT_EFFECT:
392 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
393 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
394 break;
396 default:
397 alSetError(AL_INVALID_ENUM);
398 break;
401 else
402 alSetError(AL_INVALID_NAME);
404 ProcessContext(Context);
407 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
409 ALCcontext *Context;
411 Context = alcGetCurrentContext();
412 if(!Context)
414 alSetError(AL_INVALID_OPERATION);
415 return;
417 SuspendContext(Context);
419 if (alIsAuxiliaryEffectSlot(effectslot))
421 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
423 switch(param)
425 case AL_EFFECTSLOT_GAIN:
426 *pflValue = ALEffectSlot->Gain;
427 break;
429 default:
430 alSetError(AL_INVALID_ENUM);
431 break;
434 else
435 alSetError(AL_INVALID_NAME);
437 ProcessContext(Context);
440 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
442 ALCcontext *Context;
444 Context = alcGetCurrentContext();
445 if(!Context)
447 alSetError(AL_INVALID_OPERATION);
448 return;
450 SuspendContext(Context);
452 if (alIsAuxiliaryEffectSlot(effectslot))
454 switch(param)
456 case AL_EFFECTSLOT_GAIN:
457 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
458 break;
460 default:
461 alSetError(AL_INVALID_ENUM);
462 break;
465 else
466 alSetError(AL_INVALID_NAME);
468 ProcessContext(Context);
472 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
474 if((!effect) || (effect->type != ALEffectSlot->effect.type))
476 ALeffectState *NewState = NULL;
477 if(effect)
479 if(effect->type == AL_EFFECT_EAXREVERB)
480 NewState = EAXVerbCreate(Context);
481 else if(effect->type == AL_EFFECT_REVERB)
482 NewState = VerbCreate(Context);
483 else if(effect->type == AL_EFFECT_ECHO)
484 NewState = EchoCreate(Context);
485 /* No new state? An error occured.. */
486 if(!NewState)
487 return;
489 if(ALEffectSlot->EffectState)
490 ALEffect_Destroy(ALEffectSlot->EffectState);
491 ALEffectSlot->EffectState = NewState;
493 if(!effect)
495 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
496 return;
498 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
499 ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
503 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
505 #ifdef _DEBUG
506 if(Context->AuxiliaryEffectSlotCount > 0)
507 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
508 #endif
510 while(Context->AuxiliaryEffectSlot)
512 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
513 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
515 // Release effectslot structure
516 if(temp->EffectState)
517 ALEffect_Destroy(temp->EffectState);
518 ALTHUNK_REMOVEENTRY(temp->effectslot);
520 memset(temp, 0, sizeof(ALeffectslot));
521 free(temp);
523 Context->AuxiliaryEffectSlotCount = 0;