summaryrefslogtreecommitdiffstats
path: root/nixos
diff options
context:
space:
mode:
authorJörg Thalheim <Mic92@users.noreply.github.com>2021-03-07 09:34:42 +0000
committerGitHub <noreply@github.com>2021-03-07 09:34:42 +0000
commit413b44590f4b3e9d06a5f84f13b60e440be5327c (patch)
treed1f90c789c20ea3e2d546ab18bca95e4c4a6d1ae /nixos
parent40c0d29cf50a07a1f48ef95a4d79ec2977b50915 (diff)
parentb012ecaae7a273a9b09adbf608f7bf44374b8869 (diff)
Merge pull request #114482 from jansol/pipewire
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/services/desktops/pipewire/alsa-monitor.conf.json34
-rw-r--r--nixos/modules/services/desktops/pipewire/bluez-monitor.conf.json30
-rw-r--r--nixos/modules/services/desktops/pipewire/client-rt.conf.json26
-rw-r--r--nixos/modules/services/desktops/pipewire/client.conf.json19
-rw-r--r--nixos/modules/services/desktops/pipewire/jack.conf.json21
-rw-r--r--nixos/modules/services/desktops/pipewire/media-session.conf.json53
-rw-r--r--nixos/modules/services/desktops/pipewire/pipewire-media-session.nix320
-rw-r--r--nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json28
-rw-r--r--nixos/modules/services/desktops/pipewire/pipewire.conf.json55
-rw-r--r--nixos/modules/services/desktops/pipewire/pipewire.nix211
-rw-r--r--nixos/modules/services/desktops/pipewire/v4l2-monitor.conf.json30
11 files changed, 439 insertions, 388 deletions
diff --git a/nixos/modules/services/desktops/pipewire/alsa-monitor.conf.json b/nixos/modules/services/desktops/pipewire/alsa-monitor.conf.json
new file mode 100644
index 000000000000..53fc9cc96343
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/alsa-monitor.conf.json
@@ -0,0 +1,34 @@
+{
+ "properties": {},
+ "rules": [
+ {
+ "matches": [
+ {
+ "device.name": "~alsa_card.*"
+ }
+ ],
+ "actions": {
+ "update-props": {
+ "api.alsa.use-acp": true,
+ "api.acp.auto-profile": false,
+ "api.acp.auto-port": false
+ }
+ }
+ },
+ {
+ "matches": [
+ {
+ "node.name": "~alsa_input.*"
+ },
+ {
+ "node.name": "~alsa_output.*"
+ }
+ ],
+ "actions": {
+ "update-props": {
+ "node.pause-on-idle": false
+ }
+ }
+ }
+ ]
+}
diff --git a/nixos/modules/services/desktops/pipewire/bluez-monitor.conf.json b/nixos/modules/services/desktops/pipewire/bluez-monitor.conf.json
new file mode 100644
index 000000000000..4d50cb9f1adb
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/bluez-monitor.conf.json
@@ -0,0 +1,30 @@
+{
+ "properties": {},
+ "rules": [
+ {
+ "matches": [
+ {
+ "device.name": "~bluez_card.*"
+ }
+ ],
+ "actions": {
+ "update-props": {}
+ }
+ },
+ {
+ "matches": [
+ {
+ "node.name": "~bluez_input.*"
+ },
+ {
+ "node.name": "~bluez_output.*"
+ }
+ ],
+ "actions": {
+ "update-props": {
+ "node.pause-on-idle": false
+ }
+ }
+ }
+ ]
+}
diff --git a/nixos/modules/services/desktops/pipewire/client-rt.conf.json b/nixos/modules/services/desktops/pipewire/client-rt.conf.json
new file mode 100644
index 000000000000..d294927b4f64
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/client-rt.conf.json
@@ -0,0 +1,26 @@
+{
+ "context.properties": {
+ "log.level": 0
+ },
+ "context.spa-libs": {
+ "audio.convert.*": "audioconvert/libspa-audioconvert",
+ "support.*": "support/libspa-support"
+ },
+ "context.modules": {
+ "libpipewire-module-rtkit": {
+ "args": {},
+ "flags": [
+ "ifexists",
+ "nofail"
+ ]
+ },
+ "libpipewire-module-protocol-native": null,
+ "libpipewire-module-client-node": null,
+ "libpipewire-module-client-device": null,
+ "libpipewire-module-adapter": null,
+ "libpipewire-module-metadata": null,
+ "libpipewire-module-session-manager": null
+ },
+ "filter.properties": {},
+ "stream.properties": {}
+}
diff --git a/nixos/modules/services/desktops/pipewire/client.conf.json b/nixos/modules/services/desktops/pipewire/client.conf.json
new file mode 100644
index 000000000000..224938abbbcf
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/client.conf.json
@@ -0,0 +1,19 @@
+{
+ "context.properties": {
+ "log.level": 0
+ },
+ "context.spa-libs": {
+ "audio.convert.*": "audioconvert/libspa-audioconvert",
+ "support.*": "support/libspa-support"
+ },
+ "context.modules": {
+ "libpipewire-module-protocol-native": null,
+ "libpipewire-module-client-node": null,
+ "libpipewire-module-client-device": null,
+ "libpipewire-module-adapter": null,
+ "libpipewire-module-metadata": null,
+ "libpipewire-module-session-manager": null
+ },
+ "filter.properties": {},
+ "stream.properties": {}
+}
diff --git a/nixos/modules/services/desktops/pipewire/jack.conf.json b/nixos/modules/services/desktops/pipewire/jack.conf.json
new file mode 100644
index 000000000000..2de04036b312
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/jack.conf.json
@@ -0,0 +1,21 @@
+{
+ "context.properties": {
+ "log.level": 0
+ },
+ "context.spa-libs": {
+ "support.*": "support/libspa-support"
+ },
+ "context.modules": {
+ "libpipewire-module-rtkit": {
+ "args": {},
+ "flags": [
+ "ifexists",
+ "nofail"
+ ]
+ },
+ "libpipewire-module-protocol-native": null,
+ "libpipewire-module-client-node": null,
+ "libpipewire-module-metadata": null
+ },
+ "jack.properties": {}
+}
diff --git a/nixos/modules/services/desktops/pipewire/media-session.conf.json b/nixos/modules/services/desktops/pipewire/media-session.conf.json
new file mode 100644
index 000000000000..4b2505ff8164
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/media-session.conf.json
@@ -0,0 +1,53 @@
+{
+ "context.properties": {},
+ "context.spa-libs": {
+ "api.bluez5.*": "bluez5/libspa-bluez5",
+ "api.alsa.*": "alsa/libspa-alsa",
+ "api.v4l2.*": "v4l2/libspa-v4l2",
+ "api.libcamera.*": "libcamera/libspa-libcamera"
+ },
+ "context.modules": {
+ "libpipewire-module-rtkit": {
+ "args": {},
+ "flags": [
+ "ifexists",
+ "nofail"
+ ]
+ },
+ "libpipewire-module-protocol-native": null,
+ "libpipewire-module-client-node": null,
+ "libpipewire-module-client-device": null,
+ "libpipewire-module-adapter": null,
+ "libpipewire-module-metadata": null,
+ "libpipewire-module-session-manager": null
+ },
+ "session.modules": {
+ "default": [
+ "flatpak",
+ "portal",
+ "v4l2",
+ "suspend-node",
+ "policy-node"
+ ],
+ "with-audio": [
+ "metadata",
+ "default-nodes",
+ "default-profile",
+ "default-routes",
+ "alsa-seq",
+ "alsa-monitor"
+ ],
+ "with-alsa": [
+ "with-audio"
+ ],
+ "with-jack": [
+ "with-audio"
+ ],
+ "with-pulseaudio": [
+ "with-audio",
+ "bluez5",
+ "restore-stream",
+ "streams-follow-default"
+ ]
+ }
+}
diff --git a/nixos/modules/services/desktops/pipewire/pipewire-media-session.nix b/nixos/modules/services/desktops/pipewire/pipewire-media-session.nix
index 81f4762e1e60..b41ea349fb8d 100644
--- a/nixos/modules/services/desktops/pipewire/pipewire-media-session.nix
+++ b/nixos/modules/services/desktops/pipewire/pipewire-media-session.nix
@@ -9,18 +9,36 @@ let
&& pkgs.stdenv.isx86_64
&& pkgs.pkgsi686Linux.pipewire != null;
+ prioritizeNativeProtocol = {
+ "context.modules" = {
+ "libpipewire-module-protocol-native" = {
+ _priority = -100;
+ _content = null;
+ };
+ };
+ };
+
+ # Use upstream config files passed through spa-json-dump as the base
+ # Patched here as necessary for them to work with this module
+ defaults = {
+ alsa-monitor = (builtins.fromJSON (builtins.readFile ./alsa-monitor.conf.json));
+ bluez-monitor = (builtins.fromJSON (builtins.readFile ./bluez-monitor.conf.json));
+ media-session = recursiveUpdate (builtins.fromJSON (builtins.readFile ./media-session.conf.json)) prioritizeNativeProtocol;
+ v4l2-monitor = (builtins.fromJSON (builtins.readFile ./v4l2-monitor.conf.json));
+ };
# Helpers for generating the pipewire JSON config file
mkSPAValueString = v:
if builtins.isList v then "[${lib.concatMapStringsSep " " mkSPAValueString v}]"
else if lib.types.attrs.check v then
"{${lib.concatStringsSep " " (mkSPAKeyValue v)}}"
+ else if builtins.isString v then "\"${lib.generators.mkValueStringDefault { } v}\""
else lib.generators.mkValueStringDefault { } v;
mkSPAKeyValue = attrs: map (def: def.content) (
lib.sortProperties
(
lib.mapAttrsToList
- (k: v: lib.mkOrder (v._priority or 1000) "${lib.escape [ "=" ] k} = ${mkSPAValueString (v._content or v)}")
+ (k: v: lib.mkOrder (v._priority or 1000) "${lib.escape [ "=" ":" ] k} = ${mkSPAValueString (v._content or v)}")
attrs
)
);
@@ -51,272 +69,41 @@ in {
'';
};
- config = mkOption {
- type = types.attrs;
- description = ''
- Configuration for the media session core.
- '';
- default = {
- # media-session config file
- properties = {
- # Properties to configure the session and some
- # modules
- #mem.mlock-all = false;
- #context.profile.modules = "default,rtkit";
- };
-
- spa-libs = {
- # Mapping from factory name to library.
- "api.bluez5.*" = "bluez5/libspa-bluez5";
- "api.alsa.*" = "alsa/libspa-alsa";
- "api.v4l2.*" = "v4l2/libspa-v4l2";
- "api.libcamera.*" = "libcamera/libspa-libcamera";
- };
-
- modules = {
- # These are the modules that are enabled when a file with
- # the key name is found in the media-session.d config directory.
- # the default bundle is always enabled.
-
- default = [
- "flatpak" # manages flatpak access
- "portal" # manage portal permissions
- "v4l2" # video for linux udev detection
- #"libcamera" # libcamera udev detection
- "suspend-node" # suspend inactive nodes
- "policy-node" # configure and link nodes
- #"metadata" # export metadata API
- #"default-nodes" # restore default nodes
- #"default-profile" # restore default profiles
- #"default-routes" # restore default route
- #"streams-follow-default" # move streams when default changes
- #"alsa-seq" # alsa seq midi support
- #"alsa-monitor" # alsa udev detection
- #"bluez5" # bluetooth support
- #"restore-stream" # restore stream settings
- ];
- "with-audio" = [
- "metadata"
- "default-nodes"
- "default-profile"
- "default-routes"
- "alsa-seq"
- "alsa-monitor"
- ];
- "with-alsa" = [
- "with-audio"
- ];
- "with-jack" = [
- "with-audio"
- ];
- "with-pulseaudio" = [
- "with-audio"
- "bluez5"
- "restore-stream"
- "streams-follow-default"
- ];
- };
+ config = {
+ media-session = mkOption {
+ type = types.attrs;
+ description = ''
+ Configuration for the media session core. For details see
+ https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/${cfg.package.version}/src/daemon/media-session.d/media-session.conf
+ '';
+ default = {};
};
- };
-
- alsaMonitorConfig = mkOption {
- type = types.attrs;
- description = ''
- Configuration for the alsa monitor.
- '';
- default = {
- # alsa-monitor config file
- properties = {
- #alsa.jack-device = true
- };
- rules = [
- # an array of matches/actions to evaluate
- {
- # rules for matching a device or node. It is an array of
- # properties that all need to match the regexp. If any of the
- # matches work, the actions are executed for the object.
- matches = [
- {
- # this matches all cards
- device.name = "~alsa_card.*";
- }
- ];
- actions = {
- # actions can update properties on the matched object.
- update-props = {
- api.alsa.use-acp = true;
- #api.alsa.use-ucm = true;
- #api.alsa.soft-mixer = false;
- #api.alsa.ignore-dB = false;
- #device.profile-set = "profileset-name";
- #device.profile = "default profile name";
- api.acp.auto-profile = false;
- api.acp.auto-port = false;
- #device.nick = "My Device";
- };
- };
- }
- {
- matches = [
- {
- # matches all sinks
- node.name = "~alsa_input.*";
- }
- {
- # matches all sources
- node.name = "~alsa_output.*";
- }
- ];
- actions = {
- update-props = {
- #node.nick = "My Node";
- #node.nick = null;
- #priority.driver = 100;
- #priority.session = 100;
- #node.pause-on-idle = false;
- #resample.quality = 4;
- #channelmix.normalize = false;
- #channelmix.mix-lfe = false;
- #audio.channels = 2;
- #audio.format = "S16LE";
- #audio.rate = 44100;
- #audio.position = "FL,FR";
- #api.alsa.period-size = 1024;
- #api.alsa.headroom = 0;
- #api.alsa.disable-mmap = false;
- #api.alsa.disable-batch = false;
- };
- };
- }
- ];
+ alsa-monitor = mkOption {
+ type = types.attrs;
+ description = ''
+ Configuration for the alsa monitor. For details see
+ https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/${cfg.package.version}/src/daemon/media-session.d/alsa-monitor.conf
+ '';
+ default = {};
};
- };
-
- bluezMonitorConfig = mkOption {
- type = types.attrs;
- description = ''
- Configuration for the bluez5 monitor.
- '';
- default = {
- # bluez-monitor config file
- properties = {
- # msbc is not expected to work on all headset + adapter combinations.
- #bluez5.msbc-support = true;
- #bluez5.sbc-xq-support = true;
- # Enabled headset roles (default: [ hsp_hs hfp_ag ]), this
- # property only applies to native backend. Currently some headsets
- # (Sony WH-1000XM3) are not working with both hsp_ag and hfp_ag
- # enabled, disable either hsp_ag or hfp_ag to work around it.
- #
- # Supported headset roles: hsp_hs (HSP Headset),
- # hsp_ag (HSP Audio Gateway),
- # hfp_ag (HFP Audio Gateway)
- #bluez5.headset-roles = [ "hsp_hs" "hsp_ag" "hfp_ag" ];
-
- # Enabled A2DP codecs (default: all)
- #bluez5.codecs = [ "sbc" "aac" "ldac" "aptx" "aptx_hd" ];
- };
-
- rules = [
- # an array of matches/actions to evaluate
- {
- # rules for matching a device or node. It is an array of
- # properties that all need to match the regexp. If any of the
- # matches work, the actions are executed for the object.
- matches = [
- {
- # this matches all cards
- device.name = "~bluez_card.*";
- }
- ];
- actions = {
- # actions can update properties on the matched object.
- update-props = {
- #device.nick = "My Device";
- };
- };
- }
- {
- matches = [
- {
- # matches all sinks
- node.name = "~bluez_input.*";
- }
- {
- # matches all sources
- node.name = "~bluez_output.*";
- }
- ];
- actions = {
- update-props = {
- #node.nick = "My Node"
- #node.nick = null;
- #priority.driver = 100;
- #priority.session = 100;
- #node.pause-on-idle = false;
- #resample.quality = 4;
- #channelmix.normalize = false;
- #channelmix.mix-lfe = false;
- };
- };
- }
- ];
+ bluez-monitor = mkOption {
+ type = types.attrs;
+ description = ''
+ Configuration for the bluez5 monitor. For details see
+ https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/${cfg.package.version}/src/daemon/media-session.d/bluez-monitor.conf
+ '';
+ default = {};
};
- };
-
- v4l2MonitorConfig = mkOption {
- type = types.attrs;
- description = ''
- Configuration for the V4L2 monitor.
- '';
- default = {
- # v4l2-monitor config file
- properties = {
- };
- rules = [
- # an array of matches/actions to evaluate
- {
- # rules for matching a device or node. It is an array of
- # properties that all need to match the regexp. If any of the
- # matches work, the actions are executed for the object.
- matches = [
- {
- # this matches all devices
- device.name = "~v4l2_device.*";
- }
- ];
- actions = {
- # actions can update properties on the matched object.
- update-props = {
- #device.nick = "My Device";
- };
- };
- }
- {
- matches = [
- {
- # matches all sinks
- node.name = "~v4l2_input.*";
- }
- {
- # matches all sources
- node.name = "~v4l2_output.*";
- }
- ];
- actions = {
- update-props = {
- #node.nick = "My Node";
- #node.nick = null;
- #priority.driver = 100;
- #priority.session = 100;
- #node.pause-on-idle = true;
- };
- };
- }
- ];
+ v4l2-monitor = mkOption {
+ type = types.attrs;
+ description = ''
+ Configuration for the V4L2 monitor. For details see
+ https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/${cfg.package.version}/src/daemon/media-session.d/v4l2-monitor.conf
+ '';
+ default = {};
};
};
};
@@ -325,16 +112,17 @@ in {
###### implementation
config = mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
- services.pipewire.sessionManagerExecutable = "${cfg.package}/bin/pipewire-media-session";
+ systemd.packages = [ cfg.package ];
+ systemd.user.services.pipewire-media-session.wantedBy = [ "pipewire.service" ];
- environment.etc."pipewire/media-session.d/media-session.conf" = { text = toSPAJSON cfg.config; };
- environment.etc."pipewire/media-session.d/v4l2-monitor.conf" = { text = toSPAJSON cfg.v4l2MonitorConfig; };
+ environment.etc."pipewire/media-session.d/media-session.conf" = { text = toSPAJSON (recursiveUpdate defaults.media-session cfg.config.media-session); };
+ environment.etc."pipewire/media-session.d/v4l2-monitor.conf" = { text = toSPAJSON (recursiveUpdate defaults.v4l2-monitor cfg.config.v4l2-monitor); };
environment.etc."pipewire/media-session.d/with-alsa" = mkIf config.services.pipewire.alsa.enable { text = ""; };
- environment.etc."pipewire/media-session.d/alsa-monitor.conf" = mkIf config.services.pipewire.alsa.enable { text = toSPAJSON cfg.alsaMonitorConfig; };
+ environment.etc."pipewire/media-session.d/alsa-monitor.conf" = mkIf config.services.pipewire.alsa.enable { text = toSPAJSON (recursiveUpdate defaults.alsa-monitor cfg.config.alsa-monitor); };
environment.etc."pipewire/media-session.d/with-pulseaudio" = mkIf config.services.pipewire.pulse.enable { text = ""; };
- environment.etc."pipewire/media-session.d/bluez-monitor.conf" = mkIf config.services.pipewire.pulse.enable { text = toSPAJSON cfg.bluezMonitorConfig; };
+ environment.etc."pipewire/media-session.d/bluez-monitor.conf" = mkIf config.services.pipewire.pulse.enable { text = toSPAJSON (recursiveUpdate defaults.bluez-monitor cfg.config.bluez-monitor); };
environment.etc."pipewire/media-session.d/with-jack" = mkIf config.services.pipewire.jack.enable { text = ""; };
};
diff --git a/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json b/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json
new file mode 100644
index 000000000000..da08bcea2c90
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/pipewire-pulse.conf.json
@@ -0,0 +1,28 @@
+{
+ "context.properties": {},
+ "context.spa-libs": {
+ "audio.convert.*": "audioconvert/libspa-audioconvert",
+ "support.*": "support/libspa-support"
+ },
+ "context.modules": {
+ "libpipewire-module-rtkit": {
+ "args": {},
+ "flags": [
+ "ifexists",
+ "nofail"
+ ]
+ },
+ "libpipewire-module-protocol-native": null,
+ "libpipewire-module-client-node": null,
+ "libpipewire-module-adapter": null,
+ "libpipewire-module-metadata": null,
+ "libpipewire-module-protocol-pulse": {
+ "args": {
+ "server.address": [
+ "unix:native"
+ ]
+ }
+ }
+ },
+ "stream.properties": {}
+}
diff --git a/nixos/modules/services/desktops/pipewire/pipewire.conf.json b/nixos/modules/services/desktops/pipewire/pipewire.conf.json
new file mode 100644
index 000000000000..59e2afca0939
--- /dev/null
+++ b/nixos/modules/services/desktops/pipewire/pipewire.conf.json
@@ -0,0 +1,55 @@
+{
+ "context.properties": {
+ "link.max-buffers": 16,
+ "core.daemon": true,
+ "core.name": "pipewire-0"
+ },
+ "context.spa-libs": {
+ "audio.convert.*": "audioconvert/libspa-audioconvert",
+ "api.alsa.*": "alsa/libspa-alsa",
+ "api.v4l2.*": "v4l2/libspa-v4l2",
+ "api.libcamera.*": "libcamera/libspa-libcamera",
+ "api.bluez5.*": "bluez5/libspa-bluez5",
+ "api.vulkan.*": "vulkan/libspa-vulkan",
+ "api.jack.*": "jack/libspa-jack",
+ "support.*": "support/libspa-support"
+ },
+ "context.modules": {
+ "libpipewire-module-rtkit": {
+ "args": {},
+ "flags": [
+ "ifexists",
+ "nofail"
+ ]
+ },
+ "libpipewire-module-protocol-native": null,
+ "libpipewire-module-profiler": null,
+ "libpipewire-module-metadata": null,
+ "libpipewire-module-spa-device-factory": null,
+ "libpipewire-module-spa-node-factory": null,
+ "libpipewire-module-client-node": null,
+ "libpipewire-module-client-device": null,
+ "libpipewire-module-portal": {
+ "flags": [
+ "ifexists",
+ "nofail"
+ ]
+ },
+ "libpipewire-module-access": {
+ "args": {}
+ },
+ "libpipewire-module-adapter": null,
+ "libpipewire-module-link-factory": null,
+ "libpipewire-module-session-manager": null
+ },
+ "context.objects": {
+ "spa-node-factory": {
+ "args": {
+ "factory.name": "support.node.driver",
+ "node.name": "Dummy-Driver",
+ "priority.driver": 8000
+ }
+ }
+ },
+ "context.exec": {}
+}
diff --git a/nixos/modules/services/desktops/pipewire/pipewire.nix b/nixos/modules/services/desktops/pipewire/pipewire.nix
index 044120de7c71..2577e77c4a1f 100644
--- a/nixos/modules/services/desktops/pipewire/pipewire.nix
+++ b/nixos/modules/services/desktops/pipewire/pipewire.nix
@@ -18,11 +18,53 @@ let
ln -s "${cfg.package.jack}/lib" "$out/lib/pipewire"
'';
+ prioritizeNativeProtocol = {
+ "context.modules" = {
+ # Most other modules depend on this, so put it first
+ "libpipewire-module-protocol-native" = {
+ _priority = -100;
+ _content = null;
+ };
+ };
+ };
+
+ fixDaemonModulePriorities = {
+ "context.modules" = {
+ # Most other modules depend on thism so put it first
+ "libpipewire-module-protocol-native" = {
+ _priority = -100;
+ _content = null;
+ };
+ # Needs to be before libpipewire-module-access
+ "libpipewire-module-portal" = {
+ _priority = -50;
+ _content = {
+ flags = [
+ "ifexists"
+ "nofail"
+ ];
+ };
+ };
+ };
+ };
+
+ # Use upstream config files passed through spa-json-dump as the base
+ # Patched here as necessary for them to work with this module
+ defaults = {
+ client = recursiveUpdate (builtins.fromJSON (builtins.readFile ./client.conf.json)) prioritizeNativeProtocol;
+ client-rt = recursiveUpdate (builtins.fromJSON (builtins.readFile ./client-rt.conf.json)) prioritizeNativeProtocol;
+ jack = recursiveUpdate (builtins.fromJSON (builtins.readFile ./jack.conf.json)) prioritizeNativeProtocol;
+ # Remove session manager invocation from the upstream generated file, it points to the wrong path
+ pipewire = recursiveUpdate (builtins.fromJSON (builtins.readFile ./pipewire.conf.json)) fixDaemonModulePriorities;
+ pipewire-pulse = recursiveUpdate (builtins.fromJSON (builtins.readFile ./pipewire-pulse.conf.json)) prioritizeNativeProtocol;
+ };
+
# Helpers for generating the pipewire JSON config file
mkSPAValueString = v:
if builtins.isList v then "[${lib.concatMapStringsSep " " mkSPAValueString v}]"
else if lib.types.attrs.check v then
"{${lib.concatStringsSep " " (mkSPAKeyValue v)}}"
+ else if builtins.isString v then "\"${lib.generators.mkValueStringDefault { } v}\""
else lib.generators.mkValueStringDefault { } v;
mkSPAKeyValue = attrs: map (def: def.content) (
@@ -64,129 +106,51 @@ in {
'';
};
- config = mkOption {
- type = types.attrs;
- description = ''
- Configuration for the pipewire daemon.
- '';
- default = {
- properties = {
- ## set-prop is used to configure properties in the system
- #
- # "library.name.system" = "support/libspa-support";
- # "context.data-loop.library.name.system" = "support/libspa-support";
- "link.max-buffers" = 16; # version < 3 clients can't handle more than 16
- #"mem.allow-mlock" = false;
- #"mem.mlock-all" = true;
- ## https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/src/pipewire/pipewire.h#L93
- #"log.level" = 2; # 5 is trace, which is verbose as hell, default is 2 which is warnings, 4 is debug output, 3 is info
-
- ## Properties for the DSP configuration
- #
- #"default.clock.rate" = 48000;
- #"default.clock.quantum" = 1024;
- #"default.clock.min-quantum" = 32;
- #"default.clock.max-quantum" = 8192;
- #"default.video.width" = 640;
- #"default.video.height" = 480;
- #"default.video.rate.num" = 25;
- #"default.video.rate.denom" = 1;
- };
-
- spa-libs = {
- ## add-spa-lib <factory-name regex> <library-name>
- #
- # used to find spa factory names. It maps an spa factory name
- # regular expression to a library name that should contain
- # that factory.
- #
- "audio.convert*" = "audioconvert/libspa-audioconvert";
- "api.alsa.*" = "alsa/libspa-alsa";
- "api.v4l2.*" = "v4l2/libspa-v4l2";
- "api.libcamera.*" = "libcamera/libspa-libcamera";
- "api.bluez5.*" = "bluez5/libspa-bluez5";
- "api.vulkan.*" = "vulkan/libspa-vulkan";
- "api.jack.*" = "jack/libspa-jack";
- "support.*" = "support/libspa-support";
- # "videotestsrc" = "videotestsrc/libspa-videotestsrc";
- # "audiotestsrc" = "audiotestsrc/libspa-audiotestsrc";
- };
-
- modules = {
- ## <module-name> = { [args = "<key>=<value> ..."]
- # [flags = ifexists] }
- # [flags = [ifexists]|[nofail]}
- #
- # Loads a module with the given parameters.
- # If ifexists is given, the module is ignoed when it is not found.
- # If nofail is given, module initialization failures are ignored.
- #
- libpipewire-module-rtkit = {
- args = {
- #rt.prio = 20;
- #rt.time.soft = 200000;
- #rt.time.hard = 200000;
- #nice.level = -11;
- };
- flags = "ifexists|nofail";
- };
- libpipewire-module-protocol-native = { _priority = -100; _content = "null"; };
- libpipewire-module-profiler = "null";
- libpipewire-module-metadata = "null";
- libpipewire-module-spa-device-factory = "null";
- libpipewire-module-spa-node-factory = "null";
- libpipewire-module-client-node = "null";
- libpipewire-module-client-device = "null";
- libpipewire-module-portal = "null";
- libpipewire-module-access = {
- args.access = {
- allowed = ["${builtins.unsafeDiscardStringContext cfg.sessionManagerExecutable}"];
- rejected = [];
- restricted = [];
- force = "flatpak";
- };
- };
- libpipewire-module-adapter = "null";
- libpipewire-module-link-factory = "null";
- libpipewire-module-session-manager = "null";
- };
-
- objects = {
- ## create-object [-nofail] <factory-name> [<key>=<value> ...]
- #
- # Creates an object from a PipeWire factory with the given parameters.
- # If -nofail is given, errors are ignored (and no object is created)
- #
- };
+ config = {
+ client = mkOption {
+ type = types.attrs;
+ default = {};
+ description = ''
+ Configuration for pipewire clients. For details see
+ https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/${cfg.package.version}/src/daemon/client.conf.in
+ '';
+ };
+ client-rt = mkOption {
+ type = types.attrs;
+ default = {};
+ description = ''
+ Configuration for realtime pipewire clients. For details see
+ https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/${cfg.package.version}/src/daemon/client-rt.conf.in
+ '';
+ };
- exec = {
- ## exec <program-name>
- #
- # Execute the given program. This is usually used to start the
- # session manager. run the session manager with -h for options
- #
- "${builtins.unsafeDiscardStringContext cfg.sessionManagerExecutable}" = { args = "\"${lib.concatStringsSep " " cfg.sessionManagerArguments}\""; };
- };
+ jack = mkOption {
+ type = types.attrs;
+ default = {};
+ description = ''
+ Configuration for the pipewire daemon's jack module. For details see
+ https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/${cfg.package.version}/src/daemon/jack.conf.in
+ '';
};
- };
- sessionManagerExecutable = mkOpt