mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 20:56:43 +01:00
wip(p62,e21)
This commit is contained in:
parent
76da19d9c6
commit
5673dd7e8a
14 changed files with 170 additions and 190 deletions
|
|
@ -12,7 +12,7 @@ pub enum FocusCommand {
|
||||||
Exit
|
Exit
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: HasFocus + FocusGrid + FocusEnter> Command<F> for FocusCommand {
|
impl<F: HasFocus + FocusGrid> Command<F> for FocusCommand {
|
||||||
fn execute (self, state: &mut F) -> Perhaps<FocusCommand> {
|
fn execute (self, state: &mut F) -> Perhaps<FocusCommand> {
|
||||||
use FocusCommand::*;
|
use FocusCommand::*;
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -46,6 +46,12 @@ pub trait HasFocus {
|
||||||
self.focus_next()
|
self.focus_next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Enter the focused item
|
||||||
|
fn focus_enter (&mut self) {}
|
||||||
|
/// Exit the focused item
|
||||||
|
fn focus_exit (&mut self) {}
|
||||||
|
/// Return the focused item, if any
|
||||||
|
fn focus_entered (&self) -> Option<Self::Item> { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for things that implement directional focus.
|
/// Trait for things that implement directional focus.
|
||||||
|
|
@ -94,7 +100,7 @@ pub trait FocusGrid {
|
||||||
impl<T, U> HasFocus for U
|
impl<T, U> HasFocus for U
|
||||||
where
|
where
|
||||||
T: Copy + PartialEq + Debug,
|
T: Copy + PartialEq + Debug,
|
||||||
U: FocusGrid<Item = T> + FocusEnter<Item = T>,
|
U: FocusGrid<Item = T>
|
||||||
{
|
{
|
||||||
type Item = T;
|
type Item = T;
|
||||||
fn focused (&self) -> Self::Item {
|
fn focused (&self) -> Self::Item {
|
||||||
|
|
@ -134,11 +140,3 @@ where
|
||||||
self.focus_update();
|
self.focus_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for things that can be focused into.
|
|
||||||
pub trait FocusEnter {
|
|
||||||
type Item: Copy + PartialEq + Debug;
|
|
||||||
fn focus_enter (&mut self) {}
|
|
||||||
fn focus_exit (&mut self) {}
|
|
||||||
fn focus_entered (&self) -> Option<Self::Item>;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ pub struct SequencerTui {
|
||||||
pub(crate) cursor: (usize, usize),
|
pub(crate) cursor: (usize, usize),
|
||||||
pub(crate) split: u16,
|
pub(crate) split: u16,
|
||||||
pub(crate) entered: bool,
|
pub(crate) entered: bool,
|
||||||
|
/// MIDI output buffer
|
||||||
|
pub(crate) note_buf: Vec<u8>,
|
||||||
|
/// MIDI output buffer
|
||||||
|
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Root view for standalone `tek_arranger`
|
/// Root view for standalone `tek_arranger`
|
||||||
|
|
@ -35,10 +39,12 @@ pub struct ArrangerTui {
|
||||||
pub(crate) color: ItemColor,
|
pub(crate) color: ItemColor,
|
||||||
pub(crate) entered: bool,
|
pub(crate) entered: bool,
|
||||||
pub(crate) size: Measure<Tui>,
|
pub(crate) size: Measure<Tui>,
|
||||||
pub(crate) note_buf: Vec<u8>,
|
|
||||||
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
|
||||||
pub(crate) cursor: (usize, usize),
|
pub(crate) cursor: (usize, usize),
|
||||||
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>,
|
||||||
|
/// MIDI output buffer
|
||||||
|
pub(crate) note_buf: Vec<u8>,
|
||||||
|
/// MIDI output buffer
|
||||||
|
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ pub enum SequencerCommand {
|
||||||
|
|
||||||
impl<T> Command<T> for SequencerCommand
|
impl<T> Command<T> for SequencerCommand
|
||||||
where
|
where
|
||||||
T: PhrasesControl + PhraseEditorControl + PlayheadApi
|
T: PhrasesControl + PhraseEditorControl + PlayheadApi + FocusGrid<Item = SequencerFocus>
|
||||||
+ FocusGrid<Item = SequencerFocus> + FocusEnter<Item = SequencerFocus>
|
|
||||||
{
|
{
|
||||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
||||||
use SequencerCommand::*;
|
use SequencerCommand::*;
|
||||||
|
|
@ -70,7 +69,7 @@ pub enum ArrangerCommand {
|
||||||
Clip(ArrangerClipCommand),
|
Clip(ArrangerClipCommand),
|
||||||
Select(ArrangerSelection),
|
Select(ArrangerSelection),
|
||||||
Zoom(usize),
|
Zoom(usize),
|
||||||
Phrases(PhrasePoolCommand),
|
Phrases(PhrasesCommand),
|
||||||
Editor(PhraseCommand),
|
Editor(PhraseCommand),
|
||||||
EditPhrase(Option<Arc<RwLock<Phrase>>>),
|
EditPhrase(Option<Arc<RwLock<Phrase>>>),
|
||||||
}
|
}
|
||||||
|
|
@ -263,10 +262,7 @@ pub enum PhraseCommand {
|
||||||
TimeZoomSet(usize),
|
TimeZoomSet(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Command<T> for PhraseCommand
|
impl<T: PhraseEditorControl> Command<T> for PhraseCommand {
|
||||||
where
|
|
||||||
T: PhraseEditorControl + FocusEnter
|
|
||||||
{
|
|
||||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
||||||
use PhraseCommand::*;
|
use PhraseCommand::*;
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
|
|
|
||||||
|
|
@ -123,9 +123,9 @@ impl<'a, T: PhrasesViewState> Content for PhrasesView<'a, T> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
let focused = self.0.phrases_focused();
|
let focused = self.0.phrases_focused();
|
||||||
let entered = self.0.entered();
|
let entered = self.0.phrases_entered();
|
||||||
let phrases = self.0.phrases();
|
let phrases = self.0.phrases();
|
||||||
let selected_phrase = self.0.phrase();
|
let selected_phrase = self.0.phrase_index();
|
||||||
let mode = self.0.phrase_mode();
|
let mode = self.0.phrase_mode();
|
||||||
let content = col!(
|
let content = col!(
|
||||||
(i, phrase) in phrases.iter().enumerate() => Layers::new(|add|{
|
(i, phrase) in phrases.iter().enumerate() => Layers::new(|add|{
|
||||||
|
|
@ -173,7 +173,7 @@ impl<'a, T: PhraseViewState> Content for PhraseView<'a, T> {
|
||||||
let phrase = self.0.phrase();
|
let phrase = self.0.phrase();
|
||||||
let size = self.0.size();
|
let size = self.0.size();
|
||||||
let focused = self.0.phrase_focused();
|
let focused = self.0.phrase_focused();
|
||||||
let entered = self.0.entered();
|
let entered = self.0.phrase_editor_entered();
|
||||||
let keys = self.0.keys();
|
let keys = self.0.keys();
|
||||||
let buffer = self.0.buffer();
|
let buffer = self.0.buffer();
|
||||||
let note_len = self.0.note_len();
|
let note_len = self.0.note_len();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,26 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
pub trait TransportControl: ClockApi {}
|
pub trait TransportControl: ClockApi {
|
||||||
|
fn transport_focused (&self) -> TransportFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransportControl for TransportTui {
|
||||||
|
fn transport_focused (&self) -> TransportFocus {
|
||||||
|
self.state.focus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransportControl for SequencerTui {
|
||||||
|
fn transport_focused (&self) -> TransportFocus {
|
||||||
|
self.transport.focus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransportControl for ArrangerTui {
|
||||||
|
fn transport_focused (&self) -> TransportFocus {
|
||||||
|
self.transport.focus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait SequencerControl: TransportControl {}
|
pub trait SequencerControl: TransportControl {}
|
||||||
|
|
||||||
|
|
@ -50,7 +70,7 @@ pub trait PhrasesControl: HasPhrases {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PhraseEditorControl {
|
pub trait PhraseEditorControl: HasFocus {
|
||||||
fn edit_phrase (&self, phrase: &Option<Arc<RwLock<Phrase>>>);
|
fn edit_phrase (&self, phrase: &Option<Arc<RwLock<Phrase>>>);
|
||||||
fn editing_phrase (&self) -> &Option<Arc<RwLock<Phrase>>>;
|
fn editing_phrase (&self) -> &Option<Arc<RwLock<Phrase>>>;
|
||||||
fn phrase_editor_entered (&self) -> bool;
|
fn phrase_editor_entered (&self) -> bool;
|
||||||
|
|
@ -67,12 +87,6 @@ pub trait PhraseEditorControl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TransportControl for TransportTui {}
|
|
||||||
|
|
||||||
impl TransportControl for SequencerTui {}
|
|
||||||
|
|
||||||
impl TransportControl for ArrangerTui {}
|
|
||||||
|
|
||||||
impl SequencerControl for SequencerTui {}
|
impl SequencerControl for SequencerTui {}
|
||||||
|
|
||||||
impl ArrangerControl for ArrangerTui {
|
impl ArrangerControl for ArrangerTui {
|
||||||
|
|
|
||||||
|
|
@ -68,27 +68,6 @@ impl TransportFocus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl HasFocus for TransportTui {
|
|
||||||
//type Item = TransportFocus;
|
|
||||||
//}
|
|
||||||
|
|
||||||
//impl FocusEnter for TransportTui {
|
|
||||||
//type Item = TransportFocus;
|
|
||||||
//fn focus_enter (&mut self) {
|
|
||||||
//self.entered = true;
|
|
||||||
//}
|
|
||||||
//fn focus_exit (&mut self) {
|
|
||||||
//self.entered = false;
|
|
||||||
//}
|
|
||||||
//fn focus_entered (&self) -> Option<Self::Item> {
|
|
||||||
//if self.entered {
|
|
||||||
//Some(self.focused())
|
|
||||||
//} else {
|
|
||||||
//None
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
impl FocusGrid for TransportTui {
|
impl FocusGrid for TransportTui {
|
||||||
type Item = TransportFocus;
|
type Item = TransportFocus;
|
||||||
fn focus_cursor (&self) -> (usize, usize) {
|
fn focus_cursor (&self) -> (usize, usize) {
|
||||||
|
|
@ -113,29 +92,29 @@ impl FocusGrid for TransportTui {
|
||||||
//type Item = SequencerFocus;
|
//type Item = SequencerFocus;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
impl FocusEnter for SequencerTui {
|
//impl FocusEnter for SequencerTui {
|
||||||
type Item = SequencerFocus;
|
//type Item = SequencerFocus;
|
||||||
fn focus_enter (&mut self) {
|
//fn focus_enter (&mut self) {
|
||||||
let focused = self.focused();
|
//let focused = self.focused();
|
||||||
if !self.entered {
|
//if !self.entered {
|
||||||
self.entered = true;
|
//self.entered = true;
|
||||||
// TODO
|
//// TODO
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
fn focus_exit (&mut self) {
|
//fn focus_exit (&mut self) {
|
||||||
if self.entered {
|
//if self.entered {
|
||||||
self.entered = false;
|
//self.entered = false;
|
||||||
// TODO
|
//// TODO
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
fn focus_entered (&self) -> Option<Self::Item> {
|
//fn focus_entered (&self) -> Option<Self::Item> {
|
||||||
if self.entered {
|
//if self.entered {
|
||||||
Some(self.focused())
|
//Some(self.focused())
|
||||||
} else {
|
//} else {
|
||||||
None
|
//None
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
|
|
||||||
impl FocusGrid for SequencerTui {
|
impl FocusGrid for SequencerTui {
|
||||||
type Item = SequencerFocus;
|
type Item = SequencerFocus;
|
||||||
|
|
@ -158,34 +137,34 @@ impl FocusGrid for SequencerTui {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FocusEnter for ArrangerTui {
|
//impl FocusEnter for ArrangerTui {
|
||||||
type Item = ArrangerFocus;
|
//type Item = ArrangerFocus;
|
||||||
fn focus_enter (&mut self) {
|
//fn focus_enter (&mut self) {
|
||||||
self.entered = true;
|
//self.entered = true;
|
||||||
//use ArrangerFocus::*;
|
////use ArrangerFocus::*;
|
||||||
//let focused = self.focused();
|
////let focused = self.focused();
|
||||||
//if !self.entered {
|
////if !self.entered {
|
||||||
//self.entered = focused == Arranger;
|
////self.entered = focused == Arranger;
|
||||||
//self.editor.entered = focused == PhraseEditor;
|
////self.editor.entered = focused == PhraseEditor;
|
||||||
//self.phrases.entered = focused == Phrases;
|
////self.phrases.entered = focused == Phrases;
|
||||||
|
////}
|
||||||
//}
|
//}
|
||||||
}
|
//fn focus_exit (&mut self) {
|
||||||
fn focus_exit (&mut self) {
|
|
||||||
self.entered = false;
|
|
||||||
//if self.entered {
|
|
||||||
//self.entered = false;
|
//self.entered = false;
|
||||||
//self.editor.entered = false;
|
////if self.entered {
|
||||||
//self.phrases.entered = false;
|
////self.entered = false;
|
||||||
|
////self.editor.entered = false;
|
||||||
|
////self.phrases.entered = false;
|
||||||
|
////}
|
||||||
|
//}
|
||||||
|
//fn focus_entered (&self) -> Option<Self::Item> {
|
||||||
|
//if self.entered {
|
||||||
|
//Some(self.focused())
|
||||||
|
//} else {
|
||||||
|
//None
|
||||||
|
//}
|
||||||
|
//}
|
||||||
//}
|
//}
|
||||||
}
|
|
||||||
fn focus_entered (&self) -> Option<Self::Item> {
|
|
||||||
if self.entered {
|
|
||||||
Some(self.focused())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Focus layout of arranger app
|
/// Focus layout of arranger app
|
||||||
impl FocusGrid for ArrangerTui {
|
impl FocusGrid for ArrangerTui {
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,13 @@ impl Handle<Tui> for ArrangerTui {
|
||||||
ArrangerCommand::execute_with_state(self, i)
|
ArrangerCommand::execute_with_state(self, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Handle<Tui> for PhrasesModel {
|
//impl Handle<Tui> for PhrasesModel {
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
//fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
PhrasesCommand::execute_with_state(self, from)
|
//PhrasesCommand::execute_with_state(self, from)
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
impl Handle<Tui> for PhraseEditorModel {
|
//impl Handle<Tui> for PhraseEditorModel {
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
//fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
PhraseCommand::execute_with_state(self, from)
|
//PhraseCommand::execute_with_state(self, from)
|
||||||
}
|
//}
|
||||||
}
|
//}
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ impl_has_phrase!(SequencerTui::player);
|
||||||
impl_has_phrase!(ArrangerTrack::player);
|
impl_has_phrase!(ArrangerTrack::player);
|
||||||
impl_has_phrase!(PhrasePlayerModel);
|
impl_has_phrase!(PhrasePlayerModel);
|
||||||
impl_midi_player!(ArrangerTrack);
|
impl_midi_player!(ArrangerTrack);
|
||||||
|
impl_midi_player!(PhrasePlayerModel);
|
||||||
|
|
||||||
impl HasScenes<ArrangerScene> for ArrangerTui {
|
impl HasScenes<ArrangerScene> for ArrangerTui {
|
||||||
fn scenes (&self) -> &Vec<ArrangerScene> {
|
fn scenes (&self) -> &Vec<ArrangerScene> {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
|
||||||
cursor: (0, 0),
|
cursor: (0, 0),
|
||||||
entered: false,
|
entered: false,
|
||||||
split: 20,
|
split: 20,
|
||||||
|
midi_buf: vec![],
|
||||||
|
note_buf: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -42,8 +44,6 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
|
||||||
tracks: vec![],
|
tracks: vec![],
|
||||||
color: Color::Rgb(28, 35, 25).into(),
|
color: Color::Rgb(28, 35, 25).into(),
|
||||||
history: vec![],
|
history: vec![],
|
||||||
midi_buf: vec![],
|
|
||||||
note_buf: vec![],
|
|
||||||
mode: ArrangerMode::Vertical(2),
|
mode: ArrangerMode::Vertical(2),
|
||||||
name: Arc::new(RwLock::new(String::new())),
|
name: Arc::new(RwLock::new(String::new())),
|
||||||
size: Measure::new(),
|
size: Measure::new(),
|
||||||
|
|
@ -52,6 +52,8 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
|
||||||
entered: false,
|
entered: false,
|
||||||
menu_bar: None,
|
menu_bar: None,
|
||||||
status_bar: None,
|
status_bar: None,
|
||||||
|
midi_buf: vec![],
|
||||||
|
note_buf: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,12 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
impl<T> InputToCommand<Tui, T> for TransportCommand
|
impl<T: TransportControl> InputToCommand<Tui, T> for TransportCommand {
|
||||||
where
|
|
||||||
T: TransportControl
|
|
||||||
+ HasFocus<Item = TransportFocus>
|
|
||||||
+ FocusEnter<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};
|
||||||
use TransportFocus as Focused;
|
use TransportFocus as Focused;
|
||||||
use TransportCommand::{Focus, Clock, Playhead};
|
use TransportCommand::{Focus, Clock, Playhead};
|
||||||
let focused = state.focused();
|
let focused = state.transport_focused();
|
||||||
Some(match input.event() {
|
Some(match input.event() {
|
||||||
key!(Left) => Focus(FocusCommand::Prev),
|
key!(Left) => Focus(FocusCommand::Prev),
|
||||||
key!(Right) => Focus(FocusCommand::Next),
|
key!(Right) => Focus(FocusCommand::Next),
|
||||||
|
|
@ -57,7 +52,6 @@ where
|
||||||
T: SequencerControl + TransportControl + PhrasesControl + PhraseEditorControl + PlayheadApi
|
T: SequencerControl + TransportControl + PhrasesControl + PhraseEditorControl + PlayheadApi
|
||||||
+ HasFocus<Item = SequencerFocus>
|
+ HasFocus<Item = SequencerFocus>
|
||||||
+ FocusGrid<Item = SequencerFocus>
|
+ FocusGrid<Item = SequencerFocus>
|
||||||
+ FocusEnter<Item = SequencerFocus>
|
|
||||||
{
|
{
|
||||||
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
|
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
|
||||||
use FocusCommand::*;
|
use FocusCommand::*;
|
||||||
|
|
@ -73,14 +67,11 @@ where
|
||||||
key!(KeyCode::Right) => Some(Self::Focus(Right)),
|
key!(KeyCode::Right) => Some(Self::Focus(Right)),
|
||||||
_ => Some(match state.focused() {
|
_ => Some(match state.focused() {
|
||||||
SequencerFocus::Transport => {
|
SequencerFocus::Transport => {
|
||||||
use TransportCommand::{Clock, Playhead};
|
use TransportCommand::{Clock, Playhead, Focus};
|
||||||
match TransportCommand::input_to_command(state, input)? {
|
match TransportCommand::input_to_command(state, input)? {
|
||||||
Clock(command) => {
|
Clock(command) => { todo!() },
|
||||||
todo!()
|
Playhead(command) => { todo!() },
|
||||||
},
|
Focus(command) => { todo!() },
|
||||||
Playhead(command) => {
|
|
||||||
todo!()
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
SequencerFocus::Phrases =>
|
SequencerFocus::Phrases =>
|
||||||
|
|
@ -110,23 +101,21 @@ impl InputToCommand<Tui, ArrangerTui> for ArrangerCommand {
|
||||||
key!(KeyCode::Esc) => Self::Focus(Exit),
|
key!(KeyCode::Esc) => Self::Focus(Exit),
|
||||||
key!(KeyCode::Char(' ')) => Self::Playhead(PlayheadCommand::Play(None)),
|
key!(KeyCode::Char(' ')) => Self::Playhead(PlayheadCommand::Play(None)),
|
||||||
_ => match state.focused() {
|
_ => match state.focused() {
|
||||||
|
ArrangerFocus::Menu => { todo!() },
|
||||||
ArrangerFocus::Transport => {
|
ArrangerFocus::Transport => {
|
||||||
use TransportCommand::{Clock, Playhead};
|
use TransportCommand::{Clock, Playhead, Focus};
|
||||||
match TransportCommand::input_to_command(state, input)? {
|
match TransportCommand::input_to_command(state, input)? {
|
||||||
Clock(command) => {
|
Clock(command) => { todo!() },
|
||||||
todo!()
|
Playhead(command) => { todo!() },
|
||||||
},
|
Focus(command) => { todo!() }
|
||||||
Playhead(command) => {
|
|
||||||
todo!()
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ArrangerFocus::PhraseEditor => Editor(
|
ArrangerFocus::PhraseEditor => Editor(
|
||||||
PhraseCommand::input_to_command(state, input)?
|
PhraseCommand::input_to_command(state, input)?
|
||||||
),
|
),
|
||||||
ArrangerFocus::Phrases => match input.event() {
|
ArrangerFocus::Phrases => match input.event() {
|
||||||
key!(KeyCode::Char('e')) => EditPhrase(Some(state.phrase().clone())),
|
key!(KeyCode::Char('e')) => EditPhrase(state.phrase().clone()),
|
||||||
_ => Phrases(PhrasePoolCommand::input_to_command(state, input)?)
|
_ => Phrases(PhrasesCommand::input_to_command(state, input)?)
|
||||||
},
|
},
|
||||||
ArrangerFocus::Arranger => {
|
ArrangerFocus::Arranger => {
|
||||||
use ArrangerSelection as Select;
|
use ArrangerSelection as Select;
|
||||||
|
|
@ -134,7 +123,7 @@ impl InputToCommand<Tui, ArrangerTui> for ArrangerCommand {
|
||||||
use ArrangerClipCommand as Clip;
|
use ArrangerClipCommand as Clip;
|
||||||
use ArrangerSceneCommand as Scene;
|
use ArrangerSceneCommand as Scene;
|
||||||
match input.event() {
|
match input.event() {
|
||||||
key!(KeyCode::Char('e')) => EditPhrase(state.phrase()),
|
key!(KeyCode::Char('e')) => EditPhrase(state.phrase().clone()),
|
||||||
_ => match input.event() {
|
_ => match input.event() {
|
||||||
// FIXME: boundary conditions
|
// FIXME: boundary conditions
|
||||||
|
|
||||||
|
|
@ -361,10 +350,7 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseRenameCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> InputToCommand<Tui, T> for PhraseCommand
|
impl<T: PhraseEditorControl> InputToCommand<Tui, T> for PhraseCommand {
|
||||||
where
|
|
||||||
T: PhraseEditorControl + FocusEnter
|
|
||||||
{
|
|
||||||
fn input_to_command (state: &T, from: &TuiInput) -> Option<Self> {
|
fn input_to_command (state: &T, from: &TuiInput) -> Option<Self> {
|
||||||
use PhraseCommand::*;
|
use PhraseCommand::*;
|
||||||
Some(match from.event() {
|
Some(match from.event() {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,11 @@ impl Audio for SequencerTui {
|
||||||
if PlayheadAudio(self).process(client, scope) == Control::Quit {
|
if PlayheadAudio(self).process(client, scope) == Control::Quit {
|
||||||
return Control::Quit
|
return Control::Quit
|
||||||
}
|
}
|
||||||
if PlayerAudio(self.player).process(client, scope) == Control::Quit {
|
if PlayerAudio(
|
||||||
|
&mut self.player,
|
||||||
|
&mut self.note_buf,
|
||||||
|
&mut self.midi_buf,
|
||||||
|
).process(client, scope) == Control::Quit {
|
||||||
return Control::Quit
|
return Control::Quit
|
||||||
}
|
}
|
||||||
Control::Continue
|
Control::Continue
|
||||||
|
|
@ -39,14 +43,14 @@ impl Audio for ArrangerTui {
|
||||||
let pulse = self.current().pulse.get();
|
let pulse = self.current().pulse.get();
|
||||||
let start = started_at.pulse.get();
|
let start = started_at.pulse.get();
|
||||||
let now = (pulse - start) % phrase.length as f64;
|
let now = (pulse - start) % phrase.length as f64;
|
||||||
self.now.set(now);
|
self.now().set(now);
|
||||||
return Control::Continue
|
return Control::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.now.set(0.);
|
self.now().set(0.);
|
||||||
return Control::Continue
|
return Control::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,6 @@ pub struct PhrasePlayerModel {
|
||||||
pub(crate) midi_ins: Vec<Port<MidiIn>>,
|
pub(crate) midi_ins: Vec<Port<MidiIn>>,
|
||||||
/// Play from current sequence to MIDI ports
|
/// Play from current sequence to MIDI ports
|
||||||
pub(crate) midi_outs: Vec<Port<MidiOut>>,
|
pub(crate) midi_outs: Vec<Port<MidiOut>>,
|
||||||
/// MIDI output buffer
|
|
||||||
pub(crate) note_buf: Vec<u8>,
|
|
||||||
/// MIDI output buffer
|
|
||||||
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
|
||||||
/// Notes currently held at input
|
/// Notes currently held at input
|
||||||
pub(crate) notes_in: Arc<RwLock<[bool; 128]>>,
|
pub(crate) notes_in: Arc<RwLock<[bool; 128]>>,
|
||||||
/// Notes currently held at output
|
/// Notes currently held at output
|
||||||
|
|
@ -79,8 +75,6 @@ impl Default for PhrasePlayerModel {
|
||||||
next_phrase: None,
|
next_phrase: None,
|
||||||
notes_in: RwLock::new([false;128]).into(),
|
notes_in: RwLock::new([false;128]).into(),
|
||||||
notes_out: RwLock::new([false;128]).into(),
|
notes_out: RwLock::new([false;128]).into(),
|
||||||
note_buf: vec![],
|
|
||||||
midi_buf: vec![],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +121,7 @@ impl Default for PhraseEditorModel {
|
||||||
mode: false,
|
mode: false,
|
||||||
notes_in: RwLock::new([false;128]).into(),
|
notes_in: RwLock::new([false;128]).into(),
|
||||||
notes_out: RwLock::new([false;128]).into(),
|
notes_out: RwLock::new([false;128]).into(),
|
||||||
now: Instant::default().into(),
|
now: Pulse::default().into(),
|
||||||
size: Measure::new(),
|
size: Measure::new(),
|
||||||
note_axis: RwLock::new(FixedAxis {
|
note_axis: RwLock::new(FixedAxis {
|
||||||
start: 12,
|
start: 12,
|
||||||
|
|
@ -301,7 +295,7 @@ impl PhrasesModel {
|
||||||
pub fn new (phrases: Vec<Arc<RwLock<Phrase>>>) -> Self {
|
pub fn new (phrases: Vec<Arc<RwLock<Phrase>>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
scroll: 0,
|
scroll: 0,
|
||||||
phrase: 0,
|
phrase: 0.into(),
|
||||||
mode: None,
|
mode: None,
|
||||||
focused: false,
|
focused: false,
|
||||||
entered: false,
|
entered: false,
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ impl StatusBar for ArrangerStatus {
|
||||||
ArrangerSelection::Scene(_) => ArrangerStatus::ArrangerScene,
|
ArrangerSelection::Scene(_) => ArrangerStatus::ArrangerScene,
|
||||||
ArrangerSelection::Clip(_, _) => ArrangerStatus::ArrangerClip,
|
ArrangerSelection::Clip(_, _) => ArrangerStatus::ArrangerClip,
|
||||||
},
|
},
|
||||||
ArrangerFocus::PhrasePool => ArrangerStatus::PhrasePool,
|
ArrangerFocus::Phrases => ArrangerStatus::PhrasePool,
|
||||||
ArrangerFocus::PhraseEditor => match entered {
|
ArrangerFocus::PhraseEditor => match entered {
|
||||||
true => ArrangerStatus::PhraseEdit,
|
true => ArrangerStatus::PhraseEdit,
|
||||||
false => ArrangerStatus::PhraseView,
|
false => ArrangerStatus::PhraseView,
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ pub trait ArrangerViewState {
|
||||||
|
|
||||||
pub trait PhrasesViewState: Send + Sync {
|
pub trait PhrasesViewState: Send + Sync {
|
||||||
fn phrases_focused (&self) -> bool;
|
fn phrases_focused (&self) -> bool;
|
||||||
fn entered (&self) -> bool;
|
fn phrases_entered (&self) -> bool;
|
||||||
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>>;
|
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>>;
|
||||||
fn phrase (&self) -> usize;
|
fn phrase_index (&self) -> usize;
|
||||||
fn phrase_mode (&self) -> &Option<PhrasesMode>;
|
fn phrase_mode (&self) -> &Option<PhrasesMode>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ pub trait PhraseViewState: Send + Sync {
|
||||||
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>>;
|
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>>;
|
||||||
fn phrase_focused (&self) -> bool;
|
fn phrase_focused (&self) -> bool;
|
||||||
fn phrase_editor_size (&self) -> &Measure<Tui>;
|
fn phrase_editor_size (&self) -> &Measure<Tui>;
|
||||||
fn entered (&self) -> bool;
|
fn phrase_editor_entered (&self) -> bool;
|
||||||
fn keys (&self) -> &Buffer;
|
fn keys (&self) -> &Buffer;
|
||||||
fn buffer (&self) -> &BigBuffer;
|
fn buffer (&self) -> &BigBuffer;
|
||||||
fn note_len (&self) -> usize;
|
fn note_len (&self) -> usize;
|
||||||
|
|
@ -96,13 +96,13 @@ impl PhrasesViewState for PhrasesModel {
|
||||||
fn phrases_focused (&self) -> bool {
|
fn phrases_focused (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn entered (&self) -> bool {
|
fn phrases_entered (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
|
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrase (&self) -> usize {
|
fn phrase_index (&self) -> usize {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrase_mode (&self) -> &Option<PhrasesMode> {
|
fn phrase_mode (&self) -> &Option<PhrasesMode> {
|
||||||
|
|
@ -114,13 +114,13 @@ impl PhrasesViewState for SequencerTui {
|
||||||
fn phrases_focused (&self) -> bool {
|
fn phrases_focused (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn entered (&self) -> bool {
|
fn phrases_entered (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
|
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrase (&self) -> usize {
|
fn phrase_index (&self) -> usize {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrase_mode (&self) -> &Option<PhrasesMode> {
|
fn phrase_mode (&self) -> &Option<PhrasesMode> {
|
||||||
|
|
@ -132,13 +132,13 @@ impl PhrasesViewState for ArrangerTui {
|
||||||
fn phrases_focused (&self) -> bool {
|
fn phrases_focused (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn entered (&self) -> bool {
|
fn phrases_entered (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
|
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrase (&self) -> usize {
|
fn phrase_index (&self) -> usize {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn phrase_mode (&self) -> &Option<PhrasesMode> {
|
fn phrase_mode (&self) -> &Option<PhrasesMode> {
|
||||||
|
|
@ -156,7 +156,7 @@ impl PhraseViewState for PhraseEditorModel {
|
||||||
fn phrase_editor_size (&self) -> &Measure<Tui> {
|
fn phrase_editor_size (&self) -> &Measure<Tui> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn entered (&self) -> bool {
|
fn phrase_editor_entered (&self) -> bool {
|
||||||
self.entered
|
self.entered
|
||||||
}
|
}
|
||||||
fn keys (&self) -> &Buffer {
|
fn keys (&self) -> &Buffer {
|
||||||
|
|
@ -192,7 +192,7 @@ impl PhraseViewState for SequencerTui {
|
||||||
fn phrase_editor_size (&self) -> &Measure<Tui> {
|
fn phrase_editor_size (&self) -> &Measure<Tui> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn entered (&self) -> bool {
|
fn phrase_editor_entered (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn keys (&self) -> &Buffer {
|
fn keys (&self) -> &Buffer {
|
||||||
|
|
@ -228,7 +228,7 @@ impl PhraseViewState for ArrangerTui {
|
||||||
fn phrase_editor_size (&self) -> &Measure<Tui> {
|
fn phrase_editor_size (&self) -> &Measure<Tui> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn entered (&self) -> bool {
|
fn phrase_editor_entered (&self) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn keys (&self) -> &Buffer {
|
fn keys (&self) -> &Buffer {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue