Merge branch '3-integrate-carla'

This commit is contained in:
Loic Coenen
2026-05-17 19:39:54 +00:00
42 changed files with 2716 additions and 340 deletions

View File

@@ -5,11 +5,19 @@
#include <stdio.h>
#include <string.h>
/* Helper: zero a scene and set its state to IDLE */
void init_scene(scene_t *sc) {
memset(sc, 0, sizeof(scene_t));
atomic_store(&sc->state, STATE_IDLE);
atomic_store(&sc->prev_state, -1);
}
void channel_add(jack_client_t *client, int idx) {
char in_name[64], out_name[64];
snprintf(in_name, sizeof(in_name), "channel%d_input", next_channel_id);
snprintf(out_name, sizeof(out_name), "channel%d_output", next_channel_id);
/* Always register audio ports (needed for pass-through even for MIDI channels?) */
channels[idx].audio_in = jack_port_register(
client, in_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
channels[idx].audio_out = jack_port_register(
@@ -22,13 +30,36 @@ void channel_add(jack_client_t *client, int idx) {
return;
}
/* If this is a MIDI channel, register MIDI ports */
if (channels[idx].type == CHANNEL_MIDI) {
char midi_in_name[64], midi_out_name[64];
snprintf(midi_in_name, sizeof(midi_in_name), "channel%d_midi_in", next_channel_id);
snprintf(midi_out_name, sizeof(midi_out_name), "channel%d_midi_out", next_channel_id);
channels[idx].midi_in = jack_port_register(
client, midi_in_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
channels[idx].midi_out = jack_port_register(
client, midi_out_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
if (!channels[idx].midi_in || !channels[idx].midi_out) {
fprintf(stderr, "Failed to register MIDI ports for channel %d\n",
next_channel_id);
atomic_store(&channels[idx].active, 0);
jack_port_unregister(client, channels[idx].audio_in);
jack_port_unregister(client, channels[idx].audio_out);
return;
}
} else {
channels[idx].midi_in = NULL;
channels[idx].midi_out = NULL;
}
atomic_store(&channels[idx].active, 1);
atomic_store(&channels[idx].state, STATE_IDLE);
channels[idx].prev_state = -1;
channels[idx].loop_count = 0;
channels[idx].record_pos = 0;
channels[idx].playback_pos = 0;
/* Initialise first scene */
channels[idx].scene_count = 1;
channels[idx].current_scene = 0;
init_scene(&channels[idx].scenes[0]);
channels[idx].save_ring = NULL;
atomic_store(&channels[idx].save_complete, 0);
next_channel_id++;
channel_count++;
@@ -37,5 +68,61 @@ void channel_add(jack_client_t *client, int idx) {
void channel_remove(jack_client_t *client, int idx) {
(void)client;
atomic_store(&channels[idx].active, 0);
channel_count--;
atomic_fetch_sub(&channel_count, 1);
}
void channel_add_scene(jack_client_t *client, int idx) {
(void)client;
if (atomic_load(&channels[idx].scene_count) >= MAX_SCENES)
return;
int ns = atomic_load(&channels[idx].scene_count);
init_scene(&channels[idx].scenes[ns]);
atomic_fetch_add(&channels[idx].scene_count, 1);
}
void channel_remove_scene(jack_client_t *client, int idx) {
(void)client;
int sc = atomic_load(&channels[idx].scene_count);
if (sc <= 1)
return;
int cs = atomic_load(&channels[idx].current_scene);
/* shift remaining scenes down (atomic copy of fields) */
for (int i = cs; i < sc - 1; i++) {
atomic_store(&channels[idx].scenes[i].loop_count,
atomic_load(&channels[idx].scenes[i + 1].loop_count));
atomic_store(&channels[idx].scenes[i].record_pos,
atomic_load(&channels[idx].scenes[i + 1].record_pos));
atomic_store(&channels[idx].scenes[i].playback_pos,
atomic_load(&channels[idx].scenes[i + 1].playback_pos));
atomic_store(&channels[idx].scenes[i].state,
atomic_load(&channels[idx].scenes[i + 1].state));
atomic_store(&channels[idx].scenes[i].prev_state,
atomic_load(&channels[idx].scenes[i + 1].prev_state));
/* copy loop data (may race with RT thread; acceptable for this release) */
memcpy(channels[idx].scenes[i].loop.audio_buffer,
channels[idx].scenes[i + 1].loop.audio_buffer,
LOOP_BUF_SIZE * sizeof(float));
}
atomic_fetch_sub(&channels[idx].scene_count, 1);
int new_sc = atomic_load(&channels[idx].scene_count);
if (cs >= new_sc)
atomic_store(&channels[idx].current_scene, new_sc - 1);
}
void channel_next_scene(jack_client_t *client, int idx) {
(void)client;
int sc = atomic_load(&channels[idx].scene_count);
if (sc > 1) {
int cs = atomic_load(&channels[idx].current_scene);
atomic_store(&channels[idx].current_scene, (cs + 1) % sc);
}
}
void channel_prev_scene(jack_client_t *client, int idx) {
(void)client;
int sc = atomic_load(&channels[idx].scene_count);
if (sc > 1) {
int cs = atomic_load(&channels[idx].current_scene);
atomic_store(&channels[idx].current_scene, (cs - 1 + sc) % sc);
}
}