refactor: pass structs as pointers except for background things

This commit is contained in:
2025-11-08 19:24:14 +01:00
parent 92f010ca70
commit 3b7a550b6a
23 changed files with 418 additions and 450 deletions
+1 -1
View File
@@ -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
+54 -56
View File
@@ -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;
}
+1 -1
View File
@@ -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 */
+15 -18
View File
@@ -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); }
void config_file_free(ConfigFile *config) { hashmap_free(config->map); }
+4 -4
View File
@@ -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 */
+9 -17
View File
@@ -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]);
}
}
+2 -4
View File
@@ -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 */
+41 -41
View File
@@ -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(&params->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();
+1 -1
View File
@@ -3,6 +3,6 @@
#ifndef FORGE_H
#define FORGE_H
void forge_run(Parameters params);
void forge_run(Parameters *params);
#endif /* FORGE_H */
+2 -2
View File
@@ -13,13 +13,13 @@
int main(int argc, char **argv) {
Parameters params;
params = args_parse(argc, argv);
args_parse(&params, argc, argv);
puts(PACKAGE " " VERSION);
set_seed((unsigned long)time(NULL));
forge_run(params);
forge_run(&params);
return EXIT_SUCCESS;
}
+8 -12
View File
@@ -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,
+2 -2
View File
@@ -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));
+10 -9
View File
@@ -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);
}
+84 -82
View File
@@ -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);
}
}
+6 -6
View File
@@ -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 */
+113 -116
View File
@@ -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);
}
+7 -7
View File
@@ -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 */
+5 -8
View File
@@ -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);
}
+3 -3
View File
@@ -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 */
+4 -8
View File
@@ -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) {
+1 -1
View File
@@ -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);
+41 -48
View File
@@ -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);
}
}
+4 -3
View File
@@ -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 */