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 {
fn phrase_entered (&self) -> bool;
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>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self {
metronome: false,
transport: jack.read().unwrap().transport(),
jack: jack.clone(),
focused: false,
current: Instant::default(),
cursor: (0, 0),
focus: TransportFocus::PlayPause,
focused: false,
jack: jack.clone(),
metronome: false,
playing: RwLock::new(None),
quant: Quantize::default(),
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 {
type Error = Box<dyn std::error::Error>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self::new(SequencerTui {
phrases: vec![],
metronome: false,
transport: jack.read().unwrap().transport(),
jack: jack.clone(),
focused: false,
size: Measure::new(),
}.into(), None, None))
Ok(Self {
current: Instant::default(),
cursor: (0, 0),
entered: false,
jack: jack.clone(),
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(),
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>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<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(),
size: Measure::new(),
entered: false,
quant: Default::default(),
sync: Default::default(),
splits: [20, 20],
note_buf: vec![],
midi_buf: vec![],
cursor: (0, 0),
entered: false,
history: vec![],
size: Measure::new(),
menu_bar: None,
status_bar: None,
color: Color::Rgb(28, 35, 25).into(),
current: Instant::default(),
cursor: (0, 0),
entered: false,
history: vec![],
jack: jack.clone(),
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,
sync: Default::default(),
tracks: vec![],
transport: jack.read().unwrap().transport(),
})
}
}

View file

