diff --git a/.gitignore b/.gitignore
index 0af4da6..a689f8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,6 @@ pkg
forge-*
confdeps.*
conftest.*
-forge_saved_state.txt
+*.txt
error.glsl
draft/
\ No newline at end of file
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 23d2a97..fed0f33 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -120,7 +120,8 @@ make -f Makefile.dev release-arch
- [ ] Extra features
- [x] `--auto-random-cycle=4`
- [x] Arrows (up-down: bpm / left-right: cycle)
- - [ ] Save states (numkey: load / shift + numkey: save)
+ - [x] Save states (numkey: load / shift + numkey: save)
+ - [ ] (clean) static functions at top of files
- [ ] Configurable key codes
- [ ] Key codes as inputs
- [ ] Mouse position and scroll as inputs
diff --git a/README.md b/README.md
index b5806ce..6b18920 100644
--- a/README.md
+++ b/README.md
@@ -166,11 +166,13 @@ When running, the following hotkeys are available:
| A | Auto Random mode On/Off |
| ← / → | Auto Random Cycle -/+ 1 |
| ↑ / ↓ | BPM +/- 1 |
+| 0-9 | Load state 0 to 9 |
+| Shift + 0-9 | Save state 0 to 9 |
### CLI arguments
```txt
-usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-arc=CYCLES] [-v=FILE] [-vs=SIZE] [-is=SIZE] [-sf=STATE_PATH] [-ls / -nls] [-ss / -nss] [-tm] [-tf]
+usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-arc=CYCLES] [-v=FILE] [-vs=SIZE] [-is=SIZE] [-ls / -nls] [-ss / -nss] [-tm] [-tf]
Fusion Of Real-time Generative Effects.
@@ -192,7 +194,6 @@ options:
-v, --video-in path to video capture device (multiple allowed)
-vs, --video-size video capture desired height (default: internal texture height)
-is, --internal-size internal texture height (default: 720)
- -sf, --state-file saved state file (default: forge_saved_state.txt)
-ls, --load-state load saved state (default)
-nls, --no-load-state do not load saved state
-ss, --save-state save state (default)
diff --git a/default/forge_project.cfg b/default/forge_project.cfg
index c807a5f..edb7a51 100644
--- a/default/forge_project.cfg
+++ b/default/forge_project.cfg
@@ -264,3 +264,9 @@ MIDI_3_1_Z=
MIDI_3_2_X=0
MIDI_3_2_Y=16
MIDI_3_2_Z=
+
+# =====
+# OTHER
+# =====
+
+SAVE_FILE_PREFIX=forge_default_save
\ No newline at end of file
diff --git a/src/args.c b/src/args.c
index e45625e..3cbd8b2 100644
--- a/src/args.c
+++ b/src/args.c
@@ -33,7 +33,6 @@ static void print_help(int status_code) {
"[-v=FILE] "
"[-vs=SIZE] "
"[-is=SIZE] "
- "[-sf=STATE_PATH] "
"[-ls / -nls] "
"[-ss / -nss] "
"[-tm] "
@@ -63,8 +62,6 @@ static void print_help(int status_code) {
" -vs, --video-size video capture desired height (default: "
"internal texture height)\n"
" -is, --internal-size internal texture height (default: 720)\n"
- " -sf, --state-file saved state file (default: "
- "forge_saved_state.txt)\n"
" -ls, --load-state load saved state (default)\n"
" -nls, --no-load-state do not load saved state\n"
" -ss, --save-state save state (default)\n"
@@ -131,7 +128,6 @@ void args_parse(Parameters *params, int argc, char **argv) {
params->video_in.length = 0;
params->video_size = 0;
params->internal_size = 720;
- strlcpy(params->state_file, "forge_saved_state.txt", STR_LEN);
params->load_state = true;
params->save_state = true;
params->trace_midi = false;
@@ -194,8 +190,6 @@ void args_parse(Parameters *params, int argc, char **argv) {
if (params->internal_size == 0) {
invalid_value(arg, value);
}
- } else if (is_arg(arg, "-sf") || is_arg(arg, "--state-file")) {
- strlcpy(params->state_file, value, STR_LEN);
} else if (is_arg(arg, "-ls") || is_arg(arg, "--load-state")) {
params->load_state = true;
} else if (is_arg(arg, "-nls") || is_arg(arg, "--no-load-state")) {
diff --git a/src/config_file.c b/src/config_file.c
index a3bf6de..749cdfe 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -75,9 +75,12 @@ void config_file_read(ConfigFile *config, const char *path) {
file_read(&file, path);
if (file.error) {
+ config->error = true;
return;
}
+ config->error = false;
+
line = strtok_r(file.content, "\n", &rest);
while (line != NULL) {
diff --git a/src/forge.c b/src/forge.c
index b572206..b126c08 100644
--- a/src/forge.c
+++ b/src/forge.c
@@ -59,8 +59,7 @@ static void compute_fps(bool trace_fps) {
static void init_context(const Parameters *params, unsigned int in_count) {
state_init(context, &project.state_config, params->demo, params->auto_random,
- params->auto_random_cycle, params->base_tempo, params->state_file,
- params->load_state);
+ params->auto_random_cycle, params->base_tempo, params->load_state);
context->monitor = params->monitor;
@@ -247,7 +246,7 @@ void forge_run(const Parameters *params) {
context->stop = true;
if (params->save_state) {
- state_save(context, &project.state_config, params->state_file);
+ state_save(context, &project.state_config);
}
shaders_free(&program);
diff --git a/src/midi.c b/src/midi.c
index a4274a7..ff7dc7b 100644
--- a/src/midi.c
+++ b/src/midi.c
@@ -21,6 +21,10 @@ void midi_open(MidiDevice *device, const char *name) {
void midi_write(const MidiDevice *device, unsigned char code,
unsigned char value) {
+ if (device->error) {
+ return;
+ }
+
unsigned char buffer[3];
buffer[0] = 0xB0;
diff --git a/src/state.c b/src/state.c
index 5a9226c..eaef068 100644
--- a/src/state.c
+++ b/src/state.c
@@ -12,6 +12,232 @@
#include "state.h"
#include "tempo.h"
+static void safe_midi_write(const MidiDevice *midi, unsigned int code,
+ unsigned char value) {
+ if (code != UNSET_MIDI_CODE) {
+ midi_write(midi, code, value);
+ }
+}
+
+static void update_page(const SharedContext *context,
+ const StateConfig *state_config,
+ const MidiDevice *midi) {
+ unsigned int page_item_min;
+ unsigned int page_item_max;
+ // SHOW PAGE
+ for (unsigned int i = 0; i < state_config->select_page_codes.length; i++) {
+ safe_midi_write(midi, state_config->select_page_codes.values[i],
+ i == context->page ? MIDI_MAX : 0);
+ }
+
+ // SHOW PAGE ITEM
+ page_item_min = state_config->select_item_codes.length * context->page;
+ page_item_max = page_item_min + state_config->select_item_codes.length;
+
+ if (context->state.values[context->selected] >= page_item_min &&
+ context->state.values[context->selected] < page_item_max) {
+ for (unsigned int i = 0; i < state_config->select_item_codes.length; i++) {
+ safe_midi_write(midi, state_config->select_item_codes.values[i],
+ i == context->state.values[context->selected] -
+ page_item_min
+ ? MIDI_MAX
+ : 0);
+ }
+ } else {
+ for (unsigned int i = 0; i < state_config->select_item_codes.length; i++) {
+ safe_midi_write(midi, state_config->select_item_codes.values[i], 0);
+ }
+ }
+}
+
+static void update_active(const SharedContext *context,
+ const StateConfig *state_config,
+ const MidiDevice *midi) {
+ unsigned int k;
+
+ for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
+ for (unsigned int j = 0; j < state_config->midi_active_counts.values[i];
+ j++) {
+ k = state_config->midi_active_offsets.values[i] + j;
+ safe_midi_write(midi, state_config->midi_active_codes.values[k],
+ context->active[i] == j ? MIDI_MAX : 0);
+ }
+ }
+}
+
+static void update_values(const SharedContext *context,
+ const StateConfig *state_config,
+ const MidiDevice *midi) {
+ unsigned int j;
+ unsigned int k;
+ unsigned int part;
+
+ for (unsigned int i = 0; i < state_config->midi_codes.length; i++) {
+ j = i / 3;
+ part = arr_uint_remap_index(state_config->midi_offsets, &j);
+ k = state_config->values_offsets.values[part] +
+ context->active[part] * state_config->midi_counts.values[part] + j;
+ safe_midi_write(midi, state_config->midi_codes.values[i],
+ context->values[k][i % 3] * MIDI_MAX);
+ }
+}
+
+static void reset(SharedContext *context) {
+ memset(context->values, 0, sizeof(context->values));
+ memset(context->state.values, 0, sizeof(context->state.values));
+}
+
+static void randomize(SharedContext *context, const StateConfig *state_config) {
+ unsigned int j;
+ unsigned int l;
+ unsigned int part;
+
+ for (unsigned int i = 0; i < state_config->midi_codes.length; i++) {
+ j = i / 3;
+ part = arr_uint_remap_index(state_config->midi_offsets, &j);
+ for (unsigned int k = 0; k < state_config->midi_active_counts.values[part];
+ k++) {
+ l = state_config->values_offsets.values[part] +
+ k * state_config->midi_counts.values[part] + j;
+
+ if (arr_uint_index_of(state_config->fader_codes,
+ state_config->midi_codes.values[i]) !=
+ ARRAY_NOT_FOUND) {
+ context->values[l][i % 3] = (float)rand_uint(MIDI_MAX + 1) / MIDI_MAX;
+ } else {
+ context->values[l][i % 3] = rand_uint(2) == 1 ? 1 : 0;
+ }
+ }
+ }
+
+ for (unsigned int i = 0; i < context->state.length; i++) {
+ context->state.values[i] = rand_uint(state_config->state_max);
+ }
+}
+
+static void load_from_file(SharedContext *context,
+ const StateConfig *state_config, char *state_file) {
+ ConfigFile saved_state;
+ char key[STR_LEN];
+
+ config_file_read(&saved_state, state_file);
+
+ if (saved_state.error) {
+ return;
+ }
+
+ tempo_set(&context->tempo,
+ config_file_get_int(&saved_state, "tempo", context->tempo.tempo));
+ context->page = config_file_get_int(&saved_state, "page", 0);
+ context->selected = config_file_get_int(&saved_state, "selected", 0);
+
+ for (unsigned int i = 0; i < context->state.length; i++) {
+ snprintf(key, STR_LEN, "seed_%d", i);
+ context->seeds[i] =
+ config_file_get_int(&saved_state, key, context->seeds[i]);
+ snprintf(key, STR_LEN, "state_%d", i);
+ context->state.values[i] = config_file_get_int(&saved_state, key, 0);
+ }
+
+ for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
+ snprintf(key, STR_LEN, "active_%d", i);
+ context->active[i] = config_file_get_int(&saved_state, key, 0);
+ }
+
+ for (unsigned int i = 0; i < state_config->value_count; i++) {
+ snprintf(key, STR_LEN, "value_%d_x", i);
+ context->values[i][0] =
+ (float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX;
+ snprintf(key, STR_LEN, "value_%d_y", i);
+ context->values[i][1] =
+ (float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX;
+ snprintf(key, STR_LEN, "value_%d_z", i);
+ context->values[i][2] =
+ (float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX;
+ }
+
+ config_file_free(&saved_state);
+}
+
+static void load_from_default_file(SharedContext *context,
+ const StateConfig *state_config) {
+ char state_file[STR_LEN];
+
+ snprintf(state_file, STR_LEN, "%s.txt", state_config->save_file_prefix);
+
+ load_from_file(context, state_config, state_file);
+}
+
+static void load_from_index_file(SharedContext *context,
+ const StateConfig *state_config,
+ unsigned int index) {
+ char state_file[STR_LEN];
+
+ snprintf(state_file, STR_LEN, "%s.%d.txt", state_config->save_file_prefix,
+ index);
+
+ load_from_file(context, state_config, state_file);
+}
+
+static void save_to_file(const SharedContext *context,
+ const StateConfig *state_config,
+ const char *state_file) {
+ StringArray lines;
+
+ log_info("Saving state to '%s'...", state_file);
+
+ lines.length = 0;
+
+ snprintf(lines.values[lines.length++], STR_LEN, "tempo=%d",
+ (unsigned int)context->tempo.tempo);
+ snprintf(lines.values[lines.length++], STR_LEN, "page=%d", context->page);
+ snprintf(lines.values[lines.length++], STR_LEN, "selected=%d",
+ context->selected);
+
+ for (unsigned int i = 0; i < context->state.length; i++) {
+ snprintf(lines.values[lines.length++], STR_LEN, "seed_%d=%d", i,
+ context->seeds[i]);
+ snprintf(lines.values[lines.length++], STR_LEN, "state_%d=%d", i,
+ context->state.values[i]);
+ }
+
+ for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
+ snprintf(lines.values[lines.length++], STR_LEN, "active_%d=%d", i,
+ context->active[i]);
+ }
+
+ for (unsigned int i = 0; i < state_config->value_count; i++) {
+ snprintf(lines.values[lines.length++], STR_LEN, "value_%d_x=%d", i,
+ (unsigned int)(context->values[i][0] * MIDI_MAX));
+ snprintf(lines.values[lines.length++], STR_LEN, "value_%d_y=%d", i,
+ (unsigned int)(context->values[i][1] * MIDI_MAX));
+ snprintf(lines.values[lines.length++], STR_LEN, "value_%d_z=%d", i,
+ (unsigned int)(context->values[i][2] * MIDI_MAX));
+ }
+
+ file_write(state_file, &lines);
+}
+
+static void save_to_default_file(const SharedContext *context,
+ const StateConfig *state_config) {
+ char state_file[STR_LEN];
+
+ snprintf(state_file, STR_LEN, "%s.txt", state_config->save_file_prefix);
+
+ save_to_file(context, state_config, state_file);
+}
+
+static void save_to_index_file(const SharedContext *context,
+ const StateConfig *state_config,
+ unsigned int index) {
+ char state_file[STR_LEN];
+
+ snprintf(state_file, STR_LEN, "%s.%d.txt", state_config->save_file_prefix,
+ index);
+
+ save_to_file(context, state_config, state_file);
+}
+
void state_parse_config(StateConfig *state_config, const ConfigFile *config) {
unsigned int offset;
unsigned int count;
@@ -118,76 +344,10 @@ void state_parse_config(StateConfig *state_config, const ConfigFile *config) {
state_config->tap_tempo_code =
config_file_get_int(config, "TAP_TEMPO", UNSET_MIDI_CODE);
-}
-static void safe_midi_write(const MidiDevice *midi, unsigned int code,
- unsigned char value) {
- if (code != UNSET_MIDI_CODE) {
- midi_write(midi, code, value);
- }
-}
-
-static void update_page(const SharedContext *context,
- const StateConfig *state_config,
- const MidiDevice *midi) {
- unsigned int page_item_min;
- unsigned int page_item_max;
- // SHOW PAGE
- for (unsigned int i = 0; i < state_config->select_page_codes.length; i++) {
- safe_midi_write(midi, state_config->select_page_codes.values[i],
- i == context->page ? MIDI_MAX : 0);
- }
-
- // SHOW PAGE ITEM
- page_item_min = state_config->select_item_codes.length * context->page;
- page_item_max = page_item_min + state_config->select_item_codes.length;
-
- if (context->state.values[context->selected] >= page_item_min &&
- context->state.values[context->selected] < page_item_max) {
- for (unsigned int i = 0; i < state_config->select_item_codes.length; i++) {
- safe_midi_write(midi, state_config->select_item_codes.values[i],
- i == context->state.values[context->selected] -
- page_item_min
- ? MIDI_MAX
- : 0);
- }
- } else {
- for (unsigned int i = 0; i < state_config->select_item_codes.length; i++) {
- safe_midi_write(midi, state_config->select_item_codes.values[i], 0);
- }
- }
-}
-
-static void update_active(const SharedContext *context,
- const StateConfig *state_config,
- const MidiDevice *midi) {
- unsigned int k;
-
- for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
- for (unsigned int j = 0; j < state_config->midi_active_counts.values[i];
- j++) {
- k = state_config->midi_active_offsets.values[i] + j;
- safe_midi_write(midi, state_config->midi_active_codes.values[k],
- context->active[i] == j ? MIDI_MAX : 0);
- }
- }
-}
-
-static void update_values(const SharedContext *context,
- const StateConfig *state_config,
- const MidiDevice *midi) {
- unsigned int j;
- unsigned int k;
- unsigned int part;
-
- for (unsigned int i = 0; i < state_config->midi_codes.length; i++) {
- j = i / 3;
- part = arr_uint_remap_index(state_config->midi_offsets, &j);
- k = state_config->values_offsets.values[part] +
- context->active[part] * state_config->midi_counts.values[part] + j;
- safe_midi_write(midi, state_config->midi_codes.values[i],
- context->values[k][i % 3] * MIDI_MAX);
- }
+ strlcpy(state_config->save_file_prefix,
+ config_file_get_str(config, "SAVE_FILE_PREFIX", "forge_save"),
+ STR_LEN);
}
void state_midi_event(SharedContext *context, const StateConfig *state_config,
@@ -281,39 +441,6 @@ void state_midi_event(SharedContext *context, const StateConfig *state_config,
}
}
-static void reset(SharedContext *context) {
- memset(context->values, 0, sizeof(context->values));
- memset(context->state.values, 0, sizeof(context->state.values));
-}
-
-static void randomize(SharedContext *context, const StateConfig *state_config) {
- unsigned int j;
- unsigned int l;
- unsigned int part;
-
- for (unsigned int i = 0; i < state_config->midi_codes.length; i++) {
- j = i / 3;
- part = arr_uint_remap_index(state_config->midi_offsets, &j);
- for (unsigned int k = 0; k < state_config->midi_active_counts.values[part];
- k++) {
- l = state_config->values_offsets.values[part] +
- k * state_config->midi_counts.values[part] + j;
-
- if (arr_uint_index_of(state_config->fader_codes,
- state_config->midi_codes.values[i]) !=
- ARRAY_NOT_FOUND) {
- context->values[l][i % 3] = (float)rand_uint(MIDI_MAX + 1) / MIDI_MAX;
- } else {
- context->values[l][i % 3] = rand_uint(2) == 1 ? 1 : 0;
- }
- }
- }
-
- for (unsigned int i = 0; i < context->state.length; i++) {
- context->state.values[i] = rand_uint(state_config->state_max);
- }
-}
-
void state_key_event(SharedContext *context, const StateConfig *state_config,
unsigned int code, const MidiDevice *midi) {
if (code == 82) {
@@ -354,6 +481,12 @@ void state_key_event(SharedContext *context, const StateConfig *state_config,
tempo_set(&context->tempo, context->tempo.tempo - 1);
}
log_info("[DOWN] Tempo: %f", context->tempo);
+ } else if (code >= 48 && code <= 57) {
+ log_info("[%d] Loading state %d", code - 48, code - 48);
+ load_from_index_file(context, state_config, code - 48);
+ } else if (code >= 1048 && code <= 1057) {
+ log_info("[%d] Saving state %d", code - 1048, code - 1048);
+ save_to_index_file(context, state_config, code - 1048);
} else {
log_info("[%d] No hotkey defined", code);
}
@@ -414,50 +547,9 @@ bool state_background_write(SharedContext *context,
return false;
}
-static void state_load(SharedContext *context, const StateConfig *state_config,
- const char *state_file) {
- ConfigFile saved_state;
- char key[STR_LEN];
-
- config_file_read(&saved_state, state_file);
-
- tempo_set(&context->tempo,
- config_file_get_int(&saved_state, "tempo", context->tempo.tempo));
- context->page = config_file_get_int(&saved_state, "page", 0);
- context->selected = config_file_get_int(&saved_state, "selected", 0);
-
- for (unsigned int i = 0; i < context->state.length; i++) {
- snprintf(key, STR_LEN, "seed_%d", i);
- context->seeds[i] =
- config_file_get_int(&saved_state, key, context->seeds[i]);
- snprintf(key, STR_LEN, "state_%d", i);
- context->state.values[i] = config_file_get_int(&saved_state, key, 0);
- }
-
- for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
- snprintf(key, STR_LEN, "active_%d", i);
- context->active[i] = config_file_get_int(&saved_state, key, 0);
- }
-
- for (unsigned int i = 0; i < state_config->value_count; i++) {
- snprintf(key, STR_LEN, "value_%d_x", i);
- context->values[i][0] =
- (float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX;
- snprintf(key, STR_LEN, "value_%d_y", i);
- context->values[i][1] =
- (float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX;
- snprintf(key, STR_LEN, "value_%d_z", i);
- context->values[i][2] =
- (float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX;
- }
-
- config_file_free(&saved_state);
-}
-
void state_init(SharedContext *context, const StateConfig *state_config,
bool demo, bool auto_random, unsigned int auto_random_cycles,
- unsigned int base_tempo, const char *state_file,
- bool load_state) {
+ unsigned int base_tempo, bool load_state) {
tempo_init(&context->tempo);
tempo_set(&context->tempo, base_tempo);
context->demo = demo;
@@ -484,44 +576,10 @@ void state_init(SharedContext *context, const StateConfig *state_config,
}
if (load_state) {
- state_load(context, state_config, state_file);
+ load_from_default_file(context, state_config);
}
}
-void state_save(const SharedContext *context, const StateConfig *state_config,
- const char *state_file) {
- StringArray lines;
-
- log_info("Saving state to '%s'...", state_file);
-
- lines.length = 0;
-
- snprintf(lines.values[lines.length++], STR_LEN, "tempo=%d",
- (unsigned int)context->tempo.tempo);
- snprintf(lines.values[lines.length++], STR_LEN, "page=%d", context->page);
- snprintf(lines.values[lines.length++], STR_LEN, "selected=%d",
- context->selected);
-
- for (unsigned int i = 0; i < context->state.length; i++) {
- snprintf(lines.values[lines.length++], STR_LEN, "seed_%d=%d", i,
- context->seeds[i]);
- snprintf(lines.values[lines.length++], STR_LEN, "state_%d=%d", i,
- context->state.values[i]);
- }
-
- for (unsigned int i = 0; i < state_config->midi_active_counts.length; i++) {
- snprintf(lines.values[lines.length++], STR_LEN, "active_%d=%d", i,
- context->active[i]);
- }
-
- for (unsigned int i = 0; i < state_config->value_count; i++) {
- snprintf(lines.values[lines.length++], STR_LEN, "value_%d_x=%d", i,
- (unsigned int)(context->values[i][0] * MIDI_MAX));
- snprintf(lines.values[lines.length++], STR_LEN, "value_%d_y=%d", i,
- (unsigned int)(context->values[i][1] * MIDI_MAX));
- snprintf(lines.values[lines.length++], STR_LEN, "value_%d_z=%d", i,
- (unsigned int)(context->values[i][2] * MIDI_MAX));
- }
-
- file_write(state_file, &lines);
+void state_save(const SharedContext *context, const StateConfig *state_config) {
+ save_to_default_file(context, state_config);
}
diff --git a/src/state.h b/src/state.h
index 438063e..1fae705 100644
--- a/src/state.h
+++ b/src/state.h
@@ -18,10 +18,8 @@ bool state_background_write(SharedContext *context,
void state_init(SharedContext *context, const StateConfig *state_config,
bool demo, bool auto_random, unsigned int auto_random_cycles,
- unsigned int base_tempo, const char *state_file,
- bool load_state);
+ unsigned int base_tempo, bool load_state);
-void state_save(const SharedContext *context, const StateConfig *state_config,
- const char *state_file);
+void state_save(const SharedContext *context, const StateConfig *state_config);
#endif /* STATE_H */
\ No newline at end of file
diff --git a/src/types.h b/src/types.h
index 7867e26..1db22d3 100644
--- a/src/types.h
+++ b/src/types.h
@@ -47,7 +47,6 @@ typedef struct Parameters {
StringArray video_in;
unsigned int video_size;
unsigned int internal_size;
- char state_file[STR_LEN];
bool load_state;
bool save_state;
bool trace_midi;
@@ -213,6 +212,8 @@ typedef struct StateConfig {
unsigned int value_count;
unsigned int tap_tempo_code;
+
+ char save_file_prefix[STR_LEN];
} StateConfig;
// timer.c
@@ -227,6 +228,7 @@ typedef struct Timer {
typedef struct ConfigFile {
struct hashmap *map;
+ bool error;
} ConfigFile;
typedef struct ConfigFileItem {