Keep track of references to effect slots, so they aren't deleted while in use
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blobf39659e9f55ec1bff3b66f39fc45630616be7348
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;
73 (*list)->refcount = 0;
75 effectslots[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
76 (*list)->effectslot = effectslots[i];
78 Context->AuxiliaryEffectSlotCount++;
79 i++;
81 list = &(*list)->next;
85 else
86 alSetError(AL_INVALID_OPERATION);
89 ProcessContext(Context);
92 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
94 ALCcontext *Context;
95 ALeffectslot *ALAuxiliaryEffectSlot;
96 ALsizei i;
98 Context = alcGetCurrentContext();
99 if(!Context)
101 alSetError(AL_INVALID_OPERATION);
102 return;
104 SuspendContext(Context);
106 if (n >= 0)
108 // Check that all effectslots are valid
109 for (i = 0; i < n; i++)
111 if (!alIsAuxiliaryEffectSlot(effectslots[i]))
113 alSetError(AL_INVALID_NAME);
114 break;
116 else
118 ALAuxiliaryEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]);
119 if(ALAuxiliaryEffectSlot->refcount > 0)
121 alSetError(AL_INVALID_NAME);
122 break;
127 if (i == n)
129 // All effectslots are valid
130 for (i = 0; i < n; i++)
132 // Recheck that the effectslot is valid, because there could be duplicated names
133 if (alIsAuxiliaryEffectSlot(effectslots[i]))
135 ALeffectslot **list;
137 ALAuxiliaryEffectSlot = ((ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslots[i]));
139 // Remove Source from list of Sources
140 list = &Context->AuxiliaryEffectSlot;
141 while(*list && *list != ALAuxiliaryEffectSlot)
142 list = &(*list)->next;
144 if(*list)
145 *list = (*list)->next;
146 ALTHUNK_REMOVEENTRY(ALAuxiliaryEffectSlot->effectslot);
148 memset(ALAuxiliaryEffectSlot, 0, sizeof(ALeffectslot));
149 free(ALAuxiliaryEffectSlot);
151 Context->AuxiliaryEffectSlotCount--;
156 else
157 alSetError(AL_INVALID_VALUE);
159 ProcessContext(Context);
162 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
164 ALCcontext *Context;
165 ALeffectslot **list;
167 Context = alcGetCurrentContext();
168 if(!Context)
170 alSetError(AL_INVALID_OPERATION);
171 return AL_FALSE;
173 SuspendContext(Context);
175 list = &Context->AuxiliaryEffectSlot;
176 while(*list && (*list)->effectslot != effectslot)
177 list = &(*list)->next;
179 ProcessContext(Context);
181 return (*list ? AL_TRUE : AL_FALSE);
184 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue)
186 ALCcontext *Context;
188 Context = alcGetCurrentContext();
189 if(!Context)
191 alSetError(AL_INVALID_OPERATION);
192 return;
194 SuspendContext(Context);
196 if (alIsAuxiliaryEffectSlot(effectslot))
198 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
200 switch(param)
202 case AL_EFFECTSLOT_EFFECT:
203 if(alIsEffect(iValue))
205 ALeffect *effect = (ALeffect*)ALTHUNK_LOOKUPENTRY(iValue);
206 if(!effect)
208 ALEffectSlot->effect.type = AL_EFFECT_NULL;
209 ALEffectSlot->effect.effect = 0;
211 else
212 memcpy(&ALEffectSlot->effect, effect, sizeof(*effect));
214 else
215 alSetError(AL_INVALID_VALUE);
216 break;
218 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
219 if(iValue == AL_TRUE || iValue == AL_FALSE)
220 ALEffectSlot->AuxSendAuto = iValue;
221 else
222 alSetError(AL_INVALID_VALUE);
223 break;
225 default:
226 alSetError(AL_INVALID_ENUM);
227 break;
230 else
231 alSetError(AL_INVALID_NAME);
233 ProcessContext(Context);
236 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
238 ALCcontext *Context;
240 Context = alcGetCurrentContext();
241 if(!Context)
243 alSetError(AL_INVALID_OPERATION);
244 return;
246 SuspendContext(Context);
248 if (alIsAuxiliaryEffectSlot(effectslot))
250 switch(param)
252 case AL_EFFECTSLOT_EFFECT:
253 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
254 alAuxiliaryEffectSloti(effectslot, param, piValues[0]);
255 break;
257 default:
258 alSetError(AL_INVALID_ENUM);
259 break;
262 else
263 alSetError(AL_INVALID_NAME);
265 ProcessContext(Context);
268 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue)
270 ALCcontext *Context;
272 Context = alcGetCurrentContext();
273 if(!Context)
275 alSetError(AL_INVALID_OPERATION);
276 return;
278 SuspendContext(Context);
280 if (alIsAuxiliaryEffectSlot(effectslot))
282 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
284 switch(param)
286 case AL_EFFECTSLOT_GAIN:
287 if(flValue >= 0.0f && flValue <= 1.0f)
288 ALEffectSlot->Gain = flValue;
289 else
290 alSetError(AL_INVALID_VALUE);
291 break;
293 default:
294 alSetError(AL_INVALID_ENUM);
295 break;
298 else
299 alSetError(AL_INVALID_NAME);
301 ProcessContext(Context);
304 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
306 ALCcontext *Context;
308 Context = alcGetCurrentContext();
309 if(!Context)
311 alSetError(AL_INVALID_OPERATION);
312 return;
314 SuspendContext(Context);
316 if (alIsAuxiliaryEffectSlot(effectslot))
318 switch(param)
320 case AL_EFFECTSLOT_GAIN:
321 alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]);
322 break;
324 default:
325 alSetError(AL_INVALID_ENUM);
326 break;
329 else
330 alSetError(AL_INVALID_NAME);
332 ProcessContext(Context);
335 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue)
337 ALCcontext *Context;
339 Context = alcGetCurrentContext();
340 if(!Context)
342 alSetError(AL_INVALID_OPERATION);
343 return;
345 SuspendContext(Context);
347 if (alIsAuxiliaryEffectSlot(effectslot))
349 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
351 switch(param)
353 case AL_EFFECTSLOT_EFFECT:
354 *piValue = ALEffectSlot->effect.effect;
355 break;
357 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
358 *piValue = ALEffectSlot->AuxSendAuto;
359 break;
361 default:
362 alSetError(AL_INVALID_ENUM);
363 break;
366 else
367 alSetError(AL_INVALID_NAME);
369 ProcessContext(Context);
372 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues)
374 ALCcontext *Context;
376 Context = alcGetCurrentContext();
377 if(!Context)
379 alSetError(AL_INVALID_OPERATION);
380 return;
382 SuspendContext(Context);
384 if (alIsAuxiliaryEffectSlot(effectslot))
386 switch(param)
388 case AL_EFFECTSLOT_EFFECT:
389 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
390 alGetAuxiliaryEffectSloti(effectslot, param, piValues);
391 break;
393 default:
394 alSetError(AL_INVALID_ENUM);
395 break;
398 else
399 alSetError(AL_INVALID_NAME);
401 ProcessContext(Context);
404 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue)
406 ALCcontext *Context;
408 Context = alcGetCurrentContext();
409 if(!Context)
411 alSetError(AL_INVALID_OPERATION);
412 return;
414 SuspendContext(Context);
416 if (alIsAuxiliaryEffectSlot(effectslot))
418 ALeffectslot *ALEffectSlot = (ALeffectslot*)ALTHUNK_LOOKUPENTRY(effectslot);
420 switch(param)
422 case AL_EFFECTSLOT_GAIN:
423 *pflValue = ALEffectSlot->Gain;
424 break;
426 default:
427 alSetError(AL_INVALID_ENUM);
428 break;
431 else
432 alSetError(AL_INVALID_NAME);
434 ProcessContext(Context);
437 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues)
439 ALCcontext *Context;
441 Context = alcGetCurrentContext();
442 if(!Context)
444 alSetError(AL_INVALID_OPERATION);
445 return;
447 SuspendContext(Context);
449 if (alIsAuxiliaryEffectSlot(effectslot))
451 switch(param)
453 case AL_EFFECTSLOT_GAIN:
454 alGetAuxiliaryEffectSlotf(effectslot, param, pflValues);
455 break;
457 default:
458 alSetError(AL_INVALID_ENUM);
459 break;
462 else
463 alSetError(AL_INVALID_NAME);
465 ProcessContext(Context);
469 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
471 #ifdef _DEBUG
472 if(Context->AuxiliaryEffectSlotCount > 0)
473 AL_PRINT("exit() %d AuxiliaryEffectSlot(s) NOT deleted\n", Context->AuxiliaryEffectSlotCount);
474 #endif
476 while(Context->AuxiliaryEffectSlot)
478 ALeffectslot *temp = Context->AuxiliaryEffectSlot;
479 Context->AuxiliaryEffectSlot = Context->AuxiliaryEffectSlot->next;
481 // Release effectslot structure
482 memset(temp, 0, sizeof(ALeffectslot));
483 free(temp);
485 Context->AuxiliaryEffectSlotCount = 0;