99 lines
2.9 KiB
C
99 lines
2.9 KiB
C
// 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;
|
||
|
||
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) {
|
||
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, cmd);
|
||
} break;
|
||
case 61:
|
||
{
|
||
command_t cmd = { .type = CMD_REMOVE_CHANNEL, .channel = -1, .data = 0 };
|
||
queue_push(&cmd_queue_main, cmd);
|
||
} break;
|
||
case 62:
|
||
{
|
||
int bch = atomic_load(&bind_channel);
|
||
if (bch >= 0 && bch < MAX_CHANNELS) {
|
||
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;
|
||
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, cmd);
|
||
} break;
|
||
case 61:
|
||
{
|
||
command_t cmd = { .type = CMD_REMOVE_CHANNEL, .channel = -1, .data = 0 };
|
||
queue_push(&cmd_queue_main, cmd);
|
||
} break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
} else if ((status & 0xf0) == 0x80 ||
|
||
((status & 0xf0) == 0x90 && vel == 0)) {
|
||
atomic_store(&control_key_active, 0);
|
||
}
|
||
}
|
||
}
|