From 368db8aea6f80e201d6df5fe3b7c7796ada3b866 Mon Sep 17 00:00:00 2001 From: novenary Date: Mon, 23 Dec 2024 23:52:43 +0200 Subject: [PATCH] librespot: init module Librespot is a Spotify client. While there is already a module for spotifyd, which uses Librespot as a library, this adds one for the upstream frontend. --- modules/modules.nix | 1 + modules/services/librespot.nix | 88 ++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 modules/services/librespot.nix diff --git a/modules/modules.nix b/modules/modules.nix index d7f139333..a7d6f2394 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -327,6 +327,7 @@ let ./services/kdeconnect.nix ./services/keybase.nix ./services/keynav.nix + ./services/librespot.nix ./services/lieer.nix ./services/listenbrainz-mpd.nix ./services/lorri.nix diff --git a/modules/services/librespot.nix b/modules/services/librespot.nix new file mode 100644 index 000000000..f8e19c0a8 --- /dev/null +++ b/modules/services/librespot.nix @@ -0,0 +1,88 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) types; + + # Like lib.mapAttrsToList, but concatenate the results + concatMapAttrsToList = f: attrs: + builtins.concatMap (name: f name attrs.${name}) (builtins.attrNames attrs); + + cfg = config.services.librespot; +in { + options.services.librespot = { + enable = lib.mkEnableOption "Librespot (Spotify Connect speaker daemon)"; + + package = lib.mkPackageOption pkgs "librespot" { }; + + settings = lib.mkOption { + description = '' + Command-line arguments to pass to librespot. + + Boolean values render as a flag if true, and nothing if false. + Null values are ignored. + All other values are rendered as options with an argument. + ''; + type = types.submodule { + freeformType = let t = types; + in t.attrsOf (t.nullOr (t.oneOf [ t.bool t.str t.int t.path ])); + + options = { + cache = lib.mkOption { + default = "${config.xdg.cacheHome}/librespot"; + defaultText = "$XDG_CACHE_HOME/librespot"; + type = types.nullOr types.path; + description = + "Path to a directory where files will be cached after downloading."; + }; + + system-cache = lib.mkOption { + default = "${config.xdg.stateHome}/librespot"; + defaultText = "$XDG_STATE_HOME/librespot"; + type = types.nullOr types.path; + description = + "Path to a directory where system files (credentials, volume) will be cached."; + }; + }; + }; + default = { }; + }; + + args = lib.mkOption { + type = types.listOf types.str; + internal = true; + description = '' + Command-line arguments to pass to the service. + + This is generated from {option}`services.librespot.settings`. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + services.librespot = { + args = concatMapAttrsToList (k: v: + if v == null || v == false then + [ ] + else if v == true then + [ "--${k}" ] + else + [ "--${k}=${toString v}" ]) cfg.settings; + }; + + home.packages = [ cfg.package ]; + + systemd.user.services.librespot = { + Unit = { Description = "Librespot (an open source Spotify client)"; }; + + Install.WantedBy = [ "default.target" ]; + + Service = { + ExecStart = pkgs.writeShellScript "librespot" '' + exec '${cfg.package}/bin/librespot' ${lib.escapeShellArgs cfg.args} + ''; + Restart = "always"; + RestartSec = 12; + }; + }; + }; +}