Class: Vizcore::Server::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/vizcore/server/runner.rb

Overview

Bootstraps Rack/Puma, audio pipeline, scene reload, and MIDI runtime.

Instance Method Summary collapse

Constructor Details

#initialize(config, output: $stdout) ⇒ Runner

Returns a new instance of Runner.

Parameters:



20
21
22
23
24
25
26
27
28
29
# File 'lib/vizcore/server/runner.rb', line 20

def initialize(config, output: $stdout)
  @config = config
  @output = output
  @shader_source_resolver = Vizcore::DSL::ShaderSourceResolver.new
  @scene_catalog_mutex = Mutex.new
  @scene_catalog = []
  @runtime_globals_mutex = Mutex.new
  @runtime_globals = {}
  @live_controls = { "blackout" => false, "freeze" => false }
end

Instance Method Details

#runvoid

This method returns an undefined value.

Run server lifecycle until interrupted.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/vizcore/server/runner.rb', line 36

def run
  validate_scene_file!
  validate_feature_settings!
  validate_control_preset_settings!
  validate_plugin_asset_settings!
  validate_audio_settings!
  definition = load_definition!
  control_preset = load_control_preset
  replace_runtime_globals(globals_for(definition))
  @tap_tempo_key = tap_tempo_key(definition)
  scene = first_scene(definition) || fallback_scene

  app = RackApp.new(
    frontend_root: Vizcore.frontend_root,
    audio_source: runtime_audio_source,
    audio_file: runtime_audio_file,
    scene_names: scene_names_for(definition),
    tap_tempo_key: @tap_tempo_key,
    key_mappings: key_mappings_for(definition),
    globals: runtime_globals_snapshot,
    control_preset: control_preset,
    control_preset_path: @config.control_preset,
    plugin_assets: @config.plugin_assets,
    projector_mode: @config.projector_mode
  )
  server = Puma::Server.new(app, nil, min_threads: 0, max_threads: 4)
  server.add_tcp_listener(@config.host, @config.port)
  server.run

  input_manager = build_input_manager
  broadcaster = FrameBroadcaster.new(
    scene_name: scene[:name].to_s,
    scene_layers: scene[:layers],
    scene_catalog: definition[:scenes],
    transitions: definition[:transitions],
    input_manager: input_manager,
    analysis_pipeline: replay_pipeline,
    noise_gate: @config.noise_gate,
    audio_normalize: audio_normalize_settings(definition),
    bpm: bpm_setting(definition),
    bpm_lock: bpm_lock_setting(definition),
    error_reporter: ->(message) { @output.puts(message) }
  )
  replace_scene_catalog(definition[:scenes])
  if file_transport_enabled?
    broadcaster.sync_transport(playing: false, position_seconds: 0.0)
  end
  broadcaster.start
  register_client_message_handler(broadcaster)
  midi_runtime = start_midi_runtime(definition, broadcaster)
  osc_runtime = start_osc_runtime(broadcaster)
  watcher = if @config.reload?
              start_scene_watcher(broadcaster, definition: definition) do |updated_definition|
                midi_runtime = refresh_midi_runtime(midi_runtime, updated_definition, broadcaster)
              end
            end

  @output.puts("Vizcore server listening at http://#{@config.host}:#{@config.port}")
  @output.puts("Projector output: http://#{@config.host}:#{@config.port}/projector")
  @output.puts("Control panel: http://#{@config.host}:#{@config.port}/control")
  @output.puts("Scene: #{scene[:name]}")
  @output.puts("Hot reload: #{@config.reload? ? 'enabled' : 'disabled'}")
  @output.puts("Audio playback: http://#{@config.host}:#{@config.port}/audio-file") if file_transport_enabled?
  @output.puts("Feature replay: #{@config.feature_file}") if feature_replay?
  @output.puts("OSC sync: udp://#{@config.host}:#{@config.osc_port}") if osc_runtime
  @output.puts("Press Ctrl+C to stop.")

  wait_for_interrupt
ensure
  Vizcore::Server::WebSocketHandler.clear_message_handler
  stop_osc_runtime(osc_runtime)
  stop_midi_runtime(midi_runtime)
  watcher&.stop
  broadcaster&.stop
  server&.stop(true)
end