Modify some context checks
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blobe01c78d82f85c384f40967f1e76f475a746075ec
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 = GetContextSuspended();
43 if(!Context)
45 alSetError(AL_INVALID_OPERATION);
46 return;
49 if (n > 0)
51 ALCdevice *Device = alcGetContextsDevice(Context);
53 if(Context->AuxiliaryEffectSlotCount+n <= Device->AuxiliaryEffectSlotMax)
55 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
56 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
58 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
59 while(*list)
60 list = &(*list)->next;
62 i = 0;
63 while(i < n)
65 *list = calloc(1, sizeof(ALeffectslot));
66 if(!(*list))
68 // We must have run out or memory
69 alDeleteAuxiliaryEffectSlots(i, effectslots);
70 alSetError(AL_OUT_OF_MEMORY);
71 break;
74 (*list)->Gain = 1.0;
75 (*list)->AuxSendAuto = AL_TRUE;
76 for(j = 0;j < BUFFERSIZE;j++)
77 (*list)->WetBuffer[j] = 0.0f;
78 (*list)->refcount = 0;
80 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
81 (*list)->effectslot = effectslots[i];
83 Context->AuxiliaryEffectSlotCount++;
84 i++;
86 list = &(*list)->next;
90 else
91 alSetError(AL_INVALID_OPERATION);
94 ProcessContext(Context);
97 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
99 ALCcontext *Context;
100 ALeffectslot *ALAuxiliaryEffectSlot;
101 ALsizei i;
103 Context = GetContextSuspended();
104 if(!Context)
106 alSetError(AL_INVALID_OPERATION);
107 return;
110 if (n >= 0)
112 // Check that all effectslots are valid
113 for (i = 0; i < n; i++)
115 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
117 alSetError(AL_INVALID_NAME);
118 break;
120 else
122 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
123 if(ALAuxiliaryEffectSlot->refcount > 0)
125 alSetError(AL_INVALID_NAME);
126 break;
131 if (i == n)
133 // All effectslots are valid
134 for (i = 0; i < n; i++)
136 // Recheck that the effectslot is valid, because there could be duplicated names
137 if (alIsAuxiliaryEffectSlot(effectslots[i]))
139 ALeffectslot **list;
141 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
143 // Remove Source from list of Sources
144 list = &Context->AuxiliaryEffectSlot;
145 while(*list && *list != ALAuxiliaryEffectSlot)
146 list = &(*list)->next;
148 if(*list)
149 *list = (*list)->next;
150 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
152 if(ALAuxiliaryEffectSlot->EffectState)
153 ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
155 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
156 free(ALAuxiliaryEffectSlot);
158 Context->AuxiliaryEffectSlotCount--;
163 else
164 alSetError(AL_INVALID_VALUE);
166 ProcessContext(Context);
169 ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
171 ALCcontext *Context;
172 ALeffectslot **list;
174 Context = GetContextSuspended();
175 if(!Context)
177 alSetError(AL_INVALID_OPERATION);
178 return AL_FALSE;
181 list = &Context->AuxiliaryEffectSlot;
182 while(*list && (*list)->effectslot != effectslot)
183 list = &(*list)->next;
185 ProcessContext(Context);
187 return (*list ? AL_TRUE : AL_FALSE);
190 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
192 ALCcontext *Context;
194 Context = GetContextSuspended();
195 if(!Context)
197 alSetError(AL_INVALID_OPERATION);
198 return;
201 if (alIsAuxiliaryEffectSlot(effectslot))
203 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
205 switch(param)
207 case AL_EFFECTSLOT_EFFECT:
208 if(alIsEffect(iValue))
210 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
211 InitializeEffect(Context, ALEffectSlot, effect);
213 else
214 alSetError(AL_INVALID_VALUE);
215 break;
217 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
218 if(iValue == AL_TRUE || iValue == AL_FALSE)
219 ALEffectSlot->AuxSendAuto = iValue;
220 else
221 alSetError(AL_INVALID_VALUE);
222 break;
224 default:
225 alSetError(AL_INVALID_ENUM);
226 break;
229 else
230 alSetError(AL_INVALID_NAME);
232 ProcessContext(Context);
235 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
237 ALCcontext *Context;
239 Context = GetContextSuspended();
240 if(!Context)
242 alSetError(AL_INVALID_OPERATION);
243 return;
246 if (alIsAuxiliaryEffectSlot(effectslot))
248 switch(param)
250 case AL_EFFECTSLOT_EFFECT:
251 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
252 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
253 break;
255 default:
256 alSetError(AL_INVALID_ENUM);
257 break;
260 else
261 alSetError(AL_INVALID_NAME);
263 ProcessContext(Context);
266 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
268 ALCcontext *Context;
270 Context = GetContextSuspended();
271 if(!Context)
273 alSetError(AL_INVALID_OPERATION);
274 return;
277 if (alIsAuxiliaryEffectSlot(effectslot))
279 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
281 switch(param)
283 case AL_EFFECTSLOT_GAIN:
284 if(flValue >= 0.0f && flValue <= 1.0f)
285 ALEffectSlot->Gain = flValue;
286 else
287 alSetError(AL_INVALID_VALUE);
288 break;
290 default:
291 alSetError(AL_INVALID_ENUM);
292 break;
295 else
296 alSetError(AL_INVALID_NAME);
298 ProcessContext(Context);
301 ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
303 ALCcontext *Context;
305 Context = GetContextSuspended();
306 if(!Context)
308 alSetError(AL_INVALID_OPERATION);
309 return;
312 if (alIsAuxiliaryEffectSlot(effectslot))
314 switch(param)
316 case AL_EFFECTSLOT_GAIN:
317 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
318 break;
320 default:
321 alSetError(AL_INVALID_ENUM);
322 break;
325 else
326 alSetError(AL_INVALID_NAME);
328 ProcessContext(Context);
331 ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
333 ALCcontext *Context;
335 Context = GetContextSuspended();
336 if(!Context)
338 alSetError(AL_INVALID_OPERATION);
339 return;
342 if (alIsAuxiliaryEffectSlot(effectslot))
344 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
346 switch(param)
348 case AL_EFFECTSLOT_EFFECT:
349 *piValue = ALEffectSlot->effect.effect;
350 break;
352 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
353 *piValue = ALEffectSlot->AuxSendAuto;
354 break;
356 default:
357 alSetError(AL_INVALID_ENUM);
358 break;
361 else
362 alSetError(AL_INVALID_NAME);
364 ProcessContext(Context);
367 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
369 ALCcontext *Context;
371 Context = GetContextSuspended();
372 if(!Context)
374 alSetError(AL_INVALID_OPERATION);
375 return;
378 if (alIsAuxiliaryEffectSlot(effectslot))
380 switch(param)
382 case AL_EFFECTSLOT_EFFECT:
383 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
384 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
385 break;
387 default:
388 alSetError(AL_INVALID_ENUM);
389 break;
392 else
393 alSetError(AL_INVALID_NAME);
395 ProcessContext(Context);
398 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
400 ALCcontext *Context;
402 Context = GetContextSuspended();
403 if(!Context)
405 alSetError(AL_INVALID_OPERATION);
406 return;
409 if (alIsAuxiliaryEffectSlot(effectslot))
411 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
413 switch(param)
415 case AL_EFFECTSLOT_GAIN:
416 *pflValue = ALEffectSlot->Gain;
417 break;
419 default:
420 alSetError(AL_INVALID_ENUM);
421 break;
424 else
425 alSetError(AL_INVALID_NAME);
427 ProcessContext(Context);
430 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
432 ALCcontext *Context;
434 Context = GetContextSuspended();
435 if(!Context)
437 alSetError(AL_INVALID_OPERATION);
438 return;
441 if (alIsAuxiliaryEffectSlot(effectslot))
443 switch(param)
445 case AL_EFFECTSLOT_GAIN:
446 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
447 break;
449 default:
450 alSetError(AL_INVALID_ENUM);
451 break;
454 else
455 alSetError(AL_INVALID_NAME);
457 ProcessContext(Context);
461 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
463 if((!effect) || (effect->type != ALEffectSlot->effect.type))
465 ALeffectState *NewState = NULL;
466 if(effect)
468 if(effect->type == AL_EFFECT_EAXREVERB)
469 NewState = EAXVerbCreate(Context);
470 else if(effect->type == AL_EFFECT_REVERB)
471 NewState = VerbCreate(Context);
472 else if(effect->type == AL_EFFECT_ECHO)
473 NewState = EchoCreate(Context);
474 /* No new state? An error occured.. */
475 if(!NewState)
476 return;
478 if(ALEffectSlot->EffectState)
479 ALEffect_Destroy(ALEffectSlot->EffectState);
480 ALEffectSlot->EffectState = NewState;
482 if(!effect)
484 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
485 return;
487 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
488 ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
492 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
494 #ifdef _DEBUG
495 if(Context->AuxiliaryEffectSlotCount > 0)
496 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
497 #endif
499 while(Context->AuxiliaryEffectSlot)
501 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
502 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
504 // Release effectslot structure
505 if(temp->EffectState)
506 ALEffect_Destroy(temp->EffectState);
507 ALTHUNK_REMOVEENTRY(temp->effectslot);
509 memset(temp, 0, sizeof(ALeffectslot));
510 free(temp);
512 Context->AuxiliaryEffectSlotCount = 0;