home: services: Add 'pulseaudio-rtp-sink' and 'pulseaudio-rtp-source'.
* gnu/home/services/sound.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * doc/guix.texi (Sound Home Services): New section.master
parent
833febb522
commit
674d893316
114
doc/guix.texi
114
doc/guix.texi
|
@ -41679,15 +41679,16 @@ service with the @code{simple-service} procedure from @code{(gnu
|
||||||
services)}.
|
services)}.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Essential Home Services:: Environment variables, packages, on-* scripts.
|
* Essential Home Services:: Environment variables, packages, on-* scripts.
|
||||||
* Shells: Shells Home Services. POSIX shells, Bash, Zsh.
|
* Shells: Shells Home Services. POSIX shells, Bash, Zsh.
|
||||||
* Mcron: Mcron Home Service. Scheduled User's Job Execution.
|
* Mcron: Mcron Home Service. Scheduled User's Job Execution.
|
||||||
* Power Management: Power Management Home Services. Services for battery power.
|
* Power Management: Power Management Home Services. Services for battery power.
|
||||||
* Shepherd: Shepherd Home Service. Managing User's Daemons.
|
* Shepherd: Shepherd Home Service. Managing User's Daemons.
|
||||||
* SSH: Secure Shell. Setting up the secure shell client.
|
* SSH: Secure Shell. Setting up the secure shell client.
|
||||||
* Desktop: Desktop Home Services. Services for graphical environments.
|
* Desktop: Desktop Home Services. Services for graphical environments.
|
||||||
* Guix: Guix Home Services. Services for Guix.
|
* Guix: Guix Home Services. Services for Guix.
|
||||||
* Fonts: Fonts Home Services. Services for managing User's fonts.
|
* Fonts: Fonts Home Services. Services for managing User's fonts.
|
||||||
|
* Sound: Sound Home Services. Dealing with audio.
|
||||||
@end menu
|
@end menu
|
||||||
@c In addition to that Home Services can provide
|
@c In addition to that Home Services can provide
|
||||||
|
|
||||||
|
@ -42601,6 +42602,101 @@ like this:
|
||||||
@end lisp
|
@end lisp
|
||||||
@end defvar
|
@end defvar
|
||||||
|
|
||||||
|
@node Sound Home Services
|
||||||
|
@subsection Sound Home Services
|
||||||
|
|
||||||
|
The @code{(gnu home services sound)} module provides services related to
|
||||||
|
sound support.
|
||||||
|
|
||||||
|
@cindex PulseAudio, home service
|
||||||
|
@cindex RTP, for PulseAudio
|
||||||
|
|
||||||
|
The following services dynamically reconfigure the
|
||||||
|
@uref{https://pulseaudio.org,PulseAudio sound server}: they let you
|
||||||
|
toggle broadcast of audio output over the network using the
|
||||||
|
@acronym{RTP, real-time transport protocol} and, correspondingly,
|
||||||
|
playback of sound received over RTP. Once
|
||||||
|
@code{home-pulseaudio-rtp-sink-service-type} is among your home
|
||||||
|
services, you can start broadcasting audio output by running this
|
||||||
|
command:
|
||||||
|
|
||||||
|
@example
|
||||||
|
herd start pulseaudio-rtp-sink
|
||||||
|
@end example
|
||||||
|
|
||||||
|
You can then run a PulseAudio-capable mixer, such as @code{pavucontrol}
|
||||||
|
or @code{pulsemixer} (both from the same-named package) to control which
|
||||||
|
audio stream(s) should be sent to the RTP ``sink''.
|
||||||
|
|
||||||
|
By default, audio is broadcasted to a multicast address: any device on
|
||||||
|
the @acronym{LAN, local area network} receives it and may play it.
|
||||||
|
Using multicast in this way puts a lot of pressure on the network and
|
||||||
|
degrades its performance, so you may instead prefer sending to
|
||||||
|
specifically one device. The first way to do that is by specifying the
|
||||||
|
IP address of the target device when starting the service:
|
||||||
|
|
||||||
|
@example
|
||||||
|
herd start pulseaudio-rtp-sink 192.168.1.42
|
||||||
|
@end example
|
||||||
|
|
||||||
|
The other option is to specify this IP address as the one to use by
|
||||||
|
default in your home environment configuration:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(service home-pulseaudio-rtp-sink-service-type
|
||||||
|
"192.168.1.42")
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
On the device where you intend to receive and play the RTP stream, you
|
||||||
|
can use @code{home-pulseaudio-rtp-source-service-type}, like so:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(service home-pulseaudio-rtp-source-service-type)
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
This will then let you start the receiving module for PulseAudio:
|
||||||
|
|
||||||
|
@example
|
||||||
|
herd start pulseaudio-rtp-source
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Again, by default it will listen on the multicast address. If, instead,
|
||||||
|
you'd like it to listen for direct incoming connections, you can do that
|
||||||
|
by running:
|
||||||
|
|
||||||
|
@lisp
|
||||||
|
(service home-pulseaudio-rtp-source-service-type
|
||||||
|
"0.0.0.0")
|
||||||
|
@end lisp
|
||||||
|
|
||||||
|
The reference of these services is given below.
|
||||||
|
|
||||||
|
@defvar home-pulseaudio-rtp-sink-service-type
|
||||||
|
@defvarx home-pulseaudio-rtp-source-service-type
|
||||||
|
This is the type of the service to send, respectively receive, audio
|
||||||
|
streams over @acronym{RTP, real-time transport protocol}.
|
||||||
|
|
||||||
|
The value associated with this service is the IP address (a string)
|
||||||
|
where to send, respectively receive, the audio stream. By default,
|
||||||
|
audio is sent/received on multicast address
|
||||||
|
@code{%pulseaudio-rtp-multicast-address}.
|
||||||
|
|
||||||
|
This service defines one Shepherd service: @code{pulseaudio-rtp-sink},
|
||||||
|
respectively @code{pulseaudio-rtp-source}. The service is not started
|
||||||
|
by default, so you have to explicitly start it when you want to turn it
|
||||||
|
on, as in this example:
|
||||||
|
|
||||||
|
@example
|
||||||
|
herd start pulseaudio-rtp-sink
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Stopping the Shepherd service turns off broadcasting.
|
||||||
|
@end defvar
|
||||||
|
|
||||||
|
@defvar %pulseaudio-rtp-multicast-address
|
||||||
|
This is the multicast address used by default by the two services above.
|
||||||
|
@end defvar
|
||||||
|
|
||||||
@node Invoking guix home
|
@node Invoking guix home
|
||||||
@section Invoking @command{guix home}
|
@section Invoking @command{guix home}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
;;; GNU Guix --- Functional package management for GNU
|
||||||
|
;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
|
||||||
|
;;;
|
||||||
|
;;; This file is part of GNU Guix.
|
||||||
|
;;;
|
||||||
|
;;; GNU Guix is free software; you can redistribute it and/or modify it
|
||||||
|
;;; under the terms of the GNU General Public License as published by
|
||||||
|
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||||
|
;;; your option) any later version.
|
||||||
|
;;;
|
||||||
|
;;; GNU Guix is distributed in the hope that it will be useful, but
|
||||||
|
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;;; GNU General Public License for more details.
|
||||||
|
;;;
|
||||||
|
;;; You should have received a copy of the GNU General Public License
|
||||||
|
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
(define-module (gnu home services sound)
|
||||||
|
#:use-module (gnu home services)
|
||||||
|
#:use-module (gnu home services shepherd)
|
||||||
|
#:use-module (guix records)
|
||||||
|
#:use-module (guix gexp)
|
||||||
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (ice-9 match)
|
||||||
|
#:export (home-pulseaudio-rtp-sink-service-type
|
||||||
|
home-pulseaudio-rtp-source-service-type
|
||||||
|
%pulseaudio-rtp-multicast-address))
|
||||||
|
|
||||||
|
|
||||||
|
;;;
|
||||||
|
;;; PulseAudio support.
|
||||||
|
;;;
|
||||||
|
|
||||||
|
(define (with-pulseaudio-connection sock exp)
|
||||||
|
;; Wrap EXP in an expression where SOCK is bound to a socket connected to
|
||||||
|
;; the user's PulseAudio command-line interface socket.
|
||||||
|
#~(let* ((#$sock (socket AF_UNIX SOCK_STREAM 0))
|
||||||
|
(pulse-user-file
|
||||||
|
(lambda (name)
|
||||||
|
(string-append "/run/user/" (number->string (getuid))
|
||||||
|
"/pulse/" name)))
|
||||||
|
(file (pulse-user-file "cli")))
|
||||||
|
(let loop ((tries 0))
|
||||||
|
(catch #t
|
||||||
|
(lambda ()
|
||||||
|
(connect #$sock AF_UNIX file)
|
||||||
|
(let ((result #$exp))
|
||||||
|
(close-port #$sock)
|
||||||
|
result))
|
||||||
|
(lambda (key . args)
|
||||||
|
(if (and (eq? key 'system-error)
|
||||||
|
(= ENOENT (system-error-errno (cons key args)))
|
||||||
|
(< tries 3))
|
||||||
|
;; The CLI socket doesn't exist yet, so send pulseaudio
|
||||||
|
;; SIGUSR2 so that it creates it and listens to it.
|
||||||
|
(let ((pid (call-with-input-file (pulse-user-file "pid")
|
||||||
|
read)))
|
||||||
|
(when (and (integer? pid) (> pid 1))
|
||||||
|
(kill pid SIGUSR2))
|
||||||
|
((@ (fibers) sleep) 1)
|
||||||
|
(loop (+ tries 1)))
|
||||||
|
(begin
|
||||||
|
(close-port #$sock)
|
||||||
|
(apply throw key args))))))))
|
||||||
|
|
||||||
|
(define %pulseaudio-rtp-multicast-address
|
||||||
|
;; Default address used by 'module-rtp-sink' and 'module-rtp-recv'. This is
|
||||||
|
;; a multicast address, for the Session Announcement Protocol (SAP) and the
|
||||||
|
;; Session Description Protocol (SDP).
|
||||||
|
"224.0.0.56")
|
||||||
|
|
||||||
|
(define (pulseaudio-rtp-sink-shepherd-services destination-ip)
|
||||||
|
(list (shepherd-service
|
||||||
|
(provision '(pulseaudio-rtp-sink))
|
||||||
|
(start
|
||||||
|
#~(lambda* (#:optional (destination-ip #$destination-ip))
|
||||||
|
#$(with-pulseaudio-connection
|
||||||
|
#~sock
|
||||||
|
#~(begin
|
||||||
|
(display "\
|
||||||
|
load-module module-null-sink \
|
||||||
|
sink_name=rtp sink_properties=\"device.description='RTP network output'\"\n"
|
||||||
|
sock)
|
||||||
|
(display (string-append "\
|
||||||
|
load-module module-rtp-send source=rtp.monitor"
|
||||||
|
(if destination-ip
|
||||||
|
(string-append
|
||||||
|
" destination_ip="
|
||||||
|
destination-ip)
|
||||||
|
"")
|
||||||
|
"\n")
|
||||||
|
sock)
|
||||||
|
#t))))
|
||||||
|
(stop
|
||||||
|
#~(lambda (_)
|
||||||
|
#$(with-pulseaudio-connection
|
||||||
|
#~sock
|
||||||
|
#~(begin
|
||||||
|
(display "unload-module module-rtp-send\n"
|
||||||
|
sock)
|
||||||
|
(display "unload-module module-null-sink\n"
|
||||||
|
sock)
|
||||||
|
#f))))
|
||||||
|
(auto-start? #f))))
|
||||||
|
|
||||||
|
(define home-pulseaudio-rtp-sink-service-type
|
||||||
|
(service-type
|
||||||
|
(name 'pulseaudio-rtp-sink)
|
||||||
|
(extensions
|
||||||
|
(list (service-extension home-shepherd-service-type
|
||||||
|
pulseaudio-rtp-sink-shepherd-services)))
|
||||||
|
(description
|
||||||
|
"Define a PulseAudio sink to broadcast audio output over RTP, which can
|
||||||
|
then by played by another PulseAudio instance.")
|
||||||
|
|
||||||
|
;; By default, send to the SAP multicast address, 224.0.0.56, which can be
|
||||||
|
;; network-intensive.
|
||||||
|
(default-value %pulseaudio-rtp-multicast-address)))
|
||||||
|
|
||||||
|
(define (pulseaudio-rtp-source-shepherd-services source-ip)
|
||||||
|
(list (shepherd-service
|
||||||
|
(provision '(pulseaudio-rtp-source))
|
||||||
|
(start
|
||||||
|
#~(lambda* (#:optional (source-ip #$source-ip))
|
||||||
|
#$(with-pulseaudio-connection
|
||||||
|
#~sock
|
||||||
|
#~(begin
|
||||||
|
(format sock "\
|
||||||
|
load-module module-rtp-recv sap_address=~a\n" source-ip)
|
||||||
|
#t))))
|
||||||
|
(stop
|
||||||
|
#~(lambda (_)
|
||||||
|
#$(with-pulseaudio-connection
|
||||||
|
#~sock
|
||||||
|
#~(begin
|
||||||
|
(display "unload-module module-rtp-recv\n"
|
||||||
|
sock)
|
||||||
|
#f))))
|
||||||
|
(auto-start? #f))))
|
||||||
|
|
||||||
|
(define home-pulseaudio-rtp-source-service-type
|
||||||
|
(service-type
|
||||||
|
(name 'pulseaudio-rtp-source)
|
||||||
|
(extensions
|
||||||
|
(list (service-extension home-shepherd-service-type
|
||||||
|
pulseaudio-rtp-source-shepherd-services)))
|
||||||
|
(description
|
||||||
|
"Define a PulseAudio source to receive audio broadcasted over RTP by
|
||||||
|
another PulseAudio instance.")
|
||||||
|
(default-value %pulseaudio-rtp-multicast-address)))
|
|
@ -1,5 +1,5 @@
|
||||||
# GNU Guix --- Functional package management for GNU
|
# GNU Guix --- Functional package management for GNU
|
||||||
# Copyright © 2012-2021, 2021-2022 Ludovic Courtès <ludo@gnu.org>
|
# Copyright © 2012-2023 Ludovic Courtès <ludo@gnu.org>
|
||||||
# Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2022 Andreas Enge <andreas@enge.fr>
|
# Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2022 Andreas Enge <andreas@enge.fr>
|
||||||
# Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
|
# Copyright © 2016 Mathieu Lirzin <mthl@gnu.org>
|
||||||
# Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Mark H Weaver <mhw@netris.org>
|
# Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Mark H Weaver <mhw@netris.org>
|
||||||
|
@ -94,6 +94,7 @@ GNU_SYSTEM_MODULES = \
|
||||||
%D%/home/services/pm.scm \
|
%D%/home/services/pm.scm \
|
||||||
%D%/home/services/shells.scm \
|
%D%/home/services/shells.scm \
|
||||||
%D%/home/services/shepherd.scm \
|
%D%/home/services/shepherd.scm \
|
||||||
|
%D%/home/services/sound.scm \
|
||||||
%D%/home/services/ssh.scm \
|
%D%/home/services/ssh.scm \
|
||||||
%D%/home/services/mcron.scm \
|
%D%/home/services/mcron.scm \
|
||||||
%D%/home/services/utils.scm \
|
%D%/home/services/utils.scm \
|
||||||
|
|
Reference in New Issue