AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value) { ALCdevice *device; ALCcontext *context; ALbuffer *albuf; context = GetContextRef(); if(!context) return; device = context->Device; if((albuf=LookupBuffer(device, buffer)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); switch(param) { case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: if(!(value >= 0)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); ExchangeInt(&albuf->UnpackAlign, value); break; case AL_PACK_BLOCK_ALIGNMENT_SOFT: if(!(value >= 0)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); ExchangeInt(&albuf->PackAlign, value); break; default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } done: ALCcontext_DecRef(context); }
AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void) { ALCcontext *Context; Context = GetContextRef(); if(!Context) return; if(ExchangeInt(&Context->DeferUpdates, AL_FALSE)) { ALsizei pos; LockContext(Context); LockUIntMapRead(&Context->SourceMap); for(pos = 0;pos < Context->SourceMap.size;pos++) { ALsource *Source = Context->SourceMap.array[pos].value; ALenum new_state; if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && Source->Offset >= 0.0) ApplyOffset(Source); new_state = ExchangeInt(&Source->new_state, AL_NONE); if(new_state) SetSourceState(Source, Context, new_state); } UnlockUIntMapRead(&Context->SourceMap); UnlockContext(Context); } ALCcontext_DecRef(Context); }
AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void) { ALCcontext *Context; Context = GetContextRef(); if(!Context) return; if(!Context->DeferUpdates) { ALboolean UpdateSources; ALsource **src, **src_end; ALeffectslot **slot, **slot_end; FPUCtl oldMode; SetMixerFPUMode(&oldMode); LockContext(Context); Context->DeferUpdates = AL_TRUE; /* Make sure all pending updates are performed */ UpdateSources = ExchangeInt(&Context->UpdateSources, AL_FALSE); src = Context->ActiveSources; src_end = src + Context->ActiveSourceCount; while(src != src_end) { if((*src)->state != AL_PLAYING) { Context->ActiveSourceCount--; *src = *(--src_end); continue; } if(ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) || UpdateSources) ALsource_Update(*src, Context); src++; } slot = Context->ActiveEffectSlots; slot_end = slot + Context->ActiveEffectSlotCount; while(slot != slot_end) { if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE)) VCALL((*slot)->EffectState,update,(Context->Device, *slot)); slot++; } UnlockContext(Context); RestoreFPUMode(&oldMode); } ALCcontext_DecRef(Context); }
void FreeThunkEntry(ALuint index) { ReadLock(&ThunkLock); if(index > 0 && index <= ThunkArraySize) ExchangeInt(&ThunkArray[index-1], AL_FALSE); ReadUnlock(&ThunkLock); }
ALenum NewThunkEntry(ALuint *index) { ALenum *NewList; ALuint i; ReadLock(&ThunkLock); for(i = 0;i < ThunkArraySize;i++) { if(ExchangeInt(&ThunkArray[i], AL_TRUE) == AL_FALSE) { ReadUnlock(&ThunkLock); *index = i+1; return AL_NO_ERROR; } } ReadUnlock(&ThunkLock); WriteLock(&ThunkLock); NewList = realloc(ThunkArray, ThunkArraySize*2 * sizeof(*ThunkArray)); if(!NewList) { WriteUnlock(&ThunkLock); ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2); return AL_OUT_OF_MEMORY; } memset(&NewList[ThunkArraySize], 0, ThunkArraySize*sizeof(*ThunkArray)); ThunkArraySize *= 2; ThunkArray = NewList; ThunkArray[i] = AL_TRUE; WriteUnlock(&ThunkLock); *index = i+1; return AL_NO_ERROR; }
ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids) { ALCdevice *device = context->Device; ALsoundfont **sfonts; ALsizei i; if(self->State != AL_INITIAL && self->State != AL_STOPPED) return AL_INVALID_OPERATION; sfonts = calloc(1, count * sizeof(sfonts[0])); if(!sfonts) return AL_OUT_OF_MEMORY; for(i = 0;i < count;i++) { if(ids[i] == 0) sfonts[i] = ALsoundfont_getDefSoundfont(context); else if(!(sfonts[i]=LookupSfont(device, ids[i]))) { free(sfonts); return AL_INVALID_VALUE; } } for(i = 0;i < count;i++) IncrementRef(&sfonts[i]->ref); sfonts = ExchangePtr((XchgPtr*)&self->Soundfonts, sfonts); count = ExchangeInt(&self->NumSoundfonts, count); for(i = 0;i < count;i++) DecrementRef(&sfonts[i]->ref); free(sfonts); return AL_NO_ERROR; }
AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const ALuint *fsids) { ALCdevice *device; ALCcontext *context; ALsfpreset *preset; ALfontsound **sounds; ALsizei i; context = GetContextRef(); if(!context) return; device = context->Device; if(!(preset=LookupPreset(device, id))) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); if(count < 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); if(ReadRef(&preset->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); if(count == 0) sounds = NULL; else { sounds = calloc(count, sizeof(sounds[0])); if(!sounds) SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); for(i = 0;i < count;i++) { if(!(sounds[i]=LookupFontsound(device, fsids[i]))) { free(sounds); SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); } } } for(i = 0;i < count;i++) IncrementRef(&sounds[i]->ref); sounds = ExchangePtr((XchgPtr*)&preset->Sounds, sounds); count = ExchangeInt(&preset->NumSounds, count); for(i = 0;i < count;i++) DecrementRef(&sounds[i]->ref); free(sounds); done: ALCcontext_DecRef(context); }
AL_API ALenum AL_APIENTRY alGetError(void) { ALCcontext *Context; ALenum errorCode; Context = GetContextRef(); if(!Context) return AL_INVALID_OPERATION; errorCode = ExchangeInt(&Context->LastError, AL_NO_ERROR); ALCcontext_DecRef(Context); return errorCode; }
void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device) { ALsfpreset **presets; ALsizei num_presets; VECTOR(ALbuffer*) buffers; ALsizei i; VECTOR_INIT(buffers); presets = ExchangePtr((XchgPtr*)&self->Presets, NULL); num_presets = ExchangeInt(&self->NumPresets, 0); for(i = 0;i < num_presets;i++) { ALsfpreset *preset = presets[i]; ALfontsound **sounds; ALsizei num_sounds; ALboolean deleting; ALsizei j; sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL); num_sounds = ExchangeInt(&preset->NumSounds, 0); DeletePreset(device, preset); preset = NULL; for(j = 0;j < num_sounds;j++) DecrementRef(&sounds[j]->ref); /* Some fontsounds may not be immediately deletable because they're * linked to another fontsound. When those fontsounds are deleted * they should become deletable, so use a loop until all fontsounds * are deleted. */ do { deleting = AL_FALSE; for(j = 0;j < num_sounds;j++) { if(sounds[j] && ReadRef(&sounds[j]->ref) == 0) { ALbuffer *buffer; deleting = AL_TRUE; if((buffer=ATOMIC_LOAD(&sounds[j]->Buffer)) != NULL) { ALbuffer **iter; #define MATCH_BUFFER(_i) (buffer == *(_i)) VECTOR_FIND_IF(iter, ALbuffer*, buffers, MATCH_BUFFER); if(iter == VECTOR_ITER_END(buffers)) VECTOR_PUSH_BACK(buffers, buffer); #undef MATCH_BUFFER } DeleteFontsound(device, sounds[j]); sounds[j] = NULL; } } } while(deleting); free(sounds); } ALsoundfont_Destruct(self); free(self); #define DELETE_BUFFER(iter) do { \ assert(ReadRef(&(*(iter))->ref) == 0); \ DeleteBuffer(device, *(iter)); \ } while(0) VECTOR_FOR_EACH(ALbuffer*, buffers, DELETE_BUFFER); #undef DELETE_BUFFER VECTOR_DEINIT(buffers); }
AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids) { ALCdevice *device; ALCcontext *context; ALsoundfont *sfont; ALsfpreset **presets; ALsizei i; context = GetContextRef(); if(!context) return; device = context->Device; if(id == 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); if(!(sfont=LookupSfont(device, id))) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); if(count < 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); WriteLock(&sfont->Lock); if(ReadRef(&sfont->ref) != 0) { WriteUnlock(&sfont->Lock); SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); } if(count == 0) presets = NULL; else { presets = calloc(count, sizeof(presets[0])); if(!presets) { WriteUnlock(&sfont->Lock); SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); } for(i = 0;i < count;i++) { if(!(presets[i]=LookupPreset(device, pids[i]))) { free(presets); WriteUnlock(&sfont->Lock); SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); } } } for(i = 0;i < count;i++) IncrementRef(&presets[i]->ref); presets = ExchangePtr((XchgPtr*)&sfont->Presets, presets); count = ExchangeInt(&sfont->NumPresets, count); WriteUnlock(&sfont->Lock); for(i = 0;i < count;i++) DecrementRef(&presets[i]->ref); free(presets); done: ALCcontext_DecRef(context); }
static inline void MidiSynth_setState(MidiSynth *self, ALenum state) { ExchangeInt(&self->State, state); }
static void Unlock(volatile ALenum *l) { ExchangeInt(l, AL_FALSE); }
static void Lock(volatile ALenum *l) { while(ExchangeInt(l, AL_TRUE) == AL_TRUE) sched_yield(); }
static void Lock(volatile ALenum *l) { while(ExchangeInt(l, AL_TRUE) == AL_TRUE) Sleep(0); }