mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: running interface in separate or combined mode
also disassociating render functions from state structs
This commit is contained in:
parent
f9218e887a
commit
d6bf840a1f
31 changed files with 905 additions and 532 deletions
240
src/mixer.rs
240
src/mixer.rs
|
|
@ -1,3 +1,9 @@
|
|||
mod handle;
|
||||
mod jack;
|
||||
mod render;
|
||||
pub use self::handle::*;
|
||||
pub use self::jack::*;
|
||||
pub use self::render::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
// TODO:
|
||||
|
|
@ -5,17 +11,36 @@ use crate::prelude::*;
|
|||
// - If one stage clips, all stages after it are marked red
|
||||
// - If one track clips, all tracks that feed from it are marked red?
|
||||
|
||||
const ACTIONS: [(&'static str, &'static str);2] = [
|
||||
("+/-", "Adjust"),
|
||||
("Ins/Del", "Add/remove track"),
|
||||
];
|
||||
|
||||
pub struct Mixer {
|
||||
jack: Jack<Notifications>,
|
||||
exit: bool,
|
||||
stdout: Stdout,
|
||||
cols: u16,
|
||||
rows: u16,
|
||||
tracks: Vec<Track>,
|
||||
selected_track: usize,
|
||||
selected_column: usize,
|
||||
}
|
||||
|
||||
pub struct Track {
|
||||
name: String,
|
||||
channels: u8,
|
||||
input_ports: Vec<Port<AudioIn>>,
|
||||
pre_gain_meter: f64,
|
||||
gain: f64,
|
||||
insert_ports: Vec<Port<AudioOut>>,
|
||||
return_ports: Vec<Port<AudioIn>>,
|
||||
post_gain_meter: f64,
|
||||
post_insert_meter: f64,
|
||||
level: f64,
|
||||
pan: f64,
|
||||
output_ports: Vec<Port<AudioOut>>,
|
||||
post_fader_meter: f64,
|
||||
route: String,
|
||||
}
|
||||
|
||||
impl Mixer {
|
||||
|
||||
pub fn new () -> Result<Self, Box<dyn Error>> {
|
||||
|
|
@ -33,9 +58,6 @@ impl Mixer {
|
|||
)?;
|
||||
Ok(Self {
|
||||
exit: false,
|
||||
stdout: std::io::stdout(),
|
||||
cols: 0,
|
||||
rows: 0,
|
||||
selected_column: 0,
|
||||
selected_track: 1,
|
||||
tracks: vec![
|
||||
|
|
@ -51,174 +73,6 @@ impl Mixer {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn run_tui () -> Result<(), Box<dyn Error>> {
|
||||
let mut app = Self::new()?;
|
||||
let sleep = std::time::Duration::from_millis(16);
|
||||
crossterm::terminal::enable_raw_mode()?;
|
||||
let (tx, input) = channel::<crossterm::event::Event>();
|
||||
let exited = Arc::new(AtomicBool::new(false));
|
||||
// Spawn the input thread
|
||||
let exit_input_thread = exited.clone();
|
||||
spawn(move || {
|
||||
loop {
|
||||
// Exit if flag is set
|
||||
if exit_input_thread.fetch_and(true, Ordering::Relaxed) {
|
||||
break
|
||||
}
|
||||
// Listen for events and send them to the main thread
|
||||
if crossterm::event::poll(Duration::from_millis(100)).is_ok() {
|
||||
if tx.send(crossterm::event::read().unwrap()).is_err() {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
loop {
|
||||
app.render()?;
|
||||
app.handle(input.recv()?)?;
|
||||
if app.exit {
|
||||
app.stdout.queue(cursor::Hide)?.flush()?;
|
||||
crossterm::terminal::disable_raw_mode()?;
|
||||
break
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle (&mut self, event: crossterm::event::Event) -> Result<(), Box<dyn Error>> {
|
||||
use crossterm::event::{Event, KeyCode, KeyModifiers};
|
||||
if let Event::Key(event) = event {
|
||||
match event.code {
|
||||
KeyCode::Char('c') => {
|
||||
if event.modifiers == KeyModifiers::CONTROL {
|
||||
self.exit = true;
|
||||
}
|
||||
},
|
||||
KeyCode::Down => {
|
||||
self.selected_track = (self.selected_track + 1) % self.tracks.len();
|
||||
println!("{}", self.selected_track);
|
||||
},
|
||||
KeyCode::Up => {
|
||||
if self.selected_track == 0 {
|
||||
self.selected_track = self.tracks.len() - 1;
|
||||
} else {
|
||||
self.selected_track = self.selected_track - 1;
|
||||
}
|
||||
println!("{}", self.selected_track);
|
||||
},
|
||||
KeyCode::Left => {
|
||||
if self.selected_column == 0 {
|
||||
self.selected_column = 6
|
||||
} else {
|
||||
self.selected_column = self.selected_column - 1;
|
||||
}
|
||||
},
|
||||
KeyCode::Right => {
|
||||
if self.selected_column == 6 {
|
||||
self.selected_column = 0
|
||||
} else {
|
||||
self.selected_column = self.selected_column + 1;
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
println!("{event:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render (&mut self) -> Result<(), Box<dyn Error>> {
|
||||
let (cols, rows) = terminal::size()?;
|
||||
self.cols = cols;
|
||||
self.rows = rows;
|
||||
self.stdout.queue(terminal::Clear(terminal::ClearType::All))?;
|
||||
self.stdout.queue(cursor::Hide)?;
|
||||
self.render_toolbar()?;
|
||||
self.render_table()?;
|
||||
self.render_meters()?;
|
||||
self.stdout.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_toolbar (&mut self) -> Result<(), Box<dyn Error>> {
|
||||
self.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("[+/-]".yellow().bold()))?
|
||||
.queue(cursor::MoveTo(11, 1))?
|
||||
.queue(PrintStyledContent("Adjust value".yellow()))?
|
||||
|
||||
.queue(cursor::MoveTo(25, 0))?
|
||||
.queue(PrintStyledContent("[Ins/Del]".yellow().bold()))?
|
||||
.queue(cursor::MoveTo(25, 1))?
|
||||
.queue(PrintStyledContent("Add/remove track".yellow()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_table (&mut self) -> Result<(), Box<dyn Error>> {
|
||||
self.stdout
|
||||
.queue(cursor::MoveTo(0, 3))?
|
||||
.queue(Print(
|
||||
" Name Gain FX1 Pan Level FX2 Route"))?;
|
||||
for (i, track) in self.tracks.iter().enumerate() {
|
||||
let row = 4 + i as u16;
|
||||
for (j, (column, field)) in [
|
||||
(0, format!(" {:7} ", track.name)),
|
||||
(12, format!(" {:.1}dB ", track.gain)),
|
||||
(22, format!(" [ ] ")),
|
||||
(30, format!(" C ")),
|
||||
(35, format!(" {:.1}dB ", track.level)),
|
||||
(45, format!(" [ ] ")),
|
||||
(51, format!(" {:7} ", track.route)),
|
||||
].into_iter().enumerate() {
|
||||
self.stdout.queue(cursor::MoveTo(column, row))?;
|
||||
if self.selected_track == i && self.selected_column == j {
|
||||
self.stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?;
|
||||
} else {
|
||||
self.stdout.queue(PrintStyledContent(field.to_string().bold()))?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_meters (&mut self) -> Result<(), Box<dyn Error>> {
|
||||
for (i, track) in self.tracks.iter().enumerate() {
|
||||
let row = 4 + i as u16;
|
||||
self.stdout
|
||||
.queue(cursor::MoveTo(10, row))?
|
||||
.queue(PrintStyledContent("▁".green()))?
|
||||
.queue(cursor::MoveTo(20, row))?
|
||||
.queue(PrintStyledContent("▁".green()))?
|
||||
.queue(cursor::MoveTo(28, row))?
|
||||
.queue(PrintStyledContent("▁".green()))?
|
||||
.queue(cursor::MoveTo(43, row))?
|
||||
.queue(PrintStyledContent("▁".green()))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Track {
|
||||
name: String,
|
||||
channels: u8,
|
||||
input_ports: Vec<Port<AudioIn>>,
|
||||
pre_gain_meter: f64,
|
||||
gain: f64,
|
||||
insert_ports: Vec<Port<AudioOut>>,
|
||||
return_ports: Vec<Port<AudioIn>>,
|
||||
post_gain_meter: f64,
|
||||
post_insert_meter: f64,
|
||||
level: f64,
|
||||
pan: f64,
|
||||
output_ports: Vec<Port<AudioOut>>,
|
||||
post_fader_meter: f64,
|
||||
route: String,
|
||||
}
|
||||
|
||||
impl Track {
|
||||
|
|
@ -254,41 +108,3 @@ impl Track {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct Notifications;
|
||||
|
||||
impl NotificationHandler for Notifications {
|
||||
fn thread_init (&self, _: &Client) {
|
||||
}
|
||||
|
||||
fn shutdown (&mut self, status: ClientStatus, reason: &str) {
|
||||
}
|
||||
|
||||
fn freewheel (&mut self, _: &Client, is_enabled: bool) {
|
||||
}
|
||||
|
||||
fn sample_rate (&mut self, _: &Client, _: Frames) -> Control {
|
||||
Control::Quit
|
||||
}
|
||||
|
||||
fn client_registration (&mut self, _: &Client, name: &str, is_reg: bool) {
|
||||
}
|
||||
|
||||
fn port_registration (&mut self, _: &Client, port_id: PortId, is_reg: bool) {
|
||||
}
|
||||
|
||||
fn port_rename (&mut self, _: &Client, id: PortId, old: &str, new: &str) -> Control {
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
fn ports_connected (&mut self, _: &Client, id_a: PortId, id_b: PortId, are: bool) {
|
||||
}
|
||||
|
||||
fn graph_reorder (&mut self, _: &Client) -> Control {
|
||||
Control::Continue
|
||||
}
|
||||
|
||||
fn xrun (&mut self, _: &Client) -> Control {
|
||||
Control::Continue
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue