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
31 #include "alDatabuffer.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
)
47 Context
= GetContextSuspended();
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
);
55 ALCdevice
*device
= Context
->Device
;
58 /* Create all the new Databuffers */
61 ALdatabuffer
*buffer
= calloc(1, sizeof(ALdatabuffer
));
64 alSetError(Context
, AL_OUT_OF_MEMORY
);
65 alDeleteDatabuffersEXT(i
, puiBuffers
);
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
));
78 alSetError(Context
, err
);
79 alDeleteDatabuffersEXT(i
, puiBuffers
);
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
)
104 Context
= GetContextSuspended();
107 /* Check we are actually Deleting some Databuffers */
109 device
= Context
->Device
;
111 alSetError(Context
, AL_INVALID_VALUE
);
115 /* Check that all the databuffers are valid and can actually be
122 /* Check for valid Buffer ID */
123 if((ALBuf
=LookupDatabuffer(device
->DatabufferMap
, buffers
[i
])) == NULL
)
125 /* Invalid Databuffer */
126 alSetError(Context
, AL_INVALID_NAME
);
130 else if(ALBuf
->state
!= UNMAPPED
)
132 /* Databuffer still in use, cannot be deleted */
133 alSetError(Context
, AL_INVALID_OPERATION
);
140 /* If all the Databuffers were valid (and unmapped), then we can delete them */
145 if((ALBuf
=LookupDatabuffer(device
->DatabufferMap
, buffers
[i
])) == NULL
)
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
156 // Release buffer structure
157 RemoveUIntMapKey(&device
->DatabufferMap
, ALBuf
->databuffer
);
158 ALTHUNK_REMOVEENTRY(ALBuf
->databuffer
);
160 memset(ALBuf
, 0, sizeof(ALdatabuffer
));
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
)
179 Context
= GetContextSuspended();
180 if(!Context
) return AL_FALSE
;
182 device
= Context
->Device
;
183 result
= ((!buffer
|| LookupDatabuffer(device
->DatabufferMap
, buffer
)) ?
186 ProcessContext(Context
);
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
)
203 Context
= GetContextSuspended();
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
)
219 /* (Re)allocate data */
220 temp
= realloc(ALBuf
->data
, size
);
225 ALBuf
->usage
= usage
;
227 memcpy(ALBuf
->data
, data
, size
);
230 alSetError(Context
, AL_OUT_OF_MEMORY
);
233 alSetError(Context
, AL_INVALID_VALUE
);
236 alSetError(Context
, AL_INVALID_ENUM
);
239 alSetError(Context
, AL_INVALID_OPERATION
);
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
;
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
);
264 alSetError(pContext
, AL_INVALID_OPERATION
);
267 alSetError(pContext
, AL_INVALID_VALUE
);
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
;
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
);
292 alSetError(pContext
, AL_INVALID_OPERATION
);
295 alSetError(pContext
, AL_INVALID_VALUE
);
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
;
311 pContext
= GetContextSuspended();
312 if(!pContext
) return;
314 Device
= pContext
->Device
;
315 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
320 alSetError(pContext
, AL_INVALID_ENUM
);
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
;
337 pContext
= GetContextSuspended();
338 if(!pContext
) return;
340 Device
= pContext
->Device
;
341 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
346 alSetError(pContext
, AL_INVALID_ENUM
);
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
;
364 pContext
= GetContextSuspended();
365 if(!pContext
) return;
367 Device
= pContext
->Device
;
368 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
373 alSetError(pContext
, AL_INVALID_ENUM
);
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
;
390 pContext
= GetContextSuspended();
391 if(!pContext
) return;
393 Device
= pContext
->Device
;
394 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
399 alSetError(pContext
, AL_INVALID_ENUM
);
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
;
415 pContext
= GetContextSuspended();
416 if(!pContext
) return;
420 Device
= pContext
->Device
;
421 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
426 alSetError(pContext
, AL_INVALID_ENUM
);
431 alSetError(pContext
, AL_INVALID_NAME
);
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
;
444 pContext
= GetContextSuspended();
445 if(!pContext
) return;
449 Device
= pContext
->Device
;
450 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
455 alSetError(pContext
, AL_INVALID_ENUM
);
460 alSetError(pContext
, AL_INVALID_NAME
);
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
;
474 pContext
= GetContextSuspended();
475 if(!pContext
) return;
479 Device
= pContext
->Device
;
480 if((pBuffer
=LookupDatabuffer(Device
->DatabufferMap
, buffer
)) != NULL
)
485 *plValue
= (ALint
)pBuffer
->size
;
489 alSetError(pContext
, AL_INVALID_ENUM
);
494 alSetError(pContext
, AL_INVALID_NAME
);
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
;
507 pContext
= GetContextSuspended();
508 if(!pContext
) return;
512 Device
= pContext
->Device
;
513 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
518 alGetDatabufferiEXT(buffer
, eParam
, plValues
);
522 alSetError(pContext
, AL_INVALID_ENUM
);
527 alSetError(pContext
, AL_INVALID_NAME
);
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
;
542 pContext
= GetContextSuspended();
543 if(!pContext
) return;
545 Device
= pContext
->Device
;
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
;
554 alSetError(pContext
, AL_INVALID_VALUE
);
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
;
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
;
587 alSetError(pContext
, AL_INVALID_OPERATION
);
590 alSetError(pContext
, AL_INVALID_ENUM
);
593 alSetError(pContext
, AL_INVALID_VALUE
);
596 alSetError(pContext
, AL_INVALID_NAME
);
598 ProcessContext(pContext
);
603 AL_API ALvoid AL_APIENTRY
alUnmapDatabufferEXT(ALuint uiBuffer
)
605 ALCcontext
*pContext
;
606 ALdatabuffer
*pBuffer
;
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
;
618 alSetError(pContext
, AL_INVALID_OPERATION
);
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
)
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
643 // Release Buffer structure
644 ALTHUNK_REMOVEENTRY(temp
->databuffer
);
645 memset(temp
, 0, sizeof(ALdatabuffer
));