mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: init shared jack clients
This commit is contained in:
parent
5a325666fd
commit
ec2c96d00e
8 changed files with 74 additions and 35 deletions
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
||||||
9
crates/tek_sequencer/src/arranger_snd.rs
Normal file
9
crates/tek_sequencer/src/arranger_snd.rs
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 (
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue