mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
switch toolbar actions; bold borders and titles
This commit is contained in:
parent
7dd5f7f488
commit
31f8ec5362
8 changed files with 103 additions and 116 deletions
44
src/main.rs
44
src/main.rs
|
|
@ -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()?)?;
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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![],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue