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
= alcGetCurrentContext();
47 SuspendContext(Context
);
49 /* Check that we are actually generation some Databuffers */
52 ALCdevice
*device
= Context
->Device
;
54 /* Check the pointer is valid (and points to enough memory to store
55 * Databuffer Names) */
56 if(!IsBadWritePtr((void*)puiBuffers
, n
* sizeof(ALuint
)))
58 ALdatabuffer
**list
= &device
->Databuffers
;
60 list
= &(*list
)->next
;
62 /* Create all the new Databuffers */
65 *list
= calloc(1, sizeof(ALdatabuffer
));
68 alDeleteDatabuffersEXT(i
, puiBuffers
);
69 alSetError(AL_OUT_OF_MEMORY
);
73 puiBuffers
[i
] = (ALuint
)ALTHUNK_ADDENTRY(*list
);
74 (*list
)->databuffer
= puiBuffers
[i
];
75 (*list
)->state
= UNMAPPED
;
76 device
->DatabufferCount
++;
79 list
= &(*list
)->next
;
83 alSetError(AL_INVALID_VALUE
);
86 ProcessContext(Context
);
90 * alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers)
92 * Deletes the n AL Databuffers pointed to by puiBuffers
94 ALvoid ALAPIENTRY
alDeleteDatabuffersEXT(ALsizei n
, const ALuint
*puiBuffers
)
99 ALboolean bFailed
= AL_FALSE
;
101 Context
= alcGetCurrentContext();
103 SuspendContext(Context
);
105 /* Check we are actually Deleting some Databuffers */
108 ALCdevice
*device
= Context
->Device
;
110 /* Check that all the databuffers are valid and can actually be
114 /* Check for valid Buffer ID (can be NULL buffer) */
115 if(alIsDatabufferEXT(puiBuffers
[i
]))
117 /* If not the NULL buffer, check that it's unmapped */
118 ALBuf
= ((ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(puiBuffers
[i
]));
121 if(ALBuf
->state
!= UNMAPPED
)
123 /* Databuffer still in use, cannot be deleted */
124 alSetError(AL_INVALID_OPERATION
);
131 /* Invalid Databuffer */
132 alSetError(AL_INVALID_NAME
);
137 /* If all the Databuffers were valid (and unmapped), then we can
143 if(puiBuffers
[i
] && alIsDatabufferEXT(puiBuffers
[i
]))
145 ALdatabuffer
**list
= &device
->Databuffers
;
147 ALBuf
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(puiBuffers
[i
]);
148 while(*list
&& *list
!= ALBuf
)
149 list
= &(*list
)->next
;
152 *list
= (*list
)->next
;
154 if(ALBuf
== Context
->SampleSource
)
155 Context
->SampleSource
= NULL
;
156 if(ALBuf
== Context
->SampleSink
)
157 Context
->SampleSink
= NULL
;
159 // Release the memory used to store audio data
162 // Release buffer structure
163 ALTHUNK_REMOVEENTRY(puiBuffers
[i
]);
164 memset(ALBuf
, 0, sizeof(ALdatabuffer
));
165 device
->DatabufferCount
--;
172 alSetError(AL_INVALID_VALUE
);
174 ProcessContext(Context
);
181 * alIsDatabufferEXT(ALuint uiBuffer)
183 * Checks if ulBuffer is a valid Databuffer Name
185 ALboolean ALAPIENTRY
alIsDatabufferEXT(ALuint uiBuffer
)
190 Context
= alcGetCurrentContext();
191 if(!Context
) return AL_FALSE
;
192 SuspendContext(Context
);
194 /* Check through list of generated databuffers for uiBuffer */
195 ALBuf
= Context
->Device
->Databuffers
;
196 while(ALBuf
&& ALBuf
->databuffer
!= uiBuffer
)
199 ProcessContext(Context
);
201 return ((ALBuf
|| !uiBuffer
) ? AL_TRUE
: AL_FALSE
);
205 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
207 * Fill databuffer with data
209 ALvoid ALAPIENTRY
alDatabufferDataEXT(ALuint buffer
,const ALvoid
*data
,ALsizei size
,ALenum usage
)
215 Context
= alcGetCurrentContext();
217 SuspendContext(Context
);
219 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
221 ALBuf
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(buffer
);
222 if(ALBuf
->state
== UNMAPPED
)
224 if(usage
== AL_STREAM_WRITE_EXT
|| usage
== AL_STREAM_READ_EXT
||
225 usage
== AL_STREAM_COPY_EXT
|| usage
== AL_STATIC_WRITE_EXT
||
226 usage
== AL_STATIC_READ_EXT
|| usage
== AL_STATIC_COPY_EXT
||
227 usage
== AL_DYNAMIC_WRITE_EXT
|| usage
== AL_DYNAMIC_READ_EXT
||
228 usage
== AL_DYNAMIC_COPY_EXT
)
230 /* (Re)allocate data */
231 temp
= realloc(ALBuf
->data
, size
);
236 ALBuf
->usage
= usage
;
238 memcpy(ALBuf
->data
, data
, size
);
241 alSetError(AL_OUT_OF_MEMORY
);
244 alSetError(AL_INVALID_ENUM
);
247 alSetError(AL_INVALID_OPERATION
);
250 alSetError(AL_INVALID_NAME
);
252 ProcessContext(Context
);
255 ALvoid ALAPIENTRY
alDatabufferSubDataEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, const ALvoid
*data
)
257 ALCcontext
*pContext
;
258 ALdatabuffer
*pBuffer
;
260 pContext
= alcGetCurrentContext();
261 if(!pContext
) return;
262 SuspendContext(pContext
);
264 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
266 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
268 if(length
>= 0 && start
+length
<= pBuffer
->size
)
270 if(pBuffer
->state
== UNMAPPED
)
271 memcpy(pBuffer
->data
+start
, data
, length
);
273 alSetError(AL_INVALID_OPERATION
);
276 alSetError(AL_INVALID_VALUE
);
279 alSetError(AL_INVALID_NAME
);
281 ProcessContext(pContext
);
284 ALvoid ALAPIENTRY
alGetDatabufferSubDataEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, ALvoid
*data
)
286 ALCcontext
*pContext
;
287 ALdatabuffer
*pBuffer
;
289 pContext
= alcGetCurrentContext();
290 if(!pContext
) return;
291 SuspendContext(pContext
);
293 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
295 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
297 if(length
>= 0 && start
+length
<= pBuffer
->size
)
299 if(pBuffer
->state
== UNMAPPED
)
300 memcpy(data
, pBuffer
->data
+start
, length
);
302 alSetError(AL_INVALID_OPERATION
);
305 alSetError(AL_INVALID_VALUE
);
308 alSetError(AL_INVALID_NAME
);
310 ProcessContext(pContext
);
314 ALvoid ALAPIENTRY
alDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat flValue
)
316 ALCcontext
*pContext
;
320 pContext
= alcGetCurrentContext();
321 if(!pContext
) return;
322 SuspendContext(pContext
);
324 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
329 alSetError(AL_INVALID_ENUM
);
334 alSetError(AL_INVALID_NAME
);
336 ProcessContext(pContext
);
339 ALvoid ALAPIENTRY
alDatabufferfvEXT(ALuint buffer
, ALenum eParam
, const ALfloat
* flValues
)
341 ALCcontext
*pContext
;
345 pContext
= alcGetCurrentContext();
346 if(!pContext
) return;
347 SuspendContext(pContext
);
349 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
354 alSetError(AL_INVALID_ENUM
);
359 alSetError(AL_INVALID_NAME
);
361 ProcessContext(pContext
);
365 ALvoid ALAPIENTRY
alDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint lValue
)
367 ALCcontext
*pContext
;
371 pContext
= alcGetCurrentContext();
372 if(!pContext
) return;
373 SuspendContext(pContext
);
375 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
380 alSetError(AL_INVALID_ENUM
);
385 alSetError(AL_INVALID_NAME
);
387 ProcessContext(pContext
);
390 ALvoid ALAPIENTRY
alDatabufferivEXT(ALuint buffer
, ALenum eParam
, const ALint
* plValues
)
392 ALCcontext
*pContext
;
396 pContext
= alcGetCurrentContext();
397 if(!pContext
) return;
398 SuspendContext(pContext
);
400 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
405 alSetError(AL_INVALID_ENUM
);
410 alSetError(AL_INVALID_NAME
);
412 ProcessContext(pContext
);
416 ALvoid ALAPIENTRY
alGetDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat
*pflValue
)
418 ALCcontext
*pContext
;
420 pContext
= alcGetCurrentContext();
421 if(!pContext
) return;
422 SuspendContext(pContext
);
426 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
431 alSetError(AL_INVALID_ENUM
);
436 alSetError(AL_INVALID_NAME
);
439 alSetError(AL_INVALID_VALUE
);
441 ProcessContext(pContext
);
444 ALvoid ALAPIENTRY
alGetDatabufferfvEXT(ALuint buffer
, ALenum eParam
, ALfloat
* pflValues
)
446 ALCcontext
*pContext
;
448 pContext
= alcGetCurrentContext();
449 if(!pContext
) return;
450 SuspendContext(pContext
);
454 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
459 alSetError(AL_INVALID_ENUM
);
464 alSetError(AL_INVALID_NAME
);
467 alSetError(AL_INVALID_VALUE
);
469 ProcessContext(pContext
);
472 ALvoid ALAPIENTRY
alGetDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint
*plValue
)
474 ALCcontext
*pContext
;
475 ALdatabuffer
*pBuffer
;
477 pContext
= alcGetCurrentContext();
478 if(!pContext
) return;
479 SuspendContext(pContext
);
483 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
485 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(buffer
);
490 *plValue
= pBuffer
->size
;
494 alSetError(AL_INVALID_ENUM
);
499 alSetError(AL_INVALID_NAME
);
502 alSetError(AL_INVALID_VALUE
);
504 ProcessContext(pContext
);
507 ALvoid ALAPIENTRY
alGetDatabufferivEXT(ALuint buffer
, ALenum eParam
, ALint
* plValues
)
509 ALCcontext
*pContext
;
511 pContext
= alcGetCurrentContext();
512 if(!pContext
) return;
513 SuspendContext(pContext
);
517 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
522 alGetBufferi(buffer
, eParam
, plValues
);
526 alSetError(AL_INVALID_ENUM
);
531 alSetError(AL_INVALID_NAME
);
534 alSetError(AL_INVALID_VALUE
);
536 ProcessContext(pContext
);
540 ALvoid ALAPIENTRY
alSelectDatabufferEXT(ALenum target
, ALuint uiBuffer
)
542 ALCcontext
*pContext
;
543 ALdatabuffer
*pBuffer
;
545 pContext
= alcGetCurrentContext();
546 if(!pContext
) return;
547 SuspendContext(pContext
);
549 if(alIsDatabufferEXT(uiBuffer
))
551 pBuffer
= (ALdatabuffer
*)(uiBuffer
? ALTHUNK_LOOKUPENTRY(uiBuffer
) : NULL
);
552 if(target
== AL_SAMPLE_SOURCE_EXT
)
553 pContext
->SampleSource
= pBuffer
;
554 else if(target
== AL_SAMPLE_SINK_EXT
)
555 pContext
->SampleSink
= pBuffer
;
557 alSetError(AL_INVALID_VALUE
);
560 alSetError(AL_INVALID_NAME
);
562 ProcessContext(pContext
);
566 ALvoid
* ALAPIENTRY
alMapDatabufferEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, ALenum access
)
568 ALCcontext
*pContext
;
569 ALdatabuffer
*pBuffer
;
572 pContext
= alcGetCurrentContext();
573 if(!pContext
) return NULL
;
574 SuspendContext(pContext
);
576 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
578 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
580 if(length
>= 0 && start
+length
<= pBuffer
->size
)
582 if(access
== AL_READ_ONLY_EXT
|| access
== AL_WRITE_ONLY_EXT
||
583 access
== AL_READ_WRITE_EXT
)
585 if(pBuffer
->state
== UNMAPPED
)
587 ret
= pBuffer
->data
+ start
;
588 pBuffer
->state
= MAPPED
;
591 alSetError(AL_INVALID_OPERATION
);
594 alSetError(AL_INVALID_ENUM
);
597 alSetError(AL_INVALID_VALUE
);
600 alSetError(AL_INVALID_NAME
);
602 ProcessContext(pContext
);
607 ALvoid ALAPIENTRY
alUnmapDatabufferEXT(ALuint uiBuffer
)
609 ALCcontext
*pContext
;
610 ALdatabuffer
*pBuffer
;
612 pContext
= alcGetCurrentContext();
613 if(!pContext
) return;
614 SuspendContext(pContext
);
616 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
618 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
620 if(pBuffer
->state
== MAPPED
)
621 pBuffer
->state
= UNMAPPED
;
623 alSetError(AL_INVALID_OPERATION
);
626 alSetError(AL_INVALID_NAME
);
628 ProcessContext(pContext
);
633 * ReleaseALDatabuffers()
635 * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist
637 ALvoid
ReleaseALDatabuffers(ALCdevice
*device
)
639 ALdatabuffer
*ALBuffer
;
640 ALdatabuffer
*ALBufferTemp
;
642 ALBuffer
= device
->Databuffers
;
645 // Release sample data
646 free(ALBuffer
->data
);
648 // Release Buffer structure
649 ALBufferTemp
= ALBuffer
;
650 ALBuffer
= ALBuffer
->next
;
651 memset(ALBufferTemp
, 0, sizeof(ALdatabuffer
));
654 device
->Databuffers
= NULL
;
655 device
->DatabufferCount
= 0;