refactor: device abstraction, layout components

This commit is contained in:
🪞👃🪞 2024-06-12 16:55:57 +03:00
parent d330d31ce4
commit 788dc1ccde
21 changed files with 1144 additions and 1166 deletions

View file

@ -6,20 +6,17 @@ pub const ACTIONS: [(&'static str, &'static str);2] = [
];
pub struct Sampler {
exited: Arc<AtomicBool>,
jack: Jack<Notifications>,
name: String,
jack: Jack<self::Notifications>,
samples: Arc<Mutex<Vec<Sample>>>,
selected_sample: usize,
selected_column: usize,
}
impl Sampler {
pub fn new () -> Result<Self, Box<dyn Error>> {
pub fn new (name: &str) -> Result<DynamicDevice<Self>, Box<dyn Error>> {
let exited = Arc::new(AtomicBool::new(false));
let (client, status) = Client::new(
"Sampler#000",
ClientOptions::NO_START_SERVER
)?;
let (client, status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
let samples = vec![
Sample::new("Kick", &client, 1, 35)?,
Sample::new("Snare", &client, 1, 38)?,
@ -64,8 +61,8 @@ impl Sampler {
Control::Continue
})
});
Ok(Self {
exited,
Ok(DynamicDevice::new(render, handle, |_|{}, Self {
name: name.into(),
selected_sample: 0,
selected_column: 0,
samples,
@ -73,7 +70,7 @@ impl Sampler {
self::Notifications,
ClosureProcessHandler::new(handler)
)?,
})
}))
}
}
@ -109,131 +106,97 @@ impl Sample {
}
impl Exitable for Sampler {
fn exit (&mut self) {
self.exited.store(true, Ordering::Relaxed)
}
fn exited (&self) -> bool {
self.exited.fetch_and(true, Ordering::Relaxed)
}
pub fn render (state: &Sampler, buf: &mut Buffer, area: Rect) {
//render_table(state, stdout, offset)?;
//render_meters(state, stdout, offset)?;
}
impl WidgetRef for Sampler {
fn render_ref (&self, area: Rect, buf: &mut Buffer) {
}
}
//fn render_table (
//state: &mut Sampler,
//stdout: &mut Stdout,
//offset: (u16, u16),
//) -> Result<(), Box<dyn Error>> {
//let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
//stdout.queue(move_to(0, 3))?.queue(
//Print(" Name Rate Trigger Route")
//)?;
//for (i, sample) in state.samples.lock().unwrap().iter().enumerate() {
//let row = 4 + i as u16;
//for (j, (column, field)) in [
//(0, format!(" {:7} ", sample.name)),
//(9, format!(" {:.1}Hz ", sample.rate)),
//(18, format!(" MIDI C{} {} ", sample.trigger.0, sample.trigger.1)),
//(33, format!(" {:.1}dB -> Output ", sample.gain)),
//(50, format!(" {} ", sample.playing.unwrap_or(0))),
//].into_iter().enumerate() {
//stdout.queue(move_to(column, row))?;
//if state.selected_sample == i && state.selected_column == j {
//stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?;
//} else {
//stdout.queue(PrintStyledContent(field.to_string().bold()))?;
//}
//}
//}
//Ok(())
//}
pub fn render (
state: &mut Sampler,
stdout: &mut Stdout,
offset: (u16, u16),
) -> Result<(), Box<dyn Error>> {
render_table(state, stdout, offset)?;
render_meters(state, stdout, offset)?;
//fn render_meters (
//state: &mut Sampler,
//stdout: &mut Stdout,
//offset: (u16, u16),
//) -> Result<(), Box<dyn Error>> {
//let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
//for (i, sample) in state.samples.lock().iter().enumerate() {
//let row = 4 + i as u16;
//stdout.queue(move_to(32, row))?.queue(
//PrintStyledContent("▁".green())
//)?;
//}
//Ok(())
//}
pub fn handle (state: &mut Sampler, event: &EngineEvent) -> Result<(), Box<dyn Error>> {
//if let Event::Input(crossterm::event::Event::Key(event)) = event {
//match event.code {
//KeyCode::Char('c') => {
//if event.modifiers == KeyModifiers::CONTROL {
//state.exit();
//}
//},
//KeyCode::Down => {
//state.selected_sample = (state.selected_sample + 1) % state.samples.lock().unwrap().len();
//println!("{}", state.selected_sample);
//},
//KeyCode::Up => {
//if state.selected_sample == 0 {
//state.selected_sample = state.samples.lock().unwrap().len() - 1;
//} else {
//state.selected_sample = state.selected_sample - 1;
//}
//println!("{}", state.selected_sample);
//},
//KeyCode::Left => {
//if state.selected_column == 0 {
//state.selected_column = 6
//} else {
//state.selected_column = state.selected_column - 1;
//}
//},
//KeyCode::Right => {
//if state.selected_column == 6 {
//state.selected_column = 0
//} else {
//state.selected_column = state.selected_column + 1;
//}
//},
//_ => {
//println!("{event:?}");
//}
//}
//}
Ok(())
}
fn render_table (
state: &mut Sampler,
stdout: &mut Stdout,
offset: (u16, u16),
) -> Result<(), Box<dyn Error>> {
let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
stdout.queue(move_to(0, 3))?.queue(
Print(" Name Rate Trigger Route")
)?;
for (i, sample) in state.samples.lock().unwrap().iter().enumerate() {
let row = 4 + i as u16;
for (j, (column, field)) in [
(0, format!(" {:7} ", sample.name)),
(9, format!(" {:.1}Hz ", sample.rate)),
(18, format!(" MIDI C{} {} ", sample.trigger.0, sample.trigger.1)),
(33, format!(" {:.1}dB -> Output ", sample.gain)),
(50, format!(" {} ", sample.playing.unwrap_or(0))),
].into_iter().enumerate() {
stdout.queue(move_to(column, row))?;
if state.selected_sample == i && state.selected_column == j {
stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?;
} else {
stdout.queue(PrintStyledContent(field.to_string().bold()))?;
}
}
}
Ok(())
}
fn render_meters (
state: &mut Sampler,
stdout: &mut Stdout,
offset: (u16, u16),
) -> Result<(), Box<dyn Error>> {
let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
for (i, sample) in state.samples.lock().iter().enumerate() {
let row = 4 + i as u16;
stdout.queue(move_to(32, row))?.queue(
PrintStyledContent("".green())
)?;
}
Ok(())
}
impl HandleInput for Sampler {
fn handle (&mut self, event: &Event) -> Result<(), Box<dyn Error>> {
handle(self, event)
}
}
pub fn handle (
state: &mut Sampler,
event: &Event
) -> Result<(), Box<dyn Error>> {
if let Event::Input(crossterm::event::Event::Key(event)) = event {
match event.code {
KeyCode::Char('c') => {
if event.modifiers == KeyModifiers::CONTROL {
state.exit();
}
},
KeyCode::Down => {
state.selected_sample = (state.selected_sample + 1) % state.samples.lock().unwrap().len();
println!("{}", state.selected_sample);
},
KeyCode::Up => {
if state.selected_sample == 0 {
state.selected_sample = state.samples.lock().unwrap().len() - 1;
} else {
state.selected_sample = state.selected_sample - 1;
}
println!("{}", state.selected_sample);
},
KeyCode::Left => {
if state.selected_column == 0 {
state.selected_column = 6
} else {
state.selected_column = state.selected_column - 1;
}
},
KeyCode::Right => {
if state.selected_column == 6 {
state.selected_column = 0
} else {
state.selected_column = state.selected_column + 1;
}
},
_ => {
println!("{event:?}");
}
}
}
Ok(())
}
pub struct Notifications;
impl NotificationHandler for Notifications {