feat: add project save/load with .wheel files and auto-save thread

Co-authored-by: aider (deepseek/deepseek-coder) <aider@aider.chat>
This commit is contained in:
Loic Coenen
2026-05-02 22:53:59 +00:00
parent bee7f6d22b
commit 1487619cc2
7 changed files with 778 additions and 11 deletions

View File

@@ -1,5 +1,6 @@
#include "dispatcher.h"
#include "wav_io.h"
#include "fs.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -69,6 +70,11 @@ static bool pop_action(Action *action) {
static void dispatch_function(Action action) {
push_action(action);
pthread_cond_signal(&dispatcher.action_cond);
// Trigger autosave for non-quit actions
if (action.type != ACTION_QUIT) {
fs_trigger_autosave();
}
}
// ============================================================
@@ -447,6 +453,48 @@ AppState reducer(AppState state, Action action) {
case ACTION_PROCESS_AUDIO:
return state;
case ACTION_SAVE_PROJECT: {
fs_save_project(action.data.save_project.filename, &state);
return state;
}
case ACTION_LOAD_PROJECT: {
// Reset clips first
for (int i = 0; i < MAX_CLIPS; i++) {
Clip *clip = &state.clips[i];
clip->state = CLIP_EMPTY;
clip->buffer_size = 0;
clip->write_position = 0;
clip->read_position = 0;
if (clip->buffer) memset(clip->buffer, 0, MAX_BUFFER_SIZE * sizeof(float));
}
// Reset Carla host
for (int ch = 0; ch < MAX_CHANNELS; ch++) {
ChannelRack *rack = &state.carla_host.channel_racks[ch];
for (int p = 0; p < rack->num_plugins; p++) {
PluginInfo *plugin = &rack->plugins[p];
if (plugin->parameters) {
free(plugin->parameters);
plugin->parameters = NULL;
}
if (plugin->parameter_names) {
for (int pi = 0; pi < plugin->num_parameters; pi++) {
free(plugin->parameter_names[pi]);
}
free(plugin->parameter_names);
plugin->parameter_names = NULL;
}
}
rack->num_plugins = 0;
rack->volume = 1.0f;
rack->bypassed = false;
}
fs_load_project(action.data.load_project.filename, &state);
return state;
}
case ACTION_QUIT:
state.running = false;
return state;