mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: refactor pt.22: api traits in snd
This commit is contained in:
parent
029614631e
commit
e7e57cea1e
8 changed files with 100 additions and 67 deletions
|
|
@ -2,9 +2,10 @@ use crate::*;
|
||||||
|
|
||||||
pub trait ArrangerModelApi: JackModelApi + ClockModelApi {
|
pub trait ArrangerModelApi: JackModelApi + ClockModelApi {
|
||||||
fn name (&self) -> &Arc<RwLock<String>>;
|
fn name (&self) -> &Arc<RwLock<String>>;
|
||||||
fn phrases (&self) -> &Arc<RwLock<PhrasePool>>;
|
|
||||||
fn tracks (&self) -> &Vec<ArrangerTrack>;
|
fn tracks (&self) -> &Vec<ArrangerTrack>;
|
||||||
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack>;
|
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack>;
|
||||||
|
|
||||||
fn scenes (&self) -> &Vec<ArrangerScene>;
|
fn scenes (&self) -> &Vec<ArrangerScene>;
|
||||||
fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene>;
|
fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene>;
|
||||||
|
|
||||||
|
|
@ -54,13 +55,31 @@ pub trait ArrangerModelApi: JackModelApi + ClockModelApi {
|
||||||
|
|
||||||
impl JackModelApi for ArrangerModel {
|
impl JackModelApi for ArrangerModel {
|
||||||
fn jack (&self) -> &Arc<RwLock<JackClient>> {
|
fn jack (&self) -> &Arc<RwLock<JackClient>> {
|
||||||
&self.jack
|
&self.transport.jack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClockModelApi for ArrangerModel {
|
impl ClockModelApi for ArrangerModel {
|
||||||
fn clock (&self) -> &Arc<Clock> {
|
fn clock (&self) -> &Arc<Clock> {
|
||||||
&self.clock
|
&self.transport.clock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransportModelApi for ArrangerModel {
|
||||||
|
fn transport (&self) -> &jack::Transport {
|
||||||
|
&self.transport.transport()
|
||||||
|
}
|
||||||
|
fn metronome (&self) -> bool {
|
||||||
|
self.transport.metronome()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhrasePoolModelApi for ArrangerModel {
|
||||||
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&self.phrases
|
||||||
|
}
|
||||||
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&mut self.phrases
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,9 +87,6 @@ impl ArrangerModelApi for ArrangerModel {
|
||||||
fn name (&self) -> &Arc<RwLock<String>> {
|
fn name (&self) -> &Arc<RwLock<String>> {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
fn phrases (&self) -> &Arc<RwLock<PhrasePool>> {
|
|
||||||
&self.phrases
|
|
||||||
}
|
|
||||||
fn tracks (&self) -> &Vec<ArrangerTrack> {
|
fn tracks (&self) -> &Vec<ArrangerTrack> {
|
||||||
&self.tracks
|
&self.tracks
|
||||||
}
|
}
|
||||||
|
|
@ -87,18 +103,16 @@ impl ArrangerModelApi for ArrangerModel {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ArrangerModel {
|
pub struct ArrangerModel {
|
||||||
/// JACK client handle (needs to not be dropped for standalone mode to work).
|
/// State of the JACK transport.
|
||||||
jack: Arc<RwLock<JackClient>>,
|
transport: TransportModel,
|
||||||
/// Global timebase
|
|
||||||
clock: Arc<Clock>,
|
|
||||||
/// Name of arranger
|
|
||||||
name: Arc<RwLock<String>>,
|
|
||||||
/// Collection of phrases.
|
/// Collection of phrases.
|
||||||
phrases: Arc<RwLock<PhrasePool>>,
|
phrases: Vec<Arc<RwLock<Phrase>>>,
|
||||||
/// Collection of tracks.
|
/// Collection of tracks.
|
||||||
tracks: Vec<ArrangerTrack>,
|
tracks: Vec<ArrangerTrack>,
|
||||||
/// Collection of scenes.
|
/// Collection of scenes.
|
||||||
scenes: Vec<ArrangerScene>,
|
scenes: Vec<ArrangerScene>,
|
||||||
|
/// Name of arranger
|
||||||
|
name: Arc<RwLock<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,22 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
pub trait PhrasePoolModelApi {
|
||||||
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>>;
|
||||||
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhrasePoolModelApi for PhrasePoolModel {
|
||||||
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&self.phrases
|
||||||
|
}
|
||||||
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&mut self.phrases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Contains all phrases in a project
|
/// Contains all phrases in a project
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PhrasePool {
|
pub struct PhrasePoolModel {
|
||||||
/// Phrases in the pool
|
/// Phrases in the pool
|
||||||
pub phrases: Vec<Arc<RwLock<Phrase>>>,
|
pub phrases: Vec<Arc<RwLock<Phrase>>>,
|
||||||
}
|
}
|
||||||
|
|
@ -20,8 +34,8 @@ pub enum PhrasePoolCommand {
|
||||||
SetLength(usize, usize),
|
SetLength(usize, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command<PhrasePool> for PhrasePoolCommand {
|
impl Command<PhrasePoolModel> for PhrasePoolCommand {
|
||||||
fn execute (self, state: &mut PhrasePool) -> Perhaps<Self> {
|
fn execute (self, model: &mut PhrasePoolModel) -> Perhaps<Self> {
|
||||||
match self {
|
match self {
|
||||||
Self::Add(index) => {
|
Self::Add(index) => {
|
||||||
//Self::Append => { view.append_new(None, None) },
|
//Self::Append => { view.append_new(None, None) },
|
||||||
|
|
@ -29,8 +43,8 @@ impl Command<PhrasePool> for PhrasePoolCommand {
|
||||||
},
|
},
|
||||||
Self::Delete(index) => {
|
Self::Delete(index) => {
|
||||||
//if view.phrase > 0 {
|
//if view.phrase > 0 {
|
||||||
//view.state.phrases.remove(view.phrase);
|
//view.model.phrases.remove(view.phrase);
|
||||||
//view.phrase = view.phrase.min(view.state.phrases.len().saturating_sub(1));
|
//view.phrase = view.phrase.min(view.model.phrases.len().saturating_sub(1));
|
||||||
//}
|
//}
|
||||||
},
|
},
|
||||||
Self::Duplicate(index) => {
|
Self::Duplicate(index) => {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub trait SequencerModelApi: JackModelApi + ClockModelApi {
|
pub trait SequencerModelApi: JackModelApi + ClockModelApi + TransportModelApi {
|
||||||
fn phrases (&self) -> &PhrasePool;
|
|
||||||
fn player (&self) -> &MIDIPlayer;
|
fn player (&self) -> &MIDIPlayer;
|
||||||
|
fn player_mut (&mut self) -> &mut MIDIPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl JackModelApi for SequencerModel {
|
impl JackModelApi for SequencerModel {
|
||||||
|
|
@ -26,20 +26,29 @@ impl TransportModelApi for SequencerModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SequencerModelApi for SequencerModel {
|
impl PhrasePoolModelApi for SequencerModel {
|
||||||
fn phrases (&self) -> &PhrasePool {
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
||||||
&self.phrases
|
&self.phrases
|
||||||
}
|
}
|
||||||
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&mut self.phrases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SequencerModelApi for SequencerModel {
|
||||||
fn player (&self) -> &MIDIPlayer {
|
fn player (&self) -> &MIDIPlayer {
|
||||||
&self.player
|
&self.player
|
||||||
}
|
}
|
||||||
|
fn player_mut (&mut self) -> &mut MIDIPlayer {
|
||||||
|
&mut self.player
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SequencerModel {
|
pub struct SequencerModel {
|
||||||
/// State of the JACK transport.
|
/// State of the JACK transport.
|
||||||
transport: TransportModel,
|
transport: TransportModel,
|
||||||
/// State of the phrase pool.
|
/// State of the phrase pool.
|
||||||
phrases: PhrasePool,
|
phrases: Vec<Arc<RwLock<Phrase>>>,
|
||||||
/// State of the phrase player.
|
/// State of the phrase player.
|
||||||
player: MIDIPlayer,
|
player: MIDIPlayer,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,18 @@ pub enum TransportCommand {
|
||||||
SetSync(f64),
|
SetSync(f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command<Transport> for TransportCommand {
|
impl<T: TransportModelApi> Command<T> for TransportCommand {
|
||||||
fn execute (self, state: &mut Transport) -> Perhaps<Self> {
|
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
||||||
use TransportCommand::*;
|
use TransportCommand::*;
|
||||||
match self.translate(&state) {
|
match self {
|
||||||
Play(start) => {todo!()},
|
Play(start) => {todo!()},
|
||||||
Pause(start) => {todo!()},
|
Pause(start) => {todo!()},
|
||||||
SeekUsec(usec) => {state.clock.current.update_from_usec(usec);},
|
SeekUsec(usec) => {state.clock().current.update_from_usec(usec);},
|
||||||
SeekSample(sample) => {state.clock.current.update_from_sample(sample);},
|
SeekSample(sample) => {state.clock().current.update_from_sample(sample);},
|
||||||
SeekPulse(pulse) => {state.clock.current.update_from_pulse(pulse);},
|
SeekPulse(pulse) => {state.clock().current.update_from_pulse(pulse);},
|
||||||
SetBpm(bpm) => {return Ok(Some(Self::SetBpm(state.clock.timebase().bpm.set(bpm))))},
|
SetBpm(bpm) => {return Ok(Some(Self::SetBpm(state.clock().timebase().bpm.set(bpm))))},
|
||||||
SetQuant(quant) => {return Ok(Some(Self::SetQuant(state.clock.quant.set(quant))))},
|
SetQuant(quant) => {return Ok(Some(Self::SetQuant(state.clock().quant.set(quant))))},
|
||||||
SetSync(sync) => {return Ok(Some(Self::SetSync(state.clock.sync.set(sync))))},
|
SetSync(sync) => {return Ok(Some(Self::SetSync(state.clock().sync.set(sync))))},
|
||||||
_ => { unreachable!() }
|
_ => { unreachable!() }
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
pub use tek_core::{*, jack::{*, Transport as JackTransport}};
|
pub use tek_core::{*, jack::*};
|
||||||
pub use tek_api::{*, Transport};
|
pub use tek_api::*;
|
||||||
pub(crate) use tek_core::midly::{*, live::LiveEvent, num::u7};
|
pub(crate) use tek_core::midly::{*, live::LiveEvent, num::u7};
|
||||||
|
|
||||||
submod! {
|
submod! {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,16 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
impl<T: ArrangerModelApi + Send + Sync> Audio for T {
|
impl Audio for ArrangerModel {
|
||||||
|
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||||
|
ArrangerRefAudio(self).process(client, scope)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ArrangerRefAudio<'a, T: ArrangerModelApi + Send + Sync>(&'a mut T);
|
||||||
|
|
||||||
|
impl<'a, T: ArrangerModelApi + Send + Sync> Audio for ArrangerRefAudio<'a, T> {
|
||||||
#[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
#[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||||
for track in self.tracks_mut().iter_mut() {
|
for track in self.0.tracks_mut().iter_mut() {
|
||||||
if MIDIPlayerAudio::from(&mut track.player).process(client, scope) == Control::Quit {
|
if MIDIPlayerAudio::from(&mut track.player).process(client, scope) == Control::Quit {
|
||||||
return Control::Quit
|
return Control::Quit
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,19 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub struct SequencerAudio(pub Arc<RwLock<Transport>>, pub Arc<RwLock<MIDIPlayer>>);
|
impl Audio for SequencerModel {
|
||||||
|
|
||||||
/// JACK process callback for sequencer app
|
|
||||||
impl<'a> Audio for SequencerAudio {
|
|
||||||
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||||
SequencerRefAudio(
|
SequencerRefAudio(self).process(client, scope)
|
||||||
&mut*self.0.write().unwrap(),
|
|
||||||
&mut*self.1.write().unwrap()
|
|
||||||
).process(client, scope)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SequencerRefAudio<'a, T: SequencerModelApi + Send + Sync>(&'a mut T);
|
||||||
|
|
||||||
pub struct SequencerRefAudio<'a>(pub &'a mut Transport, pub &'a mut MIDIPlayer);
|
impl<'a, T: SequencerModelApi + Send + Sync> Audio for SequencerRefAudio<'a, T> {
|
||||||
|
#[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||||
/// JACK process callback for sequencer embed
|
|
||||||
impl<'a> Audio for SequencerRefAudio<'a> {
|
|
||||||
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
|
||||||
if TransportRefAudio(&mut*self.0).process(client, scope) == Control::Quit {
|
if TransportRefAudio(&mut*self.0).process(client, scope) == Control::Quit {
|
||||||
return Control::Quit
|
return Control::Quit
|
||||||
}
|
}
|
||||||
if MIDIPlayerAudio::from(&mut*self.1).process(client, scope) == Control::Quit {
|
if MIDIPlayerAudio::from(&mut*self.0.player_mut()).process(client, scope) == Control::Quit {
|
||||||
return Control::Quit
|
return Control::Quit
|
||||||
}
|
}
|
||||||
Control::Continue
|
Control::Continue
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,23 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub struct TransportAudio(pub Arc<RwLock<Transport>>);
|
impl Audio for TransportModel {
|
||||||
|
|
||||||
impl Audio for TransportAudio {
|
|
||||||
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||||
TransportRefAudio(
|
TransportRefAudio(self).process(client, scope)
|
||||||
&mut*self.0.write().unwrap()
|
|
||||||
).process(client, scope)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TransportRefAudio<'a>(pub &'a mut Transport);
|
pub struct TransportRefAudio<'a, T: TransportModelApi + Send + Sync>(pub(crate) &'a mut T);
|
||||||
|
|
||||||
impl<'a> Audio for TransportRefAudio<'a> {
|
impl<'a, T: TransportModelApi + Send + Sync> Audio for TransportRefAudio<'a, T> {
|
||||||
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
#[inline] fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||||
let ref state = self.0;
|
let state = &mut self.0;
|
||||||
let times = scope.cycle_times().unwrap();
|
let times = scope.cycle_times().unwrap();
|
||||||
let CycleTimes { current_frames, current_usecs, next_usecs: _, period_usecs: _ } = times;
|
let CycleTimes { current_frames, current_usecs, next_usecs: _, period_usecs: _ } = times;
|
||||||
let _chunk_size = scope.n_frames() as usize;
|
let _chunk_size = scope.n_frames() as usize;
|
||||||
let transport = state.transport.query().unwrap();
|
let transport = state.transport().query().unwrap();
|
||||||
state.clock.current.sample.set(transport.pos.frame() as f64);
|
state.clock().current.sample.set(transport.pos.frame() as f64);
|
||||||
let mut playing = state.clock.playing.write().unwrap();
|
let mut playing = state.clock().playing.write().unwrap();
|
||||||
let mut started = state.clock.started.write().unwrap();
|
let mut started = state.clock().started.write().unwrap();
|
||||||
if *playing != Some(transport.state) {
|
if *playing != Some(transport.state) {
|
||||||
match transport.state {
|
match transport.state {
|
||||||
TransportState::Rolling => {
|
TransportState::Rolling => {
|
||||||
|
|
@ -37,7 +33,7 @@ impl<'a> Audio for TransportRefAudio<'a> {
|
||||||
if *playing == Some(TransportState::Stopped) {
|
if *playing == Some(TransportState::Stopped) {
|
||||||
*started = None;
|
*started = None;
|
||||||
}
|
}
|
||||||
state.clock.current.update_from_usec(match *started {
|
state.clock().current.update_from_usec(match *started {
|
||||||
Some((_, usecs)) => current_usecs as f64 - usecs as f64,
|
Some((_, usecs)) => current_usecs as f64 - usecs as f64,
|
||||||
None => 0.
|
None => 0.
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue