diff options
author | Chris Robinson <[email protected]> | 2013-11-28 03:57:26 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2013-11-28 03:57:45 -0800 |
commit | 7794e5366747a402d386f5fd559d0e433ed7cffb (patch) | |
tree | 3905b66ebad51cb48a3ebdbaa405defc23961a2f /OpenAL32 | |
parent | bb0207d784ee2d5ebbdb6d7c26a4a626e62dbbed (diff) |
Be a bit safer with MIDI state changes
Diffstat (limited to 'OpenAL32')
-rw-r--r-- | OpenAL32/Include/alMidi.h | 6 | ||||
-rw-r--r-- | OpenAL32/alMidi.c | 54 |
2 files changed, 30 insertions, 30 deletions
diff --git a/OpenAL32/Include/alMidi.h b/OpenAL32/Include/alMidi.h index f2b29df0..d648e179 100644 --- a/OpenAL32/Include/alMidi.h +++ b/OpenAL32/Include/alMidi.h @@ -21,6 +21,12 @@ typedef struct MidiSynth { ALuint SampleRate; ALdouble SamplesPerTick; + /* NOTE: This rwlock is for the state and soundfont. The EventQueue and + * related must instead use the device lock as they're used in the mixer + * thread. + */ + RWLock Lock; + volatile ALenum State; const struct MidiSynthVtable *vtbl; diff --git a/OpenAL32/alMidi.c b/OpenAL32/alMidi.c index 0cbe11b2..3bc61aae 100644 --- a/OpenAL32/alMidi.c +++ b/OpenAL32/alMidi.c @@ -30,13 +30,15 @@ static void MidiSynth_Construct(MidiSynth *self, ALCdevice *device) { InitEvtQueue(&self->EventQueue); + RWLockInit(&self->Lock); + + self->State = AL_INITIAL; + self->LastEvtTime = 0; self->NextEvtTime = UINT64_MAX; self->SamplesSinceLast = 0.0; self->SamplesToNext = 0.0; - self->State = AL_INITIAL; - self->SampleRate = device->Frequency; self->SamplesPerTick = (ALdouble)self->SampleRate / TICKS_PER_SECOND; MidiSynth_updateSpeed(self); @@ -49,7 +51,9 @@ static void MidiSynth_Destruct(MidiSynth *self) static inline void MidiSynth_setState(MidiSynth *self, ALenum state) { + WriteLock(&self->Lock); ExchangeInt(&self->State, state); + WriteUnlock(&self->Lock); } ALuint64 MidiSynth_getTime(const MidiSynth *self) @@ -107,11 +111,6 @@ static ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event typedef struct FSynth { DERIVE_FROM_TYPE(MidiSynth); - /* NOTE: This rwlock is for setting the soundfont. The EventQueue and - * related must use the device lock as they're used in the mixer thread. - */ - RWLock Lock; - fluid_settings_t *Settings; fluid_synth_t *Synth; int FontID; @@ -133,8 +132,6 @@ static void FSynth_Construct(FSynth *self, ALCdevice *device) MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device); SET_VTABLE2(FSynth, MidiSynth, self); - RWLockInit(&self->Lock); - self->Settings = NULL; self->Synth = NULL; self->FontID = FLUID_FAILED; @@ -184,21 +181,11 @@ static ALboolean FSynth_init(FSynth *self, ALCdevice *device) static ALenum FSynth_loadSoundfont(FSynth *self, const char *filename) { - ALenum state; int fontid; - WriteLock(&self->Lock); - state = STATIC_CAST(MidiSynth, self)->State; - if(state == AL_PLAYING || state == AL_PAUSED) - { - WriteUnlock(&self->Lock); - return AL_INVALID_OPERATION; - } - fontid = fluid_synth_sfload(self->Synth, filename, 1); if(fontid == FLUID_FAILED) { - WriteUnlock(&self->Lock); ERR("Failed to load soundfont '%s'\n", filename); return AL_INVALID_VALUE; } @@ -206,14 +193,13 @@ static ALenum FSynth_loadSoundfont(FSynth *self, const char *filename) if(self->FontID != FLUID_FAILED) fluid_synth_sfunload(self->Synth, self->FontID, 1); self->FontID = fontid; - WriteUnlock(&self->Lock); return AL_NO_ERROR; } static void FSynth_setState(FSynth *self, ALenum state) { - WriteLock(&self->Lock); + WriteLock(&STATIC_CAST(MidiSynth, self)->Lock); if(state == AL_PLAYING) { if(self->FontID == FLUID_FAILED) @@ -229,8 +215,8 @@ static void FSynth_setState(FSynth *self, ALenum state) } } } - MidiSynth_setState(STATIC_CAST(MidiSynth, self), state); - WriteUnlock(&self->Lock); + ExchangeInt(&STATIC_CAST(MidiSynth, self)->State, state); + WriteUnlock(&STATIC_CAST(MidiSynth, self)->Lock); } static void FSynth_update(FSynth *self, ALCdevice *device) @@ -290,11 +276,12 @@ static void FSynth_processQueue(FSynth *self, ALuint64 time) static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]) { MidiSynth *synth = STATIC_CAST(MidiSynth, self); + ALenum state = synth->State; ALuint total = 0; - if(synth->State != AL_PLAYING) + if(state != AL_PLAYING) { - if(synth->State == AL_PAUSED) + if(state == AL_PAUSED) fluid_synth_write_float(self->Synth, SamplesToDo, DryBuffer[FrontLeft], 0, 1, DryBuffer[FrontRight], 0, 1); return; @@ -468,21 +455,28 @@ MidiSynth *SynthCreate(ALCdevice *device) AL_API void AL_APIENTRY alMidiSoundfontSOFT(const char *filename) { - ALCdevice *device; ALCcontext *context; ALenum err; context = GetContextRef(); if(!context) return; - device = context->Device; if(!(filename && filename[0])) alSetError(context, AL_INVALID_VALUE); else { - err = V(device->Synth,loadSoundfont)(filename); - if(err != AL_NO_ERROR) - alSetError(context, err); + ALCdevice *device = context->Device; + MidiSynth *synth = device->Synth; + WriteLock(&synth->Lock); + if(synth->State == AL_PLAYING || synth->State == AL_PAUSED) + alSetError(context, AL_INVALID_OPERATION); + else + { + err = V(synth,loadSoundfont)(filename); + if(err != AL_NO_ERROR) + alSetError(context, err); + } + WriteUnlock(&synth->Lock); } ALCcontext_DecRef(context); |