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
);
176 * alIsDatabufferEXT(ALuint uiBuffer)
178 * Checks if ulBuffer is a valid Databuffer Name
180 ALboolean ALAPIENTRY
alIsDatabufferEXT(ALuint uiBuffer
)
185 Context
= GetContextSuspended();
186 if(!Context
) return AL_FALSE
;
188 /* Check through list of generated databuffers for uiBuffer */
189 ALBuf
= Context
->Device
->Databuffers
;
190 while(ALBuf
&& ALBuf
->databuffer
!= uiBuffer
)
193 ProcessContext(Context
);
195 return ((ALBuf
|| !uiBuffer
) ? AL_TRUE
: AL_FALSE
);
199 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
201 * Fill databuffer with data
203 ALvoid ALAPIENTRY
alDatabufferDataEXT(ALuint buffer
,const ALvoid
*data
,ALsizei size
,ALenum usage
)
209 Context
= GetContextSuspended();
212 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
214 ALBuf
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(buffer
);
215 if(ALBuf
->state
== UNMAPPED
)
217 if(usage
== AL_STREAM_WRITE_EXT
|| usage
== AL_STREAM_READ_EXT
||
218 usage
== AL_STREAM_COPY_EXT
|| usage
== AL_STATIC_WRITE_EXT
||
219 usage
== AL_STATIC_READ_EXT
|| usage
== AL_STATIC_COPY_EXT
||
220 usage
== AL_DYNAMIC_WRITE_EXT
|| usage
== AL_DYNAMIC_READ_EXT
||
221 usage
== AL_DYNAMIC_COPY_EXT
)
223 /* (Re)allocate data */
224 temp
= realloc(ALBuf
->data
, size
);
229 ALBuf
->usage
= usage
;
231 memcpy(ALBuf
->data
, data
, size
);
234 alSetError(AL_OUT_OF_MEMORY
);
237 alSetError(AL_INVALID_ENUM
);
240 alSetError(AL_INVALID_OPERATION
);
243 alSetError(AL_INVALID_NAME
);
245 ProcessContext(Context
);
248 ALvoid ALAPIENTRY
alDatabufferSubDataEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, const ALvoid
*data
)
250 ALCcontext
*pContext
;
251 ALdatabuffer
*pBuffer
;
253 pContext
= GetContextSuspended();
254 if(!pContext
) return;
256 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
258 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
260 if(length
>= 0 && start
+length
<= pBuffer
->size
)
262 if(pBuffer
->state
== UNMAPPED
)
263 memcpy(pBuffer
->data
+start
, data
, length
);
265 alSetError(AL_INVALID_OPERATION
);
268 alSetError(AL_INVALID_VALUE
);
271 alSetError(AL_INVALID_NAME
);
273 ProcessContext(pContext
);
276 ALvoid ALAPIENTRY
alGetDatabufferSubDataEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, ALvoid
*data
)
278 ALCcontext
*pContext
;
279 ALdatabuffer
*pBuffer
;
281 pContext
= GetContextSuspended();
282 if(!pContext
) return;
284 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
286 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
288 if(length
>= 0 && start
+length
<= pBuffer
->size
)
290 if(pBuffer
->state
== UNMAPPED
)
291 memcpy(data
, pBuffer
->data
+start
, length
);
293 alSetError(AL_INVALID_OPERATION
);
296 alSetError(AL_INVALID_VALUE
);
299 alSetError(AL_INVALID_NAME
);
301 ProcessContext(pContext
);
305 ALvoid ALAPIENTRY
alDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat flValue
)
307 ALCcontext
*pContext
;
311 pContext
= GetContextSuspended();
312 if(!pContext
) return;
314 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
319 alSetError(AL_INVALID_ENUM
);
324 alSetError(AL_INVALID_NAME
);
326 ProcessContext(pContext
);
329 ALvoid ALAPIENTRY
alDatabufferfvEXT(ALuint buffer
, ALenum eParam
, const ALfloat
* flValues
)
331 ALCcontext
*pContext
;
335 pContext
= GetContextSuspended();
336 if(!pContext
) return;
338 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
343 alSetError(AL_INVALID_ENUM
);
348 alSetError(AL_INVALID_NAME
);
350 ProcessContext(pContext
);
354 ALvoid ALAPIENTRY
alDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint lValue
)
356 ALCcontext
*pContext
;
360 pContext
= GetContextSuspended();
361 if(!pContext
) return;
363 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
368 alSetError(AL_INVALID_ENUM
);
373 alSetError(AL_INVALID_NAME
);
375 ProcessContext(pContext
);
378 ALvoid ALAPIENTRY
alDatabufferivEXT(ALuint buffer
, ALenum eParam
, const ALint
* plValues
)
380 ALCcontext
*pContext
;
384 pContext
= GetContextSuspended();
385 if(!pContext
) return;
387 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
392 alSetError(AL_INVALID_ENUM
);
397 alSetError(AL_INVALID_NAME
);
399 ProcessContext(pContext
);
403 ALvoid ALAPIENTRY
alGetDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat
*pflValue
)
405 ALCcontext
*pContext
;
407 pContext
= GetContextSuspended();
408 if(!pContext
) return;
412 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
417 alSetError(AL_INVALID_ENUM
);
422 alSetError(AL_INVALID_NAME
);
425 alSetError(AL_INVALID_VALUE
);
427 ProcessContext(pContext
);
430 ALvoid ALAPIENTRY
alGetDatabufferfvEXT(ALuint buffer
, ALenum eParam
, ALfloat
* pflValues
)
432 ALCcontext
*pContext
;
434 pContext
= GetContextSuspended();
435 if(!pContext
) return;
439 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
444 alSetError(AL_INVALID_ENUM
);
449 alSetError(AL_INVALID_NAME
);
452 alSetError(AL_INVALID_VALUE
);
454 ProcessContext(pContext
);
457 ALvoid ALAPIENTRY
alGetDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint
*plValue
)
459 ALCcontext
*pContext
;
460 ALdatabuffer
*pBuffer
;
462 pContext
= GetContextSuspended();
463 if(!pContext
) return;
467 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
469 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(buffer
);
474 *plValue
= pBuffer
->size
;
478 alSetError(AL_INVALID_ENUM
);
483 alSetError(AL_INVALID_NAME
);
486 alSetError(AL_INVALID_VALUE
);
488 ProcessContext(pContext
);
491 ALvoid ALAPIENTRY
alGetDatabufferivEXT(ALuint buffer
, ALenum eParam
, ALint
* plValues
)
493 ALCcontext
*pContext
;
495 pContext
= GetContextSuspended();
496 if(!pContext
) return;
500 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
505 alGetDatabufferiEXT(buffer
, eParam
, plValues
);
509 alSetError(AL_INVALID_ENUM
);
514 alSetError(AL_INVALID_NAME
);
517 alSetError(AL_INVALID_VALUE
);
519 ProcessContext(pContext
);
523 ALvoid ALAPIENTRY
alSelectDatabufferEXT(ALenum target
, ALuint uiBuffer
)
525 ALCcontext
*pContext
;
526 ALdatabuffer
*pBuffer
;
528 pContext
= GetContextSuspended();
529 if(!pContext
) return;
531 if(alIsDatabufferEXT(uiBuffer
))
533 pBuffer
= (ALdatabuffer
*)(uiBuffer
? ALTHUNK_LOOKUPENTRY(uiBuffer
) : NULL
);
534 if(target
== AL_SAMPLE_SOURCE_EXT
)
535 pContext
->SampleSource
= pBuffer
;
536 else if(target
== AL_SAMPLE_SINK_EXT
)
537 pContext
->SampleSink
= pBuffer
;
539 alSetError(AL_INVALID_VALUE
);
542 alSetError(AL_INVALID_NAME
);
544 ProcessContext(pContext
);
548 ALvoid
* ALAPIENTRY
alMapDatabufferEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, ALenum access
)
550 ALCcontext
*pContext
;
551 ALdatabuffer
*pBuffer
;
554 pContext
= GetContextSuspended();
555 if(!pContext
) return NULL
;
557 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
559 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
561 if(length
>= 0 && start
+length
<= pBuffer
->size
)
563 if(access
== AL_READ_ONLY_EXT
|| access
== AL_WRITE_ONLY_EXT
||
564 access
== AL_READ_WRITE_EXT
)
566 if(pBuffer
->state
== UNMAPPED
)
568 ret
= pBuffer
->data
+ start
;
569 pBuffer
->state
= MAPPED
;
572 alSetError(AL_INVALID_OPERATION
);
575 alSetError(AL_INVALID_ENUM
);
578 alSetError(AL_INVALID_VALUE
);
581 alSetError(AL_INVALID_NAME
);
583 ProcessContext(pContext
);
588 ALvoid ALAPIENTRY
alUnmapDatabufferEXT(ALuint uiBuffer
)
590 ALCcontext
*pContext
;
591 ALdatabuffer
*pBuffer
;
593 pContext
= GetContextSuspended();
594 if(!pContext
) return;
596 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
598 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
600 if(pBuffer
->state
== MAPPED
)
601 pBuffer
->state
= UNMAPPED
;
603 alSetError(AL_INVALID_OPERATION
);
606 alSetError(AL_INVALID_NAME
);
608 ProcessContext(pContext
);
613 * ReleaseALDatabuffers()
615 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
617 ALvoid
ReleaseALDatabuffers(ALCdevice
*device
)
619 ALdatabuffer
*ALBuffer
;
620 ALdatabuffer
*ALBufferTemp
;
622 ALBuffer
= device
->Databuffers
;
625 // Release sample data
626 free(ALBuffer
->data
);
628 // Release Buffer structure
629 ALBufferTemp
= ALBuffer
;
630 ALBuffer
= ALBuffer
->next
;
631 memset(ALBufferTemp
, 0, sizeof(ALdatabuffer
));
634 device
->Databuffers
= NULL
;
635 device
->DatabufferCount
= 0;