mirror of
https://github.com/nix-community/home-manager.git
synced 2026-06-05 21:02:51 +00:00
pipewire: add module
This commit is contained in:
committed by
Robert Helgesson
parent
f7f6a559c2
commit
f899c5d6f3
15
modules/misc/news/2026/03/2026-04-11_09-06-17.nix
Normal file
15
modules/misc/news/2026/03/2026-04-11_09-06-17.nix
Normal file
@@ -0,0 +1,15 @@
|
||||
{ pkgs, ... }:
|
||||
{
|
||||
time = "2026-04-11T09:06:17+00:00";
|
||||
condition = pkgs.stdenv.hostPlatform.isLinux;
|
||||
message = ''
|
||||
A new module is available: `services.pipewire`.
|
||||
|
||||
The module provides options for configuring the PipeWire server, the
|
||||
client library, the PulseAudio and JACK emulators, the WirePlumber session
|
||||
manager, and the LV2 plugins for use in filter chains.
|
||||
|
||||
The module does *not* provide a way to install PipeWire, as that should be
|
||||
done through your NixOS config (or system package manager).
|
||||
'';
|
||||
}
|
||||
462
modules/services/pipewire.nix
Normal file
462
modules/services/pipewire.nix
Normal file
@@ -0,0 +1,462 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
attrByPath
|
||||
concatLists
|
||||
concatMap
|
||||
escapeShellArgs
|
||||
flatten
|
||||
hasSuffix
|
||||
hm
|
||||
literalExpression
|
||||
maintainers
|
||||
mapAttrsToList
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
optional
|
||||
optionals
|
||||
path
|
||||
platforms
|
||||
types
|
||||
;
|
||||
inherit (pkgs)
|
||||
buildEnv
|
||||
formats
|
||||
runCommand
|
||||
symlinkJoin
|
||||
writeTextDir
|
||||
;
|
||||
|
||||
jsonFormat = formats.json { };
|
||||
jsonAttrs = types.attrsOf jsonFormat.type;
|
||||
|
||||
cfg = config.services.pipewire;
|
||||
systemdCfg = config.systemd.user;
|
||||
in
|
||||
|
||||
{
|
||||
meta.maintainers = with maintainers; [ mikaeladev ];
|
||||
|
||||
options.services.pipewire = {
|
||||
enable = mkEnableOption "PipeWire configurations";
|
||||
|
||||
configs = mkOption {
|
||||
type = jsonAttrs;
|
||||
default = { };
|
||||
example = {
|
||||
"10-clock-rate" = {
|
||||
"context.properties" = {
|
||||
"default.clock.rate" = 44100;
|
||||
};
|
||||
};
|
||||
"11-no-upmixing" = {
|
||||
"stream.properties" = {
|
||||
"channelmix.upmix" = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Set of configuration files for the PipeWire server.
|
||||
|
||||
Every item in this attrset becomes a separate drop-in file in
|
||||
{file}`$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/`.
|
||||
|
||||
See `man pipewire.conf` for details, and the [PipeWire wiki] for
|
||||
examples.
|
||||
|
||||
[pipewire wiki]: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PipeWire
|
||||
'';
|
||||
};
|
||||
|
||||
clientConfigs = mkOption {
|
||||
type = jsonAttrs;
|
||||
default = { };
|
||||
example = {
|
||||
"10-no-resample" = {
|
||||
"stream.properties" = {
|
||||
"resample.disable" = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Set of configuration files for the PipeWire client library.
|
||||
|
||||
Every item in this attrset becomes a separate drop-in file in
|
||||
{file}`$XDG_CONFIG_HOME/pipewire/client.conf.d/`.
|
||||
|
||||
See the [PipeWire wiki][wiki] for examples.
|
||||
|
||||
[wiki]: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-client
|
||||
'';
|
||||
};
|
||||
|
||||
jackConfigs = mkOption {
|
||||
type = jsonAttrs;
|
||||
default = { };
|
||||
example = {
|
||||
"20-hide-midi" = {
|
||||
"jack.properties" = {
|
||||
"jack.show-midi" = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Set of configuration files for the PipeWire JACK server and client
|
||||
library.
|
||||
|
||||
Every item in this attrset becomes a separate drop-in file in
|
||||
{file}`$XDG_CONFIG_HOME/pipewire/jack.conf.d/`.
|
||||
|
||||
See the [PipeWire wiki] for examples.
|
||||
|
||||
[pipewire wiki]: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-JACK
|
||||
'';
|
||||
};
|
||||
|
||||
pulseConfigs = mkOption {
|
||||
type = jsonAttrs;
|
||||
default = { };
|
||||
example = {
|
||||
"15-force-s16-info" = {
|
||||
"pulse.rules" = [
|
||||
{
|
||||
matches = [ { "application.process.binary" = "my-broken-app"; } ];
|
||||
actions = {
|
||||
quirks = [ "force-s16-info" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Set of configuration files for the PipeWire PulseAudio server.
|
||||
|
||||
Every item in this attrset becomes a separate drop-in file in
|
||||
{file}`$XDG_CONFIG_HOME/pipewire/pipewire-pulse.conf.d/`.
|
||||
|
||||
See `man pipewire-pulse.conf` for details, and the [PipeWire wiki] for
|
||||
examples.
|
||||
|
||||
[pipewire wiki]: https://gitlab.freedesktop.org/pipewire/pipewire/-/wikis/Config-PulseAudio
|
||||
'';
|
||||
};
|
||||
|
||||
configPackages = mkOption {
|
||||
type = with types; listOf package;
|
||||
default = [ ];
|
||||
example = literalExpression ''
|
||||
[
|
||||
(pkgs.writeTextDir "share/pipewire/pipewire.conf.d/10-loopback.conf" '''
|
||||
context.modules = [
|
||||
{
|
||||
name = libpipewire-module-loopback
|
||||
args = {
|
||||
node.description = "Scarlett Focusrite Line 1"
|
||||
capture.props = {
|
||||
audio.position = [ FL ]
|
||||
stream.dont-remix = true
|
||||
node.target = "alsa_input.usb-Focusrite_Scarlett_Solo_USB_Y7ZD17C24495BC-00.analog-stereo"
|
||||
node.passive = true
|
||||
}
|
||||
playback.props = {
|
||||
node.name = "SF_mono_in_1"
|
||||
media.class = "Audio/Source"
|
||||
audio.position = [ MONO ]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
''')
|
||||
]'';
|
||||
description = ''
|
||||
List of packages that provide PipeWire configurations, in the form of
|
||||
{file}`share/pipewire/*/*.conf` files.
|
||||
|
||||
LV2 dependencies will be picked up from config packages automatically
|
||||
via `passthru.requiredLv2Packages`.
|
||||
'';
|
||||
};
|
||||
|
||||
extraLv2Packages = mkOption {
|
||||
type = with types; listOf package;
|
||||
default = [ ];
|
||||
example = literalExpression "[ pkgs.lsp-plugins ]";
|
||||
description = ''
|
||||
List of packages that provide LV2 plugins, in the form of
|
||||
{file}`lib/lv2/*` files.
|
||||
|
||||
LV2 dependencies will be picked up from config packages automatically
|
||||
via `passthru.requiredLv2Packages`, so they don't need to be set here.
|
||||
'';
|
||||
};
|
||||
|
||||
wireplumber = {
|
||||
enable = mkEnableOption "WirePlumber configurations";
|
||||
|
||||
configs = mkOption {
|
||||
type = jsonAttrs;
|
||||
default = { };
|
||||
example = {
|
||||
log-level-debug = {
|
||||
"context.properties" = {
|
||||
"log.level" = "D";
|
||||
};
|
||||
};
|
||||
wh-1000xm3-ldac-hq = {
|
||||
"monitor.bluez.rules" = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
"device.name" = "~bluez_card.*";
|
||||
"device.product.id" = "0x0cd3";
|
||||
"device.vendor.id" = "usb:054c";
|
||||
}
|
||||
];
|
||||
actions = {
|
||||
update-props = {
|
||||
"bluez5.a2dp.ldac.quality" = "hq";
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
description = ''
|
||||
Set of configuration files for the WirePlumber daemon.
|
||||
|
||||
Every item in this attrset becomes a separate drop-in file in
|
||||
{file}`$XDG_CONFIG_HOME/wireplumber/wireplumber.conf.d/`.
|
||||
|
||||
See the [NixOS option] for details.
|
||||
|
||||
[nixos option]: https://search.nixos.org/options?channel=25.11&type=options&show=services.pipewire.wireplumber.extraConfig
|
||||
'';
|
||||
};
|
||||
|
||||
configPackages = mkOption {
|
||||
type = with types; listOf package;
|
||||
default = [ ];
|
||||
example = literalExpression ''
|
||||
[
|
||||
(pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/10-bluez.conf" '''
|
||||
monitor.bluez.properties = {
|
||||
bluez5.roles = [ a2dp_sink a2dp_source bap_sink bap_source hsp_hs hsp_ag hfp_hf hfp_ag ]
|
||||
bluez5.codecs = [ sbc sbc_xq aac ]
|
||||
bluez5.enable-sbc-xq = true
|
||||
bluez5.hfphsp-backend = "native"
|
||||
}
|
||||
''')
|
||||
]'';
|
||||
description = ''
|
||||
List of packages that provide WirePlumber configurations, in the form
|
||||
of {file}`share/wireplumber/*/*.conf` files.
|
||||
|
||||
LV2 dependencies will be picked up from config packages automatically
|
||||
via `passthru.requiredLv2Packages`.
|
||||
'';
|
||||
};
|
||||
|
||||
scripts = mkOption {
|
||||
type = with types; attrsOf lines;
|
||||
default = { };
|
||||
example = {
|
||||
"test/hello-world.lua" = ''
|
||||
print("Hello, world!")
|
||||
'';
|
||||
};
|
||||
description = ''
|
||||
Set of lua scripts to be used by WirePlumber configuration files.
|
||||
|
||||
Every item in this attrset becomes a separate drop-in file in
|
||||
{file}`$XDG_DATA_HOME/wireplumber/scripts/`.
|
||||
|
||||
See the [NixOS option] for details.
|
||||
|
||||
[nixos option]: https://search.nixos.org/options?channel=25.11&type=options&show=services.pipewire.wireplumber.extraScripts
|
||||
'';
|
||||
};
|
||||
|
||||
scriptPackages = mkOption {
|
||||
type = with types; listOf package;
|
||||
default = [ ];
|
||||
example = literalExpression ''
|
||||
[
|
||||
(pkgs.writeTextDir "share/wireplumber/scripts/test/hello-world.lua" '''
|
||||
print("Hello, world!")
|
||||
''')
|
||||
]'';
|
||||
description = ''
|
||||
List of packages that provide WirePlumber scripts, in the form of
|
||||
{file}`share/wireplumber/scripts/*/*.lua` files.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
(hm.assertions.assertPlatform "services.pipewire" pkgs platforms.linux)
|
||||
];
|
||||
|
||||
xdg =
|
||||
let
|
||||
withSuffix = suffix: value: if (hasSuffix suffix value) then value else (value + suffix);
|
||||
|
||||
mapConfigsToPaths =
|
||||
parent: subdir: configs:
|
||||
mapAttrsToList (
|
||||
name: value:
|
||||
let
|
||||
filename = withSuffix ".conf" name;
|
||||
filepath = path.subpath.join [
|
||||
"share/${parent}/${subdir}.conf.d"
|
||||
filename
|
||||
];
|
||||
in
|
||||
runCommand "pipewire-${name}-config" { } ''
|
||||
mkdir -p $out/${dirOf filepath}
|
||||
ln -s ${jsonFormat.generate name value} $out/${filepath}
|
||||
''
|
||||
) configs;
|
||||
|
||||
condMapConfigsToPaths =
|
||||
parent: subdir: configs:
|
||||
optional (configs != { }) (mapConfigsToPaths parent subdir configs);
|
||||
|
||||
pipewireConfigPaths =
|
||||
cfg.configPackages
|
||||
++ concatLists [
|
||||
(condMapConfigsToPaths "pipewire" "pipewire" cfg.configs)
|
||||
(condMapConfigsToPaths "pipewire" "client" cfg.clientConfigs)
|
||||
(condMapConfigsToPaths "pipewire" "jack" cfg.jackConfigs)
|
||||
(condMapConfigsToPaths "pipewire" "pipewire-pulse" cfg.pulseConfigs)
|
||||
];
|
||||
|
||||
wireplumberConfigPaths =
|
||||
cfg.wireplumber.configPackages
|
||||
++ (condMapConfigsToPaths "wireplumber" "wireplumber" cfg.wireplumber.configs);
|
||||
|
||||
wireplumberScriptPaths =
|
||||
cfg.wireplumber.scriptPackages
|
||||
++ (optional (cfg.wireplumber.scripts != { }) (
|
||||
mapAttrsToList (
|
||||
name: content:
|
||||
let
|
||||
filename = withSuffix ".lua" name;
|
||||
filepath = path.subpath.join [
|
||||
"share/wireplumber/scripts"
|
||||
filename
|
||||
];
|
||||
in
|
||||
writeTextDir filepath content
|
||||
) cfg.wireplumber.scripts
|
||||
));
|
||||
|
||||
onChange = ''
|
||||
if [[ ! -v PIPEWIRE_RELOAD ]]; then
|
||||
PIPEWIRE_RELOAD=1
|
||||
fi
|
||||
'';
|
||||
in
|
||||
{
|
||||
configFile = {
|
||||
"pipewire" = {
|
||||
inherit onChange;
|
||||
enable = pipewireConfigPaths != [ ];
|
||||
source = symlinkJoin {
|
||||
name = "pipewire-configs";
|
||||
paths = pipewireConfigPaths;
|
||||
stripPrefix = "/share/pipewire";
|
||||
};
|
||||
};
|
||||
"wireplumber" = mkIf cfg.wireplumber.enable {
|
||||
inherit onChange;
|
||||
enable = wireplumberConfigPaths != [ ];
|
||||
source = symlinkJoin {
|
||||
name = "wireplumber-configs";
|
||||
paths = wireplumberConfigPaths;
|
||||
stripPrefix = "/share/wireplumber";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dataFile = {
|
||||
"wireplumber" = mkIf cfg.wireplumber.enable {
|
||||
inherit onChange;
|
||||
enable = wireplumberScriptPaths != [ ];
|
||||
source = symlinkJoin {
|
||||
name = "wireplumber-scripts";
|
||||
paths = wireplumberScriptPaths;
|
||||
stripPrefix = "/share/wireplumber";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.user.sessionVariables =
|
||||
let
|
||||
lv2PluginPaths =
|
||||
cfg.extraLv2Packages
|
||||
++ flatten (
|
||||
concatMap (p: attrByPath [ "passthru" "requiredLv2Packages" ] [ ] p) (
|
||||
cfg.configPackages ++ (optionals cfg.wireplumber.enable cfg.wireplumber.configPackages)
|
||||
)
|
||||
);
|
||||
|
||||
lv2Plugins = buildEnv {
|
||||
name = "pipewire-lv2-plugins";
|
||||
paths = lv2PluginPaths;
|
||||
pathsToLink = [ "/lib/lv2" ];
|
||||
};
|
||||
in
|
||||
{
|
||||
LV2_PATH = mkIf (lv2PluginPaths != [ ]) "${lv2Plugins}/lib/lv2\${LV2_PATH:+:$LV2_PATH}";
|
||||
};
|
||||
|
||||
home.activation.reloadPipewire =
|
||||
let
|
||||
pipewireUnits = escapeShellArgs (
|
||||
[
|
||||
"pipewire"
|
||||
"pipewire-pulse"
|
||||
]
|
||||
++ optional cfg.wireplumber.enable "wireplumber"
|
||||
);
|
||||
|
||||
ensureSystemd = ''
|
||||
env XDG_RUNTIME_DIR="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" \
|
||||
PATH="${dirOf systemdCfg.systemctlPath}:$PATH" \
|
||||
'';
|
||||
|
||||
systemctl = "${ensureSystemd} systemctl";
|
||||
in
|
||||
mkIf (systemdCfg.enable && config.home.username != "root") (
|
||||
hm.dag.entryAfter [ "onFilesChange" "reloadSystemd" ] ''
|
||||
if [[ -v PIPEWIRE_RELOAD ]]; then
|
||||
if [[ -v DRY_RUN ]]; then
|
||||
echo 'systemctl --user restart ${pipewireUnits}'
|
||||
else
|
||||
systemdStatus=$(${systemctl} --user is-system-running 2>&1 || true)
|
||||
|
||||
if [[ $systemdStatus == 'running' ]]; then
|
||||
${systemctl} --user restart ${pipewireUnits}
|
||||
else
|
||||
echo "User systemd daemon not running. Skipping pipewire reload."
|
||||
fi
|
||||
|
||||
unset systemdStatus
|
||||
fi
|
||||
|
||||
unset PIPEWIRE_RELOAD
|
||||
fi
|
||||
''
|
||||
);
|
||||
};
|
||||
}
|
||||
76
tests/modules/services/pipewire/configs.nix
Normal file
76
tests/modules/services/pipewire/configs.nix
Normal file
@@ -0,0 +1,76 @@
|
||||
{ pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
jsonFormat = pkgs.formats.json { };
|
||||
|
||||
expectedValue = {
|
||||
"foo.bar" = {
|
||||
"baz.qux" = true;
|
||||
};
|
||||
"baz.qux" = {
|
||||
"foo.bar" = false;
|
||||
};
|
||||
};
|
||||
|
||||
expectedValuePath = jsonFormat.generate "expected-pipewire-config" expectedValue;
|
||||
expectedValueContent = lib.readFile expectedValuePath;
|
||||
in
|
||||
|
||||
{
|
||||
services.pipewire = rec {
|
||||
enable = true;
|
||||
|
||||
configs = {
|
||||
"10-test" = expectedValue;
|
||||
"11-test" = expectedValue;
|
||||
};
|
||||
|
||||
clientConfigs = configs;
|
||||
jackConfigs = configs;
|
||||
pulseConfigs = configs;
|
||||
|
||||
configPackages = [
|
||||
(pkgs.writeTextDir "share/pipewire/pipewire.conf.d/12-test.conf" expectedValueContent)
|
||||
(pkgs.writeTextDir "share/pipewire/client.conf.d/12-test.conf" expectedValueContent)
|
||||
(pkgs.writeTextDir "share/pipewire/jack.conf.d/12-test.conf" expectedValueContent)
|
||||
(pkgs.writeTextDir "share/pipewire/pipewire-pulse.conf.d/12-test.conf" expectedValueContent)
|
||||
];
|
||||
|
||||
wireplumber = {
|
||||
enable = true;
|
||||
inherit configs;
|
||||
configPackages = [
|
||||
(pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/12-test.conf" expectedValueContent)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertPathNotExists 'home-files/.local/share/wireplumber'
|
||||
|
||||
local expected=${expectedValuePath}
|
||||
|
||||
local names=(
|
||||
'10-test.conf'
|
||||
'11-test.conf'
|
||||
'12-test.conf'
|
||||
)
|
||||
|
||||
local subdirs=(
|
||||
'pipewire/pipewire.conf.d'
|
||||
'pipewire/client.conf.d'
|
||||
'pipewire/jack.conf.d'
|
||||
'pipewire/pipewire-pulse.conf.d'
|
||||
'wireplumber/wireplumber.conf.d'
|
||||
)
|
||||
|
||||
for subdir in $subdirs; do
|
||||
for name in $names; do
|
||||
local file="home-files/.config/$subdir/$name"
|
||||
|
||||
assertFileExists "$file"
|
||||
assertFileContent "$file" "$expected"
|
||||
done
|
||||
done
|
||||
'';
|
||||
}
|
||||
8
tests/modules/services/pipewire/default.nix
Normal file
8
tests/modules/services/pipewire/default.nix
Normal file
@@ -0,0 +1,8 @@
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
|
||||
pipewire-configs = ./configs.nix;
|
||||
pipewire-empty = ./empty.nix;
|
||||
pipewire-plugins = ./plugins.nix;
|
||||
pipewire-scripts = ./scripts.nix;
|
||||
}
|
||||
12
tests/modules/services/pipewire/empty.nix
Normal file
12
tests/modules/services/pipewire/empty.nix
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
wireplumber.enable = true;
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertPathNotExists 'home-files/.config/pipewire'
|
||||
assertPathNotExists 'home-files/.config/wireplumber'
|
||||
assertPathNotExists 'home-files/.local/share/wireplumber'
|
||||
'';
|
||||
}
|
||||
25
tests/modules/services/pipewire/plugins.nix
Normal file
25
tests/modules/services/pipewire/plugins.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
|
||||
extraLv2Packages = [
|
||||
(pkgs.writeTextDir "lib/lv2/test" ''
|
||||
bing bong
|
||||
'')
|
||||
];
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertPathNotExists 'home-files/.config/pipewire'
|
||||
assertPathNotExists 'home-files/.config/wireplumber'
|
||||
assertPathNotExists 'home-files/.local/share/wireplumber'
|
||||
|
||||
file='home-files/.config/environment.d/10-home-manager.conf'
|
||||
regex='^LV2_PATH=/nix/store/.*/lib/lv2\''${LV2_PATH:+:\$LV2_PATH}$'
|
||||
|
||||
assertFileExists "$file"
|
||||
assertFileRegex "$file" "$regex"
|
||||
'';
|
||||
}
|
||||
47
tests/modules/services/pipewire/scripts.nix
Normal file
47
tests/modules/services/pipewire/scripts.nix
Normal file
@@ -0,0 +1,47 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (pkgs) writeText;
|
||||
|
||||
expectedValue = ''
|
||||
print("Hello, world!")
|
||||
'';
|
||||
|
||||
expectedValuePath = writeText "expected-wireplumber-script" expectedValue;
|
||||
in
|
||||
|
||||
{
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
wireplumber = {
|
||||
enable = true;
|
||||
scripts = {
|
||||
"foo/hello-world.lua" = expectedValue;
|
||||
"bar/hello-world.lua" = expectedValue;
|
||||
};
|
||||
scriptPackages = [
|
||||
(pkgs.writeTextDir "share/wireplumber/scripts/baz/hello-world.lua" expectedValue)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertPathNotExists 'home-files/.config/pipewire'
|
||||
assertPathNotExists 'home-files/.config/wireplumber'
|
||||
|
||||
local expected=${expectedValuePath}
|
||||
|
||||
local scripts=(
|
||||
'foo/hello-world.lua'
|
||||
'bar/hello-world.lua'
|
||||
'baz/hello-world.lua'
|
||||
)
|
||||
|
||||
for script in $scripts; do
|
||||
local file="home-files/.local/share/wireplumber/scripts/$script"
|
||||
|
||||
assertFileExists "$file"
|
||||
assertFileContent "$file" "$expected"
|
||||
done
|
||||
'';
|
||||
}
|
||||
Reference in New Issue
Block a user