mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: p.56, e=86
This commit is contained in:
parent
37ac7823af
commit
0964ad3be4
4 changed files with 108 additions and 72 deletions
|
|
@ -67,7 +67,6 @@ impl PhrasesControl for PhrasesTui {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub trait PhraseControl {
|
||||
fn phrase_entered (&self) -> bool;
|
||||
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>>;
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue