I wrote a function that can pick out a port based on index, id or name. There already is a MidiIO trait which enables a lot of this, but I had add my own MidiPort trait as a workaround, and implement it for both MidiInputPort and MidiOutputPort.
The trait was needed because I could not get to the id on the ports otherwise. MidiInputPort and MidiOutputPort each implement their own id(&self) -> String.
Would it be possible to add id to MidiInputPort and MidiOutputPort via a trait instead of implementing it individually for the structs?
Here is my workaround in case someone also needs to solve this problem:
pub enum Error {
PortIndexOutOfBounds(usize),
UnknownPortIdOrName(String),
}
pub enum Port {
Index(usize),
IdOrName(String),
}
trait MidiPort {
fn get_id(&self) -> String;
}
impl MidiPort for MidiInputPort {
fn get_id(&self) -> String {
self.id()
}
}
impl MidiPort for MidiOutputPort {
fn get_id(&self) -> String {
self.id()
}
}
fn pick_port<T>(midi_io: &T, port: Port) -> Result<T::Port, Error>
where
T: MidiIO,
T::Port: MidiPort,
{
let mut ports = midi_io.ports();
match port {
Port::Index(index) => (index < ports.len())
.then(|| ports.swap_remove(index))
.ok_or(Error::PortIndexOutOfBounds(index)),
Port::IdOrName(id_or_name) => ports
.into_iter()
.find(|port| {
port.get_id() == id_or_name || midi_io.port_name(port).is_ok_and(|name| name == id_or_name)
})
.ok_or(Error::UnknownPortIdOrName(id_or_name)),
}
}
I wrote a function that can pick out a port based on index, id or name. There already is a
MidiIOtrait which enables a lot of this, but I had add my ownMidiPorttrait as a workaround, and implement it for bothMidiInputPortandMidiOutputPort.The trait was needed because I could not get to the
idon the ports otherwise.MidiInputPortandMidiOutputPorteach implement their ownid(&self) -> String.Would it be possible to add
idtoMidiInputPortandMidiOutputPortvia a trait instead of implementing it individually for the structs?Here is my workaround in case someone also needs to solve this problem: