Add a basic WaveOut device
[openal-soft.git] / OpenAL32 / alDatabuffer.c
blobcbe65a09674dd7e7684b3eb530361eaf193eefa7
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 #define LookupDatabuffer(m, k) ((ALdatabuffer*)LookupUIntMapKey(&(m), (k)))
38 * alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers)
40 * Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers
42 AL_API 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 || IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint)))
52 alSetError(Context, AL_INVALID_VALUE);
53 else
55 ALCdevice *device = Context->Device;
56 ALenum err;
58 /* Create all the new Databuffers */
59 while(i < n)
61 ALdatabuffer *buffer = calloc(1, sizeof(ALdatabuffer));
62 if(!buffer)
64 alSetError(Context, AL_OUT_OF_MEMORY);
65 alDeleteDatabuffersEXT(i, puiBuffers);
66 break;
69 buffer->databuffer = ALTHUNK_ADDENTRY(buffer);
70 err = InsertUIntMapEntry(&device->DatabufferMap,
71 buffer->databuffer, buffer);
72 if(err != AL_NO_ERROR)
74 ALTHUNK_REMOVEENTRY(buffer->databuffer);
75 memset(buffer, 0, sizeof(ALdatabuffer));
76 free(buffer);
78 alSetError(Context, err);
79 alDeleteDatabuffersEXT(i, puiBuffers);
80 break;
82 puiBuffers[i++] = buffer->databuffer;
84 buffer->state = UNMAPPED;
88 ProcessContext(Context);
92 * alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
94 * Deletes the n AL Databuffers pointed to by puiBuffers
96 AL_API ALvoid AL_APIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *buffers)
98 ALCcontext *Context;
99 ALCdevice *device;
100 ALdatabuffer *ALBuf;
101 ALboolean Failed;
102 ALsizei i;
104 Context = GetContextSuspended();
105 if(!Context) return;
107 /* Check we are actually Deleting some Databuffers */
108 Failed = AL_TRUE;
109 device = Context->Device;
110 if(n < 0)
111 alSetError(Context, AL_INVALID_VALUE);
112 else
114 Failed = AL_FALSE;
115 /* Check that all the databuffers are valid and can actually be
116 * deleted */
117 for(i = 0;i < n;i++)
119 if(!buffers[i])
120 continue;
122 /* Check for valid Buffer ID */
123 if((ALBuf=LookupDatabuffer(device->DatabufferMap, buffers[i])) == NULL)
125 /* Invalid Databuffer */
126 alSetError(Context, AL_INVALID_NAME);
127 Failed = AL_TRUE;
128 break;
130 else if(ALBuf->state != UNMAPPED)
132 /* Databuffer still in use, cannot be deleted */
133 alSetError(Context, AL_INVALID_OPERATION);
134 Failed = AL_TRUE;
135 break;
140 /* If all the Databuffers were valid (and unmapped), then we can delete them */
141 if(!Failed)
143 for(i = 0;i < n;i++)
145 if((ALBuf=LookupDatabuffer(device->DatabufferMap, buffers[i])) == NULL)
146 continue;
148 if(ALBuf == Context->SampleSource)
149 Context->SampleSource = NULL;
150 if(ALBuf == Context->SampleSink)
151 Context->SampleSink = NULL;
153 // Release the memory used to store audio data
154 free(ALBuf->data);
156 // Release buffer structure
157 RemoveUIntMapKey(&device->DatabufferMap, ALBuf->databuffer);
158 ALTHUNK_REMOVEENTRY(ALBuf->databuffer);
160 memset(ALBuf, 0, sizeof(ALdatabuffer));
161 free(ALBuf);
165 ProcessContext(Context);
169 * alIsDatabufferEXT(ALuint uiBuffer)
171 * Checks if ulBuffer is a valid Databuffer Name
173 AL_API ALboolean AL_APIENTRY alIsDatabufferEXT(ALuint buffer)
175 ALCcontext *Context;
176 ALboolean result;
177 ALCdevice *device;
179 Context = GetContextSuspended();
180 if(!Context) return AL_FALSE;
182 device = Context->Device;
183 result = ((!buffer || LookupDatabuffer(device->DatabufferMap, buffer)) ?
184 AL_TRUE : AL_FALSE);
186 ProcessContext(Context);
188 return result;
192 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
194 * Fill databuffer with data
196 AL_API ALvoid AL_APIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizeiptrEXT size,ALenum usage)
198 ALCcontext *Context;
199 ALdatabuffer *ALBuf;
200 ALCdevice *Device;
201 ALvoid *temp;
203 Context = GetContextSuspended();
204 if(!Context) return;
206 Device = Context->Device;
207 if((ALBuf=LookupDatabuffer(Device->DatabufferMap, buffer)) != NULL)
209 if(ALBuf->state == UNMAPPED)
211 if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT ||
212 usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT ||
213 usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT ||
214 usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT ||
215 usage == AL_DYNAMIC_COPY_EXT)
217 if(size >= 0)
219 /* (Re)allocate data */
220 temp = realloc(ALBuf->data, size);
221 if(temp)
223 ALBuf->data = temp;
224 ALBuf->size = size;
225 ALBuf->usage = usage;
226 if(data)
227 memcpy(ALBuf->data, data, size);
229 else
230 alSetError(Context, AL_OUT_OF_MEMORY);
232 else
233 alSetError(Context, AL_INVALID_VALUE);
235 else
236 alSetError(Context, AL_INVALID_ENUM);
238 else
239 alSetError(Context, AL_INVALID_OPERATION);
241 else
242 alSetError(Context, AL_INVALID_NAME);
244 ProcessContext(Context);
247 AL_API ALvoid AL_APIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, const ALvoid *data)
249 ALCcontext *pContext;
250 ALdatabuffer *pBuffer;
251 ALCdevice *Device;
253 pContext = GetContextSuspended();
254 if(!pContext) return;
256 Device = pContext->Device;
257 if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
259 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
261 if(pBuffer->state == UNMAPPED)
262 memcpy(pBuffer->data+start, data, length);
263 else
264 alSetError(pContext, AL_INVALID_OPERATION);
266 else
267 alSetError(pContext, AL_INVALID_VALUE);
269 else
270 alSetError(pContext, AL_INVALID_NAME);
272 ProcessContext(pContext);
275 AL_API ALvoid AL_APIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALvoid *data)
277 ALCcontext *pContext;
278 ALdatabuffer *pBuffer;
279 ALCdevice *Device;
281 pContext = GetContextSuspended();
282 if(!pContext) return;
284 Device = pContext->Device;
285 if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
287 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
289 if(pBuffer->state == UNMAPPED)
290 memcpy(data, pBuffer->data+start, length);
291 else
292 alSetError(pContext, AL_INVALID_OPERATION);
294 else
295 alSetError(pContext, AL_INVALID_VALUE);
297 else
298 alSetError(pContext, AL_INVALID_NAME);
300 ProcessContext(pContext);
304 AL_API ALvoid AL_APIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue)
306 ALCcontext *pContext;
307 ALCdevice *Device;
309 (void)flValue;
311 pContext = GetContextSuspended();
312 if(!pContext) return;
314 Device = pContext->Device;
315 if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
317 switch(eParam)
319 default:
320 alSetError(pContext, AL_INVALID_ENUM);
321 break;
324 else
325 alSetError(pContext, AL_INVALID_NAME);
327 ProcessContext(pContext);
330 AL_API ALvoid AL_APIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues)
332 ALCcontext *pContext;
333 ALCdevice *Device;
335 (void)flValues;
337 pContext = GetContextSuspended();
338 if(!pContext) return;
340 Device = pContext->Device;
341 if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
343 switch(eParam)
345 default:
346 alSetError(pContext, AL_INVALID_ENUM);
347 break;
350 else
351 alSetError(pContext, AL_INVALID_NAME);
353 ProcessContext(pContext);
357 AL_API ALvoid AL_APIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue)
359 ALCcontext *pContext;
360 ALCdevice *Device;
362 (void)lValue;
364 pContext = GetContextSuspended();
365 if(!pContext) return;
367 Device = pContext->Device;
368 if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
370 switch(eParam)
372 default:
373 alSetError(pContext, AL_INVALID_ENUM);
374 break;
377 else
378 alSetError(pContext, AL_INVALID_NAME);
380 ProcessContext(pContext);
383 AL_API ALvoid AL_APIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues)
385 ALCcontext *pContext;
386 ALCdevice *Device;
388 (void)plValues;
390 pContext = GetContextSuspended();
391 if(!pContext) return;
393 Device = pContext->Device;
394 if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
396 switch(eParam)
398 default:
399 alSetError(pContext, AL_INVALID_ENUM);
400 break;
403 else
404 alSetError(pContext, AL_INVALID_NAME);
406 ProcessContext(pContext);
410 AL_API ALvoid AL_APIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue)
412 ALCcontext *pContext;
413 ALCdevice *Device;
415 pContext = GetContextSuspended();
416 if(!pContext) return;
418 if(pflValue)
420 Device = pContext->Device;
421 if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
423 switch(eParam)
425 default:
426 alSetError(pContext, AL_INVALID_ENUM);
427 break;
430 else
431 alSetError(pContext, AL_INVALID_NAME);
433 else
434 alSetError(pContext, AL_INVALID_VALUE);
436 ProcessContext(pContext);
439 AL_API ALvoid AL_APIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues)
441 ALCcontext *pContext;
442 ALCdevice *Device;
444 pContext = GetContextSuspended();
445 if(!pContext) return;
447 if(pflValues)
449 Device = pContext->Device;
450 if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
452 switch(eParam)
454 default:
455 alSetError(pContext, AL_INVALID_ENUM);
456 break;
459 else
460 alSetError(pContext, AL_INVALID_NAME);
462 else
463 alSetError(pContext, AL_INVALID_VALUE);
465 ProcessContext(pContext);
468 AL_API ALvoid AL_APIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue)
470 ALCcontext *pContext;
471 ALdatabuffer *pBuffer;
472 ALCdevice *Device;
474 pContext = GetContextSuspended();
475 if(!pContext) return;
477 if(plValue)
479 Device = pContext->Device;
480 if((pBuffer=LookupDatabuffer(Device->DatabufferMap, buffer)) != NULL)
482 switch(eParam)
484 case AL_SIZE:
485 *plValue = (ALint)pBuffer->size;
486 break;
488 default:
489 alSetError(pContext, AL_INVALID_ENUM);
490 break;
493 else
494 alSetError(pContext, AL_INVALID_NAME);
496 else
497 alSetError(pContext, AL_INVALID_VALUE);
499 ProcessContext(pContext);
502 AL_API ALvoid AL_APIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues)
504 ALCcontext *pContext;
505 ALCdevice *Device;
507 pContext = GetContextSuspended();
508 if(!pContext) return;
510 if(plValues)
512 Device = pContext->Device;
513 if(LookupDatabuffer(Device->DatabufferMap, buffer) != NULL)
515 switch (eParam)
517 case AL_SIZE:
518 alGetDatabufferiEXT(buffer, eParam, plValues);
519 break;
521 default:
522 alSetError(pContext, AL_INVALID_ENUM);
523 break;
526 else
527 alSetError(pContext, AL_INVALID_NAME);
529 else
530 alSetError(pContext, AL_INVALID_VALUE);
532 ProcessContext(pContext);
536 AL_API ALvoid AL_APIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer)
538 ALCcontext *pContext;
539 ALdatabuffer *pBuffer = NULL;
540 ALCdevice *Device;
542 pContext = GetContextSuspended();
543 if(!pContext) return;
545 Device = pContext->Device;
546 if(uiBuffer == 0 ||
547 (pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
549 if(target == AL_SAMPLE_SOURCE_EXT)
550 pContext->SampleSource = pBuffer;
551 else if(target == AL_SAMPLE_SINK_EXT)
552 pContext->SampleSink = pBuffer;
553 else
554 alSetError(pContext, AL_INVALID_VALUE);
556 else
557 alSetError(pContext, AL_INVALID_NAME);
559 ProcessContext(pContext);
563 AL_API ALvoid* AL_APIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALintptrEXT start, ALsizeiptrEXT length, ALenum access)
565 ALCcontext *pContext;
566 ALdatabuffer *pBuffer;
567 ALvoid *ret = NULL;
568 ALCdevice *Device;
570 pContext = GetContextSuspended();
571 if(!pContext) return NULL;
573 Device = pContext->Device;
574 if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
576 if(start >= 0 && length >= 0 && start+length <= pBuffer->size)
578 if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT ||
579 access == AL_READ_WRITE_EXT)
581 if(pBuffer->state == UNMAPPED)
583 ret = pBuffer->data + start;
584 pBuffer->state = MAPPED;
586 else
587 alSetError(pContext, AL_INVALID_OPERATION);
589 else
590 alSetError(pContext, AL_INVALID_ENUM);
592 else
593 alSetError(pContext, AL_INVALID_VALUE);
595 else
596 alSetError(pContext, AL_INVALID_NAME);
598 ProcessContext(pContext);
600 return ret;
603 AL_API ALvoid AL_APIENTRY alUnmapDatabufferEXT(ALuint uiBuffer)
605 ALCcontext *pContext;
606 ALdatabuffer *pBuffer;
607 ALCdevice *Device;
609 pContext = GetContextSuspended();
610 if(!pContext) return;
612 Device = pContext->Device;
613 if((pBuffer=LookupDatabuffer(Device->DatabufferMap, uiBuffer)) != NULL)
615 if(pBuffer->state == MAPPED)
616 pBuffer->state = UNMAPPED;
617 else
618 alSetError(pContext, AL_INVALID_OPERATION);
620 else
621 alSetError(pContext, 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 ALsizei i;
635 for(i = 0;i < device->DatabufferMap.size;i++)
637 ALdatabuffer *temp = device->DatabufferMap.array[i].value;
638 device->DatabufferMap.array[i].value = NULL;
640 // Release buffer data
641 free(temp->data);
643 // Release Buffer structure
644 ALTHUNK_REMOVEENTRY(temp->databuffer);
645 memset(temp, 0, sizeof(ALdatabuffer));
646 free(temp);