diff --git a/dispatcher.c b/dispatcher.c index a0e3753..348d0b9 100644 --- a/dispatcher.c +++ b/dispatcher.c @@ -127,11 +127,11 @@ AppState* dispatcher_get_state_ptr(void) { static void save_undo_state(AppState *state, int clip_index) { int undo_idx = state->undo.undo_index % MAX_UNDO_HISTORY; - state->undo.prev_clip_states[undo_idx] = state->clips[clip_index].state; + state->undo.prev_clip_states[undo_idx] = (ClipState)atomic_load(&state->clips[clip_index].state); state->undo.prev_clip_indices[undo_idx] = clip_index; state->undo.prev_buffer_sizes[undo_idx] = state->clips[clip_index].buffer_size; state->undo.prev_write_positions[undo_idx] = state->clips[clip_index].write_position; - state->undo.prev_read_positions[undo_idx] = state->clips[clip_index].read_position; + state->undo.prev_read_positions[undo_idx] = atomic_load(&state->clips[clip_index].read_position); state->undo.batch_sizes[undo_idx] = 0; // Will be set by caller state->undo.undo_index++; state->undo.redo_index = state->undo.undo_index; @@ -145,17 +145,19 @@ static void clip_trigger(AppState *state, int clip_index) { // Do NOT save undo here - caller will do it - switch (clip->state) { + ClipState current_state = (ClipState)atomic_load(&clip->state); + + switch (current_state) { case CLIP_EMPTY: - clip->state = CLIP_RECORDING; + atomic_store(&clip->state, CLIP_RECORDING); clip->write_position = 0; clip->buffer_size = 0; - clip->read_position = 0; + atomic_store(&clip->read_position, 0); break; case CLIP_RECORDING: { // Transition to looping: copy from ring buffer to clip buffer - clip->state = CLIP_LOOPING; - clip->read_position = 0; + atomic_store(&clip->state, CLIP_LOOPING); + atomic_store(&clip->read_position, 0); // Determine which channel this clip belongs to int channel = clip_index % MAX_CHANNELS; @@ -177,12 +179,12 @@ static void clip_trigger(AppState *state, int clip_index) { break; } case CLIP_LOOPING: - clip->state = CLIP_STOPPED; - clip->read_position = 0; + atomic_store(&clip->state, CLIP_STOPPED); + atomic_store(&clip->read_position, 0); break; case CLIP_STOPPED: - clip->state = CLIP_LOOPING; - clip->read_position = 0; + atomic_store(&clip->state, CLIP_LOOPING); + atomic_store(&clip->read_position, 0); break; } } @@ -192,22 +194,24 @@ static void midi_clip_trigger(AppState *state, int clip_index) { MidiClip *clip = &state->midi_clips[clip_index]; - switch (clip->state) { + ClipState current_state = (ClipState)atomic_load(&clip->state); + + switch (current_state) { case CLIP_EMPTY: - clip->state = CLIP_RECORDING; + atomic_store(&clip->state, CLIP_RECORDING); clip->event_count = 0; clip->read_index = 0; break; case CLIP_RECORDING: - clip->state = CLIP_LOOPING; + atomic_store(&clip->state, CLIP_LOOPING); clip->read_index = 0; break; case CLIP_LOOPING: - clip->state = CLIP_STOPPED; + atomic_store(&clip->state, CLIP_STOPPED); clip->read_index = 0; break; case CLIP_STOPPED: - clip->state = CLIP_LOOPING; + atomic_store(&clip->state, CLIP_LOOPING); clip->read_index = 0; break; } @@ -243,10 +247,10 @@ static void clip_reset(AppState *state, int clip_index) { save_undo_state(state, clip_index); - clip->state = CLIP_EMPTY; + atomic_store(&clip->state, CLIP_EMPTY); clip->buffer_size = 0; clip->write_position = 0; - clip->read_position = 0; + atomic_store(&clip->read_position, 0); if (clip->buffer) memset(clip->buffer, 0, MAX_BUFFER_SIZE * sizeof(float)); // Also reset the ring buffer read position for this channel @@ -269,10 +273,10 @@ static void undo_action(AppState *state) { if (clip_idx >= 0 && clip_idx < MAX_CLIPS) { Clip *clip = &state->clips[clip_idx]; - clip->state = state->undo.prev_clip_states[current_idx]; + atomic_store(&clip->state, state->undo.prev_clip_states[current_idx]); clip->buffer_size = state->undo.prev_buffer_sizes[current_idx]; clip->write_position = state->undo.prev_write_positions[current_idx]; - clip->read_position = state->undo.prev_read_positions[current_idx]; + atomic_store(&clip->read_position, state->undo.prev_read_positions[current_idx]); } } @@ -294,25 +298,26 @@ static void redo_action(AppState *state) { if (clip_idx >= 0 && clip_idx < MAX_CLIPS) { Clip *clip = &state->clips[clip_idx]; - switch (clip->state) { + ClipState current_state = (ClipState)atomic_load(&clip->state); + switch (current_state) { case CLIP_EMPTY: - clip->state = CLIP_RECORDING; + atomic_store(&clip->state, CLIP_RECORDING); clip->write_position = 0; clip->buffer_size = 0; - clip->read_position = 0; + atomic_store(&clip->read_position, 0); break; case CLIP_RECORDING: - clip->state = CLIP_LOOPING; + atomic_store(&clip->state, CLIP_LOOPING); clip->buffer_size = clip->write_position; - clip->read_position = 0; + atomic_store(&clip->read_position, 0); break; case CLIP_LOOPING: - clip->state = CLIP_STOPPED; - clip->read_position = 0; + atomic_store(&clip->state, CLIP_STOPPED); + atomic_store(&clip->read_position, 0); break; case CLIP_STOPPED: - clip->state = CLIP_LOOPING; - clip->read_position = 0; + atomic_store(&clip->state, CLIP_LOOPING); + atomic_store(&clip->read_position, 0); break; } } @@ -430,10 +435,10 @@ void reducer(AppState *state, Action action) { if (clip->buffer) { size_t copy_size = (num_samples < MAX_BUFFER_SIZE) ? num_samples : MAX_BUFFER_SIZE; memcpy(clip->buffer, new_buffer, copy_size * sizeof(float)); - clip->state = CLIP_LOOPING; + atomic_store(&clip->state, CLIP_LOOPING); clip->buffer_size = copy_size; clip->write_position = copy_size; - clip->read_position = 0; + atomic_store(&clip->read_position, 0); printf("Loaded clip %d from %s\n", clip_idx, action.data.load_clip.filename); } free(new_buffer); @@ -516,7 +521,7 @@ void reducer(AppState *state, Action action) { case ACTION_MIDI_CLIP_RESET: { int idx = action.data.midi_clip_reset.clip_index; if (idx >= 0 && idx < MAX_CLIPS) { - state->midi_clips[idx].state = CLIP_EMPTY; + atomic_store(&state->midi_clips[idx].state, CLIP_EMPTY); state->midi_clips[idx].event_count = 0; state->midi_clips[idx].read_index = 0; // Don't free events here - just reset count @@ -542,10 +547,10 @@ void reducer(AppState *state, Action action) { // Reset clips first for (int i = 0; i < MAX_CLIPS; i++) { Clip *clip = &state->clips[i]; - clip->state = CLIP_EMPTY; + atomic_store(&clip->state, CLIP_EMPTY); clip->buffer_size = 0; clip->write_position = 0; - clip->read_position = 0; + atomic_store(&clip->read_position, 0); if (clip->buffer) { memset(clip->buffer, 0, MAX_BUFFER_SIZE * sizeof(float)); } else { @@ -554,7 +559,7 @@ void reducer(AppState *state, Action action) { // NEW: Reset midi clips MidiClip *mclip = &state->midi_clips[i]; - mclip->state = CLIP_EMPTY; + atomic_store(&mclip->state, CLIP_EMPTY); mclip->event_count = 0; mclip->read_index = 0; mclip->max_events = MAX_MIDI_EVENTS; @@ -645,6 +650,7 @@ DispatchFn dispatcher_init(AppState *initial_state) { dispatcher.state.midi_clips[i].events = (MidiEvent *)calloc(MAX_MIDI_EVENTS, sizeof(MidiEvent)); dispatcher.state.midi_clips[i].max_events = MAX_MIDI_EVENTS; } + atomic_store(&dispatcher.state.midi_clips[i].state, CLIP_EMPTY); } atomic_store(&dispatcher.running, false); @@ -673,6 +679,7 @@ void dispatcher_stop(void) { for (int i = 0; i < MAX_CLIPS; i++) { free(dispatcher.state.midi_clips[i].events); dispatcher.state.midi_clips[i].events = NULL; + atomic_store(&dispatcher.state.midi_clips[i].state, CLIP_EMPTY); } pthread_mutex_lock(&dispatcher.subscribers_mutex);