mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 20:26:42 +01:00
nice (and working) port connect api
This commit is contained in:
parent
f928b026ed
commit
3ed9ebddd4
7 changed files with 209 additions and 190 deletions
|
|
@ -25,4 +25,16 @@ impl JackDevice {
|
|||
pub fn state (&self) -> MutexGuard<Box<dyn Device>> {
|
||||
self.state.lock().unwrap()
|
||||
}
|
||||
pub fn connect_midi_in (&self, index: usize, port: &Port<Unowned>) -> Usually<()> {
|
||||
Ok(self.client.as_client().connect_ports(port, self.midi_ins()?[index])?)
|
||||
}
|
||||
pub fn connect_midi_out (&self, index: usize, port: &Port<Unowned>) -> Usually<()> {
|
||||
Ok(self.client.as_client().connect_ports(self.midi_outs()?[index], port)?)
|
||||
}
|
||||
pub fn connect_audio_in (&self, index: usize, port: &Port<Unowned>) -> Usually<()> {
|
||||
Ok(self.client.as_client().connect_ports(port, self.audio_ins()?[index])?)
|
||||
}
|
||||
pub fn connect_audio_out (&self, index: usize, port: &Port<Unowned>) -> Usually<()> {
|
||||
Ok(self.client.as_client().connect_ports(self.audio_outs()?[index], port)?)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,22 +3,44 @@ use super::*;
|
|||
/// `JackDevice` factory. Creates JACK `Client`s, performs port registration
|
||||
/// and activation, and encapsulates a `Device` into a `JackDevice`.
|
||||
pub struct Jack {
|
||||
pub client: Client,
|
||||
pub ports: JackPorts,
|
||||
pub client: Client,
|
||||
pub midi_ins: Vec<String>,
|
||||
pub audio_ins: Vec<String>,
|
||||
pub midi_outs: Vec<String>,
|
||||
pub audio_outs: Vec<String>,
|
||||
}
|
||||
impl Jack {
|
||||
pub fn new (name: &str) -> Usually<Self> {
|
||||
let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
||||
Ok(Self { client, ports: JackPorts::default() })
|
||||
Ok(Self {
|
||||
midi_ins: vec![],
|
||||
audio_ins: vec![],
|
||||
midi_outs: vec![],
|
||||
audio_outs: vec![],
|
||||
client: Client::new(
|
||||
name,
|
||||
ClientOptions::NO_START_SERVER
|
||||
)?.0,
|
||||
})
|
||||
}
|
||||
pub fn run <T: Device + Process + Sized + 'static> (
|
||||
mut self, state: impl FnOnce(JackPorts)->Box<T>
|
||||
self, state: impl FnOnce(JackPorts)->Box<T>
|
||||
)
|
||||
-> Usually<JackDevice>
|
||||
{
|
||||
let mut owned_ports = JackPorts::default();
|
||||
std::mem::swap(&mut self.ports, &mut owned_ports);
|
||||
let unowned_ports = owned_ports.clone_unowned(&self.client);
|
||||
let owned_ports = JackPorts {
|
||||
audio_ins: register_ports(&self.client, self.audio_ins, AudioIn)?,
|
||||
audio_outs: register_ports(&self.client, self.audio_outs, AudioOut)?,
|
||||
midi_ins: register_ports(&self.client, self.midi_ins, MidiIn)?,
|
||||
midi_outs: register_ports(&self.client, self.midi_outs, MidiOut)?,
|
||||
};
|
||||
let midi_outs = owned_ports.midi_outs.values()
|
||||
.map(|p|Ok(p.name()?)).collect::<Usually<Vec<_>>>()?;
|
||||
let midi_ins = owned_ports.midi_ins.values()
|
||||
.map(|p|Ok(p.name()?)).collect::<Usually<Vec<_>>>()?;
|
||||
let audio_outs = owned_ports.audio_outs.values()
|
||||
.map(|p|Ok(p.name()?)).collect::<Usually<Vec<_>>>()?;
|
||||
let audio_ins = owned_ports.audio_ins.values()
|
||||
.map(|p|Ok(p.name()?)).collect::<Usually<Vec<_>>>()?;
|
||||
let state = Arc::new(Mutex::new(state(owned_ports) as Box<dyn Device>));
|
||||
let client = self.client.activate_async(
|
||||
Notifications(Box::new({
|
||||
|
|
@ -35,44 +57,68 @@ impl Jack {
|
|||
}
|
||||
}) as BoxedProcessHandler)
|
||||
)?;
|
||||
Ok(JackDevice { client, state, ports: unowned_ports })
|
||||
Ok(JackDevice {
|
||||
ports: UnownedJackPorts {
|
||||
audio_ins: query_ports(&client.as_client(), audio_ins),
|
||||
audio_outs: query_ports(&client.as_client(), audio_outs),
|
||||
midi_ins: query_ports(&client.as_client(), midi_ins),
|
||||
midi_outs: query_ports(&client.as_client(), midi_outs),
|
||||
},
|
||||
client,
|
||||
state,
|
||||
})
|
||||
}
|
||||
pub fn ports_from_lv2 (self, plugin: &::livi::Plugin) -> Usually<Self> {
|
||||
pub fn ports_from_lv2 (self, plugin: &::livi::Plugin) -> Self {
|
||||
let counts = plugin.port_counts();
|
||||
let mut jack = self;
|
||||
for i in 0..counts.atom_sequence_inputs {
|
||||
jack = jack.register_midi_in(&format!("midi-in-{i}"))?
|
||||
jack = jack.midi_in(&format!("midi-in-{i}"))
|
||||
}
|
||||
for i in 0..counts.atom_sequence_outputs {
|
||||
jack = jack.register_midi_out(&format!("midi-out-{i}"))?;
|
||||
jack = jack.midi_out(&format!("midi-out-{i}"));
|
||||
}
|
||||
for i in 0..counts.audio_inputs {
|
||||
jack = jack.register_audio_in(&format!("audio-in-{i}"))?
|
||||
jack = jack.audio_in(&format!("audio-in-{i}"));
|
||||
}
|
||||
for i in 0..counts.audio_outputs {
|
||||
jack = jack.register_audio_out(&format!("audio-out-{i}"))?;
|
||||
jack = jack.audio_out(&format!("audio-out-{i}"));
|
||||
}
|
||||
Ok(jack)
|
||||
jack
|
||||
}
|
||||
pub fn register_midi_out (mut self, name: &str) -> Usually<Self> {
|
||||
let port = self.client.register_port(name, MidiOut::default())?;
|
||||
self.ports.midi_outs.insert(name.to_string(), port);
|
||||
Ok(self)
|
||||
pub fn audio_in (mut self, name: &str) -> Self {
|
||||
self.audio_ins.push(name.to_string());
|
||||
self
|
||||
}
|
||||
pub fn register_midi_in (mut self, name: &str) -> Usually<Self> {
|
||||
let port = self.client.register_port(name, MidiIn::default())?;
|
||||
self.ports.midi_ins.insert(name.to_string(), port);
|
||||
Ok(self)
|
||||
pub fn audio_out (mut self, name: &str) -> Self {
|
||||
self.audio_outs.push(name.to_string());
|
||||
self
|
||||
}
|
||||
pub fn register_audio_out (mut self, name: &str) -> Usually<Self> {
|
||||
let port = self.client.register_port(name, AudioOut::default())?;
|
||||
self.ports.audio_outs.insert(name.to_string(), port);
|
||||
Ok(self)
|
||||
pub fn midi_in (mut self, name: &str) -> Self {
|
||||
self.midi_ins.push(name.to_string());
|
||||
self
|
||||
}
|
||||
pub fn register_audio_in (mut self, name: &str) -> Usually<Self> {
|
||||
let port = self.client.register_port(name, AudioIn::default())?;
|
||||
self.ports.audio_ins.insert(name.to_string(), port);
|
||||
Ok(self)
|
||||
pub fn midi_out (mut self, name: &str) -> Self {
|
||||
self.midi_outs.push(name.to_string());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn register_ports <T: PortSpec + Copy> (
|
||||
client: &Client, names: Vec<String>, spec: T
|
||||
) -> Usually<BTreeMap<String, Port<T>>> {
|
||||
names.into_iter().try_fold(BTreeMap::new(), |mut ports, name|{
|
||||
let port = client.register_port(&name, spec)?;
|
||||
ports.insert(name, port);
|
||||
Ok(ports)
|
||||
})
|
||||
}
|
||||
|
||||
fn query_ports (
|
||||
client: &Client, names: Vec<String>
|
||||
) -> BTreeMap<String, Port<Unowned>> {
|
||||
names.into_iter().fold(BTreeMap::new(), |mut ports, name|{
|
||||
let port = client.port_by_name(&name).unwrap();
|
||||
ports.insert(name, port);
|
||||
ports
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use super::*;
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct JackPorts {
|
||||
lifesaver: Arc<()>,
|
||||
pub audio_ins: BTreeMap<String, Port<AudioIn>>,
|
||||
pub midi_ins: BTreeMap<String, Port<MidiIn>>,
|
||||
pub audio_outs: BTreeMap<String, Port<AudioOut>>,
|
||||
|
|
@ -18,27 +17,19 @@ pub struct UnownedJackPorts {
|
|||
}
|
||||
|
||||
impl JackPorts {
|
||||
pub fn clone_unowned (&self, client: &Client) -> UnownedJackPorts {
|
||||
pub fn clone_unowned (&self) -> UnownedJackPorts {
|
||||
let mut unowned = UnownedJackPorts::default();
|
||||
for (name, port) in self.midi_ins.iter() {
|
||||
unowned.midi_ins.insert(name.clone(), unsafe {
|
||||
Port::from_raw(::jack::Unowned, client.raw(), port.raw(), Arc::downgrade(&self.lifesaver))
|
||||
});
|
||||
unowned.midi_ins.insert(name.clone(), port.clone_unowned());
|
||||
}
|
||||
for (name, port) in self.midi_outs.iter() {
|
||||
unowned.midi_outs.insert(name.clone(), unsafe {
|
||||
Port::from_raw(::jack::Unowned, client.raw(), port.raw(), Arc::downgrade(&self.lifesaver))
|
||||
});
|
||||
unowned.midi_outs.insert(name.clone(), port.clone_unowned());
|
||||
}
|
||||
for (name, port) in self.audio_ins.iter() {
|
||||
unowned.audio_ins.insert(name.clone(), unsafe {
|
||||
Port::from_raw(::jack::Unowned, client.raw(), port.raw(), Arc::downgrade(&self.lifesaver))
|
||||
});
|
||||
unowned.audio_ins.insert(name.clone(), port.clone_unowned());
|
||||
}
|
||||
for (name, port) in self.audio_outs.iter() {
|
||||
unowned.audio_outs.insert(name.clone(), unsafe {
|
||||
Port::from_raw(::jack::Unowned, client.raw(), port.raw(), Arc::downgrade(&self.lifesaver))
|
||||
});
|
||||
unowned.audio_outs.insert(name.clone(), port.clone_unowned());
|
||||
}
|
||||
unowned
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue