add global volume control

This commit is contained in:
Crispy 2023-01-28 21:45:54 +01:00
parent cb438c1887
commit 39eedfc5f4

View file

@ -1,8 +1,9 @@
use crossterm::cursor::MoveTo; use crossterm::cursor::{self, MoveTo};
use crossterm::event::{self, Event, KeyCode}; use crossterm::event::{self, Event, KeyCode};
use crossterm::terminal::{self, Clear, ClearType}; use crossterm::terminal::{self, Clear, ClearType};
use crossterm::ExecutableCommand; use crossterm::ExecutableCommand;
use rodio::{source::Source, OutputStream, OutputStreamHandle}; use rodio::Sink;
use rodio::{OutputStream, OutputStreamHandle};
use std::fs; use std::fs;
use std::io::stdout; use std::io::stdout;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -18,7 +19,7 @@ fn main() {
struct UIChannel { struct UIChannel {
name: String, name: String,
volume: i32, volume: i32,
internal_volume: Arc<Mutex<f32>>, volume_sync: Arc<Mutex<f32>>,
muted: bool, muted: bool,
} }
@ -27,7 +28,7 @@ impl UIChannel {
if self.muted { if self.muted {
self.sync(); self.sync();
} else { } else {
*self.internal_volume.lock().unwrap() = 0.0; *self.volume_sync.lock().unwrap() = 0.0;
} }
self.muted = !self.muted; self.muted = !self.muted;
} }
@ -43,27 +44,33 @@ impl UIChannel {
} }
fn sync(&mut self) { fn sync(&mut self) {
*self.internal_volume.lock().unwrap() = self.get_vol(); *self.volume_sync.lock().unwrap() = self.get_vol();
} }
} }
struct App { struct App {
channels: Vec<UIChannel>, channels: Vec<UIChannel>,
selected: usize, selected: usize,
_stream: OutputStream, _stream: (OutputStream, OutputStreamHandle),
stream_handle: OutputStreamHandle, sink: Sink,
volume: i32,
playing: bool,
quit: bool, quit: bool,
} }
impl App { impl App {
fn new() -> Self { fn new() -> Self {
let (_stream, stream_handle) = OutputStream::try_default() // let (stream, stream_handle) = OutputStream::try_default() //
.expect("Failed to create output stream"); .expect("Failed to create output stream");
let sink = Sink::try_new(&stream_handle).unwrap();
Self { Self {
channels: Vec::new(), channels: Vec::new(),
selected: 0, selected: 0,
_stream, _stream: (stream, stream_handle),
stream_handle, sink,
playing: true,
volume: 20,
quit: false, quit: false,
} }
} }
@ -81,23 +88,25 @@ impl App {
let ui_channel = UIChannel { let ui_channel = UIChannel {
name: file.file_name().to_string_lossy().into(), name: file.file_name().to_string_lossy().into(),
volume: 100, volume: 100,
internal_volume, volume_sync: internal_volume,
muted: false, muted: false,
}; };
self.channels.push(ui_channel); self.channels.push(ui_channel);
} }
self.stream_handle self.sink.append(snoud);
.play_raw(snoud.convert_samples()) self.sink.play();
.unwrap(); self.change_vol(0);
terminal::enable_raw_mode().unwrap(); terminal::enable_raw_mode().unwrap();
stdout().execute(Clear(ClearType::All)).unwrap(); stdout().execute(Clear(ClearType::All)).unwrap();
stdout().execute(cursor::Hide).unwrap();
while !self.quit { while !self.quit {
self.render(); self.render();
self.input(); self.input();
} }
stdout().execute(cursor::Show).unwrap();
terminal::disable_raw_mode().unwrap(); terminal::disable_raw_mode().unwrap();
println!("Exiting"); println!("Exiting");
} }
@ -105,7 +114,16 @@ impl App {
fn render(&mut self) { fn render(&mut self) {
stdout().execute(MoveTo(0, 0)).unwrap(); stdout().execute(MoveTo(0, 0)).unwrap();
println!("Snoud - ambient sound player\n\r"); println!("Snoud - ambient sound player\r");
println!(
"Master volume: {:3}%, {:10}\n\r",
self.volume,
if self.playing {
"[Playing]"
} else {
"[Paused]"
}
);
for (i, channel) in self.channels.iter().enumerate() { for (i, channel) in self.channels.iter().enumerate() {
println!( println!(
"{selection} {name}:\r\n {volume:3.0}% {status:-<21}\r\n", "{selection} {name}:\r\n {volume:3.0}% {status:-<21}\r\n",
@ -130,11 +148,7 @@ impl App {
return; return;
} }
let event = if let Ok(Event::Key(keyevent)) = event::read() { let Ok(Event::Key(event)) = event::read() else { return };
keyevent
} else {
return;
};
match event.code { match event.code {
KeyCode::Char('q') => self.quit = true, KeyCode::Char('q') => self.quit = true,
@ -142,7 +156,10 @@ impl App {
KeyCode::Down => self.select_next(), KeyCode::Down => self.select_next(),
KeyCode::Right => self.channels[self.selected].change_vol(10), KeyCode::Right => self.channels[self.selected].change_vol(10),
KeyCode::Left => self.channels[self.selected].change_vol(-10), KeyCode::Left => self.channels[self.selected].change_vol(-10),
KeyCode::Char(' ' | 'm') => self.channels[self.selected].mute(), KeyCode::Char('m') => self.channels[self.selected].mute(),
KeyCode::Char(' ') => self.mute(),
KeyCode::Char('.') => self.change_vol(5),
KeyCode::Char(',') => self.change_vol(-5),
_ => (), _ => (),
} }
} }
@ -157,4 +174,18 @@ impl App {
fn select_next(&mut self) { fn select_next(&mut self) {
self.selected = (self.selected + 1) % self.channels.len(); self.selected = (self.selected + 1) % self.channels.len();
} }
fn change_vol(&mut self, amount: i32) {
self.volume += amount;
self.sink.set_volume(self.volume as f32 / 100.0);
}
fn mute(&mut self) {
self.playing = !self.playing;
if self.playing {
self.sink.play();
} else {
self.sink.pause();
}
}
} }