services: syslogd: Do not fsync at each line.
[jackhill/guix/guix.git] / gnu / services / sound.scm
CommitLineData
8cd1e8e8 1;;; GNU Guix --- Functional package management for GNU
a66ee82a 2;;; Copyright © 2018, 2020 Oleg Pykhalov <go.wigust@gmail.com>
719bbcc1 3;;; Copyright © 2020 Liliana Marie Prikler <liliana.prikler@gmail.com>
3ed94ed8 4;;; Copyright © 2020 Marius Bakke <mbakke@fastmail.com>
1cc9060c 5;;; Copyright © 2022 Maxim Cournoyer <maxim.cournoyer@gmail.com>
8cd1e8e8
OP
6;;;
7;;; This file is part of GNU Guix.
8;;;
9;;; GNU Guix is free software; you can redistribute it and/or modify it
10;;; under the terms of the GNU General Public License as published by
11;;; the Free Software Foundation; either version 3 of the License, or (at
12;;; your option) any later version.
13;;;
14;;; GNU Guix is distributed in the hope that it will be useful, but
15;;; WITHOUT ANY WARRANTY; without even the implied warranty of
16;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;;; GNU General Public License for more details.
18;;;
19;;; You should have received a copy of the GNU General Public License
20;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
21
22(define-module (gnu services sound)
23 #:use-module (gnu services base)
24 #:use-module (gnu services configuration)
25 #:use-module (gnu services shepherd)
26 #:use-module (gnu services)
a66ee82a 27 #:use-module (gnu system pam)
8cd1e8e8 28 #:use-module (gnu system shadow)
60cb647a 29 #:use-module (guix diagnostics)
8cd1e8e8
OP
30 #:use-module (guix gexp)
31 #:use-module (guix packages)
32 #:use-module (guix records)
33 #:use-module (guix store)
60cb647a 34 #:use-module (guix ui)
a66ee82a 35 #:use-module (gnu packages audio)
1e3861eb 36 #:use-module (gnu packages linux)
8cd1e8e8
OP
37 #:use-module (gnu packages pulseaudio)
38 #:use-module (ice-9 match)
60cb647a 39 #:use-module (srfi srfi-1)
8cd1e8e8 40 #:export (alsa-configuration
a66ee82a
OP
41 alsa-service-type
42
f5474262 43 pulseaudio-configuration
f1022fbf
LP
44 pulseaudio-service-type
45
46 ladspa-configuration
47 ladspa-service-type))
8cd1e8e8
OP
48
49;;; Commentary:
50;;;
51;;; Sound services.
52;;;
53;;; Code:
54
55\f
56;;;
57;;; ALSA
58;;;
59
60(define-record-type* <alsa-configuration>
61 alsa-configuration make-alsa-configuration alsa-configuration?
892f1b72 62 (alsa-plugins alsa-configuration-alsa-plugins ;file-like
1e3861eb 63 (default alsa-plugins))
8cd1e8e8
OP
64 (pulseaudio? alsa-configuration-pulseaudio? ;boolean
65 (default #t))
66 (extra-options alsa-configuration-extra-options ;string
67 (default "")))
68
1e3861eb
OP
69(define alsa-config-file
70 ;; Return the ALSA configuration file.
71 (match-lambda
72 (($ <alsa-configuration> alsa-plugins pulseaudio? extra-options)
73 (apply mixed-text-file "asound.conf"
74 `("# Generated by 'alsa-service'.\n\n"
75 ,@(if pulseaudio?
76 `("# Use PulseAudio by default
77pcm_type.pulse {
78 lib \"" ,#~(string-append #$alsa-plugins:pulseaudio
79 "/lib/alsa-lib/libasound_module_pcm_pulse.so") "\"
80}
81
82ctl_type.pulse {
83 lib \"" ,#~(string-append #$alsa-plugins:pulseaudio
84 "/lib/alsa-lib/libasound_module_ctl_pulse.so") "\"
85}
86
8cd1e8e8
OP
87pcm.!default {
88 type pulse
89 fallback \"sysdefault\"
90 hint {
91 show on
92 description \"Default ALSA Output (currently PulseAudio Sound Server)\"
93 }
94}
95
96ctl.!default {
97 type pulse
98 fallback \"sysdefault\"
1e3861eb
OP
99}\n\n")
100 '())
101 ,extra-options)))))
8cd1e8e8
OP
102
103(define (alsa-etc-service config)
104 (list `("asound.conf" ,(alsa-config-file config))))
105
106(define alsa-service-type
107 (service-type
108 (name 'alsa)
109 (extensions
110 (list (service-extension etc-service-type alsa-etc-service)))
111 (default-value (alsa-configuration))
112 (description "Configure low-level Linux sound support, ALSA.")))
113
a66ee82a
OP
114\f
115;;;
116;;; PulseAudio
117;;;
118
f5474262
LP
119(define-record-type* <pulseaudio-configuration>
120 pulseaudio-configuration make-pulseaudio-configuration
121 pulseaudio-configuration?
1cc9060c 122 (client-conf pulseaudio-configuration-client-conf
f5474262 123 (default '()))
1cc9060c 124 (daemon-conf pulseaudio-configuration-daemon-conf
f6f91811
LP
125 ;; Flat volumes may cause unpleasant experiences to users
126 ;; when applications inadvertently max out the system volume
127 ;; (see e.g. <https://bugs.gnu.org/38172>).
128 (default '((flat-volumes . no))))
1cc9060c 129 (script-file pulseaudio-configuration-script-file
f5474262 130 (default (file-append pulseaudio "/etc/pulse/default.pa")))
60cb647a
MC
131 (extra-script-files pulseaudio-configuration-extra-script-files
132 (default '()))
1cc9060c 133 (system-script-file pulseaudio-configuration-system-script-file
f5474262
LP
134 (default
135 (file-append pulseaudio "/etc/pulse/system.pa"))))
136
f5474262
LP
137(define (pulseaudio-conf-entry arg)
138 (match arg
139 ((key . value)
140 (format #f "~a = ~s~%" key value))
141 ((? string? _)
142 (string-append arg "\n"))))
143
3ed94ed8
MB
144(define pulseaudio-environment
145 (match-lambda
146 (($ <pulseaudio-configuration> client-conf daemon-conf default-script-file)
e680c408
MC
147 ;; These config files kept at a fixed location, so that the following
148 ;; environment values are stable and do not require the user to reboot to
149 ;; effect their PulseAudio configuration changes.
150 '(("PULSE_CONFIG" . "/etc/pulse/daemon.conf")
151 ("PULSE_CLIENTCONFIG" . "/etc/pulse/client.conf")))))
3ed94ed8 152
60cb647a
MC
153(define (extra-script-files->file-union extra-script-files)
154 "Return a G-exp obtained by processing EXTRA-SCRIPT-FILES with FILE-UNION."
155
156 (define (file-like->name file)
157 (match file
158 ((? local-file?)
159 (local-file-name file))
160 ((? plain-file?)
161 (plain-file-name file))
162 ((? computed-file?)
163 (computed-file-name file))
164 (_ (leave (G_ "~a is not a local-file, plain-file or \
165computed-file object~%") file))))
166
167 (define (assert-pulseaudio-script-file-name name)
168 (unless (string-suffix? ".pa" name)
169 (leave (G_ "`~a' lacks the required `.pa' file name extension~%") name))
170 name)
171
172 (let ((labels (map (compose assert-pulseaudio-script-file-name
173 file-like->name)
174 extra-script-files)))
175 (file-union "default.pa.d" (zip labels extra-script-files))))
176
177(define (append-include-directive script-file)
178 "Append an include directive to source scripts under /etc/pulse/default.pa.d."
179 (computed-file "default.pa"
180 #~(begin
181 (use-modules (ice-9 textual-ports))
182 (define script-text
183 (call-with-input-file #$script-file get-string-all))
184 (call-with-output-file #$output
185 (lambda (port)
186 (format port (string-append script-text "
187### Added by Guix to include scripts specified in extra-script-files.
188.nofail
189.include /etc/pulse/default.pa.d~%")))))))
190
f5474262
LP
191(define pulseaudio-etc
192 (match-lambda
e680c408
MC
193 (($ <pulseaudio-configuration> client-conf daemon-conf default-script-file
194 extra-script-files system-script-file)
f5474262
LP
195 `(("pulse"
196 ,(file-union
197 "pulse"
60cb647a
MC
198 `(("default.pa"
199 ,(if (null? extra-script-files)
200 default-script-file
201 (append-include-directive default-script-file)))
202 ("system.pa" ,system-script-file)
203 ,@(if (null? extra-script-files)
204 '()
205 `(("default.pa.d" ,(extra-script-files->file-union
e680c408
MC
206 extra-script-files))))
207 ,@(if (null? daemon-conf)
208 '()
209 `(("daemon.conf"
210 ,(apply mixed-text-file "daemon.conf"
211 "default-script-file = " default-script-file "\n"
212 (map pulseaudio-conf-entry daemon-conf)))))
213 ,@(if (null? client-conf)
214 '()
215 `(("client.conf"
216 ,(apply mixed-text-file "client.conf"
217 (map pulseaudio-conf-entry client-conf))))))))))))
a66ee82a
OP
218
219(define pulseaudio-service-type
220 (service-type
221 (name 'pulseaudio)
222 (extensions
223 (list (service-extension session-environment-service-type
f5474262 224 pulseaudio-environment)
fff4daa5
MC
225 (service-extension etc-service-type pulseaudio-etc)
226 (service-extension udev-service-type (const (list pulseaudio)))))
f5474262 227 (default-value (pulseaudio-configuration))
a66ee82a
OP
228 (description "Configure PulseAudio sound support.")))
229
f1022fbf
LP
230\f
231;;;
232;;; LADSPA
233;;;
234
235(define-record-type* <ladspa-configuration>
236 ladspa-configuration make-ladspa-configuration
237 ladspa-configuration?
238 (plugins ladspa-plugins (default '())))
239
240(define (ladspa-environment config)
241 ;; Define this variable in the global environment such that
242 ;; pulseaudio swh-plugins (and similar LADSPA plugins) work.
243 `(("LADSPA_PATH" .
244 (string-join
245 ',(map (lambda (package) (file-append package "/lib/ladspa"))
246 (ladspa-plugins config))
247 ":"))))
248
249(define ladspa-service-type
250 (service-type
251 (name 'ladspa)
252 (extensions
253 (list (service-extension session-environment-service-type
254 ladspa-environment)))
255 (default-value (ladspa-configuration))
256 (description "Configure LADSPA plugins.")))
257
8cd1e8e8 258;;; sound.scm ends here