Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pipewire: 0.3.18 -> 0.3.21 #110615

Merged
merged 5 commits into from Feb 17, 2021
Merged

pipewire: 0.3.18 -> 0.3.21 #110615

merged 5 commits into from Feb 17, 2021

Conversation

jansol
Copy link
Contributor

@jansol jansol commented Jan 23, 2021

Motivation for this change

https://gitlab.freedesktop.org/pipewire/pipewire/-/releases/0.3.21
https://gitlab.freedesktop.org/pipewire/pipewire/-/releases/0.3.20
https://gitlab.freedesktop.org/pipewire/pipewire/-/releases/0.3.19

Things done

Initial attempt at generating config file in the new format using the upstream template as a base. Pulseaudio and jack (patchbays) seem to be working, everything else needs testing.

  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

Copy link
Member

@eadwu eadwu left a comment

Choose a reason for hiding this comment

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

I think it's still missing the *-monitor files, though overriding specific array values are a problem, though it can be mitigated by overrides if it is based on the order of the elements in the array.

Not quite sure about if the attribute sets are valid for the configuration, I only used a literal translation "bluez5.msbc-support".

};
flags = "ifexists|nofail";
};
libpipewire-module-protocol-native = null;
Copy link
Member

Choose a reason for hiding this comment

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

This needs to be ordered in order for pipewire to work on my machine (thus the sortProperties in the generation), though I'm not too sure about how nice it looks with libpipewire-module-protocol-native = { _priority = -100; _content = "null"; }; being what I have locally.

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 addressed now? Do we care?

"{${lib.concatStringsSep " " (mkSPAKeyValue { _SPA_DUP = v._type or "" == "_SPA_DUP"; } v)}}"
else lib.generators.mkValueStringDefault {} v;

mkSPAKeyValue = { _SPA_DUP ? false }: attrs: map (def: def.content) (lib.sortProperties
Copy link
Member

Choose a reason for hiding this comment

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

I couldn't get this working in any sort of elegant fashion, though the only part affected by this is the objects field for pipewire.conf.

Copy link
Member

@eadwu eadwu Jan 23, 2021

Choose a reason for hiding this comment

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

The simplified version that just gets rid of the _SPA_DUP

  mkSPAValueString = v:
    if builtins.isList v then "[${lib.concatMapStringsSep " " mkSPAValueString v}]"
    else if lib.types.attrs.check v then
      "{${lib.concatStringsSep " " (mkSPAKeyValue 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)}")
          attrs
      )
  );

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm how is that meant to be used? With the current toSPAJSON = attrs: lib.concatStringsSep "\n" (mkSPAKeyValue {} attrs); these just cause a "attempt to call something which is not a function but a list.

Copy link
Member

Choose a reason for hiding this comment

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

How about this?

Copy link
Member

Choose a reason for hiding this comment

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

If we're making converting the JSON to Nix sets before reconverting that to SPA JSON then more or less you'll still need parts of this. sortProperties will definitely be needed because of the load-module ordering dependency.

Copy link
Member

Choose a reason for hiding this comment

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

Also get's messy if there are multiple objects with the same factory since duplicate keys aren't allowed in Nix sets.

@jansol
Copy link
Contributor Author

jansol commented Jan 24, 2021

Now it builds and the config file looks horrible somewhat usable but the daemon fails to launch with: pipewire[32692]: daemon 0x7ffde1ef2070: could not load module "libpipewire-module-metadata": Protocol error. Need to figure out why that happens.

There are also a couple of config files for the media session that need to be generated...

@eadwu
Copy link
Member

eadwu commented Jan 24, 2021

I'm pretty sure that's because of protocol-native needs to be loaded first. My local config in a gist, https://gist.github.com/eadwu/321fb3b45e0790424ba88488f7407b85.

@jansol
Copy link
Contributor Author

jansol commented Jan 24, 2021

Ah, that's what you meant by that. Let's see how adapting that gist of yours works out.

@ashkitten
Copy link
Contributor

any progress on this?

@jansol
Copy link
Contributor Author

jansol commented Jan 29, 2021

Been busy with work and other stuff, planning to get back to this PR in the evening.

@collares
Copy link
Member

collares commented Jan 29, 2021

