mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16: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 {
|
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>>;
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue