diff options
Diffstat (limited to 'OpenAL32/alDatabuffer.c')
-rw-r--r-- | OpenAL32/alDatabuffer.c | 651 |
1 files changed, 651 insertions, 0 deletions
diff --git a/OpenAL32/alDatabuffer.c b/OpenAL32/alDatabuffer.c new file mode 100644 index 00000000..5b285b8d --- /dev/null +++ b/OpenAL32/alDatabuffer.c @@ -0,0 +1,651 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2007 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include "alMain.h" +#include "AL/al.h" +#include "AL/alc.h" +#include "AL/alext.h" +#include "alError.h" +#include "alDatabuffer.h" +#include "alThunk.h" + + +/* +* alGenDatabuffersEXT(ALsizei n, ALuint *puiBuffers) +* +* Generates n AL Databuffers, and stores the Databuffers Names in the array pointed to by puiBuffers +*/ +ALvoid ALAPIENTRY alGenDatabuffersEXT(ALsizei n,ALuint *puiBuffers) +{ + ALCcontext *Context; + ALsizei i=0; + + Context = alcGetCurrentContext(); + if(!Context) return; + SuspendContext(Context); + + /* Check that we are actually generation some Databuffers */ + if(n > 0) + { + ALCdevice *device = Context->Device; + + /* Check the pointer is valid (and points to enough memory to store + * Databuffer Names) */ + if(!IsBadWritePtr((void*)puiBuffers, n * sizeof(ALuint))) + { + ALdatabuffer **list = &device->Databuffers; + while(*list) + list = &(*list)->next; + + /* Create all the new Databuffers */ + while(i < n) + { + *list = calloc(1, sizeof(ALdatabuffer)); + if(!(*list)) + { + alDeleteDatabuffersEXT(i, puiBuffers); + alSetError(AL_OUT_OF_MEMORY); + break; + } + + puiBuffers[i] = (ALuint)ALTHUNK_ADDENTRY(*list); + (*list)->databuffer = puiBuffers[i]; + (*list)->state = UNMAPPED; + device->DatabufferCount++; + i++; + + list = &(*list)->next; + } + } + else + alSetError(AL_INVALID_VALUE); + } + + ProcessContext(Context); +} + +/* +* alDatabeleteBuffersEXT(ALsizei n, ALuint *puiBuffers) +* +* Deletes the n AL Databuffers pointed to by puiBuffers +*/ +ALvoid ALAPIENTRY alDeleteDatabuffersEXT(ALsizei n, const ALuint *puiBuffers) +{ + ALCcontext *Context; + ALdatabuffer *ALBuf; + ALsizei i; + ALboolean bFailed = AL_FALSE; + + Context = alcGetCurrentContext(); + if(!Context) return; + SuspendContext(Context); + + /* Check we are actually Deleting some Databuffers */ + if(n >= 0) + { + ALCdevice *device = Context->Device; + + /* Check that all the databuffers are valid and can actually be + * deleted */ + for(i = 0;i < n;i++) + { + /* Check for valid Buffer ID (can be NULL buffer) */ + if(alIsDatabufferEXT(puiBuffers[i])) + { + /* If not the NULL buffer, check that it's unmapped */ + ALBuf = ((ALdatabuffer *)ALTHUNK_LOOKUPENTRY(puiBuffers[i])); + if(ALBuf) + { + if(ALBuf->state != UNMAPPED) + { + /* Databuffer still in use, cannot be deleted */ + alSetError(AL_INVALID_OPERATION); + bFailed = AL_TRUE; + } + } + } + else + { + /* Invalid Databuffer */ + alSetError(AL_INVALID_NAME); + bFailed = AL_TRUE; + } + } + + /* If all the Databuffers were valid (and unmapped), then we can + * delete them */ + if(!bFailed) + { + for(i = 0;i < n;i++) + { + if(puiBuffers[i] && alIsDatabufferEXT(puiBuffers[i])) + { + ALdatabuffer **list = &device->Databuffers; + + ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(puiBuffers[i]); + while(*list && *list != ALBuf) + list = &(*list)->next; + + if(*list) + *list = (*list)->next; + + // Release the memory used to store audio data + free(ALBuf->data); + + // Release buffer structure + ALTHUNK_REMOVEENTRY(puiBuffers[i]); + memset(ALBuf, 0, sizeof(ALdatabuffer)); + device->DatabufferCount--; + free(ALBuf); + } + } + } + } + else + alSetError(AL_INVALID_VALUE); + + ProcessContext(Context); + + return; + +} + +/* +* alIsDatabufferEXT(ALuint uiBuffer) +* +* Checks if ulBuffer is a valid Databuffer Name +*/ +ALboolean ALAPIENTRY alIsDatabufferEXT(ALuint uiBuffer) +{ + ALCcontext *Context; + ALdatabuffer *ALBuf; + + Context = alcGetCurrentContext(); + if(!Context) return AL_FALSE; + SuspendContext(Context); + + /* Check through list of generated databuffers for uiBuffer */ + ALBuf = Context->Device->Databuffers; + while(ALBuf && ALBuf->databuffer != uiBuffer) + ALBuf = ALBuf->next; + + ProcessContext(Context); + + return ((ALBuf || !uiBuffer) ? AL_TRUE : AL_FALSE); +} + +/* +* alDatabufferDataEXT(ALuint buffer,ALvoid *data,ALsizei size,ALenum usage) +* +* Fill databuffer with data +*/ +ALvoid ALAPIENTRY alDatabufferDataEXT(ALuint buffer,const ALvoid *data,ALsizei size,ALenum usage) +{ + ALCcontext *Context; + ALdatabuffer *ALBuf; + ALvoid *temp; + + Context = alcGetCurrentContext(); + if(!Context) return; + SuspendContext(Context); + + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + ALBuf = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer); + if(ALBuf->state == UNMAPPED) + { + if(usage == AL_STREAM_WRITE_EXT || usage == AL_STREAM_READ_EXT || + usage == AL_STREAM_COPY_EXT || usage == AL_STATIC_WRITE_EXT || + usage == AL_STATIC_READ_EXT || usage == AL_STATIC_COPY_EXT || + usage == AL_DYNAMIC_WRITE_EXT || usage == AL_DYNAMIC_READ_EXT || + usage == AL_DYNAMIC_COPY_EXT) + { + /* (Re)allocate data */ + temp = realloc(ALBuf->data, size); + if(temp) + { + ALBuf->data = temp; + ALBuf->size = size; + ALBuf->usage = usage; + if(data) + memcpy(ALBuf->data, data, size); + } + else + alSetError(AL_OUT_OF_MEMORY); + } + else + alSetError(AL_INVALID_ENUM); + } + else + alSetError(AL_INVALID_OPERATION); + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(Context); +} + +ALvoid ALAPIENTRY alDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, const ALvoid *data) +{ + ALCcontext *pContext; + ALdatabuffer *pBuffer; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0) + { + pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer); + + if(length >= 0 && start+length <= pBuffer->size) + { + if(pBuffer->state == UNMAPPED) + memcpy(pBuffer->data+start, data, length); + else + alSetError(AL_INVALID_OPERATION); + } + else + alSetError(AL_INVALID_VALUE); + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + +ALvoid ALAPIENTRY alGetDatabufferSubDataEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALvoid *data) +{ + ALCcontext *pContext; + ALdatabuffer *pBuffer; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0) + { + pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer); + + if(length >= 0 && start+length <= pBuffer->size) + { + if(pBuffer->state == UNMAPPED) + memcpy(data, pBuffer->data+start, length); + else + alSetError(AL_INVALID_OPERATION); + } + else + alSetError(AL_INVALID_VALUE); + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + + +ALvoid ALAPIENTRY alDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat flValue) +{ + ALCcontext *pContext; + + (void)flValue; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + switch(eParam) + { + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + +ALvoid ALAPIENTRY alDatabufferfvEXT(ALuint buffer, ALenum eParam, const ALfloat* flValues) +{ + ALCcontext *pContext; + + (void)flValues; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + switch(eParam) + { + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + + +ALvoid ALAPIENTRY alDatabufferiEXT(ALuint buffer, ALenum eParam, ALint lValue) +{ + ALCcontext *pContext; + + (void)lValue; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + switch(eParam) + { + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + +ALvoid ALAPIENTRY alDatabufferivEXT(ALuint buffer, ALenum eParam, const ALint* plValues) +{ + ALCcontext *pContext; + + (void)plValues; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + switch(eParam) + { + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + + +ALvoid ALAPIENTRY alGetDatabufferfEXT(ALuint buffer, ALenum eParam, ALfloat *pflValue) +{ + ALCcontext *pContext; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(pflValue) + { + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + switch(eParam) + { + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + } + else + alSetError(AL_INVALID_VALUE); + + ProcessContext(pContext); +} + +ALvoid ALAPIENTRY alGetDatabufferfvEXT(ALuint buffer, ALenum eParam, ALfloat* pflValues) +{ + ALCcontext *pContext; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(pflValues) + { + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + switch(eParam) + { + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + } + else + alSetError(AL_INVALID_VALUE); + + ProcessContext(pContext); +} + +ALvoid ALAPIENTRY alGetDatabufferiEXT(ALuint buffer, ALenum eParam, ALint *plValue) +{ + ALCcontext *pContext; + ALdatabuffer *pBuffer; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(plValue) + { + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(buffer); + + switch(eParam) + { + case AL_SIZE: + *plValue = pBuffer->size; + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + } + else + alSetError(AL_INVALID_VALUE); + + ProcessContext(pContext); +} + +ALvoid ALAPIENTRY alGetDatabufferivEXT(ALuint buffer, ALenum eParam, ALint* plValues) +{ + ALCcontext *pContext; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(plValues) + { + if(alIsDatabufferEXT(buffer) && buffer != 0) + { + switch (eParam) + { + case AL_SIZE: + alGetBufferi(buffer, eParam, plValues); + break; + + default: + alSetError(AL_INVALID_ENUM); + break; + } + } + else + alSetError(AL_INVALID_NAME); + } + else + alSetError(AL_INVALID_VALUE); + + ProcessContext(pContext); +} + + +ALvoid ALAPIENTRY alSelectDatabufferEXT(ALenum target, ALuint uiBuffer) +{ + ALCcontext *pContext; + ALdatabuffer *pBuffer; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(uiBuffer)) + { + pBuffer = (ALdatabuffer*)(uiBuffer ? ALTHUNK_LOOKUPENTRY(uiBuffer) : NULL); + if(target == AL_SAMPLE_SOURCE_EXT) + pContext->SampleSource = pBuffer; + else if(target == AL_SAMPLE_SINK_EXT) + pContext->SampleSink = pBuffer; + else + alSetError(AL_INVALID_VALUE); + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + + +ALvoid* ALAPIENTRY alMapDatabufferEXT(ALuint uiBuffer, ALuint start, ALsizei length, ALenum access) +{ + ALCcontext *pContext; + ALdatabuffer *pBuffer; + ALvoid *ret = NULL; + + pContext = alcGetCurrentContext(); + if(!pContext) return NULL; + SuspendContext(pContext); + + if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0) + { + pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer); + + if(length >= 0 && start+length <= pBuffer->size) + { + if(access == AL_READ_ONLY_EXT || access == AL_WRITE_ONLY_EXT || + access == AL_READ_WRITE_EXT) + { + if(pBuffer->state == UNMAPPED) + { + ret = pBuffer->data + start; + pBuffer->state = MAPPED; + } + else + alSetError(AL_INVALID_OPERATION); + } + else + alSetError(AL_INVALID_ENUM); + } + else + alSetError(AL_INVALID_VALUE); + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); + + return ret; +} + +ALvoid ALAPIENTRY alUnmapDatabufferEXT(ALuint uiBuffer) +{ + ALCcontext *pContext; + ALdatabuffer *pBuffer; + + pContext = alcGetCurrentContext(); + if(!pContext) return; + SuspendContext(pContext); + + if(alIsDatabufferEXT(uiBuffer) && uiBuffer != 0) + { + pBuffer = (ALdatabuffer*)ALTHUNK_LOOKUPENTRY(uiBuffer); + + if(pBuffer->state == MAPPED) + pBuffer->state = UNMAPPED; + else + alSetError(AL_INVALID_OPERATION); + } + else + alSetError(AL_INVALID_NAME); + + ProcessContext(pContext); +} + + +/* +* ReleaseALDatabuffers() +* +* INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist +*/ +ALvoid ReleaseALDatabuffers(ALCdevice *device) +{ + ALdatabuffer *ALBuffer; + ALdatabuffer *ALBufferTemp; + + ALBuffer = device->Databuffers; + while(ALBuffer) + { + // Release sample data + free(ALBuffer->data); + + // Release Buffer structure + ALBufferTemp = ALBuffer; + ALBuffer = ALBuffer->next; + memset(ALBufferTemp, 0, sizeof(ALdatabuffer)); + free(ALBufferTemp); + } + device->Databuffers = NULL; + device->DatabufferCount = 0; +} |