about summary refs log tree commit diff stats
path: root/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs211
1 files changed, 31 insertions, 180 deletions
diff --git a/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs b/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
index 82a354d6..d9d607d5 100644
--- a/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
@@ -32,82 +32,12 @@ use mpdpopm::{
     storage::{last_played, play_count, rating_count},
 };
 
-use backtrace::Backtrace;
+use anyhow::{Context, Result, anyhow, bail};
 use clap::{Parser, Subcommand};
 use tracing::{debug, info, level_filters::LevelFilter, trace};
 use tracing_subscriber::{EnvFilter, Registry, layer::SubscriberExt};
 
-use std::{fmt, path::PathBuf};
-
-#[non_exhaustive]
-pub enum Error {
-    NoSubCommand,
-    NoConfigArg,
-    NoRating,
-    NoPlayCount,
-    NoLastPlayed,
-    NoConfig {
-        config: std::path::PathBuf,
-        cause: std::io::Error,
-    },
-    PlayerStopped,
-    BadPath {
-        path: PathBuf,
-        back: Backtrace,
-    },
-    NoPlaylist,
-    Client {
-        source: mpdpopm::clients::Error,
-        back: Backtrace,
-    },
-    Ratings {
-        source: Box<mpdpopm::storage::Error>,
-        back: Backtrace,
-    },
-    Playcounts {
-        source: Box<mpdpopm::storage::Error>,
-        back: Backtrace,
-    },
-    ExpectedInt {
-        source: std::num::ParseIntError,
-        back: Backtrace,
-    },
-    Config {
-        source: crate::config::Error,
-        back: Backtrace,
-    },
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            Error::NoSubCommand => write!(f, "No sub-command given"),
-            Error::NoConfigArg => write!(f, "No argument given for the configuration option"),
-            Error::NoRating => write!(f, "No rating supplied"),
-            Error::NoPlayCount => write!(f, "No play count supplied"),
-            Error::NoLastPlayed => write!(f, "No last played timestamp given"),
-            Error::NoConfig { config, cause } => write!(f, "Bad config ({:?}): {}", config, cause),
-            Error::PlayerStopped => write!(f, "The player is stopped"),
-            Error::BadPath { path, back: _ } => write!(f, "Bad path: {:?}", path),
-            Error::NoPlaylist => write!(f, "No playlist given"),
-            Error::Client { source, back: _ } => write!(f, "Client error: {}", source),
-            Error::Ratings { source, back: _ } => write!(f, "Rating error: {}", source),
-            Error::Playcounts { source, back: _ } => write!(f, "Playcount error: {}", source),
-            Error::ExpectedInt { source, back: _ } => write!(f, "Expected integer: {}", source),
-            Error::Config { source, back: _ } => {
-                write!(f, "Error reading configuration: {}", source)
-            }
-        }
-    }
-}
-
-impl fmt::Debug for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", self)
-    }
-}
-
-type Result<T> = std::result::Result<T, Error>;
+use std::path::PathBuf;
 
 /// Map `tracks' argument(s) to a Vec of String containing one or more mpd URIs
 ///
