diff --git a/src/pipe.c b/src/pipe.c index da043f8..1cb6700 100644 --- a/src/pipe.c +++ b/src/pipe.c @@ -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); diff --git a/tests/integration.c b/tests/integration.c index 154d26e..107503e 100644 --- a/tests/integration.c +++ b/tests/integration.c @@ -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;