wip: init shared jack clients

This commit is contained in:
🪞👃🪞 2024-10-27 02:58:51 +03:00
parent 5a325666fd
commit ec2c96d00e
8 changed files with 74 additions and 35 deletions

View file

@ -2,6 +2,8 @@ use crate::*;
/// Root level object for standalone `tek_arranger` /// Root level object for standalone `tek_arranger`
pub struct Arranger<E: Engine> { pub struct Arranger<E: Engine> {
/// JACK client handle (needs to not be dropped for standalone mode to work).
pub jack: Option<Arc<JackClient>>,
/// Which view is focused /// Which view is focused
pub focus_cursor: (usize, usize), pub focus_cursor: (usize, usize),
/// Controls the JACK transport. /// Controls the JACK transport.
@ -121,7 +123,8 @@ impl<E: Engine> Arranger<E> {
phrases: Arc<RwLock<PhrasePool<E>>>, phrases: Arc<RwLock<PhrasePool<E>>>,
) -> Self { ) -> Self {
let mut app = Self { let mut app = Self {
focus_cursor: (0, 1), jack: None,
focus_cursor: (0, 1),
phrases_split: 20, phrases_split: 20,
arrangement_split: 21, arrangement_split: 21,
editor: PhraseEditor::new(), editor: PhraseEditor::new(),

View file

@ -44,19 +44,26 @@ impl ArrangerCli {
Some(okhsl_to_rgb(scene_color_1.mix(scene_color_2, i as f32 / self.scenes as f32))) Some(okhsl_to_rgb(scene_color_1.mix(scene_color_2, i as f32 / self.scenes as f32)))
)?; )?;
} }
transport.write().unwrap().jack = Some( let arranger = Arc::new(RwLock::new(Arranger::new(
jack.activate(
&transport.clone(),
|state: &Arc<RwLock<TransportToolbar<Tui>>>, client, scope| {
state.write().unwrap().process(client, scope)
}
)?.into()
);
Tui::run(Arc::new(RwLock::new(Arranger::new(
self.transport.then_some(transport), self.transport.then_some(transport),
arrangement, arrangement,
phrases, phrases,
))))?; )));
let jack = jack.activate(&arranger.clone(), arranger_jack_callback)?;
let jack = Some(jack.into());
if let Some(ref transport) = arranger.read().unwrap().transport {
transport.write().unwrap().jack = jack.clone();
}
arranger.write().unwrap().jack = jack.clone();
Tui::run(arranger)?;
Ok(()) Ok(())
} }
} }
fn arranger_jack_callback (
state: &Arc<RwLock<Arranger<Tui>>>,
client: &Client,
scope: &ProcessScope,
) -> Control {
state.write().unwrap().process(client, scope)
}

View file

@ -0,0 +1,9 @@
use crate::*;
impl<E: Engine> Audio for Arranger<E> {
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
if let Some(ref transport) = self.transport {
transport.write().unwrap().process(client, scope);
}
todo!("arranger process")
}
}

View file

@ -10,7 +10,7 @@ pub(crate) use palette::{*, convert::*, okhsl::*};
use rand::distributions::uniform::UniformSampler; use rand::distributions::uniform::UniformSampler;
submod! { submod! {
arranger arranger_cmd arranger_tui arranger arranger_cmd arranger_tui arranger_snd
sequencer sequencer_cmd sequencer_tui sequencer_snd sequencer sequencer_cmd sequencer_tui sequencer_snd
transport transport_cmd transport_tui transport_snd transport transport_cmd transport_tui transport_snd
} }

View file