@@ -132,20 +62,18 @@ async fn provide_file(client: &mut Client, maybe_file: Option<String>) -> Result
     let file = match maybe_file {
         Some(file) => file,
         None => {
-            match client.status().await.map_err(|err| Error::Client {
-                source: err,
-                back: Backtrace::new(),
-            })? {
+            match client
+                .status()
+                .await
+                .context("Failed to get status of client")?
+            {
                 PlayerStatus::Play(curr) | PlayerStatus::Pause(curr) => curr
                     .file
                     .to_str()
-                    .ok_or_else(|| Error::BadPath {
-                        path: curr.file.clone(),
-                        back: Backtrace::new(),
-                    })?
+                    .ok_or_else(|| anyhow!("Path is not utf8: `{}`", curr.file.display()))?
                     .to_string(),
                 PlayerStatus::Stopped => {
-                    return Err(Error::PlayerStopped);
+                    bail!("Player is stopped");
                 }
             }
         }
@@ -163,12 +91,7 @@ async fn get_ratings(
     let mut ratings: Vec<(String, i8)> = Vec::new();
 
     for file in map_tracks(client, tracks).await? {
-        let rating = rating_count::get(client, &file)
-            .await
-            .map_err(|err| Error::Ratings {
-                source: Box::new(err),
-                back: Backtrace::new(),
-            })?;
+        let rating = rating_count::get(client, &file).await?;
 
         ratings.push((file, rating.unwrap_or_default()));
     }
@@ -189,12 +112,7 @@ async fn set_rating(client: &mut Client, rating: i8, arg: Option<String>) -> Res
     let is_current = arg.is_none();
     let file = provide_file(client, arg).await?;
 
-    rating_count::set(client, &file, rating)
-        .await
-        .map_err(|err| Error::Ratings {
-            source: Box::new(err),
-            back: Backtrace::new(),
-        })?;
+    rating_count::set(client, &file, rating).await?;
 
     match is_current {
         false => info!("Set the rating for \"{}\" to \"{}\".", file, rating),
@@ -209,19 +127,9 @@ async fn inc_rating(client: &mut Client, arg: Option<String>) -> Result<()> {
     let is_current = arg.is_none();
     let file = provide_file(client, arg).await?;
 
-    let now = rating_count::get(client, &file)
-        .await
-        .map_err(|err| Error::Ratings {
-            source: Box::new(err),
-            back: Backtrace::new(),
-        })?;
+    let now = rating_count::get(client, &file).await?;
 
-    rating_count::set(client, &file, now.unwrap_or_default().saturating_add(1))
-        .await
-        .map_err(|err| Error::Ratings {
-            source: Box::new(err),
-            back: Backtrace::new(),
-        })?;
+    rating_count::set(client, &file, now.unwrap_or_default().saturating_add(1)).await?;
 
     match is_current {
         false => info!("Incremented the rating for \"{}\".", file),
@@ -236,19 +144,9 @@ async fn decr_rating(client: &mut Client, arg: Option<String>) -> Result<()> {
     let is_current = arg.is_none();
     let file = provide_file(client, arg).await?;
 
-    let now = rating_count::get(client, &file)
-        .await
-        .map_err(|err| Error::Ratings {
-            source: Box::new(err),
-            back: Backtrace::new(),
-        })?;
+    let now = rating_count::get(client, &file).await?;
 
-    rating_count::set(client, &file, now.unwrap_or_default().saturating_sub(1))
-        .await
-        .map_err(|err| Error::Ratings {
-            source: Box::new(err),
-            back: Backtrace::new(),
-        })?;
+    rating_count::set(client, &file, now.unwrap_or_default().saturating_sub(1)).await?;
 
     match is_current {
         false => info!("Decremented the rating for \"{}\".", file),
@@ -266,13 +164,7 @@ async fn get_play_counts(
 ) -> Result<()> {
     let mut playcounts: Vec<(String, usize)> = Vec::new();
     for file in map_tracks(client, tracks).await? {
-        let playcount = play_count::get(client, &file)
-            .await
-            .map_err(|err| Error::Playcounts {
-                source: Box::new(err),
-                back: Backtrace::new(),
-            })?
-            .unwrap_or_default();
+        let playcount = play_count::get(client, &file).await?.unwrap_or_default();
         playcounts.push((file, playcount));
     }
 
@@ -292,12 +184,7 @@ async fn set_play_counts(client: &mut Client, playcount: usize, arg: Option<Stri
     let is_current = arg.is_none();
     let file = provide_file(client, arg).await?;
 
-    play_count::set(client, &file, playcount)
-        .await
-        .map_err(|err| Error::Playcounts {
-            source: Box::new(err),
-            back: Backtrace::new(),
-        })?;
+    play_count::set(client, &file, playcount).await?;
 
     match is_current {
         false => info!("Set the playcount for \"{}\" to \"{}\".", file, playcount),
@@ -318,13 +205,7 @@ async fn get_last_playeds(
 ) -> Result<()> {
     let mut lastplayeds: Vec<(String, Option<u64>)> = Vec::new();
     for file in map_tracks(client, tracks).await? {
-        let lastplayed =
-            last_played::get(client, &file)
-                .await
-                .map_err(|err| Error::Playcounts {
-                    source: Box::new(err),
-                    back: Backtrace::new(),
-                })?;
+        let lastplayed = last_played::get(client, &file).await?;
         lastplayeds.push((file, lastplayed));
     }
 
@@ -357,12 +238,7 @@ async fn set_last_playeds(client: &mut Client, lastplayed: u64, arg: Option<Stri
     let is_current = arg.is_none();
     let file = provide_file(client, arg).await?;
 
-    last_played::set(client, &file, lastplayed)
-        .await
-        .map_err(|err| Error::Playcounts {
-            source: Box::new(err),
-            back: Backtrace::new(),
-        })?;
+    last_played::set(client, &file, lastplayed).await?;
 
     match is_current {
         false => info!("Set last played for \"{}\" to \"{}\".", file, lastplayed),
@@ -377,13 +253,7 @@ async fn set_last_playeds(client: &mut Client, lastplayed: u64, arg: Option<Stri
 
 /// Retrieve the list of stored playlists
 async fn get_playlists(client: &mut Client) -> Result<()> {
-    let mut pls = client
-        .get_stored_playlists()
-        .await
-        .map_err(|err| Error::Client {
-            source: err,
-            back: Backtrace::new(),
-        })?;
+    let mut pls = client.get_stored_playlists().await?;
     pls.sort();
     println!("Stored playlists:");
     for pl in pls {
@@ -397,13 +267,7 @@ async fn findadd(client: &mut Client, chan: &str, filter: &str, case: bool) -> R
     let qfilter = quote(filter);
     debug!("findadd: got ``{}'', quoted to ``{}''.", filter, qfilter);
     let cmd = format!("{} {}", if case { "findadd" } else { "searchadd" }, qfilter);
-    client
-        .send_message(chan, &cmd)
-        .await
-        .map_err(|err| Error::Client {
-            source: err,
-            back: Backtrace::new(),
-        })?;
+    client.send_message(chan, &cmd).await?;
     Ok(())
 }
 
@@ -419,11 +283,7 @@ async fn send_command(client: &mut Client, chan: &str, args: Vec<String>) -> Res
                 .join(" ")
                 .as_str(),
         )
-        .await
-        .map_err(|err| Error::Client {
-            source: err,
-            back: Backtrace::new(),
-        })?;
+        .await?;
     Ok(())
 }
 
@@ -647,18 +507,17 @@ async fn main() -> Result<()> {
 
     let config = if let Some(configpath) = &args.config {
         match std::fs::read_to_string(configpath) {
-            Ok(text) => config::from_str(&text).map_err(|err| Error::Config {
-                source: err,
-                back: Backtrace::new(),
+            Ok(text) => config::from_str(&text).with_context(|| {
+                format!("Failed to parse config file at: `{}`", configpath.display())
             })?,
             Err(err) => {
                 // Either they did _not_, in which case they probably want to know that the config
                 // file they explicitly asked for does not exist, or there was some other problem,
                 // in which case we're out of options, anyway. Either way:
-                return Err(Error::NoConfig {
-                    config: PathBuf::from(configpath),
-                    cause: err,
-                });
+                bail!(
+                    "Failed to read config file at: `{}`, because: {err}",
+                    configpath.display()
+                )
             }
         }
     } else {
@@ -691,18 +550,10 @@ async fn main() -> Result<()> {
     trace!("logging configured.");
 
     let mut client = match config.conn {
-        config::Connection::Local { path } => {
-            Client::open(path).await.map_err(|err| Error::Client {
-                source: err,
-                back: Backtrace::new(),
-            })?
+        config::Connection::Local { path } => Client::open(path).await?,
+        config::Connection::TCP { host, port } => {
+            Client::connect(format!("{}:{}", host, port)).await?
         }
-        config::Connection::TCP { host, port } => Client::connect(format!("{}:{}", host, port))
-            .await
-            .map_err(|err| Error::Client {
-                source: err,
-                back: Backtrace::new(),
-            })?,
     };
 
     match args.command {