mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
wip(p63,e22)
This commit is contained in:
parent
5673dd7e8a
commit
f49823b7a7
5 changed files with 158 additions and 194 deletions
|
|
@ -47,4 +47,6 @@ pub struct ArrangerTui {
|
||||||
pub(crate) note_buf: Vec<u8>,
|
pub(crate) note_buf: Vec<u8>,
|
||||||
/// MIDI output buffer
|
/// MIDI output buffer
|
||||||
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
||||||
|
/// MIDI editor state
|
||||||
|
pub(crate) editor: PhraseEditorModel,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ impl TransportControl for ArrangerTui {
|
||||||
|
|
||||||
pub trait SequencerControl: TransportControl {}
|
pub trait SequencerControl: TransportControl {}
|
||||||
|
|
||||||
|
impl SequencerControl for SequencerTui {}
|
||||||
|
|
||||||
pub trait ArrangerControl: TransportControl {
|
pub trait ArrangerControl: TransportControl {
|
||||||
fn selected (&self) -> ArrangerSelection;
|
fn selected (&self) -> ArrangerSelection;
|
||||||
fn selected_mut (&mut self) -> &mut ArrangerSelection;
|
fn selected_mut (&mut self) -> &mut ArrangerSelection;
|
||||||
|
|
@ -33,6 +35,59 @@ pub trait ArrangerControl: TransportControl {
|
||||||
fn randomize_color (&mut self);
|
fn randomize_color (&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ArrangerControl for ArrangerTui {
|
||||||
|
fn selected (&self) -> ArrangerSelection {
|
||||||
|
self.selected
|
||||||
|
}
|
||||||
|
fn selected_mut (&mut self) -> &mut ArrangerSelection {
|
||||||
|
&mut self.selected
|
||||||
|
}
|
||||||
|
fn activate (&mut self) {
|
||||||
|
if let ArrangerSelection::Scene(s) = self.selected {
|
||||||
|
for (t, track) in self.tracks().iter().enumerate() {
|
||||||
|
let phrase = self.scenes()[s].clips[t].clone();
|
||||||
|
if track.player.play_phrase.is_some() || phrase.is_some() {
|
||||||
|
track.enqueue_next(phrase.as_ref());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO make transport available here, so that
|
||||||
|
// activating a scene when stopped starts playback
|
||||||
|
//if self.is_stopped() {
|
||||||
|
//self.transport.toggle_play()
|
||||||
|
//}
|
||||||
|
} else if let ArrangerSelection::Clip(t, s) = self.selected {
|
||||||
|
let phrase = self.scenes()[s].clips[t].clone();
|
||||||
|
self.tracks_mut()[t].enqueue_next(phrase.as_ref());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
fn selected_phrase (&self) -> Option<Arc<RwLock<Phrase>>> {
|
||||||
|
self.selected_scene()?.clips.get(self.selected.track()?)?.clone()
|
||||||
|
}
|
||||||
|
fn toggle_loop (&mut self) {
|
||||||
|
if let Some(phrase) = self.selected_phrase() {
|
||||||
|
phrase.write().unwrap().toggle_loop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn randomize_color (&mut self) {
|
||||||
|
match self.selected {
|
||||||
|
ArrangerSelection::Mix => {
|
||||||
|
self.color = ItemColor::random_dark()
|
||||||
|
},
|
||||||
|
ArrangerSelection::Track(t) => {
|
||||||
|
self.tracks_mut()[t].color = ItemColor::random()
|
||||||
|
},
|
||||||
|
ArrangerSelection::Scene(s) => {
|
||||||
|
self.scenes_mut()[s].color = ItemColor::random()
|
||||||
|
},
|
||||||
|
ArrangerSelection::Clip(t, s) => {
|
||||||
|
if let Some(phrase) = &self.scenes_mut()[s].clips[t] {
|
||||||
|
phrase.write().unwrap().color = ItemColorTriplet::random();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait PhrasesControl: HasPhrases {
|
pub trait PhrasesControl: HasPhrases {
|
||||||
fn phrase_index (&self) -> usize;
|
fn phrase_index (&self) -> usize;
|
||||||
fn set_phrase_index (&self, index: usize);
|
fn set_phrase_index (&self, index: usize);
|
||||||
|
|
@ -86,145 +141,3 @@ pub trait PhraseEditorControl: HasFocus {
|
||||||
self.time_axis().write().unwrap().point = point.map(forward);
|
self.time_axis().write().unwrap().point = point.map(forward);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SequencerControl for SequencerTui {}
|
|
||||||
|
|
||||||
impl ArrangerControl for ArrangerTui {
|
|
||||||
fn selected (&self) -> ArrangerSelection {
|
|
||||||
self.selected
|
|
||||||
}
|
|
||||||
fn selected_mut (&mut self) -> &mut ArrangerSelection {
|
|
||||||
&mut self.selected
|
|
||||||
}
|
|
||||||
fn activate (&mut self) {
|
|
||||||
if let ArrangerSelection::Scene(s) = self.selected {
|
|
||||||
for (t, track) in self.tracks_mut().iter_mut().enumerate() {
|
|
||||||
let clip = self.scenes()[s].clips[t].as_ref();
|
|
||||||
if track.player.play_phrase.is_some() || clip.is_some() {
|
|
||||||
track.enqueue_next(clip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO make transport available here, so that
|
|
||||||
// activating a scene when stopped starts playback
|
|
||||||
//if self.is_stopped() {
|
|
||||||
//self.transport.toggle_play()
|
|
||||||
//}
|
|
||||||
} else if let ArrangerSelection::Clip(t, s) = self.selected {
|
|
||||||
self.tracks_mut()[t].enqueue_next(self.scenes()[s].clips[t].as_ref());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
fn selected_phrase (&self) -> Option<Arc<RwLock<Phrase>>> {
|
|
||||||
self.selected_scene()?.clips.get(self.selected.track()?)?.clone()
|
|
||||||
}
|
|
||||||
fn toggle_loop (&mut self) {
|
|
||||||
if let Some(phrase) = self.selected_phrase() {
|
|
||||||
phrase.write().unwrap().toggle_loop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn randomize_color (&mut self) {
|
|
||||||
match self.selected {
|
|
||||||
ArrangerSelection::Mix => {
|
|
||||||
self.color = ItemColor::random_dark()
|
|
||||||
},
|
|
||||||
ArrangerSelection::Track(t) => {
|
|
||||||
self.tracks_mut()[t].color = ItemColor::random()
|
|
||||||
},
|
|
||||||
ArrangerSelection::Scene(s) => {
|
|
||||||
self.scenes_mut()[s].color = ItemColor::random()
|
|
||||||
},
|
|
||||||
ArrangerSelection::Clip(t, s) => {
|
|
||||||
if let Some(phrase) = &self.scenes_mut()[s].clips[t] {
|
|
||||||
phrase.write().unwrap().color = ItemColorTriplet::random();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhrasesControl for SequencerTui {
|
|
||||||
fn phrase_index (&self) -> usize {
|
|
||||||
self.phrases.phrase.load(Ordering::Relaxed)
|
|
||||||
}
|
|
||||||
fn set_phrase_index (&self, value: usize) {
|
|
||||||
self.phrases.phrase.store(value, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
fn phrases_mode (&self) -> &Option<PhrasesMode> {
|
|
||||||
&self.phrases.mode
|
|
||||||
}
|
|
||||||
fn phrases_mode_mut (&mut self) -> &mut Option<PhrasesMode> {
|
|
||||||
&mut self.phrases.mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhrasesControl for ArrangerTui {
|
|
||||||
fn phrase_index (&self) -> usize {
|
|
||||||
self.phrases.phrase.load(Ordering::Relaxed)
|
|
||||||
}
|
|
||||||
fn set_phrase_index (&self, value: usize) {
|
|
||||||
self.phrases.phrase.store(value, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
fn phrases_mode (&self) -> &Option<PhrasesMode> {
|
|
||||||
&self.phrases.mode
|
|
||||||
}
|
|
||||||
fn phrases_mode_mut (&mut self) -> &mut Option<PhrasesMode> {
|
|
||||||
&mut self.phrases.mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhraseEditorControl for SequencerTui {
|
|
||||||
fn edit_phrase (&self, phrase: &Option<Arc<RwLock<Phrase>>>) {
|
|
||||||
//self.editor.show(self.selected_phrase().as_ref());
|
|
||||||
//state.editor.phrase = phrase.clone();
|
|
||||||
//state.focus(ArrangerFocus::PhraseEditor);
|
|
||||||
//state.focus_enter();
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn editing_phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn phrase_editor_entered (&self) -> bool {
|
|
||||||
self.entered && self.focused() == SequencerFocus::PhraseEditor
|
|
||||||
}
|
|
||||||
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn note_axis (&self) -> &RwLock<FixedAxis<usize>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn note_len (&self) -> usize {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn note_len_mut (&mut self) -> &mut usize {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn put_note (&mut self) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhraseEditorControl for ArrangerTui {
|
|
||||||
fn edit_phrase (&self, phrase: &Option<Arc<RwLock<Phrase>>>) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn editing_phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn phrase_editor_entered (&self) -> bool {
|
|
||||||
self.entered && self.focused() == ArrangerFocus::PhraseEditor
|
|
||||||
}
|
|
||||||
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn note_axis (&self) -> &RwLock<FixedAxis<usize>> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn note_len (&self) -> usize {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn note_len_mut (&mut self) -> &mut usize {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
fn put_note (&mut self) {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -49,16 +49,16 @@ macro_rules! impl_has_phrases {
|
||||||
($Struct:ident $(:: $field:ident)*) => {
|
($Struct:ident $(:: $field:ident)*) => {
|
||||||
impl HasPhrases for $Struct {
|
impl HasPhrases for $Struct {
|
||||||
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
||||||
&self$(.$field)*
|
&self$(.$field)*.phrases
|
||||||
}
|
}
|
||||||
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
||||||
&mut self$(.$field)*
|
&mut self$(.$field)*.phrases
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_has_phrase {
|
macro_rules! impl_midi_player {
|
||||||
($Struct:ident $(:: $field:ident)*) => {
|
($Struct:ident $(:: $field:ident)*) => {
|
||||||
impl HasPhrase for $Struct {
|
impl HasPhrase for $Struct {
|
||||||
fn reset (&self) -> bool {
|
fn reset (&self) -> bool {
|
||||||
|
|
@ -80,11 +80,6 @@ macro_rules! impl_has_phrase {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_midi_player {
|
|
||||||
($Struct:ident $(:: $field:ident)*) => {
|
|
||||||
impl MidiInputApi for $Struct {
|
impl MidiInputApi for $Struct {
|
||||||
fn midi_ins(&self) -> &Vec<Port<jack::MidiIn>> {
|
fn midi_ins(&self) -> &Vec<Port<jack::MidiIn>> {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
@ -132,6 +127,60 @@ macro_rules! impl_midi_player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_phrases_control {
|
||||||
|
($Struct:ident $(:: $field:ident)*) => {
|
||||||
|
impl PhrasesControl for $Struct {
|
||||||
|
fn phrase_index (&self) -> usize {
|
||||||
|
self.phrases.phrase.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
fn set_phrase_index (&self, value: usize) {
|
||||||
|
self.phrases.phrase.store(value, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
fn phrases_mode (&self) -> &Option<PhrasesMode> {
|
||||||
|
&self.phrases.mode
|
||||||
|
}
|
||||||
|
fn phrases_mode_mut (&mut self) -> &mut Option<PhrasesMode> {
|
||||||
|
&mut self.phrases.mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_phrase_editor_control {
|
||||||
|
($Struct:ident $(:: $field:ident)* [$Focus:expr]) => {
|
||||||
|
impl PhraseEditorControl for $Struct {
|
||||||
|
fn edit_phrase (&self, phrase: &Option<Arc<RwLock<Phrase>>>) {
|
||||||
|
//self.editor.show(self.selected_phrase().as_ref());
|
||||||
|
//state.editor.phrase = phrase.clone();
|
||||||
|
//state.focus(ArrangerFocus::PhraseEditor);
|
||||||
|
//state.focus_enter();
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn editing_phrase (&self) -> &Option<Arc<RwLock<Phrase>>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn phrase_editor_entered (&self) -> bool {
|
||||||
|
self.entered && self.focused() == $Focus
|
||||||
|
}
|
||||||
|
fn time_axis (&self) -> &RwLock<ScaledAxis<usize>> {
|
||||||
|
&self.editor.time_axis
|
||||||
|
}
|
||||||
|
fn note_axis (&self) -> &RwLock<FixedAxis<usize>> {
|
||||||
|
&self.editor.note_axis
|
||||||
|
}
|
||||||
|
fn note_len (&self) -> usize {
|
||||||
|
self.editor.note_len
|
||||||
|
}
|
||||||
|
fn note_len_mut (&mut self) -> &mut usize {
|
||||||
|
&mut self.editor.note_len
|
||||||
|
}
|
||||||
|
fn put_note (&mut self) {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -148,45 +197,10 @@ impl_playhead_api!(ArrangerTrack);
|
||||||
impl_has_phrases!(PhrasesModel::phrases);
|
impl_has_phrases!(PhrasesModel::phrases);
|
||||||
impl_has_phrases!(SequencerTui::phrases);
|
impl_has_phrases!(SequencerTui::phrases);
|
||||||
impl_has_phrases!(ArrangerTui::phrases);
|
impl_has_phrases!(ArrangerTui::phrases);
|
||||||
impl_has_phrase!(SequencerTui::player);
|
impl_midi_player!(SequencerTui::player);
|
||||||
impl_has_phrase!(ArrangerTrack::player);
|
impl_midi_player!(ArrangerTrack::player);
|
||||||
impl_has_phrase!(PhrasePlayerModel);
|
|
||||||
impl_midi_player!(ArrangerTrack);
|
|
||||||
impl_midi_player!(PhrasePlayerModel);
|
impl_midi_player!(PhrasePlayerModel);
|
||||||
|
impl_phrases_control!(SequencerTui);
|
||||||
impl HasScenes<ArrangerScene> for ArrangerTui {
|
impl_phrases_control!(ArrangerTui);
|
||||||
fn scenes (&self) -> &Vec<ArrangerScene> {
|
impl_phrase_editor_control!(SequencerTui [SequencerFocus::PhraseEditor]);
|
||||||
&self.scenes
|
impl_phrase_editor_control!(ArrangerTui [ArrangerFocus::PhraseEditor]);
|
||||||
}
|
|
||||||
fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> {
|
|
||||||
&mut self.scenes
|
|
||||||
}
|
|
||||||
fn scene_add (&mut self, name: Option<&str>, color: Option<ItemColor>)
|
|
||||||
-> Usually<&mut ArrangerScene>
|
|
||||||
{
|
|
||||||
let name = name.map_or_else(||self.scene_default_name(), |x|x.to_string());
|
|
||||||
let scene = ArrangerScene {
|
|
||||||
name: Arc::new(name.into()),
|
|
||||||
clips: vec![None;self.tracks().len()],
|
|
||||||
color: color.unwrap_or_else(||ItemColor::random()),
|
|
||||||
};
|
|
||||||
self.scenes_mut().push(scene);
|
|
||||||
let index = self.scenes().len() - 1;
|
|
||||||
Ok(&mut self.scenes_mut()[index])
|
|
||||||
}
|
|
||||||
fn selected_scene (&self) -> Option<&ArrangerScene> {
|
|
||||||
self.selected.scene().map(|s|self.scenes().get(s)).flatten()
|
|
||||||
}
|
|
||||||
fn selected_scene_mut (&mut self) -> Option<&mut ArrangerScene> {
|
|
||||||
self.selected.scene().map(|s|self.scenes_mut().get_mut(s)).flatten()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HasTracks<ArrangerTrack> for ArrangerTui {
|
|
||||||
fn tracks (&self) -> &Vec<ArrangerTrack> {
|
|
||||||
&self.tracks
|
|
||||||
}
|
|
||||||
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
|
|
||||||
&mut self.tracks
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
|
||||||
jack: jack.clone(),
|
jack: jack.clone(),
|
||||||
transport: TransportModel::from(jack.read().unwrap().transport()),
|
transport: TransportModel::from(jack.read().unwrap().transport()),
|
||||||
phrases: PhrasesModel::default(),
|
phrases: PhrasesModel::default(),
|
||||||
|
editor: PhraseEditorModel::default(),
|
||||||
selected: ArrangerSelection::Clip(0, 0),
|
selected: ArrangerSelection::Clip(0, 0),
|
||||||
scenes: vec![],
|
scenes: vec![],
|
||||||
tracks: vec![],
|
tracks: vec![],
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,34 @@ impl Default for PhrasesModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasScenes<ArrangerScene> for ArrangerTui {
|
||||||
|
fn scenes (&self) -> &Vec<ArrangerScene> {
|
||||||
|
&self.scenes
|
||||||
|
}
|
||||||
|
fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> {
|
||||||
|
&mut self.scenes
|
||||||
|
}
|
||||||
|
fn scene_add (&mut self, name: Option<&str>, color: Option<ItemColor>)
|
||||||
|
-> Usually<&mut ArrangerScene>
|
||||||
|
{
|
||||||
|
let name = name.map_or_else(||self.scene_default_name(), |x|x.to_string());
|
||||||
|
let scene = ArrangerScene {
|
||||||
|
name: Arc::new(name.into()),
|
||||||
|
clips: vec![None;self.tracks().len()],
|
||||||
|
color: color.unwrap_or_else(||ItemColor::random()),
|
||||||
|
};
|
||||||
|
self.scenes_mut().push(scene);
|
||||||
|
let index = self.scenes().len() - 1;
|
||||||
|
Ok(&mut self.scenes_mut()[index])
|
||||||
|
}
|
||||||
|
fn selected_scene (&self) -> Option<&ArrangerScene> {
|
||||||
|
self.selected.scene().map(|s|self.scenes().get(s)).flatten()
|
||||||
|
}
|
||||||
|
fn selected_scene_mut (&mut self) -> Option<&mut ArrangerScene> {
|
||||||
|
self.selected.scene().map(|s|self.scenes_mut().get_mut(s)).flatten()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct ArrangerScene {
|
pub struct ArrangerScene {
|
||||||
/// Name of scene
|
/// Name of scene
|
||||||
|
|
@ -189,6 +217,15 @@ impl ArrangerSceneApi for ArrangerScene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasTracks<ArrangerTrack> for ArrangerTui {
|
||||||
|
fn tracks (&self) -> &Vec<ArrangerTrack> {
|
||||||
|
&self.tracks
|
||||||
|
}
|
||||||
|
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
|
||||||
|
&mut self.tracks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ArrangerTracksApi<ArrangerTrack> for ArrangerTui {
|
impl ArrangerTracksApi<ArrangerTrack> for ArrangerTui {
|
||||||
fn track_add (&mut self, name: Option<&str>, color: Option<ItemColor>)
|
fn track_add (&mut self, name: Option<&str>, color: Option<ItemColor>)
|
||||||
-> Usually<&mut ArrangerTrack>
|
-> Usually<&mut ArrangerTrack>
|
||||||
|
|
@ -199,7 +236,6 @@ impl ArrangerTracksApi<ArrangerTrack> for ArrangerTui {
|
||||||
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::default(),
|
||||||
editor: PhraseEditorModel::default(),
|
|
||||||
};
|
};
|
||||||
self.tracks_mut().push(track);
|
self.tracks_mut().push(track);
|
||||||
let index = self.tracks().len() - 1;
|
let index = self.tracks().len() - 1;
|
||||||
|
|
@ -223,8 +259,6 @@ pub struct ArrangerTrack {
|
||||||
pub(crate) color: ItemColor,
|
pub(crate) color: ItemColor,
|
||||||
/// MIDI player state
|
/// MIDI player state
|
||||||
pub(crate) player: PhrasePlayerModel,
|
pub(crate) player: PhrasePlayerModel,
|
||||||
/// MIDI editor state
|
|
||||||
pub(crate) editor: PhraseEditorModel,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArrangerTrackApi for ArrangerTrack {
|
impl ArrangerTrackApi for ArrangerTrack {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue