summary refs log tree commit diff
path: root/nixos/modules/services/desktops/pipewire/pipewire-media-session.nix
blob: b41ea349fb8db6cc49c6f52816946bd374a67e59 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# pipewire example session manager.
{ config, lib, pkgs, ... }:

with lib;

let
  cfg = config.services.pipewire.media-session;
  enable32BitAlsaPlugins = cfg.alsa.support32Bit
                           && 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)}")
        attrs
    )
  );

  toSPAJSON = attrs: lib.concatStringsSep "\n" (mkSPAKeyValue attrs);
in {

  meta = {
    maintainers = teams.freedesktop.members;
  };

  ###### interface
  options = {
    services.pipewire.media-session = {
      enable = mkOption {
        type = types.bool;
        default = config.services.pipewire.enable;
        defaultText = "config.services.pipewire.enable";
        description = "Example pipewire session manager";
      };

      package = mkOption {
        type = types.package;
        default = pkgs.pipewire.mediaSession;
        example = literalExample "pkgs.pipewire.mediaSession";
        description = ''
          The pipewire-media-session derivation to use.
        '';
      };

      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 = {};
        };

        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 = {};
        };

        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 = {};
        };

        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 = {};
        };
      };
    };
  };

  ###### implementation
  config = mkIf cfg.enable {
    environment.systemPackages = [ cfg.package ];
    systemd.packages = [ cfg.package ];
    systemd.user.services.pipewire-media-session.wantedBy = [ "pipewire.service" ];

    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 (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 (recursiveUpdate defaults.bluez-monitor cfg.config.bluez-monitor); };

    environment.etc."pipewire/media-session.d/with-jack" = mkIf config.services.pipewire.jack.enable { text = ""; };
  };
}