aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32/alMidi.c
diff options
context:
space:
mode:
Diffstat (limited to 'OpenAL32/alMidi.c')
-rw-r--r--OpenAL32/alMidi.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/OpenAL32/alMidi.c b/OpenAL32/alMidi.c
new file mode 100644
index 00000000..0679b64c
--- /dev/null
+++ b/OpenAL32/alMidi.c
@@ -0,0 +1,221 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "alMain.h"
+#include "alMidi.h"
+#include "alError.h"
+#include "alThunk.h"
+#include "evtqueue.h"
+#include "rwlock.h"
+#include "alu.h"
+
+#include "midi/base.h"
+
+
+MidiSynth *SynthCreate(ALCdevice *device)
+{
+ MidiSynth *synth = FSynth_create(device);
+ if(!synth) synth = DSynth_create(device);
+ return synth;
+}
+
+
+AL_API void AL_APIENTRY alMidiSoundfontSOFT(ALuint id)
+{
+ alMidiSoundfontvSOFT(1, &id);
+}
+
+AL_API void AL_APIENTRY alMidiSoundfontvSOFT(ALsizei count, const ALuint *ids)
+{
+ ALCdevice *device;
+ ALCcontext *context;
+ MidiSynth *synth;
+ ALenum err;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ if(count < 0)
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+ device = context->Device;
+ synth = device->Synth;
+
+ WriteLock(&synth->Lock);
+ if(synth->State == AL_PLAYING || synth->State == AL_PAUSED)
+ alSetError(context, AL_INVALID_OPERATION);
+ else
+ {
+ err = V(synth,selectSoundfonts)(context, count, ids);
+ if(err != AL_NO_ERROR)
+ alSetError(context, err);
+ }
+ WriteUnlock(&synth->Lock);
+
+done:
+ ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2)
+{
+ ALCdevice *device;
+ ALCcontext *context;
+ ALenum err;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ if(!(event == AL_NOTEOFF_SOFT || event == AL_NOTEON_SOFT ||
+ event == AL_KEYPRESSURE_SOFT || event == AL_CONTROLLERCHANGE_SOFT ||
+ event == AL_PROGRAMCHANGE_SOFT || event == AL_CHANNELPRESSURE_SOFT ||
+ event == AL_PITCHBEND_SOFT))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+ if(!(channel >= 0 && channel <= 15))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ if(!(param1 >= 0 && param1 <= 127))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ if(!(param2 >= 0 && param2 <= 127))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+ device = context->Device;
+ ALCdevice_Lock(device);
+ err = MidiSynth_insertEvent(device->Synth, time, event|channel, param1, param2);
+ ALCdevice_Unlock(device);
+ if(err != AL_NO_ERROR)
+ alSetError(context, err);
+
+done:
+ ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, ALsizei size)
+{
+ ALCdevice *device;
+ ALCcontext *context;
+ ALenum err;
+ ALsizei i;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ if(!data || size < 0)
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ for(i = 0;i < size;i++)
+ {
+ if((data[i]&0x80))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ }
+
+ device = context->Device;
+ ALCdevice_Lock(device);
+ err = MidiSynth_insertSysExEvent(device->Synth, time, data, size);
+ ALCdevice_Unlock(device);
+ if(err != AL_NO_ERROR)
+ alSetError(context, err);
+
+done:
+ ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alMidiPlaySOFT(void)
+{
+ ALCcontext *context;
+ MidiSynth *synth;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ synth = context->Device->Synth;
+ WriteLock(&synth->Lock);
+ V(synth,setState)(AL_PLAYING);
+ WriteUnlock(&synth->Lock);
+
+ ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alMidiPauseSOFT(void)
+{
+ ALCcontext *context;
+ MidiSynth *synth;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ synth = context->Device->Synth;
+ WriteLock(&synth->Lock);
+ V(synth,setState)(AL_PAUSED);
+ WriteUnlock(&synth->Lock);
+
+ ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alMidiStopSOFT(void)
+{
+ ALCdevice *device;
+ ALCcontext *context;
+ MidiSynth *synth;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ device = context->Device;
+ synth = device->Synth;
+
+ WriteLock(&synth->Lock);
+ V(synth,setState)(AL_STOPPED);
+
+ ALCdevice_Lock(device);
+ V0(synth,stop)();
+ ALCdevice_Unlock(device);
+ WriteUnlock(&synth->Lock);
+
+ ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alMidiResetSOFT(void)
+{
+ ALCdevice *device;
+ ALCcontext *context;
+ MidiSynth *synth;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ device = context->Device;
+ synth = device->Synth;
+
+ WriteLock(&synth->Lock);
+ V(synth,setState)(AL_INITIAL);
+
+ ALCdevice_Lock(device);
+ V0(synth,reset)();
+ ALCdevice_Unlock(device);
+ WriteUnlock(&synth->Lock);
+
+ ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alMidiGainSOFT(ALfloat value)
+{
+ ALCdevice *device;
+ ALCcontext *context;
+
+ context = GetContextRef();
+ if(!context) return;
+
+ if(!(value >= 0.0f && isfinite(value)))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+ device = context->Device;
+ V(device->Synth,setGain)(value);
+
+done:
+ ALCcontext_DecRef(context);
+}