@ -1,12 +1,15 @@
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> {
use KeyCode::Char;
use ClockCommand::{SetBpm, SetQuant, SetSync};
use TransportFocus as Focused;
use TransportCommand::{Focus, Clock, Playhead};
let focused = state.focused();
let focused = state.focused();
Some(match input.event() {
key!(Left) => Focus(FocusCommand::Prev),
key!(Right) => Focus(FocusCommand::Next),
@ -18,7 +21,7 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
Focused::Clock => Playhead(todo!()),
_ => {todo!()}
},
key!(KeyCode::Char(',')) => match focused {
key!(Char(',')) => match focused {
Focused::Bpm => Clock(SetBpm(state.bpm().get() - 1.0)),
Focused::Quant => Clock(SetQuant(state.prev_quant())),
Focused::Sync => Clock(SetSync(state.prev_sync())),
@ -26,7 +29,7 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
Focused::Clock => Playhead(todo!()),
_ => {todo!()}
},
key!(KeyCode::Char('>')) => match focused {
key!(Char('>')) => match focused {
Focused::Bpm => Clock(SetBpm(state.bpm().get() + 0.001)),
Focused::Quant => Clock(SetQuant(state.next_quant())),
Focused::Sync => Clock(SetSync(state.next_sync())),
@ -34,7 +37,7 @@ impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
Focused::Clock => Playhead(todo!()),
_ => {todo!()}
},
key!(KeyCode::Char('<')) => match focused {
key!(Char('<')) => match focused {
Focused::Bpm => Clock(SetBpm(state.bpm().get() - 0.001)),
Focused::Quant => Clock(SetQuant(state.prev_quant())),
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 {
fn input_to_command (state: &SequencerTui, input: &TuiInput) -> Option<Self> {
impl<T> InputToCommand<Tui, T> for SequencerCommand
where
T: SequencerControl + TransportControl + PhrasesControl + PhraseControl + HasFocus<Item = SequencerFocus>
{
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
use FocusCommand::*;
use SequencerCommand::*;
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> {
use FocusCommand::*;
use ArrangerCommand::*;
@ -242,28 +251,27 @@ impl<T: ArrangerControl> InputToCommand<Tui, T> for ArrangerCommand {
impl<T: PhrasesControl> InputToCommand<Tui, T> for PhrasesCommand {
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
use PhrasesCommand as Cmd;
use PhrasePoolCommand as Edit;
use PhraseRenameCommand as Rename;
use PhraseLengthCommand as Length;
match input.event() {
key!(KeyCode::Up) => Some(Cmd::Select(0)),
key!(KeyCode::Down) => Some(Cmd::Select(0)),
key!(KeyCode::Char(',')) => Some(Cmd::Edit(Edit::Swap(0, 0))),
key!(KeyCode::Char('.')) => Some(Cmd::Edit(Edit::Swap(0, 0))),
key!(KeyCode::Delete) => Some(Cmd::Edit(Edit::Delete(0))),
key!(KeyCode::Char('a')) => Some(Cmd::Edit(Edit::Add(0))),
key!(KeyCode::Char('i')) => Some(Cmd::Edit(Edit::Add(0))),
key!(KeyCode::Char('d')) => Some(Cmd::Edit(Edit::Duplicate(0))),
key!(KeyCode::Char('c')) => Some(Cmd::Edit(Edit::RandomColor(0))),
key!(KeyCode::Char('n')) => Some(Cmd::Rename(Rename::Begin)),
key!(KeyCode::Char('t')) => Some(Cmd::Length(Length::Begin)),
key!(KeyCode::Up) => Some(Self::Select(0)),
key!(KeyCode::Down) => Some(Self::Select(0)),
key!(KeyCode::Char(',')) => Some(Self::Edit(Edit::Swap(0, 0))),
key!(KeyCode::Char('.')) => Some(Self::Edit(Edit::Swap(0, 0))),
key!(KeyCode::Delete) => Some(Self::Edit(Edit::Delete(0))),
key!(KeyCode::Char('a')) => Some(Self::Edit(Edit::Add(0))),
key!(KeyCode::Char('i')) => Some(Self::Edit(Edit::Add(0))),
key!(KeyCode::Char('d')) => Some(Self::Edit(Edit::Duplicate(0))),
key!(KeyCode::Char('c')) => Some(Self::Edit(Edit::RandomColor(0))),
key!(KeyCode::Char('n')) => Some(Self::Rename(Rename::Begin)),
key!(KeyCode::Char('t')) => Some(Self::Length(Length::Begin)),
_ => match state.phrases_mode() {
Some(PhrasesMode::Rename(..)) => {
Rename::input_to_command(state, input).map(Cmd::Rename)
Rename::input_to_command(state, input).map(Self::Rename)
},
Some(PhrasesMode::Length(..)) => {
Length::input_to_command(state, input).map(Cmd::Length)
Length::input_to_command(state, input).map(Self::Length)
},
_ => None
}
@ -279,7 +287,7 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseLengthCommand {
key!(KeyCode::Down) => Self::Dec,
key!(KeyCode::Right) => Self::Next,
key!(KeyCode::Left) => Self::Prev,
key!(KeyCode::Enter) => Self::Set(length),
key!(KeyCode::Enter) => Self::Set(*length),
key!(KeyCode::Esc) => Self::Cancel,
_ => return None
})
@ -293,7 +301,7 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseRenameCommand {
fn input_to_command (state: &T, from: &TuiInput) -> Option<Self> {
if let Some(PhrasesMode::Rename(_, ref old_name)) = state.phrases_mode() {
Some(match from.event() {
key!(KeyCode::Char(c)) => {
key!(KeyCode::Char(c)) => {
let mut new_name = old_name.clone();
new_name.push(*c);
Self::Set(new_name)
@ -303,8 +311,8 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseRenameCommand {
new_name.pop();
Self::Set(new_name)
},
key!(KeyCode::Enter) => Self::Confirm,
key!(KeyCode::Esc) => Self::Cancel,
key!(KeyCode::Enter) => Self::Confirm,
key!(KeyCode::Esc) => Self::Cancel,
_ => return None
})
} else {
@ -330,19 +338,20 @@ impl<T: PhraseControl> InputToCommand<Tui, T> for PhraseCommand {
key!(KeyCode::Char('+')) => TimeZoomSet(0),
key!(KeyCode::PageUp) => NoteScrollSet(0),
key!(KeyCode::PageDown) => NoteScrollSet(0),
key!(KeyCode::Up) => match state.phrase_entered() {
key!(KeyCode::Up) => match state.phrase_entered() {
true => NoteCursorSet(0),
false => NoteScrollSet(0),
},
key!(KeyCode::Down) => match state.phrase_entered() {
key!(KeyCode::Down) => match state.phrase_entered() {
true => NoteCursorSet(0),
false => NoteScrollSet(0),
},
key!(KeyCode::Left) => match state.phrase_entered() {
key!(KeyCode::Left) => match state.phrase_entered() {
true => TimeCursorSet(0),
false => TimeScrollSet(0),
},
key!(KeyCode::Right) => match state.phrase_entered() {
key!(KeyCode::Right) => match state.phrase_entered() {
true => TimeCursorSet(0),
false => TimeScrollSet(0),
},

View file

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