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 */
53 ALCdevice
*device
= Context
->Device
;
55 /* Check the pointer is valid (and points to enough memory to store
56 * Databuffer Names) */
57 if(!IsBadWritePtr((void*)puiBuffers
, n
* sizeof(ALuint
)))
61 /* Create all the new Databuffers */
64 ALdatabuffer
*buffer
= calloc(1, sizeof(ALdatabuffer
));
67 alSetError(Context
, AL_OUT_OF_MEMORY
);
68 alDeleteDatabuffersEXT(i
, puiBuffers
);
72 buffer
->databuffer
= ALTHUNK_ADDENTRY(buffer
);
73 err
= InsertUIntMapEntry(&device
->DatabufferMap
,
74 buffer
->databuffer
, buffer
);
75 if(err
!= AL_NO_ERROR
)
77 ALTHUNK_REMOVEENTRY(buffer
->databuffer
);
78 memset(buffer
, 0, sizeof(ALdatabuffer
));
81 alSetError(Context
, err
);
82 alDeleteDatabuffersEXT(i
, puiBuffers
);
85 puiBuffers
[i
++] = buffer
->databuffer
;
87 buffer
->state
= UNMAPPED
;
91 alSetError(Context
, AL_INVALID_VALUE
);
94 ProcessContext(Context
);
98 * alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
100 * Deletes the n AL Databuffers pointed to by puiBuffers
102 AL_API ALvoid AL_APIENTRY
alDeleteDatabuffersEXT(ALsizei n
, const ALuint
*puiBuffers
)
107 ALboolean bFailed
= AL_FALSE
;
109 Context
= GetContextSuspended();
112 /* Check we are actually Deleting some Databuffers */
115 ALCdevice
*device
= Context
->Device
;
117 /* Check that all the databuffers are valid and can actually be
124 /* Check for valid Buffer ID */
125 if((ALBuf
=LookupDatabuffer(device
->DatabufferMap
, puiBuffers
[i
])) != NULL
)
127 if(ALBuf
->state
!= UNMAPPED
)
129 /* Databuffer still in use, cannot be deleted */
130 alSetError(Context
, AL_INVALID_OPERATION
);
137 /* Invalid Databuffer */
138 alSetError(Context
, AL_INVALID_NAME
);
144 /* If all the Databuffers were valid (and unmapped), then we can
150 if((ALBuf
=LookupDatabuffer(device
->DatabufferMap
, puiBuffers
[i
])) != NULL
)
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
160 // Release buffer structure
161 RemoveUIntMapKey(&device
->DatabufferMap
, ALBuf
->databuffer
);
162 ALTHUNK_REMOVEENTRY(puiBuffers
[i
]);
164 memset(ALBuf
, 0, sizeof(ALdatabuffer
));
171 alSetError(Context
, AL_INVALID_VALUE
);
173 ProcessContext(Context
);
177 * alIsDatabufferEXT(ALuint uiBuffer)
179 * Checks if ulBuffer is a valid Databuffer Name
181 AL_API ALboolean AL_APIENTRY
alIsDatabufferEXT(ALuint buffer
)
187 Context
= GetContextSuspended();
188 if(!Context
) return AL_FALSE
;
190 device
= Context
->Device
;
191 result
= ((!buffer
|| LookupDatabuffer(device
->DatabufferMap
, buffer
)) ?
194 ProcessContext(Context
);
200 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
202 * Fill databuffer with data
204 AL_API ALvoid AL_APIENTRY
alDatabufferDataEXT(ALuint buffer
,const ALvoid
*data
,ALsizeiptrEXT size
,ALenum usage
)
211 Context
= GetContextSuspended();
214 Device
= Context
->Device
;
215 if((ALBuf
=LookupDatabuffer(Device
->DatabufferMap
, buffer
)) != NULL
)
217 if(ALBuf
->state
== UNMAPPED
)
219 if(usage
== AL_STREAM_WRITE_EXT
|| usage
== AL_STREAM_READ_EXT
||
220 usage
== AL_STREAM_COPY_EXT
|| usage
== AL_STATIC_WRITE_EXT
||
221 usage
== AL_STATIC_READ_EXT
|| usage
== AL_STATIC_COPY_EXT
||
222 usage
== AL_DYNAMIC_WRITE_EXT
|| usage
== AL_DYNAMIC_READ_EXT
||
223 usage
== AL_DYNAMIC_COPY_EXT
)
227 /* (Re)allocate data */
228 temp
= realloc(ALBuf
->data
, size
);
233 ALBuf
->usage
= usage
;
235 memcpy(ALBuf
->data
, data
, size
);
238 alSetError(Context
, AL_OUT_OF_MEMORY
);
241 alSetError(Context
, AL_INVALID_VALUE
);
244 alSetError(Context
, AL_INVALID_ENUM
);
247 alSetError(Context
, AL_INVALID_OPERATION
);
250 alSetError(Context
, AL_INVALID_NAME
);
252 ProcessContext(Context
);
255 AL_API ALvoid AL_APIENTRY
alDatabufferSubDataEXT(ALuint uiBuffer
, ALintptrEXT start
, ALsizeiptrEXT length
, const ALvoid
*data
)
257 ALCcontext
*pContext
;
258 ALdatabuffer
*pBuffer
;
261 pContext
= GetContextSuspended();
262 if(!pContext
) return;
264 Device
= pContext
->Device
;
265 if((pBuffer
=LookupDatabuffer(Device
->DatabufferMap
, uiBuffer
)) != NULL
)
267 if(start
>= 0 && length
>= 0 && start
+length
<= pBuffer
->size
)
269 if(pBuffer
->state
== UNMAPPED
)
270 memcpy(pBuffer
->data
+start
, data
, length
);
272 alSetError(pContext
, AL_INVALID_OPERATION
);
275 alSetError(pContext
, AL_INVALID_VALUE
);
278 alSetError(pContext
, AL_INVALID_NAME
);
280 ProcessContext(pContext
);
283 AL_API ALvoid AL_APIENTRY
alGetDatabufferSubDataEXT(ALuint uiBuffer
, ALintptrEXT start
, ALsizeiptrEXT length
, ALvoid
*data
)
285 ALCcontext
*pContext
;
286 ALdatabuffer
*pBuffer
;
289 pContext
= GetContextSuspended();
290 if(!pContext
) return;
292 Device
= pContext
->Device
;
293 if((pBuffer
=LookupDatabuffer(Device
->DatabufferMap
, uiBuffer
)) != NULL
)
295 if(start
>= 0 && length
>= 0 && start
+length
<= pBuffer
->size
)
297 if(pBuffer
->state
== UNMAPPED
)
298 memcpy(data
, pBuffer
->data
+start
, length
);
300 alSetError(pContext
, AL_INVALID_OPERATION
);
303 alSetError(pContext
, AL_INVALID_VALUE
);
306 alSetError(pContext
, AL_INVALID_NAME
);
308 ProcessContext(pContext
);
312 AL_API ALvoid AL_APIENTRY
alDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat flValue
)
314 ALCcontext
*pContext
;
319 pContext
= GetContextSuspended();
320 if(!pContext
) return;
322 Device
= pContext
->Device
;
323 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
328 alSetError(pContext
, AL_INVALID_ENUM
);
333 alSetError(pContext
, AL_INVALID_NAME
);
335 ProcessContext(pContext
);
338 AL_API ALvoid AL_APIENTRY
alDatabufferfvEXT(ALuint buffer
, ALenum eParam
, const ALfloat
* flValues
)
340 ALCcontext
*pContext
;
345 pContext
= GetContextSuspended();
346 if(!pContext
) return;
348 Device
= pContext
->Device
;
349 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
354 alSetError(pContext
, AL_INVALID_ENUM
);
359 alSetError(pContext
, AL_INVALID_NAME
);
361 ProcessContext(pContext
);
365 AL_API ALvoid AL_APIENTRY
alDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint lValue
)
367 ALCcontext
*pContext
;
372 pContext
= GetContextSuspended();
373 if(!pContext
) return;
375 Device
= pContext
->Device
;
376 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
381 alSetError(pContext
, AL_INVALID_ENUM
);
386 alSetError(pContext
, AL_INVALID_NAME
);
388 ProcessContext(pContext
);
391 AL_API ALvoid AL_APIENTRY
alDatabufferivEXT(ALuint buffer
, ALenum eParam
, const ALint
* plValues
)
393 ALCcontext
*pContext
;
398 pContext
= GetContextSuspended();
399 if(!pContext
) return;
401 Device
= pContext
->Device
;
402 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
407 alSetError(pContext
, AL_INVALID_ENUM
);
412 alSetError(pContext
, AL_INVALID_NAME
);
414 ProcessContext(pContext
);
418 AL_API ALvoid AL_APIENTRY
alGetDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat
*pflValue
)
420 ALCcontext
*pContext
;
423 pContext
= GetContextSuspended();
424 if(!pContext
) return;
428 Device
= pContext
->Device
;
429 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
434 alSetError(pContext
, AL_INVALID_ENUM
);
439 alSetError(pContext
, AL_INVALID_NAME
);
442 alSetError(pContext
, AL_INVALID_VALUE
);
444 ProcessContext(pContext
);
447 AL_API ALvoid AL_APIENTRY
alGetDatabufferfvEXT(ALuint buffer
, ALenum eParam
, ALfloat
* pflValues
)
449 ALCcontext
*pContext
;
452 pContext
= GetContextSuspended();
453 if(!pContext
) return;
457 Device
= pContext
->Device
;
458 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
463 alSetError(pContext
, AL_INVALID_ENUM
);
468 alSetError(pContext
, AL_INVALID_NAME
);
471 alSetError(pContext
, AL_INVALID_VALUE
);
473 ProcessContext(pContext
);
476 AL_API ALvoid AL_APIENTRY
alGetDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint
*plValue
)
478 ALCcontext
*pContext
;
479 ALdatabuffer
*pBuffer
;
482 pContext
= GetContextSuspended();
483 if(!pContext
) return;
487 Device
= pContext
->Device
;
488 if((pBuffer
=LookupDatabuffer(Device
->DatabufferMap
, buffer
)) != NULL
)
493 *plValue
= (ALint
)pBuffer
->size
;
497 alSetError(pContext
, AL_INVALID_ENUM
);
502 alSetError(pContext
, AL_INVALID_NAME
);
505 alSetError(pContext
, AL_INVALID_VALUE
);
507 ProcessContext(pContext
);
510 AL_API ALvoid AL_APIENTRY
alGetDatabufferivEXT(ALuint buffer
, ALenum eParam
, ALint
* plValues
)
512 ALCcontext
*pContext
;
515 pContext
= GetContextSuspended();
516 if(!pContext
) return;
520 Device
= pContext
->Device
;
521 if(LookupDatabuffer(Device
->DatabufferMap
, buffer
) != NULL
)
526 alGetDatabufferiEXT(buffer
, eParam
, plValues
);
530 alSetError(pContext
, AL_INVALID_ENUM
);
535 alSetError(pContext
, AL_INVALID_NAME
);
538 alSetError(pContext
, AL_INVALID_VALUE
);
540 ProcessContext(pContext
);
544 AL_API ALvoid AL_APIENTRY
alSelectDatabufferEXT(ALenum target
, ALuint uiBuffer
)
546 ALCcontext
*pContext
;
547 ALdatabuffer
*pBuffer
= NULL
;
550 pContext
= GetContextSuspended();
551 if(!pContext
) return;
553 Device
= pContext
->Device
;
555 (pBuffer
=LookupDatabuffer(Device
->DatabufferMap
, uiBuffer
)) != NULL
)
557 if(target
== AL_SAMPLE_SOURCE_EXT
)
558 pContext
->SampleSource
= pBuffer
;
559 else if(target
== AL_SAMPLE_SINK_EXT
)
560 pContext
->SampleSink
= pBuffer
;
562 alSetError(pContext
, AL_INVALID_VALUE
);
565 alSetError(pContext
, AL_INVALID_NAME
);
567 ProcessContext(pContext
);
571 AL_API ALvoid
* AL_APIENTRY
alMapDatabufferEXT(ALuint uiBuffer
, ALintptrEXT start
, ALsizeiptrEXT length
, ALenum access
)
573 ALCcontext
*pContext
;
574 ALdatabuffer
*pBuffer
;
578 pContext
= GetContextSuspended();
579 if(!pContext
) return NULL
;
581 Device
= pContext
->Device
;
582 if((pBuffer
=LookupDatabuffer(Device
->DatabufferMap
, uiBuffer
)) != NULL
)
584 if(start
>= 0 && length
>= 0 && start
+length
<= pBuffer
->size
)
586 if(access
== AL_READ_ONLY_EXT
|| access
== AL_WRITE_ONLY_EXT
||
587 access
== AL_READ_WRITE_EXT
)
589 if(pBuffer
->state
== UNMAPPED
)
591 ret
= pBuffer
->data
+ start
;
592 pBuffer
->state
= MAPPED
;
595 alSetError(pContext
, AL_INVALID_OPERATION
);
598 alSetError(pContext
, AL_INVALID_ENUM
);
601 alSetError(pContext
, AL_INVALID_VALUE
);
604 alSetError(pContext
, AL_INVALID_NAME
);
606 ProcessContext(pContext
);
611 AL_API ALvoid AL_APIENTRY
alUnmapDatabufferEXT(ALuint uiBuffer
)
613 ALCcontext
*pContext
;
614 ALdatabuffer
*pBuffer
;
617 pContext
= GetContextSuspended();
618 if(!pContext
) return;
620 Device
= pContext
->Device
;
621 if((pBuffer
=LookupDatabuffer(Device
->DatabufferMap
, uiBuffer
)) != NULL
)
623 if(pBuffer
->state
== MAPPED
)
624 pBuffer
->state
= UNMAPPED
;
626 alSetError(pContext
, AL_INVALID_OPERATION
);
629 alSetError(pContext
, AL_INVALID_NAME
);
631 ProcessContext(pContext
);
636 * ReleaseALDatabuffers()
638 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
640 ALvoid
ReleaseALDatabuffers(ALCdevice
*device
)
643 for(i
= 0;i
< device
->DatabufferMap
.size
;i
++)
645 ALdatabuffer
*temp
= device
->DatabufferMap
.array
[i
].value
;
646 device
->DatabufferMap
.array
[i
].value
= NULL
;
648 // Release buffer data
651 // Release Buffer structure
652 ALTHUNK_REMOVEENTRY(temp
->databuffer
);
653 memset(temp
, 0, sizeof(ALdatabuffer
));