summaryrefslogtreecommitdiff
path: root/src/main.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-09 19:34:46 +0100
committerskal <pascal.massimino@gmail.com>2026-02-09 19:34:46 +0100
commitf449fe7f78e059d455dfefcf4b09d763363f6344 (patch)
tree0a1e6ebfc42025e4e72200d3c34e2bf799a32aa8 /src/main.cc
parentdd42eeef53df8ea36f436986f915f29986c094a3 (diff)
feat: Add headless mode for testing without GPU
Implements DEMO_HEADLESS build option for fast iteration cycles: - Functional GPU/platform stubs (not pure no-ops like STRIP_EXTERNAL_LIBS) - Audio and timeline systems work normally - No rendering overhead - Useful for CI, audio development, timeline validation Files added: - doc/HEADLESS_MODE.md - Documentation - src/gpu/headless_gpu.cc - Validated GPU stubs - src/platform/headless_platform.cc - Time simulation (60Hz) - scripts/test_headless.sh - End-to-end test script Usage: cmake -B build_headless -DDEMO_HEADLESS=ON cmake --build build_headless -j4 ./build_headless/demo64k --headless --duration 30 Progress printed every 5s. Compatible with --dump_wav mode. handoff(Claude): Task #76 follow-up - headless mode complete
Diffstat (limited to 'src/main.cc')
-rw-r--r--src/main.cc37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/main.cc b/src/main.cc
index b4091e7..58ea124 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -32,6 +32,8 @@ int main(int argc, char** argv) {
int height = 720;
bool dump_wav = false;
bool tempo_test_enabled = false;
+ bool headless_mode = false;
+ float headless_duration = 30.0f;
const char* wav_output_file = "audio_dump.wav";
bool hot_reload_enabled = false;
@@ -59,6 +61,11 @@ int main(int argc, char** argv) {
}
} else if (strcmp(argv[i], "--tempo") == 0) {
tempo_test_enabled = true;
+ } else if (strcmp(argv[i], "--headless") == 0) {
+ headless_mode = true;
+ } else if (strcmp(argv[i], "--duration") == 0 && i + 1 < argc) {
+ headless_duration = atof(argv[i + 1]);
+ ++i;
} else if (strcmp(argv[i], "--hot-reload") == 0) {
hot_reload_enabled = true;
printf("Hot-reload enabled (watching config files)\n");
@@ -74,7 +81,9 @@ int main(int argc, char** argv) {
gpu_init(&platform_state);
// Load timeline data (visual effects layering)
+#if !defined(DEMO_HEADLESS)
LoadTimeline(*gpu_get_main_sequence(), *gpu_get_context());
+#endif
#if !defined(STRIP_ALL)
// Set WAV dump backend if requested
@@ -182,6 +191,34 @@ int main(int argc, char** argv) {
#endif
#if !defined(STRIP_ALL)
+ // In headless mode, run simulation without rendering
+ if (headless_mode) {
+ printf("Running headless simulation (%.1fs)...\n", headless_duration);
+
+ const float update_dt = 1.0f / 60.0f;
+ double physical_time = 0.0;
+ while (physical_time < headless_duration) {
+ fill_audio_buffer(update_dt, physical_time);
+ gpu_simulate_until(g_music_time);
+ physical_time += update_dt;
+
+ if ((int)physical_time % 5 == 0 &&
+ physical_time - update_dt < (int)physical_time) {
+ printf(" Progress: %.1fs / %.1fs (music: %.1fs)\r",
+ physical_time, headless_duration, g_music_time);
+ fflush(stdout);
+ }
+ }
+
+ printf("\nHeadless simulation complete: %.2fs\n", physical_time);
+
+ g_audio_engine.shutdown();
+ audio_shutdown();
+ gpu_shutdown();
+ platform_shutdown(&platform_state);
+ return 0;
+ }
+
// In WAV dump mode, run headless simulation and write audio to file
if (dump_wav) {
printf("Running WAV dump simulation...\n");