wip: p.56, e=86

This commit is contained in:
🪞👃🪞 2024-11-18 22:17:22 +01:00
parent 37ac7823af
commit 0964ad3be4
4 changed files with 108 additions and 72 deletions

View file

@ -67,7 +67,6 @@ impl PhrasesControl for PhrasesTui {
} }
} }
pub trait PhraseControl { pub trait PhraseControl {
fn phrase_entered (&self) -> bool; fn phrase_entered (&self) -> bool;
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>>; fn time_axis (&self) -> &RwLock<ScaledAxis<usize>>;

View file

@ -5,12 +5,18 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for TransportTui {
type Error = Box<dyn std::error::Error>; type Error = Box<dyn std::error::Error>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> { fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self { Ok(Self {
metronome: false, current: Instant::default(),
transport: jack.read().unwrap().transport(), cursor: (0, 0),
jack: jack.clone(),
focused: false,
focus: TransportFocus::PlayPause, focus: TransportFocus::PlayPause,
focused: false,
jack: jack.clone(),
metronome: false,
playing: RwLock::new(None),
quant: Quantize::default(),
size: Measure::new(), size: Measure::new(),
started: RwLock::new(None),
sync: LaunchSync::default(),
transport: jack.read().unwrap().transport(),
}) })
} }
} }
@ -18,14 +24,35 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for TransportTui {
impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui { impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
type Error = Box<dyn std::error::Error>; type Error = Box<dyn std::error::Error>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> { fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self::new(SequencerTui { Ok(Self {
phrases: vec![], current: Instant::default(),
metronome: false, cursor: (0, 0),
transport: jack.read().unwrap().transport(), entered: false,
jack: jack.clone(), jack: jack.clone(),
focused: false, metronome: false,
midi_buf: vec![],
midi_inputs: vec![],
midi_outputs: vec![],
monitoring: true,
next_phrase: None,
note_buf: vec![],
notes_in: RwLock::new([false;128]).into(),
notes_out: RwLock::new([false;128]).into(),
overdub: true,
phrases: vec![],
phrases_mode: None,
play_phrase: None,
playing: RwLock::new(None),
quant: Quantize::default(),
recording: true,
reset: false,
size: Measure::new(), size: Measure::new(),
}.into(), None, None)) split: 20,
started: RwLock::new(None),
sync: LaunchSync::default(),
transport: jack.read().unwrap().transport(),
view_phrase: 0,
})
} }
} }
@ -33,33 +60,32 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
type Error = Box<dyn std::error::Error>; type Error = Box<dyn std::error::Error>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> { fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self { Ok(Self {
name: Arc::new(RwLock::new(String::new())),
phrases: vec![],
phrase: 0,
scenes: vec![],
tracks: vec![],
metronome: false,
playing: None.into(),
started: None.into(),
transport: jack.read().unwrap().transport(),
current: Instant::default(),
jack: jack.clone(),
selected: ArrangerSelection::Clip(0, 0),
mode: ArrangerMode::Vertical(2),
color: Color::Rgb(28, 35, 25).into(), color: Color::Rgb(28, 35, 25).into(),
size: Measure::new(), current: Instant::default(),
entered: false,
quant: Default::default(),
sync: Default::default(),
splits: [20, 20],
note_buf: vec![],
midi_buf: vec![],
cursor: (0, 0), cursor: (0, 0),
entered: false, entered: false,
history: vec![], history: vec![],
size: Measure::new(), jack: jack.clone(),
menu_bar: None, menu_bar: None,
metronome: false,
midi_buf: vec![],
mode: ArrangerMode::Vertical(2),
name: Arc::new(RwLock::new(String::new())),
note_buf: vec![],
phrase: 0,
phrases: vec![],
phrases_mode: None,
playing: None.into(),
quant: Default::default(),
scenes: vec![],
selected: ArrangerSelection::Clip(0, 0),
size: Measure::new(),
splits: [20, 20],
started: None.into(),
status_bar: None, status_bar: None,
sync: Default::default(),
tracks: vec![],
transport: jack.read().unwrap().transport(),
}) })
} }
} }

View file

