From patchwork Thu Feb 2 20:07:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bruno Victal X-Patchwork-Id: 46607 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id 8258D27BBED; Thu, 2 Feb 2023 20:08:18 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-3.9 required=5.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS autolearn=ham autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id C7C6527BBE9 for ; Thu, 2 Feb 2023 20:08:16 +0000 (GMT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pNfsK-0002oo-Ee; Thu, 02 Feb 2023 15:08:04 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pNfsI-0002mW-Ry for guix-patches@gnu.org; Thu, 02 Feb 2023 15:08:02 -0500 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pNfsI-0004JZ-Jo for guix-patches@gnu.org; Thu, 02 Feb 2023 15:08:02 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pNfsI-0007a1-FM for guix-patches@gnu.org; Thu, 02 Feb 2023 15:08:02 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#59866] [PATCH v6 1/3] services: mpd: Rewrite using 'define-configuration'. References: In-Reply-To: Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 02 Feb 2023 20:08:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 59866 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 59866@debbugs.gnu.org Cc: Bruno Victal , liliana.prikler@gmail.com Received: via spool by 59866-submit@debbugs.gnu.org id=B59866.167536846929116 (code B ref 59866); Thu, 02 Feb 2023 20:08:02 +0000 Received: (at 59866) by debbugs.gnu.org; 2 Feb 2023 20:07:49 +0000 Received: from localhost ([127.0.0.1]:35879 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pNfs5-0007ZX-1Q for submit@debbugs.gnu.org; Thu, 02 Feb 2023 15:07:49 -0500 Received: from smtpmciv3.myservices.hosting ([185.26.107.239]:55878) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pNfs3-0007ZN-FD for 59866@debbugs.gnu.org; Thu, 02 Feb 2023 15:07:48 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.172]) by smtpmciv3.myservices.hosting (Postfix) with ESMTP id 549292079E; Thu, 2 Feb 2023 21:07:45 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id 0E92E80096; Thu, 2 Feb 2023 21:07:45 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-1.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id s5UzeYsfdz2q; Thu, 2 Feb 2023 21:07:42 +0100 (CET) Received: from guix-nuc.home.arpa (bl9-118-236.dsl.telepac.pt [85.242.118.236]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id D489980093; Thu, 2 Feb 2023 21:07:41 +0100 (CET) From: Bruno Victal Date: Thu, 2 Feb 2023 20:07:36 +0000 Message-Id: <23b0f83d1fd58fce9262d0b281b34e9678e21471.1675367583.git.mirai@makinata.eu> X-Mailer: git-send-email 2.38.1 MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches * gnu/services/audio.scm (mpd-configuration, mpd-output): Rewrite using define-configuration. (uglify-field-name, mpd-serialize-field, mpd-serialize-alist) (mpd-serialize-number, mpd-serialize-boolean, mpd-serialize-list-of-mpd-output) (mpd-serialize-configuration): New procedure. (list-of-mpd-output?): New predicate. (mpd-config->file, mpd-output->string): Remove procedure. --- Notable changes since v5: * Completely eliminate indented procedures from patchset. gnu/services/audio.scm | 222 ++++++++++++++++++++++++----------------- 1 file changed, 133 insertions(+), 89 deletions(-) diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm index c60053f33c..b7cb0ebe38 100644 --- a/gnu/services/audio.scm +++ b/gnu/services/audio.scm @@ -2,6 +2,7 @@ ;;; Copyright © 2017 Peter Mikkelsen ;;; Copyright © 2019 Ricardo Wurmus ;;; Copyright © 2020 Ludovic Courtès +;;; Copyright © 2022 Bruno Victal ;;; ;;; This file is part of GNU Guix. ;;; @@ -21,13 +22,15 @@ (define-module (gnu services audio) #:use-module (guix gexp) #:use-module (gnu services) + #:use-module (gnu services configuration) #:use-module (gnu services shepherd) #:use-module (gnu system shadow) #:use-module (gnu packages admin) #:use-module (gnu packages mpd) #:use-module (guix records) #:use-module (ice-9 match) - #:use-module (ice-9 format) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-26) #:export (mpd-output mpd-output? mpd-configuration @@ -40,93 +43,134 @@ (define-module (gnu services audio) ;;; ;;; Code: -(define-record-type* - mpd-output make-mpd-output - mpd-output? - (type mpd-output-type - (default "pulse")) - (name mpd-output-name - (default "MPD")) - (enabled? mpd-output-enabled? - (default #t)) - (tags? mpd-output-tags? - (default #t)) - (always-on? mpd-output-always-on? - (default #f)) - (mixer-type mpd-output-mixer-type - ;; valid: hardware, software, null, none - (default #f)) - (extra-options mpd-output-extra-options - (default '()))) - -(define-record-type* - mpd-configuration make-mpd-configuration - mpd-configuration? - (user mpd-configuration-user - (default "mpd")) - (music-dir mpd-configuration-music-dir - (default "~/Music")) - (playlist-dir mpd-configuration-playlist-dir - (default "~/.mpd/playlists")) - (db-file mpd-configuration-db-file - (default "~/.mpd/tag_cache")) - (state-file mpd-configuration-state-file - (default "~/.mpd/state")) - (sticker-file mpd-configuration-sticker-file - (default "~/.mpd/sticker.sql")) - (port mpd-configuration-port - (default "6600")) - (address mpd-configuration-address - (default "any")) - (outputs mpd-configuration-outputs - (default (list (mpd-output))))) - -(define (mpd-output->string output) - "Convert the OUTPUT of type to a configuration file snippet." - (let ((extra (string-join - (map (match-lambda - ((key . value) - (format #f " ~a \"~a\"" - (string-map - (lambda (c) (if (char=? c #\-) #\_ c)) - (symbol->string key)) - value))) - (mpd-output-extra-options output)) - "\n"))) - (format #f "\ -audio_output { - type \"~a\" - name \"~a\" -~:[ enabled \"no\"~%~;~]\ -~:[ tags \"no\"~%~;~]\ -~:[~; always_on \"yes\"~%~]\ -~@[ mixer_type \"~a\"~%~]\ -~a~%}~%" - (mpd-output-type output) - (mpd-output-name output) - (mpd-output-enabled? output) - (mpd-output-tags? output) - (mpd-output-always-on? output) - (mpd-output-mixer-type output) - extra))) - -(define (mpd-config->file config) - (apply - mixed-text-file "mpd.conf" - "pid_file \"" (mpd-file-name config "pid") "\"\n" - (append (map mpd-output->string - (mpd-configuration-outputs config)) - (map (match-lambda - ((config-name config-val) - (string-append config-name " \"" (config-val config) "\"\n"))) - `(("user" ,mpd-configuration-user) - ("music_directory" ,mpd-configuration-music-dir) - ("playlist_directory" ,mpd-configuration-playlist-dir) - ("db_file" ,mpd-configuration-db-file) - ("state_file" ,mpd-configuration-state-file) - ("sticker_file" ,mpd-configuration-sticker-file) - ("port" ,mpd-configuration-port) - ("bind_to_address" ,mpd-configuration-address)))))) +(define (uglify-field-name field-name) + (let ((str (symbol->string field-name))) + (string-join (string-split (if (string-suffix? "?" str) + (string-drop-right str 1) + str) + #\-) "_"))) + +(define (mpd-serialize-field field-name value) + #~(format #f "~a ~s~%" #$(if (string? field-name) + field-name + (uglify-field-name field-name)) + #$(if (string? value) + value + (object->string value)))) + +(define (mpd-serialize-alist field-name value) + #~(string-append #$@(generic-serialize-alist list mpd-serialize-field + value))) + +(define mpd-serialize-string mpd-serialize-field) + +(define (mpd-serialize-boolean field-name value) + (mpd-serialize-field field-name (if value "yes" "no"))) + +(define (mpd-serialize-list-of-mpd-output field-name value) + #~(string-append "\naudio_output {\n" + #$@(map (cut serialize-configuration <> + mpd-output-fields) + value) + "}\n")) + +(define (mpd-serialize-configuration configuration) + (mixed-text-file + "mpd.conf" + (serialize-configuration configuration mpd-configuration-fields))) + +(define-configuration mpd-output + (name + (string "MPD") + "The name of the audio output.") + + (type + (string "pulse") + "The type of audio output.") + + (enabled? + (boolean #t) + "Specifies whether this audio output is enabled when MPD is started. By +default, all audio outputs are enabled. This is just the default +setting when there is no state file; with a state file, the previous +state is restored.") + + (tags? + (boolean #t) + "If set to @code{#f}, then MPD will not send tags to this output. This +is only useful for output plugins that can receive tags, for example the +@code{httpd} output plugin.") + + (always-on? + (boolean #f) + "If set to @code{#t}, then MPD attempts to keep this audio output always +open. This may be useful for streaming servers, when you don’t want to +disconnect all listeners even when playback is accidentally stopped.") + + (mixer-type + (string "none") + "This field accepts a symbol that specifies which mixer should be used +for this audio output: the @code{hardware} mixer, the @code{software} +mixer, the @code{null} mixer (allows setting the volume, but with no +effect; this can be used as a trick to implement an external mixer +External Mixer) or no mixer (@code{none}).") + + (extra-options + (alist '()) + "An association list of option symbols to string values to be appended to +the audio output configuration.") + + (prefix mpd-)) + +(define list-of-mpd-output? + (list-of mpd-output?)) + +(define-configuration mpd-configuration + (user + (string "mpd") + "The user to run mpd as.") + + (music-dir + (string "~/Music") + "The directory to scan for music files." + (lambda (_ x) + (mpd-serialize-field "music_directory" x))) + + (playlist-dir + (string "~/.mpd/playlists") + "The directory to store playlists." + (lambda (_ x) + (mpd-serialize-field "playlist_directory" x))) + + (db-file + (string "~/.mpd/tag_cache") + "The location of the music database.") + + (state-file + (string "~/.mpd/state") + "The location of the file that stores current MPD's state.") + + (sticker-file + (string "~/.mpd/sticker.sql") + "The location of the sticker database.") + + (port + (string "6600") + "The port to run mpd on.") + + (address + (string "any") + "The address that mpd will bind to. +To use a Unix domain socket, an absolute path can be specified here." + (lambda (_ x) + (mpd-serialize-field "bind_to_address" x))) + + (outputs + (list-of-mpd-output (list (mpd-output))) + "The audio outputs that MPD can use. +By default this is a single output using pulseaudio.") + + (prefix mpd-)) (define (mpd-file-name config file) "Return a path in /var/run/mpd/ that is writable @@ -143,7 +187,7 @@ (define (mpd-shepherd-service config) (start #~(make-forkexec-constructor (list #$(file-append mpd "/bin/mpd") "--no-daemon" - #$(mpd-config->file config)) + #$(mpd-serialize-configuration config)) #:environment-variables ;; Required to detect PulseAudio when run under a user account. (list (string-append From patchwork Thu Feb 2 20:07:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bruno Victal X-Patchwork-Id: 46608 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id B5F4C27BBEB; Thu, 2 Feb 2023 20:09:16 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-3.9 required=5.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id 0750727BBE9 for ; Thu, 2 Feb 2023 20:09:10 +0000 (GMT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pNftI-0003gN-UA; Thu, 02 Feb 2023 15:09:05 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pNftH-0003gB-1m for guix-patches@gnu.org; Thu, 02 Feb 2023 15:09:03 -0500 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pNftG-0004Zu-2S for guix-patches@gnu.org; Thu, 02 Feb 2023 15:09:02 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pNftF-0007bi-U6 for guix-patches@gnu.org; Thu, 02 Feb 2023 15:09:01 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#59866] [PATCH v6 2/3] services: mpd: Refactor MPD service. Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 02 Feb 2023 20:09:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 59866 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 59866@debbugs.gnu.org Cc: Bruno Victal , liliana.prikler@gmail.com Received: via spool by 59866-submit@debbugs.gnu.org id=B59866.167536849529183 (code B ref 59866); Thu, 02 Feb 2023 20:09:01 +0000 Received: (at 59866) by debbugs.gnu.org; 2 Feb 2023 20:08:15 +0000 Received: from localhost ([127.0.0.1]:35883 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pNfsT-0007ac-Sc for submit@debbugs.gnu.org; Thu, 02 Feb 2023 15:08:15 -0500 Received: from smtpm2.myservices.hosting ([185.26.105.233]:40388) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pNfsQ-0007aR-Tq for 59866@debbugs.gnu.org; Thu, 02 Feb 2023 15:08:12 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.172]) by smtpm2.myservices.hosting (Postfix) with ESMTP id EF1EE20E7C; Thu, 2 Feb 2023 21:08:09 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id B061480096; Thu, 2 Feb 2023 21:08:09 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-1.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id L-GJINCNunHY; Thu, 2 Feb 2023 21:08:08 +0100 (CET) Received: from guix-nuc.home.arpa (bl9-118-236.dsl.telepac.pt [85.242.118.236]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id 8E76380093; Thu, 2 Feb 2023 21:08:08 +0100 (CET) From: Bruno Victal Date: Thu, 2 Feb 2023 20:07:37 +0000 Message-Id: X-Mailer: git-send-email 2.38.1 In-Reply-To: <23b0f83d1fd58fce9262d0b281b34e9678e21471.1675367583.git.mirai@makinata.eu> References: <23b0f83d1fd58fce9262d0b281b34e9678e21471.1675367583.git.mirai@makinata.eu> MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches Refactor mpd-service-type to support additional mpd.conf directives and move activation-service-extension into service constructor. * gnu/services/audio.scm (mpd-plugin, mpd-partition): New record. (mpd-serialize-boolean, mpd-serialize-field): Integrate serializers into a single procedure for alist interop. (mpd-plugin?, mpd-partition?, list-of-string?, list-of-symbol?) (list-of-mpd-plugin?, list-of-mpd-partition?) (list-of-mpd-plugin-or-output?, port?): New predicate. (mpd-file-name, mpd-service-activation): Remove procedure. (mpd-configuration) [package, group, shepherd-requirement, log-file, log-level, music-directory] [playlist-directory, endpoints, database, partitions, neighbors, inputs] [archive-plugins, input-cache-size, decoders, resampler, filters] [playlist-plugins, extra-options]: New field. [music-dir, playlist-dir, address]: Deprecate shorthand field. [db-file, state-file, sticker-file, port, outputs]: Change admissible type. (mpd-shepherd-service) [actions]: New shepherd actions: 'reopen' and 'configuration'. [requirement]: Splice with 'shepherd-requirement' field. [start]: Use 'package' field. Remove #:log-file parameter. Move activation-service extension into constructor. (mpd-accounts): Honor user and group names from configuration. (mpd-log-rotation): New procedure. (mpd-service-type)[extensions]: Add rottlog-service-type extension. Remove activation-service-type extension. (mpd-output-name, mpd-output-type, mpd-output-enabled?, mpd-output-format) (mpd-output-tags?, mpd-output-always-on?, mpd-output-mixer-type) (mpd-output-replay-gain-handler, mpd-output-extra-options) (mpd-plugin-plugin, mpd-plugin-name, mpd-plugin-enabled?) (mpd-plugin-extra-options) (mpd-partition-name, mpd-partition-extra-options) (mpd-configuration-package, mpd-configuration-user) (mpd-configuration-group, mpd-configuration-shepherd-requirement) (mpd-configuration-log-file, mpd-configuration-log-level) (mpd-configuration-music-directory, mpd-configuration-music-dir) (mpd-configuration-playlist-directory, mpd-configuration-playlist-dir) (mpd-configuration-db-file, mpd-configuration-state-file) (mpd-configuration-sticker-file, mpd-configuration-default-port) (mpd-configuration-endpoints, mpd-configuration-address) (mpd-configuration-database, mpd-configuration-partitions) (mpd-configuration-neighbors, mpd-configuration-inputs) (mpd-configuration-archive-plugins, mpd-configuration-input-cache-size) (mpd-configuration-decoders, mpd-configuration-resampler) (mpd-configuration-filters, mpd-configuration-outputs) (mpd-configuration-playlist-plugins, mpd-configuration-extra-options): Export accessors. * doc/guix.texi (Audio Services)[Music Player Daemon]: Update doc. --- Notable changes since v5: * Export accessors. * Integrate activation-service-type extension into service constructor. * Honor existing directories and permissions, only create when absent. doc/guix.texi | 177 ++++++++++++--- gnu/services/audio.scm | 492 +++++++++++++++++++++++++++++++++-------- 2 files changed, 543 insertions(+), 126 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 64873db00b..8e220e0631 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -109,6 +109,7 @@ Copyright @copyright{} 2022 Simon Streit@* Copyright @copyright{} 2022 (@* Copyright @copyright{} 2022 John Kehayias@* +Copyright @copyright{} 2022 Bruno Victal@* Copyright @copyright{} 2022 Ivan Vilata-i-Balaguer@* Copyright @copyright{} 2023 Giacomo Leidi@* Copyright @copyright{} 2022 Antero Mejr@* @@ -33185,79 +33186,187 @@ Audio Services Data type representing the configuration of @command{mpd}. @table @asis -@item @code{user} (default: @code{"mpd"}) +@item @code{package} (default: @code{mpd}) (type: file-like) +The MPD package. + +@item @code{user} (default: @code{"mpd"}) (type: string) The user to run mpd as. -@item @code{music-dir} (default: @code{"~/Music"}) +@item @code{group} (default: @code{"mpd"}) (type: string) +The group to run mpd as. + +@item @code{shepherd-requirement} (default: @code{()}) (type: list-of-symbol) +This is a list of symbols naming Shepherd services that this service +will depend on. + +@item @code{log-file} (default: @code{"/var/log/mpd/log"}) (type: maybe-string) +The location of the log file. Set to @code{syslog} to use the local +syslog daemon or @code{%unset-value} to omit this directive from the +configuration file. + +@item @code{log-level} (type: maybe-string) +Supress any messages below this threshold. Available values: +@code{notice}, @code{info}, @code{verbose}, @code{warning} and +@code{error}. + +@item @code{music-directory} (type: maybe-string) The directory to scan for music files. -@item @code{playlist-dir} (default: @code{"~/.mpd/playlists"}) +@item @code{playlist-directory} (type: maybe-string) The directory to store playlists. -@item @code{db-file} (default: @code{"~/.mpd/tag_cache"}) +@item @code{db-file} (type: maybe-string) The location of the music database. -@item @code{state-file} (default: @code{"~/.mpd/state"}) +@item @code{state-file} (type: maybe-string) The location of the file that stores current MPD's state. -@item @code{sticker-file} (default: @code{"~/.mpd/sticker.sql"}) +@item @code{sticker-file} (type: maybe-string) The location of the sticker database. -@item @code{port} (default: @code{"6600"}) -The port to run mpd on. +@item @code{default-port} (default: @code{6600}) (type: maybe-integer) +The default port to run mpd on. + +@item @code{endpoints} (type: maybe-list-of-string) +The addresses that mpd will bind to. A port different from @var{default-port} +may be specified, e.g. @code{localhost:6602} and IPv6 addresses must be +enclosed in square brackets when a different port is used. +To use a Unix domain socket, an absolute path or a path starting with @code{~} +can be specified here. + +@item @code{database} (type: maybe-mpd-plugin) +MPD database plugin configuration. + +@item @code{partitions} (default: @code{()}) (type: list-of-mpd-partition) +List of MPD "partitions". -@item @code{address} (default: @code{"any"}) -The address that mpd will bind to. To use a Unix domain socket, -an absolute path can be specified here. +@item @code{neighbors} (default: @code{()}) (type: list-of-mpd-plugin) +List of MPD neighbor plugin configurations. -@item @code{outputs} (default: @code{"(list (mpd-output))"}) -The audio outputs that MPD can use. By default this is a single output using pulseaudio. +@item @code{inputs} (default: @code{()}) (type: list-of-mpd-plugin) +List of MPD input plugin configurations. + +@item @code{archive-plugins} (default: @code{()}) (type: list-of-mpd-plugin) +List of MPD archive plugin configurations. + +@item @code{input-cache-size} (type: maybe-string) +MPD input cache size. + +@item @code{decoders} (default: @code{()}) (type: list-of-mpd-plugin) +List of MPD decoder plugin configurations. + +@item @code{resampler} (type: maybe-mpd-plugin) +MPD resampler plugin configuration. + +@item @code{filters} (default: @code{()}) (type: list-of-mpd-plugin) +List of MPD filter plugin configurations. + +@item @code{outputs} (type: list-of-mpd-plugin-or-output) +The audio outputs that MPD can use. By default this is a single output +using pulseaudio. + +@item @code{playlist-plugins} (default: @code{()}) (type: list-of-mpd-plugin) +List of MPD playlist plugin configurations. + +@item @code{extra-options} (default: @code{()}) (type: alist) +An association list of option symbols/strings to string values to be +appended to the configuration. + +@end table +@end deftp + +@deftp {Data Type} mpd-plugin +Data type representing a @command{mpd} plugin. + +@table @asis +@item @code{plugin} (type: maybe-string) +Plugin name. + +@item @code{name} (type: maybe-string) +Name. + +@item @code{enabled?} (type: maybe-boolean) +Whether the plugin is enabled/disabled. + +@item @code{extra-options} (default: @code{()}) (type: alist) +An association list of option symbols/strings to string values to be +appended to the plugin configuration. See +@uref{https://mpd.readthedocs.io/en/latest/plugins.html,MPD plugin +reference} for available options. + +@end table +@end deftp + +@deftp {Data Type} mpd-partition +Data type representing a @command{mpd} partition. + +@table @asis +@item @code{name} (type: string) +Partition name. + +@item @code{extra-options} (default: @code{()}) (type: alist) +An association list of option symbols/strings to string values to be +appended to the partition configuration. See +@uref{https://mpd.readthedocs.io/en/latest/user.html#configuring-partitions,Configuring +Partitions} for available options. @end table @end deftp @deftp {Data Type} mpd-output -Data type representing an @command{mpd} audio output. +Data type representing a @command{mpd} audio output. @table @asis -@item @code{name} (default: @code{"MPD"}) +@item @code{name} (default: @code{"MPD"}) (type: string) The name of the audio output. -@item @code{type} (default: @code{"pulse"}) +@item @code{type} (default: @code{"pulse"}) (type: string) The type of audio output. -@item @code{enabled?} (default: @code{#t}) +@item @code{enabled?} (default: @code{#t}) (type: boolean) Specifies whether this audio output is enabled when MPD is started. By default, all audio outputs are enabled. This is just the default setting when there is no state file; with a state file, the previous state is restored. -@item @code{tags?} (default: @code{#t}) +@item @code{format} (type: maybe-string) +Force a specific audio format on output. See +@uref{https://mpd.readthedocs.io/en/latest/user.html#audio-output-format,Global +Audio Format} for a more detailed description. + +@item @code{tags?} (default: @code{#t}) (type: boolean) If set to @code{#f}, then MPD will not send tags to this output. This is only useful for output plugins that can receive tags, for example the @code{httpd} output plugin. -@item @code{always-on?} (default: @code{#f}) +@item @code{always-on?} (default: @code{#f}) (type: boolean) If set to @code{#t}, then MPD attempts to keep this audio output always -open. This may be useful for streaming servers, when you don’t want to +open. This may be useful for streaming servers, when you don?t want to disconnect all listeners even when playback is accidentally stopped. -@item @code{mixer-type} -This field accepts a symbol that specifies which mixer should be used +@item @code{mixer-type} (default: @code{"none"}) (type: string) +This field accepts a string that specifies which mixer should be used for this audio output: the @code{hardware} mixer, the @code{software} mixer, the @code{null} mixer (allows setting the volume, but with no effect; this can be used as a trick to implement an external mixer External Mixer) or no mixer (@code{none}). -@item @code{extra-options} (default: @code{'()}) -An association list of option symbols to string values to be appended to -the audio output configuration. +@item @code{replay-gain-handler} (type: maybe-string) +This field accepts a string that specifies how +@uref{https://mpd.readthedocs.io/en/latest/user.html#replay-gain,Replay +Gain} is to be applied. @code{software} uses an internal software +volume control, @code{mixer} uses the configured (hardware) mixer +control and @code{none} disables replay gain on this audio output. + +@item @code{extra-options} (default: @code{()}) (type: alist) +An association list of option symbols/strings to string values to be +appended to the audio output configuration. @end table @end deftp -The following example shows a configuration of @code{mpd} that provides -an HTTP audio streaming output. +The following example shows a configuration of @command{mpd} that +configures some of its plugins and provides a HTTP audio streaming output. @lisp (service mpd-service-type @@ -33269,7 +33378,19 @@ Audio Services (mixer-type 'null) (extra-options `((encoder . "vorbis") - (port . "8080")))))))) + (port . "8080")))))) + (decoders + (list (mpd-plugin + (plugin "mikmod") + (enabled? #f)) + (mpd-plugin + (plugin "openmpt") + (enabled? #t) + (extra-options `((repeat-count . -1) + (interpolation-filter . 1)))))) + (resampler (mpd-plugin + (plugin "libsamplerate") + (extra-options `((type . 0))))))) @end lisp diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm index b7cb0ebe38..7168320635 100644 --- a/gnu/services/audio.scm +++ b/gnu/services/audio.scm @@ -21,20 +21,75 @@ (define-module (gnu services audio) #:use-module (guix gexp) + #:use-module (guix deprecation) + #:use-module (guix diagnostics) + #:use-module (guix i18n) #:use-module (gnu services) #:use-module (gnu services configuration) #:use-module (gnu services shepherd) + #:use-module (gnu services admin) #:use-module (gnu system shadow) #:use-module (gnu packages admin) #:use-module (gnu packages mpd) #:use-module (guix records) #:use-module (ice-9 match) #:use-module (srfi srfi-1) + #:use-module (srfi srfi-8) #:use-module (srfi srfi-26) #:export (mpd-output mpd-output? + mpd-output-name + mpd-output-type + mpd-output-enabled? + mpd-output-format + mpd-output-tags? + mpd-output-always-on? + mpd-output-mixer-type + mpd-output-replay-gain-handler + mpd-output-extra-options + + mpd-plugin + mpd-plugin? + mpd-plugin-plugin + mpd-plugin-name + mpd-plugin-enabled? + mpd-plugin-extra-options + + mpd-partition + mpd-partition? + mpd-partition-name + mpd-partition-extra-options + mpd-configuration mpd-configuration? + mpd-configuration-package + mpd-configuration-user + mpd-configuration-group + mpd-configuration-shepherd-requirement + mpd-configuration-log-file + mpd-configuration-log-level + mpd-configuration-music-directory + mpd-configuration-music-dir + mpd-configuration-playlist-directory + mpd-configuration-playlist-dir + mpd-configuration-db-file + mpd-configuration-state-file + mpd-configuration-sticker-file + mpd-configuration-default-port + mpd-configuration-endpoints + mpd-configuration-address + mpd-configuration-database + mpd-configuration-partitions + mpd-configuration-neighbors + mpd-configuration-inputs + mpd-configuration-archive-plugins + mpd-configuration-input-cache-size + mpd-configuration-decoders + mpd-configuration-resampler + mpd-configuration-filters + mpd-configuration-outputs + mpd-configuration-playlist-plugins + mpd-configuration-extra-options mpd-service-type)) ;;; Commentary: @@ -50,13 +105,20 @@ (define (uglify-field-name field-name) str) #\-) "_"))) +(define list-of-string? + (list-of string?)) + +(define list-of-symbol? + (list-of symbol?)) + (define (mpd-serialize-field field-name value) - #~(format #f "~a ~s~%" #$(if (string? field-name) - field-name - (uglify-field-name field-name)) - #$(if (string? value) - value - (object->string value)))) + (let ((field (if (string? field-name) field-name + (uglify-field-name field-name))) + (value (cond + ((boolean? value) (if value "yes" "no")) + ((string? value) value) + (else (object->string value))))) + #~(format #f "~a ~s~%" #$field #$value))) (define (mpd-serialize-alist field-name value) #~(string-append #$@(generic-serialize-alist list mpd-serialize-field @@ -64,20 +126,103 @@ (define (mpd-serialize-alist field-name value) (define mpd-serialize-string mpd-serialize-field) -(define (mpd-serialize-boolean field-name value) - (mpd-serialize-field field-name (if value "yes" "no"))) +(define mpd-serialize-boolean mpd-serialize-field) -(define (mpd-serialize-list-of-mpd-output field-name value) - #~(string-append "\naudio_output {\n" - #$@(map (cut serialize-configuration <> - mpd-output-fields) - value) - "}\n")) -(define (mpd-serialize-configuration configuration) - (mixed-text-file - "mpd.conf" - (serialize-configuration configuration mpd-configuration-fields))) +(define-maybe string (prefix mpd-)) +(define-maybe list-of-string (prefix mpd-)) +(define-maybe boolean (prefix mpd-)) + +;;; TODO: Procedures for deprecated fields, to be removed. + +(define mpd-deprecated-fields '((music-dir . music-directory) + (playlist-dir . playlist-directory) + (address . endpoints))) + +(define (port? value) (or (string? value) (integer? value))) + +(define (mpd-serialize-deprecated-field field-name value) + (if (maybe-value-set? value) + (begin + (warn-about-deprecation + field-name #f + #:replacement (assoc-ref mpd-deprecated-fields field-name)) + (match field-name + ('playlist-dir (mpd-serialize-string "playlist_directory" value)) + ('music-dir (mpd-serialize-string "music_directory" value)) + ('address (mpd-serialize-string "bind_to_address" value)))) + "")) + +(define (mpd-serialize-port field-name value) + (when (string? value) + (warning + (G_ "string value for '~a' is deprecated, use integer instead~%") + field-name)) + (mpd-serialize-field "port" value)) + +(define-maybe port (prefix mpd-)) + +;;; + +;; Generic MPD plugin record, lists only the most prevalent fields. +(define-configuration mpd-plugin + (plugin + maybe-string + "Plugin name.") + + (name + maybe-string + "Name.") + + (enabled? + maybe-boolean + "Whether the plugin is enabled/disabled.") + + (extra-options + (alist '()) + "An association list of option symbols/strings to string values +to be appended to the plugin configuration. See +@uref{https://mpd.readthedocs.io/en/latest/plugins.html,MPD plugin reference} +for available options.") + + (prefix mpd-)) + +(define (mpd-serialize-mpd-plugin field-name value) + #~(format #f "~a {~%~a}~%" + '#$field-name + #$(serialize-configuration value mpd-plugin-fields))) + +(define (mpd-serialize-list-of-mpd-plugin field-name value) + #~(string-append #$@(map (cut mpd-serialize-mpd-plugin field-name <>) + value))) + +(define list-of-mpd-plugin? (list-of mpd-plugin?)) + +(define-maybe mpd-plugin (prefix mpd-)) + +(define-configuration mpd-partition + (name + string + "Partition name.") + + (extra-options + (alist '()) + "An association list of option symbols/strings to string values +to be appended to the partition configuration. See +@uref{https://mpd.readthedocs.io/en/latest/user.html#configuring-partitions,Configuring Partitions} +for available options.") + + (prefix mpd-)) + +(define (mpd-serialize-mpd-partition field-name value) + #~(format #f "partition {~%~a}~%" + #$(serialize-configuration value mpd-partition-fields))) + +(define (mpd-serialize-list-of-mpd-partition field-name value) + #~(string-append #$@(map (cut mpd-serialize-mpd-partition #f <>) value))) + +(define list-of-mpd-partition? + (list-of mpd-partition?)) (define-configuration mpd-output (name @@ -95,6 +240,12 @@ (define-configuration mpd-output setting when there is no state file; with a state file, the previous state is restored.") + (format + maybe-string + "Force a specific audio format on output. See +@uref{https://mpd.readthedocs.io/en/latest/user.html#audio-output-format,Global Audio Format} +for a more detailed description.") + (tags? (boolean #t) "If set to @code{#f}, then MPD will not send tags to this output. This @@ -109,125 +260,270 @@ (define-configuration mpd-output (mixer-type (string "none") - "This field accepts a symbol that specifies which mixer should be used + "This field accepts a string that specifies which mixer should be used for this audio output: the @code{hardware} mixer, the @code{software} mixer, the @code{null} mixer (allows setting the volume, but with no effect; this can be used as a trick to implement an external mixer External Mixer) or no mixer (@code{none}).") + (replay-gain-handler + maybe-string + "This field accepts a string that specifies how +@uref{https://mpd.readthedocs.io/en/latest/user.html#replay-gain,Replay Gain} +is to be applied. @code{software} uses an internal software volume control, +@code{mixer} uses the configured (hardware) mixer control and @code{none} +disables replay gain on this audio output.") + (extra-options (alist '()) - "An association list of option symbols to string values to be appended to -the audio output configuration.") + "An association list of option symbols/strings to string values +to be appended to the audio output configuration.") (prefix mpd-)) -(define list-of-mpd-output? - (list-of mpd-output?)) +(define (mpd-serialize-mpd-output field-name value) + #~(format #f "audio_output {~%~a}~%" + #$(serialize-configuration value mpd-output-fields))) + +(define (mpd-serialize-list-of-mpd-plugin-or-output field-name value) + (receive (plugins outputs) + (partition mpd-plugin? value) + #~(string-append #$@(map (cut mpd-serialize-mpd-plugin "audio_output" <>) + plugins) + #$@(map (cut mpd-serialize-mpd-output #f <>) outputs)))) + +(define list-of-mpd-plugin-or-output? + (list-of (lambda (x) + (or (mpd-output? x) (mpd-plugin? x))))) (define-configuration mpd-configuration + (package + (file-like mpd) + "The MPD package." + empty-serializer) + (user (string "mpd") "The user to run mpd as.") - (music-dir - (string "~/Music") + (group + (string "mpd") + "The group to run mpd as.") + + (shepherd-requirement + (list-of-symbol '()) + "This is a list of symbols naming Shepherd services that this service +will depend on." + empty-serializer) + + (log-file + (maybe-string "/var/log/mpd/log") + "The location of the log file. Set to @code{syslog} to use the +local syslog daemon or @code{%unset-value} to omit this directive +from the configuration file.") + + (log-level + maybe-string + "Supress any messages below this threshold. +Available values: @code{notice}, @code{info}, @code{verbose}, +@code{warning} and @code{error}.") + + (music-directory + maybe-string + "The directory to scan for music files.") + + (music-dir ; TODO: deprecated, remove later + maybe-string "The directory to scan for music files." - (lambda (_ x) - (mpd-serialize-field "music_directory" x))) + mpd-serialize-deprecated-field) + + (playlist-directory + maybe-string + "The directory to store playlists.") - (playlist-dir - (string "~/.mpd/playlists") + (playlist-dir ; TODO: deprecated, remove later + maybe-string "The directory to store playlists." - (lambda (_ x) - (mpd-serialize-field "playlist_directory" x))) + mpd-serialize-deprecated-field) (db-file - (string "~/.mpd/tag_cache") + maybe-string "The location of the music database.") (state-file - (string "~/.mpd/state") + maybe-string "The location of the file that stores current MPD's state.") (sticker-file - (string "~/.mpd/sticker.sql") + maybe-string "The location of the sticker database.") - (port - (string "6600") - "The port to run mpd on.") + (default-port + (maybe-port 6600) + "The default port to run mpd on.") + + (endpoints + maybe-list-of-string + "The addresses that mpd will bind to. A port different from +@var{default-port} may be specified, e.g. @code{localhost:6602} and +IPv6 addresses must be enclosed in square brackets when a different +port is used. +To use a Unix domain socket, an absolute path or a path starting with @code{~} +can be specified here." + (lambda (_ x) + (if (maybe-value-set? x) + #~(string-append #$@(map + (cut mpd-serialize-field "bind_to_address" <>) + x)) ""))) - (address - (string "any") + (address ; TODO: deprecated, remove later + maybe-string "The address that mpd will bind to. To use a Unix domain socket, an absolute path can be specified here." + mpd-serialize-deprecated-field) + + (database + maybe-mpd-plugin + "MPD database plugin configuration.") + + (partitions + (list-of-mpd-partition '()) + "List of MPD \"partitions\".") + + (neighbors + (list-of-mpd-plugin '()) + "List of MPD neighbor plugin configurations.") + + (inputs + (list-of-mpd-plugin '()) + "List of MPD input plugin configurations." (lambda (_ x) - (mpd-serialize-field "bind_to_address" x))) + (mpd-serialize-list-of-mpd-plugin "input" x))) + + (archive-plugins + (list-of-mpd-plugin '()) + "List of MPD archive plugin configurations." + (lambda (_ x) + (mpd-serialize-list-of-mpd-plugin "archive_plugin" x))) + + (input-cache-size + maybe-string + "MPD input cache size." + (lambda (_ x) + (if (maybe-value-set? x) + #~(string-append "\ninput_cache {\n" + #$(mpd-serialize-string "size" x) + "}\n") ""))) + + (decoders + (list-of-mpd-plugin '()) + "List of MPD decoder plugin configurations." + (lambda (_ x) + (mpd-serialize-list-of-mpd-plugin "decoder" x))) + + (resampler + maybe-mpd-plugin + "MPD resampler plugin configuration.") + + (filters + (list-of-mpd-plugin '()) + "List of MPD filter plugin configurations." + (lambda (_ x) + (mpd-serialize-list-of-mpd-plugin "filter" x))) (outputs - (list-of-mpd-output (list (mpd-output))) + (list-of-mpd-plugin-or-output (list (mpd-output))) "The audio outputs that MPD can use. By default this is a single output using pulseaudio.") + (playlist-plugins + (list-of-mpd-plugin '()) + "List of MPD playlist plugin configurations." + (lambda (_ x) + (mpd-serialize-list-of-mpd-plugin "playlist_plugin" x))) + + (extra-options + (alist '()) + "An association list of option symbols/strings to string values to be +appended to the configuration.") + (prefix mpd-)) -(define (mpd-file-name config file) - "Return a path in /var/run/mpd/ that is writable - by @code{user} from @code{config}." - (string-append "/var/run/mpd/" - (mpd-configuration-user config) - "/" file)) +(define (mpd-serialize-configuration configuration) + (mixed-text-file + "mpd.conf" + (serialize-configuration configuration mpd-configuration-fields))) + +(define (mpd-log-rotation config) + (match-record config (log-file) + (log-rotation + (files (list log-file)) + (post-rotate #~(begin + (use-modules (gnu services herd)) + (with-shepherd-action 'mpd ('reopen) #f)))))) (define (mpd-shepherd-service config) - (shepherd-service - (documentation "Run the MPD (Music Player Daemon)") - (requirement '(user-processes)) - (provision '(mpd)) - (start #~(make-forkexec-constructor - (list #$(file-append mpd "/bin/mpd") - "--no-daemon" - #$(mpd-serialize-configuration config)) - #:environment-variables - ;; Required to detect PulseAudio when run under a user account. - (list (string-append - "XDG_RUNTIME_DIR=/run/user/" - (number->string - (passwd:uid - (getpwnam #$(mpd-configuration-user config)))))) - #:log-file #$(mpd-file-name config "log"))) - (stop #~(make-kill-destructor)))) - -(define (mpd-service-activation config) - (with-imported-modules '((guix build utils)) - #~(begin - (use-modules (guix build utils)) - (define %user - (getpw #$(mpd-configuration-user config))) - - (let ((directory #$(mpd-file-name config ".mpd"))) - (mkdir-p directory) - (chown directory (passwd:uid %user) (passwd:gid %user)) - - ;; Make /var/run/mpd/USER user-owned as well. - (chown (dirname directory) - (passwd:uid %user) (passwd:gid %user)))))) - - -(define %mpd-accounts - ;; Default account and group for MPD. - (list (user-group (name "mpd") (system? #t)) - (user-account - (name "mpd") - (group "mpd") - (system? #t) - (comment "Music Player Daemon (MPD) user") - - ;; Note: /var/run/mpd hosts one sub-directory per user, of which - ;; /var/run/mpd/mpd corresponds to the "mpd" user. - (home-directory "/var/run/mpd/mpd") - - (shell (file-append shadow "/sbin/nologin"))))) + (match-record config (user package shepherd-requirement + log-file playlist-directory + db-file state-file sticker-file) + (let* ((config-file (mpd-serialize-configuration config))) + (shepherd-service + (documentation "Run the MPD (Music Player Daemon)") + (requirement `(user-processes loopback ,@shepherd-requirement)) + (provision '(mpd)) + (start #~(begin + (and=> #$(maybe-value log-file) + (compose mkdir-p dirname)) + + (let ((user (getpw #$user))) + (for-each + (lambda (x) + (when (and x (not (file-exists? x))) + (mkdir-p x) + (chown x (passwd:uid user) (passwd:gid user)))) + (list #$(maybe-value playlist-directory) + (and=> #$(maybe-value db-file) dirname) + (and=> #$(maybe-value state-file) dirname) + (and=> #$(maybe-value sticker-file) dirname)))) + + (make-forkexec-constructor + (list #$(file-append package "/bin/mpd") + "--no-daemon" + #$config-file) + #:environment-variables + ;; Required to detect PulseAudio when run under a user account. + (list (string-append + "XDG_RUNTIME_DIR=/run/user/" + (number->string (passwd:uid (getpwnam #$user)))))))) + (stop #~(make-kill-destructor)) + (actions + (list (shepherd-configuration-action config-file) + (shepherd-action + (name 'reopen) + (documentation "Re-open log files and flush caches.") + (procedure + #~(lambda (pid) + (if pid + (begin + (kill pid SIGHUP) + (format #t + "Issued SIGHUP to Service MPD (PID ~a)." + pid)) + (format #t "Service MPD is not running."))))))))))) + +(define (mpd-accounts config) + (match-record config (user group) + (list (user-group + (name group) + (system? #t)) + (user-account + (name user) + (group group) + (system? #t) + (comment "Music Player Daemon (MPD) user") + ;; MPD can use $HOME (or $XDG_CONFIG_HOME) to place its data + (home-directory "/var/lib/mpd") + (shell (file-append shadow "/sbin/nologin")))))) (define mpd-service-type (service-type @@ -237,7 +533,7 @@ (define mpd-service-type (list (service-extension shepherd-root-service-type (compose list mpd-shepherd-service)) (service-extension account-service-type - (const %mpd-accounts)) - (service-extension activation-service-type - mpd-service-activation))) + mpd-accounts) + (service-extension rottlog-service-type + (compose list mpd-log-rotation)))) (default-value (mpd-configuration)))) From patchwork Thu Feb 2 20:07:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bruno Victal X-Patchwork-Id: 46609 Return-Path: X-Original-To: patchwork@mira.cbaines.net Delivered-To: patchwork@mira.cbaines.net Received: by mira.cbaines.net (Postfix, from userid 113) id F30A327BBED; Thu, 2 Feb 2023 20:10:22 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on mira.cbaines.net X-Spam-Level: X-Spam-Status: No, score=-3.9 required=5.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS autolearn=ham autolearn_force=no version=3.4.6 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mira.cbaines.net (Postfix) with ESMTPS id 4185027BBEB for ; Thu, 2 Feb 2023 20:10:22 +0000 (GMT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pNfuQ-0003qS-MS; Thu, 02 Feb 2023 15:10:14 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pNfuF-0003oB-8c for guix-patches@gnu.org; Thu, 02 Feb 2023 15:10:04 -0500 Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pNfuE-0004o4-GV for guix-patches@gnu.org; Thu, 02 Feb 2023 15:10:02 -0500 Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1pNfuE-0007dR-CX for guix-patches@gnu.org; Thu, 02 Feb 2023 15:10:02 -0500 X-Loop: help-debbugs@gnu.org Subject: [bug#59866] [PATCH v6 3/3] services: mpd: Do not hardcode environment variables. Resent-From: Bruno Victal Original-Sender: "Debbugs-submit" Resent-CC: guix-patches@gnu.org Resent-Date: Thu, 02 Feb 2023 20:10:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 59866 X-GNU-PR-Package: guix-patches X-GNU-PR-Keywords: patch To: 59866@debbugs.gnu.org Cc: Bruno Victal , liliana.prikler@gmail.com Received: via spool by 59866-submit@debbugs.gnu.org id=B59866.167536859229328 (code B ref 59866); Thu, 02 Feb 2023 20:10:02 +0000 Received: (at 59866) by debbugs.gnu.org; 2 Feb 2023 20:09:52 +0000 Received: from localhost ([127.0.0.1]:35887 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pNfu3-0007cx-L2 for submit@debbugs.gnu.org; Thu, 02 Feb 2023 15:09:51 -0500 Received: from smtpmciv6.myservices.hosting ([185.26.106.201]:47066) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1pNfu1-0007cp-E3 for 59866@debbugs.gnu.org; Thu, 02 Feb 2023 15:09:50 -0500 Received: from mail1.netim.hosting (unknown [185.26.106.172]) by smtpmciv6.myservices.hosting (Postfix) with ESMTP id 7B85320DE9; Thu, 2 Feb 2023 21:09:48 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by mail1.netim.hosting (Postfix) with ESMTP id 2EFF680098; Thu, 2 Feb 2023 21:09:48 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at mail1.netim.hosting Received: from mail1.netim.hosting ([127.0.0.1]) by localhost (mail1-1.netim.hosting [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id rtrGhNt4uFWV; Thu, 2 Feb 2023 21:09:47 +0100 (CET) Received: from guix-nuc.home.arpa (bl9-118-236.dsl.telepac.pt [85.242.118.236]) (Authenticated sender: lumen@makinata.eu) by mail1.netim.hosting (Postfix) with ESMTPSA id A5A7880097; Thu, 2 Feb 2023 21:09:47 +0100 (CET) From: Bruno Victal Date: Thu, 2 Feb 2023 20:07:38 +0000 Message-Id: <6b51304098d50a01c207abddb3b02ba863034e56.1675367583.git.mirai@makinata.eu> X-Mailer: git-send-email 2.38.1 In-Reply-To: <23b0f83d1fd58fce9262d0b281b34e9678e21471.1675367583.git.mirai@makinata.eu> References: <23b0f83d1fd58fce9262d0b281b34e9678e21471.1675367583.git.mirai@makinata.eu> MIME-Version: 1.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: guix-patches@gnu.org List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org Sender: guix-patches-bounces+patchwork=mira.cbaines.net@gnu.org X-getmail-retrieved-from-mailbox: Patches Services should not expect for XDG_RUNTIME_DIR to be set. Inferring from the past comment, this seemed to resolve an issue when the service was launched with an _interactive_ user-account, which tends to have this variable set by the login-manager. This is not the case for system accounts and setting this variable results in PulseAudio (launched by the same system user) failing to start since it attempts to use a nonexistent directory. Ideally, this service should have a home-service counterpart but the old behavior can be emulated by setting the environment-variables field to: (environment-variables (list (string-append "XDG_RUNTIME_DIR=/run/user/" (number->string (passwd:uid (getpwnam "myuser")))))) * gnu/services/audio.scm (mpd-configuration)[environment-variables]: New field. (mpd-shepherd-service)[start]: Use new field. * doc/guix.texi (Audio Services)[Music Player Daemon]: Document it. --- Notable changes since v5: * NEW. Fixes PulseAudio issues resulting from hardcoded environment variables. doc/guix.texi | 3 +++ gnu/services/audio.scm | 14 ++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 8e220e0631..05c216bec4 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -33199,6 +33199,9 @@ Audio Services This is a list of symbols naming Shepherd services that this service will depend on. +@item @code{environment-variables} (default: @code{()}) (type: list-of-string) +A list of strings specifying environment variables. + @item @code{log-file} (default: @code{"/var/log/mpd/log"}) (type: maybe-string) The location of the log file. Set to @code{syslog} to use the local syslog daemon or @code{%unset-value} to omit this directive from the diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm index 7168320635..96b27660e5 100644 --- a/gnu/services/audio.scm +++ b/gnu/services/audio.scm @@ -316,6 +316,11 @@ (define-configuration mpd-configuration will depend on." empty-serializer) + (environment-variables + (list-of-string '()) + "A list of strings specifying environment variables." + empty-serializer) + (log-file (maybe-string "/var/log/mpd/log") "The location of the log file. Set to @code{syslog} to use the @@ -465,7 +470,8 @@ (define (mpd-log-rotation config) (define (mpd-shepherd-service config) (match-record config (user package shepherd-requirement log-file playlist-directory - db-file state-file sticker-file) + db-file state-file sticker-file + environment-variables) (let* ((config-file (mpd-serialize-configuration config))) (shepherd-service (documentation "Run the MPD (Music Player Daemon)") @@ -490,11 +496,7 @@ (define (mpd-shepherd-service config) (list #$(file-append package "/bin/mpd") "--no-daemon" #$config-file) - #:environment-variables - ;; Required to detect PulseAudio when run under a user account. - (list (string-append - "XDG_RUNTIME_DIR=/run/user/" - (number->string (passwd:uid (getpwnam #$user)))))))) + #:environment-variables '#$environment-variables))) (stop #~(make-kill-destructor)) (actions (list (shepherd-configuration-action config-file)