Reset the target if the databuffer being deleted is currently selected
[openal-soft.git] / OpenAL32 / alDatabuffer.c
blob2eed1d8e28596a2578683194b2708e54f8ba8291
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 if(ALBuf == Context->SampleSource)
155 Context->SampleSource = NULL;
156 if(ALBuf == Context->SampleSink)
157 Context->SampleSink = NULL;
159 // Release the memory used to store audio data
160 free(ALBuf->data);
162 // Release buffer structure
163 ALTHUNK_REMOVEENTRY(puiBuffers[i]);
164 memset(ALBuf, 0, sizeof(ALdatabuffer));
165 device->DatabufferCount--;
166 free(ALBuf);
171 else
172 alSetError(AL_INVALID_VALUE);
174 ProcessContext(Context);
176 return;
181 * alIsDatabufferEXT(ALuint uiBuffer)
183 * Checks if ulBuffer is a valid Databuffer Name
185 ALboolean ALAPIENTRY alIsDatabufferEXT(ALuint uiBuffer)
187 ALCcontext *Context;
188 ALdatabuffer *ALBuf;
190 Context = alcGetCurrentContext();
191 if(!Context) return AL_FALSE;
192 SuspendContext(Context);
194 /* Check through list of generated databuffers for uiBuffer */
195 ALBuf = Context->Device->Databuffers;
196 while(ALBuf && ALBuf->databuffer != uiBuffer)
197 ALBuf = ALBuf->next;
199 ProcessContext(Context);
201 return ((ALBuf || !uiBuffer) ? AL_TRUE : AL_FALSE);
205 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
207 * Fill databuffer with data
209 ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage)
211 ALCcontext *Context;
212 ALdatabuffer *ALBuf;
213 ALvoid *temp;
215 Context = alcGetCurrentContext();
216 if(!Context) return;
217 SuspendContext(Context);
219 if(alIsDatabufferEXT(buffer) && buffer != 0)
221 ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
222 if(ALBuf->state == UNMAPPED)
224 if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
225 usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
226 usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
227 usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
228 usage == AL_DYNAMIC_COPY_EXT)
230 /* (Re)allocate data */
231 temp = realloc(ALBuf->data, size);
232 if(temp)
234 ALBuf->data = temp;
235 ALBuf->size = size;
236 ALBuf->usage = usage;
237 if(data)
238 memcpy(ALBuf->data, data, size);
240 else
241 alSetError(AL_OUT_OF_MEMORY);
243 else
244 alSetError(AL_INVALID_ENUM);
246 else
247 alSetError(AL_INVALID_OPERATION);
249 else
250 alSetError(AL_INVALID_NAME);
252 ProcessContext(Context);
255 ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, const ALvoid *data)
257 ALCcontext *pContext;
258 ALdatabuffer *pBuffer;
260 pContext = alcGetCurrentContext();
261 if(!pContext) return;
262 SuspendContext(pContext);
264 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
266 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
268 if(length >= 0 && start+length <= pBuffer->size)
270 if(pBuffer->state == UNMAPPED)
271 memcpy(pBuffer->data+start, data, length);
272 else
273 alSetError(AL_INVALID_OPERATION);
275 else
276 alSetError(AL_INVALID_VALUE);
278 else
279 alSetError(AL_INVALID_NAME);
281 ProcessContext(pContext);
284 ALvoid ALAPIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALvoid *data)
286 ALCcontext *pContext;
287 ALdatabuffer *pBuffer;
289 pContext = alcGetCurrentContext();
290 if(!pContext) return;
291 SuspendContext(pContext);
293 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
295 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
297 if(length >= 0 && start+length <= pBuffer->size)
299 if(pBuffer->state == UNMAPPED)
300 memcpy(data, pBuffer->data+start, length);
301 else
302 alSetError(AL_INVALID_OPERATION);
304 else
305 alSetError(AL_INVALID_VALUE);
307 else
308 alSetError(AL_INVALID_NAME);
310 ProcessContext(pContext);
314 ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
316 ALCcontext *pContext;
318 (void)flValue;
320 pContext = alcGetCurrentContext();
321 if(!pContext) return;
322 SuspendContext(pContext);
324 if(alIsDatabufferEXT(buffer) && buffer != 0)
326 switch(eParam)
328 default:
329 alSetError(AL_INVALID_ENUM);
330 break;
333 else
334 alSetError(AL_INVALID_NAME);
336 ProcessContext(pContext);
339 ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
341 ALCcontext *pContext;
343 (void)flValues;
345 pContext = alcGetCurrentContext();
346 if(!pContext) return;
347 SuspendContext(pContext);
349 if(alIsDatabufferEXT(buffer) && buffer != 0)
351 switch(eParam)
353 default:
354 alSetError(AL_INVALID_ENUM);
355 break;
358 else
359 alSetError(AL_INVALID_NAME);
361 ProcessContext(pContext);
365 ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
367 ALCcontext *pContext;
369 (void)lValue;
371 pContext = alcGetCurrentContext();
372 if(!pContext) return;
373 SuspendContext(pContext);
375 if(alIsDatabufferEXT(buffer) && buffer != 0)
377 switch(eParam)
379 default:
380 alSetError(AL_INVALID_ENUM);
381 break;
384 else
385 alSetError(AL_INVALID_NAME);
387 ProcessContext(pContext);
390 ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
392 ALCcontext *pContext;
394 (void)plValues;
396 pContext = alcGetCurrentContext();
397 if(!pContext) return;
398 SuspendContext(pContext);
400 if(alIsDatabufferEXT(buffer) && buffer != 0)
402 switch(eParam)
404 default:
405 alSetError(AL_INVALID_ENUM);
406 break;
409 else
410 alSetError(AL_INVALID_NAME);
412 ProcessContext(pContext);
416 ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
418 ALCcontext *pContext;
420 pContext = alcGetCurrentContext();
421 if(!pContext) return;
422 SuspendContext(pContext);
424 if(pflValue)
426 if(alIsDatabufferEXT(buffer) && buffer != 0)
428 switch(eParam)
430 default:
431 alSetError(AL_INVALID_ENUM);
432 break;
435 else
436 alSetError(AL_INVALID_NAME);
438 else
439 alSetError(AL_INVALID_VALUE);
441 ProcessContext(pContext);
444 ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
446 ALCcontext *pContext;
448 pContext = alcGetCurrentContext();
449 if(!pContext) return;
450 SuspendContext(pContext);
452 if(pflValues)
454 if(alIsDatabufferEXT(buffer) && buffer != 0)
456 switch(eParam)
458 default:
459 alSetError(AL_INVALID_ENUM);
460 break;
463 else
464 alSetError(AL_INVALID_NAME);
466 else
467 alSetError(AL_INVALID_VALUE);
469 ProcessContext(pContext);
472 ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
474 ALCcontext *pContext;
475 ALdatabuffer *pBuffer;
477 pContext = alcGetCurrentContext();
478 if(!pContext) return;
479 SuspendContext(pContext);
481 if(plValue)
483 if(alIsDatabufferEXT(buffer) && buffer != 0)
485 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer);
487 switch(eParam)
489 case AL_SIZE:
490 *plValue = pBuffer->size;
491 break;
493 default:
494 alSetError(AL_INVALID_ENUM);
495 break;
498 else
499 alSetError(AL_INVALID_NAME);
501 else
502 alSetError(AL_INVALID_VALUE);
504 ProcessContext(pContext);
507 ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
509 ALCcontext *pContext;
511 pContext = alcGetCurrentContext();
512 if(!pContext) return;
513 SuspendContext(pContext);
515 if(plValues)
517 if(alIsDatabufferEXT(buffer) && buffer != 0)
519 switch (eParam)
521 case AL_SIZE:
522 alGetBufferi(buffer, eParam, plValues);
523 break;
525 default:
526 alSetError(AL_INVALID_ENUM);
527 break;
530 else
531 alSetError(AL_INVALID_NAME);
533 else
534 alSetError(AL_INVALID_VALUE);
536 ProcessContext(pContext);
540 ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
542 ALCcontext *pContext;
543 ALdatabuffer *pBuffer;
545 pContext = alcGetCurrentContext();
546 if(!pContext) return;
547 SuspendContext(pContext);
549 if(alIsDatabufferEXT(uiBuffer))
551 pBuffer = (ALdatabuffer*)(uiBuffer ? ALTHUNK_LOOKUPENTRY(uiBuffer) : NULL);
552 if(target == AL_SAMPLE_SOURCE_EXT)
553 pContext->SampleSource = pBuffer;
554 else if(target == AL_SAMPLE_SINK_EXT)
555 pContext->SampleSink = pBuffer;
556 else
557 alSetError(AL_INVALID_VALUE);
559 else
560 alSetError(AL_INVALID_NAME);
562 ProcessContext(pContext);
566 ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access)
568 ALCcontext *pContext;
569 ALdatabuffer *pBuffer;
570 ALvoid *ret = NULL;
572 pContext = alcGetCurrentContext();
573 if(!pContext) return NULL;
574 SuspendContext(pContext);
576 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
578 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
580 if(length >= 0 && start+length <= pBuffer->size)
582 if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
583 access == AL_READ_WRITE_EXT)
585 if(pBuffer->state == UNMAPPED)
587 ret = pBuffer->data + start;
588 pBuffer->state = MAPPED;
590 else
591 alSetError(AL_INVALID_OPERATION);
593 else
594 alSetError(AL_INVALID_ENUM);
596 else
597 alSetError(AL_INVALID_VALUE);
599 else
600 alSetError(AL_INVALID_NAME);
602 ProcessContext(pContext);
604 return ret;
607 ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
609 ALCcontext *pContext;
610 ALdatabuffer *pBuffer;
612 pContext = alcGetCurrentContext();
613 if(!pContext) return;
614 SuspendContext(pContext);
616 if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0)
618 pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer);
620 if(pBuffer->state == MAPPED)
621 pBuffer->state = UNMAPPED;
622 else
623 alSetError(AL_INVALID_OPERATION);
625 else
626 alSetError(AL_INVALID_NAME);
628 ProcessContext(pContext);
633 * ReleaseALDatabuffers()
635 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
637 ALvoid ReleaseALDatabuffers(ALCdevice *device)
639 ALdatabuffer *ALBuffer;
640 ALdatabuffer *ALBufferTemp;
642 ALBuffer = device->Databuffers;
643 while(ALBuffer)
645 // Release sample data
646 free(ALBuffer->data);
648 // Release Buffer structure
649 ALBufferTemp = ALBuffer;
650 ALBuffer = ALBuffer->next;
651 memset(ALBufferTemp, 0, sizeof(ALdatabuffer));
652 free(ALBufferTemp);
654 device->Databuffers = NULL;
655 device->DatabufferCount = 0;