wip(p65,e2)

This commit is contained in:
🪞👃🪞 2024-11-21 16:34:44 +01:00
parent fffd830e15
commit e768790658
9 changed files with 226 additions and 299 deletions

View file

@ -1,5 +1,47 @@
use crate::*; use crate::*;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum FocusState<T: Copy + Debug + PartialEq> {
Exited(T),
Focused(T),
Entered(T),
}
impl<T: Copy + Debug + PartialEq> FocusState<T> {
pub fn inner (&self) -> T {
match self {
Self::Exited(inner) => *inner,
Self::Focused(inner) => *inner,
Self::Entered(inner) => *inner,
}
}
pub fn set_inner (&mut self, inner: T) {
*self = match self {
Self::Exited(_) => Self::Exited(inner),
Self::Focused(_) => Self::Focused(inner),
Self::Entered(_) => Self::Entered(inner),
}
}
pub fn is_exited (&self) -> bool {
if let Self::Exited(_) = self { true } else { false }
}
pub fn is_focused (&self) -> bool {
if let Self::Focused(_) = self { true } else { false }
}
pub fn is_entered (&self) -> bool {
if let Self::Entered(_) = self { true } else { false }
}
pub fn to_exited (&mut self) {
*self = Self::Exited(self.inner())
}
pub fn to_focused (&mut self) {
*self = Self::Focused(self.inner())
}
pub fn to_entered (&mut self) {
*self = Self::Entered(self.inner())
}
}
#[derive(Copy, Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
pub enum FocusCommand { pub enum FocusCommand {
Next, Next,

View file

@ -170,9 +170,9 @@ impl<'a, T: PhrasesViewState> Content for PhrasesView<'a, T> {
impl<'a, T: PhraseViewState> Content for PhraseView<'a, T> { impl<'a, T: PhraseViewState> Content for PhraseView<'a, T> {
type Engine = Tui; type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> { fn content (&self) -> impl Widget<Engine = Tui> {
let phrase = self.0.phrase(); let phrase = self.0.phrase_editing();
let size = self.0.size(); let size = self.0.size();
let focused = self.0.phrase_focused(); let focused = self.0.phrase_editor_focused();
let entered = self.0.phrase_editor_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();

View file

@ -6,19 +6,19 @@ pub trait TransportControl: ClockApi {
impl TransportControl for TransportTui { impl TransportControl for TransportTui {
fn transport_focused (&self) -> TransportFocus { fn transport_focused (&self) -> TransportFocus {
self.state.focus self.state.focus.inner()
} }
} }
impl TransportControl for SequencerTui { impl TransportControl for SequencerTui {
fn transport_focused (&self) -> TransportFocus { fn transport_focused (&self) -> TransportFocus {
self.transport.focus self.transport.focus.inner()
} }
} }
impl TransportControl for ArrangerTui { impl TransportControl for ArrangerTui {
fn transport_focused (&self) -> TransportFocus { fn transport_focused (&self) -> TransportFocus {
self.transport.focus self.transport.focus.inner()
} }
} }

View file

@ -1,8 +1,13 @@
// Not all fields are included here. Add as needed.
use crate::*; use crate::*;
impl std::fmt::Debug for TransportModel { use std::fmt::{Debug, Formatter, Error};
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { type DebugResult = std::result::Result<(), Error>;
f.debug_struct("TransportModel")
impl Debug for ClockModel {
fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
f.debug_struct("editor")
.field("playing", &self.playing) .field("playing", &self.playing)
.field("started", &self.started) .field("started", &self.started)
.field("current", &self.current) .field("current", &self.current)
@ -12,8 +17,17 @@ impl std::fmt::Debug for TransportModel {
} }
} }
impl std::fmt::Debug for TransportTui { impl Debug for TransportModel {
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
f.debug_struct("TransportModel")
.field("clock", &self.clock)
.field("focus", &self.focus)
.finish()
}
}
impl Debug for TransportTui {
fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
f.debug_struct("Measure") f.debug_struct("Measure")
.field("jack", &self.jack) .field("jack", &self.jack)
.field("state", &self.state) .field("state", &self.state)
@ -23,11 +37,21 @@ impl std::fmt::Debug for TransportTui {
} }
} }
impl std::fmt::Debug for PhraseEditorModel { impl Debug for PhraseEditorModel {
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
f.debug_struct("editor") f.debug_struct("editor")
.field("note_axis", &self.time_axis) .field("note_axis", &self.time_axis)
.field("time_axis", &self.note_axis) .field("time_axis", &self.note_axis)
.finish() .finish()
} }
} }
impl Debug for PhrasePlayerModel {
fn fmt (&self, f: &mut Formatter<'_>) -> DebugResult {
f.debug_struct("editor")
.field("clock", &self.clock)
.field("play_phrase", &self.play_phrase)
.field("next_phrase", &self.next_phrase)
.finish()
}
}

View file

@ -174,18 +174,23 @@ macro_rules! impl_phrase_editor_control {
impl_jack_api!(TransportTui::jack); impl_jack_api!(TransportTui::jack);
impl_jack_api!(SequencerTui::jack); impl_jack_api!(SequencerTui::jack);
impl_jack_api!(ArrangerTui::jack); impl_jack_api!(ArrangerTui::jack);
impl_clock_api!(TransportTui::state);
impl_clock_api!(SequencerTui::transport); impl_clock_api!(TransportTui::state::clock);
impl_clock_api!(ArrangerTui::transport); impl_clock_api!(SequencerTui::transport::clock);
impl_clock_api!(PhrasePlayerModel); impl_clock_api!(ArrangerTui::transport::clock);
impl_clock_api!(ArrangerTrack::player); impl_clock_api!(PhrasePlayerModel::clock);
impl_clock_api!(ArrangerTrack::player::clock);
impl_has_phrases!(PhrasesModel); impl_has_phrases!(PhrasesModel);
impl_has_phrases!(SequencerTui::phrases); impl_has_phrases!(SequencerTui::phrases);
impl_has_phrases!(ArrangerTui::phrases); impl_has_phrases!(ArrangerTui::phrases);
impl_midi_player!(SequencerTui::player); impl_midi_player!(SequencerTui::player);
impl_midi_player!(ArrangerTrack::player); impl_midi_player!(ArrangerTrack::player);
impl_midi_player!(PhrasePlayerModel); impl_midi_player!(PhrasePlayerModel);
impl_phrases_control!(SequencerTui); impl_phrases_control!(SequencerTui);
impl_phrases_control!(ArrangerTui); impl_phrases_control!(ArrangerTui);
impl_phrase_editor_control!(SequencerTui [SequencerFocus::PhraseEditor]); impl_phrase_editor_control!(SequencerTui [SequencerFocus::PhraseEditor]);
impl_phrase_editor_control!(ArrangerTui [ArrangerFocus::PhraseEditor]); impl_phrase_editor_control!(ArrangerTui [ArrangerFocus::PhraseEditor]);

View file

@ -6,7 +6,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for TransportTui {
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> { fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self { Ok(Self {
jack: jack.clone(), jack: jack.clone(),
state: TransportModel::from(jack.read().unwrap().transport()), state: TransportModel::from(&Arc::new(jack.read().unwrap().transport())),
size: Measure::new(), size: Measure::new(),
cursor: (0, 0), cursor: (0, 0),
}) })
@ -16,11 +16,11 @@ 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> {
let transport = TransportModel::from(&Arc::new(jack.read().unwrap().transport()));
Ok(Self { Ok(Self {
jack: jack.clone(), jack: jack.clone(),
transport: TransportModel::from(jack.read().unwrap().transport()),
phrases: PhrasesModel::default(), phrases: PhrasesModel::default(),
player: PhrasePlayerModel::default(), player: PhrasePlayerModel::from(&transport.clock),
editor: PhraseEditorModel::default(), editor: PhraseEditorModel::default(),
size: Measure::new(), size: Measure::new(),
cursor: (0, 0), cursor: (0, 0),
@ -28,6 +28,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
split: 20, split: 20,
midi_buf: vec![], midi_buf: vec![],
note_buf: vec![], note_buf: vec![],
transport,
}) })
} }
} }
@ -37,7 +38,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> { fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self { Ok(Self {
jack: jack.clone(), jack: jack.clone(),
transport: TransportModel::from(jack.read().unwrap().transport()), transport: TransportModel::from(&Arc::new(jack.read().unwrap().transport())),
phrases: PhrasesModel::default(), phrases: PhrasesModel::default(),
editor: PhraseEditorModel::default(), editor: PhraseEditorModel::default(),
selected: ArrangerSelection::Clip(0, 0), selected: ArrangerSelection::Clip(0, 0),
@ -58,4 +59,3 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
}) })
} }
} }

