mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: fixing some assumptions
This commit is contained in:
parent
5ae99b4ada
commit
2a60808239
11 changed files with 73 additions and 125 deletions
|
|
@ -24,26 +24,27 @@ impl Chain {
|
||||||
pub fn device_mut (&self) -> Option<RwLockWriteGuard<Box<dyn Device>>> {
|
pub fn device_mut (&self) -> Option<RwLockWriteGuard<Box<dyn Device>>> {
|
||||||
self.get_device_mut(self.device)
|
self.get_device_mut(self.device)
|
||||||
}
|
}
|
||||||
pub fn connect_first_device (&self) -> Usually<()> {
|
/// Add a device to the end of the chain.
|
||||||
if let (Some(port), Some(device)) = (&self.midi_out, self.devices.get(0)) {
|
pub fn append_device (&mut self, device: JackDevice) -> Usually<&mut JackDevice> {
|
||||||
device.client.as_client().connect_ports(&port, &device.midi_ins()?[0])?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
pub fn connect_last_device (&self, app: &App) -> Usually<()> {
|
|
||||||
Ok(match self.devices.get(self.devices.len().saturating_sub(1)) {
|
|
||||||
Some(device) => {
|
|
||||||
app.audio_out(0).map(|left|device.connect_audio_out(0, &left)).transpose()?;
|
|
||||||
app.audio_out(1).map(|right|device.connect_audio_out(1, &right)).transpose()?;
|
|
||||||
()
|
|
||||||
},
|
|
||||||
None => ()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pub fn add_device (&mut self, device: JackDevice) -> Usually<&mut JackDevice> {
|
|
||||||
self.devices.push(device);
|
self.devices.push(device);
|
||||||
let index = self.devices.len() - 1;
|
let index = self.devices.len() - 1;
|
||||||
Ok(&mut self.devices[index])
|
Ok(&mut self.devices[index])
|
||||||
}
|
}
|
||||||
|
//pub fn connect_first_device (&self) -> Usually<()> {
|
||||||
|
//if let (Some(port), Some(device)) = (&self.midi_out, self.devices.get(0)) {
|
||||||
|
//device.client.as_client().connect_ports(&port, &device.midi_ins()?[0])?;
|
||||||
|
//}
|
||||||
|
//Ok(())
|
||||||
|
//}
|
||||||
|
//pub fn connect_last_device (&self, app: &App) -> Usually<()> {
|
||||||
|
//Ok(match self.devices.get(self.devices.len().saturating_sub(1)) {
|
||||||
|
//Some(device) => {
|
||||||
|
//app.audio_out(0).map(|left|device.connect_audio_out(0, &left)).transpose()?;
|
||||||
|
//app.audio_out(1).map(|right|device.connect_audio_out(1, &right)).transpose()?;
|
||||||
|
//()
|
||||||
|
//},
|
||||||
|
//None => ()
|
||||||
|
//})
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,39 +2,26 @@ use crate::*;
|
||||||
use tek_core::Direction;
|
use tek_core::Direction;
|
||||||
|
|
||||||
pub struct ChainView<'a> {
|
pub struct ChainView<'a> {
|
||||||
pub track: Option<&'a Chain>,
|
pub chain: Option<&'a Chain>,
|
||||||
pub direction: Direction,
|
pub direction: Direction,
|
||||||
pub focused: bool,
|
pub focused: bool,
|
||||||
pub entered: bool,
|
pub entered: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ChainView<'a> {
|
|
||||||
pub fn horizontal (app: &'a App) -> Self {
|
|
||||||
Self::new(app, Direction::Right)
|
|
||||||
}
|
|
||||||
pub fn vertical (app: &'a App) -> Self {
|
|
||||||
Self::new(app, Direction::Down)
|
|
||||||
}
|
|
||||||
pub fn new (app: &'a App, direction: Direction) -> Self {
|
|
||||||
Self {
|
|
||||||
direction,
|
|
||||||
entered: app.entered,
|
|
||||||
focused: app.section == AppFocus::Chain,
|
|
||||||
track: app.arranger.track()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Render for ChainView<'a> {
|
impl<'a> Render for ChainView<'a> {
|
||||||
fn render (&self, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
fn render (&self, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
||||||
if let Some(track) = self.track {
|
if let Some(chain) = self.chain {
|
||||||
match self.direction {
|
match self.direction {
|
||||||
Direction::Down => area.width = area.width.min(40),
|
Direction::Down => area.width = area.width.min(40),
|
||||||
Direction::Right => area.width = area.width.min(10),
|
Direction::Right => area.width = area.width.min(10),
|
||||||
}
|
}
|
||||||
fill_bg(buf, area, Nord::bg_lo(self.focused, self.entered));
|
fill_bg(buf, area, Nord::bg_lo(self.focused, self.entered));
|
||||||
|
let devices: Vec<&(dyn Render + Send + Sync)> = chain.devices.as_slice()
|
||||||
|
.iter()
|
||||||
|
.map(|d|d as &(dyn Render + Send + Sync))
|
||||||
|
.collect();
|
||||||
let (area, areas) = self.direction
|
let (area, areas) = self.direction
|
||||||
.split_focus(0, track.devices.as_slice(), if self.focused {
|
.split_focus(0, devices.as_slice(), if self.focused {
|
||||||
Style::default().green().dim()
|
Style::default().green().dim()
|
||||||
} else {
|
} else {
|
||||||
Style::default().dim()
|
Style::default().dim()
|
||||||
|
|
@ -46,7 +33,7 @@ impl<'a> Render for ChainView<'a> {
|
||||||
Ok(area)
|
Ok(area)
|
||||||
} else {
|
} else {
|
||||||
let Rect { x, y, width, height } = area;
|
let Rect { x, y, width, height } = area;
|
||||||
let label = "No track selected";
|
let label = "No chain selected";
|
||||||
let x = x + (width - label.len() as u16) / 2;
|
let x = x + (width - label.len() as u16) / 2;
|
||||||
let y = y + height / 2;
|
let y = y + height / 2;
|
||||||
label.blit(buf, x, y, Some(Style::default().dim().bold()))?;
|
label.blit(buf, x, y, Some(Style::default().dim().bold()))?;
|
||||||
|
|
@ -55,4 +42,19 @@ impl<'a> Render for ChainView<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//impl<'a> ChainView<'a> {
|
||||||
|
//pub fn horizontal (app: &'a App) -> Self {
|
||||||
|
//Self::new(app, Direction::Right)
|
||||||
|
//}
|
||||||
|
//pub fn vertical (app: &'a App) -> Self {
|
||||||
|
//Self::new(app, Direction::Down)
|
||||||
|
//}
|
||||||
|
//pub fn new (app: &'a App, direction: Direction) -> Self {
|
||||||
|
//Self {
|
||||||
|
//direction,
|
||||||
|
//entered: app.entered,
|
||||||
|
//focused: app.section == AppFocus::Chain,
|
||||||
|
//chain: app.arranger.chain()
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ impl<'a, const N: usize> Render for Split<'a, N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Renderables<'a> = &'a [&'a dyn Component];
|
type Renderables<'a> = &'a [&'a (dyn Render + Send + Sync)];
|
||||||
|
|
||||||
pub struct SplitFocus<'a>(pub Direction, pub usize, pub Renderables<'a>, pub Style);
|
pub struct SplitFocus<'a>(pub Direction, pub usize, pub Renderables<'a>, pub Style);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,6 @@
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
use self::arr_focus::ArrangerFocus;
|
|
||||||
pub use self::arr_scene::Scene;
|
|
||||||
|
|
||||||
submod! { arr_draw_h arr_draw_v arr_focus arr_phrase arr_scene arr_track }
|
|
||||||
|
|
||||||
/// Key bindings for arranger section.
|
/// Key bindings for arranger section.
|
||||||
pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {
|
||||||
[Char('`'), NONE, "arranger_mode_switch", "switch the display mode", |app: &mut Arranger| {
|
[Char('`'), NONE, "arranger_mode_switch", "switch the display mode", |app: &mut Arranger| {
|
||||||
|
|
@ -68,7 +63,7 @@ pub struct Arranger {
|
||||||
/// Currently selected element.
|
/// Currently selected element.
|
||||||
pub selected: ArrangerFocus,
|
pub selected: ArrangerFocus,
|
||||||
/// Collection of tracks.
|
/// Collection of tracks.
|
||||||
pub tracks: Vec<Track>,
|
pub tracks: Vec<SequencerTrack>,
|
||||||
/// Collection of scenes.
|
/// Collection of scenes.
|
||||||
pub scenes: Vec<Scene>,
|
pub scenes: Vec<Scene>,
|
||||||
|
|
||||||
|
|
@ -135,10 +130,10 @@ impl Arranger {
|
||||||
|
|
||||||
render!(Arranger |self, buf, area| match self.mode {
|
render!(Arranger |self, buf, area| match self.mode {
|
||||||
ArrangerViewMode::Horizontal =>
|
ArrangerViewMode::Horizontal =>
|
||||||
self::arr_draw_h::draw(self, buf, area),
|
super::arranger_view_h::draw(self, buf, area),
|
||||||
ArrangerViewMode::Vertical =>
|
ArrangerViewMode::Vertical =>
|
||||||
self::arr_draw_v::draw_expanded(self, buf, area),
|
super::arranger_view_v::draw_expanded(self, buf, area),
|
||||||
ArrangerViewMode::VerticalCompact =>
|
ArrangerViewMode::VerticalCompact =>
|
||||||
self::arr_draw_v::draw_compact(self, buf, area),
|
super::arranger_view_v::draw_compact(self, buf, area),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,14 @@ impl Scene {
|
||||||
Self { name, clips, }
|
Self { name, clips, }
|
||||||
}
|
}
|
||||||
/// 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 (&self, tracks: &[Track]) -> usize {
|
pub fn pulses (&self, tracks: &[SequencerTrack]) -> usize {
|
||||||
self.clips.iter().enumerate()
|
self.clips.iter().enumerate()
|
||||||
.filter_map(|(i, c)|c.map(|c|tracks[i].phrases.get(c)))
|
.filter_map(|(i, c)|c.map(|c|tracks[i].phrases.get(c)))
|
||||||
.filter_map(|p|p)
|
.filter_map(|p|p)
|
||||||
.fold(0, |a, p|a.max(p.read().unwrap().length))
|
.fold(0, |a, p|a.max(p.read().unwrap().length))
|
||||||
}
|
}
|
||||||
/// Returns true if all phrases in the scene are currently playing
|
/// Returns true if all phrases in the scene are currently playing
|
||||||
pub fn is_playing (&self, tracks: &[Track]) -> bool {
|
pub fn is_playing (&self, tracks: &[SequencerTrack]) -> bool {
|
||||||
self.clips.iter().enumerate()
|
self.clips.iter().enumerate()
|
||||||
.all(|(track_index, phrase_index)|match phrase_index {
|
.all(|(track_index, phrase_index)|match phrase_index {
|
||||||
Some(i) => tracks[track_index].sequence == Some(*i),
|
Some(i) => tracks[track_index].sequence == Some(*i),
|
||||||
|
|
@ -37,7 +37,7 @@ pub fn scene_name_max_len (scenes: &[Scene]) -> usize {
|
||||||
.fold(0, usize::max)
|
.fold(0, usize::max)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scene_ppqs (tracks: &[Track], scenes: &[Scene]) -> Vec<(usize, usize)> {
|
pub fn scene_ppqs (tracks: &[SequencerTrack], scenes: &[Scene]) -> 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);
|
let pulses = scene.pulses(tracks);
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ use super::Arranger;
|
||||||
|
|
||||||
/// Track management methods
|
/// Track management methods
|
||||||
impl Arranger {
|
impl Arranger {
|
||||||
pub fn track (&self) -> Option<&Track> {
|
pub fn track (&self) -> Option<&SequencerTrack> {
|
||||||
self.selected.track().map(|t|self.tracks.get(t)).flatten()
|
self.selected.track().map(|t|self.tracks.get(t)).flatten()
|
||||||
}
|
}
|
||||||
pub fn track_mut (&mut self) -> Option<&mut Track> {
|
pub fn track_mut (&mut self) -> Option<&mut SequencerTrack> {
|
||||||
self.selected.track().map(|t|self.tracks.get_mut(t)).flatten()
|
self.selected.track().map(|t|self.tracks.get_mut(t)).flatten()
|
||||||
}
|
}
|
||||||
pub fn track_next (&mut self) {
|
pub fn track_next (&mut self) {
|
||||||
|
|
@ -16,10 +16,10 @@ impl Arranger {
|
||||||
pub fn track_prev (&mut self) {
|
pub fn track_prev (&mut self) {
|
||||||
self.selected.track_prev()
|
self.selected.track_prev()
|
||||||
}
|
}
|
||||||
pub fn track_add (&mut self, name: Option<&str>) -> Usually<&mut Track> {
|
pub fn track_add (&mut self, name: Option<&str>) -> Usually<&mut SequencerTrack> {
|
||||||
self.tracks.push(name.map_or_else(
|
self.tracks.push(name.map_or_else(
|
||||||
|| Track::new(&self.track_default_name()),
|
|| SequencerTrack::new(&self.track_default_name()),
|
||||||
|name| Track::new(name),
|
|name| SequencerTrack::new(name),
|
||||||
)?);
|
)?);
|
||||||
let index = self.tracks.len() - 1;
|
let index = self.tracks.len() - 1;
|
||||||
Ok(&mut self.tracks[index])
|
Ok(&mut self.tracks[index])
|
||||||
|
|
@ -32,13 +32,13 @@ impl Arranger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn track_name_max_len (tracks: &[Track]) -> usize {
|
pub fn track_name_max_len (tracks: &[SequencerTrack]) -> usize {
|
||||||
tracks.iter()
|
tracks.iter()
|
||||||
.map(|s|s.name.len())
|
.map(|s|s.name.len())
|
||||||
.fold(0, usize::max)
|
.fold(0, usize::max)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn track_clip_name_lengths (tracks: &[Track]) -> Vec<(usize, usize)> {
|
pub fn track_clip_name_lengths (tracks: &[SequencerTrack]) -> Vec<(usize, usize)> {
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
let mut lengths: Vec<(usize, usize)> = tracks.iter().map(|track|{
|
let mut lengths: Vec<(usize, usize)> = tracks.iter().map(|track|{
|
||||||
let len = 2 + track.phrases
|
let len = 2 + track.phrases
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use super::{Arranger, arr_track::*};
|
|
||||||
|
|
||||||
pub fn draw (state: &Arranger, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
pub fn draw (state: &Arranger, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
||||||
area.height = area.height.min((2 + state.tracks.len() * 2) as u16);
|
area.height = area.height.min((2 + state.tracks.len() * 2) as u16);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,4 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use super::{
|
|
||||||
Arranger,
|
|
||||||
arr_focus::ArrangerFocus,
|
|
||||||
arr_track::track_clip_name_lengths,
|
|
||||||
arr_scene::{Scene, scene_ppqs, scene_name_max_len}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn draw_expanded (state: &Arranger, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
pub fn draw_expanded (state: &Arranger, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||||
let track_cols = track_clip_name_lengths(state.tracks.as_slice());
|
let track_cols = track_clip_name_lengths(state.tracks.as_slice());
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,22 @@ pub(crate) use tek_jack::{*, jack::*};
|
||||||
pub(crate) use tek_timer::*;
|
pub(crate) use tek_timer::*;
|
||||||
pub(crate) use std::sync::{Arc, RwLock};
|
pub(crate) use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
submod! { midi phrase arranger sequencer sequencer_track }
|
submod! {
|
||||||
|
midi
|
||||||
|
phrase
|
||||||
|
sequencer
|
||||||
|
sequencer_track
|
||||||
|
arranger
|
||||||
|
arranger_focus
|
||||||
|
arranger_phrase
|
||||||
|
arranger_scene
|
||||||
|
arranger_track
|
||||||
|
}
|
||||||
|
|
||||||
|
pubmod! {
|
||||||
|
arranger_view_h
|
||||||
|
arranger_view_v
|
||||||
|
}
|
||||||
|
|
||||||
/// Key bindings for phrase editor.
|
/// Key bindings for phrase editor.
|
||||||
pub const KEYMAP_SEQUENCER: &'static [KeyBinding<Sequencer>] = keymap!(Sequencer {
|
pub const KEYMAP_SEQUENCER: &'static [KeyBinding<Sequencer>] = keymap!(Sequencer {
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ pub struct Sequencer {
|
||||||
pub ppq: usize,
|
pub ppq: usize,
|
||||||
pub note_axis: FixedAxis<usize>,
|
pub note_axis: FixedAxis<usize>,
|
||||||
pub time_axis: ScaledAxis<usize>,
|
pub time_axis: ScaledAxis<usize>,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render!(Sequencer |self, buf, area| {
|
render!(Sequencer |self, buf, area| {
|
||||||
|
|
|
||||||
|
|
@ -168,60 +168,3 @@ impl SequencerTrack {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct ChainView<'a> {
|
|
||||||
pub track: Option<&'a Track>,
|
|
||||||
pub direction: Direction,
|
|
||||||
pub focused: bool,
|
|
||||||
pub entered: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> ChainView<'a> {
|
|
||||||
pub fn horizontal (app: &'a App) -> Self {
|
|
||||||
Self::new(app, Direction::Right)
|
|
||||||
}
|
|
||||||
pub fn vertical (app: &'a App) -> Self {
|
|
||||||
Self::new(app, Direction::Down)
|
|
||||||
}
|
|
||||||
pub fn new (app: &'a App, direction: Direction) -> Self {
|
|
||||||
Self {
|
|
||||||
direction,
|
|
||||||
entered: app.entered,
|
|
||||||
focused: app.section == AppFocus::Chain,
|
|
||||||
track: app.arranger.track()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Render for ChainView<'a> {
|
|
||||||
fn render (&self, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
|
||||||
if let Some(track) = self.track {
|
|
||||||
match self.direction {
|
|
||||||
Direction::Down => area.width = area.width.min(40),
|
|
||||||
Direction::Right => area.width = area.width.min(10),
|
|
||||||
}
|
|
||||||
fill_bg(buf, area, Nord::bg_lo(self.focused, self.entered));
|
|
||||||
let (area, areas) = self.direction
|
|
||||||
.split_focus(0, track.devices.as_slice(), if self.focused {
|
|
||||||
Style::default().green().dim()
|
|
||||||
} else {
|
|
||||||
Style::default().dim()
|
|
||||||
})
|
|
||||||
.render_areas(buf, area)?;
|
|
||||||
if self.focused && self.entered {
|
|
||||||
Corners(Style::default().green().not_dim()).draw(buf, areas[0])?;
|
|
||||||
}
|
|
||||||
Ok(area)
|
|
||||||
} else {
|
|
||||||
let Rect { x, y, width, height } = area;
|
|
||||||
let label = "No track selected";
|
|
||||||
let x = x + (width - label.len() as u16) / 2;
|
|
||||||
let y = y + height / 2;
|
|
||||||
label.blit(buf, x, y, Some(Style::default().dim().bold()))?;
|
|
||||||
Ok(area)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue