Skip to content

Commit

Permalink
Add "no reply retry" count for autodetect/test
Browse files Browse the repository at this point in the history
Seems like it takes a few messages to get the PODxt going. The test
and autodetect logic send a UDI message and expect a reply. When one
doesn't come, this means that no device answered, no device found.

With this change, the autodetect and test logic is changes to try
again if there was no reply (and no error) as many times as the
`MidiIn` requests. We set no reply retry count for MIDI devices to 0
and for USB devices to 3. Well-behaving USB device (PocketPOD) answer
right away, but this retry seems enough to get the PODxt talking.

PS. Maybe we just need to give PODxt more time after a reset &
configure to start talking, but let's try this first.
  • Loading branch information
arteme committed Nov 20, 2024
1 parent 6ce806e commit 03b5cd8
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 11 deletions.
59 changes: 48 additions & 11 deletions core/src/midi_io.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use midir::*;
use anyhow::*;
use core::result::Result::Ok;
use regex::Regex;
use std::str::FromStr;
use std::time::Duration;
Expand All @@ -21,6 +22,8 @@ pub trait MidiIn {
fn name(&self) -> String;
async fn recv(&mut self) -> Option<Vec<u8>>;
fn close(&mut self);

fn no_reply_retry(&self) -> usize;
}

#[async_trait]
Expand Down Expand Up @@ -97,6 +100,10 @@ impl MidiIn for MidiInPort {
});
self.rx.close();
}

fn no_reply_retry(&self) -> usize {
0
}
}

impl Drop for MidiInPort {
Expand Down Expand Up @@ -307,7 +314,27 @@ fn list_ports<T: MidiIO>(midi: T) -> Result<Vec<String>> {
const DETECT_DELAY: Duration = Duration::from_millis(1000);

async fn detect(in_ports: &mut [BoxedMidiIn], out_ports: &mut [BoxedMidiOut]) -> Result<(Vec<(usize, &'static Config)>, Option<String>)> {
detect_with_channel(in_ports, out_ports, Channel::all()).await
let mut no_reply_retries = in_ports.iter().map(|m| m.no_reply_retry()).max().unwrap_or(0);
let mut res;

loop {
res = detect_with_channel(in_ports, out_ports, Channel::all()).await;
if let Ok((replied, error)) = &res {
if error.is_none() && replied.is_empty() {
// no reply retry
if no_reply_retries == 0 {
break
} else {
no_reply_retries -= 1;
continue
}
} else {
break;
}
}
}

res
}

async fn detect_with_channel(in_ports: &mut [BoxedMidiIn], out_ports: &mut [BoxedMidiOut], channel: u8) -> Result<(Vec<(usize, &'static Config)>, Option<String>)> {
Expand Down Expand Up @@ -559,22 +586,32 @@ pub async fn autodetect_with_ports(in_ports: Vec<BoxedMidiIn>, out_ports: Vec<Bo
}

pub async fn test_with_ports(in_port: BoxedMidiIn, out_port: BoxedMidiOut, channel: u8, config: &Config) -> Result<(BoxedMidiIn, BoxedMidiOut, u8)> {
let mut no_response_retries = in_port.no_reply_retry();
let mut in_ports = vec![in_port];
let mut out_ports = vec![out_port];

let (rep, error) = detect_with_channel(
in_ports.as_mut_slice(), out_ports.as_mut_slice(), channel
).await?;
if rep.len() == 0 {
if let Some(e) = error {
bail!("{}", e);
loop {
let (rep, error) = detect_with_channel(
in_ports.as_mut_slice(), out_ports.as_mut_slice(), channel
).await?;
if rep.len() == 0 {
if let Some(e) = error {
bail!("{}", e);
} else {
if no_response_retries == 0 {
bail!("Received no device response");
} else {
no_response_retries -= 1;
continue
}
}
}
if *rep[0].1 != *config {
bail!("Incorrect device type");
} else {
bail!("Received no device response");
break
}
}
if *rep[0].1 != *config {
bail!("Incorrect device type");
}

Ok((in_ports.remove(0), out_ports.remove(0), channel))
}
Expand Down
4 changes: 4 additions & 0 deletions usb/src/dev_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,10 @@ impl MidiIn for DeviceInput {
fn close(&mut self) {
debug!("midi in close - nop");
}

fn no_reply_retry(&self) -> usize {
3
}
}

#[async_trait]
Expand Down

0 comments on commit 03b5cd8

Please sign in to comment.