Class: Vizcore::CLI
- Inherits:
-
Thor
- Object
- Thor
- Vizcore::CLI
- Defined in:
- lib/vizcore/cli.rb
Overview
Thor-based CLI entrypoint for Vizcore.
Constant Summary collapse
- SCAFFOLD_TEMPLATES =
{ "standard" => { label: "standard", start_scene: "scenes/basic.rb", files: [ ["basic_scene.rb", "scenes/basic.rb", "Minimal wireframe starter"], ["intro_drop_scene.rb", "scenes/intro_drop.rb", "Transition flow with beat trigger"], ["midi_control_scene.rb", "scenes/midi_control.rb", "MIDI note/CC mapping example"], ["custom_shader_scene.rb", "scenes/custom_shader.rb", "Custom GLSL + post/VJ effect example"], ["custom_wave.frag", "shaders/custom_wave.frag", "Custom GLSL fragment shader"] ], notes: [ "`scenes/custom_shader.rb` references `shaders/custom_wave.frag`.", "Use `vizcore devices midi` before running `scenes/midi_control.rb`." ] }, "minimal" => { label: "minimal", start_scene: "scenes/basic.rb", files: [ ["basic_scene.rb", "scenes/basic.rb", "Minimal wireframe starter"] ], notes: [] }, "shader" => { label: "shader", start_scene: "scenes/custom_shader.rb", files: [ ["custom_shader_scene.rb", "scenes/custom_shader.rb", "Custom GLSL + post/VJ effect example"], ["custom_wave.frag", "shaders/custom_wave.frag", "Custom GLSL fragment shader"] ], notes: [ "`scenes/custom_shader.rb` references `shaders/custom_wave.frag`." ] }, "midi" => { label: "midi", start_scene: "scenes/midi_control.rb", files: [ ["midi_control_scene.rb", "scenes/midi_control.rb", "MIDI note/CC mapping example"] ], notes: [ "Run `vizcore devices midi` before starting the MIDI scene." ] }, "live-set" => { label: "live-set", start_scene: "scenes/live_set.rb", files: [ ["intro_drop_scene.rb", "scenes/live_set.rb", "Two-scene transition flow with beat trigger"] ], notes: [ "Use file audio or a microphone input with clear beats for transition triggers." ] }, "rubykaigi" => { label: "rubykaigi", start_scene: "scenes/rubykaigi.rb", files: [ ["rubykaigi_scene.rb", "scenes/rubykaigi.rb", "Ruby conference visual starter"] ], notes: [ "This scene uses Ruby-red text and audio-reactive geometry for talk or event visuals." ] } }.freeze
- PLUGIN_SCAFFOLD_FILES =
[ ["plugin_readme.md", "README.md"], ["plugin_layer.rb", "lib/{{plugin_name}}.rb"], ["plugin_renderer.js", "frontend/{{plugin_name}}-renderer.js"], ["plugin_scene.rb", "examples/{{plugin_name}}_scene.rb"] ].freeze
- DEFAULT_CAPTURE_PORT =
4579
Class Method Summary collapse
-
.exit_on_failure? ⇒ Boolean
Exit with non-zero status when a Thor command fails.
Instance Method Summary collapse
-
#browser_capture(url) ⇒ void
Capture browser-rendered output from a running Vizcore server.
-
#capture(scene_file) ⇒ void
Start Vizcore and capture a browser-rendered canvas from the projector route.
-
#demo ⇒ void
Start a bundled scene with bundled audio for first-run verification.
-
#devices(type = nil) ⇒ void
Print audio and/or MIDI devices detected by the runtime.
-
#doctor ⇒ void
Print local environment checks for Vizcore runtime dependencies.
-
#dsl_docs ⇒ void
Print generated documentation for the Ruby scene DSL.
-
#gallery ⇒ void
Start a browser gallery for bundled example scenes.
-
#inspect_scene(scene_file) ⇒ void
Load a scene DSL file and print its runtime structure.
-
#layers ⇒ void
Print supported layer types, params, and browser-side capabilities.
-
#new(name) ⇒ void
Generate a new Vizcore project scaffold.
-
#plugin(command = nil, name = nil) ⇒ void
Run plugin helper commands.
-
#record_features(audio_file) ⇒ void
Analyze an audio file and persist feature frames as JSON.
-
#render(scene_file) ⇒ void
Load a scene DSL file and write a software-rendered PNG image sequence or MP4.
-
#shader(command = nil, name = nil) ⇒ void
Run custom shader helper commands.
-
#shader_docs ⇒ void
Print generated documentation for custom GLSL uniforms.
-
#snapshot(scene_file) ⇒ void
Load a scene DSL file and write a software-rendered PNG preview.
-
#start(scene_file = nil) ⇒ void
Start the Vizcore server with the given scene file.
-
#validate(scene_file) ⇒ void
Load and validate a scene DSL file without starting the server.
Class Method Details
.exit_on_failure? ⇒ Boolean
Exit with non-zero status when a Thor command fails.
28 29 30 |
# File 'lib/vizcore/cli.rb', line 28 def self.exit_on_failure? true end |
Instance Method Details
#browser_capture(url) ⇒ void
This method returns an undefined value.
Capture browser-rendered output from a running Vizcore server.
365 366 367 368 369 370 371 372 373 374 |
# File 'lib/vizcore/cli.rb', line 365 def browser_capture(url) run_browser_capture( url, out: .fetch(:out), selector: .fetch(:selector), wait: .fetch(:wait), width: .fetch(:width), height: .fetch(:height) ) end |
#capture(scene_file) ⇒ void
This method returns an undefined value.
Start Vizcore and capture a browser-rendered canvas from the projector route.
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/vizcore/cli.rb', line 394 def capture(scene_file) config = Config.new( scene_file: scene_file, host: .fetch(:host), port: .fetch(:port), audio_source: .fetch(:audio_source), audio_file: [:audio_file], feature_file: [:feature_file], control_preset: [:control_preset], reload: false, projector_mode: true ) validate_snapshot_config!(config) pid = Kernel.spawn(*temporary_server_command(config), out: File::NULL, err: File::NULL) begin wait_for_http("http://#{config.host}:#{config.port}/health", timeout: .fetch(:timeout)) run_browser_capture( "http://#{config.host}:#{config.port}/projector", out: .fetch(:out), selector: .fetch(:selector), wait: .fetch(:wait), width: .fetch(:width), height: .fetch(:height) ) ensure stop_temporary_server(pid) end rescue StandardError => e raise Thor::Error, e. end |
#demo ⇒ void
This method returns an undefined value.
Start a bundled scene with bundled audio for first-run verification.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/vizcore/cli.rb', line 169 def demo config = Config.new( scene_file: Vizcore.root.join("examples", "rhythm_geometry.rb"), host: .fetch(:host), port: .fetch(:port), audio_source: :file, audio_file: Vizcore.root.join("examples", "assets", "complex_demo_loop.wav"), noise_gate: .fetch(:noise_gate), bpm: [:bpm], bpm_lock: .fetch(:bpm_lock), control_preset: [:control_preset], osc_port: [:osc_port], projector_mode: .fetch(:projector) ) Server::Runner.new(config).run rescue ArgumentError => e raise Thor::Error, e. end |
#devices(type = nil) ⇒ void
This method returns an undefined value.
Print audio and/or MIDI devices detected by the runtime.
232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/vizcore/cli.rb', line 232 def devices(type = nil) case type when nil print_audio_devices print_midi_devices when "audio" print_audio_devices when "midi" print_midi_devices else raise Thor::Error, "Unknown type: #{type}. Use `audio` or `midi`." end end |
#doctor ⇒ void
This method returns an undefined value.
Print local environment checks for Vizcore runtime dependencies.
251 252 253 254 255 256 257 |
# File 'lib/vizcore/cli.rb', line 251 def doctor report = Vizcore::CLISupport::Doctor.new.call report.checks.each do |check| say("#{status_label(check.status)} #{check.name}: #{check.}") end raise Thor::Error, "vizcore doctor found required failures" if report.failure? end |
#dsl_docs ⇒ void
This method returns an undefined value.
Print generated documentation for the Ruby scene DSL.
302 303 304 |
# File 'lib/vizcore/cli.rb', line 302 def dsl_docs Vizcore::CLISupport::DslReference.new.lines.each { |line| say(line) } end |
#gallery ⇒ void
This method returns an undefined value.
Start a browser gallery for bundled example scenes.
194 195 196 197 198 199 |
# File 'lib/vizcore/cli.rb', line 194 def gallery Vizcore::Server::GalleryRunner.new( host: .fetch(:host), port: .fetch(:port) ).run end |
#inspect_scene(scene_file) ⇒ void
This method returns an undefined value.
Load a scene DSL file and print its runtime structure.
266 267 268 269 270 271 272 273 |
# File 'lib/vizcore/cli.rb', line 266 def inspect_scene(scene_file) diagnostics = Vizcore::CLISupport::SceneDiagnostics.new(scene_file: scene_file) result = diagnostics.validate print_issues(result.issues) raise Thor::Error, "scene inspection failed" unless result.definition diagnostics.inspect_lines(result.definition).each { |line| say(line) } end |
#layers ⇒ void
This method returns an undefined value.
Print supported layer types, params, and browser-side capabilities.
293 294 295 |
# File 'lib/vizcore/cli.rb', line 293 def layers Vizcore::CLISupport::LayerDocs.new.lines.each { |line| say(line) } end |
#new(name) ⇒ void
This method returns an undefined value.
Generate a new Vizcore project scaffold.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/vizcore/cli.rb', line 210 def new(name) scaffold = scaffold_template(.fetch(:template)) root = Pathname.new(name). FileUtils.mkdir_p(root) write_project_readme(root.join("README.md"), project_name: name, scaffold: scaffold) scaffold.fetch(:files).each do |template_name, destination, _description| write_template(template_name, root.join(destination), project_name: name) end say("Created project scaffold (#{scaffold.fetch(:label)}): #{root}") say("Next: cd #{name} && vizcore start #{scaffold.fetch(:start_scene)}") rescue ArgumentError => e raise Thor::Error, e. end |
#plugin(command = nil, name = nil) ⇒ void
This method returns an undefined value.
Run plugin helper commands.
342 343 344 345 346 347 348 349 350 351 |
# File 'lib/vizcore/cli.rb', line 342 def plugin(command = nil, name = nil) case command.to_s when "new" create_plugin_scaffold(name) else raise Thor::Error, "Unknown plugin command: #{command || '(nil)'}. Use `vizcore plugin new NAME`." end rescue ArgumentError => e raise Thor::Error, e. end |
#record_features(audio_file) ⇒ void
This method returns an undefined value.
Analyze an audio file and persist feature frames as JSON.
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
# File 'lib/vizcore/cli.rb', line 523 def record_features(audio_file) result = Vizcore::Analysis::FeatureRecorder.new( audio_file: audio_file, frames: .fetch(:frames), fps: .fetch(:fps), noise_gate: .fetch(:noise_gate), audio_normalize: feature_audio_normalize_setting, bpm: [:bpm], bpm_lock: .fetch(:bpm_lock) ).write(out: .fetch(:out)) say( "Features written: #{result[:path]} " \ "(frames=#{result[:frames]}, fps=#{result[:fps]}, sample_rate=#{result[:sample_rate]})" ) rescue StandardError => e raise Thor::Error, e. end |
#render(scene_file) ⇒ void
This method returns an undefined value.
Load a scene DSL file and write a software-rendered PNG image sequence or MP4.
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 |
# File 'lib/vizcore/cli.rb', line 480 def render(scene_file) config = Config.new( scene_file: scene_file, audio_source: .fetch(:audio_source), audio_file: [:audio_file], audio_device: [:audio_device], noise_gate: .fetch(:noise_gate), bpm: [:bpm], bpm_lock: .fetch(:bpm_lock) ) validate_snapshot_config!(config) result = Vizcore::Renderer::RenderSequence.new( config: config, frames: .fetch(:frames), fps: .fetch(:fps), width: .fetch(:width), height: .fetch(:height) ).write(out: .fetch(:out)) return say((result)) if result[:format] == :mp4 say( "Frames written: #{result[:path]} " \ "(scene=#{result[:scene]}, frames=#{result[:frames]}, fps=#{result[:fps]}, #{result[:width]}x#{result[:height]})" ) rescue StandardError => e raise Thor::Error, e. end |
#shader(command = nil, name = nil) ⇒ void
This method returns an undefined value.
Run custom shader helper commands.
323 324 325 326 327 328 329 330 331 332 |
# File 'lib/vizcore/cli.rb', line 323 def shader(command = nil, name = nil) case command.to_s when "new" create_shader_template(name) else raise Thor::Error, "Unknown shader command: #{command || '(nil)'}. Use `vizcore shader new NAME`." end rescue ArgumentError => e raise Thor::Error, e. end |
#shader_docs ⇒ void
This method returns an undefined value.
Print generated documentation for custom GLSL uniforms.
311 312 313 |
# File 'lib/vizcore/cli.rb', line 311 def shader_docs Vizcore::CLISupport::ShaderUniformDocs.new.lines.each { |line| say(line) } end |
#snapshot(scene_file) ⇒ void
This method returns an undefined value.
Load a scene DSL file and write a software-rendered PNG preview.
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 |
# File 'lib/vizcore/cli.rb', line 441 def snapshot(scene_file) config = Config.new( scene_file: scene_file, audio_source: .fetch(:audio_source), audio_file: [:audio_file], audio_device: [:audio_device], noise_gate: .fetch(:noise_gate), bpm: [:bpm], bpm_lock: .fetch(:bpm_lock) ) validate_snapshot_config!(config) result = Vizcore::Renderer::Snapshot.new( config: config, width: .fetch(:width), height: .fetch(:height) ).write(out: .fetch(:out)) say("Snapshot written: #{result[:path]} (scene=#{result[:scene]}, #{result[:width]}x#{result[:height]})") rescue StandardError => e raise Thor::Error, e. end |
#start(scene_file = nil) ⇒ void
This method returns an undefined value.
Start the Vizcore server with the given scene file.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/vizcore/cli.rb', line 130 def start(scene_file = nil) manifest = load_project_manifest([:manifest]) profile = [:profile] load_manifest_plugins(manifest, profile: profile) defaults = manifest&.config_defaults(profile: profile) || {} config = Config.new( scene_file: scene_file || defaults[:scene_file], host: .fetch(:host), port: .fetch(:port), audio_source: [:audio_source] || defaults[:audio_source] || Config::DEFAULT_AUDIO_SOURCE, audio_file: [:audio_file] || defaults[:audio_file], audio_device: [:audio_device] || defaults[:audio_device], feature_file: [:feature_file] || defaults[:feature_file], control_preset: [:control_preset] || defaults[:control_preset], plugin_assets: defaults[:plugin_assets], noise_gate: .fetch(:noise_gate), bpm: [:bpm], bpm_lock: .fetch(:bpm_lock), osc_port: [:osc_port] || defaults[:osc_port], reload: .fetch(:reload), projector_mode: .fetch(:projector) ) Server::Runner.new(config).run rescue ArgumentError => e raise Thor::Error, e. end |
#validate(scene_file) ⇒ void
This method returns an undefined value.
Load and validate a scene DSL file without starting the server.
281 282 283 284 285 286 287 |
# File 'lib/vizcore/cli.rb', line 281 def validate(scene_file) result = Vizcore::CLISupport::SceneDiagnostics.new(scene_file: scene_file).validate print_issues(result.issues) raise Thor::Error, "scene validation failed" unless result.valid? say("Scene valid: #{scene_file}") end |