Don't use deprecated macros
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blobbc381bf60a4714cdf2d030657da5df0e74cbda50
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 ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
42 ALCcontext *Context;
43 ALsizei i, 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 **list = &Context->EffectSlotList;
58 while(*list)
59 list = &(*list)->next;
61 i = 0;
62 while(i < n)
64 *list = calloc(1, sizeof(ALeffectslot));
65 if(!(*list) || !((*list)->EffectState=NoneCreate()))
67 // We must have run out or memory
68 free(*list); *list = NULL;
69 alDeleteAuxiliaryEffectSlots(i, effectslots);
70 alSetError(Context, 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->EffectSlotCount++;
84 i++;
86 list = &(*list)->next;
90 else
91 alSetError(Context, 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) return;
106 if (n >= 0)
108 // Check that all effectslots are valid
109 for (i = 0; i < n; i++)
111 if((ALAuxiliaryEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslots[i])) == NULL)
113 alSetError(Context, AL_INVALID_NAME);
114 break;
116 else
118 if(ALAuxiliaryEffectSlot->refcount > 0)
120 alSetError(Context, AL_INVALID_NAME);
121 break;
126 if (i == n)
128 // All effectslots are valid
129 for (i = 0; i < n; i++)
131 // Recheck that the effectslot is valid, because there could be duplicated names
132 if((ALAuxiliaryEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslots[i])) != NULL)
134 ALeffectslot **list;
136 // Remove Source from list of Sources
137 list = &Context->EffectSlotList;
138 while(*list && *list != ALAuxiliaryEffectSlot)
139 list = &(*list)->next;
141 if(*list)
142 *list = (*list)->next;
143 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
145 if(ALAuxiliaryEffectSlot->EffectState)
146 ALEffect_Destroy(ALAuxiliaryEffectSlot->EffectState);
148 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
149 free(ALAuxiliaryEffectSlot);
151 Context->EffectSlotCount--;
156 else
157 alSetError(Context, AL_INVALID_VALUE);
159 ProcessContext(Context);
162 ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
164 ALCcontext *Context;
165 ALboolean result;
167 Context = GetContextSuspended();
168 if(!Context) return AL_FALSE;
170 result = (VerifyEffectSlot(Context->EffectSlotList, effectslot) ?
171 AL_TRUE : AL_FALSE);
173 ProcessContext(Context);
175 return result;
178 ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
180 ALCcontext *Context;
181 ALboolean updateSources = AL_FALSE;
182 ALeffectslot *ALEffectSlot;
184 Context = GetContextSuspended();
185 if(!Context) return;
187 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
189 switch(param)
191 case AL_EFFECTSLOT_EFFECT: {
192 ALeffect *effect = NULL;
194 if(iValue == 0 ||
195 (effect=VerifyEffect(Context->Device->EffectList, iValue)) != NULL)
197 InitializeEffect(Context, ALEffectSlot, effect);
198 updateSources = AL_TRUE;
200 else
201 alSetError(Context, AL_INVALID_VALUE);
202 } break;
204 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
205 if(iValue == AL_TRUE || iValue == AL_FALSE)
207 ALEffectSlot->AuxSendAuto = iValue;
208 updateSources = AL_TRUE;
210 else
211 alSetError(Context, AL_INVALID_VALUE);
212 break;
214 default:
215 alSetError(Context, AL_INVALID_ENUM);
216 break;
219 else
220 alSetError(Context, AL_INVALID_NAME);
222 // Force updating the sources that use this slot, since it affects the
223 // sending parameters
224 if(updateSources)
226 ALsource *source = Context->SourceList;
227 while(source)
229 ALuint i;
230 for(i = 0;i < MAX_SENDS;i++)
232 if(!source->Send[i].Slot ||
233 source->Send[i].Slot->effectslot != effectslot)
234 continue;
235 source->NeedsUpdate = AL_TRUE;
236 break;
238 source = source->next;
242 ProcessContext(Context);
245 ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
247 ALCcontext *Context;
249 Context = GetContextSuspended();
250 if(!Context) return;
252 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
254 switch(param)
256 case AL_EFFECTSLOT_EFFECT:
257 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
258 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
259 break;
261 default:
262 alSetError(Context, AL_INVALID_ENUM);
263 break;
266 else
267 alSetError(Context, AL_INVALID_NAME);
269 ProcessContext(Context);
272 ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
274 ALCcontext *Context;
275 ALeffectslot *ALEffectSlot;
277 Context = GetContextSuspended();
278 if(!Context) return;
280 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
282 switch(param)
284 case AL_EFFECTSLOT_GAIN:
285 if(flValue >= 0.0f && flValue <= 1.0f)
286 ALEffectSlot->Gain = flValue;
287 else
288 alSetError(Context, AL_INVALID_VALUE);
289 break;
291 default:
292 alSetError(Context, AL_INVALID_ENUM);
293 break;
296 else
297 alSetError(Context, AL_INVALID_NAME);
299 ProcessContext(Context);
302 ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
304 ALCcontext *Context;
306 Context = GetContextSuspended();
307 if(!Context) return;
309 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
311 switch(param)
313 case AL_EFFECTSLOT_GAIN:
314 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
315 break;
317 default:
318 alSetError(Context, AL_INVALID_ENUM);
319 break;
322 else
323 alSetError(Context, AL_INVALID_NAME);
325 ProcessContext(Context);
328 ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
330 ALCcontext *Context;
331 ALeffectslot *ALEffectSlot;
333 Context = GetContextSuspended();
334 if(!Context) return;
336 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
338 switch(param)
340 case AL_EFFECTSLOT_EFFECT:
341 *piValue = ALEffectSlot->effect.effect;
342 break;
344 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
345 *piValue = ALEffectSlot->AuxSendAuto;
346 break;
348 default:
349 alSetError(Context, AL_INVALID_ENUM);
350 break;
353 else
354 alSetError(Context, AL_INVALID_NAME);
356 ProcessContext(Context);
359 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
361 ALCcontext *Context;
363 Context = GetContextSuspended();
364 if(!Context) return;
366 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
368 switch(param)
370 case AL_EFFECTSLOT_EFFECT:
371 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
372 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
373 break;
375 default:
376 alSetError(Context, AL_INVALID_ENUM);
377 break;
380 else
381 alSetError(Context, AL_INVALID_NAME);
383 ProcessContext(Context);
386 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
388 ALCcontext *Context;
389 ALeffectslot *ALEffectSlot;
391 Context = GetContextSuspended();
392 if(!Context) return;
394 if((ALEffectSlot=VerifyEffectSlot(Context->EffectSlotList, effectslot)) != NULL)
396 switch(param)
398 case AL_EFFECTSLOT_GAIN:
399 *pflValue = ALEffectSlot->Gain;
400 break;
402 default:
403 alSetError(Context, AL_INVALID_ENUM);
404 break;
407 else
408 alSetError(Context, AL_INVALID_NAME);
410 ProcessContext(Context);
413 ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
415 ALCcontext *Context;
417 Context = GetContextSuspended();
418 if(!Context) return;
420 if(VerifyEffectSlot(Context->EffectSlotList, effectslot) != NULL)
422 switch(param)
424 case AL_EFFECTSLOT_GAIN:
425 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
426 break;
428 default:
429 alSetError(Context, AL_INVALID_ENUM);
430 break;
433 else
434 alSetError(Context, AL_INVALID_NAME);
436 ProcessContext(Context);
440 static ALvoid NoneDestroy(ALeffectState *State)
441 { free(State); }
442 static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device)
444 return AL_TRUE;
445 (void)State;
446 (void)Device;
448 static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffect *Effect)
450 (void)State;
451 (void)Context;
452 (void)Effect;
454 static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[OUTPUTCHANNELS])
456 (void)State;
457 (void)Slot;
458 (void)SamplesToDo;
459 (void)SamplesIn;
460 (void)SamplesOut;
462 ALeffectState *NoneCreate(void)
464 ALeffectState *state;
466 state = calloc(1, sizeof(*state));
467 if(!state)
468 return NULL;
470 state->Destroy = NoneDestroy;
471 state->DeviceUpdate = NoneDeviceUpdate;
472 state->Update = NoneUpdate;
473 state->Process = NoneProcess;
475 return state;
478 static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *ALEffectSlot, ALeffect *effect)
480 if(ALEffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL))
482 ALeffectState *NewState = NULL;
483 if(!effect || effect->type == AL_EFFECT_NULL)
484 NewState = NoneCreate();
485 else if(effect->type == AL_EFFECT_EAXREVERB)
486 NewState = EAXVerbCreate();
487 else if(effect->type == AL_EFFECT_REVERB)
488 NewState = VerbCreate();
489 else if(effect->type == AL_EFFECT_ECHO)
490 NewState = EchoCreate();
491 /* No new state? An error occured.. */
492 if(NewState == NULL ||
493 ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE)
495 if(NewState)
496 ALEffect_Destroy(NewState);
497 alSetError(Context, AL_OUT_OF_MEMORY);
498 return;
500 if(ALEffectSlot->EffectState)
501 ALEffect_Destroy(ALEffectSlot->EffectState);
502 ALEffectSlot->EffectState = NewState;
504 if(!effect)
505 memset(&ALEffectSlot->effect, 0, sizeof(ALEffectSlot->effect));
506 else
507 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
508 ALEffect_Update(ALEffectSlot->EffectState, Context, effect);
512 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
514 while(Context->EffectSlotList)
516 ALeffectslot *temp = Context->EffectSlotList;
517 Context->EffectSlotList = temp->next;
519 // Release effectslot structure
520 if(temp->EffectState)
521 ALEffect_Destroy(temp->EffectState);
522 ALTHUNK_REMOVEENTRY(temp->effectslot);
524 memset(temp, 0, sizeof(ALeffectslot));
525 free(temp);
527 Context->EffectSlotCount = 0;