From adcb20f2d0b78c555dd086f4d64403e7d4357bf3 Mon Sep 17 00:00:00 2001 From: talwat <83217276+talwat@users.noreply.github.com> Date: Wed, 12 Mar 2025 14:21:32 +0100 Subject: [PATCH] fix: reform errors for track fetching --- src/player.rs | 15 ++++++++------- src/player/downloader.rs | 4 ++-- src/tracks/list.rs | 41 +++++++++++++++++++++------------------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/player.rs b/src/player.rs index a6e583b..9b9300c 100644 --- a/src/player.rs +++ b/src/player.rs @@ -69,7 +69,7 @@ pub enum Messages { } /// The time to wait in between errors. -const TIMEOUT: Duration = Duration::from_secs(5); +const TIMEOUT: Duration = Duration::from_secs(1); /// The amount of songs to buffer up. const BUFFER_SIZE: usize = 5; @@ -222,7 +222,7 @@ impl Player { /// This will play the next track, as well as refilling the buffer in the background. /// /// This will also set `current` to the newly loaded song. - pub async fn next(&self) -> eyre::Result { + pub async fn next(&self) -> Result { // TODO: Consider replacing this with `unwrap_or_else` when async closures are stablized. let track = self.tracks.write().await.pop_front(); let track = if let Some(track) = track { @@ -235,11 +235,12 @@ impl Player { // We're doing it here so that we don't get the "loading" display // for only a frame in the other case that the buffer is not empty. self.current.store(None); - - self.list.random(&self.client).await.0? + self.list + .random(&self.client) + .await? }; - let decoded = track.decode()?; + let decoded = track.decode().map_err(|_| false)?; // Set the current track. self.set_current(decoded.info.clone()); @@ -277,8 +278,8 @@ impl Player { // Notify the audio server that the next song has actually been downloaded. tx.send(Messages::NewSong).await?; } - Err(error) => { - if !error.downcast::()?.is_timeout() { + Err(timeout) => { + if !timeout { sleep(TIMEOUT).await; } diff --git a/src/player/downloader.rs b/src/player/downloader.rs index 07a0343..3fd53bf 100644 --- a/src/player/downloader.rs +++ b/src/player/downloader.rs @@ -51,10 +51,10 @@ impl Downloader { while self.rx.recv().await == Some(()) { // For each update notification, we'll push tracks until the buffer is completely full. while self.player.tracks.read().await.len() < BUFFER_SIZE { - let (data, timeout) = self.player.list.random(&self.player.client).await; + let data = self.player.list.random(&self.player.client).await; match data { Ok(track) => self.player.tracks.write().await.push_back(track), - Err(_) => { + Err(timeout) => { if !timeout { sleep(TIMEOUT).await; } diff --git a/src/tracks/list.rs b/src/tracks/list.rs index 94ddf25..300645e 100644 --- a/src/tracks/list.rs +++ b/src/tracks/list.rs @@ -50,7 +50,7 @@ impl List { } /// Downloads a raw track, but doesn't decode it. - async fn download(&self, track: &str, client: &Client) -> (eyre::Result, bool) { + async fn download(&self, track: &str, client: &Client) -> Result { // If the track has a protocol, then we should ignore the base for it. let url = if track.contains("://") { track.to_owned() @@ -58,36 +58,39 @@ impl List { format!("{}{}", self.base(), track) }; - let (timeout, data) = if let Some(x) = url.strip_prefix("file://") { - let result = tokio::fs::read(x).await.unwrap(); - (false, Ok(result.into())) - } else { - let response = client.get(url).send().await; + let data: Bytes = if let Some(x) = url.strip_prefix("file://") { + let path = if x.starts_with("~") { + let home_path = dirs::home_dir().ok_or(false)?; + let home = home_path.to_str().ok_or(false)?; - match response { - Ok(x) => (false, x.bytes().await), - Err(x) => (x.is_timeout(), Err(x)), - } + x.replace("~", home) + } else { + x.to_owned() + }; + + let result = tokio::fs::read(path).await.map_err(|_| false)?; + result.into() + } else { + let response = client.get(url).send().await.map_err(|x| x.is_timeout())?; + response.bytes().await.map_err(|_| false)? }; - (data.map_err(|x| eyre::eyre!(x)), timeout) + Ok(data) } /// Fetches and downloads a random track from the [List]. - pub async fn random(&self, client: &Client) -> (eyre::Result, bool) { + /// + /// The Result's error is a bool, which is true if a timeout error occured, + /// and false otherwise. This tells lowfi if it shouldn't wait to try again. + pub async fn random(&self, client: &Client) -> Result { let (path, custom_name) = self.random_path(); - let (data, timeout) = self.download(&path, client).await; + let data = self.download(&path, client).await?; let name = custom_name.map_or(super::TrackName::Raw(path), |formatted| { super::TrackName::Formatted(formatted) }); - let track = match data { - Ok(x) => Ok(Track { name, data: x }), - Err(x) => Err(x), - }; - - (track, timeout) + Ok(Track { name, data: data }) } /// Parses text into a [List].