From 069225be1515db97ad446c9fb7fa7b79a1720ded Mon Sep 17 00:00:00 2001 From: Elias Aebi Date: Thu, 12 Sep 2024 15:08:29 +0200 Subject: [PATCH] MIDI --- gral.h | 14 ++++++++++++ gral_linux.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ gral_macos.m | 14 ++++++++++++ gral_windows.cpp | 14 ++++++++++++ 4 files changed, 99 insertions(+) diff --git a/gral.h b/gral.h index 3739290..b5c098d 100644 --- a/gral.h +++ b/gral.h @@ -98,6 +98,11 @@ struct gral_window_interface { struct gral_timer; struct gral_file; struct gral_directory_watcher; +struct gral_midi; +struct gral_midi_interface { + void (*note_on)(unsigned char note, unsigned char velocity, void *user_data); + void (*note_off)(unsigned char note, void *user_data); +}; /*================ @@ -207,6 +212,15 @@ double gral_time_get_monotonic(void); void gral_audio_play(int (*callback)(float *buffer, int frames, void *user_data), void *user_data); + +/*========= + MIDI + =========*/ + +struct gral_midi *gral_midi_create(struct gral_application *application, char const *name, struct gral_midi_interface const *interface, void *user_data); +void gral_midi_delete(struct gral_midi *midi); + + #ifdef __cplusplus } #endif diff --git a/gral_linux.c b/gral_linux.c index 1668b0b..689e23a 100644 --- a/gral_linux.c +++ b/gral_linux.c @@ -860,3 +860,60 @@ void gral_audio_play(int (*callback)(float *buffer, int frames, void *user_data) snd_pcm_drain(pcm); snd_pcm_close(pcm); } + + +/*========= + MIDI + =========*/ + +struct gral_midi { + struct gral_midi_interface interface; + void *user_data; + snd_seq_t *seq; + int port; + guint source_id; +}; + +static void connect_midi() { + +} + +static gboolean midi_callback(gint fd, GIOCondition condition, gpointer user_data) { + struct gral_midi *midi = user_data; + snd_seq_event_t *event; + while (snd_seq_event_input(midi->seq, &event) > 0) { + switch (event->type) { + case SND_SEQ_EVENT_NOTEON: + midi->interface.note_on(event->data.note.note, event->data.note.velocity, midi->user_data); + break; + case SND_SEQ_EVENT_NOTEOFF: + midi->interface.note_off(event->data.note.note, midi->user_data); + break; + case SND_SEQ_EVENT_CONTROLLER: + break; + default: + break; + } + } + return G_SOURCE_CONTINUE; +} + +struct gral_midi *gral_midi_create(struct gral_application *application, char const *name, struct gral_midi_interface const *interface, void *user_data) { + struct gral_midi *midi = malloc(sizeof(struct gral_midi)); + midi->interface = *interface; + midi->user_data = user_data; + snd_seq_open(&midi->seq, "default", SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK); + snd_seq_set_client_name(midi->seq, name); + int client_id = snd_seq_client_id(midi->seq); + midi->port = snd_seq_create_simple_port(midi->seq, name, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_MIDI_GENERIC); + struct pollfd pfd; + snd_seq_poll_descriptors(midi->seq, &pfd, 1, POLLIN); + midi->source_id = g_unix_fd_add(pfd.fd, pfd.events, &midi_callback, midi); + return midi; +} + +void gral_midi_delete(struct gral_midi *midi) { + g_source_remove(midi->source_id); + snd_seq_close(midi->seq); + free(midi); +} diff --git a/gral_macos.m b/gral_macos.m index ce6a33f..c28ec7c 100644 --- a/gral_macos.m +++ b/gral_macos.m @@ -921,3 +921,17 @@ void gral_audio_play(int (*callback)(float *buffer, int frames, void *user_data) CFRunLoopRun(); AudioQueueDispose(queue, NO); } + + +/*========= + MIDI + =========*/ + +struct gral_midi *gral_midi_create(struct gral_application *application, char const *name, struct gral_midi_interface const *interface, void *user_data) { + // TODO + return NULL; +} + +void gral_midi_delete(struct gral_midi *midi) { + // TODO +} diff --git a/gral_windows.cpp b/gral_windows.cpp index 6c2125b..3ffeca3 100644 --- a/gral_windows.cpp +++ b/gral_windows.cpp @@ -1390,3 +1390,17 @@ void gral_audio_play(int (*callback)(float *buffer, int frames, void *user_data) render_client->Release(); CoTaskMemFree(format); } + + +/*========= + MIDI + =========*/ + +gral_midi *gral_midi_create(gral_application *application, char const *name, gral_midi_interface const *interface, void *user_data) { + // TODO + return NULL; +} + +void gral_midi_delete(gral_midi *midi) { + // TODO +}