Subject: Librespot package and service

From: Noé Lopez <[email-masked]>
Date: Sat, 13 Apr 2024 01:01:09 +0200

Hi,

I've started writing a package for librespot, a spotify client similar
to spotifyd which is already packaged. I've gotten the package to build
and work, but I also wanted a home service to run it automatically with
shepherd.

This is my first time making a home service, can someone review my code
to make sure it follows good practices ? I would love to get feedback on
this and then submit it as a patch. Thanks in advance.

The usage for the home service is as follows:
   (service home-librespot-service-type
	    (for-home
	     (librespot-configuration
	      (username "...")
	      (password "..."))))

P.S. I'm moderately sure that the spotifyd package is using
pulseaudio as a dependency incorrectly, from my understanding spotifyd
uses exclusively ALSA, unless the pulseaudio backend is selected but
that's very optional.

Thanks in advance,
Noé Lopez

(define-module (gnu packages librespot)
  #:use-module (gnu services)
  #:use-module (gnu services shepherd)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix packages)
  #:use-module (guix download)
  #:use-module (gnu packages crates-io)
  #:use-module (gnu packages crates-web)
  #:use-module (gnu packages crates-crypto)
  #:use-module (gnu packages pkg-config)
  #:use-module (gnu packages linux)
  #:use-module (guix records)
  #:use-module (guix build-system cargo)
  #:use-module (gnu home services)
  #:use-module (guix gexp)
  #:use-module (srfi srfi-9)
  #:export (librespot-configuration
            librespot-configuration?
	    librespot-service-type
	    home-librespot-service-type))

(define-public rust-librespot-0.4
  (package
    (name "rust-librespot")
    (version "0.4.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "librespot" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "0i2aisbw9ngp51d2sd13wvmjc94qfs2pza54hj0qz5j8xx99jk7a"))))
    (build-system cargo-build-system)
    (native-inputs (list pkg-config))
    (inputs (list alsa-lib))
    (arguments
     `(#:cargo-inputs (("rust-base64" ,rust-base64-0.13)
                       ("rust-env-logger" ,rust-env-logger-0.9)
                       ("rust-futures-util" ,rust-futures-util-0.3)
                       ("rust-getopts" ,rust-getopts-0.2)
                       ("rust-hex" ,rust-hex-0.4)
                       ("rust-hyper" ,rust-hyper-0.14)
                       ("rust-librespot-audio" ,rust-librespot-audio-0.4)
                       ("rust-librespot-connect" ,rust-librespot-connect-0.4)
                       ("rust-librespot-core" ,rust-librespot-core-0.4)
                       ("rust-librespot-discovery" ,rust-librespot-discovery-0.4)
                       ("rust-librespot-metadata" ,rust-librespot-metadata-0.4)
                       ("rust-librespot-playback" ,rust-librespot-playback-0.4)
                       ("rust-librespot-protocol" ,rust-librespot-protocol-0.4)
                       ("rust-log" ,rust-log-0.4)
                       ("rust-rpassword" ,rust-rpassword-6)
                       ("rust-sha-1" ,rust-sha-1-0.9)
                       ("rust-thiserror" ,rust-thiserror-1)
                       ("rust-tokio" ,rust-tokio-1)
                       ("rust-url" ,rust-url-2))))
    (home-page "https://github.com/librespot-org/librespot")
    (synopsis
     "Open source client library for Spotify, with support for Spotify Connect")
    (description
     "Librespot is a daemon that connects to the Spotify music and can
be controlled by clients that use the Spotify Connect protocel, which
includes the official Spotify mobile apps.")
    (license license:expat)))

(define-record-type* <librespot-configuration>
  librespot-configuration make-librespot-configuration
  librespot-configuration?
  (librespot librespot-configuration-librespot ;file-like
	     (default rust-librespot-0.4))
  (username librespot-configuration-username) ;string
  (password librespot-configuration-password) ;string
  (arguments librespot-configuration-arguments ;list of strings
	     (default '())))

(define librespot-shepherd-service
  (match-record-lambda <librespot-configuration>
      (librespot username password arguments)
    (list
     (shepherd-service
      (provision '(librespot))
      (documentation "Run librespot.")
      (requirement '())
      (start #~(make-forkexec-constructor
		(cons (string-append #$librespot "/bin/librespot") '#$arguments)
		#:environment-variables
		(append (list
			 (string-append "LIBRESPOT_USERNAME=" #$username)
			 (string-append "LIBRESPOT_PASSWORD=" #$password))
			 (environ))))
      (respawn? #f)
      (stop #~(make-kill-destructor))))))

(define librespot-service-type
  (service-type
   (name 'librespot)
   (extensions (list (service-extension shepherd-root-service-type
                                        librespot-shepherd-service)))
   (description "Run librespot. A spotify client.")))

(define home-librespot-service-type
  (service-type
   (inherit (system->home-service-type librespot-service-type))))