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"
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
)
45 Context
= GetContextSuspended();
48 /* Check that we are actually generation some Databuffers */
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
;
59 list
= &(*list
)->next
;
61 /* Create all the new Databuffers */
64 *list
= calloc(1, sizeof(ALdatabuffer
));
67 alDeleteDatabuffersEXT(i
, puiBuffers
);
68 alSetError(AL_OUT_OF_MEMORY
);
72 puiBuffers
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
73 (*list
)->databuffer
= puiBuffers
[i
];
74 (*list
)->state
= UNMAPPED
;
75 device
->DatabufferCount
++;
78 list
= &(*list
)->next
;
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
)
98 ALboolean bFailed
= AL_FALSE
;
100 Context
= GetContextSuspended();
103 /* Check we are actually Deleting some Databuffers */
106 ALCdevice
*device
= Context
->Device
;
108 /* Check that all the databuffers are valid and can actually be
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
]));
119 if(ALBuf
->state
!= UNMAPPED
)
121 /* Databuffer still in use, cannot be deleted */
122 alSetError(AL_INVALID_OPERATION
);
129 /* Invalid Databuffer */
130 alSetError(AL_INVALID_NAME
);
135 /* If all the Databuffers were valid (and unmapped), then we can
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
;
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
160 // Release buffer structure
161 ALTHUNK_REMOVEENTRY(puiBuffers
[i
]);
162 memset(ALBuf
, 0, sizeof(ALdatabuffer
));
163 device
->DatabufferCount
--;
170 alSetError(AL_INVALID_VALUE
);
172 ProcessContext(Context
);
179 * alIsDatabufferEXT(ALuint uiBuffer)
181 * Checks if ulBuffer is a valid Databuffer Name
183 ALboolean ALAPIENTRY
alIsDatabufferEXT(ALuint uiBuffer
)
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
)
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
)
212 Context
= GetContextSuspended();
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
);
232 ALBuf
->usage
= usage
;
234 memcpy(ALBuf
->data
, data
, size
);
237 alSetError(AL_OUT_OF_MEMORY
);
240 alSetError(AL_INVALID_ENUM
);
243 alSetError(AL_INVALID_OPERATION
);
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
);
268 alSetError(AL_INVALID_OPERATION
);
271 alSetError(AL_INVALID_VALUE
);
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
);
296 alSetError(AL_INVALID_OPERATION
);
299 alSetError(AL_INVALID_VALUE
);
302 alSetError(AL_INVALID_NAME
);
304 ProcessContext(pContext
);
308 ALvoid ALAPIENTRY
alDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat flValue
)
310 ALCcontext
*pContext
;
314 pContext
= GetContextSuspended();
315 if(!pContext
) return;
317 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
322 alSetError(AL_INVALID_ENUM
);
327 alSetError(AL_INVALID_NAME
);
329 ProcessContext(pContext
);
332 ALvoid ALAPIENTRY
alDatabufferfvEXT(ALuint buffer
, ALenum eParam
, const ALfloat
* flValues
)
334 ALCcontext
*pContext
;
338 pContext
= GetContextSuspended();
339 if(!pContext
) return;
341 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
346 alSetError(AL_INVALID_ENUM
);
351 alSetError(AL_INVALID_NAME
);
353 ProcessContext(pContext
);
357 ALvoid ALAPIENTRY
alDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint lValue
)
359 ALCcontext
*pContext
;
363 pContext
= GetContextSuspended();
364 if(!pContext
) return;
366 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
371 alSetError(AL_INVALID_ENUM
);
376 alSetError(AL_INVALID_NAME
);
378 ProcessContext(pContext
);
381 ALvoid ALAPIENTRY
alDatabufferivEXT(ALuint buffer
, ALenum eParam
, const ALint
* plValues
)
383 ALCcontext
*pContext
;
387 pContext
= GetContextSuspended();
388 if(!pContext
) return;
390 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
395 alSetError(AL_INVALID_ENUM
);
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;
415 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
420 alSetError(AL_INVALID_ENUM
);
425 alSetError(AL_INVALID_NAME
);
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;
442 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
447 alSetError(AL_INVALID_ENUM
);
452 alSetError(AL_INVALID_NAME
);
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;
470 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
472 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(buffer
);
477 *plValue
= pBuffer
->size
;
481 alSetError(AL_INVALID_ENUM
);
486 alSetError(AL_INVALID_NAME
);
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;
503 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
508 alGetBufferi(buffer
, eParam
, plValues
);
512 alSetError(AL_INVALID_ENUM
);
517 alSetError(AL_INVALID_NAME
);
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
;
542 alSetError(AL_INVALID_VALUE
);
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
;
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
;
575 alSetError(AL_INVALID_OPERATION
);
578 alSetError(AL_INVALID_ENUM
);
581 alSetError(AL_INVALID_VALUE
);
584 alSetError(AL_INVALID_NAME
);
586 ProcessContext(pContext
);
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
;
606 alSetError(AL_INVALID_OPERATION
);
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
;
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
));
637 device
->Databuffers
= NULL
;
638 device
->DatabufferCount
= 0;