Avoid calling alDelete* from alGen*
[openal-soft.git] / OpenAL32 / alDatabuffer.c
blobf13bc34eadbb41a1071b79c5b4b557b0abc42195
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 <stdio.h>
25 #include <assert.h>
26 #include "alMain.h"
27 #include "AL/al.h"
28 #include "AL/alc.h"
29 #include "AL/alext.h"
30 #include "alError.h"
31 #include "alDatabuffer.h"
32 #include "alThunk.h"
35 DECL_VERIFIER(Databuffer, ALdatabuffer, databuffer)
38 * alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers)
40 * Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers
42 ALvoid AL_APIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers)
44 ALCcontext *Context;
45 ALsizei i=0;
47 Context = GetContextSuspended();
48 if(!Context) return;
50 /* Check that we are actually generation some Databuffers */
51 if(n > 0)
53 ALCdevice *device = Context->Device;
55 /* Check the pointer is valid (and points to enough memory to store
56 * Databuffer Names) */
57 if(!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
59 ALdatabuffer *end;
60 ALdatabuffer **list = &device->DatabufferList;
61 while(*list)
62 list = &(*list)->next;
64 /* Create all the new Databuffers */
65 end = *list;
66 while(i < n)
68 *list = calloc(1, sizeof(ALdatabuffer));
69 if(!(*list))
71 while(end->next)
73 ALdatabuffer *temp = end->next;
74 end->next = temp->next;
76 ALTHUNK_REMOVEENTRY(temp->databuffer);
77 device->DatabufferCount--;
78 free(temp);
80 alSetError(Context, AL_OUT_OF_MEMORY);
81 break;
84 puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
85 (*list)->databuffer = puiBuffers[i];
86 (*list)->state = UNMAPPED;
87 device->DatabufferCount++;
88 i++;
90 list = &(*list)->next;
93 else
94 alSetError(Context, AL_INVALID_VALUE);
97 ProcessContext(Context);
101 * alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
103 * Deletes the n AL Databuffers pointed to by puiBuffers
105 ALvoid AL_APIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers)
107 ALCcontext *Context;
108 ALdatabuffer *ALBuf;
109 ALsizei i;
110 ALboolean bFailed = AL_FALSE;
112 Context = GetContextSuspended();
113 if(!Context) return;
115 /* Check we are actually Deleting some Databuffers */
116 if(n >= 0)
118 ALCdevice *device = Context->Device;
120 /* Check that all the databuffers are valid and can actually be
121 * deleted */
122 for(i = 0;i < n;i++)
124 if(!puiBuffers[i])
125 continue;
127 /* Check for valid Buffer ID */
128 if((ALBuf=VerifyDatabuffer(device->DatabufferList, puiBuffers[i])) != NULL)
130 if(ALBuf->state != UNMAPPED)
132 /* Databuffer still in use, cannot be deleted */
133 alSetError(Context, AL_INVALID_OPERATION);
134 bFailed = AL_TRUE;
135 break;
138 else
140 /* Invalid Databuffer */
141 alSetError(Context, AL_INVALID_NAME);
142 bFailed = AL_TRUE;
143 break;
147 /* If all the Databuffers were valid (and unmapped), then we can
148 * delete them */
149 if(!bFailed)
151 for(i = 0;i < n;i++)
153 if((ALBuf=VerifyDatabuffer(device->DatabufferList, puiBuffers[i])) != NULL)
155 ALdatabuffer **list = &device->DatabufferList;
157 while(*list && *list != ALBuf)
158 list = &(*list)->next;
160 if(*list)
161 *list = (*list)->next;
163 if(ALBuf == Context->SampleSource)
164 Context->SampleSource = NULL;
165 if(ALBuf == Context->SampleSink)
166 Context->SampleSink = NULL;
168 // Release the memory used to store audio data
169 free(ALBuf->data);
171 // Release buffer structure
172 ALTHUNK_REMOVEENTRY(puiBuffers[i]);
173 memset(ALBuf, 0, sizeof(ALdatabuffer));
174 device->DatabufferCount--;
175 free(ALBuf);
180 else
181 alSetError(Context, AL_INVALID_VALUE);
183 ProcessContext(Context);
187 * alIsDatabufferEXT(ALuint uiBuffer)
189 * Checks if ulBuffer is a valid Databuffer Name
191 ALboolean AL_APIENTRY alIsDatabufferEXT(ALuint uiBuffer)
193 ALCcontext *Context;
194 ALboolean result = AL_TRUE;
195 ALCdevice *device;
197 Context = GetContextSuspended();
198 if(!Context) return AL_FALSE;
200 device = Context->Device;
201 if(uiBuffer)
202 result = (VerifyDatabuffer(device->DatabufferList, uiBuffer) ?
203 AL_TRUE : AL_FALSE);
205 ProcessContext(Context);
207 return result;
211 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
213 * Fill databuffer with data
215 ALvoid AL_APIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage)
217 ALCcontext *Context;
218 ALdatabuffer *ALBuf;
219 ALCdevice *Device;
220 ALvoid *temp;
222 Context = GetContextSuspended();
223 if(!Context) return;
225 Device = Context->Device;
226 if((ALBuf=VerifyDatabuffer(Device->DatabufferList, buffer)) != NULL)
228 if(ALBuf->state == UNMAPPED)
230 if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
231 usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
232 usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
233 usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
234 usage == AL_DYNAMIC_COPY_EXT)
236 if(size >= 0)
238 /* (Re)allocate data */
239 temp = realloc(ALBuf->data, size);
240 if(temp)
242 ALBuf->data = temp;
243 ALBuf->size = size;
244 ALBuf->usage = usage;
245 if(data)
246 memcpy(ALBuf->data, data, size);
248 else
249 alSetError(Context, AL_OUT_OF_MEMORY);
251 else
252 alSetError(Context, AL_INVALID_VALUE);
254 else
255 alSetError(Context, AL_INVALID_ENUM);
257 else
258 alSetError(Context, AL_INVALID_OPERATION);
260 else
261 alSetError(Context, AL_INVALID_NAME);
263 ProcessContext(Context);
266 ALvoid AL_APIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *data)
268 ALCcontext *pContext;
269 ALdatabuffer *pBuffer;
270 ALCdevice *Device;
272 pContext = GetContextSuspended();
273 if(!pContext) return;
275 Device = pContext->Device;
276 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
278 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
280 if(pBuffer->state == UNMAPPED)
281 memcpy(pBuffer->data+start, data, length);
282 else
283 alSetError(pContext, AL_INVALID_OPERATION);
285 else
286 alSetError(pContext, AL_INVALID_VALUE);
288 else
289 alSetError(pContext, AL_INVALID_NAME);
291 ProcessContext(pContext);
294 ALvoid AL_APIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *data)
296 ALCcontext *pContext;
297 ALdatabuffer *pBuffer;
298 ALCdevice *Device;
300 pContext = GetContextSuspended();
301 if(!pContext) return;
303 Device = pContext->Device;
304 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
306 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
308 if(pBuffer->state == UNMAPPED)
309 memcpy(data, pBuffer->data+start, length);
310 else
311 alSetError(pContext, AL_INVALID_OPERATION);
313 else
314 alSetError(pContext, AL_INVALID_VALUE);
316 else
317 alSetError(pContext, AL_INVALID_NAME);
319 ProcessContext(pContext);
323 ALvoid AL_APIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
325 ALCcontext *pContext;
326 ALCdevice *Device;
328 (void)flValue;
330 pContext = GetContextSuspended();
331 if(!pContext) return;
333 Device = pContext->Device;
334 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
336 switch(eParam)
338 default:
339 alSetError(pContext, AL_INVALID_ENUM);
340 break;
343 else
344 alSetError(pContext, AL_INVALID_NAME);
346 ProcessContext(pContext);
349 ALvoid AL_APIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
351 ALCcontext *pContext;
352 ALCdevice *Device;
354 (void)flValues;
356 pContext = GetContextSuspended();
357 if(!pContext) return;
359 Device = pContext->Device;
360 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
362 switch(eParam)
364 default:
365 alSetError(pContext, AL_INVALID_ENUM);
366 break;
369 else
370 alSetError(pContext, AL_INVALID_NAME);
372 ProcessContext(pContext);
376 ALvoid AL_APIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
378 ALCcontext *pContext;
379 ALCdevice *Device;
381 (void)lValue;
383 pContext = GetContextSuspended();
384 if(!pContext) return;
386 Device = pContext->Device;
387 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
389 switch(eParam)
391 default:
392 alSetError(pContext, AL_INVALID_ENUM);
393 break;
396 else
397 alSetError(pContext, AL_INVALID_NAME);
399 ProcessContext(pContext);
402 ALvoid AL_APIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
404 ALCcontext *pContext;
405 ALCdevice *Device;
407 (void)plValues;
409 pContext = GetContextSuspended();
410 if(!pContext) return;
412 Device = pContext->Device;
413 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
415 switch(eParam)
417 default:
418 alSetError(pContext, AL_INVALID_ENUM);
419 break;
422 else
423 alSetError(pContext, AL_INVALID_NAME);
425 ProcessContext(pContext);
429 ALvoid AL_APIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
431 ALCcontext *pContext;
432 ALCdevice *Device;
434 pContext = GetContextSuspended();
435 if(!pContext) return;
437 if(pflValue)
439 Device = pContext->Device;
440 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
442 switch(eParam)
444 default:
445 alSetError(pContext, AL_INVALID_ENUM);
446 break;
449 else
450 alSetError(pContext, AL_INVALID_NAME);
452 else
453 alSetError(pContext, AL_INVALID_VALUE);
455 ProcessContext(pContext);
458 ALvoid AL_APIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
460 ALCcontext *pContext;
461 ALCdevice *Device;
463 pContext = GetContextSuspended();
464 if(!pContext) return;
466 if(pflValues)
468 Device = pContext->Device;
469 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
471 switch(eParam)
473 default:
474 alSetError(pContext, AL_INVALID_ENUM);
475 break;
478 else
479 alSetError(pContext, AL_INVALID_NAME);
481 else
482 alSetError(pContext, AL_INVALID_VALUE);
484 ProcessContext(pContext);
487 ALvoid AL_APIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
489 ALCcontext *pContext;
490 ALdatabuffer *pBuffer;
491 ALCdevice *Device;
493 pContext = GetContextSuspended();
494 if(!pContext) return;
496 if(plValue)
498 Device = pContext->Device;
499 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, buffer)) != NULL)
501 switch(eParam)
503 case AL_SIZE:
504 *plValue = (ALint)pBuffer->size;
505 break;
507 default:
508 alSetError(pContext, AL_INVALID_ENUM);
509 break;
512 else
513 alSetError(pContext, AL_INVALID_NAME);
515 else
516 alSetError(pContext, AL_INVALID_VALUE);
518 ProcessContext(pContext);
521 ALvoid AL_APIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
523 ALCcontext *pContext;
524 ALCdevice *Device;
526 pContext = GetContextSuspended();
527 if(!pContext) return;
529 if(plValues)
531 Device = pContext->Device;
532 if(VerifyDatabuffer(Device->DatabufferList, buffer) != NULL)
534 switch (eParam)
536 case AL_SIZE:
537 alGetDatabufferiEXT(buffer, eParam, plValues);
538 break;
540 default:
541 alSetError(pContext, AL_INVALID_ENUM);
542 break;
545 else
546 alSetError(pContext, AL_INVALID_NAME);
548 else
549 alSetError(pContext, AL_INVALID_VALUE);
551 ProcessContext(pContext);
555 ALvoid AL_APIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
557 ALCcontext *pContext;
558 ALdatabuffer *pBuffer = NULL;
559 ALCdevice *Device;
561 pContext = GetContextSuspended();
562 if(!pContext) return;
564 Device = pContext->Device;
565 if(uiBuffer == 0 ||
566 (pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
568 if(target == AL_SAMPLE_SOURCE_EXT)
569 pContext->SampleSource = pBuffer;
570 else if(target == AL_SAMPLE_SINK_EXT)
571 pContext->SampleSink = pBuffer;
572 else
573 alSetError(pContext, AL_INVALID_VALUE);
575 else
576 alSetError(pContext, AL_INVALID_NAME);
578 ProcessContext(pContext);
582 ALvoid* AL_APIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access)
584 ALCcontext *pContext;
585 ALdatabuffer *pBuffer;
586 ALvoid *ret = NULL;
587 ALCdevice *Device;
589 pContext = GetContextSuspended();
590 if(!pContext) return NULL;
592 Device = pContext->Device;
593 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
595 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
597 if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
598 access == AL_READ_WRITE_EXT)
600 if(pBuffer->state == UNMAPPED)
602 ret = pBuffer->data + start;
603 pBuffer->state = MAPPED;
605 else
606 alSetError(pContext, AL_INVALID_OPERATION);
608 else
609 alSetError(pContext, AL_INVALID_ENUM);
611 else
612 alSetError(pContext, AL_INVALID_VALUE);
614 else
615 alSetError(pContext, AL_INVALID_NAME);
617 ProcessContext(pContext);
619 return ret;
622 ALvoid AL_APIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
624 ALCcontext *pContext;
625 ALdatabuffer *pBuffer;
626 ALCdevice *Device;
628 pContext = GetContextSuspended();
629 if(!pContext) return;
631 Device = pContext->Device;
632 if((pBuffer=VerifyDatabuffer(Device->DatabufferList, uiBuffer)) != NULL)
634 if(pBuffer->state == MAPPED)
635 pBuffer->state = UNMAPPED;
636 else
637 alSetError(pContext, AL_INVALID_OPERATION);
639 else
640 alSetError(pContext, AL_INVALID_NAME);
642 ProcessContext(pContext);
647 * ReleaseALDatabuffers()
649 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
651 ALvoid ReleaseALDatabuffers(ALCdevice *device)
653 ALdatabuffer *ALBuffer;
654 ALdatabuffer *ALBufferTemp;
656 ALBuffer = device->DatabufferList;
657 while(ALBuffer)
659 // Release sample data
660 free(ALBuffer->data);
662 // Release Buffer structure
663 ALBufferTemp = ALBuffer;
664 ALBuffer = ALBuffer->next;
665 memset(ALBufferTemp, 0, sizeof(ALdatabuffer));
666 free(ALBufferTemp);
668 device->DatabufferList = NULL;
669 device->DatabufferCount = 0;