mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
groovebox: looks surprisingly well
This commit is contained in:
parent
c66a006120
commit
03024f8a14
11 changed files with 130 additions and 91 deletions
|
|
@ -1,19 +1,33 @@
|
|||
use crate::*;
|
||||
|
||||
content!(TuiOut: |self: Browser| /*Stack::down(|add|{
|
||||
let mut i = 0;
|
||||
for (_, name) in self.dirs.iter() {
|
||||
if i >= self.scroll {
|
||||
add(&Tui::bold(i == self.index, name.as_str()))?;
|
||||
content!(TuiOut: |self: Browser|Map::south(1, ||EntriesIterator {
|
||||
offset: 0,
|
||||
index: 0,
|
||||
length: self.dirs.len() + self.files.len(),
|
||||
browser: self,
|
||||
}, |entry, index|Fill::x(Align::w(entry))));
|
||||
|
||||
struct EntriesIterator<'a> {
|
||||
browser: &'a Browser,
|
||||
offset: usize,
|
||||
length: usize,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for EntriesIterator<'a> {
|
||||
type Item = Modify<&'a str>;
|
||||
fn next (&mut self) -> Option<Self::Item> {
|
||||
let dirs = self.browser.dirs.len();
|
||||
let files = self.browser.files.len();
|
||||
let index = self.index;
|
||||
if self.index < dirs {
|
||||
self.index += 1;
|
||||
Some(Tui::bold(true, self.browser.dirs[index].1.as_str()))
|
||||
} else if self.index < dirs + files {
|
||||
self.index += 1;
|
||||
Some(Tui::bold(false, self.browser.files[index - dirs].1.as_str()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
for (_, name) in self.files.iter() {
|
||||
if i >= self.scroll {
|
||||
add(&Tui::bold(i == self.index, name.as_str()))?;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
add(&format!("{}/{i}", self.index))?;
|
||||
Ok(())
|
||||
})*/"todo");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,30 @@ impl Device {
|
|||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
pub fn midi_ins (&self) -> &[JackMidiIn] {
|
||||
match self {
|
||||
//Self::Sampler(Sampler { midi_in, .. }) => &[midi_in],
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn midi_outs (&self) -> &[JackMidiOut] {
|
||||
match self {
|
||||
Self::Sampler(_) => &[],
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn audio_ins (&self) -> &[JackAudioIn] {
|
||||
match self {
|
||||
Self::Sampler(Sampler { audio_ins, .. }) => audio_ins.as_slice(),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
pub fn audio_outs (&self) -> &[JackAudioOut] {
|
||||
match self {
|
||||
Self::Sampler(Sampler { audio_outs, .. }) => audio_outs.as_slice(),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DeviceAudio<'a>(pub &'a mut Device);
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@ impl MidiEditor {
|
|||
let note_name = format!("{:4}", Note::pitch_to_name(note_pos));
|
||||
let note_pos = format!("{:>3}", note_pos);
|
||||
let note_len = format!("{:>4}", self.get_note_len());
|
||||
Fixed::x(20, Bsp::s(
|
||||
Fill::x(Align::w(FieldH(color, "Time", format!("{length}/{time_zoom}+{time_pos} {time_lock}")))),
|
||||
Fixed::x(20, col!(
|
||||
Fill::x(Align::w(FieldH(color, "Time", format!("{length}/{time_zoom}+{time_pos}")))),
|
||||
Fill::x(Align::w(FieldH(color, "Lock", format!("{time_lock}")))),
|
||||
Fill::x(Align::w(FieldH(color, "Note", format!("{note_name} {note_pos} {note_len}")))),
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#![feature(let_chains)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
pub(crate) use std::cmp::Ord;
|
||||
pub(crate) use std::fmt::{Debug, Formatter};
|
||||
|
|
|
|||
|
|
@ -7,20 +7,18 @@ impl Sampler {
|
|||
/// Create [Voice]s from [Sample]s in response to MIDI input.
|
||||
pub fn process_midi_in (&mut self, scope: &ProcessScope) {
|
||||
let Sampler { midi_in, mapped, voices, .. } = self;
|
||||
if let Some(ref midi_in) = midi_in {
|
||||
for RawMidi { time, bytes } in midi_in.port().iter(scope) {
|
||||
if let LiveEvent::Midi { message, .. } = LiveEvent::parse(bytes).unwrap() {
|
||||
match message {
|
||||
MidiMessage::NoteOn { ref key, ref vel } => {
|
||||
if let Some(ref sample) = mapped[key.as_int() as usize] {
|
||||
voices.write().unwrap().push(Sample::play(sample, time as usize, vel));
|
||||
}
|
||||
},
|
||||
MidiMessage::Controller { controller: _, value: _ } => {
|
||||
// TODO
|
||||
for RawMidi { time, bytes } in midi_in.port().iter(scope) {
|
||||
if let LiveEvent::Midi { message, .. } = LiveEvent::parse(bytes).unwrap() {
|
||||
match message {
|
||||
MidiMessage::NoteOn { ref key, ref vel } => {
|
||||
if let Some(ref sample) = mapped[key.as_int() as usize] {
|
||||
voices.write().unwrap().push(Sample::play(sample, time as usize, vel));
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
MidiMessage::Controller { controller: _, value: _ } => {
|
||||
// TODO
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub struct Sampler {
|
|||
/// Sample currently being edited.
|
||||
pub editing: Option<Arc<RwLock<Sample>>>,
|
||||
/// MIDI input port. Triggers sample playback.
|
||||
pub midi_in: Option<JackMidiIn>,
|
||||
pub midi_in: JackMidiIn,
|
||||
/// Collection of currently playing instances of samples.
|
||||
pub voices: Arc<RwLock<Vec<Voice>>>,
|
||||
/// Audio output ports. Voices get played here.
|
||||
|
|
@ -47,15 +47,28 @@ pub struct Sampler {
|
|||
pub cursor: (AtomicUsize, AtomicUsize),
|
||||
}
|
||||
|
||||
impl Default for Sampler {
|
||||
fn default () -> Self {
|
||||
Self {
|
||||
midi_in: None,
|
||||
audio_ins: vec![],
|
||||
impl Sampler {
|
||||
pub fn new (
|
||||
jack: &Jack,
|
||||
name: impl AsRef<str>,
|
||||
midi_from: &[PortConnect],
|
||||
audio_from: &[&[PortConnect];2],
|
||||
audio_to: &[&[PortConnect];2],
|
||||
) -> Usually<Self> {
|
||||
let name = name.as_ref();
|
||||
Ok(Self {
|
||||
name: name.into(),
|
||||
midi_in: JackMidiIn::new(jack, format!("M/{name}"), midi_from)?,
|
||||
audio_ins: vec![
|
||||
JackAudioIn::new(jack, &format!("L/{name}"), audio_from[0])?,
|
||||
JackAudioIn::new(jack, &format!("R/{name}"), audio_from[1])?,
|
||||
],
|
||||
audio_outs: vec![
|
||||
JackAudioOut::new(jack, &format!("{name}/L"), audio_to[0])?,
|
||||
JackAudioOut::new(jack, &format!("{name}/R"), audio_to[1])?,
|
||||
],
|
||||
input_meters: vec![0.0;2],
|
||||
output_meters: vec![0.0;2],
|
||||
audio_outs: vec![],
|
||||
name: "tek_sampler".into(),
|
||||
mapped: [const { None };128],
|
||||
unmapped: vec![],
|
||||
voices: Arc::new(RwLock::new(vec![])),
|
||||
|
|
@ -71,31 +84,6 @@ impl Default for Sampler {
|
|||
color: Default::default(),
|
||||
mixing_mode: Default::default(),
|
||||
metering_mode: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Sampler {
|
||||
pub fn new (
|
||||
jack: &Jack,
|
||||
name: impl AsRef<str>,
|
||||
midi_from: &[PortConnect],
|
||||
audio_from: &[&[PortConnect];2],
|
||||
audio_to: &[&[PortConnect];2],
|
||||
) -> Usually<Self> {
|
||||
let name = name.as_ref();
|
||||
Ok(Self {
|
||||
name: name.into(),
|
||||
midi_in: Some(JackMidiIn::new(jack, format!("M/{name}"), midi_from)?),
|
||||
audio_ins: vec![
|
||||
JackAudioIn::new(jack, &format!("L/{name}"), audio_from[0])?,
|
||||
JackAudioIn::new(jack, &format!("R/{name}"), audio_from[1])?,
|
||||
],
|
||||
audio_outs: vec![
|
||||
JackAudioOut::new(jack, &format!("{name}/L"), audio_to[0])?,
|
||||
JackAudioOut::new(jack, &format!("{name}/R"), audio_to[1])?,
|
||||
],
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
/// Value of cursor
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue