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

@ -2,174 +2,37 @@ extern crate clap;
extern crate jack;
extern crate crossterm;
use clap::{Parser, Subcommand};
use clap::{Parser};
use std::error::Error;
pub mod cli;
pub mod device;
pub mod prelude;
pub mod engine;
pub mod render;
pub mod config;
pub mod layout;
use crate::prelude::*;
use crate::render::ActionBar;
use crate::device::{Chain, Sequencer, Sampler, Plugin, Mixer, Transport};
use crate::layout::{Rows, Columns};
fn main () -> Result<(), Box<dyn Error>> {
let cli = cli::Cli::parse();
let xdg = microxdg::XdgApp::new("dawdle")?;
crate::config::create_dirs(&xdg)?;
let mut engine = crate::engine::Engine::new(None)?;
match cli.command {
Some(cli::Command::Transport) => engine.run(
crate::device::transport::Transport::new(engine.jack_client.as_client())?,
),
Some(cli::Command::Mixer) => engine.run(
crate::device::mixer::Mixer::new()?,
),
Some(cli::Command::Looper) => engine.run(
crate::device::looper::Looper::new()?,
),
Some(cli::Command::Sampler) => engine.run(
crate::device::sampler::Sampler::new()?,
),
Some(cli::Command::Sequencer { inputs, outputs }) => {
engine.run(crate::device::sequencer::Sequencer::new(
Some("Sequencer"),
Some(&inputs.into_iter().map(|x|x.unwrap()).collect::<Vec<_>>()),
Some(&outputs.into_iter().map(|x|x.unwrap()).collect::<Vec<_>>()),
)?)
},
None => engine.run(App {
exited: false,
mode: Mode::Sequencer,
transport: crate::device::transport::Transport::new(
engine.jack_client.as_client()
)?,
focus: 0,
devices: vec![
crate::device::Device::Sequencer(
crate::device::sequencer::Sequencer::new(
Some("Melody#000"),
None,
None
)?
),
//crate::device::Device::Sequencer(
//crate::device::sequencer::Sequencer::new(
//Some("Rhythm#000"),
//None,
//None,
//)?
//),
//crate::device::Device::Mixer(
//crate::device::mixer::Mixer::new()?
//),
//crate::device::Device::Sampler(
//crate::device::sampler::Sampler::new()?
//),
//crate::device::Device::Looper(
//crate::device::looper::Looper::new()?
//),
]
})
}
}
struct App {
exited: bool,
mode: Mode,
transport: crate::device::transport::Transport,
focus: usize,
devices: Vec<crate::device::Device>,
}
#[derive(PartialEq)]
enum Mode {
Transport,
Mixer,
Looper,
Sampler,
Sequencer
}
impl Exitable for App {
fn exit (&mut self) {
self.exited = true
}
fn exited (&self) -> bool {
self.exited
}
}
impl WidgetRef for App {
fn render_ref (&self, area: Rect, buffer: &mut Buffer) {
use ratatui::style::Stylize;
let mut constraints = vec![
Constraint::Max(40),
Constraint::Max(40),
];
let areas = Layout::default()
.direction(Direction::Horizontal)
.constraints(&constraints)
.split(Rect {
x: area.x,
y: area.y,
width: area.width,
height: area.height - 4
});
self.transport.render(Rect {
x: area.width.saturating_sub(80u16) / 2,
y: area.y + area.height - 4,
width: area.width,
height: 4
}, buffer);
for (index, device) in self.devices.iter().enumerate() {
device.render(areas[index], buffer);
if index == self.focus {
draw_focus_corners(buffer, areas[index]);
}
}
}
}
impl HandleInput for App {
fn handle (&mut self, event: &Event) -> Result<(), Box<dyn Error>> {
//println!("{event:?}");
if let Event::Input(crossterm::event::Event::Key(key)) = event {
match key.code {
KeyCode::Char('c') => {
if key.modifiers == KeyModifiers::CONTROL {
self.exit();
}
},
KeyCode::Char(' ') => {
if key.modifiers == KeyModifiers::SHIFT {
self.transport.play_from_start_or_stop_and_rewind();
} else {
self.transport.play_or_pause().unwrap();
}
},
KeyCode::Tab => {
self.focus = self.focus + 1;
if self.focus >= self.devices.len() {
self.focus = 0;
}
},
KeyCode::BackTab => {
if self.focus == 0 {
self.focus = self.devices.len() - 1;
} else {
self.focus = self.focus - 1;
}
},
_ => {
self.devices[self.focus].handle(&event)?
}
}
}
Ok(())
}
crate::device::run(Rows(vec![
Box::new(Columns(vec![
Box::new(Chain::new("Chain#00", vec![
Box::new(Sequencer::new("Rhythm#000")?),
Box::new(Sampler::new("Sampler#00")?),
])?),
Box::new(Chain::new("Chain#01", vec![
Box::new(Sequencer::new("Melody#000")?),
Box::new(Plugin::new("Plugin#000")?),
])?),
Box::new(Chain::new("Chain#02", vec![])?),
Box::new(Chain::new("Chain#03", vec![])?),
])),
Box::new(Mixer::new("Mixer#00")?),
Box::new(Transport::new(vec![])?),
]))
}