mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
clone ports as unowned and pass outwards
This commit is contained in:
parent
394355331d
commit
ddaf870271
9 changed files with 123 additions and 112 deletions
|
|
@ -24,14 +24,14 @@ pub trait Component: Render + Handle {}
|
||||||
impl<T: Render + Handle> Component for T {}
|
impl<T: Render + Handle> Component for T {}
|
||||||
|
|
||||||
/// A UI component that may have presence on the JACK grap.
|
/// A UI component that may have presence on the JACK grap.
|
||||||
pub trait Device: Render + Handle + Process + Ports + Send + Sync {
|
pub trait Device: Render + Handle + Process + Send + Sync {
|
||||||
fn boxed (self) -> Box<dyn Device> where Self: Sized + 'static {
|
fn boxed (self) -> Box<dyn Device> where Self: Sized + 'static {
|
||||||
Box::new(self)
|
Box::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All things that implement the required traits can be treated as `Device`.
|
/// All things that implement the required traits can be treated as `Device`.
|
||||||
impl<T: Render + Handle + Process + Ports + Send + Sync> Device for T {}
|
impl<T: Render + Handle + Process + Send + Sync> Device for T {}
|
||||||
|
|
||||||
// Reexport macros:
|
// Reexport macros:
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
|
|
||||||
101
src/core/jack.rs
101
src/core/jack.rs
|
|
@ -1,24 +1,22 @@
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
|
|
||||||
pub struct Jack {
|
pub struct Jack {
|
||||||
pub client: JackClient,
|
pub client: Client,
|
||||||
pub ports: JackPorts,
|
pub ports: JackPorts,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct JackDevice {
|
||||||
|
pub client: DynamicAsyncClient,
|
||||||
|
pub state: Arc<Mutex<Box<dyn Device>>>,
|
||||||
|
pub ports: UnownedJackPorts,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum JackClient {
|
pub enum JackClient {
|
||||||
Active(DynamicAsyncClient),
|
Active(DynamicAsyncClient),
|
||||||
Inactive(Client),
|
Inactive(Client),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
ports!(JackDevice {
|
||||||
pub struct JackPorts {
|
|
||||||
pub audio_ins: BTreeMap<String, Port<AudioIn>>,
|
|
||||||
pub midi_ins: BTreeMap<String, Port<MidiIn>>,
|
|
||||||
pub audio_outs: BTreeMap<String, Port<AudioOut>>,
|
|
||||||
pub midi_outs: BTreeMap<String, Port<MidiOut>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
ports!(Jack {
|
|
||||||
audio: {
|
audio: {
|
||||||
ins: |s|Ok(s.ports.audio_ins.values().collect()),
|
ins: |s|Ok(s.ports.audio_ins.values().collect()),
|
||||||
outs: |s|Ok(s.ports.audio_outs.values().collect()),
|
outs: |s|Ok(s.ports.audio_outs.values().collect()),
|
||||||
|
|
@ -32,7 +30,33 @@ ports!(Jack {
|
||||||
impl Jack {
|
impl Jack {
|
||||||
pub fn new (name: &str) -> Usually<Self> {
|
pub fn new (name: &str) -> Usually<Self> {
|
||||||
let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
let (client, _) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
||||||
Ok(Self { client: JackClient::Inactive(client), ports: JackPorts::default(), })
|
Ok(Self { client, ports: JackPorts::default() })
|
||||||
|
}
|
||||||
|
pub fn run <T: Device + Process + Sized + 'static> (
|
||||||
|
mut 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 state = Arc::new(Mutex::new(state(owned_ports) as Box<dyn Device>));
|
||||||
|
let client = self.client.activate_async(
|
||||||
|
Notifications(Box::new({
|
||||||
|
let _state = state.clone();
|
||||||
|
move|_event|{
|
||||||
|
// FIXME: this deadlocks
|
||||||
|
//state.lock().unwrap().handle(&event).unwrap();
|
||||||
|
}
|
||||||
|
}) as Box<dyn Fn(AppEvent) + Send + Sync>),
|
||||||
|
ClosureProcessHandler::new(Box::new({
|
||||||
|
let state = state.clone();
|
||||||
|
move|c: &Client, s: &ProcessScope|{
|
||||||
|
state.lock().unwrap().process(c, s)
|
||||||
|
}
|
||||||
|
}) as BoxedProcessHandler)
|
||||||
|
)?;
|
||||||
|
Ok(JackDevice { client, state, ports: unowned_ports })
|
||||||
}
|
}
|
||||||
pub fn ports_from_lv2 (self, plugin: &::livi::Plugin) -> Usually<Self> {
|
pub fn ports_from_lv2 (self, plugin: &::livi::Plugin) -> Usually<Self> {
|
||||||
let counts = plugin.port_counts();
|
let counts = plugin.port_counts();
|
||||||
|
|
@ -52,61 +76,25 @@ impl Jack {
|
||||||
Ok(jack)
|
Ok(jack)
|
||||||
}
|
}
|
||||||
pub fn register_midi_out (mut self, name: &str) -> Usually<Self> {
|
pub fn register_midi_out (mut self, name: &str) -> Usually<Self> {
|
||||||
self.ports.midi_outs.insert(name.to_string(), match &self.client {
|
let port = self.client.register_port(name, MidiOut::default())?;
|
||||||
JackClient::Inactive(c) => c.register_port(name, MidiOut::default())?,
|
self.ports.midi_outs.insert(name.to_string(), port);
|
||||||
JackClient::Active(c) => c.as_client().register_port(name, MidiOut::default())?,
|
|
||||||
});
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
pub fn register_midi_in (mut self, name: &str) -> Usually<Self> {
|
pub fn register_midi_in (mut self, name: &str) -> Usually<Self> {
|
||||||
self.ports.midi_ins.insert(name.to_string(), match &self.client {
|
let port = self.client.register_port(name, MidiIn::default())?;
|
||||||
JackClient::Inactive(c) => c.register_port(name, MidiIn::default())?,
|
self.ports.midi_ins.insert(name.to_string(), port);
|
||||||
JackClient::Active(c) => c.as_client().register_port(name, MidiIn::default())?,
|
|
||||||
});
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
pub fn register_audio_out (mut self, name: &str) -> Usually<Self> {
|
pub fn register_audio_out (mut self, name: &str) -> Usually<Self> {
|
||||||
self.ports.audio_outs.insert(name.to_string(), match &self.client {
|
let port = self.client.register_port(name, AudioOut::default())?;
|
||||||
JackClient::Inactive(c) => c.register_port(name, AudioOut::default())?,
|
self.ports.audio_outs.insert(name.to_string(), port);
|
||||||
JackClient::Active(c) => c.as_client().register_port(name, AudioOut::default())?,
|
|
||||||
});
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
pub fn register_audio_in (mut self, name: &str) -> Usually<Self> {
|
pub fn register_audio_in (mut self, name: &str) -> Usually<Self> {
|
||||||
self.ports.audio_ins.insert(name.to_string(), match &self.client {
|
let port = self.client.register_port(name, AudioIn::default())?;
|
||||||
JackClient::Inactive(c) => c.register_port(name, AudioIn::default())?,
|
self.ports.audio_ins.insert(name.to_string(), port);
|
||||||
JackClient::Active(c) => c.as_client().register_port(name, AudioIn::default())?,
|
|
||||||
});
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
pub fn run <T> (
|
|
||||||
mut self, state: impl FnOnce(JackPorts)->Box<T>
|
|
||||||
) -> Usually<Arc<Mutex<Box<dyn Device>>>> where
|
|
||||||
T: Device + Process + Sized + 'static
|
|
||||||
{
|
|
||||||
let mut ports = JackPorts::default();
|
|
||||||
std::mem::swap(&mut self.ports, &mut ports);
|
|
||||||
let state = Arc::new(Mutex::new(state(ports) as Box<dyn Device>));
|
|
||||||
self.client = match self.client {
|
|
||||||
JackClient::Active(_) => panic!("already running"),
|
|
||||||
JackClient::Inactive(client) => JackClient::Active(client.activate_async(
|
|
||||||
Notifications(Box::new({
|
|
||||||
let _state = state.clone();
|
|
||||||
move|_event|{
|
|
||||||
// FIXME: this deadlocks
|
|
||||||
//state.lock().unwrap().handle(&event).unwrap();
|
|
||||||
}
|
|
||||||
}) as Box<dyn Fn(AppEvent) + Send + Sync>),
|
|
||||||
ClosureProcessHandler::new(Box::new({
|
|
||||||
let state = state.clone();
|
|
||||||
move|c: &Client, s: &ProcessScope|{
|
|
||||||
state.lock().unwrap().process(c, s)
|
|
||||||
}
|
|
||||||
}) as BoxedProcessHandler)
|
|
||||||
)?)
|
|
||||||
};
|
|
||||||
Ok(state)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jack_run <T> (name: &str, app: &Arc<Mutex<T>>) -> Usually<DynamicAsyncClient>
|
pub fn jack_run <T> (name: &str, app: &Arc<Mutex<T>>) -> Usually<DynamicAsyncClient>
|
||||||
|
|
@ -192,7 +180,8 @@ pub use ::jack::{
|
||||||
RawMidi,
|
RawMidi,
|
||||||
Transport,
|
Transport,
|
||||||
TransportState,
|
TransportState,
|
||||||
TransportStatePosition
|
TransportStatePosition,
|
||||||
|
Unowned
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,60 @@
|
||||||
use crate::core::*;
|
use crate::core::*;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct JackPorts {
|
||||||
|
pub audio_ins: BTreeMap<String, Port<AudioIn>>,
|
||||||
|
pub midi_ins: BTreeMap<String, Port<MidiIn>>,
|
||||||
|
pub audio_outs: BTreeMap<String, Port<AudioOut>>,
|
||||||
|
pub midi_outs: BTreeMap<String, Port<MidiOut>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct UnownedJackPorts {
|
||||||
|
pub audio_ins: BTreeMap<String, Port<::jack::Unowned>>,
|
||||||
|
pub midi_ins: BTreeMap<String, Port<::jack::Unowned>>,
|
||||||
|
pub audio_outs: BTreeMap<String, Port<::jack::Unowned>>,
|
||||||
|
pub midi_outs: BTreeMap<String, Port<::jack::Unowned>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JackPorts {
|
||||||
|
pub fn clone_unowned (&self, client: &Client) -> 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(&Arc::default()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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(&Arc::default()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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(&Arc::default()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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(&Arc::default()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
unowned
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait for things that may expose JACK ports.
|
/// Trait for things that may expose JACK ports.
|
||||||
pub trait Ports {
|
pub trait Ports {
|
||||||
fn audio_ins <'a> (&'a self) -> Usually<Vec<&'a Port<AudioIn>>> {
|
fn audio_ins <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
fn audio_outs <'a> (&'a self) -> Usually<Vec<&'a Port<AudioOut>>> {
|
fn audio_outs <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
fn midi_ins <'a> (&'a self) -> Usually<Vec<&'a Port<MidiIn>>> {
|
fn midi_ins <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
fn midi_outs <'a> (&'a self) -> Usually<Vec<&'a Port<MidiOut>>> {
|
fn midi_outs <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -26,26 +69,26 @@ pub trait Ports {
|
||||||
})?})?) => {
|
})?})?) => {
|
||||||
impl Ports for $T {$(
|
impl Ports for $T {$(
|
||||||
$(
|
$(
|
||||||
$(fn audio_ins <'a> (&'a self) -> Usually<Vec<&'a Port<AudioIn>>> {
|
$(fn audio_ins <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
let cb = |$ai_arg:&'a Self|$ai_impl;
|
let cb = |$ai_arg:&'a Self|$ai_impl;
|
||||||
cb(self)
|
cb(self)
|
||||||
})?
|
})?
|
||||||
)?
|
)?
|
||||||
$(
|
$(
|
||||||
$(fn audio_outs <'a> (&'a self) -> Usually<Vec<&'a Port<AudioOut>>> {
|
$(fn audio_outs <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
let cb = (|$ao_arg:&'a Self|$ao_impl);
|
let cb = (|$ao_arg:&'a Self|$ao_impl);
|
||||||
cb(self)
|
cb(self)
|
||||||
})?
|
})?
|
||||||
)?
|
)?
|
||||||
)? $(
|
)? $(
|
||||||
$(
|
$(
|
||||||
$(fn midi_ins <'a> (&'a self) -> Usually<Vec<&'a Port<MidiIn>>> {
|
$(fn midi_ins <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
let cb = (|$mi_arg:&'a Self|$mi_impl);
|
let cb = (|$mi_arg:&'a Self|$mi_impl);
|
||||||
cb(self)
|
cb(self)
|
||||||
})?
|
})?
|
||||||
)?
|
)?
|
||||||
$(
|
$(
|
||||||
$(fn midi_outs <'a> (&'a self) -> Usually<Vec<&'a Port<MidiOut>>> {
|
$(fn midi_outs <'a> (&'a self) -> Usually<Vec<&'a Port<Unowned>>> {
|
||||||
let cb = (|$mo_arg:&'a Self|$mo_impl);
|
let cb = (|$mo_arg:&'a Self|$mo_impl);
|
||||||
cb(self)
|
cb(self)
|
||||||
})?
|
})?
|
||||||
|
|
|
||||||
|
|
@ -17,16 +17,6 @@ pub struct Plugin {
|
||||||
render!(Plugin = crate::view::plugin::render);
|
render!(Plugin = crate::view::plugin::render);
|
||||||
handle!(Plugin = crate::control::plugin::handle);
|
handle!(Plugin = crate::control::plugin::handle);
|
||||||
process!(Plugin = Plugin::process);
|
process!(Plugin = Plugin::process);
|
||||||
ports!(Plugin {
|
|
||||||
audio: {
|
|
||||||
ins: |p|Ok(p.ports.audio_ins.values().collect()),
|
|
||||||
outs: |p|Ok(p.ports.audio_outs.values().collect()),
|
|
||||||
}
|
|
||||||
midi: {
|
|
||||||
ins: |p|Ok(p.ports.midi_ins.values().collect()),
|
|
||||||
outs: |p|Ok(p.ports.midi_outs.values().collect()),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
pub enum PluginKind {
|
pub enum PluginKind {
|
||||||
LV2(LV2Plugin),
|
LV2(LV2Plugin),
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ impl LV2Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Plugin {
|
impl super::Plugin {
|
||||||
pub fn lv2 (name: &str, path: &str) -> Usually<Arc<Mutex<Box<dyn Device>>>> {
|
pub fn lv2 (name: &str, path: &str) -> Usually<JackDevice> {
|
||||||
let plugin = LV2Plugin::new(path)?;
|
let plugin = LV2Plugin::new(path)?;
|
||||||
Jack::new(name)?
|
Jack::new(name)?
|
||||||
.ports_from_lv2(&plugin.plugin)?
|
.ports_from_lv2(&plugin.plugin)?
|
||||||
|
|
|
||||||
|
|
@ -74,21 +74,21 @@ handle!(Sampler = crate::control::sampler::handle);
|
||||||
//}
|
//}
|
||||||
//});
|
//});
|
||||||
process!(Sampler = Sampler::process);
|
process!(Sampler = Sampler::process);
|
||||||
ports!(Sampler {
|
//ports!(Sampler {
|
||||||
audio: {
|
//audio: {
|
||||||
ins: |s|Ok(s.ports.audio_ins.values().collect()),
|
//ins: |s|Ok(s.ports.audio_ins.values().collect()),
|
||||||
outs: |s|Ok(s.ports.audio_outs.values().collect()),
|
//outs: |s|Ok(s.ports.audio_outs.values().collect()),
|
||||||
}
|
//}
|
||||||
midi: {
|
//midi: {
|
||||||
ins: |s|Ok(s.ports.midi_ins.values().collect()),
|
//ins: |s|Ok(s.ports.midi_ins.values().collect()),
|
||||||
outs: |s|Ok(s.ports.midi_outs.values().collect()),
|
//outs: |s|Ok(s.ports.midi_outs.values().collect()),
|
||||||
}
|
//}
|
||||||
});
|
//});
|
||||||
|
|
||||||
impl Sampler {
|
impl Sampler {
|
||||||
pub fn new (
|
pub fn new (
|
||||||
name: &str, samples: Option<BTreeMap<u7, Arc<Sample>>>,
|
name: &str, samples: Option<BTreeMap<u7, Arc<Sample>>>,
|
||||||
) -> Usually<Arc<Mutex<Box<dyn Device>>>> {
|
) -> Usually<JackDevice> {
|
||||||
Jack::new(name)?
|
Jack::new(name)?
|
||||||
.register_midi_in("midi")?
|
.register_midi_in("midi")?
|
||||||
.register_audio_in("recL")?
|
.register_audio_in("recL")?
|
||||||
|
|
@ -104,7 +104,7 @@ impl Sampler {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||||
// Output buffer: this will be copied to the audio outs.
|
// Output buffer: this will be copied to the audio outs.
|
||||||
let channel_count = self.ports.audio_outs.len();
|
let channel_count = self.ports.audio_outs.len();
|
||||||
let mut mixed = vec![vec![0.0;scope.n_frames() as usize];channel_count];
|
let mut mixed = vec![vec![0.0;scope.n_frames() as usize];channel_count];
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ pub struct Track {
|
||||||
/// Red keys on piano roll.
|
/// Red keys on piano roll.
|
||||||
pub notes_on: Vec<bool>,
|
pub notes_on: Vec<bool>,
|
||||||
/// Device chain
|
/// Device chain
|
||||||
pub devices: Vec<Arc<Mutex<Box<dyn Device>>>>,
|
pub devices: Vec<JackDevice>,
|
||||||
/// Device selector
|
/// Device selector
|
||||||
pub device: usize,
|
pub device: usize,
|
||||||
}
|
}
|
||||||
|
|
@ -28,7 +28,7 @@ impl Track {
|
||||||
name: &str,
|
name: &str,
|
||||||
jack: &Client,
|
jack: &Client,
|
||||||
phrases: Option<Vec<Phrase>>,
|
phrases: Option<Vec<Phrase>>,
|
||||||
devices: Option<Vec<Arc<Mutex<Box<dyn Device>>>>>,
|
devices: Option<Vec<JackDevice>>,
|
||||||
) -> Usually<Self> {
|
) -> Usually<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
|
@ -44,7 +44,7 @@ impl Track {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn device (&self, i: usize) -> Option<MutexGuard<Box<dyn Device>>> {
|
pub fn device (&self, i: usize) -> Option<MutexGuard<Box<dyn Device>>> {
|
||||||
self.devices.get(i).map(|d|d.lock().unwrap())
|
self.devices.get(i).map(|d|d.state.lock().unwrap())
|
||||||
}
|
}
|
||||||
pub fn active_device (&self) -> Option<MutexGuard<Box<dyn Device>>> {
|
pub fn active_device (&self) -> Option<MutexGuard<Box<dyn Device>>> {
|
||||||
self.device(self.device)
|
self.device(self.device)
|
||||||
|
|
@ -73,22 +73,10 @@ impl Track {
|
||||||
|
|
||||||
ports!(Track {
|
ports!(Track {
|
||||||
audio: {
|
audio: {
|
||||||
outs: |track|{
|
outs: |_t|Ok(vec![]),
|
||||||
if let Some(device) = track.last_device() {
|
|
||||||
device.audio_outs()
|
|
||||||
} else {
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
midi: {
|
midi: {
|
||||||
ins: |track|if let Some(device) = track.first_device() {
|
ins: |_t|Ok(vec![]),
|
||||||
device.midi_ins()
|
outs: |_t|Ok(vec![]),
|
||||||
} else {
|
|
||||||
Ok(vec![])
|
|
||||||
},
|
|
||||||
outs: |track|Ok(vec![
|
|
||||||
&track.midi_out
|
|
||||||
]),
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,8 @@ impl<'a> ChainView<'a> {
|
||||||
//y2 = y2 + 1;
|
//y2 = y2 + 1;
|
||||||
//}
|
//}
|
||||||
let width = width.saturating_sub(x).saturating_sub(x2);
|
let width = width.saturating_sub(x).saturating_sub(x2);
|
||||||
let frame = device.render(buf, Rect { x: x + x2, y, width, height })?;
|
let frame = device.state.lock().unwrap()
|
||||||
|
.render(buf, Rect { x: x + x2, y, width, height })?;
|
||||||
let style = if i == track.device {
|
let style = if i == track.device {
|
||||||
Some(if self.focused {
|
Some(if self.focused {
|
||||||
Style::default().green().bold().not_dim()
|
Style::default().green().bold().not_dim()
|
||||||
|
|
@ -145,13 +146,13 @@ pub fn draw_as_column (
|
||||||
let mut w = 0u16;
|
let mut w = 0u16;
|
||||||
let mut frames = vec![];
|
let mut frames = vec![];
|
||||||
for device in state.devices.iter() {
|
for device in state.devices.iter() {
|
||||||
let device = device.lock().unwrap();
|
|
||||||
let style_midi = Style::default().black().bold().on_green();
|
|
||||||
let style_audio = Style::default().black().bold().on_red();
|
|
||||||
let midi_ins = device.midi_ins()?;
|
let midi_ins = device.midi_ins()?;
|
||||||
let midi_outs = device.midi_outs()?;
|
let midi_outs = device.midi_outs()?;
|
||||||
let audio_ins = device.audio_ins()?;
|
let audio_ins = device.audio_ins()?;
|
||||||
let audio_outs = device.audio_outs()?;
|
let audio_outs = device.audio_outs()?;
|
||||||
|
let device = device.state.lock().unwrap();
|
||||||
|
let style_midi = Style::default().black().bold().on_green();
|
||||||
|
let style_audio = Style::default().black().bold().on_red();
|
||||||
y = y + midi_ins.len() as u16;
|
y = y + midi_ins.len() as u16;
|
||||||
let frame = device.render(buf, Rect {
|
let frame = device.render(buf, Rect {
|
||||||
x, y, width, height: height.saturating_sub(y)
|
x, y, width, height: height.saturating_sub(y)
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ impl<'a> SceneGridView<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_horizontal (&mut self) -> Usually<Rect> {
|
pub fn draw_horizontal (&mut self) -> Usually<Rect> {
|
||||||
let (w, h) = self.size_horizontal();
|
//let (w, h) = self.size_horizontal();
|
||||||
//self.area.x = self.area.x + self.area.width.saturating_sub(w) / 2;
|
//self.area.x = self.area.x + self.area.width.saturating_sub(w) / 2;
|
||||||
self.area.height = self.tracks.len() as u16 + 2;
|
self.area.height = self.tracks.len() as u16 + 2;
|
||||||
//self.area.width = w;
|
//self.area.width = w;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue