diff --git a/Makefile.am b/Makefile.am index 24c9fcb..381fca1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,9 @@ AUTOMAKE_OPTIONS = foreign subdir-objects -Wall bin_PROGRAMS = forge -forge_SOURCES = src/main.c src/args.c src/forge.c src/file.c src/window.c src/shaders.c src/timer.c src/string.c src/config_file.c src/rand.c src/video.c src/shared.c src/midi.c src/state.c src/arr.c src/tempo.c $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/hashmap.c/hashmap.c $(top_srcdir)/log.c/src/log.c +forge_SOURCES = src/args.c src/arr.c src/config_file.c src/file.c src/forge.c src/main.c src/midi.c src/preo src/rand.c src/shaders.c src/shared.c src/state.c src/string.c src/tempo.c src/timer.c src/video.c src/window.c $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/hashmap.c/hashmap.c $(top_srcdir)/log.c/src/log.c forge_CFLAGS = -Ofast -march=native -flto -funroll-loops -fprefetch-loop-arrays -fno-exceptions -fopenmp -I$(top_srcdir)/include -DGLFW_INCLUDE_NONE -DGLFW_EXPOSE_NATIVE_EGL -DGLFW_NATIVE_INCLUDE_NONE -DLOG_USE_COLOR -DDATADIR=\"$(datadir)/$(PACKAGE)\" forge_LDADD = -lm -lGL -lglfw -lasound -include_HEADERS = src/main.h src/args.h src/config.h src/types.h src/forge.h src/file.h src/constants.h src/window.h src/shaders.h src/timer.h src/string.h src/config_file.h src/rand.h src/video.h src/shared.h src/midi.h src/state.h src/arr.h src/tempo.h $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/include/linmath.h $(top_srcdir)/include/hashmap.h $(top_srcdir)/include/log.h +include_HEADERS = src/args.h src/arr.h src/config.h src/config_file.h src/constants.h src/file.h src/forge.h src/main.h src/midi.h src/project.h src/rand.h src/shaders.h src/shared.h src/state.h src/string.h src/tempo.h src/timer.h src/types.h src/video.h src/window.h $(top_srcdir)/include/glad/gl.h $(top_srcdir)/include/glad/egl.h $(top_srcdir)/include/linmath.h $(top_srcdir)/include/hashmap.h $(top_srcdir)/include/log.h EXTRA_DIST = default/forge_project.cfg default/frag0.glsl default/frag1.glsl default/frag2.glsl default/frag3.glsl default/frag4.glsl default/frag5.glsl default/frag6.glsl default/frag7.glsl default/frag8.glsl default/frag9.glsl default/frag10.glsl confdir = $(prefix)/share/$(PACKAGE) diff --git a/src/forge.c b/src/forge.c index cee82a0..ba751af 100644 --- a/src/forge.c +++ b/src/forge.c @@ -13,6 +13,7 @@ #include "file.h" #include "forge.h" #include "midi.h" +#include "project.h" #include "shaders.h" #include "shared.h" #include "state.h" @@ -26,13 +27,10 @@ static ShaderProgram program; static Window *window_output; static Window *window_monitor; static VideoCaptureArray inputs; -static FileArray fragment_shaders; -static File common_shader_code; static Timer timer; -static ConfigFile config; static MidiDevice midi; -static StateConfig state_config; static bool trace_midi; +static Project project; static void compute_fps(bool trace_fps) { double fps; @@ -62,7 +60,7 @@ static void compute_fps(bool trace_fps) { static void init_context(Parameters params, unsigned int in_count) { unsigned int i; - state_init(context, state_config, params.demo, params.auto_random, + state_init(context, project.state_config, params.demo, params.auto_random, params.base_tempo, params.state_file, params.load_state); context->monitor = params.monitor; @@ -82,67 +80,8 @@ static void init_context(Parameters params, unsigned int in_count) { static void free_context() { shared_close_context(context); } -static void hot_reload() { - unsigned int i; - bool force_update; - - force_update = false; - - if (file_should_update(common_shader_code)) { - file_update(&common_shader_code); - force_update = true; - } - - for (i = 0; i < program.frag_count; i++) { - if (force_update || file_should_update(fragment_shaders.values[i])) { - file_update(&fragment_shaders.values[i]); - file_prepend(&fragment_shaders.values[i], common_shader_code); - - shaders_update(program, fragment_shaders, i); - } - } -} - -File read_fragment_shader_file(char *frag_path, char *frag_prefix, - unsigned int i) { - File fragment_shader; - char file_path[STR_LEN]; - - snprintf(file_path, STR_LEN, "%s/%s%d.glsl", frag_path, frag_prefix, i); - fragment_shader = file_read(file_path); - if (fragment_shader.error) { - exit(EXIT_FAILURE); - } - - return fragment_shader; -} - -static void init_files(char *frag_path, char *frag_prefix, - unsigned int frag_count) { - unsigned int i; - - fragment_shaders.length = frag_count; - - for (i = 0; i < frag_count + 1; i++) { - if (i == 0) { - common_shader_code = read_fragment_shader_file(frag_path, frag_prefix, i); - } else { - fragment_shaders.values[i - 1] = - read_fragment_shader_file(frag_path, frag_prefix, i); - - file_prepend(&fragment_shaders.values[i - 1], common_shader_code); - } - } -} - -static void free_files(unsigned int frag_count) { - unsigned int i; - - for (i = 0; i < frag_count; i++) { - file_free(&fragment_shaders.values[i]); - } - - file_free(&common_shader_code); +static void reload_shader(unsigned int i) { + shaders_update(program, project.fragment_shaders, i); } static void init_inputs(StringArray video_in, unsigned int video_size) { @@ -195,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, 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")); @@ -209,12 +148,13 @@ static void key_callback(Window *window, int key, } static void midi_callback(unsigned char code, unsigned char value) { - state_apply_event(context, state_config, midi, code, value, trace_midi); + state_apply_event(context, project.state_config, midi, code, value, + trace_midi); } static void loop(bool hr, bool trace_fps) { if (hr) { - hot_reload(); + project_reload(&project, reload_shader); } compute_fps(trace_fps); @@ -242,35 +182,21 @@ static void loop(bool hr, bool trace_fps) { } void forge_run(Parameters params) { - unsigned int frag_count, in_count; - char config_path[STR_LEN * 2 + 1]; - char *frag_prefix; - context = shared_init_context("/" PACKAGE "_context"); context->stop = false; - sprintf(config_path, "%s/%s", params.project_path, params.config_file); - - config = config_file_read(config_path); - - state_config = state_parse_config(config); - - frag_count = config_file_get_int(config, "FRAG_COUNT", 1); - in_count = config_file_get_int(config, "IN_COUNT", 0); - frag_prefix = config_file_get_str(config, "FRAG_FILE_PREFIX", "frag"); - - init_files(params.project_path, frag_prefix, frag_count); + project = project_init(params.project_path, params.config_file); init_inputs(params.video_in, params.video_size); - init_context(params, in_count); + init_context(params, project.in_count); if (!start_video_captures(params.video_in.length, params.trace_fps)) { return; } - midi = midi_open(config_file_get_str(config, "MIDI_HW", "hw")); + midi = midi_open(config_file_get_str(project.config, "MIDI_HW", "hw")); if (midi.error) { params.demo = true; @@ -282,7 +208,7 @@ void forge_run(Parameters params) { } } - if (!state_background_write(context, state_config, midi)) { + if (!state_background_write(context, project.state_config, midi)) { return; } @@ -296,8 +222,7 @@ void forge_run(Parameters params) { window_use(window_output, context); - program = shaders_init(fragment_shaders, config, context, inputs, - state_config, NULL); + program = shaders_init(project, context, inputs, NULL); } else { window_output = NULL; } @@ -309,9 +234,8 @@ void forge_run(Parameters params) { window_use(window_monitor, context); - program = - shaders_init(fragment_shaders, config, context, inputs, state_config, - window_output != NULL ? &program : NULL); + program = shaders_init(project, context, inputs, + window_output != NULL ? &program : NULL); } else { window_monitor = NULL; } @@ -334,7 +258,7 @@ void forge_run(Parameters params) { context->stop = true; if (params.save_state) { - state_save(context, state_config, params.state_file); + state_save(context, project.state_config, params.state_file); } shaders_free(program); @@ -355,9 +279,7 @@ void forge_run(Parameters params) { free_context(); - free_files(frag_count); - - config_file_free(config); + project_free(project); window_terminate(); } \ No newline at end of file diff --git a/src/project.c b/src/project.c new file mode 100644 index 0000000..ec1b5e5 --- /dev/null +++ b/src/project.c @@ -0,0 +1,95 @@ +#include "types.h" + +#include "config_file.h" +#include "file.h" +#include "project.h" +#include "state.h" + +static File read_fragment_shader_file(char *frag_path, char *frag_prefix, + unsigned int i) { + File fragment_shader; + char file_path[STR_LEN]; + + snprintf(file_path, STR_LEN, "%s/%s%d.glsl", frag_path, frag_prefix, i); + fragment_shader = file_read(file_path); + if (fragment_shader.error) { + exit(EXIT_FAILURE); + } + + return fragment_shader; +} + +static void init_files(Project *output, char *frag_path, char *frag_prefix, + unsigned int frag_count) { + unsigned int i; + + output->fragment_shaders.length = frag_count; + + for (i = 0; i < frag_count + 1; i++) { + if (i == 0) { + output->common_shader_code = + read_fragment_shader_file(frag_path, frag_prefix, i); + } else { + output->fragment_shaders.values[i - 1] = + read_fragment_shader_file(frag_path, frag_prefix, i); + + file_prepend(&output->fragment_shaders.values[i - 1], + output->common_shader_code); + } + } +} + +Project project_init(char *project_path, char *config_file) { + Project project; + char config_path[STR_LEN]; + char *frag_prefix; + + snprintf(config_path, STR_LEN, "%s/%s", project_path, config_file); + + project.config = config_file_read(config_path); + + project.state_config = state_parse_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); + frag_prefix = config_file_get_str(project.config, "FRAG_FILE_PREFIX", "frag"); + + init_files(&project, project_path, frag_prefix, project.frag_count); + + return project; +} + +void project_reload(Project *project, void (*reload_callback)(unsigned int)) { + unsigned int i; + bool force_update; + + force_update = false; + + if (file_should_update(project->common_shader_code)) { + file_update(&project->common_shader_code); + force_update = true; + } + + for (i = 0; i < project->frag_count; i++) { + if (force_update || + file_should_update(project->fragment_shaders.values[i])) { + file_update(&project->fragment_shaders.values[i]); + file_prepend(&project->fragment_shaders.values[i], + project->common_shader_code); + + reload_callback(i); + } + } +} + +void project_free(Project project) { + unsigned int i; + + for (i = 0; i < project.frag_count; i++) { + file_free(&project.fragment_shaders.values[i]); + } + + file_free(&project.common_shader_code); + + config_file_free(project.config); +} \ No newline at end of file diff --git a/src/project.h b/src/project.h new file mode 100644 index 0000000..cd295ef --- /dev/null +++ b/src/project.h @@ -0,0 +1,12 @@ +#include "types.h" + +#ifndef PROJECT_H +#define PROJECT_H + +Project project_init(char *project_path, char *config_file); + +void project_reload(Project *project, void (*reload_callback)(unsigned int)); + +void project_free(Project project); + +#endif /* PROJECT_H */ \ No newline at end of file diff --git a/src/shaders.c b/src/shaders.c index 4db4a89..4bafe3c 100644 --- a/src/shaders.c +++ b/src/shaders.c @@ -377,25 +377,25 @@ static void init_programs(ShaderProgram *program, ConfigFile config, } } -ShaderProgram shaders_init(FileArray fragment_shaders, ConfigFile config, - SharedContext *context, VideoCaptureArray inputs, - StateConfig state_config, ShaderProgram *previous) { +ShaderProgram shaders_init(Project project, SharedContext *context, + VideoCaptureArray inputs, ShaderProgram *previous) { ShaderProgram program; if (previous == NULL) { program.error = false; program.last_resolution[0] = context->resolution[0]; program.last_resolution[1] = context->resolution[1]; - program.tex_count = config_file_get_int(config, "TEX_COUNT", 9); - program.frag_count = config_file_get_int(config, "FRAG_COUNT", 10); + 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(config, "FRAG_OUTPUT", 1) - 1; + config_file_get_int(project.config, "FRAG_OUTPUT", 1) - 1; program.frag_monitor_index = - config_file_get_int(config, "FRAG_MONITOR", 1) - 1; - program.sub_type_count = config_file_get_int(config, "SUB_TYPE_COUNT", 0); - program.in_count = config_file_get_int(config, "IN_COUNT", 0); - program.sub_variant_count = state_config.state_max; - program.active_count = state_config.midi_active_counts.length; + 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); + program.sub_variant_count = project.state_config.state_max; + program.active_count = project.state_config.midi_active_counts.length; program.midi_lengths.length = 0; if (program.frag_count > MAX_FRAG) { @@ -406,7 +406,7 @@ ShaderProgram shaders_init(FileArray fragment_shaders, ConfigFile config, init_gl(&program); - init_shaders(&program, fragment_shaders); + init_shaders(&program, project.fragment_shaders); if (program.error) { return program; @@ -414,11 +414,11 @@ ShaderProgram shaders_init(FileArray fragment_shaders, ConfigFile config, init_textures(&program, context); - init_input(&program, config, inputs); + init_input(&program, project.config, inputs); - init_framebuffers(&program, config); + init_framebuffers(&program, project.config); - init_programs(&program, config, state_config); + init_programs(&program, project.config, project.state_config); init_vertices(&program); diff --git a/src/shaders.h b/src/shaders.h index 9ac969b..ad45181 100644 --- a/src/shaders.h +++ b/src/shaders.h @@ -3,9 +3,8 @@ #ifndef SHADERS_H #define SHADERS_H -ShaderProgram shaders_init(FileArray fragment_shaders, ConfigFile config, - SharedContext *context, VideoCaptureArray inputs, - StateConfig state_config, ShaderProgram *previous); +ShaderProgram shaders_init(Project project, SharedContext *context, + VideoCaptureArray inputs, ShaderProgram *previous); void shaders_update(ShaderProgram program, FileArray fragment_shaders, unsigned int i); diff --git a/src/types.h b/src/types.h index bf7eb48..991dc30 100644 --- a/src/types.h +++ b/src/types.h @@ -29,6 +29,8 @@ typedef struct StringArray { unsigned int length; } StringArray; +// args.c + typedef struct Parameters { char project_path[STR_LEN]; char config_file[STR_LEN]; @@ -51,9 +53,7 @@ typedef struct Parameters { bool trace_fps; } Parameters; -typedef struct Vertex { - vec2 pos; -} Vertex; +// file.c typedef struct File { char path[STR_LEN]; @@ -65,6 +65,12 @@ typedef struct File { typedef ARRAY(FileArray, File); +// shaders.c + +typedef struct Vertex { + vec2 pos; +} Vertex; + typedef struct ShaderProgram { bool error; @@ -121,6 +127,8 @@ typedef struct ShaderProgram { EGLDisplay egl_display; } ShaderProgram; +// video.c + typedef struct VideoCapture { char name[STR_LEN]; bool error; @@ -137,8 +145,12 @@ typedef struct VideoCapture { typedef ARRAY(VideoCaptureArray, VideoCapture); +// window.c + typedef GLFWwindow Window; +// tempo.c + typedef struct Tempo { long last_reset; long last_tap; @@ -150,6 +162,8 @@ typedef struct Tempo { float tempo; } Tempo; +// context.c + typedef struct SharedContext { int fd; @@ -176,6 +190,8 @@ typedef struct SharedContext { bool stop; } SharedContext; +// state.c + typedef struct StateConfig { unsigned int state_max; @@ -194,12 +210,16 @@ typedef struct StateConfig { unsigned int tap_tempo_code; } StateConfig; +// timer.c + typedef struct Timer { struct timeval start; unsigned int counter; unsigned int target; } Timer; +// config.c + typedef struct ConfigFile { struct hashmap *map; } ConfigFile; @@ -209,6 +229,8 @@ typedef struct ConfigFileItem { char value[STR_LEN]; } ConfigFileItem; +// midi.c + typedef struct MidiDevice { bool error; char name[STR_LEN]; @@ -216,4 +238,16 @@ typedef struct MidiDevice { snd_rawmidi_t *output; } MidiDevice; +// project.c + +typedef struct Project { + bool error; + ConfigFile config; + StateConfig state_config; + FileArray fragment_shaders; + File common_shader_code; // TODO change + unsigned int frag_count; + unsigned int in_count; +} Project; + #endif /* TYPES_H */ \ No newline at end of file