fix: use atomic stores for clip state in dispatcher.c
Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
77
dispatcher.c
77
dispatcher.c
@@ -127,11 +127,11 @@ AppState* dispatcher_get_state_ptr(void) {
|
|||||||
|
|
||||||
static void save_undo_state(AppState *state, int clip_index) {
|
static void save_undo_state(AppState *state, int clip_index) {
|
||||||
int undo_idx = state->undo.undo_index % MAX_UNDO_HISTORY;
|
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_clip_indices[undo_idx] = clip_index;
|
||||||
state->undo.prev_buffer_sizes[undo_idx] = state->clips[clip_index].buffer_size;
|
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_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.batch_sizes[undo_idx] = 0; // Will be set by caller
|
||||||
state->undo.undo_index++;
|
state->undo.undo_index++;
|
||||||
state->undo.redo_index = 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
|
// 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:
|
case CLIP_EMPTY:
|
||||||
clip->state = CLIP_RECORDING;
|
atomic_store(&clip->state, CLIP_RECORDING);
|
||||||
clip->write_position = 0;
|
clip->write_position = 0;
|
||||||
clip->buffer_size = 0;
|
clip->buffer_size = 0;
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
break;
|
break;
|
||||||
case CLIP_RECORDING: {
|
case CLIP_RECORDING: {
|
||||||
// Transition to looping: copy from ring buffer to clip buffer
|
// Transition to looping: copy from ring buffer to clip buffer
|
||||||
clip->state = CLIP_LOOPING;
|
atomic_store(&clip->state, CLIP_LOOPING);
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
|
|
||||||
// Determine which channel this clip belongs to
|
// Determine which channel this clip belongs to
|
||||||
int channel = clip_index % MAX_CHANNELS;
|
int channel = clip_index % MAX_CHANNELS;
|
||||||
@@ -177,12 +179,12 @@ static void clip_trigger(AppState *state, int clip_index) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CLIP_LOOPING:
|
case CLIP_LOOPING:
|
||||||
clip->state = CLIP_STOPPED;
|
atomic_store(&clip->state, CLIP_STOPPED);
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
break;
|
break;
|
||||||
case CLIP_STOPPED:
|
case CLIP_STOPPED:
|
||||||
clip->state = CLIP_LOOPING;
|
atomic_store(&clip->state, CLIP_LOOPING);
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,22 +194,24 @@ static void midi_clip_trigger(AppState *state, int clip_index) {
|
|||||||
|
|
||||||
MidiClip *clip = &state->midi_clips[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:
|
case CLIP_EMPTY:
|
||||||
clip->state = CLIP_RECORDING;
|
atomic_store(&clip->state, CLIP_RECORDING);
|
||||||
clip->event_count = 0;
|
clip->event_count = 0;
|
||||||
clip->read_index = 0;
|
clip->read_index = 0;
|
||||||
break;
|
break;
|
||||||
case CLIP_RECORDING:
|
case CLIP_RECORDING:
|
||||||
clip->state = CLIP_LOOPING;
|
atomic_store(&clip->state, CLIP_LOOPING);
|
||||||
clip->read_index = 0;
|
clip->read_index = 0;
|
||||||
break;
|
break;
|
||||||
case CLIP_LOOPING:
|
case CLIP_LOOPING:
|
||||||
clip->state = CLIP_STOPPED;
|
atomic_store(&clip->state, CLIP_STOPPED);
|
||||||
clip->read_index = 0;
|
clip->read_index = 0;
|
||||||
break;
|
break;
|
||||||
case CLIP_STOPPED:
|
case CLIP_STOPPED:
|
||||||
clip->state = CLIP_LOOPING;
|
atomic_store(&clip->state, CLIP_LOOPING);
|
||||||
clip->read_index = 0;
|
clip->read_index = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -243,10 +247,10 @@ static void clip_reset(AppState *state, int clip_index) {
|
|||||||
|
|
||||||
save_undo_state(state, clip_index);
|
save_undo_state(state, clip_index);
|
||||||
|
|
||||||
clip->state = CLIP_EMPTY;
|
atomic_store(&clip->state, CLIP_EMPTY);
|
||||||
clip->buffer_size = 0;
|
clip->buffer_size = 0;
|
||||||
clip->write_position = 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));
|
if (clip->buffer) memset(clip->buffer, 0, MAX_BUFFER_SIZE * sizeof(float));
|
||||||
|
|
||||||
// Also reset the ring buffer read position for this channel
|
// 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) {
|
if (clip_idx >= 0 && clip_idx < MAX_CLIPS) {
|
||||||
Clip *clip = &state->clips[clip_idx];
|
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->buffer_size = state->undo.prev_buffer_sizes[current_idx];
|
||||||
clip->write_position = state->undo.prev_write_positions[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) {
|
if (clip_idx >= 0 && clip_idx < MAX_CLIPS) {
|
||||||
Clip *clip = &state->clips[clip_idx];
|
Clip *clip = &state->clips[clip_idx];
|
||||||
switch (clip->state) {
|
ClipState current_state = (ClipState)atomic_load(&clip->state);
|
||||||
|
switch (current_state) {
|
||||||
case CLIP_EMPTY:
|
case CLIP_EMPTY:
|
||||||
clip->state = CLIP_RECORDING;
|
atomic_store(&clip->state, CLIP_RECORDING);
|
||||||
clip->write_position = 0;
|
clip->write_position = 0;
|
||||||
clip->buffer_size = 0;
|
clip->buffer_size = 0;
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
break;
|
break;
|
||||||
case CLIP_RECORDING:
|
case CLIP_RECORDING:
|
||||||
clip->state = CLIP_LOOPING;
|
atomic_store(&clip->state, CLIP_LOOPING);
|
||||||
clip->buffer_size = clip->write_position;
|
clip->buffer_size = clip->write_position;
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
break;
|
break;
|
||||||
case CLIP_LOOPING:
|
case CLIP_LOOPING:
|
||||||
clip->state = CLIP_STOPPED;
|
atomic_store(&clip->state, CLIP_STOPPED);
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
break;
|
break;
|
||||||
case CLIP_STOPPED:
|
case CLIP_STOPPED:
|
||||||
clip->state = CLIP_LOOPING;
|
atomic_store(&clip->state, CLIP_LOOPING);
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -430,10 +435,10 @@ void reducer(AppState *state, Action action) {
|
|||||||
if (clip->buffer) {
|
if (clip->buffer) {
|
||||||
size_t copy_size = (num_samples < MAX_BUFFER_SIZE) ? num_samples : MAX_BUFFER_SIZE;
|
size_t copy_size = (num_samples < MAX_BUFFER_SIZE) ? num_samples : MAX_BUFFER_SIZE;
|
||||||
memcpy(clip->buffer, new_buffer, copy_size * sizeof(float));
|
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->buffer_size = copy_size;
|
||||||
clip->write_position = 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);
|
printf("Loaded clip %d from %s\n", clip_idx, action.data.load_clip.filename);
|
||||||
}
|
}
|
||||||
free(new_buffer);
|
free(new_buffer);
|
||||||
@@ -516,7 +521,7 @@ void reducer(AppState *state, Action action) {
|
|||||||
case ACTION_MIDI_CLIP_RESET: {
|
case ACTION_MIDI_CLIP_RESET: {
|
||||||
int idx = action.data.midi_clip_reset.clip_index;
|
int idx = action.data.midi_clip_reset.clip_index;
|
||||||
if (idx >= 0 && idx < MAX_CLIPS) {
|
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].event_count = 0;
|
||||||
state->midi_clips[idx].read_index = 0;
|
state->midi_clips[idx].read_index = 0;
|
||||||
// Don't free events here - just reset count
|
// Don't free events here - just reset count
|
||||||
@@ -542,10 +547,10 @@ void reducer(AppState *state, Action action) {
|
|||||||
// Reset clips first
|
// Reset clips first
|
||||||
for (int i = 0; i < MAX_CLIPS; i++) {
|
for (int i = 0; i < MAX_CLIPS; i++) {
|
||||||
Clip *clip = &state->clips[i];
|
Clip *clip = &state->clips[i];
|
||||||
clip->state = CLIP_EMPTY;
|
atomic_store(&clip->state, CLIP_EMPTY);
|
||||||
clip->buffer_size = 0;
|
clip->buffer_size = 0;
|
||||||
clip->write_position = 0;
|
clip->write_position = 0;
|
||||||
clip->read_position = 0;
|
atomic_store(&clip->read_position, 0);
|
||||||
if (clip->buffer) {
|
if (clip->buffer) {
|
||||||
memset(clip->buffer, 0, MAX_BUFFER_SIZE * sizeof(float));
|
memset(clip->buffer, 0, MAX_BUFFER_SIZE * sizeof(float));
|
||||||
} else {
|
} else {
|
||||||
@@ -554,7 +559,7 @@ void reducer(AppState *state, Action action) {
|
|||||||
|
|
||||||
// NEW: Reset midi clips
|
// NEW: Reset midi clips
|
||||||
MidiClip *mclip = &state->midi_clips[i];
|
MidiClip *mclip = &state->midi_clips[i];
|
||||||
mclip->state = CLIP_EMPTY;
|
atomic_store(&mclip->state, CLIP_EMPTY);
|
||||||
mclip->event_count = 0;
|
mclip->event_count = 0;
|
||||||
mclip->read_index = 0;
|
mclip->read_index = 0;
|
||||||
mclip->max_events = MAX_MIDI_EVENTS;
|
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].events = (MidiEvent *)calloc(MAX_MIDI_EVENTS, sizeof(MidiEvent));
|
||||||
dispatcher.state.midi_clips[i].max_events = MAX_MIDI_EVENTS;
|
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);
|
atomic_store(&dispatcher.running, false);
|
||||||
@@ -673,6 +679,7 @@ void dispatcher_stop(void) {
|
|||||||
for (int i = 0; i < MAX_CLIPS; i++) {
|
for (int i = 0; i < MAX_CLIPS; i++) {
|
||||||
free(dispatcher.state.midi_clips[i].events);
|
free(dispatcher.state.midi_clips[i].events);
|
||||||
dispatcher.state.midi_clips[i].events = NULL;
|
dispatcher.state.midi_clips[i].events = NULL;
|
||||||
|
atomic_store(&dispatcher.state.midi_clips[i].state, CLIP_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&dispatcher.subscribers_mutex);
|
pthread_mutex_lock(&dispatcher.subscribers_mutex);
|
||||||
|
|||||||
Reference in New Issue
Block a user