Add in-progress working extension AL_EXTX_sample_buffer_object
[openal-soft.git] / OpenAL32 / alDatabuffer.c
blob5b285b8df8f7378cfc7d8c88a15140bb1aca7c0c
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"
36 * alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers)
38 * Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers
40 ALvoid ALAPIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers)
42 ALCcontext *Context;
43 ALsizei i=0;
45 Context = alcGetCurrentContext();
46 if(!Context) return;
47 SuspendContext(Context);
49 /* Check that we are actually generation some Databuffers */
50 if(n > 0)
52 ALCdevice *device = Context->Device;
54 /* Check the pointer is valid (and points to enough memory to store
55 * Databuffer Names) */
56 if(!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
58 ALdatabuffer **list = &device->Databuffers;
59 while(*list)
60 list = &(*list)->next;
62 /* Create all the new Databuffers */
63 while(i < n)
65 *list = calloc(1, sizeof(ALdatabuffer));
66 if(!(*list))
68 alDeleteDatabuffersEXT(i, puiBuffers);
69 alSetError(AL_OUT_OF_MEMORY);
70 break;
73 puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
74 (*list)->databuffer = puiBuffers[i];
75 (*list)->state = UNMAPPED;
76 device->DatabufferCount++;
77 i++;
79 list = &(*list)->next;
82 else
83 alSetError(AL_INVALID_VALUE);
86 ProcessContext(Context);
90 * alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
92 * Deletes the n AL Databuffers pointed to by puiBuffers
94 ALvoid ALAPIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers)
96 ALCcontext *Context;
97 ALdatabuffer *ALBuf;
98 ALsizei i;
99 ALboolean bFailed = AL_FALSE;
101 Context = alcGetCurrentContext();
102 if(!Context) return;
103 SuspendContext(Context);
105 /* Check we are actually Deleting some Databuffers */
106 if(n >= 0)
108 ALCdevice *device = Context->Device;
110 /* Check that all the databuffers are valid and can actually be
111 * deleted */
112 for(i = 0;i < n;i++)
114 /* Check for valid Buffer ID (can be NULL buffer) */
115 if(alIsDatabufferEXT(puiBuffers[i]))
117 /* If not the NULL buffer, check that it's unmapped */
118 ALBuf = ((ALdatabuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
119 if(ALBuf)
121 if(ALBuf->state != UNMAPPED)
123 /* Databuffer still in use, cannot be deleted */
124 alSetError(AL_INVALID_OPERATION);
125 bFailed = AL_TRUE;
129 else
131 /* Invalid Databuffer */
132 alSetError(AL_INVALID_NAME);
133 bFailed = AL_TRUE;
137 /* If all the Databuffers were valid (and unmapped), then we can
138 * delete them */
139 if(!bFailed)
141 for(i = 0;i < n;i++)
143 if(puiBuffers[i] && alIsDatabufferEXT(puiBuffers[i]))
145 ALdatabuffer **list = &device->Databuffers;
147 ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(puiBuffers[i]);
148 while(*list && *list != ALBuf)
149 list = &(*list)->next;
151 if(*list)
152 *list = (*list)->next;
154 // Release the memory used to store audio data
155 free(ALBuf->data);
157 // Release buffer structure
158 ALTHUNK_REMOVEENTRY(puiBuffers[i]);
159 memset(ALBuf, 0, sizeof(ALdatabuffer));
160 device->DatabufferCount--;
161 free(ALBuf);
166 else
167 alSetError(AL_INVALID_VALUE);
169 ProcessContext(Context);
171 return;
176 * alIsDatabufferEXT(ALuint uiBuffer)
178 * Checks if ulBuffer is a valid Databuffer Name
180 ALboolean ALAPIENTRY alIsDatabufferEXT(ALuint uiBuffer)
182 ALCcontext *Context;
183 ALdatabuffer *ALBuf;
185 Context = alcGetCurrentContext();
186 if(!Context) return AL_FALSE;
187 SuspendContext(Context);
189 /* Check through list of generated databuffers for uiBuffer */
190 ALBuf = Context->Device->Databuffers;
191 while(ALBuf && ALBuf->databuffer != uiBuffer)
192 ALBuf = ALBuf->next;
194 ProcessContext(Context);
196 return ((ALBuf || !uiBuffer) ? AL_TRUE : AL_FALSE);
200 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
202 * Fill databuffer with data
204 ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage)
206 ALCcontext *Context;
207 ALdatabuffer *ALBuf;
208 ALvoid *temp;
210 Context = alcGetCurrentContext();
211 if(!Context) return;
212 SuspendContext(Context);
214 if(alIsDatabufferEXT(buffer) && buffer != 0)
216 ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
217 if(ALBuf->state == UNMAPPED)
219 if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
220 usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
221 usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
222 usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
223 usage == AL_DYNAMIC_COPY_EXT)
225 /* (Re)allocate data */
226 temp = realloc(ALBuf->data, size);
227 if(temp)
229 ALBuf->data = temp;
230 ALBuf->size = size;
231 ALBuf->usage = usage;
232 if(data)
233 memcpy(ALBuf->data, data, size);
235 else
236 alSetError(AL_OUT_OF_MEMORY);
238 else
239 alSetError(AL_INVALID_ENUM);
241 else
242 alSetError(AL_INVALID_OPERATION);
244 else
245 alSetError(AL_INVALID_NAME);
247 ProcessContext(Context);
250 ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, const ALvoid *data)
252 ALCcontext *pContext;
253 ALdatabuffer *pBuffer;
255 pContext = alcGetCurrentContext();
256 if(!pContext) return;
257 SuspendContext(pContext);
259 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
261 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
263 if(length >= 0 && start+length <= pBuffer->size)
265 if(pBuffer->state == UNMAPPED)
266 memcpy(pBuffer->data+start, data, length);
267 else
268 alSetError(AL_INVALID_OPERATION);
270 else
271 alSetError(AL_INVALID_VALUE);
273 else
274 alSetError(AL_INVALID_NAME);
276 ProcessContext(pContext);
279 ALvoid ALAPIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALvoid *data)
281 ALCcontext *pContext;
282 ALdatabuffer *pBuffer;
284 pContext = alcGetCurrentContext();
285 if(!pContext) return;
286 SuspendContext(pContext);
288 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
290 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
292 if(length >= 0 && start+length <= pBuffer->size)
294 if(pBuffer->state == UNMAPPED)
295 memcpy(data, pBuffer->data+start, length);
296 else
297 alSetError(AL_INVALID_OPERATION);
299 else
300 alSetError(AL_INVALID_VALUE);
302 else
303 alSetError(AL_INVALID_NAME);
305 ProcessContext(pContext);
309 ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
311 ALCcontext *pContext;
313 (void)flValue;
315 pContext = alcGetCurrentContext();
316 if(!pContext) return;
317 SuspendContext(pContext);
319 if(alIsDatabufferEXT(buffer) && buffer != 0)
321 switch(eParam)
323 default:
324 alSetError(AL_INVALID_ENUM);
325 break;
328 else
329 alSetError(AL_INVALID_NAME);
331 ProcessContext(pContext);
334 ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
336 ALCcontext *pContext;
338 (void)flValues;
340 pContext = alcGetCurrentContext();
341 if(!pContext) return;
342 SuspendContext(pContext);
344 if(alIsDatabufferEXT(buffer) && buffer != 0)
346 switch(eParam)
348 default:
349 alSetError(AL_INVALID_ENUM);
350 break;
353 else
354 alSetError(AL_INVALID_NAME);
356 ProcessContext(pContext);
360 ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
362 ALCcontext *pContext;
364 (void)lValue;
366 pContext = alcGetCurrentContext();
367 if(!pContext) return;
368 SuspendContext(pContext);
370 if(alIsDatabufferEXT(buffer) && buffer != 0)
372 switch(eParam)
374 default:
375 alSetError(AL_INVALID_ENUM);
376 break;
379 else
380 alSetError(AL_INVALID_NAME);
382 ProcessContext(pContext);
385 ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
387 ALCcontext *pContext;
389 (void)plValues;
391 pContext = alcGetCurrentContext();
392 if(!pContext) return;
393 SuspendContext(pContext);
395 if(alIsDatabufferEXT(buffer) && buffer != 0)
397 switch(eParam)
399 default:
400 alSetError(AL_INVALID_ENUM);
401 break;
404 else
405 alSetError(AL_INVALID_NAME);
407 ProcessContext(pContext);
411 ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
413 ALCcontext *pContext;
415 pContext = alcGetCurrentContext();
416 if(!pContext) return;
417 SuspendContext(pContext);
419 if(pflValue)
421 if(alIsDatabufferEXT(buffer) && buffer != 0)
423 switch(eParam)
425 default:
426 alSetError(AL_INVALID_ENUM);
427 break;
430 else
431 alSetError(AL_INVALID_NAME);
433 else
434 alSetError(AL_INVALID_VALUE);
436 ProcessContext(pContext);
439 ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
441 ALCcontext *pContext;
443 pContext = alcGetCurrentContext();
444 if(!pContext) return;
445 SuspendContext(pContext);
447 if(pflValues)
449 if(alIsDatabufferEXT(buffer) && buffer != 0)
451 switch(eParam)
453 default:
454 alSetError(AL_INVALID_ENUM);
455 break;
458 else
459 alSetError(AL_INVALID_NAME);
461 else
462 alSetError(AL_INVALID_VALUE);
464 ProcessContext(pContext);
467 ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
469 ALCcontext *pContext;
470 ALdatabuffer *pBuffer;
472 pContext = alcGetCurrentContext();
473 if(!pContext) return;
474 SuspendContext(pContext);
476 if(plValue)
478 if(alIsDatabufferEXT(buffer) && buffer != 0)
480 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
482 switch(eParam)
484 case AL_SIZE:
485 *plValue = pBuffer->size;
486 break;
488 default:
489 alSetError(AL_INVALID_ENUM);
490 break;
493 else
494 alSetError(AL_INVALID_NAME);
496 else
497 alSetError(AL_INVALID_VALUE);
499 ProcessContext(pContext);
502 ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
504 ALCcontext *pContext;
506 pContext = alcGetCurrentContext();
507 if(!pContext) return;
508 SuspendContext(pContext);
510 if(plValues)
512 if(alIsDatabufferEXT(buffer) && buffer != 0)
514 switch (eParam)
516 case AL_SIZE:
517 alGetBufferi(buffer, eParam, plValues);
518 break;
520 default:
521 alSetError(AL_INVALID_ENUM);
522 break;
525 else
526 alSetError(AL_INVALID_NAME);
528 else
529 alSetError(AL_INVALID_VALUE);
531 ProcessContext(pContext);
535 ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
537 ALCcontext *pContext;
538 ALdatabuffer *pBuffer;
540 pContext = alcGetCurrentContext();
541 if(!pContext) return;
542 SuspendContext(pContext);
544 if(alIsDatabufferEXT(uiBuffer))
546 pBuffer = (ALdatabuffer*)(uiBuffer ? ALTHUNK_LOOKUPENTRY(uiBuffer) : NULL);
547 if(target == AL_SAMPLE_SOURCE_EXT)
548 pContext->SampleSource = pBuffer;
549 else if(target == AL_SAMPLE_SINK_EXT)
550 pContext->SampleSink = pBuffer;
551 else
552 alSetError(AL_INVALID_VALUE);
554 else
555 alSetError(AL_INVALID_NAME);
557 ProcessContext(pContext);
561 ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access)
563 ALCcontext *pContext;
564 ALdatabuffer *pBuffer;
565 ALvoid *ret = NULL;
567 pContext = alcGetCurrentContext();
568 if(!pContext) return NULL;
569 SuspendContext(pContext);
571 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
573 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
575 if(length >= 0 && start+length <= pBuffer->size)
577 if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
578 access == AL_READ_WRITE_EXT)
580 if(pBuffer->state == UNMAPPED)
582 ret = pBuffer->data + start;
583 pBuffer->state = MAPPED;
585 else
586 alSetError(AL_INVALID_OPERATION);
588 else
589 alSetError(AL_INVALID_ENUM);
591 else
592 alSetError(AL_INVALID_VALUE);
594 else
595 alSetError(AL_INVALID_NAME);
597 ProcessContext(pContext);
599 return ret;
602 ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
604 ALCcontext *pContext;
605 ALdatabuffer *pBuffer;
607 pContext = alcGetCurrentContext();
608 if(!pContext) return;
609 SuspendContext(pContext);
611 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
613 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
615 if(pBuffer->state == MAPPED)
616 pBuffer->state = UNMAPPED;
617 else
618 alSetError(AL_INVALID_OPERATION);
620 else
621 alSetError(AL_INVALID_NAME);
623 ProcessContext(pContext);
628 * ReleaseALDatabuffers()
630 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
632 ALvoid ReleaseALDatabuffers(ALCdevice *device)
634 ALdatabuffer *ALBuffer;
635 ALdatabuffer *ALBufferTemp;
637 ALBuffer = device->Databuffers;
638 while(ALBuffer)
640 // Release sample data
641 free(ALBuffer->data);
643 // Release Buffer structure
644 ALBufferTemp = ALBuffer;
645 ALBuffer = ALBuffer->next;
646 memset(ALBufferTemp, 0, sizeof(ALdatabuffer));
647 free(ALBufferTemp);
649 device->Databuffers = NULL;
650 device->DatabufferCount = 0;