Set an error if effect creation fails
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blobf606a099732b80732d870b9a89ac996f5b6e218b
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 if(Context->AuxiliaryEffectSlotCount+n <= Context->AuxiliaryEffectSlotMax)
54 // Check that enough memory has been allocted in the 'effectslots' array for n Effect Slots
55 if (!IsBadWritePtr((void*)effectslots, n * sizeof(ALuint)))
57 ALeffectslot **list = &Context->AuxiliaryEffectSlot;
58 while(*list)
59 list = &(*list)->next;
61 i = 0;
62 while(i < n)
64 *list = calloc(1, sizeof(ALeffectslot));
65 if(!(*list))
67 // We must have run out or memory
68 alDeleteAuxiliaryEffectSlots(i, effectslots);
69 alSetError(AL_OUT_OF_MEMORY);
70 break;
73 (*list)->Gain = 1.0;
74 (*list)->AuxSendAuto = AL_TRUE;
75 for(j = 0;j < BUFFERSIZE;j++)
76 (*list)->WetBuffer[j] = 0.0f;
77 (*list)->refcount = 0;
79 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
80 (*list)->effectslot = effectslots[i];
82 Context->AuxiliaryEffectSlotCount++;
83 i++;
85 list = &(*list)->next;
89 else
90 alSetError(AL_INVALID_OPERATION);
93 ProcessContext(Context);
96 ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
98 ALCcontext *Context;
99 ALeffectslot *ALAuxiliaryEffectSlot;
100 ALsizei i;
102 Context = alcGetCurrentContext();
103 if(!Context)
105 alSetError(AL_INVALID_OPERATION);
106 return;
108 SuspendContext(Context);
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 = alcGetCurrentContext();
175 if(!Context)
177 alSetError(AL_INVALID_OPERATION);
178 return AL_FALSE;
180 SuspendContext(Context);
182 list = &Context->AuxiliaryEffectSlot;
183 while(*list && (*list)->effectslot != effectslot)
184 list = &(*list)->next;
186 ProcessContext(Context);
188 return (*list ? AL_TRUE : AL_FALSE);
191 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
193 ALCcontext *Context;
195 Context = alcGetCurrentContext();
196 if(!Context)
198 alSetError(AL_INVALID_OPERATION);
199 return;
201 SuspendContext(Context);
203 if (alIsAuxiliaryEffectSlot(effectslot))
205 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
207 switch(param)
209 case AL_EFFECTSLOT_EFFECT:
210 if(alIsEffect(iValue))
212 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
213 InitializeEffect(Context, ALEffectSlot, effect);
215 else
216 alSetError(AL_INVALID_VALUE);
217 break;
219 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
220 if(iValue == AL_TRUE || iValue == AL_FALSE)
221 ALEffectSlot->AuxSendAuto = iValue;
222 else
223 alSetError(AL_INVALID_VALUE);
224 break;
226 default:
227 alSetError(AL_INVALID_ENUM);
228 break;
231 else
232 alSetError(AL_INVALID_NAME);
234 ProcessContext(Context);
237 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
239 ALCcontext *Context;
241 Context = alcGetCurrentContext();
242 if(!Context)
244 alSetError(AL_INVALID_OPERATION);
245 return;
247 SuspendContext(Context);
249 if (alIsAuxiliaryEffectSlot(effectslot))
251 switch(param)
253 case AL_EFFECTSLOT_EFFECT:
254 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
255 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
256 break;
258 default:
259 alSetError(AL_INVALID_ENUM);
260 break;
263 else
264 alSetError(AL_INVALID_NAME);
266 ProcessContext(Context);
269 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
271 ALCcontext *Context;
273 Context = alcGetCurrentContext();
274 if(!Context)
276 alSetError(AL_INVALID_OPERATION);
277 return;
279 SuspendContext(Context);
281 if (alIsAuxiliaryEffectSlot(effectslot))
283 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
285 switch(param)
287 case AL_EFFECTSLOT_GAIN:
288 if(flValue >= 0.0f && flValue <= 1.0f)
289 ALEffectSlot->Gain = flValue;
290 else
291 alSetError(AL_INVALID_VALUE);
292 break;
294 default:
295 alSetError(AL_INVALID_ENUM);
296 break;
299 else
300 alSetError(AL_INVALID_NAME);
302 ProcessContext(Context);
305 ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
307 ALCcontext *Context;
309 Context = alcGetCurrentContext();
310 if(!Context)
312 alSetError(AL_INVALID_OPERATION);
313 return;
315 SuspendContext(Context);
317 if (alIsAuxiliaryEffectSlot(effectslot))
319 switch(param)
321 case AL_EFFECTSLOT_GAIN:
322 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
323 break;
325 default:
326 alSetError(AL_INVALID_ENUM);
327 break;
330 else
331 alSetError(AL_INVALID_NAME);
333 ProcessContext(Context);
336 ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
338 ALCcontext *Context;
340 Context = alcGetCurrentContext();
341 if(!Context)
343 alSetError(AL_INVALID_OPERATION);
344 return;
346 SuspendContext(Context);
348 if (alIsAuxiliaryEffectSlot(effectslot))
350 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
352 switch(param)
354 case AL_EFFECTSLOT_EFFECT:
355 *piValue = ALEffectSlot->effect.effect;
356 break;
358 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
359 *piValue = ALEffectSlot->AuxSendAuto;
360 break;
362 default:
363 alSetError(AL_INVALID_ENUM);
364 break;
367 else
368 alSetError(AL_INVALID_NAME);
370 ProcessContext(Context);
373 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
375 ALCcontext *Context;
377 Context = alcGetCurrentContext();
378 if(!Context)
380 alSetError(AL_INVALID_OPERATION);
381 return;
383 SuspendContext(Context);
385 if (alIsAuxiliaryEffectSlot(effectslot))
387 switch(param)
389 case AL_EFFECTSLOT_EFFECT:
390 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
391 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
392 break;
394 default:
395 alSetError(AL_INVALID_ENUM);
396 break;
399 else
400 alSetError(AL_INVALID_NAME);
402 ProcessContext(Context);
405 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
407 ALCcontext *Context;
409 Context = alcGetCurrentContext();
410 if(!Context)
412 alSetError(AL_INVALID_OPERATION);
413 return;
415 SuspendContext(Context);
417 if (alIsAuxiliaryEffectSlot(effectslot))
419 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
421 switch(param)
423 case AL_EFFECTSLOT_GAIN:
424 *pflValue = ALEffectSlot->Gain;
425 break;
427 default:
428 alSetError(AL_INVALID_ENUM);
429 break;
432 else
433 alSetError(AL_INVALID_NAME);
435 ProcessContext(Context);
438 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
440 ALCcontext *Context;
442 Context = alcGetCurrentContext();
443 if(!Context)
445 alSetError(AL_INVALID_OPERATION);
446 return;
448 SuspendContext(Context);
450 if (alIsAuxiliaryEffectSlot(effectslot))
452 switch(param)
454 case AL_EFFECTSLOT_GAIN:
455 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
456 break;
458 default:
459 alSetError(AL_INVALID_ENUM);
460 break;
463 else
464 alSetError(AL_INVALID_NAME);
466 ProcessContext(Context);
470 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
472 if((!effect) || (effect->type != ALEffectSlot->effect.type))
474 ALeffectState *NewState = NULL;
475 if(effect)
477 if(effect->type == AL_EFFECT_EAXREVERB)
478 NewState = EAXVerbCreate(Context);
479 else if(effect->type == AL_EFFECT_REVERB)
480 NewState = VerbCreate(Context);
481 else if(effect->type == AL_EFFECT_ECHO)
482 NewState = EchoCreate(Context);
483 /* No new state? An error occured.. */
484 if(!NewState)
485 return;
487 if(ALEffectSlot->EffectState)
488 ALEffect_Destroy(ALEffectSlot->EffectState);
489 ALEffectSlot->EffectState = NewState;
491 if(!effect)
493 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
494 return;
496 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
497 ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
501 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
503 #ifdef _DEBUG
504 if(Context->AuxiliaryEffectSlotCount > 0)
505 AL_PRINT("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", Context->AuxiliaryEffectSlotCount);
506 #endif
508 while(Context->AuxiliaryEffectSlot)
510 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
511 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
513 // Release effectslot structure
514 if(temp->EffectState)
515 ALEffect_Destroy(temp->EffectState);
516 ALTHUNK_REMOVEENTRY(temp->effectslot);
518 memset(temp, 0, sizeof(ALeffectslot));
519 free(temp);
521 Context->AuxiliaryEffectSlotCount = 0;