wip: refactor pt.21: api traits

This commit is contained in:
🪞👃🪞 2024-11-13 19:14:29 +01:00
parent b8708d6b2d
commit 029614631e
10 changed files with 626 additions and 490 deletions

View file

@ -1,19 +1,104 @@
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>;
fn track_default_name (&self) -> String {
format!("Track {}", self.tracks().len() + 1)
}
fn track_add (
&mut self, name: Option<&str>, color: Option<ItemColor>
) -> Usually<&mut ArrangerTrack> {
let name = name.map_or_else(||self.track_default_name(), |x|x.to_string());
let track = ArrangerTrack {
width: name.len() + 2,
color: color.unwrap_or_else(||ItemColor::random()),
player: MIDIPlayer::new(&self.jack(), &self.clock(), name.as_str())?,
name: Arc::new(name.into()),
};
self.tracks_mut().push(track);
let index = self.tracks().len() - 1;
Ok(&mut self.tracks_mut()[index])
}
fn track_del (&mut self, index: usize) {
self.tracks_mut().remove(index);
for scene in self.scenes_mut().iter_mut() {
scene.clips.remove(index);
}
}
fn scene_default_name (&self) -> String {
format!("Scene {}", self.scenes().len() + 1)
}
fn scene_add (
&mut self, name: Option<&str>, color: Option<ItemColor>
) -> Usually<&mut ArrangerScene> {
let name = name.map_or_else(||self.scene_default_name(), |x|x.to_string());
let scene = ArrangerScene {
name: Arc::new(name.into()),
clips: vec![None;self.tracks().len()],
color: color.unwrap_or_else(||ItemColor::random()),
};
self.scenes_mut().push(scene);
let index = self.scenes().len() - 1;
Ok(&mut self.scenes_mut()[index])
}
fn scene_del (&mut self, index: usize) {
self.scenes_mut().remove(index);
}
}
impl JackModelApi for ArrangerModel {
fn jack (&self) -> &Arc<RwLock<JackClient>> {
&self.jack
}
}
impl ClockModelApi for ArrangerModel {
fn clock (&self) -> &Arc<Clock> {
&self.clock
}
}
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
}
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
&mut self.tracks
}
fn scenes (&self) -> &Vec<ArrangerScene> {
&self.scenes
}
fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> {
&mut self.scenes
}
}
#[derive(Debug)]
pub struct ArrangerModel {
/// JACK client handle (needs to not be dropped for standalone mode to work).
pub jack: Arc<RwLock<JackClient>>,
jack: Arc<RwLock<JackClient>>,
/// Global timebase
pub clock: Arc<Clock>,
clock: Arc<Clock>,
/// Name of arranger
pub name: Arc<RwLock<String>>,
name: Arc<RwLock<String>>,
/// Collection of phrases.
pub phrases: Arc<RwLock<PhrasePool>>,
phrases: Arc<RwLock<PhrasePool>>,
/// Collection of tracks.
pub tracks: Vec<ArrangerTrack>,
tracks: Vec<ArrangerTrack>,
/// Collection of scenes.
pub scenes: Vec<ArrangerScene>,
scenes: Vec<ArrangerScene>,
}
#[derive(Debug)]
@ -38,50 +123,21 @@ pub struct ArrangerScene {
pub color: ItemColor,
}
impl ArrangerModel {
pub fn is_stopped (&self) -> bool {
*self.clock.playing.read().unwrap() == Some(TransportState::Stopped)
impl ArrangerTrack {
pub fn longest_name (tracks: &[Self]) -> usize {
tracks.iter().map(|s|s.name.read().unwrap().len()).fold(0, usize::max)
}
pub fn track_default_name (&self) -> String {
format!("Track {}", self.tracks.len() + 1)
pub const MIN_WIDTH: usize = 3;
pub fn width_inc (&mut self) {
self.width += 1;
}
pub fn scene_default_name (&self) -> String {
format!("Scene {}", self.scenes.len() + 1)
}
pub fn track_add (
&mut self, name: Option<&str>, color: Option<ItemColor>
) -> Usually<&mut ArrangerTrack> {
let name = name.map_or_else(||self.track_default_name(), |x|x.to_string());
self.tracks.push(ArrangerTrack {
width: name.len() + 2,
color: color.unwrap_or_else(||ItemColor::random()),
player: MIDIPlayer::new(&self.jack, &self.clock, name.as_str())?,
name: Arc::new(name.into()),
});
let index = self.tracks.len() - 1;
Ok(&mut self.tracks[index])
}
pub fn scene_add (
&mut self, name: Option<&str>, color: Option<ItemColor>
) -> Usually<&mut ArrangerScene> {
let name = name.map_or_else(||self.scene_default_name(), |x|x.to_string());
self.scenes.push(ArrangerScene {
name: Arc::new(name.into()),
clips: vec![None;self.tracks.len()],
color: color.unwrap_or_else(||ItemColor::random()),
});
let index = self.scenes.len() - 1;
Ok(&mut self.scenes[index])
}
pub fn track_del (&mut self, index: usize) {
self.tracks.remove(index);
for scene in self.scenes.iter_mut() {
scene.clips.remove(index);
pub fn width_dec (&mut self) {
if self.width > Self::MIN_WIDTH {
self.width -= 1;
}
}
pub fn scene_del (&mut self, index: usize) {
self.scenes.remove(index);
}
}
impl ArrangerScene {
@ -160,19 +216,3 @@ impl ArrangerScene {
//})
//}
}
impl ArrangerTrack {
pub fn longest_name (tracks: &[Self]) -> usize {
tracks.iter().map(|s|s.name.read().unwrap().len()).fold(0, usize::max)
}
pub const MIN_WIDTH: usize = 3;
pub fn width_inc (&mut self) {
self.width += 1;
}
pub fn width_dec (&mut self) {
if self.width > Self::MIN_WIDTH {
self.width -= 1;
}
}
}

View file

@ -38,3 +38,15 @@ submod! {
transport
transport_cmd
}
pub trait JackModelApi {
fn jack (&self) -> &Arc<RwLock<JackClient>>;
}
pub trait ClockModelApi {
fn clock (&self) -> &Arc<Clock>;
fn is_stopped (&self) -> bool {
*self.clock().playing.read().unwrap() == Some(TransportState::Stopped)
}
}

View file

@ -41,6 +41,7 @@ impl Sampler {
},
_ => panic!("unexpected in sampler {name}: {edn:?}")
});
let midi_in = jack.read().unwrap().client().register_port("in", MidiIn::default())?;
Ok(Sampler {
jack: jack.clone(),
name: name.into(),
@ -48,7 +49,7 @@ impl Sampler {
unmapped: Default::default(),
voices: Default::default(),
buffer: Default::default(),
midi_in: jack.read().unwrap().register_port("in", MidiIn::default())?,
midi_in: midi_in,
audio_outs: vec![],
output_gain: 0.
})

View file

@ -1,5 +1,49 @@
use crate::*;
pub trait SequencerModelApi: JackModelApi + ClockModelApi {
fn phrases (&self) -> &PhrasePool;
fn player (&self) -> &MIDIPlayer;
}
impl JackModelApi for SequencerModel {
fn jack (&self) -> &Arc<RwLock<JackClient>> {
self.transport.jack()
}
}
impl ClockModelApi for SequencerModel {
fn clock (&self) -> &Arc<Clock> {
self.transport.clock()
}
}
impl TransportModelApi for SequencerModel {
fn transport (&self) -> &jack::Transport {
&self.transport.transport()
}
fn metronome (&self) -> bool {
self.transport.metronome()
}
}
impl SequencerModelApi for SequencerModel {
fn phrases (&self) -> &PhrasePool {
&self.phrases
}
fn player (&self) -> &MIDIPlayer {
&self.player
}
}
pub struct SequencerModel {
/// State of the JACK transport.
transport: TransportModel,
/// State of the phrase pool.
phrases: PhrasePool,
/// State of the phrase player.
player: MIDIPlayer,
}
#[derive(Debug)]
pub struct MIDIPlayer {
/// Global timebase

View file

@ -1,16 +1,42 @@
use crate::*;
pub struct Transport {
pub jack: Arc<RwLock<JackClient>>,
/// JACK transport handle.
pub transport: jack::Transport,
/// Current sample rate, tempo, and PPQ.
pub clock: Arc<Clock>,
/// Enable metronome?
pub metronome: bool,
pub trait TransportModelApi: JackModelApi + ClockModelApi {
fn transport (&self) -> &jack::Transport;
fn metronome (&self) -> bool;
}
impl Debug for Transport {
impl JackModelApi for TransportModel {
fn jack (&self) -> &Arc<RwLock<JackClient>> {
&self.jack
}
}
impl ClockModelApi for TransportModel {
fn clock (&self) -> &Arc<Clock> {
&self.clock
}
}
impl TransportModelApi for TransportModel {
fn transport (&self) -> &jack::Transport {
&self.transport
}
fn metronome (&self) -> bool {
self.metronome
}
}
pub struct TransportModel {
jack: Arc<RwLock<JackClient>>,
/// Current sample rate, tempo, and PPQ.
clock: Arc<Clock>,
/// JACK transport handle.
transport: jack::Transport,
/// Enable metronome?
metronome: bool,
}
impl Debug for TransportModel {
fn fmt (&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
f.debug_struct("transport")
.field("jack", &self.jack)
@ -21,7 +47,7 @@ impl Debug for Transport {
}
}
impl Transport {
impl TransportModel {
pub fn toggle_play (&mut self) -> Usually<()> {
let playing = self.clock.playing.read().unwrap().expect("1st sample has not been processed yet");
let playing = match playing {