Files
looper/src/midi.c
Loic Coenen 7b00246443 feat: implement scene infrastructure for multi-scene looper support
Co-authored-by: aider (deepseek/deepseek-reasoner) <aider@aider.chat>
2026-05-10 18:00:32 +00:00

125 lines
4.1 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// cppcheck-suppress missingIncludeSystem
#include "midi.h"
#include "channel.h"
#include "command.h"
#include "queue.h"
#include <jack/jack.h>
#include <jack/midiport.h>
#include <stdatomic.h>
extern atomic_int control_key_active;
extern atomic_int bind_channel;
extern spsc_queue_t cmd_queue;
extern spsc_queue_t cmd_queue_main_midi;
void midi_handle_events(void *port_buffer, jack_nframes_t nframes) {
(void)nframes;
jack_nframes_t nevents = jack_midi_get_event_count(port_buffer);
jack_midi_event_t ev;
for (jack_nframes_t i = 0; i < nevents; i++) {
if (jack_midi_event_get(&ev, port_buffer, i) != 0)
continue;
if (ev.size < 3)
continue;
unsigned char status = ev.buffer[0];
unsigned char note = ev.buffer[1];
unsigned char vel = ev.buffer[2];
/* noteon */
if ((status & 0xf0) == 0x90 && vel > 0) {
if (note == 64) {
atomic_store(&control_key_active, 1);
} else {
int ck = atomic_load(&control_key_active);
if (ck) {
atomic_store(&control_key_active, 0);
if (note < 16 && note < atomic_load(&channel_capacity)) {
command_t cmd = {
.type = CMD_BIND_CHANNEL, .channel = -1, .data = note};
queue_push(&cmd_queue, cmd);
} else {
switch (note) {
case 60: {
command_t cmd = {
.type = CMD_ADD_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
case 61: {
command_t cmd = {
.type = CMD_REMOVE_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
case 62: {
int bch = atomic_load(&bind_channel);
if (bch >= 0 && bch < atomic_load(&channel_capacity)) {
command_t cmd = {.type = CMD_CYCLE, .channel = bch, .data = 0};
queue_push(&cmd_queue, cmd);
}
} break;
case 63: {
command_t cmd = {.type = CMD_UNBIND, .channel = -1, .data = 0};
queue_push(&cmd_queue, cmd);
} break;
case 65: {
command_t cmd = {.type = CMD_STOP, .channel = -1, .data = 0};
queue_push(&cmd_queue, cmd);
} break;
case 66: {
command_t cmd = {
.type = CMD_ADD_MIDI_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
case 67: {
command_t cmd = {
.type = CMD_NEXT_SCENE, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
case 68: {
command_t cmd = {
.type = CMD_PREV_SCENE, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
case 69: {
command_t cmd = {
.type = CMD_ADD_SCENE, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
case 70: {
command_t cmd = {
.type = CMD_REMOVE_SCENE, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
default:
break;
}
}
} else {
/* direct mapping */
switch (note) {
case 1: {
command_t cmd = {.type = CMD_CYCLE, .channel = 0, .data = 0};
queue_push(&cmd_queue, cmd);
} break;
case 60: {
command_t cmd = {.type = CMD_ADD_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
case 61: {
command_t cmd = {
.type = CMD_REMOVE_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_midi, cmd);
} break;
default:
break;
}
}
}
} else if ((status & 0xf0) == 0x80 ||
((status & 0xf0) == 0x90 && vel == 0)) {
atomic_store(&control_key_active, 0);
}
}
}