Fix allocation of multiple effect slots, effects, and filters
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob7eae3476870999e95d4474fae16e69e09aafcf51
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 <stdlib.h>
23 #include "config.h"
25 #include "AL/al.h"
26 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alAuxEffectSlot.h"
30 #include "alThunk.h"
31 #include "alError.h"
34 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
36 ALCcontext *Context;
37 ALsizei i;
39 Context = alcGetCurrentContext();
40 if(!Context)
42 alSetError(AL_INVALID_OPERATION);
43 return;
45 SuspendContext(Context);
47 if (n > 0)
49 /* NOTE: We only support one slot currently */
50 if(n == 1 && Context->AuxiliaryEffectSlotCount == 0)
52 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
53 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
55 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
56 while(*list)
57 list = &(*list)->next;
59 i = 0;
60 while(i < n)
62 *list = calloc(1, sizeof(ALeffectslot));
63 if(!(*list))
65 // We must have run out or memory
66 alDeleteAuxiliaryEffectSlots(i, effectslots);
67 alSetError(AL_OUT_OF_MEMORY);
68 break;
71 (*list)->Gain = 1.0;
72 (*list)->AuxSendAuto = AL_TRUE;
74 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
75 (*list)->effectslot = effectslots[i];
77 Context->AuxiliaryEffectSlotCount++;
78 i++;
80 list = &(*list)->next;
84 else
85 alSetError(AL_INVALID_OPERATION);
88 ProcessContext(Context);
91 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
93 ALCcontext *Context;
94 ALeffectslot *ALAuxiliaryEffectSlot;
95 ALsizei i;
97 Context = alcGetCurrentContext();
98 if(!Context)
100 alSetError(AL_INVALID_OPERATION);
101 return;
103 SuspendContext(Context);
105 if (n >= 0)
107 // Check that all effectslots are valid
108 for (i = 0; i < n; i++)
110 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
112 alSetError(AL_INVALID_NAME);
113 break;
117 if (i == n)
119 // All effectslots are valid
120 for (i = 0; i < n; i++)
122 // Recheck that the effectslot is valid, because there could be duplicated names
123 if (alIsAuxiliaryEffectSlot(effectslots[i]))
125 ALeffectslot **list;
127 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
129 // Remove Source from list of Sources
130 list = &Context->AuxiliaryEffectSlot;
131 while(*list && *list != ALAuxiliaryEffectSlot)
132 list = &(*list)->next;
134 if(*list)
135 *list = (*list)->next;
136 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
138 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
139 free(ALAuxiliaryEffectSlot);
141 Context->AuxiliaryEffectSlotCount--;
146 else
147 alSetError(AL_INVALID_VALUE);
149 ProcessContext(Context);
152 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
154 ALCcontext *Context;
155 ALeffectslot **list;
157 Context = alcGetCurrentContext();
158 if(!Context)
160 alSetError(AL_INVALID_OPERATION);
161 return AL_FALSE;
163 SuspendContext(Context);
165 list = &Context->AuxiliaryEffectSlot;
166 while(*list && (*list)->effectslot != effectslot)
167 list = &(*list)->next;
169 ProcessContext(Context);
171 return (*list ? AL_TRUE : AL_FALSE);
174 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
176 ALCcontext *Context;
178 Context = alcGetCurrentContext();
179 if(!Context)
181 alSetError(AL_INVALID_OPERATION);
182 return;
184 SuspendContext(Context);
186 if (alIsAuxiliaryEffectSlot(effectslot))
188 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
190 switch(param)
192 case AL_EFFECTSLOT_EFFECT:
193 if(alIsEffect(iValue))
195 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
196 if(!effect)
198 ALEffectSlot->effect.type = AL_EFFECT_NULL;
199 ALEffectSlot->effect.effect = 0;
201 else
202 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
204 else
205 alSetError(AL_INVALID_VALUE);
206 break;
208 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
209 if(iValue == AL_TRUE || iValue == AL_FALSE)
210 ALEffectSlot->AuxSendAuto = iValue;
211 else
212 alSetError(AL_INVALID_VALUE);
213 break;
215 default:
216 alSetError(AL_INVALID_ENUM);
217 break;
220 else
221 alSetError(AL_INVALID_NAME);
223 ProcessContext(Context);
226 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
228 ALCcontext *Context;
230 Context = alcGetCurrentContext();
231 if(!Context)
233 alSetError(AL_INVALID_OPERATION);
234 return;
236 SuspendContext(Context);
238 if (alIsAuxiliaryEffectSlot(effectslot))
240 switch(param)
242 case AL_EFFECTSLOT_EFFECT:
243 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
244 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
245 break;
247 default:
248 alSetError(AL_INVALID_ENUM);
249 break;
252 else
253 alSetError(AL_INVALID_NAME);
255 ProcessContext(Context);
258 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
260 ALCcontext *Context;
262 Context = alcGetCurrentContext();
263 if(!Context)
265 alSetError(AL_INVALID_OPERATION);
266 return;
268 SuspendContext(Context);
270 if (alIsAuxiliaryEffectSlot(effectslot))
272 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
274 switch(param)
276 case AL_EFFECTSLOT_GAIN:
277 if(flValue >= 0.0f && flValue <= 1.0f)
278 ALEffectSlot->Gain = flValue;
279 else
280 alSetError(AL_INVALID_VALUE);
281 break;
283 default:
284 alSetError(AL_INVALID_ENUM);
285 break;
288 else
289 alSetError(AL_INVALID_NAME);
291 ProcessContext(Context);
294 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
296 ALCcontext *Context;
298 Context = alcGetCurrentContext();
299 if(!Context)
301 alSetError(AL_INVALID_OPERATION);
302 return;
304 SuspendContext(Context);
306 if (alIsAuxiliaryEffectSlot(effectslot))
308 switch(param)
310 case AL_EFFECTSLOT_GAIN:
311 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
312 break;
314 default:
315 alSetError(AL_INVALID_ENUM);
316 break;
319 else
320 alSetError(AL_INVALID_NAME);
322 ProcessContext(Context);
325 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
327 ALCcontext *Context;
329 Context = alcGetCurrentContext();
330 if(!Context)
332 alSetError(AL_INVALID_OPERATION);
333 return;
335 SuspendContext(Context);
337 if (alIsAuxiliaryEffectSlot(effectslot))
339 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
341 switch(param)
343 case AL_EFFECTSLOT_EFFECT:
344 *piValue = ALEffectSlot->effect.effect;
345 break;
347 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
348 *piValue = ALEffectSlot->AuxSendAuto;
349 break;
351 default:
352 alSetError(AL_INVALID_ENUM);
353 break;
356 else
357 alSetError(AL_INVALID_NAME);
359 ProcessContext(Context);
362 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
364 ALCcontext *Context;
366 Context = alcGetCurrentContext();
367 if(!Context)
369 alSetError(AL_INVALID_OPERATION);
370 return;
372 SuspendContext(Context);
374 if (alIsAuxiliaryEffectSlot(effectslot))
376 switch(param)
378 case AL_EFFECTSLOT_EFFECT:
379 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
380 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
381 break;
383 default:
384 alSetError(AL_INVALID_ENUM);
385 break;
388 else
389 alSetError(AL_INVALID_NAME);
391 ProcessContext(Context);
394 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
396 ALCcontext *Context;
398 Context = alcGetCurrentContext();
399 if(!Context)
401 alSetError(AL_INVALID_OPERATION);
402 return;
404 SuspendContext(Context);
406 if (alIsAuxiliaryEffectSlot(effectslot))
408 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
410 switch(param)
412 case AL_EFFECTSLOT_GAIN:
413 *pflValue = ALEffectSlot->Gain;
414 break;
416 default:
417 alSetError(AL_INVALID_ENUM);
418 break;
421 else
422 alSetError(AL_INVALID_NAME);
424 ProcessContext(Context);
427 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
429 ALCcontext *Context;
431 Context = alcGetCurrentContext();
432 if(!Context)
434 alSetError(AL_INVALID_OPERATION);
435 return;
437 SuspendContext(Context);
439 if (alIsAuxiliaryEffectSlot(effectslot))
441 switch(param)
443 case AL_EFFECTSLOT_GAIN:
444 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
445 break;
447 default:
448 alSetError(AL_INVALID_ENUM);
449 break;
452 else
453 alSetError(AL_INVALID_NAME);
455 ProcessContext(Context);
459 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
461 #ifdef _DEBUG
462 if(Context->AuxiliaryEffectSlotCount > 0)
463 AL_PRINT("exit() %d AuxiliaryEffectSlot(s) NOT deleted\n", Context->AuxiliaryEffectSlotCount);
464 #endif
466 while(Context->AuxiliaryEffectSlot)
468 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
469 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
471 // Release effectslot structure
472 memset(temp, 0, sizeof(ALeffectslot));
473 free(temp);
475 Context->AuxiliaryEffectSlotCount = 0;