-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use unique port identifiers #32
Comments
Why is it not enough to identify ports by names? :) What I always do is find the port by name first, before calling pub fn open_input(port_name: &str) -> Result<(MidiInputConnection<()>, Receiver<ChanMsg>), Box<Error + Send + Sync>> {
let mut midi = MidiInput::new("")?;
midi.ignore(Ignore::None); // All
let port = (|| {
for i in 0..midi.port_count() {
if let Ok(name) = midi.port_name(i) {
if name == port_name {
return Some(i);
}
}
}
return None;
})().ok_or(format!("midi input port '{}' not found", port_name))?;
let (tx_midi_to_daw, rx_midi_to_daw) = channel();
Ok((midi.connect(port, "", move |_stamp, msg, _| {
if let Some(msg) = LowLvlMsg::parse(msg) {
tx_midi_to_daw.send(ChanMsg::from(msg)).unwrap();
}
}, ()).map_err(|e| e.kind())?, rx_midi_to_daw))
}
pub fn open_output(port_name: &str) -> Result<MidiOutputConnection, Box<Error + Send + Sync>> {
let midi = MidiOutput::new("")?;
let port = (|| {
for i in 0..midi.port_count() {
if let Ok(name) = midi.port_name(i) {
if name == port_name {
return Some(i);
}
}
}
return None;
})().ok_or(format!("midi output port '{}' not found", port_name))?;
Ok(midi.connect(port, "").map_err(|e| e.kind())?)
} |
@Boscop Because multiple devices of the same type may have the same name. 😞 There are better ways to identify ports, as you can see in the table above, but they differ by backend, and therefore need to be wrapped in a cross-platform way. I have a prototype implementation for Windows in https://github.com/Boddlnagg/midir/tree/port-ids, if you want to see how this looks (have a look at the changes in src/common.rs to see the API changes). For configuration you can store the port name ... there's not really a good way to deal with multiple devices of the same name/type, because their internal device ID will change when they are plugged out and back in again. But that is tracked by #34. |
Status update: The port-ids branch contains an implementation of this change for all backends except CoreMIDI (which I didn't have the time to do yet). |
Implemented in #38 |
@Boddlnagg I just updated my midir dep from 0.3 to 0.5. So what is different exactly regarding ports? The Btw, now I'm starting to use multiple midi controllers of the same kind, who all have the same port names, so I need to extend my config to be able to specify which one is meant (e.g. I could add a |
Actually, version 0.5 does not yet contain this change. Don't ask me why, but there hasn't been a release for a long while now. I'll try to release a new version soon™. You can try to work with a git dependency directly if you want to try it out before that. |
It helps, because you can now implement that logic to "choose the |
I just published version 0.6.0, containing this change! |
@Boddlnagg Thanks. Btw, how exactly are these new identifiers different? And another question about the
What should I pass as the name and what exactly is it used for? For port identification during connection? I always passed |
Yeah, sorry, it's correct that you could have implemented that with v0.5. What's handled better now is the case where you display the devices in a list and let the user select one, then connect to the selected one. By the time the selection has happened, a device might have been removed so that the indices are shifted, and then the selection would be applied incorrectly. This solution is bascially what thestk/rtmidi#30 tries for RtMidi.
It's not used on Windows, but with the ALSA, CoreMIDI and Jack backends, ports in the backend actually have names, which are sometimes displayed to the user. For example, for ALSA it's passed to |
@Boddlnagg Thanks! I have multi-device operation working now. Btw, do you know if it's always the case that "when multiple midi devices of the same model are connected simultaneously, the relative order between them is the same in the list of input and output ports (as returned by midir)"? Are midi ports always appended at the end of the OS's port list when the device gets plugged in? |
I can't really answer these questions, since it depends on the respective platform backends. It might be that some or even all platforms behave that way, but I really don't know it. I guess you would have to look into the OS/platform documentation, and honestly I doubt that this is documented at all ... at least I haven't come across any statement regarding the order of ports while reading platform documentation ... sorry 😕 |
Ports should not be identified by index (for calls to
port_name
andconnect
), but rather by some backend-specific identifier that does not change when the order of devices changes.These identifiers do not need to be persistent across sessions (e.g. to write them to a configuration file), because that would be quite a bit harder and can be added later.
The following identifiers could work for each platform:
GetDevCaps
) and interface name (another string, see https://docs.microsoft.com/de-de/windows-hardware/drivers/audio/obtaining-a-device-interface-name). This requires a linear search when callingconnect()
, but I think that's not a problem.The platform-specific representation could be wrapped in a
PortId
struct.The text was updated successfully, but these errors were encountered: