mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
Compare commits
2 commits
5a360d02fa
...
25a6e94b5d
| Author | SHA1 | Date | |
|---|---|---|---|
| 25a6e94b5d | |||
| 7495dd10f2 |
5 changed files with 104 additions and 79 deletions
|
|
@ -12,9 +12,17 @@
|
||||||
(layer "./keys_global.edn"))
|
(layer "./keys_global.edn"))
|
||||||
|
|
||||||
(view (bsp/a :view-dialog (bsp/w :view-meters-output (bsp/e :view-meters-input
|
(view (bsp/a :view-dialog (bsp/w :view-meters-output (bsp/e :view-meters-input
|
||||||
(bsp/n (fixed/y 6 (bsp/e :view-sample-status :view-sample-viewer))
|
|
||||||
(bsp/e
|
(bsp/e
|
||||||
(fill/y (align/n (bsp/s :view-status-v (bsp/s
|
(fill/y (align/n
|
||||||
(bsp/s :view-midi-ports-status :view-audio-ports-status)
|
(bsp/s :view-status-v
|
||||||
(bsp/n :view-editor-status :view-pool)))))
|
(bsp/s :view-editor-status :view-pool))))
|
||||||
(bsp/e :view-samples-keys :view-editor)))))))
|
(bsp/w
|
||||||
|
(fill/y (align/n
|
||||||
|
(bsp/s :view-midi-ins-status
|
||||||
|
(bsp/s :view-midi-outs-status
|
||||||
|
(bsp/s :view-audio-ins-status :view-audio-outs-status)))))
|
||||||
|
(bsp/n
|
||||||
|
(fixed/y :h-sample-detail
|
||||||
|
(bsp/e (fill/y (fixed/x 20 (align/nw :view-sample-status)))
|
||||||
|
:view-sample-viewer))
|
||||||
|
(bsp/e :view-samples-keys :view-editor))))))))
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,9 @@ impl App {
|
||||||
fn w_sidebar (&self) -> u16 {
|
fn w_sidebar (&self) -> u16 {
|
||||||
self.project.w_sidebar(self.editor.is_some())
|
self.project.w_sidebar(self.editor.is_some())
|
||||||
}
|
}
|
||||||
|
fn h_sample_detail (&self) -> u16 {
|
||||||
|
6.max(self.height() as u16 * 3 / 9)
|
||||||
|
}
|
||||||
fn focus_editor (&self) -> bool {
|
fn focus_editor (&self) -> bool {
|
||||||
self.is_editing()
|
self.is_editing()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ impl App {
|
||||||
let cache = self.view_cache.read().unwrap();
|
let cache = self.view_cache.read().unwrap();
|
||||||
let theme = self.color;
|
let theme = self.color;
|
||||||
let playing = self.clock().is_rolling();
|
let playing = self.clock().is_rolling();
|
||||||
Tui::bg(theme.darkest.rgb, Fixed::xy(20, 6, col!(
|
Tui::bg(theme.darkest.rgb, Fixed::xy(20, 6, Outer(true, Style::default().fg(Tui::g(96))).enclose(
|
||||||
|
col!(
|
||||||
Fill::x(Align::w(Bsp::e(
|
Fill::x(Align::w(Bsp::e(
|
||||||
Align::w(Tui::bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
|
Align::w(Tui::bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) },
|
||||||
Either::new(false, // TODO
|
Either::new(false, // TODO
|
||||||
|
|
@ -42,7 +43,7 @@ impl App {
|
||||||
Fill::x(Align::w(FieldH(theme, "SR ", cache.sr.view.clone()))),
|
Fill::x(Align::w(FieldH(theme, "SR ", cache.sr.view.clone()))),
|
||||||
Fill::x(Align::w(FieldH(theme, "Buf", cache.buf.view.clone()))),
|
Fill::x(Align::w(FieldH(theme, "Buf", cache.buf.view.clone()))),
|
||||||
Fill::x(Align::w(FieldH(theme, "Lat", cache.lat.view.clone()))),
|
Fill::x(Align::w(FieldH(theme, "Lat", cache.lat.view.clone()))),
|
||||||
)))
|
))))
|
||||||
}
|
}
|
||||||
pub fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.update_clock();
|
self.update_clock();
|
||||||
|
|
@ -62,32 +63,43 @@ impl App {
|
||||||
pub fn view_editor_status (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_editor_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.editor().map(|e|Bsp::s(e.clip_status(), e.edit_status()))
|
self.editor().map(|e|Bsp::s(e.clip_status(), e.edit_status()))
|
||||||
}
|
}
|
||||||
pub fn view_midi_ports_status (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_midi_ins_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.project.get_track().map(|track|Bsp::s(
|
self.project.get_track().map(|track|{
|
||||||
Fixed::xy(20, 1 + track.sequencer.midi_ins.len() as u16, FieldV(self.color,
|
let ins = track.sequencer.midi_ins.len() as u16;
|
||||||
format!("MIDI ins: "),
|
Fixed::xy(20, 1 + ins, Outer(true, Style::default().fg(Tui::g(96))).enclose(
|
||||||
|
Fixed::xy(20, 1 + ins, FieldV(self.color, format!("MIDI ins: "),
|
||||||
Map::south(1, ||track.sequencer.midi_ins.iter(),
|
Map::south(1, ||track.sequencer.midi_ins.iter(),
|
||||||
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name())))))),
|
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))
|
||||||
Fixed::xy(20, 1 + track.sequencer.midi_outs.len() as u16, FieldV(
|
})
|
||||||
self.color,
|
|
||||||
format!("MIDI outs: "),
|
|
||||||
Map::south(1, ||track.sequencer.midi_outs.iter(),
|
|
||||||
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
pub fn view_audio_ports_status (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_midi_outs_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.project.get_track().map(|track|Bsp::s(
|
self.project.get_track().map(|track|{
|
||||||
track.devices.get(0).map(|device|
|
let outs = track.sequencer.midi_outs.len() as u16;
|
||||||
Fixed::xy(20, 1 + device.audio_ins().len() as u16, FieldV(self.color,
|
Fixed::xy(20, 1 + outs, Outer(true, Style::default().fg(Tui::g(96))).enclose(
|
||||||
format!("Audio ins: "),
|
Fixed::xy(20, 1 + outs, FieldV(self.color, format!("MIDI outs: "),
|
||||||
|
Map::south(1, ||track.sequencer.midi_outs.iter(),
|
||||||
|
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn view_audio_ins_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
self.project.get_track()
|
||||||
|
.and_then(|track|track.devices.get(0))
|
||||||
|
.map(|device|{
|
||||||
|
let ins = device.audio_ins().len() as u16;
|
||||||
|
Fixed::xy(20, 1 + ins, Outer(true, Style::default().fg(Tui::g(96))).enclose(
|
||||||
|
Fixed::xy(20, 1 + ins, FieldV(self.color, format!("Audio ins: "),
|
||||||
Map::south(1, ||device.audio_ins().iter(),
|
Map::south(1, ||device.audio_ins().iter(),
|
||||||
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))),
|
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))})
|
||||||
track.devices.last().map(|device|
|
}
|
||||||
Fixed::xy(20, 1 + device.audio_outs().len() as u16, FieldV(self.color,
|
pub fn view_audio_outs_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
format!("Audio outs:"),
|
self.project.get_track()
|
||||||
|
.and_then(|track|track.devices.last())
|
||||||
|
.map(|device|{
|
||||||
|
let outs = device.audio_outs().len() as u16;
|
||||||
|
Fixed::xy(20, 1 + outs, Outer(true, Style::default().fg(Tui::g(96))).enclose(
|
||||||
|
Fixed::xy(20, 1 + outs, FieldV(self.color, format!("Audio outs: "),
|
||||||
Map::south(1, ||device.audio_outs().iter(),
|
Map::south(1, ||device.audio_outs().iter(),
|
||||||
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))),
|
|port, index|Fill::x(Align::w(format!(" {index} {}", port.name()))))))))})
|
||||||
))
|
|
||||||
}
|
}
|
||||||
pub fn view_arranger (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_arranger (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
ArrangerView::new(&self.project, self.editor.as_ref())
|
ArrangerView::new(&self.project, self.editor.as_ref())
|
||||||
|
|
@ -218,8 +230,8 @@ impl App {
|
||||||
pub fn view_pool (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_pool (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
Fixed::x(20, Bsp::s(
|
Fixed::x(20, Bsp::s(
|
||||||
Fill::x(Align::w(FieldH(self.color, "Clip pool:", ""))),
|
Fill::x(Align::w(FieldH(self.color, "Clip pool:", ""))),
|
||||||
Fill::y(Align::n(Tui::bg(Rgb(0, 0, 0), PoolView(&self.project.pool)))),
|
Fill::y(Align::n(Tui::bg(Rgb(0, 0, 0), Outer(true, Style::default().fg(Tui::g(96)))
|
||||||
))
|
.enclose(PoolView(&self.project.pool)))))))
|
||||||
}
|
}
|
||||||
pub fn view_samples_keys (&self) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_samples_keys (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.project.sampler().map(|s|s.view_list(true, self.editor().unwrap()))
|
self.project.sampler().map(|s|s.view_list(true, self.editor().unwrap()))
|
||||||
|
|
|
||||||
|
|
@ -50,20 +50,22 @@ impl Sampler {
|
||||||
|
|
||||||
#[tengri_proc::command(Sampler)]
|
#[tengri_proc::command(Sampler)]
|
||||||
impl SamplerCommand {
|
impl SamplerCommand {
|
||||||
fn record_toggle (sampler: &mut Sampler, sample: usize) -> Perhaps<Self> {
|
fn record_toggle (sampler: &mut Sampler, slot: usize) -> Perhaps<Self> {
|
||||||
if sampler.recording.is_some() {
|
let recording = sampler.recording.as_ref().map(|x|x.0);
|
||||||
Self::record_finish(sampler)
|
Self::record_finish(sampler);
|
||||||
|
// autoslice: continue recording at next slot
|
||||||
|
if recording != Some(slot) {
|
||||||
|
Self::record_begin(sampler, slot)
|
||||||
} else {
|
} else {
|
||||||
Self::record_begin(sampler, sample)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn record_begin (sampler: &mut Sampler, pitch: usize) -> Perhaps<Self> {
|
fn record_begin (sampler: &mut Sampler, slot: usize) -> Perhaps<Self> {
|
||||||
sampler.recording = Some((
|
sampler.recording = Some((
|
||||||
pitch,
|
slot,
|
||||||
Arc::new(RwLock::new(Sample::new(
|
Arc::new(RwLock::new(Sample::new(
|
||||||
"Sample", 0, 0, vec![vec![];sampler.audio_ins.len()]
|
"Sample", 0, 0, vec![vec![];sampler.audio_ins.len()]
|
||||||
)))
|
)))
|
||||||
|
|
||||||
));
|
));
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
@ -82,39 +84,39 @@ impl SamplerCommand {
|
||||||
sampler.recording = None;
|
sampler.recording = None;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn play_sample (sampler: &mut Sampler, pitch: usize) -> Perhaps<Self> {
|
fn play_sample (sampler: &mut Sampler, slot: usize) -> Perhaps<Self> {
|
||||||
if let Some(ref sample) = sampler.mapped[pitch] {
|
if let Some(ref sample) = sampler.mapped[slot] {
|
||||||
sampler.voices.write().unwrap().push(Sample::play(sample, 0, &u7::from(128)));
|
sampler.voices.write().unwrap().push(Sample::play(sample, 0, &u7::from(128)));
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
fn stop_sample (sampler: &mut Sampler, pitch: usize) -> Perhaps<Self> {
|
fn stop_sample (sampler: &mut Sampler, slot: usize) -> Perhaps<Self> {
|
||||||
todo!();
|
todo!();
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
//fn select (&self, state: &mut Sampler, i: usize) -> Option<Self> {
|
//fn select (&self, state: &mut Sampler, i: usize) -> Option<Self> {
|
||||||
//Self::Select(state.set_note_pos(i))
|
//Self::Select(state.set_note_pos(i))
|
||||||
//}
|
//}
|
||||||
///// Assign sample to pitch
|
///// Assign sample to slot
|
||||||
//fn set (&self, pitch: u7, sample: Option<Arc<RwLock<Sample>>>) -> Option<Self> {
|
//fn set (&self, slot: u7, sample: Option<Arc<RwLock<Sample>>>) -> Option<Self> {
|
||||||
//let i = pitch.as_int() as usize;
|
//let i = slot.as_int() as usize;
|
||||||
//let old = self.mapped[i].clone();
|
//let old = self.mapped[i].clone();
|
||||||
//self.mapped[i] = sample;
|
//self.mapped[i] = sample;
|
||||||
//Some(Self::Set(old))
|
//Some(Self::Set(old))
|
||||||
//}
|
//}
|
||||||
//fn set_start (&self, state: &mut Sampler, pitch: u7, frame: usize) -> Option<Self> {
|
//fn set_start (&self, state: &mut Sampler, slot: u7, frame: usize) -> Option<Self> {
|
||||||
//todo!()
|
//todo!()
|
||||||
//}
|
//}
|
||||||
//fn set_gain (&self, state: &mut Sampler, pitch: u7, g: f32) -> Option<Self> {
|
//fn set_gain (&self, state: &mut Sampler, slot: u7, g: f32) -> Option<Self> {
|
||||||
//todo!()
|
//todo!()
|
||||||
//}
|
//}
|
||||||
//fn note_on (&self, state: &mut Sampler, pitch: u7, v: u7) -> Option<Self> {
|
//fn note_on (&self, state: &mut Sampler, slot: u7, v: u7) -> Option<Self> {
|
||||||
//todo!()
|
//todo!()
|
||||||
//}
|
//}
|
||||||
//fn note_off (&self, state: &mut Sampler, pitch: u7) -> Option<Self> {
|
//fn note_off (&self, state: &mut Sampler, slot: u7) -> Option<Self> {
|
||||||
//todo!()
|
//todo!()
|
||||||
//}
|
//}
|
||||||
//fn set_sample (&self, state: &mut Sampler, pitch: u7, s: Option<Arc<RwLock<Sample>>>) -> Option<Self> {
|
//fn set_sample (&self, state: &mut Sampler, slot: u7, s: Option<Arc<RwLock<Sample>>>) -> Option<Self> {
|
||||||
//Some(Self::SetSample(p, state.set_sample(p, s)))
|
//Some(Self::SetSample(p, state.set_sample(p, s)))
|
||||||
//}
|
//}
|
||||||
//fn import (&self, state: &mut Sampler, c: FileBrowserCommand) -> Option<Self> {
|
//fn import (&self, state: &mut Sampler, c: FileBrowserCommand) -> Option<Self> {
|
||||||
|
|
@ -169,9 +171,9 @@ impl SamplerCommand {
|
||||||
////("set/gain" [i: u7, g: f32]
|
////("set/gain" [i: u7, g: f32]
|
||||||
////Some(Self::SetGain(i.expect("no index"), g.expect("no gain"))))
|
////Some(Self::SetGain(i.expect("no index"), g.expect("no gain"))))
|
||||||
////("note/on" [p: u7, v: u7]
|
////("note/on" [p: u7, v: u7]
|
||||||
////Some(Self::NoteOn(p.expect("no pitch"), v.expect("no velocity"))))
|
////Some(Self::NoteOn(p.expect("no slot"), v.expect("no velocity"))))
|
||||||
////("note/off" [p: u7]
|
////("note/off" [p: u7]
|
||||||
////Some(Self::NoteOff(p.expect("no pitch"))))));
|
////Some(Self::NoteOff(p.expect("no slot"))))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tengri_proc::command(Sampler)]
|
#[tengri_proc::command(Sampler)]
|
||||||
|
|
|
||||||
|
|
@ -119,13 +119,13 @@ impl Sampler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_sample_status (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
pub fn view_sample_status (&self, note_pt: usize) -> impl Content<TuiOut> + use<'_> {
|
||||||
Fixed::x(20, draw_info_v(if let Some((_, sample)) = &self.recording {
|
Fixed::x(20, Outer(true, Style::default().fg(Tui::g(96))).enclose(draw_info_v(if let Some((_, sample)) = &self.recording {
|
||||||
Some(sample)
|
Some(sample)
|
||||||
} else if let Some(sample) = &self.mapped[note_pt] {
|
} else if let Some(sample) = &self.mapped[note_pt] {
|
||||||
Some(sample)
|
Some(sample)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_status (&self, index: usize) -> impl Content<TuiOut> {
|
pub fn view_status (&self, index: usize) -> impl Content<TuiOut> {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue