Start using a simpler method for error handling

This helps avoid the al_try/al_throwerr/al_endtry stuff.
This commit is contained in:
Chris Robinson
2013-10-06 18:01:01 -07:00
parent 79edd2cf3b
commit 5d014ba85f
2 changed files with 335 additions and 327 deletions
+15
View File
@@ -869,6 +869,21 @@ enum {
void FillCPUCaps(ALuint capfilter);
#define SET_ERROR_AND_RETURN(ctx, err) do { \
alSetError((ctx), (err)); \
return; \
} while(0)
#define SET_ERROR_AND_RETURN_VAL(ctx, err, val) do { \
alSetError((ctx), (err)); \
return (val); \
} while(0)
#define SET_ERROR_AND_GOTO(ctx, err, lbl) do { \
alSetError((ctx), (err)); \
goto lbl; \
} while(0)
/**
* Starts a try block. Must not be nested within another try block within the
* same function.
+320 -327
View File
@@ -182,286 +182,285 @@ static const char aLawCompressTable[128] = {
AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
{
ALCcontext *Context;
ALsizei cur = 0;
ALCdevice *device;
ALCcontext *context;
ALsizei cur = 0;
ALenum err;
Context = GetContextRef();
if(!Context) return;
context = GetContextRef();
if(!context) return;
al_try
if(!(n >= 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
device = context->Device;
for(cur = 0;cur < n;cur++)
{
ALCdevice *device = Context->Device;
ALenum err;
CHECK_VALUE(Context, n >= 0);
for(cur = 0;cur < n;cur++)
ALbuffer *buffer = calloc(1, sizeof(ALbuffer));
if(!buffer)
{
ALbuffer *buffer = calloc(1, sizeof(ALbuffer));
if(!buffer)
{
alDeleteBuffers(cur, buffers);
al_throwerr(Context, AL_OUT_OF_MEMORY);
}
RWLockInit(&buffer->lock);
err = NewThunkEntry(&buffer->id);
if(err == AL_NO_ERROR)
err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
if(err != AL_NO_ERROR)
{
FreeThunkEntry(buffer->id);
memset(buffer, 0, sizeof(ALbuffer));
free(buffer);
alDeleteBuffers(cur, buffers);
al_throwerr(Context, err);
}
buffers[cur] = buffer->id;
alDeleteBuffers(cur, buffers);
SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
}
}
al_endtry;
RWLockInit(&buffer->lock);
ALCcontext_DecRef(Context);
err = NewThunkEntry(&buffer->id);
if(err == AL_NO_ERROR)
err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
if(err != AL_NO_ERROR)
{
FreeThunkEntry(buffer->id);
memset(buffer, 0, sizeof(ALbuffer));
free(buffer);
alDeleteBuffers(cur, buffers);
SET_ERROR_AND_GOTO(context, err, done);
}
buffers[cur] = buffer->id;
}
done:
ALCcontext_DecRef(context);
}
AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
{
ALCcontext *Context;
ALCdevice *device;
ALCcontext *context;
ALbuffer *ALBuf;
ALsizei i;
Context = GetContextRef();
if(!Context) return;
context = GetContextRef();
if(!context) return;
al_try
if(!(n >= 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
device = context->Device;
for(i = 0;i < n;i++)
{
ALCdevice *device = Context->Device;
if(!buffers[i])
continue;
CHECK_VALUE(Context, n >= 0);
for(i = 0;i < n;i++)
{
if(!buffers[i])
continue;
/* Check for valid Buffer ID */
if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
if(ALBuf->ref != 0)
al_throwerr(Context, AL_INVALID_OPERATION);
}
for(i = 0;i < n;i++)
{
if((ALBuf=RemoveBuffer(device, buffers[i])) == NULL)
continue;
FreeThunkEntry(ALBuf->id);
free(ALBuf->data);
memset(ALBuf, 0, sizeof(*ALBuf));
free(ALBuf);
}
/* Check for valid Buffer ID */
if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
if(ALBuf->ref != 0)
SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
}
al_endtry;
ALCcontext_DecRef(Context);
for(i = 0;i < n;i++)
{
if((ALBuf=RemoveBuffer(device, buffers[i])) == NULL)
continue;
FreeThunkEntry(ALBuf->id);
free(ALBuf->data);
memset(ALBuf, 0, sizeof(*ALBuf));
free(ALBuf);
}
done:
ALCcontext_DecRef(context);
}
AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
{
ALCcontext *Context;
ALboolean result;
ALCcontext *context;
ALboolean ret;
Context = GetContextRef();
if(!Context) return AL_FALSE;
context = GetContextRef();
if(!context) return AL_FALSE;
result = ((!buffer || LookupBuffer(Context->Device, buffer)) ?
AL_TRUE : AL_FALSE);
ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
AL_TRUE : AL_FALSE);
ALCcontext_DecRef(Context);
ALCcontext_DecRef(context);
return result;
return ret;
}
AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
{
enum UserFmtChannels SrcChannels;
enum UserFmtType SrcType;
ALCcontext *Context;
ALuint FrameSize;
ALenum NewFormat;
ALbuffer *ALBuf;
enum UserFmtChannels srcchannels;
enum UserFmtType srctype;
ALCdevice *device;
ALCcontext *context;
ALuint framesize;
ALenum newformat;
ALbuffer *albuf;
ALenum err;
Context = GetContextRef();
if(!Context) return;
context = GetContextRef();
if(!context) return;
al_try
device = context->Device;
if((albuf=LookupBuffer(device, buffer)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
if(!(size >= 0 && freq > 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
switch(srctype)
{
ALCdevice *device = Context->Device;
if((ALBuf=LookupBuffer(device, buffer)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
CHECK_VALUE(Context, size >= 0 && freq >= 0);
if(DecomposeUserFormat(format, &SrcChannels, &SrcType) == AL_FALSE)
al_throwerr(Context, AL_INVALID_ENUM);
switch(SrcType)
{
case UserFmtByte:
case UserFmtUByte:
case UserFmtShort:
case UserFmtUShort:
case UserFmtFloat:
FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
CHECK_VALUE(Context, (size%FrameSize) == 0);
case UserFmtByte:
case UserFmtUByte:
case UserFmtShort:
case UserFmtUShort:
case UserFmtFloat:
framesize = FrameSizeFromUserFmt(srcchannels, srctype);
if(!((size%framesize) == 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
err = LoadData(ALBuf, freq, format, size/FrameSize,
SrcChannels, SrcType, data, AL_TRUE);
if(err != AL_NO_ERROR)
al_throwerr(Context, err);
break;
err = LoadData(albuf, freq, format, size/framesize,
srcchannels, srctype, data, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
case UserFmtInt:
case UserFmtUInt:
case UserFmtByte3:
case UserFmtUByte3:
case UserFmtDouble:
FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
CHECK_VALUE(Context, (size%FrameSize) == 0);
case UserFmtInt:
case UserFmtUInt:
case UserFmtByte3:
case UserFmtUByte3:
case UserFmtDouble:
framesize = FrameSizeFromUserFmt(srcchannels, srctype);
if(!((size%framesize) == 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
NewFormat = AL_FORMAT_MONO_FLOAT32;
switch(SrcChannels)
{
case UserFmtMono: NewFormat = AL_FORMAT_MONO_FLOAT32; break;
case UserFmtStereo: NewFormat = AL_FORMAT_STEREO_FLOAT32; break;
case UserFmtRear: NewFormat = AL_FORMAT_REAR32; break;
case UserFmtQuad: NewFormat = AL_FORMAT_QUAD32; break;
case UserFmtX51: NewFormat = AL_FORMAT_51CHN32; break;
case UserFmtX61: NewFormat = AL_FORMAT_61CHN32; break;
case UserFmtX71: NewFormat = AL_FORMAT_71CHN32; break;
}
err = LoadData(ALBuf, freq, NewFormat, size/FrameSize,
SrcChannels, SrcType, data, AL_TRUE);
if(err != AL_NO_ERROR)
al_throwerr(Context, err);
break;
newformat = AL_FORMAT_MONO_FLOAT32;
switch(srcchannels)
{
case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break;
case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break;
case UserFmtRear: newformat = AL_FORMAT_REAR32; break;
case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break;
case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
}
err = LoadData(albuf, freq, newformat, size/framesize,
srcchannels, srctype, data, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
case UserFmtMulaw:
case UserFmtAlaw:
FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType);
CHECK_VALUE(Context, (size%FrameSize) == 0);
case UserFmtMulaw:
case UserFmtAlaw:
framesize = FrameSizeFromUserFmt(srcchannels, srctype);
if(!((size%framesize) == 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
NewFormat = AL_FORMAT_MONO16;
switch(SrcChannels)
{
case UserFmtMono: NewFormat = AL_FORMAT_MONO16; break;
case UserFmtStereo: NewFormat = AL_FORMAT_STEREO16; break;
case UserFmtRear: NewFormat = AL_FORMAT_REAR16; break;
case UserFmtQuad: NewFormat = AL_FORMAT_QUAD16; break;
case UserFmtX51: NewFormat = AL_FORMAT_51CHN16; break;
case UserFmtX61: NewFormat = AL_FORMAT_61CHN16; break;
case UserFmtX71: NewFormat = AL_FORMAT_71CHN16; break;
}
err = LoadData(ALBuf, freq, NewFormat, size/FrameSize,
SrcChannels, SrcType, data, AL_TRUE);
if(err != AL_NO_ERROR)
al_throwerr(Context, err);
break;
newformat = AL_FORMAT_MONO16;
switch(srcchannels)
{
case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
}
err = LoadData(albuf, freq, newformat, size/framesize,
srcchannels, srctype, data, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
case UserFmtIMA4:
/* Here is where things vary:
* nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
* Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
*/
FrameSize = ChannelsFromUserFmt(SrcChannels) * 36;
CHECK_VALUE(Context, (size%FrameSize) == 0);
case UserFmtIMA4:
/* Here is where things vary:
* nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
* Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
*/
framesize = ChannelsFromUserFmt(srcchannels) * 36;
if(!((size%framesize) == 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
NewFormat = AL_FORMAT_MONO16;
switch(SrcChannels)
{
case UserFmtMono: NewFormat = AL_FORMAT_MONO16; break;
case UserFmtStereo: NewFormat = AL_FORMAT_STEREO16; break;
case UserFmtRear: NewFormat = AL_FORMAT_REAR16; break;
case UserFmtQuad: NewFormat = AL_FORMAT_QUAD16; break;
case UserFmtX51: NewFormat = AL_FORMAT_51CHN16; break;
case UserFmtX61: NewFormat = AL_FORMAT_61CHN16; break;
case UserFmtX71: NewFormat = AL_FORMAT_71CHN16; break;
}
err = LoadData(ALBuf, freq, NewFormat, size/FrameSize*65,
SrcChannels, SrcType, data, AL_TRUE);
if(err != AL_NO_ERROR)
al_throwerr(Context, err);
break;
}
newformat = AL_FORMAT_MONO16;
switch(srcchannels)
{
case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
}
err = LoadData(albuf, freq, newformat, size/framesize*65,
srcchannels, srctype, data, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
}
al_endtry;
ALCcontext_DecRef(Context);
done:
ALCcontext_DecRef(context);
}
AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
{
enum UserFmtChannels SrcChannels;
enum UserFmtType SrcType;
ALCcontext *Context;
ALbuffer *ALBuf;
enum UserFmtChannels srcchannels;
enum UserFmtType srctype;
ALCdevice *device;
ALCcontext *context;
ALbuffer *albuf;
ALuint original_align;
ALuint channels;
ALuint bytes;
Context = GetContextRef();
if(!Context) return;
context = GetContextRef();
if(!context) return;
al_try
device = context->Device;
if((albuf=LookupBuffer(device, buffer)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
if(!(length >= 0 && offset >= 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
WriteLock(&albuf->lock);
original_align = ((albuf->OriginalType == UserFmtIMA4) ?
(ChannelsFromUserFmt(albuf->OriginalChannels)*36) :
FrameSizeFromUserFmt(albuf->OriginalChannels,
albuf->OriginalType));
if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
{
ALCdevice *device = Context->Device;
ALuint original_align;
ALuint Channels;
ALuint Bytes;
if((ALBuf=LookupBuffer(device, buffer)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
CHECK_VALUE(Context, length >= 0 && offset >= 0);
if(DecomposeUserFormat(format, &SrcChannels, &SrcType) == AL_FALSE)
al_throwerr(Context, AL_INVALID_ENUM);
WriteLock(&ALBuf->lock);
original_align = ((ALBuf->OriginalType == UserFmtIMA4) ?
(ChannelsFromUserFmt(ALBuf->OriginalChannels)*36) :
FrameSizeFromUserFmt(ALBuf->OriginalChannels,
ALBuf->OriginalType));
if(SrcChannels != ALBuf->OriginalChannels || SrcType != ALBuf->OriginalType)
{
WriteUnlock(&ALBuf->lock);
al_throwerr(Context, AL_INVALID_ENUM);
}
if(offset > ALBuf->OriginalSize || length > ALBuf->OriginalSize-offset ||
(offset%original_align) != 0 || (length%original_align) != 0)
{
WriteUnlock(&ALBuf->lock);
al_throwerr(Context, AL_INVALID_VALUE);
}
Channels = ChannelsFromFmt(ALBuf->FmtChannels);
Bytes = BytesFromFmt(ALBuf->FmtType);
/* offset -> byte offset, length -> sample count */
if(SrcType == UserFmtIMA4)
{
offset = offset/36*65 * Bytes;
length = length/original_align * 65;
}
else
{
ALuint OldBytes = BytesFromUserFmt(SrcType);
offset = offset/OldBytes * Bytes;
length = length/OldBytes/Channels;
}
ConvertData((char*)ALBuf->data+offset, (enum UserFmtType)ALBuf->FmtType,
data, SrcType, Channels, length);
WriteUnlock(&ALBuf->lock);
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
(offset%original_align) != 0 || (length%original_align) != 0)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
al_endtry;
ALCcontext_DecRef(Context);
channels = ChannelsFromFmt(albuf->FmtChannels);
bytes = BytesFromFmt(albuf->FmtType);
/* offset -> byte offset, length -> sample count */
if(srctype == UserFmtIMA4)
{
offset = offset/36*65 * bytes;
length = length/original_align * 65;
}
else
{
ALuint OldBytes = BytesFromUserFmt(srctype);
offset = offset/OldBytes * bytes;
length = length/OldBytes/channels;
}
ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
data, srctype, channels, length);
WriteUnlock(&albuf->lock);
done:
ALCcontext_DecRef(context);
}
@@ -469,141 +468,135 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
ALuint samplerate, ALenum internalformat, ALsizei samples,
ALenum channels, ALenum type, const ALvoid *data)
{
ALCcontext *Context;
ALbuffer *ALBuf;
ALCdevice *device;
ALCcontext *context;
ALbuffer *albuf;
ALenum err;
Context = GetContextRef();
if(!Context) return;
context = GetContextRef();
if(!context) return;
al_try
{
ALCdevice *device = Context->Device;
if((ALBuf=LookupBuffer(device, buffer)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
CHECK_VALUE(Context, samples >= 0 && samplerate != 0);
if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
al_throwerr(Context, AL_INVALID_ENUM);
device = context->Device;
if((albuf=LookupBuffer(device, buffer)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
if(!(samples >= 0 && samplerate != 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
err = LoadData(ALBuf, samplerate, internalformat, samples,
channels, type, data, AL_FALSE);
if(err != AL_NO_ERROR)
al_throwerr(Context, err);
}
al_endtry;
err = LoadData(albuf, samplerate, internalformat, samples,
channels, type, data, AL_FALSE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
ALCcontext_DecRef(Context);
done:
ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
ALsizei offset, ALsizei samples,
ALenum channels, ALenum type, const ALvoid *data)
{
ALCcontext *Context;
ALbuffer *ALBuf;
ALCdevice *device;
ALCcontext *context;
ALuint framesize;
ALbuffer *albuf;
Context = GetContextRef();
if(!Context) return;
context = GetContextRef();
if(!context) return;
al_try
device = context->Device;
if((albuf=LookupBuffer(device, buffer)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
if(!(samples >= 0 && offset >= 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if(IsValidType(type) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
WriteLock(&albuf->lock);
framesize = FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
if(channels != (ALenum)albuf->FmtChannels)
{
ALCdevice *device = Context->Device;
ALuint FrameSize;
if((ALBuf=LookupBuffer(device, buffer)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
CHECK_VALUE(Context, samples >= 0 && offset >= 0);
if(IsValidType(type) == AL_FALSE)
al_throwerr(Context, AL_INVALID_ENUM);
WriteLock(&ALBuf->lock);
FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType);
if(channels != (ALenum)ALBuf->FmtChannels)
{
WriteUnlock(&ALBuf->lock);
al_throwerr(Context, AL_INVALID_ENUM);
}
else if(offset > ALBuf->SampleLen || samples > ALBuf->SampleLen-offset)
{
WriteUnlock(&ALBuf->lock);
al_throwerr(Context,AL_INVALID_VALUE);
}
/* offset -> byte offset */
offset *= FrameSize;
ConvertData((char*)ALBuf->data+offset, (enum UserFmtType)ALBuf->FmtType,
data, type, ChannelsFromFmt(ALBuf->FmtChannels), samples);
WriteUnlock(&ALBuf->lock);
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
else if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
al_endtry;
ALCcontext_DecRef(Context);
/* offset -> byte offset */
offset *= framesize;
ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
data, type, ChannelsFromFmt(albuf->FmtChannels), samples);
WriteUnlock(&albuf->lock);
done:
ALCcontext_DecRef(context);
}
AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
ALsizei offset, ALsizei samples,
ALenum channels, ALenum type, ALvoid *data)
{
ALCcontext *Context;
ALbuffer *ALBuf;
ALCdevice *device;
ALCcontext *context;
ALuint framesize;
ALbuffer *albuf;
Context = GetContextRef();
if(!Context) return;
context = GetContextRef();
if(!context) return;
al_try
device = context->Device;
if((albuf=LookupBuffer(device, buffer)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
if(!(samples >= 0 && offset >= 0))
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if(IsValidType(type) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
ReadLock(&albuf->lock);
framesize = FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
if(channels != (ALenum)albuf->FmtChannels)
{
ALCdevice *device = Context->Device;
ALuint FrameSize;
if((ALBuf=LookupBuffer(device, buffer)) == NULL)
al_throwerr(Context, AL_INVALID_NAME);
CHECK_VALUE(Context, samples >= 0 && offset >= 0);
if(IsValidType(type) == AL_FALSE)
al_throwerr(Context, AL_INVALID_ENUM);
ReadLock(&ALBuf->lock);
FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType);
if(channels != (ALenum)ALBuf->FmtChannels)
{
ReadUnlock(&ALBuf->lock);
al_throwerr(Context, AL_INVALID_ENUM);
}
if(offset > ALBuf->SampleLen || samples > ALBuf->SampleLen-offset)
{
ReadUnlock(&ALBuf->lock);
al_throwerr(Context,AL_INVALID_VALUE);
}
if(type == UserFmtIMA4 && (samples%65) != 0)
{
ReadUnlock(&ALBuf->lock);
al_throwerr(Context, AL_INVALID_VALUE);
}
/* offset -> byte offset */
offset *= FrameSize;
ConvertData(data, type,
(char*)ALBuf->data+offset, (enum UserFmtType)ALBuf->FmtType,
ChannelsFromFmt(ALBuf->FmtChannels), samples);
ReadUnlock(&ALBuf->lock);
ReadUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
{
ReadUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
if(type == UserFmtIMA4 && (samples%65) != 0)
{
ReadUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
al_endtry;
ALCcontext_DecRef(Context);
/* offset -> byte offset */
offset *= framesize;
ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
ChannelsFromFmt(albuf->FmtChannels), samples);
ReadUnlock(&albuf->lock);
done:
ALCcontext_DecRef(context);
}
AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format)
{
enum FmtChannels DstChannels;
enum FmtType DstType;
ALCcontext *Context;
enum FmtChannels dstchannels;
enum FmtType dsttype;
ALCcontext *context;
ALboolean ret;
Context = GetContextRef();
if(!Context) return AL_FALSE;
context = GetContextRef();
if(!context) return AL_FALSE;
ret = DecomposeFormat(format, &DstChannels, &DstType);
ret = DecomposeFormat(format, &dstchannels, &dsttype);
ALCcontext_DecRef(Context);
ALCcontext_DecRef(context);
return ret;
}