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 // Release the memory used to store audio data
157 // Release buffer structure
158 ALTHUNK_REMOVEENTRY(puiBuffers
[i
]);
159 memset(ALBuf
, 0, sizeof(ALdatabuffer
));
160 device
->DatabufferCount
--;
167 alSetError(AL_INVALID_VALUE
);
169 ProcessContext(Context
);
176 * alIsDatabufferEXT(ALuint uiBuffer)
178 * Checks if ulBuffer is a valid Databuffer Name
180 ALboolean ALAPIENTRY
alIsDatabufferEXT(ALuint uiBuffer
)
185 Context
= alcGetCurrentContext();
186 if(!Context
) return AL_FALSE
;
187 SuspendContext(Context
);
189 /* Check through list of generated databuffers for uiBuffer */
190 ALBuf
= Context
->Device
->Databuffers
;
191 while(ALBuf
&& ALBuf
->databuffer
!= uiBuffer
)
194 ProcessContext(Context
);
196 return ((ALBuf
|| !uiBuffer
) ? AL_TRUE
: AL_FALSE
);
200 * alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage)
202 * Fill databuffer with data
204 ALvoid ALAPIENTRY
alDatabufferDataEXT(ALuint buffer
,const ALvoid
*data
,ALsizei size
,ALenum usage
)
210 Context
= alcGetCurrentContext();
212 SuspendContext(Context
);
214 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
216 ALBuf
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(buffer
);
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
)
225 /* (Re)allocate data */
226 temp
= realloc(ALBuf
->data
, size
);
231 ALBuf
->usage
= usage
;
233 memcpy(ALBuf
->data
, data
, size
);
236 alSetError(AL_OUT_OF_MEMORY
);
239 alSetError(AL_INVALID_ENUM
);
242 alSetError(AL_INVALID_OPERATION
);
245 alSetError(AL_INVALID_NAME
);
247 ProcessContext(Context
);
250 ALvoid ALAPIENTRY
alDatabufferSubDataEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, const ALvoid
*data
)
252 ALCcontext
*pContext
;
253 ALdatabuffer
*pBuffer
;
255 pContext
= alcGetCurrentContext();
256 if(!pContext
) return;
257 SuspendContext(pContext
);
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
= alcGetCurrentContext();
285 if(!pContext
) return;
286 SuspendContext(pContext
);
288 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
290 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
292 if(length
>= 0 && start
+length
<= pBuffer
->size
)
294 if(pBuffer
->state
== UNMAPPED
)
295 memcpy(data
, pBuffer
->data
+start
, length
);
297 alSetError(AL_INVALID_OPERATION
);
300 alSetError(AL_INVALID_VALUE
);
303 alSetError(AL_INVALID_NAME
);
305 ProcessContext(pContext
);
309 ALvoid ALAPIENTRY
alDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat flValue
)
311 ALCcontext
*pContext
;
315 pContext
= alcGetCurrentContext();
316 if(!pContext
) return;
317 SuspendContext(pContext
);
319 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
324 alSetError(AL_INVALID_ENUM
);
329 alSetError(AL_INVALID_NAME
);
331 ProcessContext(pContext
);
334 ALvoid ALAPIENTRY
alDatabufferfvEXT(ALuint buffer
, ALenum eParam
, const ALfloat
* flValues
)
336 ALCcontext
*pContext
;
340 pContext
= alcGetCurrentContext();
341 if(!pContext
) return;
342 SuspendContext(pContext
);
344 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
349 alSetError(AL_INVALID_ENUM
);
354 alSetError(AL_INVALID_NAME
);
356 ProcessContext(pContext
);
360 ALvoid ALAPIENTRY
alDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint lValue
)
362 ALCcontext
*pContext
;
366 pContext
= alcGetCurrentContext();
367 if(!pContext
) return;
368 SuspendContext(pContext
);
370 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
375 alSetError(AL_INVALID_ENUM
);
380 alSetError(AL_INVALID_NAME
);
382 ProcessContext(pContext
);
385 ALvoid ALAPIENTRY
alDatabufferivEXT(ALuint buffer
, ALenum eParam
, const ALint
* plValues
)
387 ALCcontext
*pContext
;
391 pContext
= alcGetCurrentContext();
392 if(!pContext
) return;
393 SuspendContext(pContext
);
395 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
400 alSetError(AL_INVALID_ENUM
);
405 alSetError(AL_INVALID_NAME
);
407 ProcessContext(pContext
);
411 ALvoid ALAPIENTRY
alGetDatabufferfEXT(ALuint buffer
, ALenum eParam
, ALfloat
*pflValue
)
413 ALCcontext
*pContext
;
415 pContext
= alcGetCurrentContext();
416 if(!pContext
) return;
417 SuspendContext(pContext
);
421 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
426 alSetError(AL_INVALID_ENUM
);
431 alSetError(AL_INVALID_NAME
);
434 alSetError(AL_INVALID_VALUE
);
436 ProcessContext(pContext
);
439 ALvoid ALAPIENTRY
alGetDatabufferfvEXT(ALuint buffer
, ALenum eParam
, ALfloat
* pflValues
)
441 ALCcontext
*pContext
;
443 pContext
= alcGetCurrentContext();
444 if(!pContext
) return;
445 SuspendContext(pContext
);
449 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
454 alSetError(AL_INVALID_ENUM
);
459 alSetError(AL_INVALID_NAME
);
462 alSetError(AL_INVALID_VALUE
);
464 ProcessContext(pContext
);
467 ALvoid ALAPIENTRY
alGetDatabufferiEXT(ALuint buffer
, ALenum eParam
, ALint
*plValue
)
469 ALCcontext
*pContext
;
470 ALdatabuffer
*pBuffer
;
472 pContext
= alcGetCurrentContext();
473 if(!pContext
) return;
474 SuspendContext(pContext
);
478 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
480 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(buffer
);
485 *plValue
= pBuffer
->size
;
489 alSetError(AL_INVALID_ENUM
);
494 alSetError(AL_INVALID_NAME
);
497 alSetError(AL_INVALID_VALUE
);
499 ProcessContext(pContext
);
502 ALvoid ALAPIENTRY
alGetDatabufferivEXT(ALuint buffer
, ALenum eParam
, ALint
* plValues
)
504 ALCcontext
*pContext
;
506 pContext
= alcGetCurrentContext();
507 if(!pContext
) return;
508 SuspendContext(pContext
);
512 if(alIsDatabufferEXT(buffer
) && buffer
!= 0)
517 alGetBufferi(buffer
, eParam
, plValues
);
521 alSetError(AL_INVALID_ENUM
);
526 alSetError(AL_INVALID_NAME
);
529 alSetError(AL_INVALID_VALUE
);
531 ProcessContext(pContext
);
535 ALvoid ALAPIENTRY
alSelectDatabufferEXT(ALenum target
, ALuint uiBuffer
)
537 ALCcontext
*pContext
;
538 ALdatabuffer
*pBuffer
;
540 pContext
= alcGetCurrentContext();
541 if(!pContext
) return;
542 SuspendContext(pContext
);
544 if(alIsDatabufferEXT(uiBuffer
))
546 pBuffer
= (ALdatabuffer
*)(uiBuffer
? ALTHUNK_LOOKUPENTRY(uiBuffer
) : NULL
);
547 if(target
== AL_SAMPLE_SOURCE_EXT
)
548 pContext
->SampleSource
= pBuffer
;
549 else if(target
== AL_SAMPLE_SINK_EXT
)
550 pContext
->SampleSink
= pBuffer
;
552 alSetError(AL_INVALID_VALUE
);
555 alSetError(AL_INVALID_NAME
);
557 ProcessContext(pContext
);
561 ALvoid
* ALAPIENTRY
alMapDatabufferEXT(ALuint uiBuffer
, ALuint start
, ALsizei length
, ALenum access
)
563 ALCcontext
*pContext
;
564 ALdatabuffer
*pBuffer
;
567 pContext
= alcGetCurrentContext();
568 if(!pContext
) return NULL
;
569 SuspendContext(pContext
);
571 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
573 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
575 if(length
>= 0 && start
+length
<= pBuffer
->size
)
577 if(access
== AL_READ_ONLY_EXT
|| access
== AL_WRITE_ONLY_EXT
||
578 access
== AL_READ_WRITE_EXT
)
580 if(pBuffer
->state
== UNMAPPED
)
582 ret
= pBuffer
->data
+ start
;
583 pBuffer
->state
= MAPPED
;
586 alSetError(AL_INVALID_OPERATION
);
589 alSetError(AL_INVALID_ENUM
);
592 alSetError(AL_INVALID_VALUE
);
595 alSetError(AL_INVALID_NAME
);
597 ProcessContext(pContext
);
602 ALvoid ALAPIENTRY
alUnmapDatabufferEXT(ALuint uiBuffer
)
604 ALCcontext
*pContext
;
605 ALdatabuffer
*pBuffer
;
607 pContext
= alcGetCurrentContext();
608 if(!pContext
) return;
609 SuspendContext(pContext
);
611 if(alIsDatabufferEXT(uiBuffer
) && uiBuffer
!= 0)
613 pBuffer
= (ALdatabuffer
*)ALTHUNK_LOOKUPENTRY(uiBuffer
);
615 if(pBuffer
->state
== MAPPED
)
616 pBuffer
->state
= UNMAPPED
;
618 alSetError(AL_INVALID_OPERATION
);
621 alSetError(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
)
634 ALdatabuffer
*ALBuffer
;
635 ALdatabuffer
*ALBufferTemp
;
637 ALBuffer
= device
->Databuffers
;
640 // Release sample data
641 free(ALBuffer
->data
);
643 // Release Buffer structure
644 ALBufferTemp
= ALBuffer
;
645 ALBuffer
= ALBuffer
->next
;
646 memset(ALBufferTemp
, 0, sizeof(ALdatabuffer
));
649 device
->Databuffers
= NULL
;
650 device
->DatabufferCount
= 0;