From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id QG/UEjEY3GNOLQAAbAwnHQ (envelope-from ) for ; Thu, 02 Feb 2023 21:08:17 +0100 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id oInNEjEY3GPwrAAA9RJhRA (envelope-from ) for ; Thu, 02 Feb 2023 21:08:17 +0100 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id BA3783AF98 for ; Thu, 2 Feb 2023 21:08:16 +0100 (CET) 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 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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+larch=yhetil.org@gnu.org Sender: guix-patches-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN ARC-Seal: i=1; s=key1; d=yhetil.org; t=1675368497; a=rsa-sha256; cv=none; b=nrsqv17myd4O5S/anRUtcB9VDQ+lkz2Q0Z+qSBnxXkYEBrI7t+Uu1m+mhkrPtoESppYtvS CDCWa6AXslmQ4Lq+Y6DDX8e8OmNYBuHKYVSxXdNohjNZQxRWG+RHh2GpMCOVTWQml2ko8g PQoxxXtODLvxYFDrnRain4/IGtU2UGlVKb6CpWTdWZ5hcMvi4617omL1mCD3KlS9oDXbEc +mk8a2iLsLgqp5Yiwo0xHrLNB2N8pKtzmUO1n2o6vKA7XUdyx/0zVSS6hxWlohoo450AEZ KuvonGf3V35GOFuUdaWQGYiqFadrm5QRjKPWQGudbxrcFTHaS7XDghVBFb2BMA== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1675368497; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:resent-cc: resent-from:resent-sender:resent-message-id:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post; bh=D1D93G4DpLIC8Xdixb4wurFeoyuDFJwIFuiQt+PsC8U=; b=O33rgKTxm4qpcJRe7hLmR+XoLRn7sVG5houZjROP3/kbCBacTYDPpz6Nr4Zcsx8yP9xYLm CzR/CWe3EgUF+i6udaazpbt7XlAcFRIkTCZpWIOpVCapy9Z0iotG4F3BDdwD2o9aSAFrkG GLOUebs9XiQHtRdKP+FWWffAkCLmw2kRLCvofTYJhTUHylttZZA2hu7E+YDKlDSNPPJUSS 1T7Xu90XyxPPQS/Uqai0BbH1kZWTL3QRCDlCTD/Tz8ur+crLhDJxByQgo/i5567B3d0YPH QZJ4ZS2VsDNnlQo3A9hG8QyWyuHbBPuisZeIhNhYQAHZt+b/IUhLdEUSlQK0Jg== X-Migadu-Spam-Score: -1.08 X-Spam-Score: -1.08 X-Migadu-Queue-Id: BA3783AF98 X-Migadu-Scanner: scn0.migadu.com Authentication-Results: aspmx1.migadu.com; dkim=none; dmarc=none; spf=pass (aspmx1.migadu.com: domain of "guix-patches-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="guix-patches-bounces+larch=yhetil.org@gnu.org" X-TUID: 5WjzvAhKlGtX * 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 -- 2.38.1