diff --git a/src/channel.c b/src/channel.c index 0d94656..713024f 100644 --- a/src/channel.c +++ b/src/channel.c @@ -19,7 +19,7 @@ void channel_add(jack_client_t *client, int idx) if (!channels[idx].audio_in || !channels[idx].audio_out) { fprintf(stderr, "Failed to register ports for channel %d\n", next_channel_id); /* Do NOT mark channel active – process loop will skip it */ - channels[idx].active = 0; + atomic_store(&channels[idx].active, 0); return; } @@ -36,8 +36,7 @@ void channel_add(jack_client_t *client, int idx) void channel_remove(jack_client_t *client, int idx) { - jack_port_unregister(client, channels[idx].audio_in); - jack_port_unregister(client, channels[idx].audio_out); + (void)client; atomic_store(&channels[idx].active, 0); channel_count--; } diff --git a/src/looper.c b/src/looper.c index f72bf35..564886e 100644 --- a/src/looper.c +++ b/src/looper.c @@ -19,6 +19,9 @@ jack_port_t *midi_control_port = NULL; jack_port_t *midi_clock_port = NULL; atomic_int control_key_active = 0; +/* Deferred removal index (1 second grace) */ +static int pending_unregister_idx = -1; + /* ---------------------------------------------------------------- * process callback * ---------------------------------------------------------------- */ @@ -198,6 +201,18 @@ int looper_init(jack_client_t *client) * ---------------------------------------------------------------- */ void looper_process_commands(jack_client_t *client) { + /* Unregister any ports that were marked for deferred removal. + By now the real‑time thread has had at least one full cycle + to see the `active = 0` store. */ + if (pending_unregister_idx != -1) { + int idx = pending_unregister_idx; + if (channels[idx].audio_in) + jack_port_unregister(client, channels[idx].audio_in); + if (channels[idx].audio_out) + jack_port_unregister(client, channels[idx].audio_out); + pending_unregister_idx = -1; + } + if (atomic_exchange(&cmd_add, 0)) { int idx; for (idx = 0; idx < MAX_CHANNELS; idx++) @@ -212,7 +227,9 @@ void looper_process_commands(jack_client_t *client) for (int idx = 1; idx < MAX_CHANNELS; idx++) if (channels[idx].active) remove_idx = idx; if (remove_idx != -1) { + /* Mark inactive now; ports will be unregistered next round */ channel_remove(client, remove_idx); + pending_unregister_idx = remove_idx; } } }