View file

@ -112,7 +112,7 @@ impl InputToCommand<Tui, ArrangerTui> for ArrangerCommand {
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(state.phrase().clone()), key!(KeyCode::Char('e')) => EditPhrase(state.phrase_editing().clone()),
_ => Phrases(PhrasesCommand::input_to_command(state, input)?) _ => Phrases(PhrasesCommand::input_to_command(state, input)?)
}, },
ArrangerFocus::Arranger => { ArrangerFocus::Arranger => {
@ -121,7 +121,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().clone()), key!(KeyCode::Char('e')) => EditPhrase(state.phrase_editing().clone()),
_ => match input.event() { _ => match input.event() {
// FIXME: boundary conditions // FIXME: boundary conditions

View file

@ -1,56 +1,57 @@
use crate::*; use crate::*;
pub struct TransportModel { #[derive(Clone)]
pub struct ClockModel {
/// JACK transport handle. /// JACK transport handle.
pub(crate) transport: Arc<Transport>, pub(crate) transport: Arc<Transport>,
/// Playback state /// Playback state
pub(crate) playing: Arc<RwLock<Option<TransportState>>>, pub(crate) playing: Arc<RwLock<Option<TransportState>>>,
/// Global sample and usec at which playback started /// Global sample and usec at which playback started
pub(crate) started: Arc<RwLock<Option<(usize, usize)>>>, pub(crate) started: Arc<RwLock<Option<(usize, usize)>>>,
/// Current moment in time /// Current moment in time
pub(crate) current: Arc<Instant>, pub(crate) current: Arc<Instant>,
/// Note quantization factor /// Note quantization factor
pub(crate) quant: Arc<Quantize>, pub(crate) quant: Arc<Quantize>,
/// Launch quantization factor /// Launch quantization factor
pub(crate) sync: Arc<LaunchSync>, pub(crate) sync: Arc<LaunchSync>,
/// Enable metronome? /// TODO: Enable metronome?
pub(crate) metronome: bool, pub(crate) metronome: bool,
/// Selected transport component
pub(crate) focus: TransportFocus,
/// Whether the transport is focused
pub(crate) is_focused: bool,
} }
impl From<jack::Transport> for TransportModel { impl From<&Arc<Transport>> for ClockModel {
fn from (transport: Transport) -> Self { fn from (transport: &Arc<Transport>) -> Self {
Self { Self {
current: Instant::default().into(), current: Instant::default().into(),
focus: TransportFocus::PlayPause, playing: RwLock::new(None).into(),
is_focused: true, quant: Quantize::default().into(),
metronome: false, started: RwLock::new(None).into(),
playing: RwLock::new(None).into(), sync: LaunchSync::default().into(),
quant: Quantize::default().into(), transport: transport.clone(),
started: RwLock::new(None).into(), metronome: false,
sync: LaunchSync::default().into(), }
transport: transport.into(), }
}
pub struct TransportModel {
/// State of clock and playhead
pub(crate) clock: ClockModel,
/// Whether the transport is focused and which part of it is selected
pub(crate) focus: FocusState<TransportFocus>,
}
impl From<&Arc<Transport>> for TransportModel {
fn from (transport: &Arc<Transport>) -> Self {
Self {
clock: ClockModel::from(transport),
focus: FocusState::Exited(TransportFocus::PlayPause),
} }
} }
} }
/// Contains state for playing a phrase /// Contains state for playing a phrase
#[derive(Debug)]
pub struct PhrasePlayerModel { pub struct PhrasePlayerModel {
/// Playback state /// State of clock and playhead
pub(crate) playing: Arc<RwLock<Option<TransportState>>>, pub(crate) clock: ClockModel,
/// Global sample and usec at which playback started
pub(crate) started: Arc<RwLock<Option<(usize, usize)>>>,
/// Current moment in time
pub(crate) current: Arc<Instant>,
/// Note quantization factor
pub(crate) quant: Arc<Quantize>,
/// Launch quantization factor
pub(crate) sync: Arc<LaunchSync>,
/// Start time and phrase being played /// Start time and phrase being played
pub(crate) play_phrase: Option<(Instant, Option<Arc<RwLock<Phrase>>>)>, pub(crate) play_phrase: Option<(Instant, Option<Arc<RwLock<Phrase>>>)>,
/// Start time and next phrase /// Start time and next phrase
@ -73,14 +74,10 @@ pub struct PhrasePlayerModel {
pub(crate) notes_out: Arc<RwLock<[bool; 128]>>, pub(crate) notes_out: Arc<RwLock<[bool; 128]>>,
} }
impl Default for PhrasePlayerModel { impl From<&ClockModel> for PhrasePlayerModel {
fn default () -> Self { fn from (clock: &ClockModel) -> Self {
Self { Self {
playing: RwLock::new(None).into(), clock: clock.clone(),
started: RwLock::new(None).into(),
current: Instant::default().into(),
quant: Quantize::default().into(),
sync: LaunchSync::default().into(),
midi_ins: vec![], midi_ins: vec![],
midi_outs: vec![], midi_outs: vec![],
reset: true, reset: true,
@ -95,19 +92,6 @@ impl Default for PhrasePlayerModel {
} }
} }
impl From<&TransportModel> for PhrasePlayerModel {
fn from (transport: &TransportModel) -> Self {
Self {
playing: transport.playing.clone(),
started: transport.started.clone(),
current: transport.current.clone(),
quant: transport.quant.clone(),
sync: transport.sync.clone(),
..Default::default()
}
}
}
/// Contains state for viewing and editing a phrase /// Contains state for viewing and editing a phrase
pub struct PhraseEditorModel { pub struct PhraseEditorModel {
/// Phrase being played /// Phrase being played
@ -123,9 +107,7 @@ pub struct PhraseEditorModel {
/// Cursor/scroll/zoom in time axis /// Cursor/scroll/zoom in time axis
pub(crate) time_axis: RwLock<ScaledAxis<usize>>, pub(crate) time_axis: RwLock<ScaledAxis<usize>>,
/// Whether this widget is focused /// Whether this widget is focused
pub(crate) focused: bool, pub(crate) focus: FocusState<()>,
/// Whether note enter mode is enabled
pub(crate) entered: bool,
/// Display mode /// Display mode
pub(crate) mode: bool, pub(crate) mode: bool,
/// Notes currently held at input /// Notes currently held at input
@ -145,8 +127,7 @@ impl Default for PhraseEditorModel {
note_len: 24, note_len: 24,
keys: keys_vert(), keys: keys_vert(),
buffer: Default::default(), buffer: Default::default(),
focused: false, focus: FocusState::Exited(()),
entered: false,
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(),
@ -178,9 +159,7 @@ pub struct PhrasesModel {
/// Mode switch /// Mode switch
pub(crate) mode: Option<PhrasesMode>, pub(crate) mode: Option<PhrasesMode>,
/// Whether this widget is focused /// Whether this widget is focused
pub(crate) focused: bool, pub(crate) focus: FocusState<()>,
/// Whether this widget is entered
pub(crate) entered: bool,
} }
impl Default for PhrasesModel { impl Default for PhrasesModel {
@ -190,8 +169,7 @@ impl Default for PhrasesModel {
phrase: 0.into(), phrase: 0.into(),
scroll: 0, scroll: 0,
mode: None, mode: None,
focused: false, focus: FocusState::Exited(()),
entered: false,
} }
} }
} }
@ -264,7 +242,7 @@ impl ArrangerTracksApi<ArrangerTrack> for ArrangerTui {
width: name.len() + 2, width: name.len() + 2,
name: Arc::new(name.into()), name: Arc::new(name.into()),
color: color.unwrap_or_else(||ItemColor::random()), color: color.unwrap_or_else(||ItemColor::random()),
player: PhrasePlayerModel::default(), player: PhrasePlayerModel::from(&self.transport.clock),
}; };
self.tracks_mut().push(track); self.tracks_mut().push(track);
let index = self.tracks().len() - 1; let index = self.tracks().len() - 1;
@ -353,16 +331,3 @@ impl PhraseLength {
format!("{:>02}", self.ticks()) format!("{:>02}", self.ticks())
} }
} }
impl PhrasesModel {
pub fn new (phrases: Vec<Arc<RwLock<Phrase>>>) -> Self {
Self {
scroll: 0,
phrase: 0.into(),
mode: None,
focused: false,
entered: false,
phrases,
}
}
}

View file

@ -22,10 +22,30 @@ pub trait TransportViewState: ClockApi + Send + Sync {
self.current().usec.format_msu() self.current().usec.format_msu()
} }
} }
macro_rules! impl_transport_view_state {
($Struct:ident :: $field:ident) => {
impl TransportViewState for $Struct {
fn transport_selected (&self) -> TransportFocus {
self.$field.focus.inner()
}
fn transport_focused (&self) -> bool {
true
}
}
}
}
impl_transport_view_state!(TransportTui::state);
impl_transport_view_state!(SequencerTui::transport);
impl_transport_view_state!(ArrangerTui::transport);
pub trait ArrangerViewState { pub trait ArrangerViewState {
fn arranger_focused (&self) -> bool; fn arranger_focused (&self) -> bool;
} }
impl ArrangerViewState for ArrangerTui {
fn arranger_focused (&self) -> bool {
self.focused() == ArrangerFocus::Arranger
}
}
pub trait PhrasesViewState: Send + Sync { pub trait PhrasesViewState: Send + Sync {
fn phrases_focused (&self) -> bool; fn phrases_focused (&self) -> bool;
@ -34,10 +54,34 @@ pub trait PhrasesViewState: Send + Sync {
fn phrase_index (&self) -> usize; fn phrase_index (&self) -> usize;
fn phrase_mode (&self) -> &Option<PhrasesMode>; fn phrase_mode (&self) -> &Option<PhrasesMode>;
} }
macro_rules! impl_phrases_view_state {
($Struct:ident $(:: $field:ident)*) => {
impl PhrasesViewState for $Struct {
fn phrases_focused (&self) -> bool {
todo!()
}
fn phrases_entered (&self) -> bool {
todo!()
}
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
todo!()
}
fn phrase_index (&self) -> usize {
todo!()
}
fn phrase_mode (&self) -> &Option<PhrasesMode> {
&self$(.$field)*.mode
}
}
}
}
impl_phrases_view_state!(PhrasesModel);
impl_phrases_view_state!(SequencerTui::phrases);
impl_phrases_view_state!(ArrangerTui::phrases);
pub trait PhraseViewState: Send + Sync { pub trait PhraseViewState: Send + Sync {
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>>; fn phrase_editing (&self) -> &Option<Arc<RwLock<Phrase>>>;
fn phrase_focused (&self) -> bool; fn phrase_editor_focused (&self) -> bool;
fn phrase_editor_size (&self) -> &Measure<Tui>; fn phrase_editor_size (&self) -> &Measure<Tui>;
fn phrase_editor_entered (&self) -> bool; fn phrase_editor_entered (&self) -> bool;
fn keys (&self) -> &Buffer; fn keys (&self) -> &Buffer;
@ -48,201 +92,48 @@ pub trait PhraseViewState: Send + Sync {
fn now (&self) -> &Arc<Pulse>; fn now (&self) -> &Arc<Pulse>;
fn size (&self) -> &Measure<Tui>; fn size (&self) -> &Measure<Tui>;
} }
macro_rules! impl_phrase_view_state {
impl TransportViewState for TransportTui { ($Struct:ident $(:: $field:ident)*) => {
fn transport_selected (&self) -> TransportFocus { impl PhraseViewState for $Struct {
self.state.focus fn phrase_editing (&self) -> &Option<Arc<RwLock<Phrase>>> {
} &self$(.$field)*.phrase
fn transport_focused (&self) -> bool { }
true fn phrase_editor_focused (&self) -> bool {
} self$(.$field)*.focus.is_focused()
} }
fn phrase_editor_size (&self) -> &Measure<Tui> {
impl TransportViewState for SequencerTui { todo!()
fn transport_selected (&self) -> TransportFocus { }
self.transport.focus fn phrase_editor_entered (&self) -> bool {
} self$(.$field)*.focus.is_entered()
fn transport_focused (&self) -> bool { }
self.focused() == SequencerFocus::Transport fn keys (&self) -> &Buffer {
} &self$(.$field)*.keys
} }
fn buffer (&self) -> &BigBuffer {
impl TransportViewState for ArrangerTui { &self$(.$field)*.buffer
fn transport_selected (&self) -> TransportFocus { }
self.transport.focus fn note_len (&self) -> usize {
} self$(.$field)*.note_len
fn transport_focused (&self) -> bool { }
self.focused() == ArrangerFocus::Transport fn note_axis (&self) -> &RwLock<FixedAxis<usize>> {
} &self$(.$field)*.note_axis
} }
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>> {
impl ArrangerViewState for ArrangerTui { &self$(.$field)*.time_axis
fn arranger_focused (&self) -> bool { }
self.focused() == ArrangerFocus::Arranger fn now (&self) -> &Arc<Pulse> {
} &self$(.$field)*.now
} }
fn size (&self) -> &Measure<Tui> {
impl PhrasesViewState for PhrasesModel { &self$(.$field)*.size
fn phrases_focused (&self) -> bool { }
todo!() }
}
fn phrases_entered (&self) -> bool {
todo!()
}
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
todo!()
}
fn phrase_index (&self) -> usize {
todo!()
}
fn phrase_mode (&self) -> &Option<PhrasesMode> {
&self.mode
}
}
impl PhrasesViewState for SequencerTui {
fn phrases_focused (&self) -> bool {
todo!()
}
fn phrases_entered (&self) -> bool {
todo!()
}
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
todo!()
}
fn phrase_index (&self) -> usize {
todo!()
}
fn phrase_mode (&self) -> &Option<PhrasesMode> {
&self.phrases.mode
}
}
impl PhrasesViewState for ArrangerTui {
fn phrases_focused (&self) -> bool {
todo!()
}
fn phrases_entered (&self) -> bool {
todo!()
}
fn phrases (&self) -> Vec<Arc<RwLock<Phrase>>> {
todo!()
}
fn phrase_index (&self) -> usize {
todo!()
}
fn phrase_mode (&self) -> &Option<PhrasesMode> {
&self.phrases.mode
}
}
impl PhraseViewState for PhraseEditorModel {
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
&self.phrase
}
fn phrase_focused (&self) -> bool {
self.focused
}
fn phrase_editor_size (&self) -> &Measure<Tui> {
todo!()
}
fn phrase_editor_entered (&self) -> bool {
self.entered
}
fn keys (&self) -> &Buffer {
&self.keys
}
fn buffer (&self) -> &BigBuffer {
&self.buffer
}
fn note_len (&self) -> usize {
self.note_len
}
fn note_axis (&self) -> &RwLock<FixedAxis<usize>> {
&self.note_axis
}
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>> {
&self.time_axis
}
fn now (&self) -> &Arc<Pulse> {
&self.now
}
fn size (&self) -> &Measure<Tui> {
&self.size
}
}
impl PhraseViewState for SequencerTui {
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
todo!()
}
fn phrase_focused (&self) -> bool {
todo!()
}
fn phrase_editor_size (&self) -> &Measure<Tui> {
todo!()
}
fn phrase_editor_entered (&self) -> bool {
todo!()
}
fn keys (&self) -> &Buffer {
todo!()
}
fn buffer (&self) -> &BigBuffer {
todo!()
}
fn note_len (&self) -> usize {
todo!()
}
fn note_axis (&self) -> &RwLock<FixedAxis<usize>> {
todo!()
}
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>> {
todo!()
}
fn now (&self) -> &Arc<Pulse> {
todo!()
}
fn size (&self) -> &Measure<Tui> {
&self.size
}
}
impl PhraseViewState for ArrangerTui {
fn phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
todo!()
}
fn phrase_focused (&self) -> bool {
todo!()
}
fn phrase_editor_size (&self) -> &Measure<Tui> {
todo!()
}
fn phrase_editor_entered (&self) -> bool {
todo!()
}
fn keys (&self) -> &Buffer {
todo!()
}
fn buffer (&self) -> &BigBuffer {
todo!()
}
fn note_len (&self) -> usize {
todo!()
}
fn note_axis (&self) -> &RwLock<FixedAxis<usize>> {
todo!()
}
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>> {
todo!()
}
fn now (&self) -> &Arc<Pulse> {
todo!()
}
fn size (&self) -> &Measure<Tui> {
&self.size
} }
} }
impl_phrase_view_state!(PhraseEditorModel);
impl_phrase_view_state!(SequencerTui::editor);
impl_phrase_view_state!(ArrangerTui::editor);
fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> { fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> {
let mut widths = vec![]; let mut widths = vec![];