From c2baa53ded315ed06cdebd96e07b1c6852d75920 Mon Sep 17 00:00:00 2001 From: Tal <83217276+talwat@users.noreply.github.com> Date: Wed, 2 Oct 2024 22:56:01 +0200 Subject: [PATCH] fix: finally fix the alsa warnings with `libc`'s `freopen` --- Cargo.lock | 3 ++- Cargo.toml | 3 ++- src/play.rs | 9 --------- src/player.rs | 31 ++++++++++++++++++++++++++++--- src/player/ui.rs | 10 ++-------- 5 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 316beb9..4057541 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -982,7 +982,7 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lowfi" -version = "1.3.1" +version = "1.3.2" dependencies = [ "Inflector", "arc-swap", @@ -992,6 +992,7 @@ dependencies = [ "eyre", "futures", "lazy_static", + "libc", "rand", "reqwest", "rodio", diff --git a/Cargo.toml b/Cargo.toml index 769a166..baf49ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lowfi" -version = "1.3.1" +version = "1.3.2" edition = "2021" description = "An extremely simple lofi player." license = "MIT" @@ -40,3 +40,4 @@ rodio = { version = "0.19.0", features = ["symphonia-mp3"], default-features = f crossterm = "0.28.1" Inflector = "0.11.4" lazy_static = "1.5.0" +libc = "0.2.159" diff --git a/src/play.rs b/src/play.rs index 6d512d2..df1484e 100644 --- a/src/play.rs +++ b/src/play.rs @@ -1,9 +1,7 @@ //! Responsible for the basic initialization & shutdown of the audio server & frontend. -use std::io::stdout; use std::sync::Arc; -use crossterm::cursor::SavePosition; use tokio::{sync::mpsc, task}; use crate::player::Player; @@ -12,13 +10,6 @@ use crate::player::{ui, Messages}; /// Initializes the audio server, and then safely stops /// it when the frontend quits. pub async fn play(alternate: bool) -> eyre::Result<()> { - // Save the position. This is important since later on we can revert to this position - // and clear any potential error messages that may have showed up. - // TODO: Figure how to set some sort of flag to hide error messages within alsa/rodio, - // TODO: Instead of just ignoring & clearing them after. - // TODO: Fix this, as it doesn't work with some terminals when the cursor is at the bottom of the terminal. - crossterm::execute!(stdout(), SavePosition)?; - let (tx, rx) = mpsc::channel(8); let player = Arc::new(Player::new().await?); diff --git a/src/player.rs b/src/player.rs index a7fae48..d1f787c 100644 --- a/src/player.rs +++ b/src/player.rs @@ -6,6 +6,7 @@ use std::{collections::VecDeque, sync::Arc, time::Duration}; use arc_swap::ArcSwapOption; use downloader::Downloader; +use libc::freopen; use reqwest::Client; use rodio::{OutputStream, OutputStreamHandle, Sink}; use tokio::{ @@ -85,12 +86,34 @@ unsafe impl Send for Player {} unsafe impl Sync for Player {} impl Player { + /// This gets the output stream while also shutting up alsa. + fn get_output_stream() -> eyre::Result<(OutputStream, OutputStreamHandle)> { + extern "C" { + static stderr: *mut libc::FILE; + } + + let mode = c"w".as_ptr(); + + // This is a bit of an ugly hack that basically just uses `libc` to redirect alsa's + // output to `/dev/null` so that it wont be shoved down our throats. + + // SAFETY: Simple enough to be impossible to fail. Hopefully. + unsafe { freopen(c"/dev/null".as_ptr(), mode, stderr) }; + + let (stream, handle) = OutputStream::try_default()?; + + // SAFETY: See the first call to `freopen`. + unsafe { freopen(c"/dev/tty".as_ptr(), mode, stderr) }; + + Ok((stream, handle)) + } + /// Initializes the entire player, including audio devices & sink. pub async fn new() -> eyre::Result { - let (_stream, handle) = OutputStream::try_default()?; + let (_stream, handle) = Self::get_output_stream()?; let sink = Sink::try_new(&handle)?; - Ok(Self { + let player = Self { tracks: RwLock::new(VecDeque::with_capacity(5)), current: ArcSwapOption::new(None), client: Client::builder() @@ -104,7 +127,9 @@ impl Player { sink, _handle: handle, _stream, - }) + }; + + Ok(player) } /// Just a shorthand for setting `current`. diff --git a/src/player/ui.rs b/src/player/ui.rs index e7cb8fa..643dbf3 100644 --- a/src/player/ui.rs +++ b/src/player/ui.rs @@ -13,7 +13,7 @@ use crate::tracks::TrackInfo; use super::Player; use crossterm::{ - cursor::{Hide, MoveTo, MoveToColumn, MoveUp, RestorePosition, Show}, + cursor::{Hide, MoveTo, MoveToColumn, MoveUp, Show}, event::{self, KeyCode, KeyModifiers}, style::{Print, Stylize}, terminal::{self, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen}, @@ -196,13 +196,7 @@ pub async fn start( sender: Sender, alternate: bool, ) -> eyre::Result<()> { - crossterm::execute!( - stdout(), - RestorePosition, - Clear(ClearType::CurrentLine), - Clear(ClearType::FromCursorDown), - Hide - )?; + crossterm::execute!(stdout(), Hide)?; terminal::enable_raw_mode()?;