diff mbox series

[bug#63863,v5,1/1] gnu: home: Add support for home-pipewire-service

Message ID 1023a7ef7f4612d8f7c08c2a4f9a39591263c284.1688301546.git.bjc@spork.org
State New
Headers show
Series gnu: home: Add support for home-pipewire-service | expand

Commit Message

Brian Cully July 2, 2023, 12:39 p.m. UTC
This adds a set of home shepherd services which will start the required
services for a functional pipewire setup.

* gnu/home/services/sound.scm (home-pipewire-shepherd-service),
(home-pipewire-pulse-shepherd-service), (home-wireplumber-shepherd-service),
(home-pipewire-shepherd-services)
(home-pipewire-asoundrc), (home-pipewire-xdg-configuration): new procedures.
(home-pipewire-service-type): new service type.
(home-pipewire-configuration): new struct.
(home-pipewire-disable-pulseaudio-auto-start): new variable.
* doc/guix.texi (Sound Home Services): document it.
---
 doc/guix.texi               |  73 +++++++++++++++++++++++
 gnu/home/services/sound.scm | 115 +++++++++++++++++++++++++++++++++++-
 2 files changed, 187 insertions(+), 1 deletion(-)

Comments

Hilton Chain Nov. 12, 2023, 2:14 p.m. UTC | #1
Hi Brian,

Tested the patch in my setup, it works well :)

(Some comments are in and after the quote.)

