summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/guix.texi60
-rw-r--r--gnu/services/audio.scm85
2 files changed, 128 insertions, 17 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 7cc33c6e22..f6dcb2ac63 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -22394,9 +22394,69 @@ The port to run mpd on.
 The address that mpd will bind to.  To use a Unix domain socket,
 an absolute path can be specified here.
 
+@item @code{outputs} (default: @code{"(list (mpd-output))"})
+The audio outputs that MPD can use.  By default this is a single output using pulseaudio.
+
+@end table
+@end deftp
+
+@deftp {Data Type} mpd-output
+Data type representing an @command{mpd} audio output.
+
+@table @asis
+@item @code{name} (default: @code{"MPD"})
+The name of the audio output.
+
+@item @code{type} (default: @code{"pulse"})
+The type of audio output.
+
+@item @code{enabled?} (default: @code{#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.
+
+@item @code{tags?} (default: @code{#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.
+
+@item @code{always-on?} (default: @code{#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.
+
+@item @code{mixer-type}
+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}).
+
+@item @code{extra-options} (default: @code{'()"})
+An association list of option symbols 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.
+
+@lisp
+(service mpd-service-type
+         (mpd-configuration
+           (outputs
+             (list (mpd-output
+                     (name "streaming")
+                     (type "httpd")
+                     (mixer-type 'null)
+                     (extra-options
+                      `((encoder . "vorbis")
+                        (port    . "8080"))))))))
+@end lisp
+
+
 @node Virtualization Services
 @subsection Virtualization services
 
diff --git a/gnu/services/audio.scm b/gnu/services/audio.scm
index ebfe05abd0..471c5fd95f 100644
--- a/gnu/services/audio.scm
+++ b/gnu/services/audio.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2017 Peter Mikkelsen <petermikkelsen10@gmail.com>
+;;; Copyright © 2019 Ricardo Wurmus <rekado@elephly.net>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -23,7 +24,9 @@
   #:use-module (gnu packages mpd)
   #:use-module (guix records)
   #:use-module (ice-9 match)
-  #:export (mpd-configuration
+  #:export (mpd-output
+            mpd-output?
+            mpd-configuration
             mpd-configuration?
             mpd-service-type))
 
@@ -33,6 +36,25 @@
 ;;;
 ;;; Code:
 
+(define-record-type* <mpd-output>
+  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>
   mpd-configuration make-mpd-configuration
   mpd-configuration?
@@ -51,27 +73,56 @@
   (port         mpd-configuration-port
                 (default "6600"))
   (address      mpd-configuration-address
-                (default "any")))
+                (default "any"))
+  (outputs      mpd-configuration-outputs
+                (default (list (mpd-output)))))
+
+(define (mpd-output->string output)
+  "Convert the OUTPUT of type <mpd-output> 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"
-   "audio_output {\n"
-   "  type \"pulse\"\n"
-   "  name \"MPD\"\n"
-   "}\n"
    "pid_file \"" (mpd-file-name config "pid") "\"\n"
-   (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)))))
+   (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 (mpd-file-name config file)
   "Return a path in /var/run/mpd/ that is writable