remove unused generic; add Sequencer::player

This commit is contained in:
🪞👃🪞 2024-11-01 00:42:12 +02:00
parent 076be5bcb3
commit 86adf493c8
5 changed files with 32 additions and 30 deletions

View file

@ -55,7 +55,7 @@ pub struct Arrangement<E: Engine> {
/// Collection of phrases. /// Collection of phrases.
pub phrases: Arc<RwLock<PhrasePool<E>>>, pub phrases: Arc<RwLock<PhrasePool<E>>>,
/// Collection of tracks. /// Collection of tracks.
pub tracks: Vec<ArrangementTrack<E>>, pub tracks: Vec<ArrangementTrack>,
/// Collection of scenes. /// Collection of scenes.
pub scenes: Vec<Scene>, pub scenes: Vec<Scene>,
/// Currently selected element. /// Currently selected element.
@ -70,13 +70,13 @@ pub struct Arrangement<E: Engine> {
pub size: Measure<E>, pub size: Measure<E>,
} }
/// Represents a track in the arrangement /// Represents a track in the arrangement
pub struct ArrangementTrack<E: Engine> { pub struct ArrangementTrack {
/// Name of track /// Name of track
pub name: Arc<RwLock<String>>, pub name: Arc<RwLock<String>>,
/// Inputs /// Inputs
pub inputs: Vec<Port<MidiIn>>, pub inputs: Vec<Port<MidiIn>>,
/// MIDI player/recorder /// MIDI player/recorder
pub player: PhrasePlayer<E>, pub player: PhrasePlayer,
/// Outputs /// Outputs
pub outputs: Vec<Port<MidiIn>>, pub outputs: Vec<Port<MidiIn>>,
/// Preferred width of track column /// Preferred width of track column
@ -374,10 +374,10 @@ impl<E: Engine> Arrangement<E> {
} }
/// Methods for tracks in arrangement /// Methods for tracks in arrangement
impl<E: Engine> Arrangement<E> { impl<E: Engine> Arrangement<E> {
pub fn track (&self) -> Option<&ArrangementTrack<E>> { pub fn track (&self) -> Option<&ArrangementTrack> {
self.selected.track().map(|t|self.tracks.get(t)).flatten() self.selected.track().map(|t|self.tracks.get(t)).flatten()
} }
pub fn track_mut (&mut self) -> Option<&mut ArrangementTrack<E>> { pub fn track_mut (&mut self) -> Option<&mut ArrangementTrack> {
self.selected.track().map(|t|self.tracks.get_mut(t)).flatten() self.selected.track().map(|t|self.tracks.get_mut(t)).flatten()
} }
pub fn track_width_inc (&mut self) { self.track_mut().map(|t|t.width_inc()); } pub fn track_width_inc (&mut self) { self.track_mut().map(|t|t.width_inc()); }
@ -386,7 +386,7 @@ impl<E: Engine> Arrangement<E> {
pub fn track_prev (&mut self) { self.selected.track_prev() } pub fn track_prev (&mut self) { self.selected.track_prev() }
pub fn track_add ( pub fn track_add (
&mut self, name: Option<&str>, color: Option<Color> &mut self, name: Option<&str>, color: Option<Color>
) -> Usually<&mut ArrangementTrack<E>> { ) -> Usually<&mut ArrangementTrack> {
self.tracks.push(name.map_or_else( self.tracks.push(name.map_or_else(
|| ArrangementTrack::new(&self.clock, &self.track_default_name(), color), || ArrangementTrack::new(&self.clock, &self.track_default_name(), color),
|name| ArrangementTrack::new(&self.clock, name, color), |name| ArrangementTrack::new(&self.clock, name, color),
@ -449,10 +449,10 @@ impl<E: Engine> Arrangement<E> {
} }
/// Methods for phrases in arrangement /// Methods for phrases in arrangement
impl<E: Engine> Arrangement<E> { impl<E: Engine> Arrangement<E> {
pub fn sequencer (&self) -> Option<&ArrangementTrack<E>> { pub fn sequencer (&self) -> Option<&ArrangementTrack> {
self.selected.track().map(|track|self.tracks.get(track)).flatten() self.selected.track().map(|track|self.tracks.get(track)).flatten()
} }
pub fn sequencer_mut (&mut self) -> Option<&mut ArrangementTrack<E>> { pub fn sequencer_mut (&mut self) -> Option<&mut ArrangementTrack> {
self.selected.track().map(|track|self.tracks.get_mut(track)).flatten() self.selected.track().map(|track|self.tracks.get_mut(track)).flatten()
} }
pub fn phrase (&self) -> Option<Arc<RwLock<Phrase>>> { pub fn phrase (&self) -> Option<Arc<RwLock<Phrase>>> {
@ -511,7 +511,7 @@ impl<E: Engine> Arrangement<E> {
} }
} }
} }
impl<E: Engine> ArrangementTrack<E> { impl ArrangementTrack {
pub fn new (clock: &Arc<TransportTime>, name: &str, color: Option<Color>) -> Self { pub fn new (clock: &Arc<TransportTime>, name: &str, color: Option<Color>) -> Self {
Self { Self {
name: Arc::new(RwLock::new(name.into())), name: Arc::new(RwLock::new(name.into())),
@ -533,7 +533,7 @@ impl<E: Engine> ArrangementTrack<E> {
impl ArrangementFocus { impl ArrangementFocus {
pub fn description <E: Engine> ( pub fn description <E: Engine> (
&self, &self,
tracks: &Vec<ArrangementTrack<E>>, tracks: &Vec<ArrangementTrack>,
scenes: &Vec<Scene>, scenes: &Vec<Scene>,
) -> String { ) -> String {
format!("Selected: {}", match self { format!("Selected: {}", match self {
@ -646,7 +646,7 @@ impl Scene {
}) })
} }
/// Returns true if all phrases in the scene are currently playing /// Returns true if all phrases in the scene are currently playing
pub fn is_playing <E: Engine> (&self, tracks: &[ArrangementTrack<E>]) -> bool { pub fn is_playing (&self, tracks: &[ArrangementTrack]) -> bool {
self.clips.iter().any(|clip|clip.is_some()) && self.clips.iter().enumerate() self.clips.iter().any(|clip|clip.is_some()) && self.clips.iter().enumerate()
.all(|(track_index, clip)|match clip { .all(|(track_index, clip)|match clip {
Some(clip) => tracks Some(clip) => tracks

View file

@ -129,7 +129,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
let Self(state, factor) = self; let Self(state, factor) = self;
let cols = state.track_widths(); let cols = state.track_widths();
let rows = Scene::ppqs(state.scenes.as_slice(), *factor); let rows = Scene::ppqs(state.scenes.as_slice(), *factor);
let tracks = state.tracks.as_ref() as &[ArrangementTrack<Tui>]; let tracks = state.tracks.as_ref() as &[ArrangementTrack];
let scenes = state.scenes.as_ref(); let scenes = state.scenes.as_ref();
let bg = state.color; let bg = state.color;
let clip_bg = Color::Rgb(40, 50, 30); let clip_bg = Color::Rgb(40, 50, 30);

View file

@ -19,6 +19,8 @@ pub struct Sequencer<E: Engine> {
pub phrases: Arc<RwLock<PhrasePool<E>>>, pub phrases: Arc<RwLock<PhrasePool<E>>>,
/// Phrase editor view /// Phrase editor view
pub editor: PhraseEditor<E>, pub editor: PhraseEditor<E>,
/// Phrase player
pub player: PhrasePlayer,
} }
/// Sections in the sequencer app that may be focused /// Sections in the sequencer app that may be focused
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
@ -113,8 +115,7 @@ pub struct PhraseEditor<E: Engine> {
pub height: AtomicUsize, pub height: AtomicUsize,
} }
/// Phrase player. /// Phrase player.
pub struct PhrasePlayer<E: Engine> { pub struct PhrasePlayer {
_engine: PhantomData<E>,
/// Global timebase /// Global timebase
pub clock: Arc<TransportTime>, pub clock: Arc<TransportTime>,
/// Start time and phrase being played /// Start time and phrase being played
@ -371,10 +372,9 @@ impl std::cmp::PartialEq for Phrase {
fn eq (&self, other: &Self) -> bool { self.uuid == other.uuid } fn eq (&self, other: &Self) -> bool { self.uuid == other.uuid }
} }
impl Eq for Phrase {} impl Eq for Phrase {}
impl<E: Engine> PhrasePlayer<E> { impl PhrasePlayer {
pub fn new (clock: &Arc<TransportTime>) -> Self { pub fn new (clock: &Arc<TransportTime>) -> Self {
Self { Self {
_engine: Default::default(),
clock: clock.clone(), clock: clock.clone(),
phrase: None, phrase: None,
started: None, started: None,

View file

@ -18,15 +18,19 @@ 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()))));
let focus_cursor = (1, 1); let clock = transport.read().unwrap().clock.clone();
let clock = transport.read().unwrap().clock.clone(); let sequencer = Sequencer {
let transport = self.transport.then_some(transport); jack: None,
let editor = PhraseEditor::new(); focus_cursor: (1, 1),
let phrases = Arc::new(RwLock::new(PhrasePool::new())); phrases: Arc::new(RwLock::new(PhrasePool::new())),
let sequencer = Sequencer { jack: None, focus_cursor, clock, transport, editor, phrases }; editor: PhraseEditor::new(),
player: PhrasePlayer::new(&clock),
transport: self.transport.then_some(transport),
clock,
};
if let Some(_) = self.name.as_ref() { if let Some(_) = self.name.as_ref() {
// TODO: sequencer.name = Arc::new(RwLock::new(name.clone())); // TODO: sequencer.name = Arc::new(RwLock::new(name.clone()));
} }

View file

@ -4,10 +4,11 @@ impl<E: Engine> Audio for Sequencer<E> {
if let Some(ref transport) = self.transport { if let Some(ref transport) = self.transport {
transport.write().unwrap().process(client, scope); transport.write().unwrap().process(client, scope);
} }
self.player.process(client, scope);
Control::Continue Control::Continue
} }
} }
impl<E: Engine> Audio for PhrasePlayer<E> { impl Audio for PhrasePlayer {
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
let frame0 = scope.last_frame_time() as usize; let frame0 = scope.last_frame_time() as usize;
let frames = scope.n_frames() as usize; let frames = scope.n_frames() as usize;
@ -94,7 +95,7 @@ impl<E: Engine> Audio for PhrasePlayer<E> {
Control::Continue Control::Continue
} }
} }
impl<E: Engine> PhrasePlayer<E> { impl PhrasePlayer {
pub fn has_midi_inputs (&self) -> bool { self.midi_inputs.len() > 0 } pub fn has_midi_inputs (&self) -> bool { self.midi_inputs.len() > 0 }
pub fn has_midi_outputs (&self) -> bool { self.midi_outputs.len() > 0 } pub fn has_midi_outputs (&self) -> bool { self.midi_outputs.len() > 0 }
/// Clear the section of the output buffer that we will be using /// Clear the section of the output buffer that we will be using
@ -103,10 +104,7 @@ impl<E: Engine> PhrasePlayer<E> {
} }
/// Emit "all notes off" at start of buffer if requested /// Emit "all notes off" at start of buffer if requested
pub fn reset_midi_out_buf (&mut self, force_reset: bool) { pub fn reset_midi_out_buf (&mut self, force_reset: bool) {
if self.reset || force_reset { if self.reset || force_reset { all_notes_off(&mut self.midi_out_buf); self.reset = false; }
all_notes_off(&mut self.midi_out_buf);
self.reset = false;
}
} }
} }
/// Add "all notes off" to the start of a buffer. /// Add "all notes off" to the start of a buffer.