Mark extension functions with AL_API/ALC_API
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blob16d26ae252e32da301839b7dff929c5fde46c494
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"
32 #include "alSource.h"
35 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect);
37 DECL_VERIFIER(EffectSlot, ALeffectslot, effectslot)
38 DECL_VERIFIER(Effect, ALeffect, effect)
40 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
42 ALCcontext *Context;
43 ALsizei i=0, j;
45 Context = GetContextSuspended();
46 if(!Context) return;
48 if (n > 0)
50 ALCdevice *Device = Context->Device;
52 if(Context->EffectSlotCount+n <= Device->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 *end;
58 ALeffectslot **list = &Context->EffectSlotList;
59 while(*list)
60 list = &(*list)->next;
62 end = *list;
63 while(i < n)
65 *list = calloc(1, sizeof(ALeffectslot));
66 if(!(*list) || !((*list)->EffectState=NoneCreate()))
68 // We must have run out or memory
69 free(*list); *list = NULL;
70 while(end->next)
72 ALeffectslot *temp = end->next;
73 end->next = temp->next;
75 ALEffect_Destroy(temp->EffectState);
76 ALTHUNK_REMOVEENTRY(temp->effectslot);
77 Context->EffectSlotCount--;
78 free(temp);
80 alSetError(Context, AL_OUT_OF_MEMORY);
81 break;
84 (*list)->Gain = 1.0;
85 (*list)->AuxSendAuto = AL_TRUE;
86 for(j = 0;j < BUFFERSIZE;j++)
87 (*list)->WetBuffer[j] = 0.0f;
88 (*list)->refcount = 0;
90 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
91 (*list)->effectslot = effectslots[i];
93 Context->EffectSlotCount++;
94 i++;
96 list = &(*list)->next;
100 else
101 alSetError(Context, AL_INVALID_OPERATION);
104 ProcessContext(Context);
107 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
109 ALCcontext *Context;
110 ALeffectslot *ALAuxiliaryEffectSlot;
111 ALsizei i;
113 Context = GetContextSuspended();
114 if(!Context) return;
116 if (n >= 0)
118 // Check that all effectslots are valid
119 for (i = 0; i < n; i++)
121 if((ALAuxiliaryEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslots[i])) == NULL)
123 alSetError(Context, AL_INVALID_NAME);
124 break;
126 else
128 if(ALAuxiliaryEffectSlot->refcount > 0)
130 alSetError(Context, AL_INVALID_NAME);
131 break;
136 if (i == n)
138 // All effectslots are valid
139 for (i = 0; i < n; i++)
141 // Recheck that the effectslot is valid, because there could be duplicated names
142 if((ALAuxiliaryEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslots[i])) != NULL)
144 ALeffectslot **list;
146 // Remove Source from list of Sources
147 list = &Context->EffectSlotList;
148 while(*list && *list != ALAuxiliaryEffectSlot)
149 list = &(*list)->next;
151 if(*list)
152 *list = (*list)->next;
153 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
155 if(ALAuxiliaryEffectSlot->EffectState)
156 ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
158 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
159 free(ALAuxiliaryEffectSlot);
161 Context->EffectSlotCount--;
166 else
167 alSetError(Context, AL_INVALID_VALUE);
169 ProcessContext(Context);
172 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
174 ALCcontext *Context;
175 ALboolean result;
177 Context = GetContextSuspended();
178 if(!Context) return AL_FALSE;
180 result = (VerifyEffectSlot(Context->EffectSlotList, effectslot) ?
181 AL_TRUE : AL_FALSE);
183 ProcessContext(Context);
185 return result;
188 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
190 ALCcontext *Context;
191 ALboolean updateSources = AL_FALSE;
192 ALeffectslot *ALEffectSlot;
194 Context = GetContextSuspended();
195 if(!Context) return;
197 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
199 switch(param)
201 case AL_EFFECTSLOT_EFFECT: {
202 ALeffect *effect = NULL;
204 if(iValue == 0 ||
205 (effect=VerifyEffect(Context->Device->EffectList, iValue)) != NULL)
207 InitializeEffect(Context, ALEffectSlot, effect);
208 updateSources = AL_TRUE;
210 else
211 alSetError(Context, AL_INVALID_VALUE);
212 } break;
214 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
215 if(iValue == AL_TRUE || iValue == AL_FALSE)
217 ALEffectSlot->AuxSendAuto = iValue;
218 updateSources = AL_TRUE;
220 else
221 alSetError(Context, AL_INVALID_VALUE);
222 break;
224 default:
225 alSetError(Context, AL_INVALID_ENUM);
226 break;
229 else
230 alSetError(Context, AL_INVALID_NAME);
232 // Force updating the sources that use this slot, since it affects the
233 // sending parameters
234 if(updateSources)
236 ALsource *source = Context->SourceList;
237 while(source)
239 ALuint i;
240 for(i = 0;i < MAX_SENDS;i++)
242 if(!source->Send[i].Slot ||
243 source->Send[i].Slot->effectslot != effectslot)
244 continue;
245 source->NeedsUpdate = AL_TRUE;
246 break;
248 source = source->next;
252 ProcessContext(Context);
255 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
257 ALCcontext *Context;
259 Context = GetContextSuspended();
260 if(!Context) return;
262 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
264 switch(param)
266 case AL_EFFECTSLOT_EFFECT:
267 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
268 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
269 break;
271 default:
272 alSetError(Context, AL_INVALID_ENUM);
273 break;
276 else
277 alSetError(Context, AL_INVALID_NAME);
279 ProcessContext(Context);
282 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
284 ALCcontext *Context;
285 ALeffectslot *ALEffectSlot;
287 Context = GetContextSuspended();
288 if(!Context) return;
290 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
292 switch(param)
294 case AL_EFFECTSLOT_GAIN:
295 if(flValue >= 0.0f && flValue <= 1.0f)
296 ALEffectSlot->Gain = flValue;
297 else
298 alSetError(Context, AL_INVALID_VALUE);
299 break;
301 default:
302 alSetError(Context, AL_INVALID_ENUM);
303 break;
306 else
307 alSetError(Context, AL_INVALID_NAME);
309 ProcessContext(Context);
312 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
314 ALCcontext *Context;
316 Context = GetContextSuspended();
317 if(!Context) return;
319 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
321 switch(param)
323 case AL_EFFECTSLOT_GAIN:
324 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
325 break;
327 default:
328 alSetError(Context, AL_INVALID_ENUM);
329 break;
332 else
333 alSetError(Context, AL_INVALID_NAME);
335 ProcessContext(Context);
338 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
340 ALCcontext *Context;
341 ALeffectslot *ALEffectSlot;
343 Context = GetContextSuspended();
344 if(!Context) return;
346 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
348 switch(param)
350 case AL_EFFECTSLOT_EFFECT:
351 *piValue = ALEffectSlot->effect.effect;
352 break;
354 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
355 *piValue = ALEffectSlot->AuxSendAuto;
356 break;
358 default:
359 alSetError(Context, AL_INVALID_ENUM);
360 break;
363 else
364 alSetError(Context, AL_INVALID_NAME);
366 ProcessContext(Context);
369 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
371 ALCcontext *Context;
373 Context = GetContextSuspended();
374 if(!Context) return;
376 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
378 switch(param)
380 case AL_EFFECTSLOT_EFFECT:
381 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
382 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
383 break;
385 default:
386 alSetError(Context, AL_INVALID_ENUM);
387 break;
390 else
391 alSetError(Context, AL_INVALID_NAME);
393 ProcessContext(Context);
396 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
398 ALCcontext *Context;
399 ALeffectslot *ALEffectSlot;
401 Context = GetContextSuspended();
402 if(!Context) return;
404 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
406 switch(param)
408 case AL_EFFECTSLOT_GAIN:
409 *pflValue = ALEffectSlot->Gain;
410 break;
412 default:
413 alSetError(Context, AL_INVALID_ENUM);
414 break;
417 else
418 alSetError(Context, AL_INVALID_NAME);
420 ProcessContext(Context);
423 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
425 ALCcontext *Context;
427 Context = GetContextSuspended();
428 if(!Context) return;
430 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
432 switch(param)
434 case AL_EFFECTSLOT_GAIN:
435 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
436 break;
438 default:
439 alSetError(Context, AL_INVALID_ENUM);
440 break;
443 else
444 alSetError(Context, AL_INVALID_NAME);
446 ProcessContext(Context);
450 static ALvoid NoneDestroy(ALeffectState *State)
451 { free(State); }
452 static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
454 return AL_TRUE;
455 (void)State;
456 (void)Device;
458 static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect)
460 (void)State;
461 (void)Context;
462 (void)Effect;
464 static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
466 (void)State;
467 (void)Slot;
468 (void)SamplesToDo;
469 (void)SamplesIn;
470 (void)SamplesOut;
472 ALeffectState *NoneCreate(void)
474 ALeffectState *state;
476 state = calloc(1, sizeof(*state));
477 if(!state)
478 return NULL;
480 state->Destroy = NoneDestroy;
481 state->DeviceUpdate = NoneDeviceUpdate;
482 state->Update = NoneUpdate;
483 state->Process = NoneProcess;
485 return state;
488 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
490 if(ALEffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
492 ALeffectState *NewState = NULL;
493 if(!effect || effect->type == AL_EFFECT_NULL)
494 NewState = NoneCreate();
495 else if(effect->type == AL_EFFECT_EAXREVERB)
496 NewState = EAXVerbCreate();
497 else if(effect->type == AL_EFFECT_REVERB)
498 NewState = VerbCreate();
499 else if(effect->type == AL_EFFECT_ECHO)
500 NewState = EchoCreate();
501 /* No new state? An error occured.. */
502 if(NewState == NULL ||
503 ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
505 if(NewState)
506 ALEffect_Destroy(NewState);
507 alSetError(Context, AL_OUT_OF_MEMORY);
508 return;
510 if(ALEffectSlot->EffectState)
511 ALEffect_Destroy(ALEffectSlot->EffectState);
512 ALEffectSlot->EffectState = NewState;
514 if(!effect)
515 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
516 else
517 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
518 ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
522 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
524 while(Context->EffectSlotList)
526 ALeffectslot *temp = Context->EffectSlotList;
527 Context->EffectSlotList = temp->next;
529 // Release effectslot structure
530 ALEffect_Destroy(temp->EffectState);
532 ALTHUNK_REMOVEENTRY(temp->effectslot);
533 memset(temp, 0, sizeof(ALeffectslot));
534 free(temp);
536 Context->EffectSlotCount = 0;