Я пробовал некоторые другие музыкальные приложения. Некоторые представлены несколькими блоками, некоторые представлены одним блоком с входами и выходами. SetBFree — пример последнего (см. ниже). Мое приложение должно получать входные MIDI-сигналы, изменять их и отправлять в другие приложения. Поэтому я бы хотел, чтобы порты были сгруппированы в одном блоке, группируя его входные и выходные порты.

Возможно ли это? Как я могу контролировать, как мое приложение распознается приложениями патч-бэя?
Я уже пытался использовать одно и то же имя в MidiInput::new и MidiOutput::new, но эффект тот же — за исключением того, что система добавляет к его имени случайное целое число.
Буду признателен за любые подсказки, в том числе пример кода C/C++ или других MIDI-библиотек или документации. Единственное условие — он должен работать в Linux.
Мой код (немного быстрый и грязный, адаптированный из Midir):
use std::error::Error;
use std::io::{stdin, stdout, Write};
use midir::{Ignore, MidiInput, MidiIO, MidiOutput};
fn main() {
match run() {
Ok(_) => (),
Err(err) => println!("Error: {}", err),
}
}
fn get_port(midi_io: &M) -> Result {
// Get an input port (read from console if multiple are available)
let in_ports = midi_io.ports();
let in_port = match in_ports.len() {
0 => return Err("no input port found".into()),
1 => {
println!(
"Choosing the only available input port: {}",
midi_io.port_name(&in_ports[0]).unwrap()
);
&in_ports[0]
}
_ => {
println!("\nAvailable input ports:");
for (i, p) in in_ports.iter().enumerate() {
println!("{}: {}", i, midi_io.port_name(p).unwrap());
}
print!("Please select input port: ");
stdout().flush()?;
let mut input = String::new();
stdin().read_line(&mut input)?;
in_ports
.get(input.trim().parse::()?)
.ok_or("invalid input port selected")?
}
};
Ok(in_port.clone())
}
fn run() -> Result {
let mut input = String::new();
let mut midi_in = MidiInput::new("midir reading input")?;
let mut midi_out = MidiOutput::new("midir reading output")?;
midi_in.ignore(Ignore::None);
let in_port = get_port(&midi_in).unwrap();
let out_port = get_port(&midi_out).unwrap();
println!("\nOpening input connection");
let in_port_name = midi_in.port_name(&in_port)?;
// _conn_in needs to be a named parameter, because it needs to be kept alive until the end of the scope
let _conn_in = midi_in.connect(
&in_port,
"midir-read-input",
move |stamp, message, _| {
println!("{}: {:?} (len = {})", stamp, message, message.len());
},
(),
)?;
println!("\nOpening output connection");
let _conn_out = midi_out.connect(
&out_port,
"midir-write-output",
);
println!(
"Connection open, reading input from '{}' (press enter to exit) ...",
in_port_name
);
input.clear();
stdin().read_line(&mut input)?; // wait for next enter key press
println!("Closing connection");
Ok(())
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... ications-i