mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
remove unused generic; add Sequencer::player
This commit is contained in:
parent
076be5bcb3
commit
86adf493c8
5 changed files with 32 additions and 30 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue