Check buffer size when copying padding instead of the data pointer
[openal-soft.git] / OpenAL32 / alDatabuffer.c
blob1bbe8be48bf7901c0ae5df2a91435c7d9fb7dee3
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 = GetContextSuspended();
46 if(!Context) return;
48 /* Check that we are actually generation some Databuffers */
49 if(n > 0)
51 ALCdevice *device = Context->Device;
53 /* Check the pointer is valid (and points to enough memory to store
54 * Databuffer Names) */
55 if(!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
57 ALdatabuffer **list = &device->Databuffers;
58 while(*list)
59 list = &(*list)->next;
61 /* Create all the new Databuffers */
62 while(i < n)
64 *list = calloc(1, sizeof(ALdatabuffer));
65 if(!(*list))
67 alDeleteDatabuffersEXT(i, puiBuffers);
68 alSetError(AL_OUT_OF_MEMORY);
69 break;
72 puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list);
73 (*list)->databuffer = puiBuffers[i];
74 (*list)->state = UNMAPPED;
75 device->DatabufferCount++;
76 i++;
78 list = &(*list)->next;
81 else
82 alSetError(AL_INVALID_VALUE);
85 ProcessContext(Context);
89 * alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
91 * Deletes the n AL Databuffers pointed to by puiBuffers
93 ALvoid ALAPIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers)
95 ALCcontext *Context;
96 ALdatabuffer *ALBuf;
97 ALsizei i;
98 ALboolean bFailed = AL_FALSE;
100 Context = GetContextSuspended();
101 if(!Context) return;
103 /* Check we are actually Deleting some Databuffers */
104 if(n >= 0)
106 ALCdevice *device = Context->Device;
108 /* Check that all the databuffers are valid and can actually be
109 * deleted */
110 for(i = 0;i < n;i++)
112 /* Check for valid Buffer ID (can be NULL buffer) */
113 if(alIsDatabufferEXT(puiBuffers[i]))
115 /* If not the NULL buffer, check that it's unmapped */
116 ALBuf = ((ALdatabuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i]));
117 if(ALBuf)
119 if(ALBuf->state != UNMAPPED)
121 /* Databuffer still in use, cannot be deleted */
122 alSetError(AL_INVALID_OPERATION);
123 bFailed = AL_TRUE;
127 else
129 /* Invalid Databuffer */
130 alSetError(AL_INVALID_NAME);
131 bFailed = AL_TRUE;
135 /* If all the Databuffers were valid (and unmapped), then we can
136 * delete them */
137 if(!bFailed)
139 for(i = 0;i < n;i++)
141 if(puiBuffers[i] && alIsDatabufferEXT(puiBuffers[i]))
143 ALdatabuffer **list = &device->Databuffers;
145 ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(puiBuffers[i]);
146 while(*list && *list != ALBuf)
147 list = &(*list)->next;
149 if(*list)
150 *list = (*list)->next;
152 if(ALBuf == Context->SampleSource)
153 Context->SampleSource = NULL;
154 if(ALBuf == Context->SampleSink)
155 Context->SampleSink = NULL;
157 // Release the memory used to store audio data
158 free(ALBuf->data);
160 // Release buffer structure
161 ALTHUNK_REMOVEENTRY(puiBuffers[i]);
162 memset(ALBuf, 0, sizeof(ALdatabuffer));
163 device->DatabufferCount--;
164 free(ALBuf);
169 else
170 alSetError(AL_INVALID_VALUE);
172 ProcessContext(Context);
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 = GetContextSuspended();
186 if(!Context) return AL_FALSE;
188 /* Check through list of generated databuffers for uiBuffer */
189 ALBuf = Context->Device->Databuffers;
190 while(ALBuf && ALBuf->databuffer != uiBuffer)
191 ALBuf = ALBuf->next;
193 ProcessContext(Context);
195 return ((ALBuf || !uiBuffer) ? AL_TRUE : AL_FALSE);
199 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
201 * Fill databuffer with data
203 ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage)
205 ALCcontext *Context;
206 ALdatabuffer *ALBuf;
207 ALvoid *temp;
209 Context = GetContextSuspended();
210 if(!Context) return;
212 if(alIsDatabufferEXT(buffer) && buffer != 0)
214 ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
215 if(ALBuf->state == UNMAPPED)
217 if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
218 usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
219 usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
220 usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
221 usage == AL_DYNAMIC_COPY_EXT)
223 /* (Re)allocate data */
224 temp = realloc(ALBuf->data, size);
225 if(temp)
227 ALBuf->data = temp;
228 ALBuf->size = size;
229 ALBuf->usage = usage;
230 if(data)
231 memcpy(ALBuf->data, data, size);
233 else
234 alSetError(AL_OUT_OF_MEMORY);
236 else
237 alSetError(AL_INVALID_ENUM);
239 else
240 alSetError(AL_INVALID_OPERATION);
242 else
243 alSetError(AL_INVALID_NAME);
245 ProcessContext(Context);
248 ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, const ALvoid *data)
250 ALCcontext *pContext;
251 ALdatabuffer *pBuffer;
253 pContext = GetContextSuspended();
254 if(!pContext) return;
256 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
258 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
260 if(length >= 0 && start+length <= pBuffer->size)
262 if(pBuffer->state == UNMAPPED)
263 memcpy(pBuffer->data+start, data, length);
264 else
265 alSetError(AL_INVALID_OPERATION);
267 else
268 alSetError(AL_INVALID_VALUE);
270 else
271 alSetError(AL_INVALID_NAME);
273 ProcessContext(pContext);
276 ALvoid ALAPIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALvoid *data)
278 ALCcontext *pContext;
279 ALdatabuffer *pBuffer;
281 pContext = GetContextSuspended();
282 if(!pContext) return;
284 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
286 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
288 if(length >= 0 && start+length <= pBuffer->size)
290 if(pBuffer->state == UNMAPPED)
291 memcpy(data, pBuffer->data+start, length);
292 else
293 alSetError(AL_INVALID_OPERATION);
295 else
296 alSetError(AL_INVALID_VALUE);
298 else
299 alSetError(AL_INVALID_NAME);
301 ProcessContext(pContext);
305 ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
307 ALCcontext *pContext;
309 (void)flValue;
311 pContext = GetContextSuspended();
312 if(!pContext) return;
314 if(alIsDatabufferEXT(buffer) && buffer != 0)
316 switch(eParam)
318 default:
319 alSetError(AL_INVALID_ENUM);
320 break;
323 else
324 alSetError(AL_INVALID_NAME);
326 ProcessContext(pContext);
329 ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
331 ALCcontext *pContext;
333 (void)flValues;
335 pContext = GetContextSuspended();
336 if(!pContext) return;
338 if(alIsDatabufferEXT(buffer) && buffer != 0)
340 switch(eParam)
342 default:
343 alSetError(AL_INVALID_ENUM);
344 break;
347 else
348 alSetError(AL_INVALID_NAME);
350 ProcessContext(pContext);
354 ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
356 ALCcontext *pContext;
358 (void)lValue;
360 pContext = GetContextSuspended();
361 if(!pContext) return;
363 if(alIsDatabufferEXT(buffer) && buffer != 0)
365 switch(eParam)
367 default:
368 alSetError(AL_INVALID_ENUM);
369 break;
372 else
373 alSetError(AL_INVALID_NAME);
375 ProcessContext(pContext);
378 ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
380 ALCcontext *pContext;
382 (void)plValues;
384 pContext = GetContextSuspended();
385 if(!pContext) return;
387 if(alIsDatabufferEXT(buffer) && buffer != 0)
389 switch(eParam)
391 default:
392 alSetError(AL_INVALID_ENUM);
393 break;
396 else
397 alSetError(AL_INVALID_NAME);
399 ProcessContext(pContext);
403 ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
405 ALCcontext *pContext;
407 pContext = GetContextSuspended();
408 if(!pContext) return;
410 if(pflValue)
412 if(alIsDatabufferEXT(buffer) && buffer != 0)
414 switch(eParam)
416 default:
417 alSetError(AL_INVALID_ENUM);
418 break;
421 else
422 alSetError(AL_INVALID_NAME);
424 else
425 alSetError(AL_INVALID_VALUE);
427 ProcessContext(pContext);
430 ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
432 ALCcontext *pContext;
434 pContext = GetContextSuspended();
435 if(!pContext) return;
437 if(pflValues)
439 if(alIsDatabufferEXT(buffer) && buffer != 0)
441 switch(eParam)
443 default:
444 alSetError(AL_INVALID_ENUM);
445 break;
448 else
449 alSetError(AL_INVALID_NAME);
451 else
452 alSetError(AL_INVALID_VALUE);
454 ProcessContext(pContext);
457 ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
459 ALCcontext *pContext;
460 ALdatabuffer *pBuffer;
462 pContext = GetContextSuspended();
463 if(!pContext) return;
465 if(plValue)
467 if(alIsDatabufferEXT(buffer) && buffer != 0)
469 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
471 switch(eParam)
473 case AL_SIZE:
474 *plValue = pBuffer->size;
475 break;
477 default:
478 alSetError(AL_INVALID_ENUM);
479 break;
482 else
483 alSetError(AL_INVALID_NAME);
485 else
486 alSetError(AL_INVALID_VALUE);
488 ProcessContext(pContext);
491 ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
493 ALCcontext *pContext;
495 pContext = GetContextSuspended();
496 if(!pContext) return;
498 if(plValues)
500 if(alIsDatabufferEXT(buffer) && buffer != 0)
502 switch (eParam)
504 case AL_SIZE:
505 alGetDatabufferiEXT(buffer, eParam, plValues);
506 break;
508 default:
509 alSetError(AL_INVALID_ENUM);
510 break;
513 else
514 alSetError(AL_INVALID_NAME);
516 else
517 alSetError(AL_INVALID_VALUE);
519 ProcessContext(pContext);
523 ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
525 ALCcontext *pContext;
526 ALdatabuffer *pBuffer;
528 pContext = GetContextSuspended();
529 if(!pContext) return;
531 if(alIsDatabufferEXT(uiBuffer))
533 pBuffer = (ALdatabuffer*)(uiBuffer ? ALTHUNK_LOOKUPENTRY(uiBuffer) : NULL);
534 if(target == AL_SAMPLE_SOURCE_EXT)
535 pContext->SampleSource = pBuffer;
536 else if(target == AL_SAMPLE_SINK_EXT)
537 pContext->SampleSink = pBuffer;
538 else
539 alSetError(AL_INVALID_VALUE);
541 else
542 alSetError(AL_INVALID_NAME);
544 ProcessContext(pContext);
548 ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access)
550 ALCcontext *pContext;
551 ALdatabuffer *pBuffer;
552 ALvoid *ret = NULL;
554 pContext = GetContextSuspended();
555 if(!pContext) return NULL;
557 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
559 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
561 if(length >= 0 && start+length <= pBuffer->size)
563 if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
564 access == AL_READ_WRITE_EXT)
566 if(pBuffer->state == UNMAPPED)
568 ret = pBuffer->data + start;
569 pBuffer->state = MAPPED;
571 else
572 alSetError(AL_INVALID_OPERATION);
574 else
575 alSetError(AL_INVALID_ENUM);
577 else
578 alSetError(AL_INVALID_VALUE);
580 else
581 alSetError(AL_INVALID_NAME);
583 ProcessContext(pContext);
585 return ret;
588 ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
590 ALCcontext *pContext;
591 ALdatabuffer *pBuffer;
593 pContext = GetContextSuspended();
594 if(!pContext) return;
596 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
598 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
600 if(pBuffer->state == MAPPED)
601 pBuffer->state = UNMAPPED;
602 else
603 alSetError(AL_INVALID_OPERATION);
605 else
606 alSetError(AL_INVALID_NAME);
608 ProcessContext(pContext);
613 * ReleaseALDatabuffers()
615 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
617 ALvoid ReleaseALDatabuffers(ALCdevice *device)
619 ALdatabuffer *ALBuffer;
620 ALdatabuffer *ALBufferTemp;
622 ALBuffer = device->Databuffers;
623 while(ALBuffer)
625 // Release sample data
626 free(ALBuffer->data);
628 // Release Buffer structure
629 ALBufferTemp = ALBuffer;
630 ALBuffer = ALBuffer->next;
631 memset(ALBufferTemp, 0, sizeof(ALdatabuffer));
632 free(ALBufferTemp);
634 device->Databuffers = NULL;
635 device->DatabufferCount = 0;