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