feat: add FIFO add_midi command and integration tests for FIFO stop/bind/unbind and MIDI channel creation

Co-authored-by: aider (deepseek/deepseek-reasoner) <aider@aider.chat>
This commit is contained in:
Loic Coenen
2026-05-10 11:46:04 +00:00
parent df181b117e
commit df5ecef580
2 changed files with 157 additions and 0 deletions

View File

@@ -34,6 +34,9 @@ static void *pipe_thread_func(void *arg) {
if (strcmp(line, "add") == 0) {
command_t cmd = {.type = CMD_ADD_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_fifo, cmd);
} else if (strcmp(line, "add_midi") == 0) {
command_t cmd = {.type = CMD_ADD_MIDI_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_fifo, cmd);
} else if (strcmp(line, "remove") == 0) {
command_t cmd = {.type = CMD_REMOVE_CHANNEL, .channel = -1, .data = 0};
queue_push(&cmd_queue_main_fifo, cmd);

View File

@@ -836,6 +836,148 @@ static int test_remove_channel(void) {
}
/* test FIFO stop, bind, unbind */
static int test_fifo_stop_bind_unbind(void) {
printf("Test: FIFO stop, bind, unbind\n");
pid_t pid = start_looper();
if (pid < 0) return 1;
jack_client_t *client;
jack_status_t status;
client = jack_client_open("test_fifo_stop", JackNoStartServer, &status);
if (!client) {
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
fprintf(stderr, " SKIP: no JACK\n");
return 1;
}
jack_port_t *audio_out = jack_port_register(client, "out",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
jack_port_t *audio_in = jack_port_register(client, "in",
JACK_DEFAULT_AUDIO_TYPE,
JackPortIsInput, 0);
if (!audio_out || !audio_in) {
jack_client_close(client);
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
return 1;
}
safe_usleep(200000);
char my_out[64], my_in[64];
snprintf(my_out, sizeof(my_out), "test_fifo_stop:out");
snprintf(my_in, sizeof(my_in), "test_fifo_stop:in");
if (jack_connect(client, my_out, "looper:input") ||
jack_connect(client, "looper:output", my_in)) {
jack_client_close(client);
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
return 1;
}
/* start recording via note1 */
if (send_jack_note_on("looper:control", 1, 127) != 0) {
jack_client_close(client);
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
return 1;
}
safe_usleep(200000);
int sr = jack_get_sample_rate(client);
continuous_sine = 0;
beep_remaining = (int)(0.1f * sr);
bursts = 0;
prev_above = 0;
passthrough_output_port = audio_out;
passthrough_input_port = audio_in;
passthrough_phase = 0.0f;
passthrough_freq = 440.0f;
passthrough_sample_rate = sr;
passthrough_total_samples = 0;
passthrough_sum_sq = 0.0;
passthrough_done = 0;
jack_set_process_callback(client, passthrough_process, NULL);
if (jack_activate(client)) {
jack_client_close(client);
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
return 1;
}
safe_usleep(150000);
/* now send stop, bind, unbind via FIFO */
int fd = open("/tmp/looper_cmd", O_WRONLY);
if (fd < 0) {
perror("open fifo");
jack_deactivate(client);
jack_client_close(client);
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
return 1;
}
write(fd, "stop\n", 5);
write(fd, "bind 0\n", 7);
write(fd, "unbind\n", 7);
close(fd);
safe_usleep(500000);
int bursts_after = bursts;
jack_deactivate(client);
jack_client_close(client);
kill(pid, SIGTERM);
waitpid(pid, NULL, 0);
if (bursts_after < 1) {
fprintf(stderr, " FAIL: no burst detected (probably no recording)\n");
return 1;
}
printf(" PASS (FIFO stop, bind, unbind executed)\n");
return 0;
}
/* test MIDI channel creation via FIFO */
static int test_midi_channel_add(void) {
printf("Test: MIDI channel creation via FIFO (add_midi)\n");
pid_t pid = start_looper();
if (pid < 0) return 1;
jack_client_t *client;
jack_status_t status;
client = jack_client_open("test_midi_add", JackNoStartServer, &status);
if (!client) {
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
fprintf(stderr, " SKIP: no JACK\n");
return 1;
}
int fd = open("/tmp/looper_cmd", O_WRONLY);
if (fd < 0) {
perror("open fifo");
jack_client_close(client);
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
return 1;
}
write(fd, "add_midi\n", 9);
close(fd);
safe_usleep(1500000); /* allow main loop to process */
const char **ports = jack_get_ports(client, NULL, JACK_DEFAULT_MIDI_TYPE, 0);
int found = 0;
if (ports) {
for (int i = 0; ports[i]; i++) {
if (strstr(ports[i], "looper:channel1_midi_in")) {
found = 1;
break;
}
}
jack_free(ports);
}
jack_client_close(client);
kill(pid, SIGTERM);
waitpid(pid, NULL, 0);
if (!found) {
fprintf(stderr, " FAIL: channel1_midi_in port not created\n");
return 1;
}
printf(" PASS (MIDI channel created)\n");
return 0;
}
/* test FIFO pipe */
static int test_fifo_pipe(void) {
printf("Test: FIFO pipe add/remove\n");
@@ -1178,6 +1320,18 @@ int main(void) {
failures++;
}
/* 13. Test FIFO stop/bind/unbind */
if (test_fifo_stop_bind_unbind() != 0) {
fprintf(stderr, " FAILED\n");
failures++;
}
/* 14. Test MIDI channel creation */
if (test_midi_channel_add() != 0) {
fprintf(stderr, " FAILED\n");
failures++;
}
if (failures > 0) {
fprintf(stderr, "%d test(s) FAILED\n", failures);
return 1;