mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 20:26:42 +01:00
fix warnings
This commit is contained in:
parent
eccb355815
commit
4994e218f7
6 changed files with 57 additions and 49 deletions
|
|
@ -17,7 +17,16 @@ pub struct Arranger<E: Engine> {
|
||||||
}
|
}
|
||||||
/// Sections in the arranger app that may be focused
|
/// Sections in the arranger app that may be focused
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum ArrangerFocus { Transport, Arrangement, PhrasePool, PhraseEditor }
|
pub enum ArrangerFocus {
|
||||||
|
/// The transport (toolbar) is focused
|
||||||
|
Transport,
|
||||||
|
/// The arrangement (grid) is focused
|
||||||
|
Arrangement,
|
||||||
|
/// The phrase list (pool) is focused
|
||||||
|
PhrasePool,
|
||||||
|
/// The phrase editor (sequencer) is focused
|
||||||
|
PhraseEditor,
|
||||||
|
}
|
||||||
/// Represents the tracks and scenes of the composition.
|
/// Represents the tracks and scenes of the composition.
|
||||||
pub struct Arrangement<E: Engine> {
|
pub struct Arrangement<E: Engine> {
|
||||||
/// Name of arranger
|
/// Name of arranger
|
||||||
|
|
@ -76,7 +85,9 @@ pub enum ArrangementFocus {
|
||||||
/// Display mode of arranger
|
/// Display mode of arranger
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub enum ArrangementViewMode {
|
pub enum ArrangementViewMode {
|
||||||
|
/// Tracks are rows
|
||||||
Horizontal,
|
Horizontal,
|
||||||
|
/// Tracks are columns
|
||||||
Vertical(usize),
|
Vertical(usize),
|
||||||
}
|
}
|
||||||
/// Arrangement, rendered vertically (session/grid mode).
|
/// Arrangement, rendered vertically (session/grid mode).
|
||||||
|
|
@ -88,10 +99,7 @@ pub struct HorizontalArranger<'a, E: Engine>(
|
||||||
pub &'a Arrangement<E>
|
pub &'a Arrangement<E>
|
||||||
);
|
);
|
||||||
impl<E: Engine> Arranger<E> {
|
impl<E: Engine> Arranger<E> {
|
||||||
pub fn edit_phrase (&mut self) {
|
/// Toggle global play/pause
|
||||||
self.editor.phrase = self.arrangement.phrase().clone();
|
|
||||||
self.focus(ArrangerFocus::PhraseEditor);
|
|
||||||
}
|
|
||||||
pub fn toggle_play (&mut self) -> Perhaps<bool> {
|
pub fn toggle_play (&mut self) -> Perhaps<bool> {
|
||||||
match self.transport {
|
match self.transport {
|
||||||
Some(ref mut transport) => { transport.write().unwrap().toggle_play()?; },
|
Some(ref mut transport) => { transport.write().unwrap().toggle_play()?; },
|
||||||
|
|
@ -99,22 +107,26 @@ impl<E: Engine> Arranger<E> {
|
||||||
}
|
}
|
||||||
Ok(Some(true))
|
Ok(Some(true))
|
||||||
}
|
}
|
||||||
|
/// Focus the editor with the current phrase
|
||||||
|
pub fn edit_phrase (&mut self) {
|
||||||
|
self.editor.phrase = self.arrangement.phrase().clone();
|
||||||
|
self.focus(ArrangerFocus::PhraseEditor);
|
||||||
|
}
|
||||||
|
/// Rename the selected track, scene, or clip
|
||||||
pub fn rename_selected (&mut self) {
|
pub fn rename_selected (&mut self) {
|
||||||
let Self { phrases, arrangement, .. } = self;
|
let Arrangement { selected, ref scenes, .. } = self.arrangement;
|
||||||
let Arrangement { selected, ref name, ref tracks, ref scenes, .. } = arrangement;
|
|
||||||
match selected {
|
match selected {
|
||||||
ArrangementFocus::Track(t) => { todo!("rename track"); },
|
ArrangementFocus::Mix => {},
|
||||||
ArrangementFocus::Scene(s) => { todo!("rename scene"); },
|
ArrangementFocus::Track(_) => { todo!("rename track"); },
|
||||||
ArrangementFocus::Clip(t, s) =>
|
ArrangementFocus::Scene(_) => { todo!("rename scene"); },
|
||||||
if let Some(ref phrase) = scenes[*s].clips[*t] {
|
ArrangementFocus::Clip(t, s) => if let Some(ref phrase) = scenes[s].clips[t] {
|
||||||
let index = self.phrases.read().unwrap().index_of(&*phrase.read().unwrap());
|
let index = self.phrases.read().unwrap().index_of(&*phrase.read().unwrap());
|
||||||
if let Some(index) = index {
|
if let Some(index) = index {
|
||||||
self.focus(ArrangerFocus::PhrasePool);
|
self.focus(ArrangerFocus::PhrasePool);
|
||||||
self.phrases.write().unwrap().phrase = index;
|
self.phrases.write().unwrap().phrase = index;
|
||||||
self.phrases.write().unwrap().begin_rename();
|
self.phrases.write().unwrap().begin_rename();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -172,27 +184,27 @@ impl<E: Engine> Arrangement<E> {
|
||||||
}
|
}
|
||||||
pub fn delete (&mut self) {
|
pub fn delete (&mut self) {
|
||||||
match self.selected {
|
match self.selected {
|
||||||
ArrangementFocus::Track(t) => self.track_del(),
|
ArrangementFocus::Track(_) => self.track_del(),
|
||||||
ArrangementFocus::Scene(s) => self.scene_del(),
|
ArrangementFocus::Scene(_) => self.scene_del(),
|
||||||
ArrangementFocus::Clip(t, s) => self.phrase_del(),
|
ArrangementFocus::Clip(_, _) => self.phrase_del(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.show_phrase()
|
self.show_phrase()
|
||||||
}
|
}
|
||||||
pub fn increment (&mut self) {
|
pub fn increment (&mut self) {
|
||||||
match self.selected {
|
match self.selected {
|
||||||
ArrangementFocus::Track(t) => self.track_width_inc(),
|
ArrangementFocus::Track(_) => self.track_width_inc(),
|
||||||
ArrangementFocus::Scene(s) => self.scene_next(),
|
ArrangementFocus::Scene(_) => self.scene_next(),
|
||||||
ArrangementFocus::Clip(t, s) => self.phrase_next(),
|
ArrangementFocus::Clip(_, _) => self.phrase_next(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.show_phrase()
|
self.show_phrase()
|
||||||
}
|
}
|
||||||
pub fn decrement (&mut self) {
|
pub fn decrement (&mut self) {
|
||||||
match self.selected {
|
match self.selected {
|
||||||
ArrangementFocus::Track(t) => self.track_width_dec(),
|
ArrangementFocus::Track(_) => self.track_width_dec(),
|
||||||
ArrangementFocus::Scene(s) => self.scene_prev(),
|
ArrangementFocus::Scene(_) => self.scene_prev(),
|
||||||
ArrangementFocus::Clip(t, s) => self.phrase_prev(),
|
ArrangementFocus::Clip(_, _) => self.phrase_prev(),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
self.show_phrase()
|
self.show_phrase()
|
||||||
|
|
@ -492,7 +504,7 @@ impl ArrangementFocus {
|
||||||
} else {
|
} else {
|
||||||
format!("S??")
|
format!("S??")
|
||||||
},
|
},
|
||||||
Self::Clip(t, s) => if let (Some(track), Some(scene)) = (
|
Self::Clip(t, s) => if let (Some(_), Some(scene)) = (
|
||||||
tracks.get(*t),
|
tracks.get(*t),
|
||||||
scenes.get(*s),
|
scenes.get(*s),
|
||||||
) {
|
) {
|
||||||
|
|
@ -607,7 +619,7 @@ impl Scene {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Returns the pulse length of the longest phrase in the scene
|
/// Returns the pulse length of the longest phrase in the scene
|
||||||
pub fn pulses <E: Engine> (&self, tracks: &[ArrangementTrack<E>]) -> usize {
|
pub fn pulses (&self) -> usize {
|
||||||
self.clips.iter().fold(0, |a, p|a.max(p.as_ref().map(|q|q.read().unwrap().length).unwrap_or(0)))
|
self.clips.iter().fold(0, |a, p|a.max(p.as_ref().map(|q|q.read().unwrap().length).unwrap_or(0)))
|
||||||
}
|
}
|
||||||
/// Returns true if all phrases in the scene are currently playing
|
/// Returns true if all phrases in the scene are currently playing
|
||||||
|
|
@ -624,10 +636,10 @@ impl Scene {
|
||||||
None => true
|
None => true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn ppqs <E: Engine> (tracks: &[ArrangementTrack<E>], scenes: &[Self]) -> Vec<(usize, usize)> {
|
pub fn ppqs (scenes: &[Self]) -> Vec<(usize, usize)> {
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
let mut scenes: Vec<(usize, usize)> = scenes.iter().map(|scene|{
|
let mut scenes: Vec<(usize, usize)> = scenes.iter().map(|scene|{
|
||||||
let pulses = scene.pulses(tracks).max(PPQ);
|
let pulses = scene.pulses().max(PPQ);
|
||||||
total = total + pulses;
|
total = total + pulses;
|
||||||
(pulses, total - pulses)
|
(pulses, total - pulses)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ impl Handle<Tui> for Arranger<Tui> {
|
||||||
key!(KeyCode::Left) => { self.focus_left(); },
|
key!(KeyCode::Left) => { self.focus_left(); },
|
||||||
key!(KeyCode::Right) => { self.focus_right(); },
|
key!(KeyCode::Right) => { self.focus_right(); },
|
||||||
key!(KeyCode::Char('e')) => { self.edit_phrase(); },
|
key!(KeyCode::Char('e')) => { self.edit_phrase(); },
|
||||||
key!(KeyCode::Char(' ')) => { self.toggle_play(); },
|
key!(KeyCode::Char(' ')) => { self.toggle_play()?; },
|
||||||
key!(KeyCode::Char('n')) => { self.rename_selected(); },
|
key!(KeyCode::Char('n')) => { self.rename_selected(); },
|
||||||
_ => return Ok(None)
|
_ => return Ok(None)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
let Self(state, factor) = self;
|
let Self(state, factor) = self;
|
||||||
let (cols, rows) = if *factor == 0 {(
|
let (cols, rows) = if *factor == 0 {(
|
||||||
state.track_widths(), Scene::ppqs(state.tracks.as_slice(), state.scenes.as_slice()),
|
state.track_widths(), Scene::ppqs(state.scenes.as_slice()),
|
||||||
)} else {(
|
)} else {(
|
||||||
state.track_widths(),
|
state.track_widths(),
|
||||||
(0..=state.scenes.len()).map(|i|(factor*PPQ, factor*PPQ*i)).collect::<Vec<_>>(),
|
(0..=state.scenes.len()).map(|i|(factor*PPQ, factor*PPQ*i)).collect::<Vec<_>>(),
|
||||||
|
|
@ -77,8 +77,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
|
|
||||||
// row separators
|
// row separators
|
||||||
add(&CustomWidget::new(|_|Ok(Some([0,0])), move|to: &mut TuiOutput|{
|
add(&CustomWidget::new(|_|Ok(Some([0,0])), move|to: &mut TuiOutput|{
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
let style = Some(Style::default().fg(COLOR_SEPARATOR));
|
|
||||||
for y in rows.iter().map(|row|row.1) {
|
for y in rows.iter().map(|row|row.1) {
|
||||||
let y = area.y() + (y / PPQ) as u16 + 1;
|
let y = area.y() + (y / PPQ) as u16 + 1;
|
||||||
if y >= to.buffer.area.height { break }
|
if y >= to.buffer.area.height { break }
|
||||||
|
|
@ -201,7 +200,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
impl<'a> Content for HorizontalArranger<'a, Tui> {
|
impl<'a> Content for HorizontalArranger<'a, Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
let Arrangement { tracks, focused, selected, scenes, .. } = self.0;
|
let Arrangement { tracks, focused, .. } = self.0;
|
||||||
let _tracks = tracks.as_slice();
|
let _tracks = tracks.as_slice();
|
||||||
lay!(
|
lay!(
|
||||||
focused.then_some(Background(Color::Rgb(40, 50, 30))),
|
focused.then_some(Background(Color::Rgb(40, 50, 30))),
|
||||||
|
|
@ -370,7 +369,7 @@ impl<'a> Content for HorizontalArranger<'a, Tui> {
|
||||||
CustomWidget::new(|_|{
|
CustomWidget::new(|_|{
|
||||||
todo!()
|
todo!()
|
||||||
}, |to: &mut TuiOutput|{
|
}, |to: &mut TuiOutput|{
|
||||||
let Arrangement { tracks, scenes, selected, .. } = self.0;
|
let Arrangement { scenes, selected, .. } = self.0;
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
let mut x2 = 0;
|
let mut x2 = 0;
|
||||||
let [x, y, _, height] = area;
|
let [x, y, _, height] = area;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ pub(crate) use tek_core::crossterm::event::KeyCode;
|
||||||
pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage};
|
pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage};
|
||||||
pub(crate) use tek_core::jack::*;
|
pub(crate) use tek_core::jack::*;
|
||||||
pub(crate) use std::sync::{Arc, RwLock};
|
pub(crate) use std::sync::{Arc, RwLock};
|
||||||
pub(crate) use rand::{thread_rng, prelude::*};
|
pub(crate) use rand::thread_rng;
|
||||||
pub(crate) use palette::{*, convert::*, okhsl::*};
|
pub(crate) use palette::{*, convert::*, okhsl::*};
|
||||||
use rand::distributions::uniform::UniformSampler;
|
use rand::distributions::uniform::UniformSampler;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,17 +35,14 @@ impl SequencerCli {
|
||||||
editor: PhraseEditor::new(),
|
editor: PhraseEditor::new(),
|
||||||
phrases: Arc::new(RwLock::new(PhrasePool::new())),
|
phrases: Arc::new(RwLock::new(PhrasePool::new())),
|
||||||
};
|
};
|
||||||
if let Some(name) = self.name.as_ref() {
|
if let Some(_) = self.name.as_ref() {
|
||||||
// TODO
|
// TODO: seq.name = Arc::new(RwLock::new(name.clone()));
|
||||||
//seq.name = Arc::new(RwLock::new(name.clone()));
|
|
||||||
}
|
}
|
||||||
if let Some(ppq) = self.ppq {
|
if let Some(_) = self.ppq {
|
||||||
// TODO
|
// TODO: seq.ppq = ppq;
|
||||||
//seq.ppq = ppq;
|
|
||||||
}
|
}
|
||||||
if let Some(length) = self.length {
|
if let Some(_) = self.length {
|
||||||
// TODO
|
// TODO: if let Some(phrase) = seq.phrase.as_mut() {
|
||||||
//if let Some(phrase) = seq.phrase.as_mut() {
|
|
||||||
//phrase.write().unwrap().length = length;
|
//phrase.write().unwrap().length = length;
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ impl Content for PhraseEditor<Tui> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}).fill_y();
|
}).fill_y();
|
||||||
let playhead = CustomWidget::new(|_|Ok(Some([32u16,2u16])), move|to: &mut TuiOutput|{
|
let playhead = CustomWidget::new(|_|Ok(Some([32u16,2u16])), move|to: &mut TuiOutput|{
|
||||||
if let Some(phrase) = phrase {
|
if let Some(_) = phrase {
|
||||||
let time_0 = time_axis.start;
|
let time_0 = time_axis.start;
|
||||||
let time_z = time_axis.scale;
|
let time_z = time_axis.scale;
|
||||||
let now = 0; // TODO FIXME: self.now % phrase.read().unwrap().length;
|
let now = 0; // TODO FIXME: self.now % phrase.read().unwrap().length;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue