fix: use pointer to dispatcher state in process callback for real-time access

Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
Loic Coenen
2026-05-04 22:25:33 +00:00
parent 4eed81ae06
commit d4ba1589ff
4 changed files with 18 additions and 5 deletions

View File

@@ -117,6 +117,10 @@ void dispatcher_get_state(AppState *out) {
pthread_mutex_unlock(&dispatcher.state_mutex);
}
AppState* dispatcher_get_state_ptr(void) {
return &dispatcher.state;
}
// ============================================================
// Reducer implementation
// ============================================================

View File

@@ -210,6 +210,11 @@ void dispatcher_stop(void);
// Get current state (thread-safe snapshot)
void dispatcher_get_state(AppState *out);
// Get pointer to dispatcher's state (for real-time threads that can't block)
// WARNING: This is NOT thread-safe. Only use in JACK process callback
// which is serialized per client.
AppState* dispatcher_get_state_ptr(void);
// ============================================================
// Reducer - pure function
// ============================================================

View File

@@ -28,9 +28,8 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
jack_midi_clear_buffer(midi_out_buf);
// Get state snapshot for reads
AppState state;
dispatcher_get_state(&state);
// Get pointer to dispatcher's state for real-time access
AppState *state = engine->state;
// Process MIDI input
int event_index;
@@ -100,7 +99,7 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
for (int s = 0; s < MAX_SCENES; s++) {
for (int g = 0; g < 8; g++) {
int clip_idx = g * GRID_ROWS * GRID_COLS + s * GRID_COLS + ch;
MidiClip *mclip = &state.midi_clips[clip_idx];
MidiClip *mclip = &state->midi_clips[clip_idx];
if (mclip->state == CLIP_LOOPING && mclip->event_count > 0 && mclip->events != NULL) {
if (mclip->read_index < mclip->event_count) {
@@ -142,7 +141,7 @@ static int process_callback(jack_nframes_t nframes, void *arg) {
// Iterate over all grids for this scene and channel
for (int g = 0; g < 8; g++) {
int clip_idx = g * GRID_ROWS * GRID_COLS + s * GRID_COLS + ch;
Clip *clip = &state.clips[clip_idx];
Clip *clip = &state->clips[clip_idx];
if (clip->state == CLIP_RECORDING) {
if (clip->write_position < MAX_BUFFER_SIZE && clip->buffer != NULL) {
@@ -237,6 +236,9 @@ int engine_init(Engine *engine, const char *client_name, DispatchFn dispatch) {
carla_init(&engine->carla_host, engine->client);
carla_scan_plugins(&engine->carla_host);
// Get pointer to dispatcher's state for real-time access
engine->state = dispatcher_get_state_ptr();
return 0;
}

View File

@@ -21,6 +21,8 @@ typedef struct {
bool running;
CarlaHost carla_host; // Carla host state for plugin management
AppState *state; // Pointer to dispatcher's state (for real-time access)
} Engine;
int engine_init(Engine *engine, const char *client_name, DispatchFn dispatch);