mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: refactor pt.14: 138 errors
This commit is contained in:
parent
fbf217e108
commit
8b68a993bc
9 changed files with 95 additions and 100 deletions
|
|
@ -99,9 +99,11 @@ impl ArrangementScene {
|
|||
}).collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn longest_name (scenes: &[Self]) -> usize {
|
||||
scenes.iter().map(|s|s.name.read().unwrap().len()).fold(0, usize::max)
|
||||
}
|
||||
|
||||
/// Returns the pulse length of the longest phrase in the scene
|
||||
pub fn pulses (&self) -> usize {
|
||||
self.clips.iter().fold(0, |a, p|{
|
||||
|
|
|
|||
|
|
@ -872,6 +872,7 @@ impl<E: Engine, A: Widget<Engine = E>, B: Widget<Engine = E>> Widget for Split<E
|
|||
}
|
||||
|
||||
/// A widget that tracks its render width and height
|
||||
#[derive(Debug)]
|
||||
pub struct Measure<E: Engine>(PhantomData<E>, AtomicUsize, AtomicUsize);
|
||||
|
||||
impl<E: Engine> Measure<E> {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,19 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct SequencerAudio {
|
||||
transport: Arc<RwLock<Transport>>,
|
||||
player: Arc<RwLock<MIDIPlayer>>,
|
||||
}
|
||||
|
||||
/// JACK process callback for sequencer app
|
||||
impl Audio for SequencerAudio {
|
||||
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||
self.transport.write().unwrap().process(client, scope);
|
||||
self.player.write().unwrap().process(client, scope);
|
||||
Control::Continue
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MIDIPlayerAudio {
|
||||
model: Arc<RwLock<MIDIPlayer>>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::*;
|
||||
|
||||
pub struct ArrangementEditor<E: Engine> {
|
||||
pub state: Arrangement,
|
||||
pub model: Arrangement,
|
||||
/// Currently selected element.
|
||||
pub selected: ArrangementEditorFocus,
|
||||
/// Display mode of arranger
|
||||
|
|
@ -39,12 +39,6 @@ impl ArrangementEditorMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Audio for ArrangementEditor<E> {
|
||||
#[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||
self.state.process(client, scope)
|
||||
}
|
||||
}
|
||||
|
||||
impl Content for ArrangementEditor<Tui> {
|
||||
type Engine = Tui;
|
||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||
|
|
@ -61,9 +55,9 @@ impl Content for ArrangementEditor<Tui> {
|
|||
}
|
||||
|
||||
impl<E: Engine> ArrangementEditor<E> {
|
||||
pub fn new (state: Arrangement) -> Self {
|
||||
pub fn new (model: Arrangement) -> Self {
|
||||
Self {
|
||||
state,
|
||||
model,
|
||||
selected: ArrangementEditorFocus::Clip(0, 0),
|
||||
mode: ArrangementEditorMode::Vertical(2),
|
||||
color: Color::Rgb(28, 35, 25).into(),
|
||||
|
|
@ -76,30 +70,30 @@ impl<E: Engine> ArrangementEditor<E> {
|
|||
|
||||
impl<E: Engine> ArrangementEditor<E> {
|
||||
pub fn track (&self) -> Option<&ArrangementTrack> {
|
||||
self.selected.track().map(|t|self.state.tracks.get(t)).flatten()
|
||||
self.selected.track().map(|t|self.model.tracks.get(t)).flatten()
|
||||
}
|
||||
pub fn track_mut (&mut self) -> Option<&mut ArrangementTrack> {
|
||||
self.selected.track().map(|t|self.state.tracks.get_mut(t)).flatten()
|
||||
self.selected.track().map(|t|self.model.tracks.get_mut(t)).flatten()
|
||||
}
|
||||
pub fn scene (&self) -> Option<&ArrangementScene> {
|
||||
self.selected.scene().map(|s|self.state.scenes.get(s)).flatten()
|
||||
self.selected.scene().map(|s|self.model.scenes.get(s)).flatten()
|
||||
}
|
||||
pub fn scene_mut (&mut self) -> Option<&mut ArrangementScene> {
|
||||
self.selected.scene().map(|s|self.state.scenes.get_mut(s)).flatten()
|
||||
self.selected.scene().map(|s|self.model.scenes.get_mut(s)).flatten()
|
||||
}
|
||||
pub fn phrase (&self) -> Option<Arc<RwLock<Phrase>>> {
|
||||
self.scene()?.clips.get(self.selected.track()?)?.clone()
|
||||
}
|
||||
pub fn track_del (&mut self) {
|
||||
if let Some(index) = self.selected.track() { self.state.track_del(index); }
|
||||
if let Some(index) = self.selected.track() { self.model.track_del(index); }
|
||||
}
|
||||
pub fn scene_del (&mut self) {
|
||||
if let Some(index) = self.selected.scene() { self.state.scene_del(index); }
|
||||
if let Some(index) = self.selected.scene() { self.model.scene_del(index); }
|
||||
}
|
||||
pub fn track_widths (&self) -> Vec<(usize, usize)> {
|
||||
let mut widths = vec![];
|
||||
let mut total = 0;
|
||||
for track in self.tracks.iter() {
|
||||
for track in self.model.tracks.iter() {
|
||||
let width = track.width;
|
||||
widths.push((width, total));
|
||||
total += width;
|
||||
|
|
@ -111,20 +105,22 @@ impl<E: Engine> ArrangementEditor<E> {
|
|||
let track_index = self.selected.track();
|
||||
let scene_index = self.selected.scene();
|
||||
track_index
|
||||
.and_then(|index|self.tracks.get_mut(index).map(|track|(index, track)))
|
||||
.and_then(|index|self.model.tracks.get_mut(index).map(|track|(index, track)))
|
||||
.map(|(track_index, _)|scene_index
|
||||
.and_then(|index|self.scenes.get_mut(index))
|
||||
.and_then(|index|self.model.scenes.get_mut(index))
|
||||
.map(|scene|scene.clips[track_index] = None));
|
||||
}
|
||||
pub fn phrase_put (&mut self) {
|
||||
if let ArrangementEditorFocus::Clip(track, scene) = self.selected {
|
||||
self.scenes[scene].clips[track] = Some(self.phrases.read().unwrap().phrase().clone());
|
||||
self.model.scenes[scene].clips[track] = Some(
|
||||
self.model.phrases.read().unwrap().phrase().clone()
|
||||
);
|
||||
}
|
||||
}
|
||||
pub fn phrase_get (&mut self) {
|
||||
if let ArrangementEditorFocus::Clip(track, scene) = self.selected {
|
||||
if let Some(phrase) = &self.scenes[scene].clips[track] {
|
||||
let mut phrases = self.phrases.write().unwrap();
|
||||
if let Some(phrase) = &self.model.scenes[scene].clips[track] {
|
||||
let mut phrases = self.model.phrases.write().unwrap();
|
||||
if let Some(index) = phrases.index_of(&*phrase.read().unwrap()) {
|
||||
phrases.phrase = index;
|
||||
}
|
||||
|
|
@ -133,8 +129,8 @@ impl<E: Engine> ArrangementEditor<E> {
|
|||
}
|
||||
pub fn phrase_next (&mut self) {
|
||||
if let ArrangementEditorFocus::Clip(track, scene) = self.selected {
|
||||
if let Some(ref mut phrase) = self.scenes[scene].clips[track] {
|
||||
let phrases = self.phrases.read().unwrap();
|
||||
if let Some(ref mut phrase) = self.model.scenes[scene].clips[track] {
|
||||
let phrases = self.model.phrases.read().unwrap();
|
||||
let index = phrases.index_of(&*phrase.read().unwrap());
|
||||
if let Some(index) = index {
|
||||
if index < phrases.phrases.len().saturating_sub(1) {
|
||||
|
|
@ -146,8 +142,8 @@ impl<E: Engine> ArrangementEditor<E> {
|
|||
}
|
||||
pub fn phrase_prev (&mut self) {
|
||||
if let ArrangementEditorFocus::Clip(track, scene) = self.selected {
|
||||
if let Some(ref mut phrase) = self.scenes[scene].clips[track] {
|
||||
let phrases = self.phrases.read().unwrap();
|
||||
if let Some(ref mut phrase) = self.model.scenes[scene].clips[track] {
|
||||
let phrases = self.model.phrases.read().unwrap();
|
||||
let index = phrases.index_of(&*phrase.read().unwrap());
|
||||
if let Some(index) = index {
|
||||
if index > 0 {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::*;
|
|||
|
||||
pub struct PhrasePoolView<E: Engine> {
|
||||
_engine: PhantomData<E>,
|
||||
pub state: PhrasePool,
|
||||
pub model: PhrasePool,
|
||||
/// Selected phrase
|
||||
pub phrase: usize,
|
||||
/// Scroll offset
|
||||
|
|
@ -24,7 +24,7 @@ pub enum PhrasePoolMode {
|
|||
}
|
||||
|
||||
impl<E: Engine> PhrasePoolView<E> {
|
||||
pub fn new (state: PhrasePool) -> Self {
|
||||
pub fn new (model: PhrasePool) -> Self {
|
||||
Self {
|
||||
_engine: Default::default(),
|
||||
scroll: 0,
|
||||
|
|
@ -32,14 +32,14 @@ impl<E: Engine> PhrasePoolView<E> {
|
|||
mode: None,
|
||||
focused: false,
|
||||
entered: false,
|
||||
state,
|
||||
model,
|
||||
}
|
||||
}
|
||||
pub fn len (&self) -> usize {
|
||||
self.state.phrases.len()
|
||||
self.model.phrases.len()
|
||||
}
|
||||
pub fn phrase (&self) -> &Arc<RwLock<Phrase>> {
|
||||
&self.state.phrases[self.phrase]
|
||||
&self.model.phrases[self.phrase]
|
||||
}
|
||||
pub fn index_before (&self, index: usize) -> usize {
|
||||
index.overflowing_sub(1).0.min(self.len() - 1)
|
||||
|
|
@ -48,8 +48,8 @@ impl<E: Engine> PhrasePoolView<E> {
|
|||
(index + 1) % self.len()
|
||||
}
|
||||
pub fn index_of (&self, phrase: &Phrase) -> Option<usize> {
|
||||
for i in 0..self.state.phrases.len() {
|
||||
if *self.state.phrases[i].read().unwrap() == *phrase { return Some(i) }
|
||||
for i in 0..self.model.phrases.len() {
|
||||
if *self.model.phrases[i].read().unwrap() == *phrase { return Some(i) }
|
||||
}
|
||||
return None
|
||||
}
|
||||
|
|
@ -60,46 +60,46 @@ impl<E: Engine> PhrasePoolView<E> {
|
|||
}
|
||||
pub fn delete_selected (&mut self) {
|
||||
if self.phrase > 0 {
|
||||
self.state.phrases.remove(self.phrase);
|
||||
self.phrase = self.phrase.min(self.state.phrases.len().saturating_sub(1));
|
||||
self.model.phrases.remove(self.phrase);
|
||||
self.phrase = self.phrase.min(self.model.phrases.len().saturating_sub(1));
|
||||
}
|
||||
}
|
||||
pub fn append_new (&mut self, name: Option<&str>, color: Option<ItemColorTriplet>) {
|
||||
self.state.phrases.push(Self::new_phrase(name, color));
|
||||
self.phrase = self.state.phrases.len() - 1;
|
||||
self.model.phrases.push(Self::new_phrase(name, color));
|
||||
self.phrase = self.model.phrases.len() - 1;
|
||||
}
|
||||
pub fn insert_new (&mut self, name: Option<&str>, color: Option<ItemColorTriplet>) {
|
||||
self.state.phrases.insert(self.phrase + 1, Self::new_phrase(name, color));
|
||||
self.model.phrases.insert(self.phrase + 1, Self::new_phrase(name, color));
|
||||
self.phrase += 1;
|
||||
}
|
||||
pub fn insert_dup (&mut self) {
|
||||
let mut phrase = self.state.phrases[self.phrase].read().unwrap().duplicate();
|
||||
let mut phrase = self.model.phrases[self.phrase].read().unwrap().duplicate();
|
||||
phrase.color = ItemColorTriplet::random_near(phrase.color, 0.25);
|
||||
self.state.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
||||
self.model.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
|
||||
self.phrase += 1;
|
||||
}
|
||||
pub fn begin_rename (&mut self) {
|
||||
self.mode = Some(PhrasePoolMode::Rename(
|
||||
self.phrase,
|
||||
self.state.phrases[self.phrase].read().unwrap().name.clone()
|
||||
self.model.phrases[self.phrase].read().unwrap().name.clone()
|
||||
));
|
||||
}
|
||||
pub fn begin_length (&mut self) {
|
||||
self.mode = Some(PhrasePoolMode::Length(
|
||||
self.phrase,
|
||||
self.state.phrases[self.phrase].read().unwrap().length,
|
||||
self.model.phrases[self.phrase].read().unwrap().length,
|
||||
PhraseLengthFocus::Bar
|
||||
));
|
||||
}
|
||||
pub fn move_up (&mut self) {
|
||||
if self.phrase > 1 {
|
||||
self.state.phrases.swap(self.phrase - 1, self.phrase);
|
||||
self.model.phrases.swap(self.phrase - 1, self.phrase);
|
||||
self.phrase -= 1;
|
||||
}
|
||||
}
|
||||
pub fn move_down (&mut self) {
|
||||
if self.phrase < self.state.phrases.len().saturating_sub(1) {
|
||||
self.state.phrases.swap(self.phrase + 1, self.phrase);
|
||||
if self.phrase < self.model.phrases.len().saturating_sub(1) {
|
||||
self.model.phrases.swap(self.phrase + 1, self.phrase);
|
||||
self.phrase += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,9 +109,9 @@ impl<E: Engine> PhrasePoolView<E> {
|
|||
impl Content for PhrasePoolView<Tui> {
|
||||
type Engine = Tui;
|
||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||
let Self { focused, state, mode, .. } = self;
|
||||
let Self { focused, model, mode, .. } = self;
|
||||
let content = col!(
|
||||
(i, phrase) in state.iter().enumerate() => Layers::new(|add|{
|
||||
(i, phrase) in model.phrases.iter().enumerate() => Layers::new(|add|{
|
||||
let Phrase { ref name, color, length, .. } = *phrase.read().unwrap();
|
||||
let mut length = PhraseLength::new(length, None);
|
||||
if let Some(PhrasePoolMode::Length(phrase, new_length, focus)) = mode {
|
||||
|
|
@ -136,7 +136,7 @@ impl Content for PhrasePoolView<Tui> {
|
|||
let content = content.fill_xy().bg(Color::Rgb(28, 35, 25)).border(border);
|
||||
let title_color = if *focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)};
|
||||
let upper_left = format!("[{}] Phrases", if self.entered {"■"} else {" "});
|
||||
let upper_right = format!("({})", state.len());
|
||||
let upper_right = format!("({})", model.phrases.len());
|
||||
lay!(
|
||||
content,
|
||||
TuiStyle::fg(upper_left.to_string(), title_color).push_x(1).align_nw().fill_xy(),
|
||||
|
|
|
|||
|
|
@ -15,15 +15,6 @@ pub struct SequencerView<E: Engine> {
|
|||
pub player: MIDIPlayer,
|
||||
}
|
||||
|
||||
/// JACK process callback for sequencer app
|
||||
impl<E: Engine> Audio for SequencerView<E> {
|
||||
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||
self.transport.process(client, scope);
|
||||
self.player.process(client, scope);
|
||||
Control::Continue
|
||||
}
|
||||
}
|
||||
|
||||
impl Content for SequencerView<Tui> {
|
||||
type Engine = Tui;
|
||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ use crate::*;
|
|||
impl<E: Engine> FocusGrid for SequencerView<E> {
|
||||
type Item = SequencerFocus;
|
||||
fn cursor (&self) -> (usize, usize) {
|
||||
self.focus_cursor
|
||||
self.cursor
|
||||
}
|
||||
fn cursor_mut (&mut self) -> &mut (usize, usize) {
|
||||
&mut self.focus_cursor
|
||||
&mut self.cursor
|
||||
}
|
||||
fn layout (&self) -> &[&[SequencerFocus]] { &[
|
||||
&[SequencerFocus::Transport],
|
||||
|
|
@ -34,10 +34,8 @@ impl<E: Engine> FocusGrid for SequencerView<E> {
|
|||
}
|
||||
fn update_focus (&mut self) {
|
||||
let focused = self.focused();
|
||||
if let Some(transport) = self.transport.as_ref() {
|
||||
transport.write().unwrap().focused = focused == SequencerFocus::Transport
|
||||
}
|
||||
self.phrases.write().unwrap().focused = focused == SequencerFocus::PhrasePool;
|
||||
self.editor.focused = focused == SequencerFocus::PhraseEditor;
|
||||
self.transport.focused = focused == SequencerFocus::Transport;
|
||||
self.phrases.focused = focused == SequencerFocus::PhrasePool;
|
||||
self.editor.focused = focused == SequencerFocus::PhraseEditor;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,24 @@
|
|||
use crate::*;
|
||||
use tek_api::Transport;
|
||||
|
||||
/// Stores and displays time-related state.
|
||||
/// Stores and displays time-related info.
|
||||
#[derive(Debug)]
|
||||
pub struct TransportView<E: Engine> {
|
||||
_engine: PhantomData<E>,
|
||||
pub state: Transport,
|
||||
pub model: Transport,
|
||||
pub focus: TransportViewFocus,
|
||||
pub focused: bool,
|
||||
pub size: Measure<E>,
|
||||
}
|
||||
|
||||
/// JACK process callback for transport app
|
||||
impl<E: Engine> Audio for TransportView<E> {
|
||||
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||
self.state.process(client, scope);
|
||||
Control::Continue
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> TransportView<E> {
|
||||
pub fn new (jack: &Arc<RwLock<JackClient>>, clock: Option<&Arc<Clock>>) -> Self {
|
||||
Self {
|
||||
_engine: Default::default(),
|
||||
focused: false,
|
||||
focus: TransportViewFocus::PlayPause,
|
||||
state: Transport {
|
||||
size: Measure::new(),
|
||||
model: Transport {
|
||||
metronome: false,
|
||||
transport: jack.read().unwrap().transport(),
|
||||
jack: jack.clone(),
|
||||
|
|
@ -53,7 +46,7 @@ impl Content for TransportView<Tui> {
|
|||
lay!(
|
||||
self.focus.wrap(self.focused, TransportViewFocus::PlayPause, &Styled(
|
||||
None,
|
||||
match *self.clock.playing.read().unwrap() {
|
||||
match *self.model.clock.playing.read().unwrap() {
|
||||
Some(TransportState::Rolling) => "▶ PLAYING",
|
||||
Some(TransportState::Starting) => "READY ...",
|
||||
Some(TransportState::Stopped) => "⏹ STOPPED",
|
||||
|
|
@ -63,20 +56,20 @@ impl Content for TransportView<Tui> {
|
|||
|
||||
row!(
|
||||
self.focus.wrap(self.focused, TransportViewFocus::Bpm, &Outset::X(1u16, {
|
||||
let bpm = self.clock.timebase().bpm.get();
|
||||
let bpm = self.model.clock.timebase().bpm.get();
|
||||
row! { "BPM ", format!("{}.{:03}", bpm as usize, (bpm * 1000.0) % 1000.0) }
|
||||
})),
|
||||
//let quant = self.focus.wrap(self.focused, TransportViewFocus::Quant, &Outset::X(1u16, row! {
|
||||
//"QUANT ", ppq_to_name(self.quant as usize)
|
||||
//})),
|
||||
self.focus.wrap(self.focused, TransportViewFocus::Sync, &Outset::X(1u16, row! {
|
||||
"SYNC ", pulses_to_name(self.clock.sync.get() as usize)
|
||||
"SYNC ", pulses_to_name(self.model.clock.sync.get() as usize)
|
||||
}))
|
||||
).align_w().fill_x(),
|
||||
|
||||
self.focus.wrap(self.focused, TransportViewFocus::Clock, &{
|
||||
let time1 = self.clock.current.format_beat();
|
||||
let time2 = self.clock.current.usec.format_msu();
|
||||
let time1 = self.model.clock.current.format_beat();
|
||||
let time2 = self.model.clock.current.usec.format_msu();
|
||||
row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1)
|
||||
}).align_e().fill_x(),
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ impl Handle<Tui> for TransportView<Tui> {
|
|||
}
|
||||
|
||||
impl InputToCommand<Tui, TransportView<Tui>> for TransportViewCommand {
|
||||
fn input_to_command (state: &TransportView<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
fn input_to_command (view: &TransportView<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
use TransportViewFocus as Focus;
|
||||
use FocusCommand as FocusCmd;
|
||||
use TransportCommand as Cmd;
|
||||
|
|
@ -22,31 +22,31 @@ impl InputToCommand<Tui, TransportView<Tui>> for TransportViewCommand {
|
|||
key!(KeyCode::Left) => Self::Focus(FocusCmd::Prev),
|
||||
key!(KeyCode::Right) => Self::Focus(FocusCmd::Next),
|
||||
|
||||
key!(KeyCode::Char('.')) => Self::Transport(match state.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() + 1.0),
|
||||
Focus::Quant => Cmd::SetQuant(next_note_length(state.state.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(next_note_length(state.state.clock.sync.get()as usize)as f64+1.),
|
||||
key!(KeyCode::Char('.')) => Self::Transport(match view.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(view.model.clock.timebase().bpm.get() + 1.0),
|
||||
Focus::Quant => Cmd::SetQuant(next_note_length(view.model.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(next_note_length(view.model.clock.sync.get()as usize)as f64+1.),
|
||||
Focus::PlayPause => {todo!()},
|
||||
Focus::Clock => {todo!()}
|
||||
}),
|
||||
key!(KeyCode::Char(',')) => Self::Transport(match state.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() - 1.0),
|
||||
Focus::Quant => Cmd::SetQuant(prev_note_length(state.state.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(prev_note_length(state.state.clock.sync.get()as usize)as f64+1.),
|
||||
key!(KeyCode::Char(',')) => Self::Transport(match view.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(view.model.clock.timebase().bpm.get() - 1.0),
|
||||
Focus::Quant => Cmd::SetQuant(prev_note_length(view.model.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(prev_note_length(view.model.clock.sync.get()as usize)as f64+1.),
|
||||
Focus::PlayPause => {todo!()},
|
||||
Focus::Clock => {todo!()}
|
||||
}),
|
||||
key!(KeyCode::Char('>')) => Self::Transport(match state.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() + 0.001),
|
||||
Focus::Quant => Cmd::SetQuant(next_note_length(state.state.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(next_note_length(state.state.clock.sync.get()as usize)as f64+1.),
|
||||
key!(KeyCode::Char('>')) => Self::Transport(match view.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(view.model.clock.timebase().bpm.get() + 0.001),
|
||||
Focus::Quant => Cmd::SetQuant(next_note_length(view.model.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(next_note_length(view.model.clock.sync.get()as usize)as f64+1.),
|
||||
Focus::PlayPause => {todo!()},
|
||||
Focus::Clock => {todo!()}
|
||||
}),
|
||||
key!(KeyCode::Char('<')) => Self::Transport(match state.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() - 0.001),
|
||||
Focus::Quant => Cmd::SetQuant(prev_note_length(state.state.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(prev_note_length(state.state.clock.sync.get()as usize)as f64+1.),
|
||||
key!(KeyCode::Char('<')) => Self::Transport(match view.focus {
|
||||
Focus::Bpm => Cmd::SetBpm(view.model.clock.timebase().bpm.get() - 0.001),
|
||||
Focus::Quant => Cmd::SetQuant(prev_note_length(view.model.clock.quant.get()as usize)as f64),
|
||||
Focus::Sync => Cmd::SetSync(prev_note_length(view.model.clock.sync.get()as usize)as f64+1.),
|
||||
Focus::PlayPause => {todo!()},
|
||||
Focus::Clock => {todo!()}
|
||||
}),
|
||||
|
|
@ -57,7 +57,7 @@ impl InputToCommand<Tui, TransportView<Tui>> for TransportViewCommand {
|
|||
}
|
||||
|
||||
impl<E: Engine> Command<TransportView<E>> for TransportViewCommand {
|
||||
fn execute (self, state: &mut TransportView<E>) -> Perhaps<Self> {
|
||||
fn execute (self, view: &mut TransportView<E>) -> Perhaps<Self> {
|
||||
Ok(Some(match self {
|
||||
Self::Focus(command) => Self::Focus({
|
||||
use FocusCommand::*;
|
||||
|
|
@ -70,9 +70,9 @@ impl<E: Engine> Command<TransportView<E>> for TransportViewCommand {
|
|||
Self::Transport(command) => Self::Transport({
|
||||
use TransportCommand::*;
|
||||
match command {
|
||||
SetBpm(bpm) => SetBpm(state.state.clock.timebase().bpm.set(bpm)),
|
||||
SetQuant(quant) => SetQuant(state.state.clock.quant.set(quant)),
|
||||
SetSync(sync) => SetSync(state.state.clock.sync.set(sync)),
|
||||
SetBpm(bpm) => SetBpm(view.model.clock.timebase().bpm.set(bpm)),
|
||||
SetQuant(quant) => SetQuant(view.model.clock.quant.set(quant)),
|
||||
SetSync(sync) => SetSync(view.model.clock.sync.set(sync)),
|
||||
_ => { todo!() }
|
||||
}
|
||||
}),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue