From 8aacf27c762306d51d9c8c3311225948881163ae Mon Sep 17 00:00:00 2001 From: Nathan Leiby Date: Sun, 17 Nov 2024 14:10:13 -0800 Subject: [PATCH] feat: allow refreshing attached midi device this is an indirect solution to the problem of "get midi working" in WASM, but it's also generally useful, I think. It seems like MIDI wasn't connecting before in browser because the device wasn't immediately available. Trying again in a few seconds, it works. I was able to determine this by recreating this polling example locally /~https://github.com/Boddlnagg/midir/blob/master/examples/browser/src/lib.rs --- src/egui_ui.rs | 21 +++++++++++++++++++++ src/events.rs | 2 ++ src/game.rs | 9 +++++++-- src/main.rs | 8 +++++++- src/midi.rs | 2 ++ src/midi_input_handler.rs | 20 ++++++++++++++++++++ 6 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/egui_ui.rs b/src/egui_ui.rs index 0996ebb..d7bbd9d 100644 --- a/src/egui_ui.rs +++ b/src/egui_ui.rs @@ -55,6 +55,7 @@ pub struct UIState { miss_margin: f64, hide_empty_tracks: bool, + midi_device_name: String, // user interaction state // is_dragging, } @@ -96,6 +97,8 @@ impl Default for UIState { miss_margin: 0., hide_empty_tracks: false, + + midi_device_name: "".to_string(), } } } @@ -173,6 +176,10 @@ impl UIState { pub fn set_hide_empty_tracks(&mut self, val: bool) { self.hide_empty_tracks = val; } + + pub fn set_midi_device_name(&mut self, val: &str) { + self.midi_device_name = val.to_owned(); + } } pub fn draw_ui(ctx: &egui::Context, ui_state: &UIState, events: &mut Vec) { @@ -413,6 +420,20 @@ fn draw_right_panel(ctx: &egui::Context, ui_state: &UIState, events: &mut Vec UIState { +pub fn compute_ui_state(gs: &GameState, audio: &Audio, midi_device_name: &str) -> UIState { let selector_vec = gs.loops.iter().map(|(name, _)| name.to_string()).collect(); let mut ui_state = UIState::default().selector_vec(&selector_vec); ui_state.set_selected_idx(gs.selected_loop_idx); @@ -116,6 +117,7 @@ pub fn compute_ui_state(gs: &GameState, audio: &Audio) -> UIState { ui_state.set_miss_margin(gs.miss_margin); ui_state.set_is_help_visible(gs.flags.help_visible); ui_state.set_hide_empty_tracks(gs.flags.hide_empty_tracks); + ui_state.set_midi_device_name(midi_device_name); ui_state } @@ -183,7 +185,6 @@ fn log_user_metric(user_metric: &UserMetric) -> Result<(), Box> { let data = serde_json::to_string(&user_metric)?; let current_dir = env::current_dir()?; log::info!("user_metric (json) = {}", data); - let dir = current_dir.join("log"); fs::create_dir_all(&dir)?; let fpath = dir.join(format!("user_metric-{}.json", user_metric.system_time_ms)); @@ -202,6 +203,7 @@ pub fn process_user_events( events: &Vec, correct_margin: &mut f64, miss_margin: &mut f64, + midi_input: &mut MidiInputHandler, ) -> Result<(), Box> { for event in events { info!("[user event] {:?}", event); @@ -282,6 +284,9 @@ pub fn process_user_events( Events::ToggleEmptyTrackVisibility => { flags.hide_empty_tracks = !flags.hide_empty_tracks; } + Events::RefreshConnectedMidiDevice => { + midi_input.refresh_connected_device(); + } } } diff --git a/src/main.rs b/src/main.rs index 30d7899..7b8bd2e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -133,12 +133,18 @@ async fn main() -> Result<(), Box> { &events, &mut gs.correct_margin, &mut gs.miss_margin, + &mut midi_input, )?; audio.schedule(&gs.voices).await?; // render UI - ui.render(&compute_ui_state(&gs, &audio)); + ui.render(&compute_ui_state( + &gs, + &audio, + midi_input.attached_device_name(), + )); + macroquad_console.update(&mut my_cvars); if gs.flags.ui_debug_mode { fps_tracker.update(); diff --git a/src/midi.rs b/src/midi.rs index ac89efe..42f89c6 100644 --- a/src/midi.rs +++ b/src/midi.rs @@ -40,7 +40,9 @@ impl MidiInputDataRaw { impl MidiInput { pub fn new() -> Option { + log::info!("MidiInput::new()"); let midi_input = midir::MidiInput::new("Input device").unwrap(); + log::info!("port count {}", midi_input.port_count()); // grab first device let input_port = match midi_input.ports().into_iter().next() { Some(port) => port, diff --git a/src/midi_input_handler.rs b/src/midi_input_handler.rs index a33e412..94d4fef 100644 --- a/src/midi_input_handler.rs +++ b/src/midi_input_handler.rs @@ -30,6 +30,26 @@ impl MidiInputHandler { Self { midi_input } } + pub fn refresh_connected_device(&mut self) { + let mut midi_input = MidiInput::new(); + match midi_input { + Some(ref mut midi_input) => { + midi_input.connect(); + } + None => log::warn!("warning: no midi input device found"), + } + + self.midi_input = midi_input; + } + + pub fn attached_device_name(&self) -> &str { + if let Some(midi_input) = &self.midi_input { + midi_input.get_device_name() + } else { + "none" + } + } + /// convert any user input from the last frame into Events pub fn process(&mut self) -> Vec { let mut events: Vec = vec![];