This is more of a suggestion for future PRs, but I found #111076 interesting. For Mattermost (completely unrelated to pipewire), the corresponding NixOS module parses the default JSON config file provided by the package, instead of duplicating most of the data in it. A similar idea could be used in pipewire, even though SPA JSON is not quite JSON. A possible downside of doing this is explained in the linked issue.

@jtojnar
Copy link
Contributor

jtojnar commented Jan 29, 2021

Using IFD in the module system will not sit right with Hydra, which makes that method a no-go for module that is enabled by default in desktop tests.

@collares
Copy link
Member

collares commented Jan 29, 2021

@jtojnar Would it still be a problem if the default config files were manually copied to nixos/modules/services/desktops (and then parsed) instead of fetched from the Nix store? It would still make it somewhat easier to sync changes in the default config files.

@jtojnar
Copy link
Contributor

jtojnar commented Jan 29, 2021

That should work. We do something similar in fwupd (copy the data to passthu and then check consistency in passthru.tests):

passthru = {
filesInstalledToEtc = [
"fwupd/ata.conf"
"fwupd/daemon.conf"
"fwupd/redfish.conf"
"fwupd/remotes.d/lvfs-testing.conf"
"fwupd/remotes.d/lvfs.conf"
"fwupd/remotes.d/vendor.conf"
"fwupd/remotes.d/vendor-directory.conf"
"fwupd/thunderbolt.conf"
"fwupd/upower.conf"
"fwupd/uefi.conf"
"pki/fwupd/GPG-KEY-Hughski-Limited"
"pki/fwupd/GPG-KEY-Linux-Foundation-Firmware"
"pki/fwupd/GPG-KEY-Linux-Vendor-Firmware-Service"
"pki/fwupd/LVFS-CA.pem"
"pki/fwupd-metadata/GPG-KEY-Linux-Foundation-Metadata"
"pki/fwupd-metadata/GPG-KEY-Linux-Vendor-Firmware-Service"
"pki/fwupd-metadata/LVFS-CA.pem"
] ++ lib.optionals haveDell [
"fwupd/remotes.d/dell-esrt.conf"
];
# DisabledPlugins key in fwupd/daemon.conf
defaultDisabledPlugins = [
"test"
"invalid"
];
tests = let
listToPy = list: "[${lib.concatMapStringsSep ", " (f: "'${f}'") list}]";
in {
installedTests = nixosTests.installed-tests.fwupd;
passthruMatches = runPythonCommand "fwupd-test-passthru-matches" ''
import itertools
import configparser
import os
import pathlib
etc = '${self}/etc'
package_etc = set(itertools.chain.from_iterable([[os.path.relpath(os.path.join(prefix, file), etc) for file in files] for (prefix, dirs, files) in os.walk(etc)]))
passthru_etc = set(${listToPy passthru.filesInstalledToEtc})
assert len(package_etc - passthru_etc) == 0, f'fwupd package contains the following paths in /etc that are not listed in passthru.filesInstalledToEtc: {package_etc - passthru_etc}'
assert len(passthru_etc - package_etc) == 0, f'fwupd package lists the following paths in passthru.filesInstalledToEtc that are not contained in /etc: {passthru_etc - package_etc}'
config = configparser.RawConfigParser()
config.read('${self}/etc/fwupd/daemon.conf')
package_disabled_plugins = config.get('fwupd', 'DisabledPlugins').rstrip(';').split(';')
passthru_disabled_plugins = ${listToPy passthru.defaultDisabledPlugins}
assert package_disabled_plugins == passthru_disabled_plugins, f'Default disabled plug-ins in the package {package_disabled_plugins} do not match those listed in passthru.defaultDisabledPlugins {passthru_disabled_plugins}'
pathlib.Path(os.getenv('out')).touch()
'';
};
};

@jansol
Copy link
Contributor Author

jansol commented Jan 29, 2021

One problem though: the default config is generated with absolute paths to the pipewire and pipewire-media-session binaries at build time...

@jansol
Copy link
Contributor Author

jansol commented Jan 30, 2021

Yay, it's making noises again. Even with over bluetooth (which is a first for me with pipewire)! Someone who actually knows what they are doing should really look it over though, there is now way this is passing tests as is. Also I didn't really get how the passthru stuff is supposed to work.

