Skip to content

Common trait for obtaining port ID #188

@frekvencia

Description

@frekvencia

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)),
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions