aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--modules/by-name/ri/river/keymap.nix2
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs267
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/messages.rs1
3 files changed, 170 insertions, 100 deletions
diff --git a/modules/by-name/ri/river/keymap.nix b/modules/by-name/ri/river/keymap.nix
index ca7ab69d..48aca3cd 100644
--- a/modules/by-name/ri/river/keymap.nix
+++ b/modules/by-name/ri/river/keymap.nix
@@ -79,6 +79,8 @@ in {
"n" = mkSpawn pkgs.mpp "next" {};
"p" = mkSpawn pkgs.mpp "prev" {};
"t" = mkSpawn pkgs.mpp "toggle" {};
+ "g" = mkSpawn' pkgs.mpdpopm "mpdpopm" "rating inc" {};
+ "b" = mkSpawn' pkgs.mpdpopm "mpdpopm" "rating decr" {};
};
# Select tags for view.
diff --git a/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs b/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
index 4ffcd499..04760f18 100644
--- a/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/bin/mpdpopm.rs
@@ -79,7 +79,6 @@ pub enum Error {
}
impl fmt::Display for Error {
- #[allow(unreachable_patterns)] // the _ arm is *currently* unreachable
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Error::NoSubCommand => write!(f, "No sub-command given"),
@@ -122,7 +121,18 @@ async fn map_tracks(client: &mut Client, args: Option<Vec<String>>) -> Result<Ve
let files = match args {
Some(iter) => iter,
None => {
- let file = match client.status().await.map_err(|err| Error::Client {
+ let file = provide_file(client, None).await?;
+ vec![file]
+ }
+ };
+ Ok(files)
+}
+
+async fn provide_file(client: &mut Client, maybe_file: Option<String>) -> Result<String> {
+ let file = match maybe_file {
+ Some(file) => file,
+ None => {
+ match client.status().await.map_err(|err| Error::Client {
source: err,
back: Backtrace::new(),
})? {
@@ -137,11 +147,11 @@ async fn map_tracks(client: &mut Client, args: Option<Vec<String>>) -> Result<Ve
PlayerStatus::Stopped => {
return Err(Error::PlayerStopped);
}
- };
- vec![file]
+ }
}
};
- Ok(files)
+
+ Ok(file)
}
/// Retrieve ratings for one or more tracks
@@ -175,49 +185,74 @@ async fn get_ratings(
}
/// Rate a track
-async fn set_rating(
- client: &mut Client,
- chan: &str,
- rating: u8,
- arg: Option<String>,
-) -> Result<()> {
- let cmd = match &arg {
- Some(uri) => format!("rate {} \\\"{}\\\"", rating, uri),
- None => format!("rate {}", rating),
- };
- client
- .send_message(chan, &cmd)
+async fn set_rating(client: &mut Client, rating: u8, arg: Option<String>) -> Result<()> {
+ let is_current = arg.is_none();
+ let file = provide_file(client, arg).await?;
+
+ rating_count::set(client, &file, rating)
.await
- .map_err(|err| Error::Client {
- source: err,
+ .map_err(|err| Error::Ratings {
+ source: Box::new(err),
back: Backtrace::new(),
})?;
- match &arg {
- Some(uri) => info!("Set the rating for \"{}\" to \"{}\".", uri, rating),
- None => info!("Set the rating for the current song to \"{}\".", rating),
+ match is_current {
+ false => info!("Set the rating for \"{}\" to \"{}\".", file, rating),
+ true => info!("Set the rating for the current song to \"{}\".", rating),
}
Ok(())
}
/// Rate a track by incrementing the current rating
-async fn inc_rating(client: &mut Client, chan: &str, arg: Option<String>) -> Result<()> {
- let cmd = match &arg {
- Some(uri) => format!("inc-rate \\\"{}\\\"", uri),
- None => "inc-rate ".to_owned(),
- };
- client
- .send_message(chan, &cmd)
+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::Client {
- source: err,
+ .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
+ .map_err(|err| Error::Ratings {
+ source: Box::new(err),
back: Backtrace::new(),
})?;
- match &arg {
- Some(uri) => info!("Incremented the rating for \"{}\".", uri),
- None => info!("Incremented the rating for the current song."),
+ match is_current {
+ false => info!("Incremented the rating for \"{}\".", file),
+ true => info!("Incremented the rating for the current song."),
+ }
+
+ Ok(())
+}
+
+/// Rate a track by decrementing the current rating
+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(),
+ })?;
+
+ 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(),
+ })?;
+
+ match is_current {
+ false => info!("Decremented the rating for \"{}\".", file),
+ true => info!("Decremented the rating for the current song."),
}
Ok(())
@@ -253,27 +288,20 @@ async fn get_play_counts(
}
/// Set the playcount for a track
-async fn set_play_counts(
- client: &mut Client,
- chan: &str,
- playcount: usize,
- arg: Option<String>,
-) -> Result<()> {
- let cmd = match &arg {
- Some(uri) => format!("setpc {} \\\"{}\\\"", playcount, uri),
- None => format!("setpc {}", playcount),
- };
- client
- .send_message(chan, &cmd)
+async fn set_play_counts(client: &mut Client, playcount: usize, arg: Option<String>) -> Result<()> {
+ let is_current = arg.is_none();
+ let file = provide_file(client, arg).await?;
+
+ play_count::set(client, &file, playcount)
.await
- .map_err(|err| Error::Client {
- source: err,
+ .map_err(|err| Error::Playcounts {
+ source: Box::new(err),
back: Backtrace::new(),
})?;
- match &arg {
- Some(uri) => info!("Set the playcount for \"{}\" to \"{}\".", uri, playcount),
- None => info!(
+ match is_current {
+ false => info!("Set the playcount for \"{}\" to \"{}\".", file, playcount),
+ true => info!(
"Set the playcount for the current song to \"{}\".",
playcount
),
@@ -325,27 +353,20 @@ async fn get_last_playeds(
}
/// Set the playcount for a track
-async fn set_last_playeds(
- client: &mut Client,
- chan: &str,
- lastplayed: u64,
- arg: Option<String>,
-) -> Result<()> {
- let cmd = match &arg {
- Some(uri) => format!("setlp {} {}", lastplayed, uri),
- None => format!("setlp {}", lastplayed),
- };
- client
- .send_message(chan, &cmd)
+async fn set_last_playeds(client: &mut Client, lastplayed: u64, arg: Option<String>) -> Result<()> {
+ let is_current = arg.is_none();
+ let file = provide_file(client, arg).await?;
+
+ last_played::set(client, &file, lastplayed)
.await
- .map_err(|err| Error::Client {
- source: err,
+ .map_err(|err| Error::Playcounts {
+ source: Box::new(err),
back: Backtrace::new(),
})?;
- match &arg {
- Some(uri) => info!("Set last played for \"{}\" to \"{}\".", uri, lastplayed),
- None => info!(
+ match is_current {
+ false => info!("Set last played for \"{}\" to \"{}\".", file, lastplayed),
+ true => info!(
"Set last played for the current song to \"{}\".",
lastplayed
),
@@ -426,7 +447,7 @@ struct Args {
}
#[derive(Subcommand)]
-enum SubCommand {
+enum RatingCommand {
/// retrieve the rating for one or more tracks
///
/// With no arguments, retrieve the rating of the current song & print it
@@ -437,7 +458,7 @@ enum SubCommand {
/// Ratings are expressed as an integer between 0 & 255, inclusive, with
/// the convention that 0 denotes "un-rated".
#[clap(verbatim_doc_comment)]
- GetRating {
+ Get {
/// Always show the song URI, even when there is only one track
#[arg(short, long)]
with_uri: bool,
@@ -451,15 +472,25 @@ enum SubCommand {
/// With a second argument, rate that song at the first argument. Ratings
/// may be expressed a an integer between 0 & 255, inclusive.
#[clap(verbatim_doc_comment)]
- SetRating { rating: u8, track: Option<String> },
+ Set { rating: u8, track: Option<String> },
/// increment the rating for one track
///
/// With one argument, increment the rating of the current song.
/// With a second argument, rate that song at the first argument.
#[clap(verbatim_doc_comment)]
- IncRating { track: Option<String> },
+ Inc { track: Option<String> },
+
+ /// decrement the rating for one track
+ ///
+ /// With one argument, decrement the rating of the current song.
+ /// With a second argument, rate that song at the first argument.
+ #[clap(verbatim_doc_comment)]
+ Decr { track: Option<String> },
+}
+#[derive(Subcommand)]
+enum PlayCountCommand {
/// retrieve the play count for one or more tracks
///
/// With no arguments, retrieve the play count of the current song & print it
@@ -467,7 +498,7 @@ enum SubCommand {
/// on stdout. With multiple arguments, print their play counts on stdout, one
/// per line, prefixed by the track name.
#[clap(verbatim_doc_comment)]
- GetPc {
+ Get {
/// Always show the song URI, even when there is only one track
#[arg(short, long)]
with_uri: bool,
@@ -480,11 +511,14 @@ enum SubCommand {
/// With one argument, set the play count of the current song to that argument. With a
/// second argument, set the play count for that song to the first.
#[clap(verbatim_doc_comment)]
- SetPc {
+ Set {
play_count: usize,
track: Option<String>,
},
+}
+#[derive(Subcommand)]
+enum LastPlayedCommand {
/// retrieve the last played timestamp for one or more tracks
///
/// With no arguments, retrieve the last played timestamp of the current
@@ -495,7 +529,7 @@ enum SubCommand {
///
/// The last played timestamp is expressed in seconds since Unix epoch.
#[clap(verbatim_doc_comment)]
- GetLp {
+ Get {
/// Always show the song URI, even when there is only one track
#[arg(short, long)]
with_uri: bool,
@@ -509,14 +543,44 @@ enum SubCommand {
/// arguments, set the last played time for the second argument to the first.
/// The last played timestamp is expressed in seconds since Unix epoch.
#[clap(verbatim_doc_comment)]
- SetLp {
+ Set {
last_played: u64,
track: Option<String>,
},
+}
+#[derive(Subcommand)]
+enum PlaylistsCommand {
/// retrieve the list of stored playlists
#[clap(verbatim_doc_comment)]
- GetPlaylists {},
+ Get {},
+}
+
+#[derive(Subcommand)]
+enum SubCommand {
+ /// Change details about rating.
+ Rating {
+ #[command(subcommand)]
+ command: RatingCommand,
+ },
+
+ /// Change details about play count.
+ PlayCount {
+ #[command(subcommand)]
+ command: PlayCountCommand,
+ },
+
+ /// Change details about last played date.
+ LastPlayed {
+ #[command(subcommand)]
+ command: LastPlayedCommand,
+ },
+
+ /// Change details about generated playlists.
+ Playlists {
+ #[command(subcommand)]
+ command: PlaylistsCommand,
+ },
/// search case-sensitively for songs matching matching a filter and add them to the queue
///
@@ -642,28 +706,33 @@ async fn main() -> Result<()> {
};
match args.command {
- SubCommand::GetRating { with_uri, tracks } => {
- get_ratings(&mut client, tracks, with_uri).await
- }
- SubCommand::SetRating { rating, track } => {
- set_rating(&mut client, &config.commands_chan, rating, track).await
- }
- SubCommand::IncRating { track } => {
- inc_rating(&mut client, &config.commands_chan, track).await
- }
- SubCommand::GetPc { with_uri, tracks } => {
- get_play_counts(&mut client, tracks, with_uri).await
- }
- SubCommand::SetPc { play_count, track } => {
- set_play_counts(&mut client, &config.commands_chan, play_count, track).await
- }
- SubCommand::GetLp { with_uri, tracks } => {
- get_last_playeds(&mut client, tracks, with_uri).await
- }
- SubCommand::SetLp { last_played, track } => {
- set_last_playeds(&mut client, &config.commands_chan, last_played, track).await
- }
- SubCommand::GetPlaylists {} => get_playlists(&mut client).await,
+ SubCommand::Rating { command } => match command {
+ RatingCommand::Get { with_uri, tracks } => {
+ get_ratings(&mut client, tracks, with_uri).await
+ }
+ RatingCommand::Set { rating, track } => set_rating(&mut client, rating, track).await,
+ RatingCommand::Inc { track } => inc_rating(&mut client, track).await,
+ RatingCommand::Decr { track } => decr_rating(&mut client, track).await,
+ },
+ SubCommand::PlayCount { command } => match command {
+ PlayCountCommand::Get { with_uri, tracks } => {
+ get_play_counts(&mut client, tracks, with_uri).await
+ }
+ PlayCountCommand::Set { play_count, track } => {
+ set_play_counts(&mut client, play_count, track).await
+ }
+ },
+ SubCommand::LastPlayed { command } => match command {
+ LastPlayedCommand::Get { with_uri, tracks } => {
+ get_last_playeds(&mut client, tracks, with_uri).await
+ }
+ LastPlayedCommand::Set { last_played, track } => {
+ set_last_playeds(&mut client, last_played, track).await
+ }
+ },
+ SubCommand::Playlists { command } => match command {
+ PlaylistsCommand::Get {} => get_playlists(&mut client).await,
+ },
SubCommand::Findadd { filter } => {
findadd(&mut client, &config.commands_chan, &filter, true).await
}
diff --git a/pkgs/by-name/mp/mpdpopm/src/messages.rs b/pkgs/by-name/mp/mpdpopm/src/messages.rs
index 85b24470..ae356f34 100644
--- a/pkgs/by-name/mp/mpdpopm/src/messages.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/messages.rs
@@ -64,7 +64,6 @@ use std::collections::VecDeque;
use std::convert::TryFrom;
use std::path::PathBuf;
-////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Debug)]
pub enum Error {