diff --git a/src/cli.rs b/src/cli.rs index 30c18b9..9cefa8c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -6,6 +6,9 @@ use std::path::PathBuf; #[clap(author, version, about, long_about = None)] pub struct Cli { #[clap(value_parser)] - pub map_file: PathBuf, + pub map_file: Option, + /// List devices and exit + #[clap(long, short, action)] + pub list: bool, } diff --git a/src/config/device.rs b/src/config/device.rs index b9ee9e0..965dc5e 100644 --- a/src/config/device.rs +++ b/src/config/device.rs @@ -55,17 +55,14 @@ impl TryFrom for DeviceConfig { fn try_from(v: DeviceConfigSerializer) -> Result { Ok(DeviceConfig { identifier: { - if v.name.is_some() { - Identifier::Name(v.name.unwrap()) - } - else if v.regex.is_some() { - Identifier::Regex(regex::Regex::new(&v.regex.unwrap())?) - } - else if v.addr.is_some() { - Identifier::Addr(v.addr.unwrap()) - } - else { - Identifier::All + match (v.name, v.regex, v.addr) { + (Some(_), Some(_), _ ) => return Err(Error::IncompatibleArgs("name","regex")), + (Some(_), None , Some(_)) => return Err(Error::IncompatibleArgs("name","addr")), + (None , Some(_), Some(_)) => return Err(Error::IncompatibleArgs("regex","addr")), + (Some(n), None, None ) => Identifier::Name(n), + (None, Some(r), None ) => Identifier::Regex(regex::Regex::new(&r)?), + (None, None , Some(a)) => Identifier::Addr(a), + (None, None, None ) => Identifier::All, } }, max_connections: v.max_connections, diff --git a/src/error.rs b/src/error.rs index c1d5c75..861a4d1 100644 --- a/src/error.rs +++ b/src/error.rs @@ -31,6 +31,10 @@ pub enum Error { RemapTooBig(f64), #[error("remap value is too low. Minimum value is {}", i64::MIN)] RemapTooLow(f64), + #[error("'{0}' and '{1}' are incompatible")] + IncompatibleArgs(&'static str, &'static str), + #[error("no map file was provided")] + NoArgument, #[error("pipe error")] Pipe, #[error("unknown error")] diff --git a/src/main.rs b/src/main.rs index 4650771..360867d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,13 +21,29 @@ use cli::Cli; fn main() { let c = Cli::parse(); + if c.list { + err_handle(run::list_devices()); + return; + } + let map_file = err_handle( + c.map_file.ok_or(Error::NoArgument) + ); loop { - match run_file(&c.map_file) { - Ok(_) => (), - Err(err) => { - eprintln!("Error: {}", err); - std::process::exit(1); - } + err_handle( + run_file(&map_file) + ); + } +} + +fn err_handle(r: Result) -> T +where + E: std::fmt::Display +{ + match r { + Ok(v) => v, + Err(err) => { + eprintln!("Error: {}", err); + std::process::exit(1); } } } diff --git a/src/midi/mod.rs b/src/midi/mod.rs index 6e00571..9326a9e 100644 --- a/src/midi/mod.rs +++ b/src/midi/mod.rs @@ -45,6 +45,15 @@ pub enum MidiPortHandler { ALSA(MidiPort), } +impl std::fmt::Display for MidiPortHandler { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + MidiPortHandler::ALSA(p) => write!(f, "{} {}:{}", p.name, p.addr.client, p.addr.port), + _ => todo!(), + } + } +} + pub enum MidiHandler { ALSA(MidiInputAlsa), } diff --git a/src/run.rs b/src/run.rs index cdb3dc4..c0b3621 100644 --- a/src/run.rs +++ b/src/run.rs @@ -24,6 +24,15 @@ pub fn cross_shell(cmd: &str) -> Vec { ).collect() } +pub fn list_devices() -> Result<(), Error> { + let input = MidiHandler::new("rmidimap")?; + let ports = input.ports()?; + for p in ports { + println!("{}", p); + } + Ok(()) +} + pub fn run_config(conf: &Config) -> Result<(), Error> { let cfevmap: Vec = conf.devices.iter().map(|x| (x, EventMap::from(x),