@ -7,6 +7,8 @@ pub type PhraseMessage = Vec<u8>;
pub type PhraseChunk = [Vec<PhraseMessage>]; pub type PhraseChunk = [Vec<PhraseMessage>];
/// Root level object for standalone `tek_sequencer` /// Root level object for standalone `tek_sequencer`
pub struct Sequencer<E: Engine> { pub struct Sequencer<E: Engine> {
/// JACK client handle (needs to not be dropped for standalone mode to work).
pub jack: Option<Arc<JackClient>>,
/// Which view is focused /// Which view is focused
pub focus_cursor: (usize, usize), pub focus_cursor: (usize, usize),
/// Controls the JACK transport. /// Controls the JACK transport.

View file

@ -18,34 +18,41 @@ pub struct SequencerCli {
impl SequencerCli { impl SequencerCli {
fn run (&self) -> Usually<()> { fn run (&self) -> Usually<()> {
let jack = Client::new("tek_arranger", ClientOptions::NO_START_SERVER)?.0; let jack = Client::new("tek_arranger", ClientOptions::NO_START_SERVER)?.0;
let jack = JackClient::Inactive(jack); let jack = JackClient::Inactive(jack);
let transport = Arc::new(RwLock::new(TransportToolbar::new(None, Some(jack.transport())))); let transport = Arc::new(RwLock::new(TransportToolbar::new(None, Some(jack.transport()))));
transport.write().unwrap().jack = Some(
jack.activate(
&transport.clone(),
|state: &Arc<RwLock<TransportToolbar<Tui>>>, client, scope| {
state.write().unwrap().process(client, scope)
}
)?.into()
);
let focus_cursor = (1, 1); let focus_cursor = (1, 1);
let clock = transport.read().unwrap().clock.clone(); let clock = transport.read().unwrap().clock.clone();
let transport = self.transport.then_some(transport); let transport = self.transport.then_some(transport);
let editor = PhraseEditor::new(); let editor = PhraseEditor::new();
let phrases = Arc::new(RwLock::new(PhrasePool::new())); let phrases = Arc::new(RwLock::new(PhrasePool::new()));
let seq = Sequencer { focus_cursor, clock, transport, editor, phrases }; let sequencer = Sequencer { jack: None, focus_cursor, clock, transport, editor, phrases };
if let Some(_) = self.name.as_ref() { if let Some(_) = self.name.as_ref() {
// TODO: seq.name = Arc::new(RwLock::new(name.clone())); // TODO: sequencer.name = Arc::new(RwLock::new(name.clone()));
} }
if let Some(_) = self.ppq { if let Some(_) = self.ppq {
// TODO: seq.ppq = ppq; // TODO: sequencer.ppq = ppq;
} }
if let Some(_) = self.length { if let Some(_) = self.length {
// TODO: if let Some(phrase) = seq.phrase.as_mut() { // TODO: if let Some(phrase) = sequencer.phrase.as_mut() {
//phrase.write().unwrap().length = length; //phrase.write().unwrap().length = length;
//} //}
} }
Tui::run(Arc::new(RwLock::new(seq))).map(|_|()) let sequencer = Arc::new(RwLock::new(sequencer));
let jack = jack.activate(&sequencer.clone(), sequencer_jack_callback)?;
let jack = Some(jack.into());
if let Some(ref transport) = sequencer.read().unwrap().transport {
transport.write().unwrap().jack = jack.clone();
}
sequencer.write().unwrap().jack = jack.clone();
Tui::run(sequencer).map(|_|())
} }
} }
fn sequencer_jack_callback (
state: &Arc<RwLock<Sequencer<Tui>>>,
client: &Client,
scope: &ProcessScope,
) -> Control {
state.write().unwrap().process(client, scope)
}

View file

@ -1,4 +1,13 @@
use crate::*; use crate::*;
impl<E: Engine> Audio for Sequencer<E> {
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
if let Some(ref transport) = self.transport {
transport.write().unwrap().process(client, scope);
}
todo!("sequencer process")
}
}
impl Phrase { impl Phrase {
/// Write a chunk of MIDI events to an output port. /// Write a chunk of MIDI events to an output port.
pub fn process_out ( pub fn process_out (

View file

@ -7,14 +7,16 @@ pub fn main () -> Usually<()> {
let mut transport = TransportToolbar::new(None, Some(jack.transport())); let mut transport = TransportToolbar::new(None, Some(jack.transport()));
transport.focused = true; transport.focused = true;
let transport = Arc::new(RwLock::new(transport)); let transport = Arc::new(RwLock::new(transport));
transport.write().unwrap().jack = Some( let jack = jack.activate(&transport.clone(), transport_jack_callback)?;
jack.activate( transport.write().unwrap().jack = Some(jack.into());
&transport.clone(),
|state: &Arc<RwLock<TransportToolbar<Tui>>>, client, scope| {
state.write().unwrap().process(client, scope)
}
)?.into()
);
Tui::run(transport)?; Tui::run(transport)?;
Ok(()) Ok(())
} }
fn transport_jack_callback (
state: &Arc<RwLock<TransportToolbar<Tui>>>,
client: &Client,
scope: &ProcessScope,
) -> Control {
state.write().unwrap().process(client, scope)
}