description = ''
Path to the pipewire session manager executable.
'';
};

sessionManagerArguments = mkOption {
Copy link
Contributor

Choose a reason for hiding this comment

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

where did sessionManagerArguments go? is there a new way to pass arguments to the session manager invocation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was thinking of adding an extraEtcFiles instead since that's the way to configure pipewire-media-session now. But for other session managers it makes sense to keep this around I guess.

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe settings as per NixOS/rfcs#42?

Copy link
Contributor Author

@jansol jansol Jan 31, 2021

Choose a reason for hiding this comment

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

The problem is that depending on the session manager there can be an arbitrary number of config files and their names (nor syntax) aren't known ahead of time. The current solution allows specifying arbitrary files and if the toSPAJSON function is made public (just looking for the right place for it) it would allow specifying settings for pipewire-media-session mostly in this way, just like is done with pipewire.conf (except for having to manually call the fn). But a fancy config generation setup can be done separately too.

@Mic92
Copy link
Member

Mic92 commented Feb 12, 2021

Don't know yet why but nix-build nixos/tests/installed-tests/default.nix -A pipewire fails with infinite recursion. This is also what ofborg complains about. Otherwise the PR now looks good to me.

@eadwu
Copy link
Member

eadwu commented Feb 12, 2021

Next release will have another wave of configuration files if master stays the same. Format will be the same, but there will be a lot more files.

@Mic92
Copy link
Member

Mic92 commented Feb 12, 2021

Next release will have another wave of configuration files if master stays the same. Format will be the same, but there will be a lot more files.

Mhm. Is there a better way to provide those without having to provide all their content in our module? This becomes a maintenance nightmare otherwise. Is the parser flexible enough to just merge trees? So if there is a default configuration that gets redefined by a later, it would just take the later value? Than we could concatenate default + overrides.

@Mic92
Copy link
Member

Mic92 commented Feb 12, 2021

cc @wtay @pv, we want to make pipewire configurable in NixOS through NixOS options. Basically we convert our own nix data structures to pipewire configuration format (see https://github.com/NixOS/nixpkgs/pull/110615/files#diff-6c167307e84d42c088d640f1859ad87e6c8cb15c1ce2353361eac78b5351027eR58). Do you see a way within the format that would allow us to use upstream defaults while still allowing all configuration items to be imported without importing all upstream defaults in our module?

@collares
Copy link
Member

As I understand it, a valid JSON file should work as a configuration file, but the SPA JSON parser accepts more than just well-formed JSON on purpose (to make the configuration file less cluttered?). So outputting a config file should be doable with standard tools, but we would need to port https://gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/spa/include/spa/utils/json.h to Nix (or have an update script that preprocesses stuff) be able to parse the sample config files.

@Mic92
Copy link
Member

Mic92 commented Feb 13, 2021

As I understand it, a valid JSON file should work as a configuration file, but the SPA JSON parser accepts more than just well-formed JSON on purpose (to make the configuration file less cluttered?). So outputting a config file should be doable with standard tools, but we would need to port gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/spa/include/spa/utils/json.h to Nix (or have an update script that preprocesses stuff) be able to parse the sample config files.

Yes. Ideally something that does it at runtime.

@Mic92
Copy link
Member

Mic92 commented Feb 13, 2021

As I understand it, a valid JSON file should work as a configuration file, but the SPA JSON parser accepts more than just well-formed JSON on purpose (to make the configuration file less cluttered?). So outputting a config file should be doable with standard tools, but we would need to port gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/spa/include/spa/utils/json.h to Nix (or have an update script that preprocesses stuff) be able to parse the sample config files.

There you go: https://github.com/nix-community/pipewire-to-json

@wtay
Copy link

wtay commented Feb 13, 2021

As I understand it, a valid JSON file should work as a configuration file, but the SPA JSON parser accepts more than just well-formed JSON on purpose (to make the configuration file less cluttered?). So outputting a config file should be doable with standard tools, but we would need to port gitlab.freedesktop.org/pipewire/pipewire/-/blob/master/spa/include/spa/utils/json.h to Nix (or have an update script that preprocesses stuff) be able to parse the sample config files.

There you go: https://github.com/nix-community/pipewire-to-json

There is now also a canonical converter in PipeWire: https://gitlab.freedesktop.org/pipewire/pipewire/-/commit/3c9996aa781c3cf3623547dbddad4772196ae391

@betaboon betaboon mentioned this pull request Feb 14, 2021
10 tasks
@collares
Copy link
Member

Would it be worth getting this merged as-is and waiting until 0.3.22 to clean up the configuration file handling (so the new spa-json-dump utility created by wtay can be used)?

@Mic92
Copy link
Member

Mic92 commented Feb 14, 2021

Would it be worth getting this merged as-is and waiting until 0.3.22 to clean up the configuration file handling (so the new spa-json-dump utility created by wtay can be used)?

I am fine either way, before we can merge this the evaluation error needs to be fixed so. Do you think it would change the module interface a lot?

moveToOutput "bin/pipewire-media-session" "$mediaSession"
'';

passthru = {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
passthru = {
passthru.tests = {

fixes the installed-tests evaluation error for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for spotting this! Must have slipped through while I tested stuff that involved changing this section.

@cawilliamson
Copy link
Member

Personally I'd like to see this merged as soon as possible - for me it's meaning I can't fully switch to pipewire because it breaks some apps which ignore the default output defined.

It looks like the fix for this is in this newer version. :)

@Mic92 Mic92 merged commit 9783fa9 into NixOS:master Feb 17, 2021
@Izorkin
Copy link
Contributor

Izorkin commented Feb 18, 2021

@jansol @Mic92 after this update on my home server automatic activated this service.

@Kazimazi
Copy link
Contributor

my pipewire refuses to start, /etc/pipewire/pipewire.conf is missing
some journalctl info:

Feb 18 23:13:01 amdboi pipewire[1590]: failed to parse config: /nix/store/43884baaflihk674g4zddg1zhyxlam6a-pipewire.conf:2: Command "modules" does not exist
Feb 18 23:13:01 amdboi systemd[1582]: pipewire.service: Main process exited, code=exited, status=255/EXCEPTION
Feb 18 23:13:01 amdboi systemd[1582]: pipewire.service: Failed with result 'exit-code'.
Feb 18 23:13:01 amdboi systemd[1582]: pipewire.service: Scheduled restart job, restart counter is at 1.
Feb 18 23:13:01 amdboi systemd[1582]: Stopped Multimedia Service.
Feb 18 23:13:01 amdboi systemd[1582]: Started Multimedia Service.
Feb 18 23:13:01 amdboi pipewire[1807]: failed to parse config: /nix/store/43884baaflihk674g4zddg1zhyxlam6a-pipewire.conf:2: Command "modules" does not exist
...
Feb 18 23:13:02 amdboi systemd[1582]: pipewire.service: Scheduled restart job, restart counter is at 5.
Feb 18 23:13:02 amdboi systemd[1582]: Stopped Multimedia Service.
Feb 18 23:13:02 amdboi systemd[1582]: pipewire.service: Start request repeated too quickly.
Feb 18 23:13:02 amdboi systemd[1582]: pipewire.service: Failed with result 'exit-code'.
Feb 18 23:13:02 amdboi systemd[1582]: Failed to start Multimedia Service.
Feb 18 23:13:02 amdboi systemd[1582]: pipewire.socket: Failed with result 'service-start-limit-hit'.
Feb 18 23:13:06 amdboi pipewire[1888]: daemon 0x7ffcffca98f0: error loading config '/etc/pipewire/pipewire.conf': No such file or directory
Feb 18 23:13:06 amdboi pipewire[1888]: failed to load config: No such file or directory

@collares
Copy link
Member

collares commented Feb 18, 2021

/etc/pipewire/pipewire.conf is not supposed to exist, since the PIPEWIRE_CONFIG_FILE env variable (defined for the systemd user service) points somewhere else. Do you see something weird in /nix/store/43884baaflihk674g4zddg1zhyxlam6a-pipewire.conf? How are you setting up pipewire in your Nix configuration?

@Kazimazi
Copy link
Contributor

Kazimazi commented Feb 18, 2021

I'm not sure what it supposed to look like, that's what I've got:

exec = {/nix/store/kq5ywwjjg7xyjplprirx5m5ijf1vav58-pipewire-0.3.21-mediaSession/bin/pipewire-media-session = {args = ""}}
modules = {libpipewire-module-protocol-native = null libpipewire-module-access = {args = {access = {allowed = [/nix/store/kq5ywwjjg7xyjplprirx5m5ijf1vav58-pipewire-0.3.21-mediaSession/bin/pipewire-media-session] force = flatpak rejected = [] restricted = []}}} libpipewire-module-adapter = null libpipewire-module-client-device = null libpipewire-module-client-node = null libpipewire-module-link-factory = null libpipewire-module-metadata = null libpipewire-module-portal = null libpipewire-module-profiler = null libpipewire-module-rtkit = {args = {} flags = ifexists|nofail} libpipewire-module-session-manager = null libpipewire-module-spa-device-factory = null libpipewire-module-spa-node-factory = null}
objects = {}
properties = {link.max-buffers = 16}
spa-libs = {api.alsa.* = alsa/libspa-alsa api.bluez5.* = bluez5/libspa-bluez5 api.jack.* = jack/libspa-jack api.libcamera.* = libcamera/libspa-libcamera api.v4l2.* = v4l2/libspa-v4l2 api.vulkan.* = vulkan/libspa-vulkan audio.convert* = audioconvert/libspa-audioconvert support.* = support/libspa-support}

edit: using triplebackquotes for pipewire.conf so linebreaks are not lost

and that's how I configured it:

{ config, pkgs, ... }: {
  security.rtkit.enable = true;
  nixpkgs.config.pulseaudio = true;
  hardware.pulseaudio.enable = pkgs.lib.mkForce false;
  services.pipewire = {
    enable = true;
    package = pkgs.master.pipewire;
    alsa.enable = true;
    pulse.enable = true;
    jack.enable = true;
  };
}

@Technical27
Copy link
Contributor

@Kazimazi pipewire's config got a massive change, you are using the module from stable (which expects 0.3.18), but pipewire 0.3.20 can't read the old config format.

@collares
Copy link
Member

collares commented Feb 18, 2021

Just to be sure: Does your config file really not contain a line break before "module"? If that was a GitHub formatting error, please use triple backquotes :)

Edit: Oh, sorry, I didn't see the other comment. Yeah, it looks like you're using Pipewire 0.3.18 with the 0.3.21 config file, since your config file looks fine for 0.3.21 (except for the lack of line breaks).

@Kazimazi
Copy link
Contributor

It might be something trivial, but I can't wrap my head around it. How do I use the new module?

@collares
Copy link
Member

collares commented Feb 19, 2021

What is "pkgs.master" on your config? I don't have this attribute on my local config (according to nix repl). Could it be pointing to an old package set? I think you're using the new module but "pkgs.master.pipewire" is an old package. Try just removing the package = ... line?

@Kazimazi
Copy link
Contributor

It's an overlay of master branch of nixpkgs, which is updated.

@Kazimazi
Copy link
Contributor

I think I've got my issue resolved... there was a symlink to a non-existent /nix/store/...pipewire3.18 in ~/.config/systemd/user and it was conflicting with the new one. Don't know when or why it got there so I deleted it.

@d4g
Copy link
Contributor

d4g commented Mar 9, 2021

I think I've got my issue resolved... there was a symlink to a non-existent /nix/store/...pipewire3.18 in ~/.config/systemd/user and it was conflicting with the new one. Don't know when or why it got there so I deleted it.

I ran into the same issue with #115492 .
This is pretty weird and an issue that more users may run into when updating. Probably something to consider, that somehow those files seem to have been created on an earlier version.

.config/systemd/user:
./pipewire.socket
./default.target.wants
./default.target.wants/pipewire.service
./pipewire.service
./sockets.target.wants
./sockets.target.wants/pipewire.socket
pipewire.service -> /nix/store/sl82a2fpsyn7ihjp0lp67p7f4k5sp5dh-pipewire-0.3.18/lib/systemd/user/pipewire.service
pipewire.socket -> /nix/store/sl82a2fpsyn7ihjp0lp67p7f4k5sp5dh-pipewire-0.3.18/lib/systemd/user/pipewire.socket

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet