about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--modules/by-name/mp/mpdpopm/module.nix65
-rw-r--r--modules/home.legacy/conf/beets/default.nix1
-rw-r--r--modules/home.legacy/conf/beets/plugins.nix7
-rw-r--r--modules/home.legacy/conf/beets/plugins/default.nix1
-rw-r--r--modules/home.legacy/conf/beets/plugins/smartplaylist/default.nix42
-rw-r--r--pkgs/by-name/mp/mpdpopm/.envrc3
-rw-r--r--pkgs/by-name/mp/mpdpopm/Cargo.lock58
-rw-r--r--pkgs/by-name/mp/mpdpopm/Cargo.toml2
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/config.rs17
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/filters_ast.rs14
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/playcounts.rs8
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/storage/mod.rs6
12 files changed, 114 insertions, 110 deletions
diff --git a/modules/by-name/mp/mpdpopm/module.nix b/modules/by-name/mp/mpdpopm/module.nix
new file mode 100644
index 00000000..3524554c
--- /dev/null
+++ b/modules/by-name/mp/mpdpopm/module.nix
@@ -0,0 +1,65 @@
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+{
+  config,
+  pkgs,
+  libraries,
+  lib,
+  ...
+}: let
+  cfg = config.soispha.services.mpdpopm;
+
+  settingsFormat = pkgs.formats.json {};
+in {
+  options.soispha.services.mpdpopm = {
+    enable = libraries.base.options.mkEnable "mpdpopm";
+
+    settings = lib.mkOption {
+      # Setting this type allows for correct merging behavior
+      inherit (settingsFormat) type;
+      default = {};
+      description = ''
+        Configuration for foo, see
+        <link xlink:href="https://example.com/docs/foo"/>
+        for supported settings.
+      '';
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    soispha.services.mpdpopm.settings = {
+      version = "1";
+      log = "${config.home-manager.users.soispha.xdg.dataHome}/mpdpopm/log";
+
+      conn.Local = {
+        path = config.home-manager.users.soispha.home.sessionVariables.MPD_HOST;
+      };
+
+      local_music_dir = config.soispha.services.mpd.directories.music;
+    };
+
+    home-manager.users.soispha = {
+      systemd.user.services.mpdpopm = {
+        Unit = {
+          Description = "mpdpopm ratings and playcounts for MPD";
+          Requires = ["mpd.service"];
+          After = ["mpd.service"];
+        };
+
+        Service = {
+          Restart = "on-failure";
+          ExecStart = "${lib.getExe' pkgs.mpdpopm "mpdpopmd"} --config ${settingsFormat.generate "config.json" cfg.settings}";
+        };
+
+        Install = {WantedBy = ["default.target"];};
+      };
+    };
+  };
+}
diff --git a/modules/home.legacy/conf/beets/default.nix b/modules/home.legacy/conf/beets/default.nix
index 2fec6881..0132a859 100644
--- a/modules/home.legacy/conf/beets/default.nix
+++ b/modules/home.legacy/conf/beets/default.nix
@@ -105,7 +105,6 @@ in {
     };
 
     mpdIntegration = {
-      enableStats = true;
       enableUpdate = true;
       host = config.home.sessionVariables.MPD_HOST;
     };
diff --git a/modules/home.legacy/conf/beets/plugins.nix b/modules/home.legacy/conf/beets/plugins.nix
index ed78b49e..01d022c4 100644
--- a/modules/home.legacy/conf/beets/plugins.nix
+++ b/modules/home.legacy/conf/beets/plugins.nix
@@ -29,12 +29,6 @@
   # Show tags on files/queries
   "info"
 
-  # Create playlist from `play_count`/`skip_count` (gathered by the `mpdstats`
-  # plugin)
-  # Note that this should come _before_ the `mpdupdate` plugin, to ensure that
-  # `mpdupgate` can propagate changed playlist to `mpd`.
-  "smartplaylist"
-
   "inline"
 
   # Warn, when importing a matching item
@@ -58,6 +52,5 @@
   # Allow beets to understand deezer id's
   # "deezer"
 
-  "mpdstats" # Transfer MPD stats to beets
   "mpdupdate" # Update MPD database on import
 ]
diff --git a/modules/home.legacy/conf/beets/plugins/default.nix b/modules/home.legacy/conf/beets/plugins/default.nix
index d22369be..2b2bd607 100644
--- a/modules/home.legacy/conf/beets/plugins/default.nix
+++ b/modules/home.legacy/conf/beets/plugins/default.nix
@@ -15,7 +15,6 @@
     ./inline
     ./lyrics
     ./replaygain
-    ./smartplaylist
     # ./xtractor
   ];
 }
diff --git a/modules/home.legacy/conf/beets/plugins/smartplaylist/default.nix b/modules/home.legacy/conf/beets/plugins/smartplaylist/default.nix
deleted file mode 100644
index 9b52c1ad..00000000
--- a/modules/home.legacy/conf/beets/plugins/smartplaylist/default.nix
+++ /dev/null
@@ -1,42 +0,0 @@
-# nixos-config - My current NixOS configuration
-#
-# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-# This file is part of my nixos-config.
-#
-# You should have received a copy of the License along with this program.
-# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
-{config, ...}: {
-  programs.beets.settings.smartplaylist = {
-    relative_to = config.services.mpd.musicDirectory;
-    playlist_dir = config.services.mpd.playlistDirectory;
-    forward_slash = false;
-
-    # Show the real m3u file paths, when running `--pretend`
-    pretend_paths = true;
-
-    playlists = [
-      {
-        name = "artists-$first_artist.m3u";
-        query = "";
-      }
-      {
-        name = "ratings-good.m3u";
-        query = "rating:0.7..1.0";
-      }
-      {
-        name = "ratings-mediocre.m3u";
-        query = "rating:0.4..0.7";
-      }
-      {
-        name = "ratings-bad.m3u";
-        query = "rating:0.0..0.4";
-      }
-      {
-        name = "not_played.m3u";
-        query = "-play_count: artist:";
-      }
-    ];
-  };
-}
diff --git a/pkgs/by-name/mp/mpdpopm/.envrc b/pkgs/by-name/mp/mpdpopm/.envrc
index 57136674..9f477e71 100644
--- a/pkgs/by-name/mp/mpdpopm/.envrc
+++ b/pkgs/by-name/mp/mpdpopm/.envrc
@@ -18,6 +18,5 @@ PATH_add ./target/debug/
 PATH_add ./target/release/
 
 if on_git_branch; then
-    echo && git status --short --branch &&
-        echo && git fetch --verbose
+    echo && git status --short --branch
 fi
diff --git a/pkgs/by-name/mp/mpdpopm/Cargo.lock b/pkgs/by-name/mp/mpdpopm/Cargo.lock
index 02886740..fbedffd4 100644
--- a/pkgs/by-name/mp/mpdpopm/Cargo.lock
+++ b/pkgs/by-name/mp/mpdpopm/Cargo.lock
@@ -557,27 +557,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
-name = "lexpr"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a84de6a9df442363b08f5dbf0cd5b92edc70097b89c4ce4bfea4679fe48bc67"
-dependencies = [
- "itoa",
- "lexpr-macros",
- "ryu",
-]
-
-[[package]]
-name = "lexpr-macros"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36b5cb8bb985c81a8ac1a0f8b5c4865214f574ddd64397ef7a99c236e21f35bb"
-dependencies = [
- "proc-macro2",
- "quote",
-]
-
-[[package]]
 name = "libc"
 version = "0.2.180"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -651,7 +630,7 @@ dependencies = [
  "pin-project",
  "regex",
  "serde",
- "serde-lexpr",
+ "serde_json",
  "snafu",
  "tokio",
  "toml",
@@ -868,12 +847,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
 
 [[package]]
-name = "ryu"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
-
-[[package]]
 name = "same-file"
 version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -899,16 +872,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "serde-lexpr"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb4cda13396159f59e7946118cdac0beadeecfb7cf76b197f4147e546f4ead6f"
-dependencies = [
- "lexpr",
- "serde",
-]
-
-[[package]]
 name = "serde_core"
 version = "1.0.228"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -929,6 +892,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "serde_json"
+version = "1.0.149"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
+dependencies = [
+ "itoa",
+ "memchr",
+ "serde",
+ "serde_core",
+ "zmij",
+]
+
+[[package]]
 name = "serde_spanned"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1449,3 +1425,9 @@ name = "winnow"
 version = "0.7.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
+
+[[package]]
+name = "zmij"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65"
diff --git a/pkgs/by-name/mp/mpdpopm/Cargo.toml b/pkgs/by-name/mp/mpdpopm/Cargo.toml
index 0bb63394..ccadfabb 100644
--- a/pkgs/by-name/mp/mpdpopm/Cargo.toml
+++ b/pkgs/by-name/mp/mpdpopm/Cargo.toml
@@ -37,7 +37,7 @@ os_str_bytes = "7.1"
 pin-project = "1.1"
 regex = "1.12"
 serde = { version = "1.0", features = ["derive"] }
-serde-lexpr = "0.1.3"
+serde_json = "1.0.149"
 snafu = { version = "0.8.9", features = ["backtrace"] }
 toml = "0.9"
 tokio = { version = "1.49", features = ["io-util", "macros", "net", "process", "rt-multi-thread", "signal", "sync", "time"] }
diff --git a/pkgs/by-name/mp/mpdpopm/src/config.rs b/pkgs/by-name/mp/mpdpopm/src/config.rs
index da8e63be..08509e47 100644
--- a/pkgs/by-name/mp/mpdpopm/src/config.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/config.rs
@@ -59,7 +59,7 @@ mod test_connection {
 
     #[test]
     fn test_serde() {
-        use serde_lexpr::to_string;
+        use serde_json::to_string;
 
         use std::path::PathBuf;
 
@@ -67,10 +67,12 @@ mod test_connection {
             path: PathBuf::from("/var/run/mpd.sock"),
         })
         .unwrap();
+
         assert_eq!(
             text,
-            String::from(r#"(Local (path . "/var/run/mpd.sock"))"#)
+            String::from(r#"{"Local":{"path":"/var/run/mpd.sock"}}"#)
         );
+
         let text = to_string(&Connection::TCP {
             host: String::from("localhost"),
             port: 6600,
@@ -78,7 +80,7 @@ mod test_connection {
         .unwrap();
         assert_eq!(
             text,
-            String::from(r#"(TCP (host . "localhost") (port . 6600))"#)
+            String::from(r#"{"TCP":{"host":"localhost","port":6600}}"#)
         );
     }
 }
@@ -156,7 +158,7 @@ impl std::fmt::Display for Error {
 pub type Result<T> = std::result::Result<T, Error>;
 
 pub fn from_str(text: &str) -> Result<Config> {
-    let cfg: Config = match serde_lexpr::from_str(text) {
+    let cfg: Config = match serde_json::from_str(text) {
         Ok(cfg) => cfg,
         Err(err_outer) => {
             return Err(Error::ParseFail {
@@ -172,19 +174,20 @@ mod test {
     use super::*;
 
     #[test]
+    #[ignore = "We changed the config format to json"]
     fn test_from_str() {
         let cfg = Config::default();
         assert_eq!(cfg.commands_chan, String::from("unwoundstack.com:commands"));
 
         assert_eq!(
-            serde_lexpr::to_string(&cfg).unwrap(),
+            serde_json::to_string(&cfg).unwrap(),
             format!(
                 r#"((version . "1") (log . "{}/log/mppopmd.log") (conn TCP (host . "localhost") (port . 6600)) (local_music_dir . "{}/Music") (playcount_sticker . "unwoundstack.com:playcount") (lastplayed_sticker . "unwoundstack.com:lastplayed") (played_thresh . 0.6) (poll_interval_ms . 5000) (commands_chan . "unwoundstack.com:commands") (playcount_command . "") (playcount_command_args) (rating_sticker . "unwoundstack.com:rating") (ratings_command . "") (ratings_command_args) (gen_cmds))"#,
                 LOCALSTATEDIR, PREFIX
             )
         );
 
-        let cfg: Config = serde_lexpr::from_str(
+        let cfg: Config = serde_json::from_str(
             r#"
 ((version . "1")
  (log . "/usr/local/var/log/mppopmd.log")
@@ -206,7 +209,7 @@ mod test {
         .unwrap();
         assert_eq!(cfg._version, String::from("1"));
 
-        let cfg: Config = serde_lexpr::from_str(
+        let cfg: Config = serde_json::from_str(
             r#"
 ((version . "1")
  (log . "/usr/local/var/log/mppopmd.log")
diff --git a/pkgs/by-name/mp/mpdpopm/src/filters_ast.rs b/pkgs/by-name/mp/mpdpopm/src/filters_ast.rs
index 15f249fb..7d30739d 100644
--- a/pkgs/by-name/mp/mpdpopm/src/filters_ast.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/filters_ast.rs
@@ -816,9 +816,15 @@ pub struct FilterStickerNames<'a> {
     lastplayed: &'a str,
 }
 
-impl<'a> FilterStickerNames<'a> {
-    pub fn new() -> FilterStickerNames<'a> {
-        FilterStickerNames {
+impl FilterStickerNames<'static> {
+    pub fn new() -> FilterStickerNames<'static> {
+        Self::default()
+    }
+}
+
+impl Default for FilterStickerNames<'static> {
+    fn default() -> Self {
+        Self {
             rating: rating_count::STICKER,
             playcount: play_count::STICKER,
             lastplayed: last_played::STICKER,
@@ -1151,7 +1157,7 @@ OK",
         )]));
         let mut cli = Client::new(mock).unwrap();
 
-        let stickers = FilterStickerNames::new("rating", "playcount", "lastplayed");
+        let stickers = FilterStickerNames::new();
 
         let expr = ExpressionParser::new().parse(r#"(base "foo")"#).unwrap();
         let result = evaluate(&expr, true, &mut cli, &stickers).await;
diff --git a/pkgs/by-name/mp/mpdpopm/src/playcounts.rs b/pkgs/by-name/mp/mpdpopm/src/playcounts.rs
index 4e308d4a..6ae8f903 100644
--- a/pkgs/by-name/mp/mpdpopm/src/playcounts.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/playcounts.rs
@@ -337,12 +337,12 @@ OK
 ",
             ),
             (
-                "sticker get song \"E/Enya - Wild Child.mp3\" pc",
-                "sticker: pc=11\nOK\n",
+                "sticker get song \"E/Enya - Wild Child.mp3\" unwoundstack.com:playcount",
+                "sticker: unwoundstack.com:playcount=11\nOK\n",
             ),
             (
                 &format!(
-                    "sticker set song \"E/Enya - Wild Child.mp3\" lp {}",
+                    "sticker set song \"E/Enya - Wild Child.mp3\" unwoundstack.com:lastplayed {}",
                     SystemTime::now()
                         .duration_since(SystemTime::UNIX_EPOCH)
                         .unwrap()
@@ -350,7 +350,7 @@ OK
                 ),
                 "OK\n",
             ),
-            ("sticker set song \"E/Enya - Wild Child.mp3\" pc 12", "OK\n"),
+            ("sticker set song \"E/Enya - Wild Child.mp3\" unwoundstack.com:playcount 12", "OK\n"),
         ]));
 
         let mut cli = Client::new(mock).unwrap();
diff --git a/pkgs/by-name/mp/mpdpopm/src/storage/mod.rs b/pkgs/by-name/mp/mpdpopm/src/storage/mod.rs
index 29cfe144..325b633a 100644
--- a/pkgs/by-name/mp/mpdpopm/src/storage/mod.rs
+++ b/pkgs/by-name/mp/mpdpopm/src/storage/mod.rs
@@ -93,12 +93,12 @@ pub mod play_count {
         #[tokio::test]
         async fn pc_smoke() {
             let mock = Box::new(Mock::new(&[
-                ("sticker get song a pc", "sticker: pc=11\nOK\n"),
+                ("sticker get song a unwoundstack.com:playcount", "sticker: unwoundstack.com:playcount=11\nOK\n"),
                 (
-                    "sticker get song a pc",
+                    "sticker get song a unwoundstack.com:playcount",
                     "ACK [50@0] {sticker} no such sticker\n",
                 ),
-                ("sticker get song a pc", "splat!"),
+                ("sticker get song a unwoundstack.com:playcount", "splat!"),
             ]));
             let mut cli = Client::new(mock).unwrap();