lowfi/src/player/ui/input.rs
2024-10-17 21:33:23 +02:00

73 lines
2.6 KiB
Rust

use std::sync::atomic::Ordering;
use crossterm::event::{self, EventStream, KeyCode, KeyEventKind, KeyModifiers};
use futures::{FutureExt, StreamExt};
use tokio::sync::mpsc::Sender;
use crate::player::Messages;
use super::VOLUME_TIMER;
/// Starts the listener to recieve input from the terminal for various events.
pub async fn listen(sender: Sender<Messages>) -> eyre::Result<()> {
let mut reader = EventStream::new();
loop {
let Some(Ok(event::Event::Key(event))) = reader.next().fuse().await else {
continue;
};
if event.kind == KeyEventKind::Release {
continue;
}
let messages = match event.code {
// Arrow key volume controls.
KeyCode::Up => Messages::ChangeVolume(0.1),
KeyCode::Right => Messages::ChangeVolume(0.01),
KeyCode::Down => Messages::ChangeVolume(-0.1),
KeyCode::Left => Messages::ChangeVolume(-0.01),
KeyCode::Char(character) => match character.to_ascii_lowercase() {
// Ctrl+C
'c' if event.modifiers == KeyModifiers::CONTROL => Messages::Quit,
// Quit
'q' => Messages::Quit,
// Skip/Next
's' | 'n' => Messages::Next,
// Pause
'p' => Messages::PlayPause,
// Volume up & down
'+' | '=' => Messages::ChangeVolume(0.1),
'-' | '_' => Messages::ChangeVolume(-0.1),
_ => continue,
},
// Media keys
KeyCode::Media(media) => match media {
event::MediaKeyCode::Play => Messages::PlayPause,
event::MediaKeyCode::Pause => Messages::PlayPause,
event::MediaKeyCode::PlayPause => Messages::PlayPause,
event::MediaKeyCode::Stop => Messages::Pause,
event::MediaKeyCode::TrackNext => Messages::Next,
event::MediaKeyCode::LowerVolume => Messages::ChangeVolume(-0.1),
event::MediaKeyCode::RaiseVolume => Messages::ChangeVolume(0.1),
event::MediaKeyCode::MuteVolume => Messages::ChangeVolume(-1.0),
_ => continue,
},
_ => continue,
};
// If it's modifying the volume, then we'll set the `VOLUME_TIMER` to 1
// so that the UI thread will know that it should show the audio bar.
if let Messages::ChangeVolume(_) = messages {
VOLUME_TIMER.store(1, Ordering::Relaxed);
}
sender.send(messages).await?;
}
}