mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
refactor vertical arranger
This commit is contained in:
parent
e62fcc333e
commit
a7a798b484
3 changed files with 116 additions and 180 deletions
|
|
@ -92,19 +92,19 @@
|
||||||
(:90 (42 70)))
|
(:90 (42 70)))
|
||||||
|
|
||||||
(sampler { :name "DrumKit1" :dir "/home/user/Lab/Music/pak" }
|
(sampler { :name "DrumKit1" :dir "/home/user/Lab/Music/pak" }
|
||||||
(sample { :midi 34 :name "808" :file "808.wav" })
|
(sample { :midi 34 :name "808 D" :file "808.wav" })
|
||||||
(sample { :midi 35 :name "KC1" :file "kik.wav" })
|
(sample { :midi 35 :name "Kick 1" :file "kik.wav" })
|
||||||
(sample { :midi 36 :name "KC2" :file "kik2.wav" })
|
(sample { :midi 36 :name "Kick 2" :file "kik2.wav" })
|
||||||
(sample { :midi 37 :name "RIM" :file "rim.wav" })
|
(sample { :midi 37 :name "Rim" :file "rim.wav" })
|
||||||
(sample { :midi 38 :name "SN1" :file "sna.wav" })
|
(sample { :midi 38 :name "Snare 1" :file "sna.wav" })
|
||||||
(sample { :midi 39 :name "SHK" :file "shk.wav" })
|
(sample { :midi 39 :name "Shaker" :file "shk.wav" })
|
||||||
(sample { :midi 40 :name "SN2" :file "sna2.wav" })
|
(sample { :midi 40 :name "Snare 2" :file "sna2.wav" })
|
||||||
(sample { :midi 42 :name "HH1" :file "chh.wav" })
|
(sample { :midi 42 :name "Closed HH 1" :file "chh.wav" })
|
||||||
(sample { :midi 45 :name "HH1" :file "ohh.wav" })
|
(sample { :midi 44 :name "Closed HH 2" :file "chh2.wav" })
|
||||||
(sample { :midi 46 :name "HH1" :file "ohh1.wav" })
|
(sample { :midi 45 :name "Open HH 0" :file "ohh.wav" })
|
||||||
(sample { :midi 47 :name "HH1" :file "ohh2.wav" })
|
(sample { :midi 46 :name "Open HH 1" :file "ohh1.wav" })
|
||||||
(sample { :midi 44 :name "HH2" :file "chh2.wav" })
|
(sample { :midi 47 :name "Open HH 2" :file "ohh2.wav" })
|
||||||
(sample { :midi 49 :name "CRS" :file "crs.wav" })))
|
(sample { :midi 49 :name "Crash" :file "crs.wav" })))
|
||||||
|
|
||||||
(track { :name "Bass" :gain +0.0 }
|
(track { :name "Bass" :gain +0.0 }
|
||||||
(phrase { :name "Bass 1" :beats 4 })
|
(phrase { :name "Bass 1" :beats 4 })
|
||||||
|
|
|
||||||
|
|
@ -96,30 +96,18 @@ impl Track {
|
||||||
reset: true,
|
reset: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn get_device (&self, i: usize) -> Option<RwLockReadGuard<Box<dyn Device>>> {
|
|
||||||
self.devices.get(i).map(|d|d.state.read().unwrap())
|
|
||||||
}
|
|
||||||
fn get_device_mut (&self, i: usize) -> Option<RwLockWriteGuard<Box<dyn Device>>> {
|
fn get_device_mut (&self, i: usize) -> Option<RwLockWriteGuard<Box<dyn Device>>> {
|
||||||
self.devices.get(i).map(|d|d.state.write().unwrap())
|
self.devices.get(i).map(|d|d.state.write().unwrap())
|
||||||
}
|
}
|
||||||
fn device (&self) -> Option<RwLockReadGuard<Box<dyn Device>>> {
|
|
||||||
self.get_device(self.device)
|
|
||||||
}
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
fn first_device (&self) -> Option<RwLockReadGuard<Box<dyn Device>>> {
|
|
||||||
self.get_device(0)
|
|
||||||
}
|
|
||||||
pub fn connect_first_device (&self) -> Usually<()> {
|
pub fn connect_first_device (&self) -> Usually<()> {
|
||||||
if let (Some(port), Some(device)) = (&self.midi_out, self.devices.get(0)) {
|
if let (Some(port), Some(device)) = (&self.midi_out, self.devices.get(0)) {
|
||||||
device.client.as_client().connect_ports(&port, &device.midi_ins()?[0])?;
|
device.client.as_client().connect_ports(&port, &device.midi_ins()?[0])?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn last_device (&self) -> Option<RwLockReadGuard<Box<dyn Device>>> {
|
|
||||||
self.get_device(self.devices.len().saturating_sub(1))
|
|
||||||
}
|
|
||||||
pub fn connect_last_device (&self, app: &App) -> Usually<()> {
|
pub fn connect_last_device (&self, app: &App) -> Usually<()> {
|
||||||
Ok(match self.devices.get(self.devices.len().saturating_sub(1)) {
|
Ok(match self.devices.get(self.devices.len().saturating_sub(1)) {
|
||||||
Some(device) => {
|
Some(device) => {
|
||||||
|
|
@ -135,37 +123,6 @@ impl Track {
|
||||||
let index = self.devices.len() - 1;
|
let index = self.devices.len() - 1;
|
||||||
Ok(&mut self.devices[index])
|
Ok(&mut self.devices[index])
|
||||||
}
|
}
|
||||||
fn add_device_with_cb (
|
|
||||||
&mut self,
|
|
||||||
mut device: JackDevice,
|
|
||||||
init: impl Fn(&Self, &mut JackDevice)->Usually<()>
|
|
||||||
) -> Usually<&mut JackDevice> {
|
|
||||||
init(&self, &mut device)?;
|
|
||||||
self.devices.push(device);
|
|
||||||
let index = self.devices.len() - 1;
|
|
||||||
Ok(&mut self.devices[index])
|
|
||||||
}
|
|
||||||
fn phrase (&self) -> Option<&Phrase> {
|
|
||||||
if let Some(phrase) = self.sequence {
|
|
||||||
return self.phrases.get(phrase)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn phrase_mut (&mut self) -> Option<&mut Phrase> {
|
|
||||||
if let Some(phrase) = self.sequence {
|
|
||||||
return self.phrases.get_mut(phrase)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn add_phrase (
|
|
||||||
&mut self, name: &str, length: usize, data: Option<PhraseData>
|
|
||||||
) -> &mut Phrase {
|
|
||||||
self.phrases.push(Phrase::new(name, length, data));
|
|
||||||
let index = self.phrases.len() - 1;
|
|
||||||
&mut self.phrases[index]
|
|
||||||
}
|
|
||||||
pub fn toggle_monitor (&mut self) {
|
pub fn toggle_monitor (&mut self) {
|
||||||
self.monitoring = !self.monitoring;
|
self.monitoring = !self.monitoring;
|
||||||
}
|
}
|
||||||
|
|
@ -201,8 +158,6 @@ impl Track {
|
||||||
all_notes_off(&mut self.midi_out_buf);
|
all_notes_off(&mut self.midi_out_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For highlighting keys and note repeat
|
|
||||||
// Currently playing phrase
|
|
||||||
if let (
|
if let (
|
||||||
Some(TransportState::Rolling), Some((start_frame, _)), Some(phrase)
|
Some(TransportState::Rolling), Some((start_frame, _)), Some(phrase)
|
||||||
) = (
|
) = (
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ impl<'a> ArrangerView<'a> {
|
||||||
|
|
||||||
impl<'a> Render for ArrangerView<'a> {
|
impl<'a> Render for ArrangerView<'a> {
|
||||||
fn render (&self, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
fn render (&self, buf: &mut Buffer, mut area: Rect) -> Usually<Rect> {
|
||||||
area.height = area.height.min(if self.vertical {
|
area.height = area.height.min(1 + if self.vertical {
|
||||||
self.scenes.len() as u16 + 3
|
self.scenes.len() as u16 * 2
|
||||||
} else {
|
} else {
|
||||||
self.tracks.len() as u16 * 2
|
self.tracks.len() as u16 * 2
|
||||||
});
|
});
|
||||||
|
|
@ -82,36 +82,6 @@ impl<'a> Render for ArrangerView<'a> {
|
||||||
|
|
||||||
impl<'a> ArrangerView<'a> {
|
impl<'a> ArrangerView<'a> {
|
||||||
|
|
||||||
fn vertical_scenes (&self, buf: &mut Buffer, x: u16, y: u16, height: u16) -> Usually<u16> {
|
|
||||||
let mut index = 0usize;
|
|
||||||
loop {
|
|
||||||
if index >= self.scenes.len() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if y + index as u16 >= height {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
self.vertical_scene(buf, x, y + index as u16, index)?;
|
|
||||||
index = index + 1;
|
|
||||||
}
|
|
||||||
Ok(self.scenes
|
|
||||||
.iter()
|
|
||||||
.map(|x|&x.name)
|
|
||||||
.fold(0, |x,y|x.max(y.len() as u16)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vertical_scene (&self, buf: &mut Buffer, x: u16, y: u16, index: usize) -> Usually<()> {
|
|
||||||
if let Some(scene) = self.scenes.get(index) {
|
|
||||||
let style = Some(highlight(
|
|
||||||
self.focused,
|
|
||||||
(0 == self.cursor.0) && (index + 1 == self.cursor.1)
|
|
||||||
).bold());
|
|
||||||
"⯈".blit(buf, x, y, style)?;
|
|
||||||
scene.name.blit(buf, x + 2, y, style)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vertical_clips (&self, buf: &mut Buffer, x: u16, y: u16, height: u16, track: usize) -> Usually<u16> {
|
fn vertical_clips (&self, buf: &mut Buffer, x: u16, y: u16, height: u16, track: usize) -> Usually<u16> {
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
let mut width = 10;
|
let mut width = 10;
|
||||||
|
|
@ -122,14 +92,7 @@ impl<'a> ArrangerView<'a> {
|
||||||
if y + index as u16 >= height {
|
if y + index as u16 >= height {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
width = 10.max(self.vertical_clip(buf, x, y, track, index)?);
|
width = 10.max(if let Some(scene) = self.scenes.get(index) {
|
||||||
index = index + 1;
|
|
||||||
}
|
|
||||||
Ok(width)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vertical_clip (&self, buf: &mut Buffer, x: u16, y: u16, track: usize, index: usize) -> Usually<u16> {
|
|
||||||
Ok(if let Some(scene) = self.scenes.get(index) {
|
|
||||||
let hi = (track + 1 == self.cursor.0) &&
|
let hi = (track + 1 == self.cursor.0) &&
|
||||||
(index + 1 == self.cursor.1);
|
(index + 1 == self.cursor.1);
|
||||||
let style = Some(highlight(self.focused, hi));
|
let style = Some(highlight(self.focused, hi));
|
||||||
|
|
@ -138,7 +101,7 @@ impl<'a> ArrangerView<'a> {
|
||||||
let label = if let Some(Some(clip)) = clip {
|
let label = if let Some(Some(clip)) = clip {
|
||||||
if let Some(phrase) = self.tracks[track].phrases.get(*clip) {
|
if let Some(phrase) = self.tracks[track].phrases.get(*clip) {
|
||||||
format!("{} {}", if self.tracks[track].sequence == Some(*clip) {
|
format!("{} {}", if self.tracks[track].sequence == Some(*clip) {
|
||||||
"⯈"
|
""
|
||||||
} else {
|
} else {
|
||||||
" "
|
" "
|
||||||
}, phrase.name)
|
}, phrase.name)
|
||||||
|
|
@ -152,74 +115,92 @@ impl<'a> ArrangerView<'a> {
|
||||||
label.len() as u16
|
label.len() as u16
|
||||||
} else {
|
} else {
|
||||||
0u16
|
0u16
|
||||||
})
|
});
|
||||||
|
index = index + 1;
|
||||||
|
}
|
||||||
|
Ok(width)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
fn draw_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||||
let Rect { x, y, width, height } = area;
|
|
||||||
let mut x2 = x;
|
|
||||||
let bg_color = self.bg_color_hi();
|
|
||||||
for (i, w) in self.track_widths().iter().enumerate() {
|
|
||||||
let focus_column = i == self.cursor.0;
|
|
||||||
if x2 >= x + width {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if focus_column {
|
|
||||||
let bg_area = Rect { x: x2, y, width: *w, height };
|
|
||||||
fill_bg(buf, bg_area, bg_color);
|
|
||||||
}
|
|
||||||
x2 = x2 + w;
|
|
||||||
}
|
|
||||||
let (mut x2, y2) = (x, y);
|
|
||||||
let columns = self.track_names();
|
|
||||||
for (i, title) in columns.iter().enumerate() {
|
|
||||||
let focus_column = i == self.cursor.0;
|
|
||||||
if x2 >= x + width {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
let w = (title.len() as u16).max(10);
|
|
||||||
let bg_area = Rect { x: x2, y: if self.cursor.1 == 0 {
|
|
||||||
y2
|
|
||||||
} else {
|
|
||||||
y2 + 1 + self.cursor.1 as u16
|
|
||||||
}, width: w + 3, height: 1 };
|
|
||||||
fill_bg(buf, bg_area, bg_color);
|
|
||||||
if i == 0 {
|
|
||||||
self.vertical_scenes(buf, x2+1, y2+2, area.height)?;
|
|
||||||
} else if i < columns.len() {
|
|
||||||
self.vertical_clips(buf, x2+1, y2+2, area.height, i - 1)?;
|
|
||||||
};
|
|
||||||
let style = Some(highlight(self.focused, focus_column).bold());
|
|
||||||
if i > 0 {
|
|
||||||
"⏺".blit(buf, x2, y2, Some(if self.tracks[i-1].recording {
|
|
||||||
Style::default().red()
|
|
||||||
} else if self.tracks[i-1].monitoring {
|
|
||||||
Style::default().yellow()
|
|
||||||
} else {
|
|
||||||
Style::default().black()
|
|
||||||
}))?;
|
|
||||||
}
|
|
||||||
title.blit(buf, x2+2, y2, style)?;
|
|
||||||
x2 = x2 + w + 3;
|
|
||||||
}
|
|
||||||
let bg_area = Rect { x: x2, y: if self.cursor.1 == 0 {
|
|
||||||
y2
|
|
||||||
} else {
|
|
||||||
y2 + 1 + self.cursor.1 as u16
|
|
||||||
}, width: width - x2, height: 1 };
|
|
||||||
fill_bg(buf, bg_area, bg_color);
|
|
||||||
Ok(area)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_vertical_2 (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
return Split::right([
|
||||||
Split::right([
|
|
||||||
// Scene list
|
// Scene column
|
||||||
&|buf: &mut Buffer, mut area: Rect|Ok(Rect::default()),
|
&|buf: &mut Buffer, area: Rect|{
|
||||||
|
let Rect { x, y, height, .. } = area;
|
||||||
|
for (scene_index, scene) in self.scenes.iter().enumerate() {
|
||||||
|
if y + 2 * scene_index as u16 >= height {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
let style = Some(highlight(
|
||||||
|
self.focused,
|
||||||
|
(0 == self.cursor.0) && (scene_index + 1 == self.cursor.1)
|
||||||
|
).bold());
|
||||||
|
let y = 1 + y + 2 * scene_index as u16;
|
||||||
|
"⯈".blit(buf, x+1, y, style)?;
|
||||||
|
scene.name.blit(buf, x + 2, y, style)?;
|
||||||
|
}
|
||||||
|
let width = 2+self.scenes.iter()
|
||||||
|
.map(|x|&x.name).fold(0, |x,y|x.max(y.len() as u16+1));
|
||||||
|
Ok(Rect { width, ..area })
|
||||||
|
},
|
||||||
|
|
||||||
// Track columns
|
// Track columns
|
||||||
&|buf: &mut Buffer, mut area: Rect|Ok(Rect::default()),
|
&|buf: &mut Buffer, area: Rect|{
|
||||||
&|buf: &mut Buffer, mut area: Rect|Ok(Rect::default()),
|
let Rect { mut x, y, width, height } = area;
|
||||||
&|buf: &mut Buffer, mut area: Rect|Ok(Rect::default()),
|
for (track_index, track) in self.tracks.iter().enumerate() {
|
||||||
]).render(buf, area)
|
if x >= width {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
let mut width = 16u16;
|
||||||
|
track.name.blit(buf, x, y, Some(Style::default().bold()))?;
|
||||||
|
for (scene_index, scene) in self.scenes.iter().enumerate() {
|
||||||
|
if y + 2 * scene_index as u16 >= height {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
let label = if let Some(Some(clip)) = scene.clips.get(track_index) {
|
||||||
|
if let Some(phrase) = track.phrases.get(*clip) {
|
||||||
|
format!("{} {}", if track.sequence == Some(*clip) {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
"┊"
|
||||||
|
}, phrase.name)
|
||||||
|
} else {
|
||||||
|
format!(" ??? ")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format!("┊ ········")
|
||||||
|
};
|
||||||
|
let hi = (track_index + 1 == self.cursor.0) && (scene_index + 1 == self.cursor.1);
|
||||||
|
let style = Some(highlight(self.focused, hi));
|
||||||
|
let y = 1 + y + 2 * scene_index as u16;
|
||||||
|
"┊".blit(buf, x, y, Some(Style::default().dim()))?;
|
||||||
|
"┊".blit(buf, x, y + 1, Some(Style::default().dim()))?;
|
||||||
|
label.blit(buf, x, y, style)?;
|
||||||
|
//width = width.max(2label.len() as u16 + 3);
|
||||||
|
}
|
||||||
|
if track_index + 1 == self.cursor.0 {
|
||||||
|
if self.cursor.1 == 0 {
|
||||||
|
let y = area.y;
|
||||||
|
fill_bg(buf, Rect { x, y, width, height: 1 }, if self.focused {
|
||||||
|
Color::Rgb(30, 90, 25)
|
||||||
|
} else {
|
||||||
|
Color::Rgb(25, 60, 15)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let y = 1 + area.y + 2 * (self.cursor.1 as u16 - 1);
|
||||||
|
fill_bg(buf, Rect { x, y, width, height: 2 }, if self.focused {
|
||||||
|
Color::Rgb(30, 90, 25)
|
||||||
|
} else {
|
||||||
|
Color::Rgb(25, 60, 15)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
x = x + width as u16;
|
||||||
|
}
|
||||||
|
Ok(Rect { x: area.x, y, width: x - area.x, height })
|
||||||
|
}
|
||||||
|
]).render(buf, area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue