mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
tabula rasa
This commit is contained in:
commit
11a9f3ba50
33 changed files with 1937 additions and 0 deletions
177
src/mixer.rs
Normal file
177
src/mixer.rs
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
use std::error::Error;
|
||||
use std::io::{stdout, Write};
|
||||
use std::thread::spawn;
|
||||
use std::time::Duration;
|
||||
use std::sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
mpsc::{channel, Sender, Receiver}
|
||||
};
|
||||
|
||||
pub struct Mixer {
|
||||
exit: bool,
|
||||
cols: u16,
|
||||
rows: u16,
|
||||
tracks: Vec<Track>,
|
||||
selected_track: usize,
|
||||
selected_column: usize,
|
||||
}
|
||||
|
||||
pub struct Track {
|
||||
name: String,
|
||||
gain: f64,
|
||||
level: f64,
|
||||
pan: f64,
|
||||
route: String,
|
||||
}
|
||||
|
||||
impl Mixer {
|
||||
|
||||
pub fn new () -> Self {
|
||||
Self {
|
||||
exit: false,
|
||||
cols: 0,
|
||||
rows: 0,
|
||||
selected_column: 0,
|
||||
selected_track: 1,
|
||||
tracks: vec! [
|
||||
Track {
|
||||
name: "Track 1".into(), gain: 0.0, level: 0.0, pan: 0.0, route: "Bus 1".into()
|
||||
},
|
||||
Track {
|
||||
name: "Track 2".into(), gain: 0.0, level: 0.0, pan: 0.0, route: "Bus 2".into()
|
||||
},
|
||||
Track {
|
||||
name: "Track 3".into(), gain: 0.0, level: 0.0, pan: 0.0, route: "Bus 1".into()
|
||||
},
|
||||
Track {
|
||||
name: "Track 4".into(), gain: 0.0, level: 0.0, pan: 0.0, route: "Bus 2".into()
|
||||
},
|
||||
Track {
|
||||
name: "Bus 1".into(), gain: 0.0, level: 0.0, pan: 0.0, route: "Mix".into()
|
||||
},
|
||||
Track {
|
||||
name: "Bus 2".into(), gain: 0.0, level: 0.0, pan: 0.0, route: "Mix".into()
|
||||
},
|
||||
Track {
|
||||
name: "Mix".into(), gain: 0.0, level: 0.0, pan: 0.0, route: "Output".into()
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_tui () -> Result<(), Box<dyn Error>> {
|
||||
let mut app = Self::new();
|
||||
let sleep = std::time::Duration::from_millis(16);
|
||||
let mut stdout = std::io::stdout();
|
||||
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(&mut stdout)?;
|
||||
app.handle(input.recv()?)?;
|
||||
if app.exit {
|
||||
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);
|
||||
}
|
||||
_ => {
|
||||
println!("{event:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render (&mut self, stdout: &mut std::io::Stdout) -> Result<(), Box<dyn Error>> {
|
||||
use crossterm::{*, style::{*, Stylize}};
|
||||
let (cols, rows) = terminal::size()?;
|
||||
if true || cols != self.cols || rows != self.rows { // TODO perf
|
||||
self.cols = cols;
|
||||
self.rows = rows;
|
||||
stdout
|
||||
.queue(terminal::Clear(terminal::ClearType::All))?
|
||||
.queue(cursor::Hide)?
|
||||
|
||||
.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()))?
|
||||
|
||||
.queue(cursor::MoveTo(0, 3))?.queue(Print(
|
||||
" Name Gain Pre Level Pan Post Route"))?;
|
||||
|
||||
for (i, track) in self.tracks.iter().enumerate() {
|
||||
let row = 4 + i as u16;
|
||||
let mut content = format!(
|
||||
" {:7} █ {:.1}dB █ [ ] █ {:.1}dB C █ [ ] {:7} ",
|
||||
track.name,
|
||||
track.gain,
|
||||
track.level,
|
||||
track.route,
|
||||
).bold();
|
||||
if i == self.selected_track {
|
||||
content = content.reverse();
|
||||
}
|
||||
stdout
|
||||
.queue(cursor::MoveTo(0, row))?
|
||||
.queue(PrintStyledContent(content))?;
|
||||
}
|
||||
|
||||
stdout
|
||||
.flush()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue