Skip to content

wireplumber: init, add NixOS module#150548

Merged
jtojnar merged 3 commits intoNixOS:masterfrom
K900:wireplumber
Jan 8, 2022
Merged

wireplumber: init, add NixOS module#150548
jtojnar merged 3 commits intoNixOS:masterfrom
K900:wireplumber

Conversation

@K900
Copy link
Contributor

@K900 K900 commented Dec 13, 2021

Motivation for this change

Upstream recommends this over pipewire-media-session: https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/41392eda7fb0e8b27a0167ef04241b18e9c14bf8/NEWS#L295

Depends on #153658

Things done
  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 22.05 Release Notes (or backporting 21.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
    • (Release notes changes) Ran nixos/doc/manual/md-to-db.sh to update generated release notes
  • Fits CONTRIBUTING.md.

@github-actions github-actions bot added 6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` labels Dec 13, 2021
@legendofmiracles
Copy link
Contributor

Result of nixpkgs-review pr 150548 run on x86_64-linux 1

1 package blacklisted:
  • nixos-install-tools
1 package built:
  • wireplumber

This was referenced Dec 13, 2021
@ofborg ofborg bot added 8.has: package (new) This PR adds a new package 11.by: package-maintainer This PR was created by a maintainer of all the package it changes. 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. labels Dec 13, 2021
@tadfisher
Copy link
Contributor

Good start. Maybe provide main/bluetooth/policy options to create a 99-nixos.lua drop-in in /etc/wireplumber/{main,bluetooth,policy}.lua.d/? That can be a follow-up though.

@K900
Copy link
Contributor Author

K900 commented Dec 13, 2021

I was thinking about it, but I decided not to, because I honestly have no idea what people's configurations are going to look like (or why anyone would want to write a custom configuration in the first place). I'd give it a few months and see what people actually use to configure it...

@jansol
Copy link
Contributor

jansol commented Dec 13, 2021

Agreed, just dropping the upstream default config in place should be a relatively safe starting point. If you don't mind, could you also change the pipewire module to have an enum for enabling one of the two session managers instead of separate enables for both? Ideally we wouldn't even have publicly visible enable options for the session managers.

Copy link
Member

@arcnmx arcnmx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some notes in addition to the inline comments...

  • pkgs/development/libraries/pipewire/wireplumber.nix doesn't quite seem like the right place to me, it is still a separate codebase from pipewire. It is however both a daemon and a library...
  • something along the lines of outputs = [ "bin" "out" "dev" "doc" (and/or "man"?) ] is probably warranted here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anything pkgs is used for should be explicitly added to this argument list instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there (probably?) should be an assertion to prevent mixing the two session managers

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo it'd be nice if this were conditional on an enableDocs arg

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed this too.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This likely needs to be optional on stdenv.hostPlatform == stdenv.buildPlatform due to longstanding issues wrt cross-compiling gobject-introspection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a separate enableGI argument that defaults to this, if someone really wants to shoot themselves in the foot, they can go ahead and override.

@K900
Copy link
Contributor Author

K900 commented Dec 14, 2021

Agreed, just dropping the upstream default config in place should be a relatively safe starting point. If you don't mind, could you also change the pipewire module to have an enum for enabling one of the two session managers instead of separate enables for both? Ideally we wouldn't even have publicly visible enable options for the session managers.

The upstream config is like 2000 lines of Lua, and it's not really intended to be modified, it's more likely you're going to write your own scripts on top of it.

@arcnmx
Copy link
Member

arcnmx commented Dec 14, 2021

The upstream config is like 2000 lines of Lua, and it's not really intended to be modified, it's more likely you're going to write your own scripts on top of it.

You're presumably talking about the upstream scripts? Those are very different from the upstream config, which despite being some 500 lines of lua is indeed very much intended to be modified by the user. It is not very fun to reproduce in nix.

(essentially, the config lua scripts generate json(ish) configuration data to be passed to the scripts, which then actually do all the work - and lua is the only available method for providing said config data to the scripts. iow the lua configs serve as an overly complex preprocessor for the actual configuration data)

@K900
Copy link
Contributor Author

K900 commented Dec 14, 2021

despite being some 500 lines of lua is indeed very much intended to be modified by the user

I think the intent of that is that you write your own scripts that you drop in whatever.lua.d and just call the same stuff upstream does, or, if you really need to override something, replace it with an empty file, systemd-style.

@K900
Copy link
Contributor Author

K900 commented Dec 14, 2021

Also, added split outputs. bin and out can't really split because of a dep cycle.

@K900
Copy link
Contributor Author

K900 commented Dec 14, 2021

Also, I haven't touched the NixOS side yet because I'm trying to think of a good way to make it extensible... Any ideas?

@arcnmx
Copy link
Member

arcnmx commented Dec 14, 2021

I think the intent of that is that you write your own scripts that you drop in whatever.lua.d and just call the same stuff upstream does, or, if you really need to override something, replace it with an empty file, systemd-style.

Eh it's... a haphazard mess, really. If you copy the commented-out examples and override an existing file, you slowly diverge from upstream over time. If you only insert new files, you can pretend that you're not modifying config but any config code you write implicitly depends on the objects defined/used in the config files that come before and after your new config. But yes, insertion is meant to be possible as long as you never dare to use the env vars to do things like override/add scripts or configs, at which point the file resolution and merging from /etc to /share is unreliable and completely changes/breaks.

Also, I haven't touched the NixOS side yet because I'm trying to think of a good way to make it extensible... Any ideas?

So I agree with what was said previously, that this is a fine start and module expansion can always happen later... but I'd probably suggest starting with having nix manage only the .conf json files. They're relatively simple compared to the rest of wireplumber; based off of the same core pipewire and media-session's pw config, just with an additional option or two for wireplumber. That lets you specify a sequence of wireplumber configs, plugins, and scripts to load, so it'd be easy enough to point it to the upstream configs, or let users point it elsewhere. At that point it's pretty customizeable, though dealing with the lua is still just kind of left as the user's problem.

Unrelated, but this might be needed btw, I don't think [Install] sections get pulled in by systemd.packages?
EDIT: I missed that, nevermind!

@K900
Copy link
Contributor Author

K900 commented Dec 14, 2021

@K900
Copy link
Contributor Author

K900 commented Dec 14, 2021

So I came up with something kind of interesting. We can have pipewire.sessionManager.package just be a package, and then have pipewire.media-session.enable and pipewire.wireplumber.enable just set that, while also allowing the user to provide their own implementation entirely.

@jansol
Copy link
Contributor

jansol commented Dec 15, 2021

Works On My Machine ™️

The lack of configuration should not be a problem for simple setups where everything just goes straight from/to the default sound card with an autodetected device profile, i.e. the vast majority of use cases... Although I'm not entirely sure how much overlap that crowd has with the NixOS userbase ;). Either way it's off by default so it shouldn't really be able to break any existing setups.

Please add assertions to make pipewire-media-session.enable and wireplumber.enable mutually exclusive to slightly reduce the risk of people shooting themselves in the foot, like requested in the review earlier. After that I'd say this is good for merging.

@K900
Copy link
Contributor Author

K900 commented Dec 15, 2021

My latest change will actually make it fail when both are enabled, as both will set pipewire.sessionManager.package

@jansol
Copy link
Contributor

jansol commented Dec 15, 2021

Right. The error message even points to the right places so I guess that's fine.

@K900
Copy link
Contributor Author

K900 commented Dec 15, 2021

Whoops. Emergency hotfix.

@jansol
Copy link
Contributor

jansol commented Dec 15, 2021

That said, it could still be more explicit about the enable options specifically being the problem, especially if one simply enables wireplumber and moves on. Right now it complains about services.pipewire.sessionManager.package which doesn't make it immediately obvious that you have to disable services.pipewire.media-session.enable which defaults to enabled.

@K900
Copy link
Contributor Author

K900 commented Dec 15, 2021

Actually, we should probably just stop defaulting that to true, and instead default to wireplumber...

@jansol
Copy link
Contributor

jansol commented Dec 15, 2021

Eventually yes since media-session is being phased out. But it's a bit too early for that, considering that you can't really configure wireplumber in the module's current state but configuration for media-session has been there for a long time and works fine.

@K900
Copy link
Contributor Author

K900 commented Dec 15, 2021

All right, let's stick to media-session for now then, and add the assertion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, I believe the nixpkgs policy is to write the parameters one per line. Helps keep diffs a bit cleaner when adding / removing stuff in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to be all over the place, but it makes sense. Added some newlines.

@K900 K900 requested review from arcnmx and jansol December 15, 2021 21:15
@K900
Copy link
Contributor Author

K900 commented Dec 15, 2021

Cleaned up the commit history a bit, also switched python39 to just python3 in build-inputs, since there's probably no reason to pin it.

@jansol
Copy link
Contributor

jansol commented Dec 16, 2021

Built & runs nicely on my desktop with that assertion fix and the latest pipewire release (#150999).

@jansol
Copy link
Contributor

jansol commented Dec 20, 2021

Found one problem with wireplumber: it refuses to let me connect the pipewire filter-chain node running rnnoise to the capture input of Teams although it is supposed to be the default input.

@K900
Copy link
Contributor Author

K900 commented Dec 20, 2021

That sounds like an upstream issue maybe?

@jansol
Copy link
Contributor

jansol commented Dec 20, 2021

Likely so, and it can probably be fixed with some configuration changes. Wireplumber overall seems to be unnecessarily eager to connect inputs to the front panel mic input that doesn't even have a mic plugged in. Anyway, seems pretty much to be expected at this stage and in a simpler setup it wouldn't be a problem anyway.

@K900 K900 requested a review from jansol December 21, 2021 10:46
@K900
Copy link
Contributor Author

K900 commented Dec 21, 2021

Anything left to do here? I say we merge as-is and then I'll try to figure out the config story.

Copy link
Contributor

@jansol jansol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think this is mergeable as a first step now.

@K900 K900 requested a review from jansol January 6, 2022 19:07
@K900
Copy link
Contributor Author

K900 commented Jan 6, 2022

Rebased to include latest pipewire systemwide changes from master, also updated to today's wireplumber 0.4.6.

@K900
Copy link
Contributor Author

K900 commented Jan 6, 2022

Will need to rerun the tests after #153658

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this option necessary? One can easily use overlays since this is not expected to be a dependency of any package so overlays should not cause any extra rebuilds.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really familiar with using overlays, does that just automagically replace the corresponding package everywhere?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you can pass e.g. overlays = [ (final: prev: { wireplumber = prev.wireplumber.overrideAttrs (attrs: rec { version = "…"; src = "…"; }); }) ] to nixpkgs (or use nixpkgs.overlays option if you do not override the nixpkgs.pkgs option) and it will replace wireplumber in pkgs passed to the modules.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, but pipewire-media-session has it, so I thought it should be here for consistency as well. Also, wireplumber is (sort of) a library, so it's possible other things will start depending on it at some point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is overlays > package options in modules a documented policy nowadays? If so, it makes sense to not have this option here at all and mark it deprecated in the pipewire module as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It always felt to me that package options are cargo cult. They should only be necessary when overriding the package globally would cause rebuilds of the system (e.g. in case of systemd).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This creates two different ways to set the session manager. Given that pipewire itself is not configured in any way by this, I think it might be cleanest to just install each session manager individually in its own module. This kind of de-duplication feels forced to me anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was to have a working session manager by default and not require looking where it needs to be disabled when switching to a different one. Granted, it is a bit redundant if media-session is going to be removed as soon as wireplumber is usable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These conflict with each other, you can only assign systemd{.user}.services.${cfg.sessionManager.package.unitName} once so to set both it has to be done with an object rather than standalone attributes, i.e.:

systemd.services."${cfg.sessionManager.package.unitName}" = {
  enable = if cfg.sessionManager.enable then cfg.systemWide else false;
  wantedBy = [ "pipewire.service" ];
};
systemd.user.services."${cfg.sessionManager.package.unitName}" = {
  enable = if cfg.sessionManager.enable then !cfg.systemWide else false;
  wantedBy = [ "pipewire.service" ];
};

But as mentioned in another comment it's probably better to not do this whole dance at all and just get rid of service.pipewire.sessionManager completely. The only thing it gets us atm is it says that two places are trying to set the option, and there is an assertion to guard against that anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All right, let's keep it simple for now then.

@K900 K900 requested review from jansol and jtojnar January 7, 2022 10:48
Copy link
Member

@jtojnar jtojnar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just few more nits, looks great otherwise.

@K900 K900 requested a review from jtojnar January 7, 2022 14:33
This is extremely basic for now, but we can add more stuff later
Copy link
Member

@jtojnar jtojnar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, did not test.

Thanks.

Copy link
Contributor

@jansol jansol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM & works on my setup.

@jtojnar jtojnar merged commit 283c47b into NixOS:master Jan 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: nixos Issues or PRs affecting NixOS modules, or package usability issues specific to NixOS 8.has: module (update) This PR changes an existing module in `nixos/` 8.has: package (new) This PR adds a new package 10.rebuild-darwin: 0 This PR does not cause any packages to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 11.by: package-maintainer This PR was created by a maintainer of all the package it changes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants