use crate::*; use ConnectName::*; use ConnectScope::*; use ConnectStatus::*; mod audio; pub use self::audio::*; mod midi; pub use self::midi::*; mod connect; pub use self::connect::*; mod register; pub use self::register::*; pub trait JackPort: HasJack<'static> { type Port: PortSpec + Default; type Pair: PortSpec + Default; fn new (jack: &Jack<'static>, name: &impl AsRef, connect: &[Connect]) -> Usually where Self: Sized; fn register (jack: &Jack<'static>, name: &impl AsRef) -> Usually> { jack.with_client(|c|c.register_port::(name.as_ref(), Default::default())) .map_err(|e|e.into()) } fn port_name (&self) -> &Arc; fn connections (&self) -> &[Connect]; fn port (&self) -> &Port; fn port_mut (&mut self) -> &mut Port; fn into_port (self) -> Port where Self: Sized; fn close (self) -> Usually<()> where Self: Sized { let jack = self.jack().clone(); Ok(jack.with_client(|c|c.unregister_port(self.into_port()))?) } fn ports (&self, re_name: Option<&str>, re_type: Option<&str>, flags: PortFlags) -> Vec { self.with_client(|c|c.ports(re_name, re_type, flags)) } fn port_by_id (&self, id: u32) -> Option> { self.with_client(|c|c.port_by_id(id)) } fn port_by_name (&self, name: impl AsRef) -> Option> { self.with_client(|c|c.port_by_name(name.as_ref())) } fn connect_to_matching <'k> (&'k self) -> Usually<()> { for connect in self.connections().iter() { match &connect.name { Some(Exact(name)) => { *connect.status.write().unwrap() = self.connect_exact(name)?; }, Some(RegExp(re)) => { *connect.status.write().unwrap() = self.connect_regexp(re, connect.scope)?; }, _ => {}, }; } Ok(()) } fn connect_exact <'k> (&'k self, name: &str) -> Usually, Arc, ConnectStatus)>> { self.with_client(move|c|{ let mut status = vec![]; for port in c.ports(None, None, PortFlags::empty()).iter() { if port.as_str() == &*name { if let Some(port) = c.port_by_name(port.as_str()) { let port_status = self.connect_to_unowned(&port)?; let name = port.name()?.into(); status.push((port, name, port_status)); if port_status == Connected { break } } } } Ok(status) }) } fn connect_regexp <'k> ( &'k self, re: &str, scope: Option ) -> Usually, Arc, ConnectStatus)>> { self.with_client(move|c|{ let mut status = vec![]; let ports = c.ports(Some(&re), None, PortFlags::empty()); for port in ports.iter() { if let Some(port) = c.port_by_name(port.as_str()) { let port_status = self.connect_to_unowned(&port)?; let name = port.name()?.into(); status.push((port, name, port_status)); if port_status == Connected && scope == Some(One) { break } } } Ok(status) }) } /** Connect to a matching port by name. */ fn connect_to_name (&self, name: impl AsRef) -> Usually { self.with_client(|c|if let Some(ref port) = c.port_by_name(name.as_ref()) { self.connect_to_unowned(port) } else { Ok(Missing) }) } /** Connect to a matching port by reference. */ fn connect_to_unowned (&self, port: &Port) -> Usually { self.with_client(|c|Ok(if let Ok(_) = c.connect_ports(self.port(), port) { Connected } else if let Ok(_) = c.connect_ports(port, self.port()) { Connected } else { Mismatch })) } /** Connect to an owned matching port by reference. */ fn connect_to_owned (&self, port: &Port) -> Usually { self.with_client(|c|Ok(if let Ok(_) = c.connect_ports(self.port(), port) { Connected } else if let Ok(_) = c.connect_ports(port, self.port()) { Connected } else { Mismatch })) } }