diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index aa64524..eead825 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -100,7 +100,7 @@ make -f Makefile.dev release-arch - [x] Define frag prefix in config - [x] Use custom `#include xxx.glsl` preprocessor - [x] Use snprintf isntead of sprintf (and strlcpy instand of strncpy) - - [ ] Pass "heavy" struct as pointer to avoid stack overload + - [x] Pass "heavy" struct as pointer to avoid stack overload - [x] Clean and sort args - [x] `--auto-random` / `--no-auto-random` - [ ] Update readme with usage documentation diff --git a/src/args.c b/src/args.c index 6276872..6dbe2a3 100644 --- a/src/args.c +++ b/src/args.c @@ -100,31 +100,30 @@ static unsigned int parse_uint(char *arg, char *value) { return (unsigned int)tmp_value; } -Parameters args_parse(int argc, char **argv) { - Parameters params; +void args_parse(Parameters *params, int argc, char **argv) { int i; char *arg; char *value; - strlcpy(params.project_path, DATADIR "/default", STR_LEN); - strlcpy(params.config_file, "forge_project.cfg", STR_LEN); - params.hot_reload = false; - params.output = true; - params.output_screen = 0; - params.monitor = false; - params.monitor_screen = 0; - params.windowed = false; - params.base_tempo = 60.0f; - params.demo = false; - params.auto_random = false; - 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; - params.trace_fps = false; + strncpy(params->project_path, DATADIR "/default", STR_LEN); + strncpy(params->config_file, "forge_project.cfg", STR_LEN); + params->hot_reload = false; + params->output = true; + params->output_screen = 0; + params->monitor = false; + params->monitor_screen = 0; + params->windowed = false; + params->base_tempo = 60.0f; + params->demo = false; + params->auto_random = false; + params->video_in.length = 0; + params->video_size = 0; + params->internal_size = 720; + strncpy(params->state_file, "forge_saved_state.txt", STR_LEN); + params->load_state = true; + params->save_state = true; + params->trace_midi = false; + params->trace_fps = false; for (i = 1; i < argc; i++) { arg = argv[i]; @@ -135,76 +134,75 @@ Parameters args_parse(int argc, char **argv) { puts(PACKAGE " " VERSION); exit(EXIT_SUCCESS); } else if (is_arg(arg, "-p") || is_arg(arg, "--project")) { - strlcpy(params.project_path, value, STR_LEN); + strncpy(params->project_path, value, STR_LEN); } else if (is_arg(arg, "-c") || is_arg(arg, "--config")) { - strlcpy(params.config_file, value, STR_LEN); + strncpy(params->config_file, value, STR_LEN); } else if (is_arg(arg, "-hr") || is_arg(arg, "--hot-reload")) { - params.hot_reload = true; + params->hot_reload = true; } else if (is_arg(arg, "-s") || is_arg(arg, "--screen")) { - params.output_screen = parse_uint(arg, value); + params->output_screen = parse_uint(arg, value); } else if (is_arg(arg, "-m") || is_arg(arg, "--monitor")) { - params.monitor = true; - params.monitor_screen = parse_uint(arg, value); + params->monitor = true; + params->monitor_screen = parse_uint(arg, value); } else if (is_arg(arg, "-mo") || is_arg(arg, "--monitor-only")) { - params.output = false; - params.monitor = true; + params->output = false; + params->monitor = true; } else if (is_arg(arg, "-w") || is_arg(arg, "--windowed")) { - params.windowed = true; + params->windowed = true; } else if (is_arg(arg, "-t") || is_arg(arg, "--tempo")) { - params.base_tempo = (float)parse_uint(arg, value); + params->base_tempo = (float)parse_uint(arg, value); } else if (is_arg(arg, "-d") || is_arg(arg, "--demo")) { - params.demo = true; - params.load_state = false; - params.save_state = false; - params.auto_random = true; + params->demo = true; + params->load_state = false; + params->save_state = false; + params->auto_random = true; } else if (is_arg(arg, "-ar") || is_arg(arg, "--auto-random")) { - params.auto_random = true; + params->auto_random = true; } else if (is_arg(arg, "-nar") || is_arg(arg, "--no-auto-random")) { - params.auto_random = false; + params->auto_random = false; } else if (is_arg(arg, "-v") || is_arg(arg, "--video-in")) { - if (params.video_in.length == MAX_VIDEO) { + if (params->video_in.length == MAX_VIDEO) { log_error("maximum video input reached"); exit(EXIT_FAILURE); } - strlcpy(params.video_in.values[params.video_in.length++], value, STR_LEN); + strncpy(params->video_in.values[params->video_in.length++], value, + STR_LEN); } else if (is_arg(arg, "-vs") || is_arg(arg, "--video-size")) { - params.video_size = parse_uint(arg, value); - if (params.video_size == 0) { + params->video_size = parse_uint(arg, value); + if (params->video_size == 0) { invalid_value(arg, value); } } else if (is_arg(arg, "-is") || is_arg(arg, "--internal-size")) { - params.internal_size = parse_uint(arg, value); - if (params.internal_size == 0) { + params->internal_size = parse_uint(arg, value); + 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); + strncpy(params->state_file, value, STR_LEN); } else if (is_arg(arg, "-ls") || is_arg(arg, "--load-state")) { - params.load_state = true; + params->load_state = true; } else if (is_arg(arg, "-nls") || is_arg(arg, "--no-load-state")) { - params.load_state = false; + params->load_state = false; } else if (is_arg(arg, "-ss") || is_arg(arg, "--save-state")) { - params.save_state = true; + params->save_state = true; } else if (is_arg(arg, "-nss") || is_arg(arg, "--no-save-state")) { - params.save_state = false; + params->save_state = false; } else if (is_arg(arg, "-tm") || is_arg(arg, "--trace-midi")) { - params.trace_midi = true; + params->trace_midi = true; } else if (is_arg(arg, "-tf") || is_arg(arg, "--trace-fps")) { - params.trace_fps = true; + params->trace_fps = true; } else { invalid_arg(arg); } } - if (params.monitor && params.output && - params.monitor_screen == params.output_screen && !params.windowed) { + if (params->monitor && params->output && + params->monitor_screen == params->output_screen && !params->windowed) { log_error("monitor screen cannot be the same as output screen"); exit(EXIT_FAILURE); } - if (params.video_size == 0) { - params.video_size = params.internal_size; + if (params->video_size == 0) { + params->video_size = params->internal_size; } - - return params; } \ No newline at end of file diff --git a/src/args.h b/src/args.h index 2d160ba..6f291cd 100644 --- a/src/args.h +++ b/src/args.h @@ -3,6 +3,6 @@ #ifndef ARGS_H #define ARGS_H -Parameters args_parse(int argc, char **argv); +void args_parse(Parameters *params, int argc, char **argv); #endif /* ARGS_H */ \ No newline at end of file diff --git a/src/config_file.c b/src/config_file.c index b15f138..7823894 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -29,7 +29,7 @@ static uint64_t item_hash(const void *item, uint64_t seed0, uint64_t seed1) { return hashmap_sip(c_item->key, strlen(c_item->key), seed0, seed1); } -static void parse_config_file_line(ConfigFile config, char *line) { +static void parse_config_file_line(ConfigFile *config, char *line) { unsigned int size; char *equal_pos; unsigned int key_size; @@ -52,29 +52,28 @@ static void parse_config_file_line(ConfigFile config, char *line) { key_size = equal_pos - line; value_size = size - key_size - 1; - strlcpy(item.key, line, key_size); + strncpy(item.key, line, key_size); item.key[key_size] = '\0'; if (value_size > 0) { - strlcpy(item.value, line + key_size + 1, value_size); + strncpy(item.value, line + key_size + 1, value_size); item.value[value_size] = '\0'; } - hashmap_set(config.map, &item); + hashmap_set(config->map, &item); } -ConfigFile config_file_read(char *path) { +void config_file_read(ConfigFile *config, char *path) { File file; - ConfigFile config; char *line; - config.map = hashmap_new(sizeof(ConfigFileItem), 0, 0, 0, item_hash, - item_compare, NULL, NULL); + config->map = hashmap_new(sizeof(ConfigFileItem), 0, 0, 0, item_hash, + item_compare, NULL, NULL); file = file_read(path); if (file.error) { - return config; + return; } line = strtok(file.content, "\n"); @@ -85,17 +84,15 @@ ConfigFile config_file_read(char *path) { } file_free(&file); - - return config; } -char *config_file_get_str(ConfigFile config, char *key, char *default_value) { +char *config_file_get_str(ConfigFile *config, char *key, char *default_value) { ConfigFileItem c_key; ConfigFileItem *item; - strlcpy(c_key.key, key, STR_LEN); + strncpy(c_key.key, key, STR_LEN); - item = (ConfigFileItem *)hashmap_get(config.map, &c_key); + item = (ConfigFileItem *)hashmap_get(config->map, &c_key); if (item == NULL || strlen(item->value) == 0) { return default_value; @@ -104,14 +101,14 @@ char *config_file_get_str(ConfigFile config, char *key, char *default_value) { return item->value; } -unsigned int config_file_get_int(ConfigFile config, char *key, +unsigned int config_file_get_int(ConfigFile *config, char *key, unsigned int default_value) { ConfigFileItem c_key; ConfigFileItem *item; - strlcpy(c_key.key, key, STR_LEN); + strncpy(c_key.key, key, STR_LEN); - item = (ConfigFileItem *)hashmap_get(config.map, &c_key); + item = (ConfigFileItem *)hashmap_get(config->map, &c_key); if (item == NULL || strlen(item->value) == 0) { return default_value; @@ -125,4 +122,4 @@ unsigned int config_file_get_int(ConfigFile config, char *key, return (unsigned int)atoi(item->value); } -void config_file_free(ConfigFile config) { hashmap_free(config.map); } \ No newline at end of file +void config_file_free(ConfigFile *config) { hashmap_free(config->map); } \ No newline at end of file diff --git a/src/config_file.h b/src/config_file.h index 501929b..e62dea6 100644 --- a/src/config_file.h +++ b/src/config_file.h @@ -3,13 +3,13 @@ #ifndef CONFIG_FILE_H #define CONFIG_FILE_H -ConfigFile config_file_read(char *path); +void config_file_read(ConfigFile *config, char *path); -char *config_file_get_str(ConfigFile config, char *key, char *default_value); +char *config_file_get_str(ConfigFile *config, char *key, char *default_value); -unsigned int config_file_get_int(ConfigFile config, char *key, +unsigned int config_file_get_int(ConfigFile *config, char *key, unsigned int default_value); -void config_file_free(ConfigFile config); +void config_file_free(ConfigFile *config); #endif /* CONFIG_FILE_H */ \ No newline at end of file diff --git a/src/file.c b/src/file.c index db38b0d..ec34855 100644 --- a/src/file.c +++ b/src/file.c @@ -11,16 +11,16 @@ #include "file.h" #include "string.h" -static time_t get_file_time(File file) { +static time_t get_file_time(File *file) { struct stat attr; - if (stat(file.path, &attr) == 0) { + if (stat(file->path, &attr) == 0) { return attr.st_mtim.tv_sec; } return 0; } -bool file_should_update(File file) { - return file.last_write != get_file_time(file); +bool file_should_update(File *file) { + return file->last_write != get_file_time(file); } bool file_update(File *file) { @@ -62,7 +62,7 @@ bool file_update(File *file) { // append null byte file->content[length] = '\0'; // read last update time - file->last_write = get_file_time(*file); + file->last_write = get_file_time(file); return true; } @@ -70,7 +70,7 @@ bool file_update(File *file) { File file_read(char *path) { File file; - strlcpy(file.path, path, STR_LEN); + strncpy(file.path, path, STR_LEN); file.content = NULL; file.error = false; file.last_write = 0; @@ -79,7 +79,7 @@ File file_read(char *path) { return file; } -void file_write(char *path, StringArray lines) { +void file_write(char *path, StringArray *lines) { unsigned int i; FILE *file_pointer; @@ -93,8 +93,8 @@ void file_write(char *path, StringArray lines) { } // write file - for (i = 0; i < lines.length; i++) { - fprintf(file_pointer, "%s\n", lines.values[i]); + for (i = 0; i < lines->length; i++) { + fprintf(file_pointer, "%s\n", lines->values[i]); } // close file @@ -107,11 +107,3 @@ void file_free(File *file) { file->error = true; } } - -void file_free_array(FileArray *files) { - unsigned int i; - - for (i = 0; i < files->length; i++) { - file_free(&files->values[i]); - } -} \ No newline at end of file diff --git a/src/file.h b/src/file.h index c9c373c..95fe96f 100644 --- a/src/file.h +++ b/src/file.h @@ -5,14 +5,12 @@ File file_read(char *path); -bool file_should_update(File file); +bool file_should_update(File *file); bool file_update(File *file); -void file_write(char *path, StringArray lines); +void file_write(char *path, StringArray *lines); void file_free(File *file); -void file_free_array(FileArray *files); - #endif /* FILE_H */ \ No newline at end of file diff --git a/src/forge.c b/src/forge.c index 8cb21c4..21fc154 100644 --- a/src/forge.c +++ b/src/forge.c @@ -57,13 +57,13 @@ static void compute_fps(bool trace_fps) { } } -static void init_context(Parameters params, unsigned int in_count) { +static void init_context(Parameters *params, unsigned int in_count) { unsigned int i; - state_init(context, project.state_config, params.demo, params.auto_random, - params.base_tempo, params.state_file, params.load_state); + state_init(context, &project.state_config, params->demo, params->auto_random, + params->base_tempo, params->state_file, params->load_state); - context->monitor = params.monitor; + context->monitor = params->monitor; memset(context->input_resolutions, 0, sizeof(context->input_resolutions)); memset(context->input_formats, 0, sizeof(context->input_formats)); @@ -81,16 +81,16 @@ static void init_context(Parameters params, unsigned int in_count) { static void free_context() { shared_close_context(context); } static void reload_shader(unsigned int i) { - shaders_update(program, project.fragment_shaders[i][0], i); + shaders_update(&program, &project.fragment_shaders[i][0], i); } -static void init_inputs(StringArray video_in, unsigned int video_size) { +static void init_inputs(StringArray *video_in, unsigned int video_size) { unsigned int i; - inputs.length = video_in.length; + inputs.length = video_in->length; - for (i = 0; i < video_in.length; i++) { - inputs.values[i] = video_init(video_in.values[i], video_size); + for (i = 0; i < video_in->length; i++) { + video_init(&inputs.values[i], video_in->values[i], video_size); } } @@ -99,7 +99,7 @@ static bool start_video_captures(unsigned int video_count, bool trace_fps) { for (i = 0; i < video_count; i++) { if (!inputs.values[i].error && - !video_background_read(&inputs.values[i], context, i, trace_fps)) { + !video_background_read(inputs.values[i], context, i, trace_fps)) { return false; } } @@ -111,9 +111,9 @@ static void free_video_captures(unsigned int video_count) { unsigned int i; for (i = 0; i < video_count; i++) { - shaders_free_input(program, inputs.values[i]); + shaders_free_input(&program, &inputs.values[i]); - video_free(inputs.values[i]); + video_free(&inputs.values[i]); } } @@ -134,7 +134,7 @@ static void key_callback(Window *window, int key, } else if (window_char_key(key, action, 82)) { // R: randomize log_info("[R] Randomizing..."); - state_randomize(context, project.state_config); + state_randomize(context, &project.state_config); } else if (window_char_key(key, action, 68)) { // D: demo on/off log_info((context->demo ? "[D] Demo OFF" : "[D] Demo ON")); @@ -148,7 +148,7 @@ static void key_callback(Window *window, int key, } static void midi_callback(unsigned char code, unsigned char value) { - state_apply_event(context, project.state_config, midi, code, value, + state_apply_event(context, &project.state_config, &midi, code, value, trace_midi); } @@ -160,12 +160,12 @@ static void loop(bool hr, bool trace_fps) { compute_fps(trace_fps); context->time = window_get_time(); - context->tempo_total = (float)tempo_total(context->tempo); + context->tempo_total = (float)tempo_total(&context->tempo); if (window_output != NULL) { window_use(window_output, context); - shaders_compute(program, context, false, false); + shaders_compute(&program, context, false, false); window_refresh(window_output); } @@ -173,7 +173,7 @@ static void loop(bool hr, bool trace_fps) { if (window_monitor != NULL) { window_use(window_monitor, context); - shaders_compute(program, context, true, window_output != NULL); + shaders_compute(&program, context, true, window_output != NULL); window_refresh(window_monitor); } @@ -181,31 +181,31 @@ static void loop(bool hr, bool trace_fps) { window_events(); } -void forge_run(Parameters params) { +void forge_run(Parameters *params) { context = shared_init_context("/" PACKAGE "_context"); context->stop = false; - project_init(&project, params.project_path, params.config_file); + project_init(&project, params->project_path, params->config_file); if (project.error) { return; } - init_inputs(params.video_in, params.video_size); + init_inputs(¶ms->video_in, params->video_size); init_context(params, project.in_count); - if (!start_video_captures(params.video_in.length, params.trace_fps)) { + if (!start_video_captures(params->video_in.length, params->trace_fps)) { return; } - midi = midi_open(config_file_get_str(project.config, "MIDI_HW", "hw")); + midi_open(&midi, config_file_get_str(&project.config, "MIDI_HW", "hw")); if (midi.error) { - params.demo = true; + params->demo = true; } else { - trace_midi = params.trace_midi; + trace_midi = params->trace_midi; if (!midi_background_listen(midi, context, midi_callback)) { return; @@ -218,27 +218,27 @@ void forge_run(Parameters params) { window_startup(error_callback); - context->tex_resolution[1] = params.internal_size; + context->tex_resolution[1] = params->internal_size; - if (params.output) { - window_output = window_init(PACKAGE " " VERSION, params.output_screen, - params.windowed, NULL, key_callback); + if (params->output) { + window_output = window_init(PACKAGE " " VERSION, params->output_screen, + params->windowed, NULL, key_callback); window_use(window_output, context); - shaders_init(&program, &project, context, inputs, false); + shaders_init(&program, &project, context, &inputs, false); } else { window_output = NULL; } - if (params.monitor) { + if (params->monitor) { window_monitor = - window_init(PACKAGE " " VERSION " (monitor)", params.monitor_screen, - params.windowed, window_output, key_callback); + window_init(PACKAGE " " VERSION " (monitor)", params->monitor_screen, + params->windowed, window_output, key_callback); window_use(window_monitor, context); - shaders_init(&program, &project, context, inputs, window_output != NULL); + shaders_init(&program, &project, context, &inputs, window_output != NULL); } else { window_monitor = NULL; } @@ -249,36 +249,36 @@ void forge_run(Parameters params) { exit(EXIT_FAILURE); } - timer = timer_init(30); + timer_init(&timer, 30); log_info("Initialized"); while ((window_output == NULL || !window_should_close(window_output)) && (window_monitor == NULL || !window_should_close(window_monitor))) { - loop(params.hot_reload, params.trace_fps); + loop(params->hot_reload, params->trace_fps); } context->stop = true; - if (params.save_state) { - state_save(context, project.state_config, params.state_file); + if (params->save_state) { + state_save(context, &project.state_config, params->state_file); } - shaders_free(program); + shaders_free(&program); if (window_output != NULL) { window_use(window_output, context); - shaders_free_window(program, false); + shaders_free_window(&program, false); } if (window_monitor != NULL) { window_use(window_monitor, context); - shaders_free_window(program, params.output); + shaders_free_window(&program, params->output); } - free_video_captures(params.video_in.length); + free_video_captures(params->video_in.length); free_context(); diff --git a/src/forge.h b/src/forge.h index 7d07457..b439d9e 100644 --- a/src/forge.h +++ b/src/forge.h @@ -3,6 +3,6 @@ #ifndef FORGE_H #define FORGE_H -void forge_run(Parameters params); +void forge_run(Parameters *params); #endif /* FORGE_H */ \ No newline at end of file diff --git a/src/main.c b/src/main.c index 4dcf122..dc3d93a 100644 --- a/src/main.c +++ b/src/main.c @@ -13,13 +13,13 @@ int main(int argc, char **argv) { Parameters params; - params = args_parse(argc, argv); + args_parse(¶ms, argc, argv); puts(PACKAGE " " VERSION); set_seed((unsigned long)time(NULL)); - forge_run(params); + forge_run(¶ms); return EXIT_SUCCESS; } diff --git a/src/midi.c b/src/midi.c index 03e8fcb..167b2d8 100644 --- a/src/midi.c +++ b/src/midi.c @@ -6,30 +6,26 @@ #include "config.h" #include "log.h" -MidiDevice midi_open(char *name) { - MidiDevice device; +void midi_open(MidiDevice *device, char *name) { + strncpy(device->name, name, STR_LEN); + device->input = NULL; + device->output = NULL; - strlcpy(device.name, name, STR_LEN); - device.input = NULL; - device.output = NULL; + snd_rawmidi_open(&device->input, &device->output, name, SND_RAWMIDI_NONBLOCK); - snd_rawmidi_open(&device.input, &device.output, name, SND_RAWMIDI_NONBLOCK); - - device.error = device.input == NULL || device.output == NULL; + device->error = device->input == NULL || device->output == NULL; log_info("(%s) MIDI open", name); - - return device; } -void midi_write(MidiDevice device, unsigned char code, unsigned char value) { +void midi_write(MidiDevice *device, unsigned char code, unsigned char value) { unsigned char buffer[3]; buffer[0] = 0xB0; buffer[1] = code; buffer[2] = value; - snd_rawmidi_write(device.output, buffer, 3); + snd_rawmidi_write(device->output, buffer, 3); } bool midi_background_listen(MidiDevice device, SharedContext *context, diff --git a/src/midi.h b/src/midi.h index 4db1420..7a9569c 100644 --- a/src/midi.h +++ b/src/midi.h @@ -3,8 +3,8 @@ #ifndef MIDI_H #define MIDI_H -MidiDevice midi_open(char *name); -void midi_write(MidiDevice device, unsigned char code, unsigned char value); +void midi_open(MidiDevice *device, char *name); +void midi_write(MidiDevice *device, unsigned char code, unsigned char value); bool midi_background_listen(MidiDevice device, SharedContext *context, void (*event_callback)(unsigned char code, unsigned char value)); diff --git a/src/project.c b/src/project.c index a64a83f..53c7546 100644 --- a/src/project.c +++ b/src/project.c @@ -77,18 +77,19 @@ void project_init(Project *project, char *project_path, char *config_file) { char *frag_prefix; unsigned int i; - strlcpy(project->path, project_path, STR_LEN); + strncpy(project->path, project_path, STR_LEN); snprintf(config_path, STR_LEN, "%s/%s", project_path, config_file); - project->config = config_file_read(config_path); + config_file_read(&project->config, config_path); - project->state_config = state_parse_config(project->config); + state_parse_config(&project->state_config, &project->config); - project->frag_count = config_file_get_int(project->config, "FRAG_COUNT", 1); - project->in_count = config_file_get_int(project->config, "IN_COUNT", 0); + project->frag_count = config_file_get_int(&project->config, "FRAG_COUNT", 1); + + project->in_count = config_file_get_int(&project->config, "IN_COUNT", 0); frag_prefix = - config_file_get_str(project->config, "FRAG_FILE_PREFIX", "frag"); + config_file_get_str(&project->config, "FRAG_FILE_PREFIX", "frag"); if (project->frag_count > MAX_FRAG) { log_error("FRAG_COUNT over %d", MAX_FRAG); @@ -113,11 +114,11 @@ void project_reload(Project *project, void (*reload_callback)(unsigned int)) { bool should_update; for (i = 0; i < project->frag_count; i++) { - should_update = file_should_update(project->fragment_shaders[i][0]); + should_update = file_should_update(&project->fragment_shaders[i][0]); for (j = 0; j < project->sub_counts.values[i]; j++) { should_update = should_update || - file_should_update(project->fragment_shaders[i][j + 1]); + file_should_update(&project->fragment_shaders[i][j + 1]); } should_update = @@ -138,5 +139,5 @@ void project_free(Project *project) { file_free(&project->fragment_shaders[i][0]); } - config_file_free(project->config); + config_file_free(&project->config); } \ No newline at end of file diff --git a/src/shaders.c b/src/shaders.c index bb5d4d8..1ab2805 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -112,24 +112,24 @@ static void link_input_to_texture(ShaderProgram *program, VideoCapture *input, log_info("Texture %d linked to %s", texture_index, input->name); } -static void init_input(ShaderProgram *program, ConfigFile config, - VideoCaptureArray inputs) { +static void init_input(ShaderProgram *program, ConfigFile *config, + VideoCaptureArray *inputs) { unsigned int i; unsigned tex_i; char name[STR_LEN]; for (i = 0; i < program->in_count; i++) { - if (i < inputs.length && !inputs.values[i].error) { + if (i < inputs->length && !inputs->values[i].error) { snprintf(name, STR_LEN, "IN_%d_OUT", i + 1); tex_i = config_file_get_int(config, name, 0); - link_input_to_texture(program, &inputs.values[i], tex_i); + link_input_to_texture(program, &inputs->values[i], tex_i); } else { log_warn("Cannot link input %d", i + 1); } } } -static void init_framebuffers(ShaderProgram *program, ConfigFile config) { +static void init_framebuffers(ShaderProgram *program, ConfigFile *config) { unsigned int i; unsigned tex_i; char name[STR_LEN]; @@ -235,7 +235,7 @@ static void init_shaders(ShaderProgram *program, Project *project) { } static void init_single_program(ShaderProgram *program, unsigned int i, - ConfigFile config, StateConfig state_config) { + ConfigFile *config, StateConfig *state_config) { unsigned int j, k, index1, index2; char name[STR_LEN]; char *prefix; @@ -334,10 +334,10 @@ static void init_single_program(ShaderProgram *program, unsigned int i, if (program->midi_lengths.length == 0) { index1 = 0; - for (j = 0; j < state_config.midi_active_counts.length; j++) { - for (k = 0; k < state_config.midi_active_counts.values[j]; k++) { + for (j = 0; j < state_config->midi_active_counts.length; j++) { + for (k = 0; k < state_config->midi_active_counts.values[j]; k++) { program->midi_lengths.values[index1++] = - state_config.midi_counts.values[j]; + state_config->midi_counts.values[j]; } } program->midi_lengths.length = index1; @@ -345,8 +345,8 @@ static void init_single_program(ShaderProgram *program, unsigned int i, prefix = config_file_get_str(config, "UNIFORM_MIDI_PREFIX", "iMidi"); index2 = 0; - for (j = 0; j < state_config.midi_active_counts.length; j++) { - for (k = 0; k < state_config.midi_active_counts.values[j]; k++) { + for (j = 0; j < state_config->midi_active_counts.length; j++) { + for (k = 0; k < state_config->midi_active_counts.values[j]; k++) { snprintf(name, STR_LEN, "%s%d_%d", prefix, j + 1, k + 1); program->imidi_locations[i * program->midi_lengths.length + index2++] = glGetUniformLocation(program->programs[i], name); @@ -368,8 +368,8 @@ static void init_single_program(ShaderProgram *program, unsigned int i, log_info("Program %d initialized", i + 1); } -static void init_programs(ShaderProgram *program, ConfigFile config, - StateConfig state_config) { +static void init_programs(ShaderProgram *program, ConfigFile *config, + StateConfig *state_config) { unsigned int i; for (i = 0; i < program->frag_count; i++) { @@ -378,21 +378,21 @@ static void init_programs(ShaderProgram *program, ConfigFile config, } void shaders_init(ShaderProgram *program, Project *project, - SharedContext *context, VideoCaptureArray inputs, + SharedContext *context, VideoCaptureArray *inputs, bool rebind) { if (!rebind) { program->error = false; program->last_resolution[0] = context->resolution[0]; program->last_resolution[1] = context->resolution[1]; - program->tex_count = config_file_get_int(project->config, "TEX_COUNT", 9); + program->tex_count = config_file_get_int(&project->config, "TEX_COUNT", 9); program->frag_count = project->frag_count; program->frag_output_index = - config_file_get_int(project->config, "FRAG_OUTPUT", 1) - 1; + config_file_get_int(&project->config, "FRAG_OUTPUT", 1) - 1; program->frag_monitor_index = - config_file_get_int(project->config, "FRAG_MONITOR", 1) - 1; + config_file_get_int(&project->config, "FRAG_MONITOR", 1) - 1; program->sub_type_count = - config_file_get_int(project->config, "SUB_TYPE_COUNT", 0); - program->in_count = config_file_get_int(project->config, "IN_COUNT", 0); + config_file_get_int(&project->config, "SUB_TYPE_COUNT", 0); + program->in_count = config_file_get_int(&project->config, "IN_COUNT", 0); program->sub_variant_count = project->state_config.state_max; program->active_count = project->state_config.midi_active_counts.length; program->midi_lengths.length = 0; @@ -407,11 +407,11 @@ void shaders_init(ShaderProgram *program, Project *project, init_textures(program, context); - init_input(program, project->config, inputs); + init_input(program, &project->config, inputs); - init_framebuffers(program, project->config); + init_framebuffers(program, &project->config); - init_programs(program, project->config, project->state_config); + init_programs(program, &project->config, &project->state_config); init_vertices(program); @@ -423,28 +423,28 @@ void shaders_init(ShaderProgram *program, Project *project, ; } -void shaders_update(ShaderProgram program, File fragment_shader, +void shaders_update(ShaderProgram *program, File *fragment_shader, unsigned int i) { bool result; - result = compile_shader(program.fragment_shaders[i], fragment_shader.path, - fragment_shader.content); + result = compile_shader(program->fragment_shaders[i], fragment_shader->path, + fragment_shader->content); if (result) { - glLinkProgram(program.programs[i]); + glLinkProgram(program->programs[i]); log_info("Program %d updated", i + 1); } } -static void update_viewport(ShaderProgram program, SharedContext *context) { +static void update_viewport(ShaderProgram *program, SharedContext *context) { unsigned int i; // viewport changed - if (context->resolution[0] != program.last_resolution[0] || - context->resolution[1] != program.last_resolution[1]) { + if (context->resolution[0] != program->last_resolution[0] || + context->resolution[1] != program->last_resolution[1]) { // clean and resize all textures - for (i = 0; i < program.tex_count; i++) { + for (i = 0; i < program->tex_count; i++) { glActiveTexture(GL_TEXTURE0 + i); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, context->tex_resolution[0], context->tex_resolution[1], 0, GL_RGB, GL_UNSIGNED_BYTE, 0); @@ -477,12 +477,12 @@ static void write_uniform_multi_3f(GLuint location, unsigned int count, } } -static void use_program(ShaderProgram program, int i, bool output, +static void use_program(ShaderProgram *program, int i, bool output, SharedContext *context) { unsigned int j, k, offset; GLuint subroutines[ARRAY_SIZE]; // use specific shader program - glUseProgram(program.programs[i]); + glUseProgram(program->programs[i]); if (output) { glViewport(0, 0, context->resolution[0], context->resolution[1]); @@ -496,118 +496,120 @@ static void use_program(ShaderProgram program, int i, bool output, glViewport(0, 0, context->tex_resolution[0], context->tex_resolution[1]); // use memory framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, program.frame_buffers[i]); + glBindFramebuffer(GL_FRAMEBUFFER, program->frame_buffers[i]); glDrawBuffer(GL_COLOR_ATTACHMENT0); } // set fragment uniforms - write_uniform_1f(program.itime_locations[i], context->time); - write_uniform_1f(program.itempo_locations[i], context->tempo.tempo); - write_uniform_1f(program.ibeats_locations[i], context->tempo_total); - write_uniform_1i(program.ifps_locations[i], context->fps); - write_uniform_1i(program.idemo_locations[i], context->demo ? 1 : 0); - write_uniform_1i(program.iautorand_locations[i], + write_uniform_1f(program->itime_locations[i], context->time); + write_uniform_1f(program->itempo_locations[i], context->tempo.tempo); + write_uniform_1f(program->ibeats_locations[i], context->tempo_total); + write_uniform_1i(program->ifps_locations[i], context->fps); + write_uniform_1i(program->idemo_locations[i], context->demo ? 1 : 0); + write_uniform_1i(program->iautorand_locations[i], context->auto_random ? 1 : 0); - write_uniform_1i(program.ipage_locations[i], context->page); - write_uniform_1i(program.iselected_locations[i], context->selected + 1); - write_uniform_2f(program.ires_locations[i], &context->resolution); - write_uniform_2f(program.itexres_locations[i], &context->tex_resolution); + write_uniform_1i(program->ipage_locations[i], context->page); + write_uniform_1i(program->iselected_locations[i], context->selected + 1); + write_uniform_2f(program->ires_locations[i], &context->resolution); + write_uniform_2f(program->itexres_locations[i], &context->tex_resolution); - for (j = 0; j < program.active_count; j++) { - write_uniform_1i(program.iactive_locations[i * program.active_count + j], + for (j = 0; j < program->active_count; j++) { + write_uniform_1i(program->iactive_locations[i * program->active_count + j], context->active[j] + 1); } - for (j = 0; j < program.in_count; j++) { - write_uniform_2f(program.iinres_locations[i * program.in_count + j], + for (j = 0; j < program->in_count; j++) { + write_uniform_2f(program->iinres_locations[i * program->in_count + j], &context->input_resolutions[j]); - write_uniform_1i(program.iinfmt_locations[i * program.in_count + j], + write_uniform_1i(program->iinfmt_locations[i * program->in_count + j], context->input_formats[j]); - write_uniform_1i(program.iinfps_locations[i * program.in_count + j], + write_uniform_1i(program->iinfps_locations[i * program->in_count + j], context->input_fps[j]); } // set seeds uniforms - for (j = 0; j < program.frag_count; j++) { - write_uniform_1i(program.iseed_locations[i * program.frag_count + j], + for (j = 0; j < program->frag_count; j++) { + write_uniform_1i(program->iseed_locations[i * program->frag_count + j], context->seeds[j]); } - for (j = 0; j < program.frag_count; j++) { - write_uniform_1i(program.istate_locations[i * program.frag_count + j], + for (j = 0; j < program->frag_count; j++) { + write_uniform_1i(program->istate_locations[i * program->frag_count + j], context->state.values[j] + 1); } offset = 0; - for (j = 0; j < program.midi_lengths.length; j++) { + for (j = 0; j < program->midi_lengths.length; j++) { write_uniform_multi_3f( - program.imidi_locations[i * program.midi_lengths.length + j], - program.midi_lengths.values[j], context->values + offset); - offset += program.midi_lengths.values[j]; + program->imidi_locations[i * program->midi_lengths.length + j], + program->midi_lengths.values[j], context->values + offset); + offset += program->midi_lengths.values[j]; } // set subroutines for fragment and update state uniforms k = context->state.values[i]; - for (j = 0; j < program.sub_type_count; j++) { - subroutines[j] = program.sub_locations[i * program.sub_type_count * - program.sub_variant_count + - j * program.sub_variant_count + k]; + for (j = 0; j < program->sub_type_count; j++) { + subroutines[j] = program->sub_locations[i * program->sub_type_count * + program->sub_variant_count + + j * program->sub_variant_count + k]; } - glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, program.sub_type_count, + glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, program->sub_type_count, subroutines); // set GL_TEXTURE(X) to uniform sampler2D texX - for (j = 0; j < program.tex_count; j++) { - write_uniform_1i(program.textures_locations[i * program.tex_count + j], j); + for (j = 0; j < program->tex_count; j++) { + write_uniform_1i(program->textures_locations[i * program->tex_count + j], + j); } // draw output glDrawArrays(GL_TRIANGLES, 0, 6); } -void shaders_compute(ShaderProgram program, SharedContext *context, +void shaders_compute(ShaderProgram *program, SharedContext *context, bool monitor, bool output_only) { unsigned int i; if (!output_only) { - glBindVertexArray(program.vertex_array[0]); + glBindVertexArray(program->vertex_array[0]); update_viewport(program, context); - for (i = 0; i < program.frag_count; i++) { - if (i != program.frag_output_index && i != program.frag_monitor_index) { + for (i = 0; i < program->frag_count; i++) { + if (i != program->frag_output_index && i != program->frag_monitor_index) { use_program(program, i, false, context); } } } else { - glBindVertexArray(program.vertex_array[1]); + glBindVertexArray(program->vertex_array[1]); - rebind_textures(&program); + rebind_textures(program); } use_program(program, - monitor ? program.frag_monitor_index : program.frag_output_index, + monitor ? program->frag_monitor_index + : program->frag_output_index, true, context); } -void shaders_free(ShaderProgram program) { +void shaders_free(ShaderProgram *program) { unsigned int i; - for (i = 0; i < program.frag_count; i++) { - glDeleteProgram(program.programs[i]); + for (i = 0; i < program->frag_count; i++) { + glDeleteProgram(program->programs[i]); } - glDeleteFramebuffers(program.frag_count, program.frame_buffers); - glDeleteTextures(program.tex_count, program.textures); - glDeleteBuffers(1, &program.vertex_buffer); + glDeleteFramebuffers(program->frag_count, program->frame_buffers); + glDeleteTextures(program->tex_count, program->textures); + glDeleteBuffers(1, &program->vertex_buffer); } -void shaders_free_window(ShaderProgram program, bool secondary) { - glDeleteVertexArrays(1, &program.vertex_array[secondary ? 1 : 0]); +void shaders_free_window(ShaderProgram *program, bool secondary) { + glDeleteVertexArrays(1, &program->vertex_array[secondary ? 1 : 0]); } -void shaders_free_input(ShaderProgram program, VideoCapture input) { - if (!input.error && input.dma_image != EGL_NO_IMAGE_KHR) { - eglDestroyImageKHR(program.egl_display, input.dma_image); +void shaders_free_input(ShaderProgram *program, VideoCapture *input) { + if (!input->error && input->dma_image != EGL_NO_IMAGE_KHR) { + eglDestroyImageKHR(program->egl_display, input->dma_image); } } \ No newline at end of file diff --git a/src/shaders.h b/src/shaders.h index fc2cb63..317b460 100644 --- a/src/shaders.h +++ b/src/shaders.h @@ -4,19 +4,19 @@ #define SHADERS_H void shaders_init(ShaderProgram *program, Project *project, - SharedContext *context, VideoCaptureArray inputs, + SharedContext *context, VideoCaptureArray *inputs, bool rebind); -void shaders_update(ShaderProgram program, File fragment_shader, +void shaders_update(ShaderProgram *program, File *fragment_shader, unsigned int i); -void shaders_compute(ShaderProgram program, SharedContext *context, +void shaders_compute(ShaderProgram *program, SharedContext *context, bool monitor, bool output_only); -void shaders_free(ShaderProgram program); +void shaders_free(ShaderProgram *program); -void shaders_free_window(ShaderProgram program, bool secondary); +void shaders_free_window(ShaderProgram *program, bool secondary); -void shaders_free_input(ShaderProgram program, VideoCapture input); +void shaders_free_input(ShaderProgram *program, VideoCapture *input); #endif /* SHADERS_H */ \ No newline at end of file diff --git a/src/state.c b/src/state.c index 485a3ce..a18cd73 100644 --- a/src/state.c +++ b/src/state.c @@ -12,186 +12,183 @@ #include "state.h" #include "tempo.h" -StateConfig state_parse_config(ConfigFile config) { +void state_parse_config(StateConfig *state_config, ConfigFile *config) { unsigned int i, j, offset, count; - StateConfig state_config; char name[STR_LEN]; - state_config.select_page_codes.length = + state_config->select_page_codes.length = config_file_get_int(config, "SELECT_PAGE_COUNT", 0); - for (i = 0; i < state_config.select_page_codes.length; i++) { + for (i = 0; i < state_config->select_page_codes.length; i++) { snprintf(name, STR_LEN, "SELECT_PAGE_%d", i + 1); - state_config.select_page_codes.values[i] = + state_config->select_page_codes.values[i] = config_file_get_int(config, name, UNSET_MIDI_CODE); } - state_config.select_item_codes.length = + state_config->select_item_codes.length = config_file_get_int(config, "SELECT_ITEM_COUNT", 0); - for (i = 0; i < state_config.select_item_codes.length; i++) { + for (i = 0; i < state_config->select_item_codes.length; i++) { snprintf(name, STR_LEN, "SELECT_ITEM_%d", i + 1); - state_config.select_item_codes.values[i] = + state_config->select_item_codes.values[i] = config_file_get_int(config, name, UNSET_MIDI_CODE); } - state_config.state_max = state_config.select_page_codes.length * - state_config.select_item_codes.length; + state_config->state_max = state_config->select_page_codes.length * + state_config->select_item_codes.length; - state_config.select_frag_codes.length = + state_config->select_frag_codes.length = config_file_get_int(config, "FRAG_COUNT", 1); - for (i = 0; i < state_config.select_frag_codes.length; i++) { + for (i = 0; i < state_config->select_frag_codes.length; i++) { snprintf(name, STR_LEN, "SELECT_FRAG_%d", i + 1); - state_config.select_frag_codes.values[i] = + state_config->select_frag_codes.values[i] = config_file_get_int(config, name, UNSET_MIDI_CODE); } - state_config.midi_active_counts.length = state_config.midi_counts.length = - state_config.midi_active_offsets.length = - state_config.midi_offsets.length = - state_config.values_offsets.length = + state_config->midi_active_counts.length = state_config->midi_counts.length = + state_config->midi_active_offsets.length = + state_config->midi_offsets.length = + state_config->values_offsets.length = config_file_get_int(config, "MIDI_COUNT", 0); count = 0; - for (i = 0; i < state_config.midi_active_counts.length; i++) { + for (i = 0; i < state_config->midi_active_counts.length; i++) { snprintf(name, STR_LEN, "MIDI_%d_ACTIVE_COUNT", i + 1); - state_config.midi_active_counts.values[i] = + state_config->midi_active_counts.values[i] = config_file_get_int(config, name, 1); - state_config.midi_active_offsets.values[i] = count; - count += state_config.midi_active_counts.values[i]; + state_config->midi_active_offsets.values[i] = count; + count += state_config->midi_active_counts.values[i]; } - state_config.midi_active_codes.length = count; + state_config->midi_active_codes.length = count; - for (i = 0; i < state_config.midi_active_counts.length; i++) { - for (j = 0; j < state_config.midi_active_counts.values[i]; j++) { + for (i = 0; i < state_config->midi_active_counts.length; i++) { + for (j = 0; j < state_config->midi_active_counts.values[i]; j++) { snprintf(name, STR_LEN, "MIDI_%d_ACTIVE_%d", i + 1, j + 1); - state_config.midi_active_codes - .values[state_config.midi_active_offsets.values[i] + j] = + state_config->midi_active_codes + .values[state_config->midi_active_offsets.values[i] + j] = config_file_get_int(config, name, UNSET_MIDI_CODE); } } count = 0; offset = 0; - for (i = 0; i < state_config.midi_counts.length; i++) { + for (i = 0; i < state_config->midi_counts.length; i++) { snprintf(name, STR_LEN, "MIDI_%d_COUNT", i + 1); - state_config.midi_counts.values[i] = config_file_get_int(config, name, 0); - state_config.midi_offsets.values[i] = count; - state_config.values_offsets.values[i] = offset; - offset += state_config.midi_counts.values[i] * - state_config.midi_active_counts.values[i]; - count += state_config.midi_counts.values[i]; + state_config->midi_counts.values[i] = config_file_get_int(config, name, 0); + state_config->midi_offsets.values[i] = count; + state_config->values_offsets.values[i] = offset; + offset += state_config->midi_counts.values[i] * + state_config->midi_active_counts.values[i]; + count += state_config->midi_counts.values[i]; } - state_config.midi_codes.length = count * 3; + state_config->midi_codes.length = count * 3; - for (i = 0; i < state_config.midi_counts.length; i++) { - offset = state_config.midi_offsets.values[i]; - for (j = 0; j < state_config.midi_counts.values[i]; j++) { + for (i = 0; i < state_config->midi_counts.length; i++) { + offset = state_config->midi_offsets.values[i]; + for (j = 0; j < state_config->midi_counts.values[i]; j++) { snprintf(name, STR_LEN, "MIDI_%d_%d_X", i + 1, j + 1); - state_config.midi_codes.values[(offset + j) * 3] = + state_config->midi_codes.values[(offset + j) * 3] = config_file_get_int(config, name, UNSET_MIDI_CODE); snprintf(name, STR_LEN, "MIDI_%d_%d_Y", i + 1, j + 1); - state_config.midi_codes.values[(offset + j) * 3 + 1] = + state_config->midi_codes.values[(offset + j) * 3 + 1] = config_file_get_int(config, name, UNSET_MIDI_CODE); snprintf(name, STR_LEN, "MIDI_%d_%d_Z", i + 1, j + 1); - state_config.midi_codes.values[(offset + j) * 3 + 2] = + state_config->midi_codes.values[(offset + j) * 3 + 2] = config_file_get_int(config, name, UNSET_MIDI_CODE); } } - state_config.fader_codes.length = + state_config->fader_codes.length = config_file_get_int(config, "FADER_COUNT", 0); - for (i = 0; i < state_config.fader_codes.length; i++) { + for (i = 0; i < state_config->fader_codes.length; i++) { snprintf(name, STR_LEN, "FADER_%d", i + 1); - state_config.fader_codes.values[i] = + state_config->fader_codes.values[i] = config_file_get_int(config, name, UNSET_MIDI_CODE); } - state_config.tap_tempo_code = + state_config->tap_tempo_code = config_file_get_int(config, "TAP_TEMPO", UNSET_MIDI_CODE); - - return state_config; } -static void safe_midi_write(MidiDevice midi, unsigned int code, +static void safe_midi_write(MidiDevice *midi, unsigned int code, unsigned char value) { if (code != UNSET_MIDI_CODE) { midi_write(midi, code, value); } } -static void update_page(SharedContext *context, StateConfig state_config, - MidiDevice midi) { +static void update_page(SharedContext *context, StateConfig *state_config, + MidiDevice *midi) { unsigned int i, page_item_min, page_item_max; // SHOW PAGE - for (i = 0; i < state_config.select_page_codes.length; i++) { - safe_midi_write(midi, state_config.select_page_codes.values[i], + for (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; + 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 (i = 0; i < state_config.select_item_codes.length; i++) { - safe_midi_write(midi, state_config.select_item_codes.values[i], + for (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 (i = 0; i < state_config.select_item_codes.length; i++) { - safe_midi_write(midi, state_config.select_item_codes.values[i], 0); + for (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(SharedContext *context, StateConfig state_config, - MidiDevice midi) { +static void update_active(SharedContext *context, StateConfig *state_config, + MidiDevice *midi) { unsigned int i, j, k; - for (i = 0; i < state_config.midi_active_counts.length; i++) { - for (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], + for (i = 0; i < state_config->midi_active_counts.length; i++) { + for (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(SharedContext *context, StateConfig state_config, - MidiDevice midi) { +static void update_values(SharedContext *context, StateConfig *state_config, + MidiDevice *midi) { unsigned int i, j, k, part; - for (i = 0; i < state_config.midi_codes.length; i++) { + for (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], + 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); } } -void state_apply_event(SharedContext *context, StateConfig state_config, - MidiDevice midi, unsigned char code, unsigned char value, - bool trace_midi) { +void state_apply_event(SharedContext *context, StateConfig *state_config, + MidiDevice *midi, unsigned char code, + unsigned char value, bool trace_midi) { unsigned int i, j, k, part; bool found; found = false; // PAGE CHANGE - i = arr_uint_index_of(state_config.select_page_codes, code); + i = arr_uint_index_of(state_config->select_page_codes, code); if (i != ARRAY_NOT_FOUND) { found = true; if (value > 0) { @@ -201,7 +198,7 @@ void state_apply_event(SharedContext *context, StateConfig state_config, } // TARGET CHANGE - i = arr_uint_index_of(state_config.select_frag_codes, code); + i = arr_uint_index_of(state_config->select_frag_codes, code); if (i != ARRAY_NOT_FOUND) { found = true; if (value > 0) { @@ -211,22 +208,22 @@ void state_apply_event(SharedContext *context, StateConfig state_config, } // ITEM CHANGE - i = arr_uint_index_of(state_config.select_item_codes, code); + i = arr_uint_index_of(state_config->select_item_codes, code); if (i != ARRAY_NOT_FOUND) { found = true; if (value > 0) { context->state.values[context->selected] = - context->page * state_config.select_item_codes.length + i; + context->page * state_config->select_item_codes.length + i; update_page(context, state_config, midi); } } // ACTIVE CHANGE - i = arr_uint_index_of(state_config.midi_active_codes, code); + i = arr_uint_index_of(state_config->midi_active_codes, code); if (i != ARRAY_NOT_FOUND) { found = true; if (value > 0) { - part = arr_uint_remap_index(state_config.midi_active_offsets, &i); + part = arr_uint_remap_index(state_config->midi_active_offsets, &i); context->active[part] = i; update_active(context, state_config, midi); update_values(context, state_config, midi); @@ -234,15 +231,15 @@ void state_apply_event(SharedContext *context, StateConfig state_config, } // VALUE CHANGE - i = arr_uint_index_of(state_config.midi_codes, code); + i = arr_uint_index_of(state_config->midi_codes, code); if (i != ARRAY_NOT_FOUND) { found = true; 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; + 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; - if (arr_uint_index_of(state_config.fader_codes, code) != ARRAY_NOT_FOUND) { + if (arr_uint_index_of(state_config->fader_codes, code) != ARRAY_NOT_FOUND) { context->values[k][i % 3] = (float)value / MIDI_MAX; } else if (value > 0) { if (context->values[k][i % 3] > 0.5) { @@ -255,7 +252,7 @@ void state_apply_event(SharedContext *context, StateConfig state_config, } } - if (code == state_config.tap_tempo_code) { + if (code == state_config->tap_tempo_code) { found = true; midi_write(midi, code, value); if (value > 0) { @@ -289,32 +286,32 @@ bool state_background_write(SharedContext *context, StateConfig state_config, log_info("(state) background writing started (pid: %d)", pid); if (!midi.error) { - update_page(context, state_config, midi); - update_active(context, state_config, midi); - update_values(context, state_config, midi); + update_page(context, &state_config, &midi); + update_active(context, &state_config, &midi); + update_values(context, &state_config, &midi); } last_active = false; last_change = false; while (!context->stop) { - beat_active = tempo_progress(context->tempo, 1.0) < 0.25; + beat_active = tempo_progress(&context->tempo, 1.0) < 0.25; if (!midi.error && beat_active != last_active) { - safe_midi_write(midi, state_config.tap_tempo_code, + safe_midi_write(&midi, state_config.tap_tempo_code, beat_active ? MIDI_MAX : 0); - safe_midi_write(midi, + safe_midi_write(&midi, state_config.select_frag_codes.values[context->selected], beat_active ? MIDI_MAX : 0); } last_active = beat_active; - change = tempo_progress(context->tempo, 4.0) < 0.25; + change = tempo_progress(&context->tempo, 4.0) < 0.25; if (context->auto_random && change && !last_change) { - state_randomize(context, state_config); + state_randomize(context, &state_config); } last_change = change; @@ -324,58 +321,58 @@ bool state_background_write(SharedContext *context, StateConfig state_config, return false; } -static void state_load(SharedContext *context, StateConfig state_config, +static void state_load(SharedContext *context, StateConfig *state_config, char *state_file) { ConfigFile saved_state; char key[STR_LEN]; unsigned int i; - saved_state = config_file_read(state_file); + 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); + 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 (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]); + 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); + context->state.values[i] = config_file_get_int(&saved_state, key, 0); } - for (i = 0; i < state_config.midi_active_counts.length; i++) { + for (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); + context->active[i] = config_file_get_int(&saved_state, key, 0); } - for (i = 0; i < state_config.midi_codes.length; i++) { + for (i = 0; i < state_config->midi_codes.length; i++) { snprintf(key, STR_LEN, "value_%d_x", i); context->values[i][0] = - (float)config_file_get_int(saved_state, key, 0) / MIDI_MAX; + (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; + (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; + (float)config_file_get_int(&saved_state, key, 0) / MIDI_MAX; } - config_file_free(saved_state); + config_file_free(&saved_state); } -void state_init(SharedContext *context, StateConfig state_config, bool demo, +void state_init(SharedContext *context, StateConfig *state_config, bool demo, bool auto_random, unsigned int base_tempo, char *state_file, bool load_state) { unsigned int i; - context->tempo = tempo_init(); + tempo_init(&context->tempo); tempo_set(&context->tempo, base_tempo); context->demo = demo; context->auto_random = auto_random; - context->state.length = state_config.select_frag_codes.length; + context->state.length = state_config->select_frag_codes.length; memset(context->state.values, 0, sizeof(context->state.values)); if (auto_random) { @@ -399,15 +396,15 @@ void state_init(SharedContext *context, StateConfig state_config, bool demo, } } -void state_randomize(SharedContext *context, StateConfig state_config) { +void state_randomize(SharedContext *context, StateConfig *state_config) { unsigned int 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, +void state_save(SharedContext *context, StateConfig *state_config, char *state_file) { StringArray lines; unsigned int i; @@ -429,12 +426,12 @@ void state_save(SharedContext *context, StateConfig state_config, context->state.values[i]); } - for (i = 0; i < state_config.midi_active_counts.length; i++) { + for (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 (i = 0; i < state_config.midi_codes.length; i++) { + for (i = 0; i < state_config->midi_codes.length; 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, @@ -443,5 +440,5 @@ void state_save(SharedContext *context, StateConfig state_config, (unsigned int)(context->values[i][2] * MIDI_MAX)); } - file_write(state_file, lines); + file_write(state_file, &lines); } diff --git a/src/state.h b/src/state.h index b6bc929..412ab1d 100644 --- a/src/state.h +++ b/src/state.h @@ -3,22 +3,22 @@ #ifndef STATE_H #define STATE_H -StateConfig state_parse_config(ConfigFile config); +void state_parse_config(StateConfig *state_config, ConfigFile *config); -void state_apply_event(SharedContext *context, StateConfig state_config, - MidiDevice midi, unsigned char code, unsigned char value, - bool trace_midi); +void state_apply_event(SharedContext *context, StateConfig *state_config, + MidiDevice *midi, unsigned char code, + unsigned char value, bool trace_midi); bool state_background_write(SharedContext *context, 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, bool auto_random, unsigned int base_tempo, char *state_file, bool load_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, +void state_save(SharedContext *context, StateConfig *state_config, char *state_file); #endif /* STATE_H */ \ No newline at end of file diff --git a/src/tempo.c b/src/tempo.c index f3fe654..ae8ecd1 100644 --- a/src/tempo.c +++ b/src/tempo.c @@ -25,15 +25,12 @@ static void reset_tap_chain(Tempo *tempo, long t) { memset(tempo->tap_durations, 0, sizeof(tempo->tap_durations)); } -Tempo tempo_init() { - Tempo tempo; +void tempo_init(Tempo *tempo) { long t; t = now(); - reset_tap_chain(&tempo, t); - - return tempo; + reset_tap_chain(tempo, t); } static bool is_chain_active(Tempo tempo, long t) { @@ -113,14 +110,14 @@ void tempo_tap(Tempo *tempo) { add_tap_to_chain(tempo, t); } -double tempo_total(Tempo tempo) { +double tempo_total(Tempo *tempo) { long t; t = now(); - return (double)(t - tempo.last_reset) / (double)tempo.beat_length; + return (double)(t - tempo->last_reset) / (double)tempo->beat_length; } -double tempo_progress(Tempo tempo, double modulo) { +double tempo_progress(Tempo *tempo, double modulo) { return fmod(tempo_total(tempo), modulo); } \ No newline at end of file diff --git a/src/tempo.h b/src/tempo.h index 3482cf8..3deb68e 100644 --- a/src/tempo.h +++ b/src/tempo.h @@ -3,14 +3,14 @@ #ifndef TEMPO_H #define TEMPO_H -Tempo tempo_init(); +void tempo_init(Tempo *tempo); void tempo_tap(Tempo *tempo); void tempo_set(Tempo *tempo, float value); -double tempo_total(Tempo tempo); +double tempo_total(Tempo *tempo); -double tempo_progress(Tempo tempo, double modulo); +double tempo_progress(Tempo *tempo, double modulo); #endif /* TEMPO_H */ \ No newline at end of file diff --git a/src/timer.c b/src/timer.c index e5501f7..85092db 100644 --- a/src/timer.c +++ b/src/timer.c @@ -4,15 +4,11 @@ #include "timer.h" -Timer timer_init(const unsigned int target) { - Timer output; +void timer_init(Timer *timer, const unsigned int target) { + timer->counter = 0; + timer->target = target; - output.counter = 0; - output.target = target; - - gettimeofday(&output.start, NULL); - - return output; + gettimeofday(&timer->start, NULL); } bool timer_inc(Timer *timer) { diff --git a/src/timer.h b/src/timer.h index b9d0309..2882aec 100644 --- a/src/timer.h +++ b/src/timer.h @@ -3,7 +3,7 @@ #ifndef TIMER_H #define TIMER_H -Timer timer_init(const unsigned int target); +void timer_init(Timer *timer, const unsigned int target); bool timer_inc(Timer *timer); diff --git a/src/video.c b/src/video.c index 9141c65..d3c18a0 100644 --- a/src/video.c +++ b/src/video.c @@ -65,21 +65,17 @@ static void ioctl_error(VideoCapture *video_capture, const char *operation, video_capture->error = true; } -static VideoCapture open_device(char *name) { - VideoCapture video_capture; +static void open_device(VideoCapture *video_capture, char *name) { + strncpy(video_capture->name, name, STR_LEN); + video_capture->error = false; + video_capture->fd = -1; + video_capture->exp_fd = -1; - strlcpy(video_capture.name, name, STR_LEN); - video_capture.error = false; - video_capture.fd = -1; - video_capture.exp_fd = -1; - - video_capture.fd = open(name, O_RDWR); - if (video_capture.fd == -1) { + video_capture->fd = open(name, O_RDWR); + if (video_capture->fd == -1) { log_warn("(%s) Cannot open device", name); - video_capture.error = true; + video_capture->error = true; } - - return video_capture; } static bool check_caps(VideoCapture *video_capture) { @@ -269,46 +265,43 @@ static void create_image_buffer(VideoCapture *video_capture) { ioctl(video_capture->fd, VIDIOC_QBUF, &video_capture->buf); } -static void close_stream(VideoCapture video_capture) { - ioctl(video_capture.fd, VIDIOC_STREAMOFF, &buf_type); +static void close_stream(VideoCapture *video_capture) { + ioctl(video_capture->fd, VIDIOC_STREAMOFF, &buf_type); } -VideoCapture video_init(char *name, unsigned int preferred_height) { - VideoCapture video_capture; +void video_init(VideoCapture *video_capture, char *name, + unsigned int preferred_height) { + open_device(video_capture, name); - video_capture = open_device(name); - - if (video_capture.error) { - return video_capture; + if (video_capture->error) { + return; } - if (!check_caps(&video_capture)) { - return video_capture; + if (!check_caps(video_capture)) { + return; } - if (!get_available_sizes(&video_capture, preferred_height)) { - return video_capture; + if (!get_available_sizes(video_capture, preferred_height)) { + return; } - if (!set_format(&video_capture)) { - return video_capture; + if (!set_format(video_capture)) { + return; } - if (!request_buffers(&video_capture)) { - return video_capture; + if (!request_buffers(video_capture)) { + return; } - if (!export_buffer(&video_capture)) { - return video_capture; + if (!export_buffer(video_capture)) { + return; } - if (!open_stream(&video_capture)) { - return video_capture; + if (!open_stream(video_capture)) { + return; } - create_image_buffer(&video_capture); - - return video_capture; + create_image_buffer(video_capture); } static bool read_video(VideoCapture *video_capture) { @@ -329,7 +322,7 @@ static bool read_video(VideoCapture *video_capture) { return true; } -bool video_background_read(VideoCapture *video_capture, SharedContext *context, +bool video_background_read(VideoCapture video_capture, SharedContext *context, int input_index, bool trace_fps) { pid_t pid; Timer timer; @@ -343,40 +336,40 @@ bool video_background_read(VideoCapture *video_capture, SharedContext *context, if (pid == 0) { return true; } - log_info("(%s) background acquisition started (pid: %d)", video_capture->name, + log_info("(%s) background acquisition started (pid: %d)", video_capture.name, pid); - timer = timer_init(30); + timer_init(&timer, 30); - while (!context->stop && read_video(video_capture)) { + while (!context->stop && read_video(&video_capture)) { // repeat infinitely if (timer_inc(&timer)) { fps = timer_reset(&timer); context->input_fps[input_index] = (unsigned int)round(fps); if (trace_fps) { - log_trace("(%s) %.2ffps", video_capture->name, fps); + log_trace("(%s) %.2ffps", video_capture.name, fps); } } } if (context->stop) { log_info("(%s) background acquisition stopped by main thread (pid: %d)", - video_capture->name, pid); + video_capture.name, pid); } else { log_info("(%s) background acquisition stopped after error (pid: %d)", - video_capture->name, pid); + video_capture.name, pid); } exit(context->stop ? EXIT_SUCCESS : EXIT_FAILURE); return false; } -void video_free(VideoCapture video_capture) { - if (!video_capture.error) { +void video_free(VideoCapture *video_capture) { + if (!video_capture->error) { close_stream(video_capture); } - if (video_capture.exp_fd != -1) { - close(video_capture.exp_fd); + if (video_capture->exp_fd != -1) { + close(video_capture->exp_fd); } - if (video_capture.fd != -1) { - close(video_capture.fd); + if (video_capture->fd != -1) { + close(video_capture->fd); } } \ No newline at end of file diff --git a/src/video.h b/src/video.h index 0b5dd6a..4307fd1 100644 --- a/src/video.h +++ b/src/video.h @@ -3,11 +3,12 @@ #ifndef VIDEO_H #define VIDEO_H -VideoCapture video_init(char *name, unsigned int preferred_height); +void video_init(VideoCapture *video_capture, char *name, + unsigned int preferred_height); -bool video_background_read(VideoCapture *video_capture, SharedContext *context, +bool video_background_read(VideoCapture video_capture, SharedContext *context, int input_index, bool trace_fps); -void video_free(VideoCapture video_capture); +void video_free(VideoCapture *video_capture); #endif /* VIDEO_H */ \ No newline at end of file