at 23.11-beta 7.2 kB view raw
1# pipewire service. 2{ config, lib, pkgs, ... }: 3 4with lib; 5 6let 7 cfg = config.services.pipewire; 8 enable32BitAlsaPlugins = cfg.alsa.support32Bit 9 && pkgs.stdenv.isx86_64 10 && pkgs.pkgsi686Linux.pipewire != null; 11 12 # The package doesn't output to $out/lib/pipewire directly so that the 13 # overlays can use the outputs to replace the originals in FHS environments. 14 # 15 # This doesn't work in general because of missing development information. 16 jack-libs = pkgs.runCommand "jack-libs" {} '' 17 mkdir -p "$out/lib" 18 ln -s "${cfg.package.jack}/lib" "$out/lib/pipewire" 19 ''; 20in { 21 meta.maintainers = teams.freedesktop.members ++ [ lib.maintainers.k900 ]; 22 23 ###### interface 24 options = { 25 services.pipewire = { 26 enable = mkEnableOption (lib.mdDoc "pipewire service"); 27 28 package = mkOption { 29 type = types.package; 30 default = pkgs.pipewire; 31 defaultText = literalExpression "pkgs.pipewire"; 32 description = lib.mdDoc '' 33 The pipewire derivation to use. 34 ''; 35 }; 36 37 socketActivation = mkOption { 38 default = true; 39 type = types.bool; 40 description = lib.mdDoc '' 41 Automatically run pipewire when connections are made to the pipewire socket. 42 ''; 43 }; 44 45 audio = { 46 enable = lib.mkOption { 47 type = lib.types.bool; 48 # this is for backwards compatibility 49 default = cfg.alsa.enable || cfg.jack.enable || cfg.pulse.enable; 50 defaultText = lib.literalExpression "config.services.pipewire.alsa.enable || config.services.pipewire.jack.enable || config.services.pipewire.pulse.enable"; 51 description = lib.mdDoc "Whether to use PipeWire as the primary sound server"; 52 }; 53 }; 54 55 alsa = { 56 enable = mkEnableOption (lib.mdDoc "ALSA support"); 57 support32Bit = mkEnableOption (lib.mdDoc "32-bit ALSA support on 64-bit systems"); 58 }; 59 60 jack = { 61 enable = mkEnableOption (lib.mdDoc "JACK audio emulation"); 62 }; 63 64 pulse = { 65 enable = mkEnableOption (lib.mdDoc "PulseAudio server emulation"); 66 }; 67 68 systemWide = lib.mkOption { 69 type = lib.types.bool; 70 default = false; 71 description = lib.mdDoc '' 72 If true, a system-wide PipeWire service and socket is enabled 73 allowing all users in the "pipewire" group to use it simultaneously. 74 If false, then user units are used instead, restricting access to 75 only one user. 76 77 Enabling system-wide PipeWire is however not recommended and disabled 78 by default according to 79 https://github.com/PipeWire/pipewire/blob/master/NEWS 80 ''; 81 }; 82 }; 83 }; 84 85 imports = [ 86 (lib.mkRemovedOptionModule ["services" "pipewire" "config"] '' 87 Overriding default Pipewire configuration through NixOS options never worked correctly and is no longer supported. 88 Please create drop-in files in /etc/pipewire/pipewire.conf.d/ to make the desired setting changes instead. 89 '') 90 91 (lib.mkRemovedOptionModule ["services" "pipewire" "media-session"] '' 92 pipewire-media-session is no longer supported upstream and has been removed. 93 Please switch to `services.pipewire.wireplumber` instead. 94 '') 95 ]; 96 97 ###### implementation 98 config = mkIf cfg.enable { 99 assertions = [ 100 { 101 assertion = cfg.audio.enable -> !config.hardware.pulseaudio.enable; 102 message = "Using PipeWire as the sound server conflicts with PulseAudio. This option requires `hardware.pulseaudio.enable` to be set to false"; 103 } 104 { 105 assertion = cfg.jack.enable -> !config.services.jack.jackd.enable; 106 message = "PipeWire based JACK emulation doesn't use the JACK service. This option requires `services.jack.jackd.enable` to be set to false"; 107 } 108 { 109 # JACK intentionally not checked, as PW-on-JACK setups are a thing that some people may want 110 assertion = (cfg.alsa.enable || cfg.pulse.enable) -> cfg.audio.enable; 111 message = "Using PipeWire's ALSA/PulseAudio compatibility layers requires running PipeWire as the sound server. Set `services.pipewire.audio.enable` to true."; 112 } 113 ]; 114 115 environment.systemPackages = [ cfg.package ] 116 ++ lib.optional cfg.jack.enable jack-libs; 117 118 systemd.packages = [ cfg.package ]; 119 120 # PipeWire depends on DBUS but doesn't list it. Without this booting 121 # into a terminal results in the service crashing with an error. 122 systemd.services.pipewire.bindsTo = [ "dbus.service" ]; 123 systemd.user.services.pipewire.bindsTo = [ "dbus.service" ]; 124 125 # Enable either system or user units. Note that for pipewire-pulse there 126 # are only user units, which work in both cases. 127 systemd.sockets.pipewire.enable = cfg.systemWide; 128 systemd.services.pipewire.enable = cfg.systemWide; 129 systemd.user.sockets.pipewire.enable = !cfg.systemWide; 130 systemd.user.services.pipewire.enable = !cfg.systemWide; 131 132 # Mask pw-pulse if it's not wanted 133 systemd.user.services.pipewire-pulse.enable = cfg.pulse.enable; 134 systemd.user.sockets.pipewire-pulse.enable = cfg.pulse.enable; 135 136 systemd.sockets.pipewire.wantedBy = lib.mkIf cfg.socketActivation [ "sockets.target" ]; 137 systemd.user.sockets.pipewire.wantedBy = lib.mkIf cfg.socketActivation [ "sockets.target" ]; 138 systemd.user.sockets.pipewire-pulse.wantedBy = lib.mkIf cfg.socketActivation [ "sockets.target" ]; 139 140 services.udev.packages = [ cfg.package ]; 141 142 # If any paths are updated here they must also be updated in the package test. 143 environment.etc."alsa/conf.d/49-pipewire-modules.conf" = mkIf cfg.alsa.enable { 144 text = '' 145 pcm_type.pipewire { 146 libs.native = ${cfg.package}/lib/alsa-lib/libasound_module_pcm_pipewire.so ; 147 ${optionalString enable32BitAlsaPlugins 148 "libs.32Bit = ${pkgs.pkgsi686Linux.pipewire}/lib/alsa-lib/libasound_module_pcm_pipewire.so ;"} 149 } 150 ctl_type.pipewire { 151 libs.native = ${cfg.package}/lib/alsa-lib/libasound_module_ctl_pipewire.so ; 152 ${optionalString enable32BitAlsaPlugins 153 "libs.32Bit = ${pkgs.pkgsi686Linux.pipewire}/lib/alsa-lib/libasound_module_ctl_pipewire.so ;"} 154 } 155 ''; 156 }; 157 environment.etc."alsa/conf.d/50-pipewire.conf" = mkIf cfg.alsa.enable { 158 source = "${cfg.package}/share/alsa/alsa.conf.d/50-pipewire.conf"; 159 }; 160 environment.etc."alsa/conf.d/99-pipewire-default.conf" = mkIf cfg.alsa.enable { 161 source = "${cfg.package}/share/alsa/alsa.conf.d/99-pipewire-default.conf"; 162 }; 163 164 environment.sessionVariables.LD_LIBRARY_PATH = 165 lib.mkIf cfg.jack.enable [ "${cfg.package.jack}/lib" ]; 166 167 users = lib.mkIf cfg.systemWide { 168 users.pipewire = { 169 uid = config.ids.uids.pipewire; 170 group = "pipewire"; 171 extraGroups = [ 172 "audio" 173 "video" 174 ] ++ lib.optional config.security.rtkit.enable "rtkit"; 175 description = "Pipewire system service user"; 176 isSystemUser = true; 177 home = "/var/lib/pipewire"; 178 createHome = true; 179 }; 180 groups.pipewire.gid = config.ids.gids.pipewire; 181 }; 182 }; 183}