diff --git a/src/channel.c b/src/channel.c index acab6c8..60fcaa4 100644 --- a/src/channel.c +++ b/src/channel.c @@ -91,9 +91,18 @@ void channel_remove_scene(jack_client_t *client, int idx) { if (cur[idx].scene_count <= 1) return; int cs = cur[idx].current_scene; - /* shift remaining scenes down */ + /* shift remaining scenes down (safe copy of fields) */ for (int i = cs; i < cur[idx].scene_count - 1; i++) { - cur[idx].scenes[i] = cur[idx].scenes[i + 1]; + cur[idx].scenes[i].loop_count = cur[idx].scenes[i+1].loop_count; + cur[idx].scenes[i].record_pos = cur[idx].scenes[i+1].record_pos; + cur[idx].scenes[i].playback_pos = cur[idx].scenes[i+1].playback_pos; + atomic_store(&cur[idx].scenes[i].state, + atomic_load(&cur[idx].scenes[i+1].state)); + cur[idx].scenes[i].prev_state = cur[idx].scenes[i+1].prev_state; + /* copy loop data */ + memcpy(cur[idx].scenes[i].loop.audio_buffer, + cur[idx].scenes[i+1].loop.audio_buffer, + LOOP_BUF_SIZE * sizeof(float)); } cur[idx].scene_count--; if (cur[idx].current_scene >= cur[idx].scene_count) diff --git a/tests/integration.c b/tests/integration.c index 40d504e..658df6e 100644 --- a/tests/integration.c +++ b/tests/integration.c @@ -1135,34 +1135,79 @@ static int write_fifo(const char *cmd) { static int test_scene_add_remove(void) { printf("Test: scene add/remove via FIFO\n"); + fflush(stdout); pid_t pid = start_looper(); if (pid < 0) return 1; - /* add a scene */ + printf(" sending scene_add...\n"); + fflush(stdout); if (!write_fifo("scene_add\n")) { - kill(pid, SIGTERM); waitpid(pid, NULL, 0); + kill(pid, SIGTERM); + for (int tries = 0; tries < 20; tries++) { + int wstatus; + pid_t ret = waitpid(pid, &wstatus, WNOHANG); + if (ret == pid) break; + if (ret < 0) break; + safe_usleep(100000); + } + kill(pid, SIGKILL); waitpid(pid, NULL, 0); fprintf(stderr, " FAIL: cannot write to FIFO\n"); return 1; } safe_usleep(50000); /* allow processing */ - /* verify that scene_next works (doesn't crash) */ + printf(" sending scene_next...\n"); + fflush(stdout); if (!write_fifo("scene_next\n")) { - kill(pid, SIGTERM); waitpid(pid, NULL, 0); + kill(pid, SIGTERM); + for (int tries = 0; tries < 20; tries++) { + int wstatus; + pid_t ret = waitpid(pid, &wstatus, WNOHANG); + if (ret == pid) break; + if (ret < 0) break; + safe_usleep(100000); + } + kill(pid, SIGKILL); waitpid(pid, NULL, 0); return 1; } safe_usleep(50000); - /* remove scene */ + printf(" sending scene_remove...\n"); + fflush(stdout); if (!write_fifo("scene_remove\n")) { - kill(pid, SIGTERM); waitpid(pid, NULL, 0); + kill(pid, SIGTERM); + for (int tries = 0; tries < 20; tries++) { + int wstatus; + pid_t ret = waitpid(pid, &wstatus, WNOHANG); + if (ret == pid) break; + if (ret < 0) break; + safe_usleep(100000); + } + kill(pid, SIGKILL); waitpid(pid, NULL, 0); return 1; } safe_usleep(50000); - kill(pid, SIGTERM); waitpid(pid, NULL, 0); - printf(" PASS (no crash means success)\n"); - return 0; + /* kill with timeout */ + kill(pid, SIGTERM); + for (int tries = 0; tries < 20; tries++) { + int wstatus; + pid_t ret = waitpid(pid, &wstatus, WNOHANG); + if (ret == pid) { + printf(" PASS (scene add/remove, looper exited)\n"); + fflush(stdout); + return 0; + } + if (ret < 0) { + perror("waitpid"); + break; + } + safe_usleep(100000); /* 100ms */ + } + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + fprintf(stderr, " FAIL: looper did not exit in time\n"); + return 1; } static int test_scene_next_prev_midi(void) {