// cppcheck-suppress missingIncludeSystem #include "midi.h" #include "channel.h" #include "command.h" #include "queue.h" #include #include #include 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]; /* note‑on */ 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); } } }