#include #include #include #include #include #include /* * Integration test for the JACK looper. * * 1. Start the looper binary (./looper) * 2. Wait for JACK ports to appear * 3. Send several note‑on messages (MIDI note number 1) to its 'control' port * using jack_midi_send, testing the state machine: * IDLE → RECORD → LOOPING → PAUSED → LOOPING → PAUSED (toggle) * 4. Send a MIDI clock Start (0xFA) to force IDLE → RECORD. * 5. Send a MIDI clock Stop (0xFC) to force RECORD → IDLE. * 6. Send a MIDI clock Continue (0xFB) to resume LOOPING from PAUSED. * 7. Kill the process and check that it exits cleanly. */ #define WAIT_SECONDS 1 static int run_cmd(const char *fmt, ...) { char buf[512]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); va_end(ap); return system(buf); } int main(void) { /* 1. binary must exist */ if (system("test -x ./looper") != 0) { fprintf(stderr, "FATAL: looper binary not found\n"); return 1; } /* 2. start the looper */ pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } if (pid == 0) { execl("./looper", "looper", NULL); perror("execl"); _exit(1); } printf("Waiting for looper (pid %d) to register ports...\n", (int)pid); sleep(3); /* generous, JACK ports must be visible */ /* 3. send note‑on messages (toggle state machine) */ printf("Sending first note‑on → IDLE → RECORD\n"); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(WAIT_SECONDS); printf("Sending second note‑on → RECORD → LOOPING\n"); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(WAIT_SECONDS); printf("Sending third note‑on → LOOPING → PAUSED\n"); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(WAIT_SECONDS); printf("Sending fourth note‑on → PAUSED → LOOPING\n"); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(WAIT_SECONDS); printf("Sending fifth note‑on → LOOPING → PAUSED (toggle)\n"); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(WAIT_SECONDS); /* 4. MIDI clock start (0xFA) – IDLE → RECORD */ printf("Sending MIDI clock Start (0xFA)\n"); run_cmd("jack_midi_send -c looper:clock -m 'FA' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(1); /* 5. MIDI clock stop (0xFC) – RECORD → IDLE */ printf("Sending MIDI clock Stop (0xFC)\n"); run_cmd("jack_midi_send -c looper:clock -m 'FC' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(1); /* bring back to PAUSED via control port */ printf("Sending note‑on to reach PAUSED again\n"); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(1); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(1); run_cmd("jack_midi_send -c looper:control -m '90 01 7f' 2>/dev/null || echo 'jack_midi_send not available'"); // now PAUSED sleep(1); /* 6. MIDI clock Continue (0xFB) – PAUSED → LOOPING */ printf("Sending MIDI clock Continue (0xFB)\n"); run_cmd("jack_midi_send -c looper:clock -m 'FB' 2>/dev/null || echo 'jack_midi_send not available'"); sleep(1); /* cleanup */ printf("Terminating looper...\n"); kill(pid, SIGTERM); int status; waitpid(pid, &status, 0); if (WIFEXITED(status)) { printf("Looper exited with status %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("Looper terminated by signal %d\n", WTERMSIG(status)); } printf("Integration test finished (manual verification recommended)\n"); return 0; }