On Sun, 02 Jul 2023 20:39:41 +0800,
Brian Cully via Guix-patches via wrote:
>
> This adds a set of home shepherd services which will start the required
> services for a functional pipewire setup.
>
> * gnu/home/services/sound.scm (home-pipewire-shepherd-service),
> (home-pipewire-pulse-shepherd-service), (home-wireplumber-shepherd-service),
> (home-pipewire-shepherd-services)
> (home-pipewire-asoundrc), (home-pipewire-xdg-configuration): new procedures.
> (home-pipewire-service-type): new service type.
> (home-pipewire-configuration): new struct.
> (home-pipewire-disable-pulseaudio-auto-start): new variable.
> * doc/guix.texi (Sound Home Services): document it.
> ---
>  doc/guix.texi               |  73 +++++++++++++++++++++++
>  gnu/home/services/sound.scm | 115 +++++++++++++++++++++++++++++++++++-
>  2 files changed, 187 insertions(+), 1 deletion(-)
>
> diff --git a/doc/guix.texi b/doc/guix.texi
> index 853396f776..7a6b7ebc3a 100644
> --- a/doc/guix.texi
> +++ b/doc/guix.texi
> @@ -116,6 +116,7 @@
>  Copyright @copyright{} 2023 Karl Hallsby@*
>  Copyright @copyright{} 2023 Nathaniel Nicandro@*
>  Copyright @copyright{} 2023 Tanguy Le Carrour@*
> +Copyright @copyright{} 2023 Brian Cully@*
>
>  Permission is granted to copy, distribute and/or modify this document
>  under the terms of the GNU Free Documentation License, Version 1.3 or
> @@ -43742,6 +43743,7 @@ Sound Home Services
>
>  @cindex PulseAudio, home service
>  @cindex RTP, for PulseAudio
> +@subsubheading PulseAudio RTP Streaming Services
>
>  The following services dynamically reconfigure the
>  @uref{https://pulseaudio.org,PulseAudio sound server}: they let you
> @@ -43829,6 +43831,77 @@ Sound Home Services
>  This is the multicast address used by default by the two services above.
>  @end defvar
>
> +@cindex PipeWire, home service
> +@subsubheading PipeWire Home Service
> +
> +@uref{https://pipewire.org, PipeWire} provides a low-latency,
> +graph-based audio and video processing service.  In addition to its
> +native protocol, it can also be used as a replacement for both JACK and
> +PulseAudio.
> +
> +While PipeWire provides the media processing and API, it does not,
> +directly, know about devices such as sound cards, nor how you might want
> +to connect applications, hardware, and media processing filters.
> +Instead, PipeWire relies on a @dfn{session manager} to specify all these
> +relationships.  While you may use any session manager you wish, for most
> +people the @url{https://pipewire.pages.freedesktop.org/wireplumber/,
> +WirePlumber} session manager, a reference implementation provided by the
> +PipeWire project itself, suffices, and that is the one
> +@code{home-pipewire-service-type} uses.
> +
> +PipeWire can be used as a replacement for PulseAudio by setting
> +@code{enable-pulseaudio?} to @code{#t} in
> +@code{home-pipewire-configuration}, so that existing PulseAudio clients
> +may use it without any further configuration.
> +
> +In addition, JACK clients may connect to PipeWire by using the
> +@command{pw-jack} program, which comes with PipeWire.  Simply prefix the
> +command with @command{pw-jack} when you run it, and audio data should go
> +through PipeWire:
> +
> +@example
> +pw-jack mpv -ao=jack sound-file.wav
> +@end example
> +
> +For more information on PulseAudio emulation, see
> +@uref{https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PulseAudio},
> +for JACK, see
> +@uref{https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-JACK}.
> +
> +As PipeWire does not use @code{dbus} to start its services on demand
> +(as PulseAudio does), @code{home-pipewire-service-type} uses Shepherd
> +to start services when logged in, provisioning the @code{pipewire},
> +@code{wireplumber}, and, if configured, @code{pipewire-pulseaudio}
> +services.  @xref{Shepherd Home Service}.
> +
> +@defvar home-pipewire-service-type
> +This provides the service definition for @command{pipewire}, which will
> +run on login.  Its value is a @code{home-pipewire-configuration} object.
> +
> +To start the service, add it to the @code{service} field of your
> +@code{home-environment}, such as:
> +
> +@lisp
> +(service home-pipewire-service-type)
> +@end lisp
> +@end defvar
> +
> +@deftp {Data Type} home-pipewire-configuration
> +Available @code{home-pipewire-configuration} fields are:
> +
> +@table @asis
> +@item @code{pipewire} (default: @code{pipewire}) (type: file-like)
> +The PipeWire package to use.
> +
> +@item @code{wireplumber} (default: @code{wireplumber}) (type: file-like)
> +The WirePlumber package to use.
> +
> +@item @code{enable-pulseaudio?} (default: @code{#t}) (type: boolean)
> +When true, enable PipeWire's PulseAudio emulation support, allowing
> +PulseAudio clients to use PipeWire transparently.
> +@end table
> +@end deftp
> +
>  @node Mail Home Services
>  @subsection Mail Home Services
>
> diff --git a/gnu/home/services/sound.scm b/gnu/home/services/sound.scm
> index 22c1a99250..5463255e8c 100644
> --- a/gnu/home/services/sound.scm
> +++ b/gnu/home/services/sound.scm
> @@ -1,5 +1,6 @@
>  ;;; GNU Guix --- Functional package management for GNU
>  ;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
> +;;; Copyright © 2023 Brian Cully <bjc@spork.org>
>  ;;;
>  ;;; This file is part of GNU Guix.
>  ;;;
> @@ -19,13 +20,125 @@
>  (define-module (gnu home services sound)
>    #:use-module (gnu home services)
>    #:use-module (gnu home services shepherd)
> +  #:use-module (gnu home services xdg)
> +  #:use-module (gnu packages linux)
> +  #:use-module (gnu services configuration)
>    #: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-rtp-multicast-address
> +
> +            home-pipewire-configuration
> +            home-pipewire-service-type))
> +
> +
> +;;;
> +;;; PipeWire support.
> +;;;
> +
> +(define-configuration/no-serialization home-pipewire-configuration
> +  (pipewire
> +   (file-like pipewire)
> +   "The PipeWire package to use.")
> +  (wireplumber
> +   (file-like wireplumber)
> +   "The WirePlumber package to use.")
> +  (enable-pulseaudio?
> +   (boolean #t)
> +   "When true, enable PipeWire's PulseAudio emulation support, allowing
> +PulseAudio clients to use PipeWire transparently."))
> +
> +(define (home-pipewire-shepherd-service config)
> +  (shepherd-service
> +   (documentation "PipeWire media processing.")
> +   (provision '(pipewire))
> +   (requirement '(dbus))
> +   (start #~(make-forkexec-constructor
> +             (list #$(file-append
> +                      (home-pipewire-configuration-pipewire config)
> +                      "/bin/pipewire"))))
> +   (stop #~(make-kill-destructor))))
> +
> +(define (home-pipewire-pulseaudio-shepherd-service config)
> +  (shepherd-service
> +   (documentation "Drop-in PulseAudio replacement service for PipeWire.")
> +   (provision '(pipewire-pulseaudio))
> +   (requirement '(pipewire))
> +   (start #~(make-forkexec-constructor
> +             (list #$(file-append
> +                      (home-pipewire-configuration-pipewire config)
> +                      "/bin/pipewire-pulse"))))
> +   (stop #~(make-kill-destructor))))
> +
> +(define (home-wireplumber-shepherd-service config)
> +  (shepherd-service
> +   (documentation "WirePlumber session management for PipeWire.")
> +   (provision '(wireplumber))
> +   (requirement '(pipewire))
> +   (start #~(make-forkexec-constructor
> +             (list #$(file-append
> +                      (home-pipewire-configuration-wireplumber config)
> +                      "/bin/wireplumber"))))
> +   (stop #~(make-kill-destructor))))
> +
> +(define (home-pipewire-shepherd-services config)
> +  (cons* (home-pipewire-shepherd-service config)
> +         (home-wireplumber-shepherd-service config)
> +         (if (home-pipewire-configuration-enable-pulseaudio? config)
> +             (list (home-pipewire-pulseaudio-shepherd-service config))
> +             '())))
> +
> +(define (home-pipewire-asoundrc config)
> +  (mixed-text-file
> +   "asoundrc"
> +   #~(string-append
> +      "<"
> +      #$(file-append
> +         (home-pipewire-configuration-pipewire config)
> +         "/share/alsa/alsa.conf.d/50-pipewire.conf")
> +      ">\n"
> +      "<"
> +      #$(file-append
> +         (home-pipewire-configuration-pipewire config)
> +         "/share/alsa/alsa.conf.d/99-pipewire-default.conf")
> +      ">\n"
> +      "pcm_type.pipewire {\n"
> +      "  lib \""
> +      #$(file-append
> +         (home-pipewire-configuration-pipewire config)
> +         "/lib/alsa-lib/libasound_module_pcm_pipewire.so")
> +      "\"\n}\n"
> +      "ctl_type.pipewire {\n"
> +      "  lib \""
> +      #$(file-append
> +         (home-pipewire-configuration-pipewire config)
> +         "/lib/alsa-lib/libasound_module_ctl_pipewire.so")
> +      "\"\n}\n")))


I'd prefer the following:
--8<---------------cut here---------------start------------->8---
(define (home-pipewire-asoundrc config)
  (match-record config <home-pipewire-configuration>
    (pipewire)
    (mixed-text-file
     "asoundrc"
     "<" pipewire "/share/alsa/alsa.conf.d/50-pipewire.conf>\n"
     "<" pipewire "/share/alsa/alsa.conf.d/99-pipewire-default.conf>\n"
     "pcm_type.pipewire {\n"
     "  lib \"" pipewire "/lib/alsa-lib/libasound_module_pcm_pipewire.so\"\n"
     "}\n"
     "ctl_type.pipewire {\n"
     "  lib \"" pipewire "/lib/alsa-lib/libasound_module_ctl_pipewire.so\"\n"
     "}\n")))
--8<---------------cut here---------------end--------------->8---

or:
--8<---------------cut here---------------start------------->8---
(define (home-pipewire-asoundrc config)
  (match-record config <home-pipewire-configuration>
    (pipewire)
    (mixed-text-file
     "asoundrc"
     #~(begin
         (use-modules (ice-9 format))
         (format #f "~
<~a/share/alsa/alsa.conf.d/50-pipewire.conf>
<~@*~a/share/alsa/alsa.conf.d/99-pipewire-default.conf>
pcm_type.pipewire {
  lib \"~@*~a/lib/alsa-lib/libasound_module_pcm_pipewire.so\"
}
ctl_type.pipewire {
  lib \"~@*~a/lib/alsa-lib/libasound_module_ctl_pipewire.so\"
}~%" #$pipewire)))))
--8<---------------cut here---------------end--------------->8---


> +
> +(define home-pipewire-disable-pulseaudio-auto-start
> +  (plain-file "client.conf" "autospawn = no"))
> +
> +(define (home-pipewire-xdg-configuration config)
> +  (cons* `("alsa/asoundrc" ,(home-pipewire-asoundrc config))
> +         (if (home-pipewire-configuration-enable-pulseaudio? config)
> +             `(("pulse/client.conf"
> +                ,home-pipewire-disable-pulseaudio-auto-start))
> +             '())))
> +
> +(define home-pipewire-service-type
> +  (service-type
> +   (name 'pipewire)
> +   (extensions
> +    (list (service-extension home-shepherd-service-type
> +                             home-pipewire-shepherd-services)
> +          (service-extension home-xdg-configuration-files-service-type
> +                             home-pipewire-xdg-configuration)))
> +   (description
> +    "Start essential PipeWire services.")
> +   (default-value (home-pipewire-configuration))))
>
>  
>  ;;;
> --
> 2.40.1


One thing to note: the wireplumber package is built with elogind integration, so
it fails to start when elogind is not present:
--8<---------------cut here---------------start------------->8---
[wireplumber] failed to start systemd logind monitor: -2 (No such file or directory)
--8<---------------cut here---------------end--------------->8---

I think we can add a wireplumber variant built with "-Delogind=disabled" and
maybe mention it in the documentation.

Thanks
diff mbox series

Patch

diff --git a/doc/guix.texi b/doc/guix.texi
index 853396f776..7a6b7ebc3a 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -116,6 +116,7 @@ 
 Copyright @copyright{} 2023 Karl Hallsby@*
 Copyright @copyright{} 2023 Nathaniel Nicandro@*
 Copyright @copyright{} 2023 Tanguy Le Carrour@*
+Copyright @copyright{} 2023 Brian Cully@*
 
 Permission is granted to copy, distribute and/or modify this document
 under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -43742,6 +43743,7 @@  Sound Home Services
 
 @cindex PulseAudio, home service
 @cindex RTP, for PulseAudio
+@subsubheading PulseAudio RTP Streaming Services
 
 The following services dynamically reconfigure the
 @uref{https://pulseaudio.org,PulseAudio sound server}: they let you
@@ -43829,6 +43831,77 @@  Sound Home Services
 This is the multicast address used by default by the two services above.
 @end defvar
 
+@cindex PipeWire, home service
+@subsubheading PipeWire Home Service
+
+@uref{https://pipewire.org, PipeWire} provides a low-latency,
+graph-based audio and video processing service.  In addition to its
+native protocol, it can also be used as a replacement for both JACK and
+PulseAudio.
+
+While PipeWire provides the media processing and API, it does not,
+directly, know about devices such as sound cards, nor how you might want
+to connect applications, hardware, and media processing filters.
+Instead, PipeWire relies on a @dfn{session manager} to specify all these
+relationships.  While you may use any session manager you wish, for most
+people the @url{https://pipewire.pages.freedesktop.org/wireplumber/,
+WirePlumber} session manager, a reference implementation provided by the
+PipeWire project itself, suffices, and that is the one
+@code{home-pipewire-service-type} uses.
+
+PipeWire can be used as a replacement for PulseAudio by setting
+@code{enable-pulseaudio?} to @code{#t} in
+@code{home-pipewire-configuration}, so that existing PulseAudio clients
+may use it without any further configuration.
+
+In addition, JACK clients may connect to PipeWire by using the
+@command{pw-jack} program, which comes with PipeWire.  Simply prefix the
+command with @command{pw-jack} when you run it, and audio data should go
+through PipeWire:
+
+@example
+pw-jack mpv -ao=jack sound-file.wav
+@end example
+
+For more information on PulseAudio emulation, see
+@uref{https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PulseAudio},
+for JACK, see
+@uref{https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-JACK}.
+
+As PipeWire does not use @code{dbus} to start its services on demand
+(as PulseAudio does), @code{home-pipewire-service-type} uses Shepherd
+to start services when logged in, provisioning the @code{pipewire},
+@code{wireplumber}, and, if configured, @code{pipewire-pulseaudio}
+services.  @xref{Shepherd Home Service}.
+
+@defvar home-pipewire-service-type
+This provides the service definition for @command{pipewire}, which will
+run on login.  Its value is a @code{home-pipewire-configuration} object.
+
+To start the service, add it to the @code{service} field of your
+@code{home-environment}, such as:
+
+@lisp
+(service home-pipewire-service-type)
+@end lisp
+@end defvar
+
+@deftp {Data Type} home-pipewire-configuration
+Available @code{home-pipewire-configuration} fields are:
+
+@table @asis
+@item @code{pipewire} (default: @code{pipewire}) (type: file-like)
+The PipeWire package to use.
+
+@item @code{wireplumber} (default: @code{wireplumber}) (type: file-like)
+The WirePlumber package to use.
+
+@item @code{enable-pulseaudio?} (default: @code{#t}) (type: boolean)
+When true, enable PipeWire's PulseAudio emulation support, allowing
+PulseAudio clients to use PipeWire transparently.
+@end table
+@end deftp
+
 @node Mail Home Services
 @subsection Mail Home Services
  
diff --git a/gnu/home/services/sound.scm b/gnu/home/services/sound.scm
index 22c1a99250..5463255e8c 100644
--- a/gnu/home/services/sound.scm
+++ b/gnu/home/services/sound.scm
@@ -1,5 +1,6 @@ 
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2023 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2023 Brian Cully <bjc@spork.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -19,13 +20,125 @@ 
 (define-module (gnu home services sound)
   #:use-module (gnu home services)
   #:use-module (gnu home services shepherd)
+  #:use-module (gnu home services xdg)
+  #:use-module (gnu packages linux)
+  #:use-module (gnu services configuration)
   #: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-rtp-multicast-address
+
+            home-pipewire-configuration
+            home-pipewire-service-type))
+
+
+;;;
+;;; PipeWire support.
+;;;
+
+(define-configuration/no-serialization home-pipewire-configuration
+  (pipewire
+   (file-like pipewire)
+   "The PipeWire package to use.")
+  (wireplumber
+   (file-like wireplumber)
+   "The WirePlumber package to use.")
+  (enable-pulseaudio?
+   (boolean #t)
+   "When true, enable PipeWire's PulseAudio emulation support, allowing
+PulseAudio clients to use PipeWire transparently."))
+
+(define (home-pipewire-shepherd-service config)
+  (shepherd-service
+   (documentation "PipeWire media processing.")
+   (provision '(pipewire))
+   (requirement '(dbus))
+   (start #~(make-forkexec-constructor
+             (list #$(file-append
+                      (home-pipewire-configuration-pipewire config)
+                      "/bin/pipewire"))))
+   (stop #~(make-kill-destructor))))
+
+(define (home-pipewire-pulseaudio-shepherd-service config)
+  (shepherd-service
+   (documentation "Drop-in PulseAudio replacement service for PipeWire.")
+   (provision '(pipewire-pulseaudio))
+   (requirement '(pipewire))
+   (start #~(make-forkexec-constructor
+             (list #$(file-append
+                      (home-pipewire-configuration-pipewire config)
+                      "/bin/pipewire-pulse"))))
+   (stop #~(make-kill-destructor))))
+
+(define (home-wireplumber-shepherd-service config)
+  (shepherd-service
+   (documentation "WirePlumber session management for PipeWire.")
+   (provision '(wireplumber))
+   (requirement '(pipewire))
+   (start #~(make-forkexec-constructor
+             (list #$(file-append
+                      (home-pipewire-configuration-wireplumber config)
+                      "/bin/wireplumber"))))
+   (stop #~(make-kill-destructor))))
+
+(define (home-pipewire-shepherd-services config)
+  (cons* (home-pipewire-shepherd-service config)
+         (home-wireplumber-shepherd-service config)
+         (if (home-pipewire-configuration-enable-pulseaudio? config)
+             (list (home-pipewire-pulseaudio-shepherd-service config))
+             '())))
+
+(define (home-pipewire-asoundrc config)
+  (mixed-text-file
+   "asoundrc"
+   #~(string-append
+      "<"
+      #$(file-append
+         (home-pipewire-configuration-pipewire config)
+         "/share/alsa/alsa.conf.d/50-pipewire.conf")
+      ">\n"
+      "<"
+      #$(file-append
+         (home-pipewire-configuration-pipewire config)
+         "/share/alsa/alsa.conf.d/99-pipewire-default.conf")
+      ">\n"
+      "pcm_type.pipewire {\n"
+      "  lib \""
+      #$(file-append
+         (home-pipewire-configuration-pipewire config)
+         "/lib/alsa-lib/libasound_module_pcm_pipewire.so")
+      "\"\n}\n"
+      "ctl_type.pipewire {\n"
+      "  lib \""
+      #$(file-append
+         (home-pipewire-configuration-pipewire config)
+         "/lib/alsa-lib/libasound_module_ctl_pipewire.so")
+      "\"\n}\n")))
+
+(define home-pipewire-disable-pulseaudio-auto-start
+  (plain-file "client.conf" "autospawn = no"))
+
+(define (home-pipewire-xdg-configuration config)
+  (cons* `("alsa/asoundrc" ,(home-pipewire-asoundrc config))
+         (if (home-pipewire-configuration-enable-pulseaudio? config)
+             `(("pulse/client.conf"
+                ,home-pipewire-disable-pulseaudio-auto-start))
+             '())))
+
+(define home-pipewire-service-type
+  (service-type
+   (name 'pipewire)
+   (extensions
+    (list (service-extension home-shepherd-service-type
+                             home-pipewire-shepherd-services)
+          (service-extension home-xdg-configuration-files-service-type
+                             home-pipewire-xdg-configuration)))
+   (description
+    "Start essential PipeWire services.")
+   (default-value (home-pipewire-configuration))))
 
 
 ;;;