aboutsummaryrefslogtreecommitdiff
;;; 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.
;;;
;;; 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 (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

            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)
  (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")))

(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))))


;;;
;;; 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)))
e1855c938'>home: services: bash: Reorder aliases....Reported in <https://issues.guix.gnu.org/67652>. * home/services/shells.scm (add-bash-configuration): Reorder aliases. Change-Id: I288856bb6befe378ca60ef78578acc069cb18532 Reported-by: Atte Torri <atte.torri@universite-paris-saclay.fr> Signed-off-by: Hilton Chain <hako@ultrarare.space> Jason Darby 2024-03-21services: shepherd: Load each service file in a fresh module....Fixes <https://issues.guix.gnu.org/67649>. * gnu/home/services/shepherd.scm (home-shepherd-configuration-file)[config]: Define ‘make-user-module’. Call ‘load’ in ‘save-module-excursion’. * gnu/services/shepherd.scm (shepherd-configuration-file): Likewise. Reported-by: Attila Lendvai <attila@lendvai.name> Change-Id: I7df11c81b5bbbf2b24a8daa02502a000e0826fe0 Ludovic Courtès 2024-03-06gnu: home: dotfiles: Properly support both plain and Stow directory layouts....Fixes <https://issues.guix.gnu.org/68848>. The current implementation of the home-dotfiles-service-type contradicts the Guix manual. This patch properly implements both the plain and Stow dotfiles directory layouts. It does so by refactoring home-dotfiles-configuration adding a new packages field to support GNU Stow's users workflow and introducing a new layout field to switch between the two directory layouts. * gnu/home/services/dotfiles (home-dotfiles-configuration): Migrate to (gnu services configuration); [packages]: new field; [layout]: new field; (strip-stow-dotfile): new variable; (strip-plain-dotfile): new variable; (home-dotfiles-configuration->files): use the new fields; [directory-contents]: allow for selecting a subset of application dotfile directories; * doc/guix.texi: document the new layouts. Change-Id: I2e96037608353e360828290f055ec5271cfdfd48 Signed-off-by: Ludovic Courtès <ludo@gnu.org> Giacomo Leidi 2024-02-19home: symlink-manager: Allow busy device skip....* gnu/home/services/symlink-manager.scm (update-symlinks-script): Allow busy device skip. Change-Id: Iff91c8a30309d25c02a8311d8d5ddbf54e90f5ad Signed-off-by: Ludovic Courtès <ludo@gnu.org> Nicolas Graves 2024-01-28home: Add home-dotfiles-service....* gnu/home/service/dotfiles.scm: New file; * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * po/guix/POTFILES.in: Add it. * doc/guix.texi (Essential Home Services): Document it. Change-Id: I6769169cfacefc3842faa5b31bee081c56c28743 Co-authored-by: Ludovic Courtès <ludo@gnu.org> Giacomo Leidi 2024-01-17home: fontutils: Don't install fontconfig....* gnu/home/services/fontutils.scm (home-fontconfig-service-type): Don't add fontconfig to the profile. Change-Id: I28208461efdfa4a585ee61db3a23bed05eb38d02 Efraim Flashner 2024-01-17home: services: zsh: Use unified zprofile....* gnu/home/services/shells.scm (zsh-file-zprofile): Use the zprofile defined in (gnu system shadow) as a base. Change-Id: Iaf4c4f66d1ccbc0bd0166136b3d082229bdec201 Efraim Flashner 2024-01-08home: services: shepherd: Use the 0.10.x interface....* gnu/home/services/shepherd.scm (home-shepherd-configuration-file): Pass ‘register-services’ a list. Call ‘start-in-the-background’ unconditionally. Change-Id: Id7ba005949653a9ac065c47eddb425df4f4792aa Ludovic Courtès 2023-12-26gnu: home: Add home-pipewire service....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-wireplumber-shepherd-service, home-pipewire-shepherd-services, home-pipewire-asoundrc, home-pipewire-xdg-configuration, home-pipewire-pulseaudio-shepherd-service): 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. Change-Id: I99e0ae860de91d459c3c554ec5503bf35f785a2a Signed-off-by: Oleg Pykhalov <go.wigust@gmail.com> Brian Cully 2023-12-02gnu: Use ‘libc-utf8-locales-for-target’....* guix/packages.scm (%standard-patch-inputs): Use ‘libc-utf8-locales-for-target’ instead of ‘glibc-utf8-locales’. * guix/self.scm (%packages): Likewise. * gnu/home/services/ssh.scm (file-join): Likewise * gnu/installer.scm (build-compiled-file): Likewise. * gnu/packages/chromium.scm (ungoogled-chromium/wayland): Likewise. * gnu/packages/gnome.scm (libgweather4, tracker): Likewise. * gnu/packages/javascript.scm (js-mathjax): Likewise. * gnu/packages/package-management.scm (guix, flatpak): Likewise. * gnu/packages/raspberry-pi.scm (raspi-arm64-chainloader): Likewise. * gnu/packages/suckless.scm (svkbd): Likewise. * gnu/services.scm (cleanup-gexp): Likewise. * gnu/services/base.scm (guix-publish-shepherd-service): Likewise. * gnu/services/guix.scm (guix-build-coordinator-shepherd-services) (guix-build-coordinator-agent-shepherd-services): Likewise. * gnu/services/guix.scm (guix-build-coordinator-queue-builds-shepherd-services): (guix-data-service-shepherd-services) (nar-herder-shepherd-services) (bffe-shepherd-services): Likewise. * gnu/services/web.scm (anonip-shepherd-service) (mumi-shepherd-services): Likewise. * gnu/system/image.scm (system-disk-image, system-iso9660-image) (system-docker-image, system-tarball-image): Likewise. * gnu/system/install.scm (%installation-services): Likewise. * guix/profiles.scm (info-dir-file): Likewise. (ca-certificate-bundle, profile-derivation): Likewise. * guix/scripts/pack.scm (store-database, set-utf8-locale): Likewise. * tests/pack.scm: Likewise. * tests/profiles.scm ("profile-derivation, cross-compilation"): Likewise. Co-authored-by: Ludovic Courtès <ludo@gnu.org> Co-authored-by: Christopher Baines <mail@cbaines.net> Change-Id: I24239f427bcc930c29d2ba5d00dc615960a6c374 Janneke Nieuwenhuizen 2023-11-05home: services: Add 'x11-display' service....* gnu/home/services/desktop.scm (x11-shepherd-service): New procedure. (home-x11-service-type): New variable. (redshift-shepherd-service): Add 'requirement' field. (home-redshift-service-type): Extend 'home-x11-service-type'. * doc/guix.texi (Desktop Home Services): Document it. Change-Id: Ibd46d71cbb80fcdff8dbf3e8dbcfc3b24163bdb6 Ludovic Courtès 2023-09-17gnu: home: zsh: Load environment when running via ssh...* gnu/home/services/shells.scm (zsh-file-zshenv): Add snippet to source /etc/profile when running via ssh. (zsh-get-configuration-files): Always add .zshenv as it is never empty. Signed-off-by: Ludovic Courtès <ludo@gnu.org> Saku Laesvuori