@ -1,6 +1,9 @@
use crate::*; use crate::*;
impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand { impl<T> InputToCommand<Tui, T> for TransportCommand
where
T: TransportControl + HasFocus<Item = TransportFocus>
{
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> { fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
use KeyCode::Char; use KeyCode::Char;
use ClockCommand::{SetBpm, SetQuant, SetSync}; use ClockCommand::{SetBpm, SetQuant, SetSync};
@ -18,7 +21,7 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
Focused::Clock => Playhead(todo!()), Focused::Clock => Playhead(todo!()),
_ => {todo!()} _ => {todo!()}
}, },
key!(KeyCode::Char(',')) => match focused { key!(Char(',')) => match focused {
Focused::Bpm => Clock(SetBpm(state.bpm().get() - 1.0)), Focused::Bpm => Clock(SetBpm(state.bpm().get() - 1.0)),
Focused::Quant => Clock(SetQuant(state.prev_quant())), Focused::Quant => Clock(SetQuant(state.prev_quant())),
Focused::Sync => Clock(SetSync(state.prev_sync())), Focused::Sync => Clock(SetSync(state.prev_sync())),
@ -26,7 +29,7 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
Focused::Clock => Playhead(todo!()), Focused::Clock => Playhead(todo!()),
_ => {todo!()} _ => {todo!()}
}, },
key!(KeyCode::Char('>')) => match focused { key!(Char('>')) => match focused {
Focused::Bpm => Clock(SetBpm(state.bpm().get() + 0.001)), Focused::Bpm => Clock(SetBpm(state.bpm().get() + 0.001)),
Focused::Quant => Clock(SetQuant(state.next_quant())), Focused::Quant => Clock(SetQuant(state.next_quant())),
Focused::Sync => Clock(SetSync(state.next_sync())), Focused::Sync => Clock(SetSync(state.next_sync())),
@ -34,7 +37,7 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
Focused::Clock => Playhead(todo!()), Focused::Clock => Playhead(todo!()),
_ => {todo!()} _ => {todo!()}
}, },
key!(KeyCode::Char('<')) => match focused { key!(Char('<')) => match focused {
Focused::Bpm => Clock(SetBpm(state.bpm().get() - 0.001)), Focused::Bpm => Clock(SetBpm(state.bpm().get() - 0.001)),
Focused::Quant => Clock(SetQuant(state.prev_quant())), Focused::Quant => Clock(SetQuant(state.prev_quant())),
Focused::Sync => Clock(SetSync(state.prev_sync())), Focused::Sync => Clock(SetSync(state.prev_sync())),
@ -47,8 +50,11 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
} }
} }
impl InputToCommand<Tui, SequencerTui> for SequencerCommand { impl<T> InputToCommand<Tui, T> for SequencerCommand
fn input_to_command (state: &SequencerTui, input: &TuiInput) -> Option<Self> { where
T: SequencerControl + TransportControl + PhrasesControl + PhraseControl + HasFocus<Item = SequencerFocus>
{
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
use FocusCommand::*; use FocusCommand::*;
use SequencerCommand::*; use SequencerCommand::*;
match input.event() { match input.event() {
@ -84,7 +90,10 @@ impl InputToCommand<Tui, SequencerTui> for SequencerCommand {
} }
} }
impl<T: ArrangerControl> InputToCommand<Tui, T> for ArrangerCommand { impl<T> InputToCommand<Tui, T> for ArrangerCommand
where
T: ArrangerControl + TransportControl + PhrasesControl + PhraseControl + HasFocus<Item = ArrangerFocus>
{
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> { fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
use FocusCommand::*; use FocusCommand::*;
use ArrangerCommand::*; use ArrangerCommand::*;
@ -242,28 +251,27 @@ impl<T: ArrangerControl> InputToCommand<Tui, T> for ArrangerCommand {
impl<T: PhrasesControl> InputToCommand<Tui, T> for PhrasesCommand { impl<T: PhrasesControl> InputToCommand<Tui, T> for PhrasesCommand {
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> { fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
use PhrasesCommand as Cmd;
use PhrasePoolCommand as Edit; use PhrasePoolCommand as Edit;
use PhraseRenameCommand as Rename; use PhraseRenameCommand as Rename;
use PhraseLengthCommand as Length; use PhraseLengthCommand as Length;
match input.event() { match input.event() {
key!(KeyCode::Up) => Some(Cmd::Select(0)), key!(KeyCode::Up) => Some(Self::Select(0)),
key!(KeyCode::Down) => Some(Cmd::Select(0)), key!(KeyCode::Down) => Some(Self::Select(0)),
key!(KeyCode::Char(',')) => Some(Cmd::Edit(Edit::Swap(0, 0))), key!(KeyCode::Char(',')) => Some(Self::Edit(Edit::Swap(0, 0))),
key!(KeyCode::Char('.')) => Some(Cmd::Edit(Edit::Swap(0, 0))), key!(KeyCode::Char('.')) => Some(Self::Edit(Edit::Swap(0, 0))),
key!(KeyCode::Delete) => Some(Cmd::Edit(Edit::Delete(0))), key!(KeyCode::Delete) => Some(Self::Edit(Edit::Delete(0))),
key!(KeyCode::Char('a')) => Some(Cmd::Edit(Edit::Add(0))), key!(KeyCode::Char('a')) => Some(Self::Edit(Edit::Add(0))),
key!(KeyCode::Char('i')) => Some(Cmd::Edit(Edit::Add(0))), key!(KeyCode::Char('i')) => Some(Self::Edit(Edit::Add(0))),
key!(KeyCode::Char('d')) => Some(Cmd::Edit(Edit::Duplicate(0))), key!(KeyCode::Char('d')) => Some(Self::Edit(Edit::Duplicate(0))),
key!(KeyCode::Char('c')) => Some(Cmd::Edit(Edit::RandomColor(0))), key!(KeyCode::Char('c')) => Some(Self::Edit(Edit::RandomColor(0))),
key!(KeyCode::Char('n')) => Some(Cmd::Rename(Rename::Begin)), key!(KeyCode::Char('n')) => Some(Self::Rename(Rename::Begin)),
key!(KeyCode::Char('t')) => Some(Cmd::Length(Length::Begin)), key!(KeyCode::Char('t')) => Some(Self::Length(Length::Begin)),
_ => match state.phrases_mode() { _ => match state.phrases_mode() {
Some(PhrasesMode::Rename(..)) => { Some(PhrasesMode::Rename(..)) => {
Rename::input_to_command(state, input).map(Cmd::Rename) Rename::input_to_command(state, input).map(Self::Rename)
}, },
Some(PhrasesMode::Length(..)) => { Some(PhrasesMode::Length(..)) => {
Length::input_to_command(state, input).map(Cmd::Length) Length::input_to_command(state, input).map(Self::Length)
}, },
_ => None _ => None
} }
@ -279,7 +287,7 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseLengthCommand {
key!(KeyCode::Down) => Self::Dec, key!(KeyCode::Down) => Self::Dec,
key!(KeyCode::Right) => Self::Next, key!(KeyCode::Right) => Self::Next,
key!(KeyCode::Left) => Self::Prev, key!(KeyCode::Left) => Self::Prev,
key!(KeyCode::Enter) => Self::Set(length), key!(KeyCode::Enter) => Self::Set(*length),
key!(KeyCode::Esc) => Self::Cancel, key!(KeyCode::Esc) => Self::Cancel,
_ => return None _ => return None
}) })
@ -330,6 +338,7 @@ impl<T: PhraseControl> InputToCommand<Tui, T> for PhraseCommand {
key!(KeyCode::Char('+')) => TimeZoomSet(0), key!(KeyCode::Char('+')) => TimeZoomSet(0),
key!(KeyCode::PageUp) => NoteScrollSet(0), key!(KeyCode::PageUp) => NoteScrollSet(0),
key!(KeyCode::PageDown) => NoteScrollSet(0), key!(KeyCode::PageDown) => NoteScrollSet(0),
key!(KeyCode::Up) => match state.phrase_entered() { key!(KeyCode::Up) => match state.phrase_entered() {
true => NoteCursorSet(0), true => NoteCursorSet(0),
false => NoteScrollSet(0), false => NoteScrollSet(0),

View file

@ -74,7 +74,7 @@ pub struct SequencerTui {
pub(crate) cursor: (usize, usize), pub(crate) cursor: (usize, usize),
pub(crate) size: Measure<Tui>, pub(crate) size: Measure<Tui>,
/// Mode switch /// Mode switch for phrase pool
pub(crate) phrases_mode: Option<PhrasesMode>, pub(crate) phrases_mode: Option<PhrasesMode>,
} }
@ -105,6 +105,8 @@ pub struct ArrangerTui {
pub(crate) menu_bar: Option<MenuBar<Tui, Self, ArrangerCommand>>, pub(crate) menu_bar: Option<MenuBar<Tui, Self, ArrangerCommand>>,
pub(crate) status_bar: Option<ArrangerStatus>, pub(crate) status_bar: Option<ArrangerStatus>,
pub(crate) history: Vec<ArrangerCommand>, pub(crate) history: Vec<ArrangerCommand>,
/// Mode switch for phrase pool
pub(crate) phrases_mode: Option<PhrasesMode>,
} }
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]