diff --git a/src/jack.rs b/src/jack.rs index bf729a57..5173607f 100644 --- a/src/jack.rs +++ b/src/jack.rs @@ -13,10 +13,6 @@ pub mod activate; pub(crate) use self::activate::*; pub use self::activate::JackActivate; -pub mod client; -pub(crate) use self::client::*; -pub use self::client::JackConnection; - pub mod jack_event; pub(crate) use self::jack_event::*; @@ -61,56 +57,69 @@ pub trait Audio: Send + Sync { } } +pub type DynamicAsyncClient = AsyncClient; -/// Trait for things that wrap a JACK client. -pub trait AudioEngine { +pub type DynamicAudioHandler = ClosureProcessHandler<(), BoxedAudioHandler>; - fn transport (&self) -> Transport { - self.client().transport() +pub type BoxedAudioHandler = Box Control + Send>; + +/// Wraps [Client] or [DynamicAsyncClient] in place. +#[derive(Debug)] +pub enum JackConnection { + /// Before activation. + Inactive(Client), + /// During activation. + Activating, + /// After activation. Must not be dropped for JACK thread to persist. + Active(DynamicAsyncClient), +} + +from!(|jack: JackConnection|Client = match jack { + JackConnection::Inactive(client) => client, + JackConnection::Activating => panic!("jack client still activating"), + JackConnection::Active(_) => panic!("jack client already activated"), +}); + +impl JackConnection { + pub fn new (name: &str) -> Usually { + let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?; + Ok(Self::Inactive(client)) } - - fn port_by_name (&self, name: &str) -> Option> { + /// Return the internal [Client] handle that lets you call the JACK API. + pub fn client (&self) -> &Client { + match self { + Self::Inactive(ref client) => client, + Self::Activating => panic!("jack client has not finished activation"), + Self::Active(ref client) => client.as_client(), + } + } + /// Bind a process callback to a `JackConnection::Inactive`, + /// consuming it and returning a `JackConnection::Active`. + /// + /// Needs work. Strange ownership situation between the callback + /// and the host object. + pub fn activate ( + self, + mut cb: impl FnMut(&Arc>, &Client, &ProcessScope) -> Control + Send + 'static, + ) -> Usually>> + where + Self: Send + Sync + 'static + { + let client = Client::from(self); + let state = Arc::new(RwLock::new(Self::Activating)); + let event = Box::new(move|_|{/*TODO*/}) as Box; + let events = Notifications(event); + let frame = Box::new({let state = state.clone(); move|c: &_, s: &_|cb(&state, c, s)}); + let frames = ClosureProcessHandler::new(frame as BoxedAudioHandler); + *state.write().unwrap() = Self::Active(client.activate_async(events, frames)?); + Ok(state) + } + pub fn port_by_name (&self, name: &str) -> Option> { self.client().port_by_name(name) } - - fn register_port (&self, name: &str, spec: PS) -> Usually> { + pub fn register_port (&self, name: &str, spec: PS) -> Usually> { Ok(self.client().register_port(name, spec)?) } - - fn client (&self) -> &Client; - - fn activate ( - self, - process: impl FnMut(&Arc>, &Client, &ProcessScope) -> Control + Send + 'static - ) -> Usually>> where Self: Send + Sync + 'static; - - fn thread_init (&self, _: &Client) {} - - unsafe fn shutdown (&mut self, _status: ClientStatus, _reason: &str) {} - - fn freewheel (&mut self, _: &Client, _enabled: bool) {} - - fn client_registration (&mut self, _: &Client, _name: &str, _reg: bool) {} - - fn port_registration (&mut self, _: &Client, _id: PortId, _reg: bool) {} - - fn ports_connected (&mut self, _: &Client, _a: PortId, _b: PortId, _are: bool) {} - - fn sample_rate (&mut self, _: &Client, _frames: Frames) -> Control { - Control::Continue - } - - fn port_rename (&mut self, _: &Client, _id: PortId, _old: &str, _new: &str) -> Control { - Control::Continue - } - - fn graph_reorder (&mut self, _: &Client) -> Control { - Control::Continue - } - - fn xrun (&mut self, _: &Client) -> Control { - Control::Continue - } } //////////////////////////////////////////////////////////////////////////////////// @@ -375,3 +384,17 @@ pub trait AudioEngine { //self //} //} + +///// A UI component that may be associated with a JACK client by the `Jack` factory. +//pub trait AudioComponent: Component + Audio { + ///// Perform type erasure for collecting heterogeneous devices. + //fn boxed(self) -> Box> + //where + //Self: Sized + 'static, + //{ + //Box::new(self) + //} +//} + +///// All things that implement the required traits can be treated as `AudioComponent`. +//impl + Audio> AudioComponent for W {} diff --git a/src/jack/activate.rs b/src/jack/activate.rs index 5b7e4923..03a7f2ef 100644 --- a/src/jack/activate.rs +++ b/src/jack/activate.rs @@ -34,17 +34,3 @@ impl JackActivate for JackConnection { Ok(target) } } - -/// A UI component that may be associated with a JACK client by the `Jack` factory. -pub trait AudioComponent: Component + Audio { - /// Perform type erasure for collecting heterogeneous devices. - fn boxed(self) -> Box> - where - Self: Sized + 'static, - { - Box::new(self) - } -} - -/// All things that implement the required traits can be treated as `AudioComponent`. -impl + Audio> AudioComponent for W {} diff --git a/src/jack/client.rs b/src/jack/client.rs deleted file mode 100644 index 674737fd..00000000 --- a/src/jack/client.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::*; -pub type DynamicAsyncClient = AsyncClient; -pub type DynamicAudioHandler = ClosureProcessHandler<(), BoxedAudioHandler>; -pub type BoxedAudioHandler = Box Control + Send>; -/// Wraps [Client] or [DynamicAsyncClient] in place. -#[derive(Debug)] -pub enum JackConnection { - /// Before activation. - Inactive(Client), - /// During activation. - Activating, - /// After activation. Must not be dropped for JACK thread to persist. - Active(DynamicAsyncClient), -} -from!(|jack: JackConnection|Client = match jack { - JackConnection::Inactive(client) => client, - JackConnection::Activating => panic!("jack client still activating"), - JackConnection::Active(_) => panic!("jack client already activated"), -}); -impl JackConnection { - pub fn new (name: &str) -> Usually { - let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?; - Ok(Self::Inactive(client)) - } -} -impl AudioEngine for JackConnection { - /// Return the internal [Client] handle that lets you call the JACK API. - fn client(&self) -> &Client { - match self { - Self::Inactive(ref client) => client, - Self::Activating => panic!("jack client has not finished activation"), - Self::Active(ref client) => client.as_client(), - } - } - /// Bind a process callback to a `JackConnection::Inactive`, - /// turning it into a `JackConnection::Active`. Needs work. - /// Strange ownership situation between the callback and - /// the host object. - fn activate( - self, - mut cb: impl FnMut(&Arc>, &Client, &ProcessScope) -> Control + Send + 'static, - ) -> Usually>> - where - Self: Send + Sync + 'static - { - let client = Client::from(self); - let state = Arc::new(RwLock::new(Self::Activating)); - let event = Box::new(move|_|{/*TODO*/}) as Box; - let events = Notifications(event); - let frame = Box::new({let state = state.clone(); move|c: &_, s: &_|cb(&state, c, s)}); - let frames = ClosureProcessHandler::new(frame as BoxedAudioHandler); - *state.write().unwrap() = Self::Active(client.activate_async(events, frames)?); - Ok(state) - } -}