Modify some context checks
[openal-soft.git] / OpenAL32 / alDatabuffer.c
blobdf1baaf2f3f30a9512ae46513ea4c5cdfdb57b6a
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);
174 return;
179 * alIsDatabufferEXT(ALuint uiBuffer)
181 * Checks if ulBuffer is a valid Databuffer Name
183 ALboolean ALAPIENTRY alIsDatabufferEXT(ALuint uiBuffer)
185 ALCcontext *Context;
186 ALdatabuffer *ALBuf;
188 Context = GetContextSuspended();
189 if(!Context) return AL_FALSE;
191 /* Check through list of generated databuffers for uiBuffer */
192 ALBuf = Context->Device->Databuffers;
193 while(ALBuf && ALBuf->databuffer != uiBuffer)
194 ALBuf = ALBuf->next;
196 ProcessContext(Context);
198 return ((ALBuf || !uiBuffer) ? AL_TRUE : AL_FALSE);
202 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
204 * Fill databuffer with data
206 ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage)
208 ALCcontext *Context;
209 ALdatabuffer *ALBuf;
210 ALvoid *temp;
212 Context = GetContextSuspended();
213 if(!Context) return;
215 if(alIsDatabufferEXT(buffer) && buffer != 0)
217 ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
218 if(ALBuf->state == UNMAPPED)
220 if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
221 usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
222 usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
223 usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
224 usage == AL_DYNAMIC_COPY_EXT)
226 /* (Re)allocate data */
227 temp = realloc(ALBuf->data, size);
228 if(temp)
230 ALBuf->data = temp;
231 ALBuf->size = size;
232 ALBuf->usage = usage;
233 if(data)
234 memcpy(ALBuf->data, data, size);
236 else
237 alSetError(AL_OUT_OF_MEMORY);
239 else
240 alSetError(AL_INVALID_ENUM);
242 else
243 alSetError(AL_INVALID_OPERATION);
245 else
246 alSetError(AL_INVALID_NAME);
248 ProcessContext(Context);
251 ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, const ALvoid *data)
253 ALCcontext *pContext;
254 ALdatabuffer *pBuffer;
256 pContext = GetContextSuspended();
257 if(!pContext) return;
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 = GetContextSuspended();
285 if(!pContext) return;
287 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
289 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
291 if(length >= 0 && start+length <= pBuffer->size)
293 if(pBuffer->state == UNMAPPED)
294 memcpy(data, pBuffer->data+start, length);
295 else
296 alSetError(AL_INVALID_OPERATION);
298 else
299 alSetError(AL_INVALID_VALUE);
301 else
302 alSetError(AL_INVALID_NAME);
304 ProcessContext(pContext);
308 ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
310 ALCcontext *pContext;
312 (void)flValue;
314 pContext = GetContextSuspended();
315 if(!pContext) return;
317 if(alIsDatabufferEXT(buffer) && buffer != 0)
319 switch(eParam)
321 default:
322 alSetError(AL_INVALID_ENUM);
323 break;
326 else
327 alSetError(AL_INVALID_NAME);
329 ProcessContext(pContext);
332 ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
334 ALCcontext *pContext;
336 (void)flValues;
338 pContext = GetContextSuspended();
339 if(!pContext) return;
341 if(alIsDatabufferEXT(buffer) && buffer != 0)
343 switch(eParam)
345 default:
346 alSetError(AL_INVALID_ENUM);
347 break;
350 else
351 alSetError(AL_INVALID_NAME);
353 ProcessContext(pContext);
357 ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
359 ALCcontext *pContext;
361 (void)lValue;
363 pContext = GetContextSuspended();
364 if(!pContext) return;
366 if(alIsDatabufferEXT(buffer) && buffer != 0)
368 switch(eParam)
370 default:
371 alSetError(AL_INVALID_ENUM);
372 break;
375 else
376 alSetError(AL_INVALID_NAME);
378 ProcessContext(pContext);
381 ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
383 ALCcontext *pContext;
385 (void)plValues;
387 pContext = GetContextSuspended();
388 if(!pContext) return;
390 if(alIsDatabufferEXT(buffer) && buffer != 0)
392 switch(eParam)
394 default:
395 alSetError(AL_INVALID_ENUM);
396 break;
399 else
400 alSetError(AL_INVALID_NAME);
402 ProcessContext(pContext);
406 ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
408 ALCcontext *pContext;
410 pContext = GetContextSuspended();
411 if(!pContext) return;
413 if(pflValue)
415 if(alIsDatabufferEXT(buffer) && buffer != 0)
417 switch(eParam)
419 default:
420 alSetError(AL_INVALID_ENUM);
421 break;
424 else
425 alSetError(AL_INVALID_NAME);
427 else
428 alSetError(AL_INVALID_VALUE);
430 ProcessContext(pContext);
433 ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
435 ALCcontext *pContext;
437 pContext = GetContextSuspended();
438 if(!pContext) return;
440 if(pflValues)
442 if(alIsDatabufferEXT(buffer) && buffer != 0)
444 switch(eParam)
446 default:
447 alSetError(AL_INVALID_ENUM);
448 break;
451 else
452 alSetError(AL_INVALID_NAME);
454 else
455 alSetError(AL_INVALID_VALUE);
457 ProcessContext(pContext);
460 ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
462 ALCcontext *pContext;
463 ALdatabuffer *pBuffer;
465 pContext = GetContextSuspended();
466 if(!pContext) return;
468 if(plValue)
470 if(alIsDatabufferEXT(buffer) && buffer != 0)
472 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
474 switch(eParam)
476 case AL_SIZE:
477 *plValue = pBuffer->size;
478 break;
480 default:
481 alSetError(AL_INVALID_ENUM);
482 break;
485 else
486 alSetError(AL_INVALID_NAME);
488 else
489 alSetError(AL_INVALID_VALUE);
491 ProcessContext(pContext);
494 ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
496 ALCcontext *pContext;
498 pContext = GetContextSuspended();
499 if(!pContext) return;
501 if(plValues)
503 if(alIsDatabufferEXT(buffer) && buffer != 0)
505 switch (eParam)
507 case AL_SIZE:
508 alGetBufferi(buffer, eParam, plValues);
509 break;
511 default:
512 alSetError(AL_INVALID_ENUM);
513 break;
516 else
517 alSetError(AL_INVALID_NAME);
519 else
520 alSetError(AL_INVALID_VALUE);
522 ProcessContext(pContext);
526 ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
528 ALCcontext *pContext;
529 ALdatabuffer *pBuffer;
531 pContext = GetContextSuspended();
532 if(!pContext) return;
534 if(alIsDatabufferEXT(uiBuffer))
536 pBuffer = (ALdatabuffer*)(uiBuffer ? ALTHUNK_LOOKUPENTRY(uiBuffer) : NULL);
537 if(target == AL_SAMPLE_SOURCE_EXT)
538 pContext->SampleSource = pBuffer;
539 else if(target == AL_SAMPLE_SINK_EXT)
540 pContext->SampleSink = pBuffer;
541 else
542 alSetError(AL_INVALID_VALUE);
544 else
545 alSetError(AL_INVALID_NAME);
547 ProcessContext(pContext);
551 ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access)
553 ALCcontext *pContext;
554 ALdatabuffer *pBuffer;
555 ALvoid *ret = NULL;
557 pContext = GetContextSuspended();
558 if(!pContext) return NULL;
560 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
562 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
564 if(length >= 0 && start+length <= pBuffer->size)
566 if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
567 access == AL_READ_WRITE_EXT)
569 if(pBuffer->state == UNMAPPED)
571 ret = pBuffer->data + start;
572 pBuffer->state = MAPPED;
574 else
575 alSetError(AL_INVALID_OPERATION);
577 else
578 alSetError(AL_INVALID_ENUM);
580 else
581 alSetError(AL_INVALID_VALUE);
583 else
584 alSetError(AL_INVALID_NAME);
586 ProcessContext(pContext);
588 return ret;
591 ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
593 ALCcontext *pContext;
594 ALdatabuffer *pBuffer;
596 pContext = GetContextSuspended();
597 if(!pContext) return;
599 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
601 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
603 if(pBuffer->state == MAPPED)
604 pBuffer->state = UNMAPPED;
605 else
606 alSetError(AL_INVALID_OPERATION);
608 else
609 alSetError(AL_INVALID_NAME);
611 ProcessContext(pContext);
616 * ReleaseALDatabuffers()
618 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
620 ALvoid ReleaseALDatabuffers(ALCdevice *device)
622 ALdatabuffer *ALBuffer;
623 ALdatabuffer *ALBufferTemp;
625 ALBuffer = device->Databuffers;
626 while(ALBuffer)
628 // Release sample data
629 free(ALBuffer->data);
631 // Release Buffer structure
632 ALBufferTemp = ALBuffer;
633 ALBuffer = ALBuffer->next;
634 memset(ALBufferTemp, 0, sizeof(ALdatabuffer));
635 free(ALBufferTemp);
637 device->Databuffers = NULL;
638 device->DatabufferCount = 0;