feat: --auto-random-cycle

This commit is contained in:
2025-11-14 09:03:23 +01:00
parent 2ab0947550
commit c229b9bc68
7 changed files with 110 additions and 89 deletions
+7 -3
View File
@@ -117,11 +117,15 @@ make -f Makefile.dev release-arch
- [x] Printable PDF of default scr/fx
- [x] Add NanoKontrol setup file
- [x] Find and fix opengl errors 0500 ?
- [ ] Improvements
- [ ] Record show as text files
- [ ] Play from record text file
- [ ] Extra features
- [ ] `--auto-random-cycle=4`
- [ ] Arrows (up-down: bpm / left-right: cycle)
- [ ] Save states (numkey: load / shift + numkey: save)
- [ ] Configurable key codes
- [ ] Key codes as inputs
- [ ] Mouse position and scroll as inputs
- [ ] Record show as text files
- [ ] Play from record text file
- [ ] Fixes
- [ ] Try to write NanoKontrol config
- [ ] Investigate video device fps loss (bad unregister ?)
+25 -24
View File
@@ -166,34 +166,35 @@ When running, the following hotkeys are available:
### CLI arguments
```txt
usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-v=FILE] [-vs=SIZE] [-is=SIZE] [-sf=STATE_PATH] [-ls / -nls] [-ss / -nss] [-tm] [-tf]
usage: forge [-h] [-v] [-p=PROJECT_PATH] [-c=CFG_FILE] [-hr] [-s=SCREEN] [-m=SCREEN] [-mo] [-w] [-t=TEMPO] [-d] [-ar / -nar] [-arc=CYCLES] [-v=FILE] [-vs=SIZE] [-is=SIZE] [-sf=STATE_PATH] [-ls / -nls] [-ss / -nss] [-tm] [-tf]
Fusion Of Real-time Generative Effects.
options:
-h, --help show this help message and exit
-v, --version print version
-p, --project forge project directory (default: /usr/share/forge/default)
-c, --config config file name (default: forge_project.cfg)
-hr, --hot-reload hot reload of shaders scripts
-s, --screen output screen number (default: primary)
-m, --monitor monitor screen number (default: none)
-mo, --monitor-only no output screen
-w, --windowed not fullscreen
-t, --tempo base tempo (default: 60)
-d, --demo demonstration mode (assume --no-save-state, --no-load-state, --auto-random)
-ar, --auto-random randomize state every 4 beats
-nar, --no-auto-random do not randomize state (default)
-v, --video-in path to video capture device (multiple allowed)
-vs, --video-size video capture desired height (default: internal texture height)
-is, --internal-size internal texture height (default: 720)
-sf, --state-file saved state file (default: forge_saved_state.txt)
-ls, --load-state load saved state (default)
-nls, --no-load-state do not load saved state
-ss, --save-state save state (default)
-nss, --no-save-state do not save state
-tm, --trace-midi print midi code and values
-tf, --trace-fps print fps status of subsystems
-h, --help show this help message and exit
-v, --version print version
-p, --project forge project directory (default: /usr/share/forge/default)
-c, --config config file name (default: forge_project.cfg)
-hr, --hot-reload hot reload of shaders scripts
-s, --screen output screen number (default: primary)
-m, --monitor monitor screen number (default: none)
-mo, --monitor-only no output screen
-w, --windowed not fullscreen
-t, --tempo base tempo (default: 60)
-d, --demo demonstration mode (assume --no-save-state, --no-load-state, --auto-random)
-ar, --auto-random randomize state every cycle (4 beats)
-nar, --no-auto-random do not randomize state (default)
-arc, --auto-random-cycle auto random cycle length (default: 4)
-v, --video-in path to video capture device (multiple allowed)
-vs, --video-size video capture desired height (default: internal texture height)
-is, --internal-size internal texture height (default: 720)
-sf, --state-file saved state file (default: forge_saved_state.txt)
-ls, --load-state load saved state (default)
-nls, --no-load-state do not load saved state
-ss, --save-state save state (default)
-nss, --no-save-state do not save state
-tm, --trace-midi print midi code and values
-tf, --trace-fps print fps status of subsystems
```
## Default Project
+64 -55
View File
@@ -13,61 +13,64 @@
#include "string.h"
static void print_help(int status_code) {
puts(PACKAGE
" " VERSION "\n\n"
"usage: " PACKAGE " "
"[-h] "
"[-v] "
"[-p=PROJECT_PATH] "
"[-c=CFG_FILE] "
"[-hr] "
"[-s=SCREEN] "
"[-m=SCREEN] "
"[-mo] "
"[-w] "
"[-t=TEMPO] "
"[-d] "
"[-ar / -nar] "
"[-v=FILE] "
"[-vs=SIZE] "
"[-is=SIZE] "
"[-sf=STATE_PATH] "
"[-ls / -nls] "
"[-ss / -nss] "
"[-tm] "
"[-tf] "
"\n\n"
"Fusion Of Real-time Generative Effects.\n\n"
"options:\n"
" -h, --help show this help message and exit\n"
" -v, --version print version\n"
" -p, --project forge project directory (default: " DATADIR
"/default)\n"
" -c, --config config file name (default: "
"forge_project.cfg)\n"
" -hr, --hot-reload hot reload of shaders scripts\n"
" -s, --screen output screen number (default: primary)\n"
" -m, --monitor monitor screen number (default: none)\n"
" -mo, --monitor-only no output screen\n"
" -w, --windowed not fullscreen\n"
" -t, --tempo base tempo (default: 60)\n"
" -d, --demo demonstration mode (assume "
"--no-save-state, --no-load-state, --auto-random)\n"
" -ar, --auto-random randomize state every 4 beats\n"
" -nar, --no-auto-random do not randomize state (default)\n"
" -v, --video-in path to video capture device (multiple "
"allowed)\n"
" -vs, --video-size video capture desired height (default: "
"internal texture height)\n"
" -is, --internal-size internal texture height (default: 720)\n"
" -sf, --state-file saved state file (default: "
"forge_saved_state.txt)\n"
" -ls, --load-state load saved state (default)\n"
" -nls, --no-load-state do not load saved state\n"
" -ss, --save-state save state (default)\n"
" -nss, --no-save-state do not save state\n"
" -tm, --trace-midi print midi code and values\n"
" -tf, --trace-fps print fps status of subsystems\n");
puts(
PACKAGE
" " VERSION "\n\n"
"usage: " PACKAGE " "
"[-h] "
"[-v] "
"[-p=PROJECT_PATH] "
"[-c=CFG_FILE] "
"[-hr] "
"[-s=SCREEN] "
"[-m=SCREEN] "
"[-mo] "
"[-w] "
"[-t=TEMPO] "
"[-d] "
"[-ar / -nar] "
"[-arc=CYCLES] "
"[-v=FILE] "
"[-vs=SIZE] "
"[-is=SIZE] "
"[-sf=STATE_PATH] "
"[-ls / -nls] "
"[-ss / -nss] "
"[-tm] "
"[-tf] "
"\n\n"
"Fusion Of Real-time Generative Effects.\n\n"
"options:\n"
" -h, --help show this help message and exit\n"
" -v, --version print version\n"
" -p, --project forge project directory (default: " DATADIR
"/default)\n"
" -c, --config config file name (default: "
"forge_project.cfg)\n"
" -hr, --hot-reload hot reload of shaders scripts\n"
" -s, --screen output screen number (default: primary)\n"
" -m, --monitor monitor screen number (default: none)\n"
" -mo, --monitor-only no output screen\n"
" -w, --windowed not fullscreen\n"
" -t, --tempo base tempo (default: 60)\n"
" -d, --demo demonstration mode (assume "
"--no-save-state, --no-load-state, --auto-random)\n"
" -ar, --auto-random randomize state every cycle (4 beats)\n"
" -nar, --no-auto-random do not randomize state (default)\n"
" -arc, --auto-random-cycle auto random cycle length (default: 4)\n"
" -v, --video-in path to video capture device (multiple "
"allowed)\n"
" -vs, --video-size video capture desired height (default: "
"internal texture height)\n"
" -is, --internal-size internal texture height (default: 720)\n"
" -sf, --state-file saved state file (default: "
"forge_saved_state.txt)\n"
" -ls, --load-state load saved state (default)\n"
" -nls, --no-load-state do not load saved state\n"
" -ss, --save-state save state (default)\n"
" -nss, --no-save-state do not save state\n"
" -tm, --trace-midi print midi code and values\n"
" -tf, --trace-fps print fps status of subsystems\n");
exit(status_code);
}
@@ -124,6 +127,7 @@ void args_parse(Parameters *params, int argc, char **argv) {
params->base_tempo = 60.0f;
params->demo = false;
params->auto_random = false;
params->auto_random_cycles = 4;
params->video_in.length = 0;
params->video_size = 0;
params->internal_size = 720;
@@ -168,6 +172,11 @@ void args_parse(Parameters *params, int argc, char **argv) {
params->auto_random = true;
} else if (is_arg(arg, "-nar") || is_arg(arg, "--no-auto-random")) {
params->auto_random = false;
} else if (is_arg(arg, "-arc") || is_arg(arg, "--auto-random-cycle")) {
params->auto_random_cycles = parse_uint(arg, value);
if (params->auto_random_cycles == 0) {
invalid_value(arg, value);
}
} else if (is_arg(arg, "-v") || is_arg(arg, "--video-in")) {
if (params->video_in.length == MAX_VIDEO) {
log_error("maximum video input reached");
+2 -1
View File
@@ -59,7 +59,8 @@ static void compute_fps(bool trace_fps) {
static void init_context(const Parameters *params, unsigned int in_count) {
state_init(context, &project.state_config, params->demo, params->auto_random,
params->base_tempo, params->state_file, params->load_state);
params->auto_random_cycles, params->base_tempo, params->state_file,
params->load_state);
context->monitor = params->monitor;
+7 -4
View File
@@ -314,7 +314,7 @@ bool state_background_write(SharedContext *context,
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.5;
if (!midi->error && beat_active != last_active) {
safe_midi_write(midi, state_config->tap_tempo_code,
@@ -327,7 +327,8 @@ bool state_background_write(SharedContext *context,
last_active = beat_active;
change = tempo_progress(&context->tempo, 4.0) < 0.25;
change = tempo_progress(&context->tempo,
(double)context->auto_random_cycles) < 0.5;
if (context->auto_random && change && !last_change) {
state_randomize(context, state_config);
@@ -383,12 +384,14 @@ static void state_load(SharedContext *context, const StateConfig *state_config,
}
void state_init(SharedContext *context, const StateConfig *state_config,
bool demo, bool auto_random, unsigned int base_tempo,
const char *state_file, bool load_state) {
bool demo, bool auto_random, unsigned int auto_random_cycles,
unsigned int base_tempo, const char *state_file,
bool load_state) {
tempo_init(&context->tempo);
tempo_set(&context->tempo, base_tempo);
context->demo = demo;
context->auto_random = auto_random;
context->auto_random_cycles = auto_random_cycles;
context->state.length = state_config->select_frag_codes.length;
memset(context->state.values, 0, sizeof(context->state.values));
+3 -2
View File
@@ -14,8 +14,9 @@ bool state_background_write(SharedContext *context,
const MidiDevice *midi);
void state_init(SharedContext *context, const StateConfig *state_config,
bool demo, bool auto_random, unsigned int base_tempo,
const char *state_file, bool load_state);
bool demo, bool auto_random, unsigned int auto_random_cycles,
unsigned int base_tempo, const char *state_file,
bool load_state);
void state_reset(SharedContext *context);
+2
View File
@@ -43,6 +43,7 @@ typedef struct Parameters {
float base_tempo;
bool demo;
bool auto_random;
unsigned int auto_random_cycles;
StringArray video_in;
unsigned int video_size;
unsigned int internal_size;
@@ -182,6 +183,7 @@ typedef struct SharedContext {
vec3 values[ARRAY_SIZE];
bool demo;
bool auto_random;
unsigned int auto_random_cycles;
unsigned int seeds[MAX_FRAG];
bool monitor;