refactor: extract project related functions to project.c

This commit is contained in:
2025-11-08 14:58:34 +01:00
parent 197c0c70da
commit de5fc8c641
7 changed files with 181 additions and 119 deletions
+2 -2
View File
@@ -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)
+18 -96
View File
@@ -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();
}
+95
View File
@@ -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);
}
+12
View File
@@ -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 */
+15 -15
View File
@@ -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);
+2 -3
View File
@@ -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);
+37 -3
View File
@@ -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 */