switch toolbar actions; bold borders and titles

This commit is contained in:
🪞👃🪞 2024-05-29 13:34:36 +03:00
parent 7dd5f7f488
commit 31f8ec5362
8 changed files with 103 additions and 116 deletions

View file

@ -78,9 +78,6 @@ fn run_one (command: &cli::Command) -> Result<(), Box<dyn Error>> {
fn run_all () -> Result<(), Box<dyn Error>> {
let mut actions = vec![];
actions.extend_from_slice(&transport::ACTIONS);
actions.extend_from_slice(&mixer::ACTIONS);
actions.extend_from_slice(&looper::ACTIONS);
main_loop(
&mut App {
exited: false,
@ -92,23 +89,38 @@ fn run_all () -> Result<(), Box<dyn Error>> {
sequencer: sequencer::Sequencer::new()?,
},
|state, stdout, mut offset| {
actions.clear();
actions.extend_from_slice(&transport::ACTIONS);
match state.mode {
Mode::Transport => {},
Mode::Mixer => actions.extend_from_slice(&mixer::ACTIONS),
Mode::Looper => actions.extend_from_slice(&looper::ACTIONS),
Mode::Sampler => actions.extend_from_slice(&sampler::ACTIONS),
Mode::Sequencer => actions.extend_from_slice(&sequencer::ACTIONS),
}
let (w, h) = render::render_toolbar_vertical(stdout, (offset.0, offset.1 + 1), &actions)?;
offset.0 = offset.0 + w + 1;
transport::render(&mut state.transport, stdout, (offset.0 + 1, 1))?;
render::render_box(stdout, offset.0, 0, 64, 4,
render::render_box(stdout, Some("Transport"), offset.0, 0, 70, 4,
state.mode == Mode::Transport)?;
mixer::render(&mut state.mixer, stdout, (offset.0 + 1, 6))?;
render::render_box(stdout, offset.0, 5, 64, 9,
render::render_box(stdout, Some("Mixer"), offset.0, 5, 70, 9,
state.mode == Mode::Mixer)?;
looper::render(&mut state.looper, stdout, (offset.0 + 1, 16))?;
render::render_box(stdout, offset.0, 15, 64, 6,
render::render_box(stdout, Some("Looper"), offset.0, 15, 70, 6,
state.mode == Mode::Looper)?;
//sampler::render(sampler, stdout, (1, 46))?;
//sequencer::render(sequencer, stdout, (1, 66))?;
sampler::render(&mut state.sampler, stdout, (offset.0 + 1, 20))?;
render::render_box(stdout, Some("Sampler"), offset.0, 22, 70, 4,
state.mode == Mode::Sampler)?;
sequencer::render(&mut state.sequencer, stdout, (offset.0 + 1, 25))?;
render::render_box(stdout, Some("Sequencer"), offset.0, 27, 70, 6,
state.mode == Mode::Sequencer)?;
Ok(())
},
|state, event| {
@ -122,11 +134,15 @@ fn run_all () -> Result<(), Box<dyn Error>> {
KeyCode::Tab => match state.mode {
Mode::Transport => state.mode = Mode::Mixer,
Mode::Mixer => state.mode = Mode::Looper,
Mode::Looper => state.mode = Mode::Transport,
Mode::Looper => state.mode = Mode::Sampler,
Mode::Sampler => state.mode = Mode::Sequencer,
Mode::Sequencer => state.mode = Mode::Transport,
_ => {}
},
KeyCode::BackTab => match state.mode {
Mode::Transport => state.mode = Mode::Looper,
Mode::Transport => state.mode = Mode::Sequencer,
Mode::Sequencer => state.mode = Mode::Sampler,
Mode::Sampler => state.mode = Mode::Looper,
Mode::Looper => state.mode = Mode::Mixer,
Mode::Mixer => state.mode = Mode::Transport,
_ => {}
@ -141,7 +157,12 @@ fn run_all () -> Result<(), Box<dyn Error>> {
Mode::Looper => looper::handle(
&mut state.looper, event
)?,
_ => {},
Mode::Sampler => sampler::handle(
&mut state.sampler, event
)?,
Mode::Sequencer => sequencer::handle(
&mut state.sequencer, event
)?,
}
}
}
@ -205,6 +226,7 @@ pub fn main_loop <T: Exitable> (
});
stdout.queue(Clear(ClearType::All))?.queue(Hide)?.flush()?;
loop {
stdout.queue(Clear(ClearType::All))?;
render(state, &mut stdout, (0, 0))?;
stdout.flush()?;
handle(state, &input.recv()?)?;

View file

@ -22,28 +22,39 @@ pub fn render_toolbar_vertical (
pub fn render_box (
stdout: &mut std::io::Stdout,
title: Option<&str>,
x: u16,
y: u16,
w: u16,
mut w: u16,
h: u16,
active: bool
) -> Result<(), Box<dyn Error>> {
let edge: String = std::iter::repeat("").take(w.saturating_sub(2) as usize).collect();
if let Some(title) = title {
w = u16::max(w, title.len() as u16 + 4);
}
let back: String = std::iter::repeat(" ").take(w.saturating_sub(2) as usize).collect();
if active {
stdout.queue(MoveTo(x, y))?.queue(PrintStyledContent(format!("{edge}").bold().yellow()))?;
for row in y+1..y+h {
stdout.queue(MoveTo(x, row))?.queue(PrintStyledContent("".bold().yellow()))?;
stdout.queue(MoveTo(x+w-1, row))?.queue(PrintStyledContent("".bold().yellow()))?;
let edge: String = std::iter::repeat("").take(w.saturating_sub(2) as usize).collect();
stdout.queue(MoveTo(x, y))?.queue(PrintStyledContent(format!("{edge}").bold().yellow()))?;
if let Some(title) = title {
stdout.queue(MoveTo(x+1, y))?.queue(PrintStyledContent(format!(" {title} ").bold().yellow()))?;
}
stdout.queue(MoveTo(x, y+h))?.queue(PrintStyledContent(format!("{edge}").bold().yellow()))?;
for row in y+1..y+h {
stdout.queue(MoveTo(x, row))?.queue(PrintStyledContent("".bold().yellow()))?;
stdout.queue(MoveTo(x+w-1, row))?.queue(PrintStyledContent("".bold().yellow()))?;
}
stdout.queue(MoveTo(x, y+h))?.queue(PrintStyledContent(format!("{edge}").bold().yellow()))?;
} else {
stdout.queue(MoveTo(x, y))?.queue(Print(&format!("{edge}")))?;
for row in y+1..y+h {
stdout.queue(MoveTo(x, row))?.queue(Print(""))?;
stdout.queue(MoveTo(x+w-1, row))?.queue(Print(""))?;
let edge: String = std::iter::repeat("").take(w.saturating_sub(2) as usize).collect();
stdout.queue(MoveTo(x, y))?.queue(PrintStyledContent(format!("{edge}").grey().dim()))?;
if let Some(title) = title {
stdout.queue(MoveTo(x+1, y))?.queue(Print(format!(" {title} ")))?;
}
stdout.queue(MoveTo(x, y+h))?.queue(Print(&format!("{edge}")))?;
for row in y+1..y+h {
stdout.queue(MoveTo(x, row))?.queue(PrintStyledContent("".grey().dim()))?;
stdout.queue(MoveTo(x+w-1, row))?.queue(PrintStyledContent("".grey().dim()))?;
}
stdout.queue(MoveTo(x, y+h))?.queue(PrintStyledContent(format!("{edge}").grey().dim()))?;
}
Ok(())
}

View file

@ -6,7 +6,10 @@ pub use self::jack::*;
pub use self::render::*;
use crate::prelude::*;
pub const ACTIONS: [(&'static str, &'static str);0] = [];
pub const ACTIONS: [(&'static str, &'static str);2] = [
("Enter", "Play sample"),
("Ins/Del", "Add/remove sample"),
];
pub struct Sampler {
exited: bool,

View file

@ -3,7 +3,7 @@ use super::Sampler;
pub fn handle (
state: &mut Sampler,
event: crossterm::event::Event
event: &Event
) -> Result<(), Box<dyn Error>> {
use crossterm::event::{Event, KeyCode, KeyModifiers};
if let Event::Key(event) = event {

View file

@ -6,45 +6,21 @@ pub fn render (
stdout: &mut Stdout,
offset: (u16, u16),
) -> Result<(), Box<dyn Error>> {
render_toolbar(state, stdout, offset)?;
render_table(state, stdout, offset)?;
render_meters(state, stdout, offset)?;
stdout.flush()?;
Ok(())
}
fn render_toolbar (
state: &mut Sampler,
stdout: &mut Stdout,
offset: (u16, u16),
) -> Result<(), Box<dyn Error>> {
stdout
.queue(cursor::MoveTo(1, 0))?
.queue(PrintStyledContent("Arrows".yellow().bold()))?
.queue(cursor::MoveTo(1, 1))?
.queue(PrintStyledContent("Navigate".yellow()))?
.queue(cursor::MoveTo(11, 0))?
.queue(PrintStyledContent("Enter".yellow().bold()))?
.queue(cursor::MoveTo(11, 1))?
.queue(PrintStyledContent("Play sample".yellow()))?
.queue(cursor::MoveTo(24, 0))?
.queue(PrintStyledContent("Ins/Del".yellow().bold()))?
.queue(cursor::MoveTo(24, 1))?
.queue(PrintStyledContent("Add/remove sample".yellow()))?;
Ok(())
}
fn render_table (
state: &mut Sampler,
stdout: &mut Stdout,
offset: (u16, u16),
) -> Result<(), Box<dyn Error>> {
stdout
.queue(cursor::MoveTo(0, 3))?
.queue(Print(
" Name Rate Trigger Route"))?;
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.iter().enumerate() {
let row = 4 + i as u16;
for (j, (column, field)) in [
@ -53,7 +29,7 @@ fn render_table (
(18, format!(" MIDI C10 36 ")),
(33, format!(" {:.1}dB -> Output ", sample.gain)),
].into_iter().enumerate() {
stdout.queue(cursor::MoveTo(column, row))?;
stdout.queue(move_to(column, row))?;
if state.selected_sample == i && state.selected_column == j {
stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?;
} else {
@ -69,11 +45,12 @@ fn render_meters (
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.iter().enumerate() {
let row = 4 + i as u16;
stdout
.queue(cursor::MoveTo(32, row))?
.queue(PrintStyledContent("".green()))?;
stdout.queue(move_to(32, row))?.queue(
PrintStyledContent("".green())
)?;
}
Ok(())
}

View file

@ -6,13 +6,18 @@ pub use self::jack::*;
pub use self::render::*;
use crate::prelude::*;
pub const ACTIONS: [(&'static str, &'static str);0] = [];
pub const ACTIONS: [(&'static str, &'static str);4] = [
("+/-", "Zoom"),
("A/D", "Add/delete note"),
("]/[", "Duration"),
("CapsLock", "Auto advance"),
];
pub struct Sequencer {
exited: bool,
jack: Jack<Notifications>,
cursor: (u16, u16),
duration: u16,
cursor: (u16, u16, u16),
sequence: Vec<()>,
}
impl Sequencer {
@ -30,10 +35,10 @@ impl Sequencer {
)
)?;
Ok(Self {
exited: false,
cursor: (0, 0),
duration: 0,
exited: false,
cursor: (0, 0, 0),
jack,
sequence: vec![],
})
}
}

View file

@ -1,12 +1,10 @@
use crate::prelude::*;
use super::Sequencer;
fn handle (
state: &mut Sequencer,
event: crossterm::event::Event
) -> Result<(), Box<dyn Error>> {
use crossterm::event::{Event, KeyCode, KeyModifiers};
pub fn handle (state: &mut Sequencer,event: &Event) -> Result<(), Box<dyn Error>> {
if let Event::Key(event) = event {
match event.code {
KeyCode::Char('c') => {
if event.modifiers == KeyModifiers::CONTROL {
@ -14,12 +12,12 @@ fn handle (
}
},
KeyCode::Char('[') => {
if state.duration > 0 {
state.duration = state.duration - 1
if state.cursor.2 > 0 {
state.cursor.2 = state.cursor.2 - 1
}
},
KeyCode::Char(']') => {
state.duration = state.duration + 1
state.cursor.2 = state.cursor.2 + 1
},
KeyCode::Down => {
state.cursor.1 = if state.cursor.1 >= 3 {
@ -49,10 +47,13 @@ fn handle (
state.cursor.0 + 1
}
},
KeyCode::Char('A') => {
},
_ => {
println!("{event:?}");
}
}
}
Ok(())
}

View file

@ -6,68 +6,36 @@ pub fn render (
stdout: &mut Stdout,
offset: (u16, u16)
) -> Result<(), Box<dyn Error>> {
render_toolbar(state, stdout, offset)?;
//render_toolbar(state, stdout, offset)?;
render_grid(state, stdout, offset)?;
render_events(state, stdout, offset)?;
Ok(())
}
fn render_toolbar (
state: &mut Sequencer,
stdout: &mut Stdout,
offset: (u16, u16)
) -> Result<(), Box<dyn Error>> {
stdout
.queue(MoveTo(1, 0))?
.queue(PrintStyledContent("Arrows".yellow().bold()))?
.queue(MoveTo(1, 1))?
.queue(PrintStyledContent("Navigate".yellow()))?
.queue(MoveTo(12, 0))?
.queue(PrintStyledContent("+/-".yellow().bold()))?
.queue(MoveTo(12, 1))?
.queue(PrintStyledContent("Zoom".yellow()))?
.queue(MoveTo(20, 0))?
.queue(PrintStyledContent("a/d".yellow().bold()))?
.queue(MoveTo(20, 1))?
.queue(PrintStyledContent("Add/delete".yellow()))?
.queue(MoveTo(33, 0))?
.queue(PrintStyledContent("[/]".yellow().bold()))?
.queue(MoveTo(33, 1))?
.queue(PrintStyledContent("Duration".yellow()))?
.queue(MoveTo(45, 0))?
.queue(PrintStyledContent("CapsLock".yellow().bold()))?
.queue(MoveTo(45, 1))?
.queue(PrintStyledContent("Auto advance".yellow()))?;
Ok(())
}
fn render_grid (
state: &mut Sequencer,
stdout: &mut Stdout,
offset: (u16, u16)
) -> Result<(), Box<dyn Error>> {
let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row);
let bg = "┊···············┊···············┊···············┊···············";
let cursor: String = if state.duration == 0 {
let cursor: String = if state.cursor.2 == 0 {
"X".into()
} else {
std::iter::repeat("·")
.take(state.duration as usize)
.take(state.cursor.2 as usize)
.collect()
};
stdout
.queue(MoveTo(1, 3))?.queue(Print("1.1"))?
.queue(MoveTo(17, 3))?.queue(Print("1.2"))?
.queue(MoveTo(33, 3))?.queue(Print("1.3"))?
.queue(MoveTo(49, 3))?.queue(Print("1.4"))?
.queue(MoveTo(1, 4))?.queue(PrintStyledContent(bg.grey()))?
.queue(MoveTo(1, 5))?.queue(PrintStyledContent(bg.grey()))?
.queue(MoveTo(1, 6))?.queue(PrintStyledContent(bg.grey()))?
.queue(MoveTo(1, 7))?.queue(PrintStyledContent(bg.grey()))?
.queue(MoveTo(1 + state.cursor.0, 4 + state.cursor.1))?
.queue(move_to(1, 3))?.queue(Print("1.1"))?
.queue(move_to(17, 3))?.queue(Print("1.2"))?
.queue(move_to(33, 3))?.queue(Print("1.3"))?
.queue(move_to(49, 3))?.queue(Print("1.4"))?
.queue(move_to(1, 4))?.queue(PrintStyledContent(bg.grey()))?
.queue(move_to(1, 5))?.queue(PrintStyledContent(bg.grey()))?
.queue(move_to(1, 6))?.queue(PrintStyledContent(bg.grey()))?
.queue(move_to(1, 7))?.queue(PrintStyledContent(bg.grey()))?
.queue(move_to(1 + state.cursor.0, 4 + state.cursor.1))?
.queue(PrintStyledContent(cursor.reverse()))?;
Ok(())
}