feat(state): save state on exiting
This commit is contained in:
+2
-1
@@ -23,4 +23,5 @@ configure
|
|||||||
pkg
|
pkg
|
||||||
forge-*
|
forge-*
|
||||||
confdeps.*
|
confdeps.*
|
||||||
conftest.*
|
conftest.*
|
||||||
|
state.txt
|
||||||
@@ -125,7 +125,7 @@ make -f Makefile.dev release-arch
|
|||||||
- [x] Read midi mapping config file
|
- [x] Read midi mapping config file
|
||||||
- [x] Write Midi events
|
- [x] Write Midi events
|
||||||
- [x] Send midi data to shaders
|
- [x] Send midi data to shaders
|
||||||
- [ ] Save midi state
|
- [x] Save midi state
|
||||||
- [ ] Load midi state from last save
|
- [ ] Load midi state from last save
|
||||||
- [x] State machine with A/B switch
|
- [x] State machine with A/B switch
|
||||||
- [x] Tap-tempo feature
|
- [x] Tap-tempo feature
|
||||||
|
|||||||
+10
@@ -22,6 +22,8 @@ static void print_help(int status_code) {
|
|||||||
"[-mo] "
|
"[-mo] "
|
||||||
"[-f=DIR_PATH] "
|
"[-f=DIR_PATH] "
|
||||||
"[-c=CFG_PATH] "
|
"[-c=CFG_PATH] "
|
||||||
|
"[-sf=STATE_PATH] "
|
||||||
|
"[-es] "
|
||||||
"[-is=SIZE] "
|
"[-is=SIZE] "
|
||||||
"[-v=FILE] "
|
"[-v=FILE] "
|
||||||
"[-vs=SIZE] "
|
"[-vs=SIZE] "
|
||||||
@@ -39,6 +41,8 @@ static void print_help(int status_code) {
|
|||||||
" -mo, --monitor-only no output screen\n"
|
" -mo, --monitor-only no output screen\n"
|
||||||
" -f, --frag fragment shaders directory "
|
" -f, --frag fragment shaders directory "
|
||||||
"(default: " DATADIR "/shaders)\n"
|
"(default: " DATADIR "/shaders)\n"
|
||||||
|
" -sf, --state-file state save file (default: state.txt)\n"
|
||||||
|
" -es, --empty-state do not load state save file\n"
|
||||||
" -c, --config fragment shaders config file "
|
" -c, --config fragment shaders config file "
|
||||||
"(default: " DATADIR "/default.cfg)\n"
|
"(default: " DATADIR "/default.cfg)\n"
|
||||||
" -is, --internal-size internal texture height (default: 720)\n"
|
" -is, --internal-size internal texture height (default: 720)\n"
|
||||||
@@ -93,6 +97,8 @@ Parameters args_parse(int argc, char **argv) {
|
|||||||
params.monitor_screen = 0;
|
params.monitor_screen = 0;
|
||||||
params.frag_path = DATADIR "/shaders";
|
params.frag_path = DATADIR "/shaders";
|
||||||
params.config_path = DATADIR "/default.cfg";
|
params.config_path = DATADIR "/default.cfg";
|
||||||
|
params.state_file = "state.txt";
|
||||||
|
params.empty_state = false;
|
||||||
params.internal_size = 720;
|
params.internal_size = 720;
|
||||||
params.video_size = 0;
|
params.video_size = 0;
|
||||||
params.base_tempo = 60.0f;
|
params.base_tempo = 60.0f;
|
||||||
@@ -116,6 +122,10 @@ Parameters args_parse(int argc, char **argv) {
|
|||||||
params.frag_path = value;
|
params.frag_path = value;
|
||||||
} else if (is_arg(arg, "-c") || is_arg(arg, "--config")) {
|
} else if (is_arg(arg, "-c") || is_arg(arg, "--config")) {
|
||||||
params.config_path = value;
|
params.config_path = value;
|
||||||
|
} else if (is_arg(arg, "-sf") || is_arg(arg, "--state-file")) {
|
||||||
|
params.state_file = value;
|
||||||
|
} else if (is_arg(arg, "-es") || is_arg(arg, "--empty-state")) {
|
||||||
|
params.empty_state = true;
|
||||||
} else if (is_arg(arg, "-is") || is_arg(arg, "--internal-size")) {
|
} else if (is_arg(arg, "-is") || is_arg(arg, "--internal-size")) {
|
||||||
params.internal_size = parse_uint(arg, value);
|
params.internal_size = parse_uint(arg, value);
|
||||||
if (params.internal_size == 0) {
|
if (params.internal_size == 0) {
|
||||||
|
|||||||
+22
@@ -75,6 +75,28 @@ File file_read(char *path) {
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void file_write(char *path, ConstStringArray lines) {
|
||||||
|
unsigned int i;
|
||||||
|
FILE *file_pointer;
|
||||||
|
|
||||||
|
log_info("Writing %s...", path);
|
||||||
|
|
||||||
|
// open file
|
||||||
|
file_pointer = fopen(path, "w");
|
||||||
|
if (file_pointer == NULL) {
|
||||||
|
log_warn("Cannot open file '%s'", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write file
|
||||||
|
for (i = 0; i < lines.length; i++) {
|
||||||
|
fprintf(file_pointer, "%s\n", lines.values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// close file
|
||||||
|
fclose(file_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
void file_prepend(File *src, File extra) {
|
void file_prepend(File *src, File extra) {
|
||||||
char *old_src_content;
|
char *old_src_content;
|
||||||
|
|
||||||
|
|||||||
@@ -13,4 +13,6 @@ void file_prepend(File *src, File extra);
|
|||||||
|
|
||||||
void file_free(File *file, bool free_path);
|
void file_free(File *file, bool free_path);
|
||||||
|
|
||||||
|
void file_write(char *path, ConstStringArray lines);
|
||||||
|
|
||||||
#endif /* FILE_H */
|
#endif /* FILE_H */
|
||||||
+4
-1
@@ -58,7 +58,8 @@ static void compute_fps() {
|
|||||||
static void init_context(Parameters params, unsigned int in_count) {
|
static void init_context(Parameters params, unsigned int in_count) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
state_init(context, state_config, params.demo, params.base_tempo);
|
state_init(context, state_config, params.demo, params.base_tempo,
|
||||||
|
params.state_file, params.empty_state);
|
||||||
|
|
||||||
context->monitor = params.monitor;
|
context->monitor = params.monitor;
|
||||||
|
|
||||||
@@ -314,6 +315,8 @@ void forge_run(Parameters params) {
|
|||||||
|
|
||||||
context->stop = true;
|
context->stop = true;
|
||||||
|
|
||||||
|
state_save(context, state_config, params.state_file);
|
||||||
|
|
||||||
shaders_free(program);
|
shaders_free(program);
|
||||||
|
|
||||||
if (window_output != NULL) {
|
if (window_output != NULL) {
|
||||||
|
|||||||
+61
-3
@@ -1,8 +1,10 @@
|
|||||||
#include <log.h>
|
#include <log.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "arr.h"
|
#include "arr.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "config_file.h"
|
#include "config_file.h"
|
||||||
|
#include "file.h"
|
||||||
#include "midi.h"
|
#include "midi.h"
|
||||||
#include "rand.h"
|
#include "rand.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
@@ -317,8 +319,23 @@ bool state_background_midi_write(SharedContext *context,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void state_load(SharedContext *context, StateConfig state_config,
|
||||||
|
char *state_file) {
|
||||||
|
File saved_state;
|
||||||
|
|
||||||
|
saved_state = file_read(state_file);
|
||||||
|
|
||||||
|
if (saved_state.error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO load state
|
||||||
|
|
||||||
|
file_free(&saved_state, false);
|
||||||
|
}
|
||||||
|
|
||||||
void state_init(SharedContext *context, StateConfig state_config, bool demo,
|
void state_init(SharedContext *context, StateConfig state_config, bool demo,
|
||||||
unsigned int base_tempo) {
|
unsigned int base_tempo, char *state_file, bool empty_state) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
context->tempo = tempo_init();
|
context->tempo = tempo_init();
|
||||||
@@ -340,9 +357,13 @@ void state_init(SharedContext *context, StateConfig state_config, bool demo,
|
|||||||
|
|
||||||
memset(context->seeds, 0, sizeof(context->seeds));
|
memset(context->seeds, 0, sizeof(context->seeds));
|
||||||
|
|
||||||
for (i = 0; i < state_config.select_frag_codes.length; i++) {
|
for (i = 0; i < context->state.length; i++) {
|
||||||
context->seeds[i] = rand_uint(1000);
|
context->seeds[i] = rand_uint(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty_state) {
|
||||||
|
state_load(context, state_config, state_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void state_randomize(SharedContext *context, StateConfig state_config) {
|
void state_randomize(SharedContext *context, StateConfig state_config) {
|
||||||
@@ -351,4 +372,41 @@ void state_randomize(SharedContext *context, StateConfig state_config) {
|
|||||||
for (i = 0; i < context->state.length; i++) {
|
for (i = 0; i < context->state.length; i++) {
|
||||||
context->state.values[i] = rand_uint(state_config.state_max);
|
context->state.values[i] = rand_uint(state_config.state_max);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void state_save(SharedContext *context, StateConfig state_config,
|
||||||
|
char *state_file) {
|
||||||
|
ConstStringArray lines;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
log_info("Saving state to '%s'...", state_file);
|
||||||
|
|
||||||
|
lines.length = 0;
|
||||||
|
|
||||||
|
sprintf(lines.values[lines.length++], "tempo=%d",
|
||||||
|
(unsigned int)context->tempo.tempo);
|
||||||
|
sprintf(lines.values[lines.length++], "page=%d", context->page);
|
||||||
|
sprintf(lines.values[lines.length++], "selected=%d", context->selected);
|
||||||
|
|
||||||
|
for (i = 0; i < context->state.length; i++) {
|
||||||
|
sprintf(lines.values[lines.length++], "seed_%d=%d", i, context->seeds[i]);
|
||||||
|
sprintf(lines.values[lines.length++], "state_%d=%d", i,
|
||||||
|
context->state.values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < state_config.midi_active_counts.length; i++) {
|
||||||
|
sprintf(lines.values[lines.length++], "active_%d=%d", i,
|
||||||
|
context->active[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < state_config.midi_codes.length; i++) {
|
||||||
|
sprintf(lines.values[lines.length++], "value_%d_x=%d", i,
|
||||||
|
(unsigned int)(context->values[i][0] * MIDI_MAX));
|
||||||
|
sprintf(lines.values[lines.length++], "value_%d_y=%d", i,
|
||||||
|
(unsigned int)(context->values[i][1] * MIDI_MAX));
|
||||||
|
sprintf(lines.values[lines.length++], "value_%d_z=%d", i,
|
||||||
|
(unsigned int)(context->values[i][2] * MIDI_MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
file_write(state_file, lines);
|
||||||
|
}
|
||||||
|
|||||||
+4
-1
@@ -13,8 +13,11 @@ bool state_background_midi_write(SharedContext *context,
|
|||||||
StateConfig state_config, MidiDevice midi);
|
StateConfig state_config, MidiDevice midi);
|
||||||
|
|
||||||
void state_init(SharedContext *context, StateConfig state_config, bool demo,
|
void state_init(SharedContext *context, StateConfig state_config, bool demo,
|
||||||
unsigned int base_tempo);
|
unsigned int base_tempo, char *state_file, bool empty_state);
|
||||||
|
|
||||||
void state_randomize(SharedContext *context, StateConfig state_config);
|
void state_randomize(SharedContext *context, StateConfig state_config);
|
||||||
|
|
||||||
|
void state_save(SharedContext *context, StateConfig state_config,
|
||||||
|
char *state_file);
|
||||||
|
|
||||||
#endif /* STATE_H */
|
#endif /* STATE_H */
|
||||||
@@ -25,6 +25,11 @@ typedef ARRAY(StringArray, char *);
|
|||||||
typedef ARRAY(Vec3Array, vec3);
|
typedef ARRAY(Vec3Array, vec3);
|
||||||
typedef ARRAY(GLuintArray, GLuint);
|
typedef ARRAY(GLuintArray, GLuint);
|
||||||
|
|
||||||
|
typedef struct ConstStringArray {
|
||||||
|
char values[ARRAY_SIZE][1000];
|
||||||
|
unsigned int length;
|
||||||
|
} ConstStringArray;
|
||||||
|
|
||||||
typedef struct Parameters {
|
typedef struct Parameters {
|
||||||
bool hot_reload;
|
bool hot_reload;
|
||||||
bool output;
|
bool output;
|
||||||
@@ -33,6 +38,8 @@ typedef struct Parameters {
|
|||||||
unsigned int monitor_screen;
|
unsigned int monitor_screen;
|
||||||
char *frag_path;
|
char *frag_path;
|
||||||
char *config_path;
|
char *config_path;
|
||||||
|
char *state_file;
|
||||||
|
bool empty_state;
|
||||||
unsigned int internal_size;
|
unsigned int internal_size;
|
||||||
unsigned int video_size;
|
unsigned int video_size;
|
||||||
float base_tempo;
|
float base_tempo;
|
||||||
|
|||||||
Reference in New Issue
Block a user