atagen

headroom

public
Star0
Watch0
b4f9722db37afb8ec0881327edf1a085c821d6a9
1
ssh://brewery@pls.lobotomise.me:33/atagen/headroom.git

Blame: flake.nix

b449da897c0fatagen2026-05-27 15:49 UTC1
{
b449da897c0fatagen2026-05-27 15:49 UTC2
  description = "automatic loudness and per-app volume control (pipewire)";
b449da897c0fatagen2026-05-27 15:49 UTC3
b449da897c0fatagen2026-05-27 15:49 UTC4
  inputs = {
b449da897c0fatagen2026-05-27 15:49 UTC5
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
b449da897c0fatagen2026-05-27 15:49 UTC6
  };
b449da897c0fatagen2026-05-27 15:49 UTC7
b449da897c0fatagen2026-05-27 15:49 UTC8
  outputs =
b449da897c0fatagen2026-05-27 15:49 UTC9
    {
b449da897c0fatagen2026-05-27 15:49 UTC10
      self,
b449da897c0fatagen2026-05-27 15:49 UTC11
      nixpkgs,
b449da897c0fatagen2026-05-27 15:49 UTC12
    }:
b449da897c0fatagen2026-05-27 15:49 UTC13
    let
b449da897c0fatagen2026-05-27 15:49 UTC14
      systems = [
b449da897c0fatagen2026-05-27 15:49 UTC15
        "x86_64-linux"
b449da897c0fatagen2026-05-27 15:49 UTC16
        "aarch64-linux"
b449da897c0fatagen2026-05-27 15:49 UTC17
      ];
b449da897c0fatagen2026-05-27 15:49 UTC18
      forAllSystems = nixpkgs.lib.genAttrs systems;
872b0bdcf4abatagen2026-10-17 11:08 UTC19
      cleanSrc =
872b0bdcf4abatagen2026-10-17 11:08 UTC20
        root:
872b0bdcf4abatagen2026-10-17 11:08 UTC21
        nixpkgs.lib.cleanSourceWith {
872b0bdcf4abatagen2026-10-17 11:08 UTC22
          src = root;
872b0bdcf4abatagen2026-10-17 11:08 UTC23
          filter =
872b0bdcf4abatagen2026-10-17 11:08 UTC24
            path: type:
872b0bdcf4abatagen2026-10-17 11:08 UTC25
            nixpkgs.lib.cleanSourceFilter path type
872b0bdcf4abatagen2026-10-17 11:08 UTC26
            && !(type == "directory" && builtins.elem (baseNameOf path) [ "target" ]);
872b0bdcf4abatagen2026-10-17 11:08 UTC27
        };
b449da897c0fatagen2026-05-27 15:49 UTC28
b449da897c0fatagen2026-05-27 15:49 UTC29
      pkgsFor =
b449da897c0fatagen2026-05-27 15:49 UTC30
        system:
b449da897c0fatagen2026-05-27 15:49 UTC31
        import nixpkgs {
b449da897c0fatagen2026-05-27 15:49 UTC32
          inherit system;
b449da897c0fatagen2026-05-27 15:49 UTC33
        };
b449da897c0fatagen2026-05-27 15:49 UTC34
b449da897c0fatagen2026-05-27 15:49 UTC35
      perSystem =
b449da897c0fatagen2026-05-27 15:49 UTC36
        system:
b449da897c0fatagen2026-05-27 15:49 UTC37
        let
b449da897c0fatagen2026-05-27 15:49 UTC38
          pkgs = pkgsFor system;
b449da897c0fatagen2026-05-27 15:49 UTC39
b449da897c0fatagen2026-05-27 15:49 UTC40
          # native libs the audio crates link against
b449da897c0fatagen2026-05-27 15:49 UTC41
          nativeAudioBuildInputs = with pkgs; [
b449da897c0fatagen2026-05-27 15:49 UTC42
            pipewire
b449da897c0fatagen2026-05-27 15:49 UTC43
            pipewire.dev
b449da897c0fatagen2026-05-27 15:49 UTC44
          ];
b449da897c0fatagen2026-05-27 15:49 UTC45
b449da897c0fatagen2026-05-27 15:49 UTC46
          nativeBuildTools = with pkgs; [
b449da897c0fatagen2026-05-27 15:49 UTC47
            pkg-config
b449da897c0fatagen2026-05-27 15:49 UTC48
            clang
b449da897c0fatagen2026-05-27 15:49 UTC49
          ];
b449da897c0fatagen2026-05-27 15:49 UTC50
b449da897c0fatagen2026-05-27 15:49 UTC51
          # system libs iced (wgpu/winit/cosmic-text) compiles + dlopens at runtime.
b449da897c0fatagen2026-05-27 15:49 UTC52
          # wayland-only (x11 feature off); re-add libx11/libxcursor/libxi/libxrandr/libxcb if x11 re-enabled
b449da897c0fatagen2026-05-27 15:49 UTC53
          guiLibs = with pkgs; [
b449da897c0fatagen2026-05-27 15:49 UTC54
            vulkan-loader
b449da897c0fatagen2026-05-27 15:49 UTC55
            libxkbcommon
b449da897c0fatagen2026-05-27 15:49 UTC56
            wayland
b449da897c0fatagen2026-05-27 15:49 UTC57
            libGL
b449da897c0fatagen2026-05-27 15:49 UTC58
            fontconfig
b449da897c0fatagen2026-05-27 15:49 UTC59
          ];
b449da897c0fatagen2026-05-27 15:49 UTC60
b449da897c0fatagen2026-05-27 15:49 UTC61
          commonEnv = {
b449da897c0fatagen2026-05-27 15:49 UTC62
            LIBCLANG_PATH = "${pkgs.libclang.lib}/lib";
b449da897c0fatagen2026-05-27 15:49 UTC63
            PKG_CONFIG_PATH = "${pkgs.pipewire.dev}/lib/pkgconfig";
b449da897c0fatagen2026-05-27 15:49 UTC64
          };
b449da897c0fatagen2026-05-27 15:49 UTC65
        in
b449da897c0fatagen2026-05-27 15:49 UTC66
        {
b449da897c0fatagen2026-05-27 15:49 UTC67
          # nix develop — dev environment
b449da897c0fatagen2026-05-27 15:49 UTC68
          devShell = pkgs.mkShell (
b449da897c0fatagen2026-05-27 15:49 UTC69
            {
b449da897c0fatagen2026-05-27 15:49 UTC70
              name = "headroom-dev";
b449da897c0fatagen2026-05-27 15:49 UTC71
b449da897c0fatagen2026-05-27 15:49 UTC72
              nativeBuildInputs = nativeBuildTools ++ [
b449da897c0fatagen2026-05-27 15:49 UTC73
                pkgs.cargo
b449da897c0fatagen2026-05-27 15:49 UTC74
                pkgs.clippy
b449da897c0fatagen2026-05-27 15:49 UTC75
                pkgs.rust-analyzer
b449da897c0fatagen2026-05-27 15:49 UTC76
                pkgs.rustc
b449da897c0fatagen2026-05-27 15:49 UTC77
                pkgs.rustfmt
b449da897c0fatagen2026-05-27 15:49 UTC78
              ];
b449da897c0fatagen2026-05-27 15:49 UTC79
b449da897c0fatagen2026-05-27 15:49 UTC80
              buildInputs =
b449da897c0fatagen2026-05-27 15:49 UTC81
                nativeAudioBuildInputs
b449da897c0fatagen2026-05-27 15:49 UTC82
                ++ guiLibs
b449da897c0fatagen2026-05-27 15:49 UTC83
                ++ (with pkgs; [
b449da897c0fatagen2026-05-27 15:49 UTC84
                  socat # poke the ipc socket
b449da897c0fatagen2026-05-27 15:49 UTC85
                  jq # pretty-print json
b449da897c0fatagen2026-05-27 15:49 UTC86
                  pipewire # pw-cli, pw-cat, etc.
b449da897c0fatagen2026-05-27 15:49 UTC87
                  wireplumber
b449da897c0fatagen2026-05-27 15:49 UTC88
                ]);
b449da897c0fatagen2026-05-27 15:49 UTC89
b449da897c0fatagen2026-05-27 15:49 UTC90
              shellHook = ''
b449da897c0fatagen2026-05-27 15:49 UTC91
                echo "headroom dev shell — rustc $(rustc --version | cut -d' ' -f2)"
b449da897c0fatagen2026-05-27 15:49 UTC92
                echo "  cargo build / cargo test for iteration."
b449da897c0fatagen2026-05-27 15:49 UTC93
                echo "  nix build  .#headroom  for the packaged binary."
b449da897c0fatagen2026-05-27 15:49 UTC94
                echo "  cargo run -p headroom-gui  for the GUI (needs a display)."
b449da897c0fatagen2026-05-27 15:49 UTC95
                export RUST_BACKTRACE=1
b449da897c0fatagen2026-05-27 15:49 UTC96
                export RUST_LOG=headroom=debug,info
b449da897c0fatagen2026-05-27 15:49 UTC97
                # iced/wgpu dlopen vulkan/wayland/xkbcommon at runtime
b449da897c0fatagen2026-05-27 15:49 UTC98
                export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath guiLibs}''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
b449da897c0fatagen2026-05-27 15:49 UTC99
              '';
b449da897c0fatagen2026-05-27 15:49 UTC100
            }
b449da897c0fatagen2026-05-27 15:49 UTC101
            // commonEnv
b449da897c0fatagen2026-05-27 15:49 UTC102
          );
b449da897c0fatagen2026-05-27 15:49 UTC103
b449da897c0fatagen2026-05-27 15:49 UTC104
          # nix build — packaged daemon + cli
b449da897c0fatagen2026-05-27 15:49 UTC105
          headroom = pkgs.rustPlatform.buildRustPackage (
b449da897c0fatagen2026-05-27 15:49 UTC106
            {
b449da897c0fatagen2026-05-27 15:49 UTC107
              pname = "headroom";
b449da897c0fatagen2026-05-27 15:49 UTC108
              # workspace version (per-crate manifests use version.workspace = true)
872b0bdcf4abatagen2026-10-17 11:08 UTC109
              version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.version;
872b0bdcf4abatagen2026-10-17 11:08 UTC110
              # + "-"
872b0bdcf4abatagen2026-10-17 11:08 UTC111
              # + (toString self.rev);
b449da897c0fatagen2026-05-27 15:49 UTC112
872b0bdcf4abatagen2026-10-17 11:08 UTC113
              src = cleanSrc ./.;
b449da897c0fatagen2026-05-27 15:49 UTC114
b449da897c0fatagen2026-05-27 15:49 UTC115
              cargoLock = {
b449da897c0fatagen2026-05-27 15:49 UTC116
                lockFile = ./Cargo.lock;
b449da897c0fatagen2026-05-27 15:49 UTC117
                # allowBuiltinFetchGit = true;
b449da897c0fatagen2026-05-27 15:49 UTC118
              };
b449da897c0fatagen2026-05-27 15:49 UTC119
b449da897c0fatagen2026-05-27 15:49 UTC120
              nativeBuildInputs = nativeBuildTools;
b449da897c0fatagen2026-05-27 15:49 UTC121
              buildInputs = nativeAudioBuildInputs;
b449da897c0fatagen2026-05-27 15:49 UTC122
b449da897c0fatagen2026-05-27 15:49 UTC123
              # one binary: `headroom` (cli + daemon)
b449da897c0fatagen2026-05-27 15:49 UTC124
              cargoBuildFlags = [
b449da897c0fatagen2026-05-27 15:49 UTC125
                "-p"
b449da897c0fatagen2026-05-27 15:49 UTC126
                "headroom-cli"
b449da897c0fatagen2026-05-27 15:49 UTC127
              ];
b449da897c0fatagen2026-05-27 15:49 UTC128
              doCheck = true;
b449da897c0fatagen2026-05-27 15:49 UTC129
              # exclude headroom-gui from the test sweep — pulls iced's gpu stack, not part of the daemon
b449da897c0fatagen2026-05-27 15:49 UTC130
              cargoTestFlags = [
b449da897c0fatagen2026-05-27 15:49 UTC131
                "--workspace"
b449da897c0fatagen2026-05-27 15:49 UTC132
                "--exclude"
b449da897c0fatagen2026-05-27 15:49 UTC133
                "headroom-gui"
b449da897c0fatagen2026-05-27 15:49 UTC134
              ];
b449da897c0fatagen2026-05-27 15:49 UTC135
b449da897c0fatagen2026-05-27 15:49 UTC136
              # systemd user unit (@bindir@ templated to this derivation's bin, not PATH)
b449da897c0fatagen2026-05-27 15:49 UTC137
              # + canonical profiles under share/headroom/profiles (daemon finds via $XDG_DATA_DIRS)
b449da897c0fatagen2026-05-27 15:49 UTC138
              postInstall = ''
b449da897c0fatagen2026-05-27 15:49 UTC139
                install -Dm644 contrib/systemd/headroom.service \
b449da897c0fatagen2026-05-27 15:49 UTC140
                  "$out/lib/systemd/user/headroom.service"
b449da897c0fatagen2026-05-27 15:49 UTC141
                substituteInPlace "$out/lib/systemd/user/headroom.service" \
b449da897c0fatagen2026-05-27 15:49 UTC142
                  --replace-fail '@bindir@' "$out/bin"
b449da897c0fatagen2026-05-27 15:49 UTC143
b449da897c0fatagen2026-05-27 15:49 UTC144
                mkdir -p "$out/share/headroom/profiles"
b449da897c0fatagen2026-05-27 15:49 UTC145
                cp -r profiles/. "$out/share/headroom/profiles/"
b449da897c0fatagen2026-05-27 15:49 UTC146
              '';
b449da897c0fatagen2026-05-27 15:49 UTC147
b449da897c0fatagen2026-05-27 15:49 UTC148
              meta = with pkgs.lib; {
b449da897c0fatagen2026-05-27 15:49 UTC149
                description = "automatic loudness and per-app volume control (pipewire)";
b449da897c0fatagen2026-05-27 15:49 UTC150
                license = licenses.gpl3Plus;
b449da897c0fatagen2026-05-27 15:49 UTC151
                platforms = platforms.linux;
b449da897c0fatagen2026-05-27 15:49 UTC152
                mainProgram = "headroom";
b449da897c0fatagen2026-05-27 15:49 UTC153
              };
b449da897c0fatagen2026-05-27 15:49 UTC154
            }
b449da897c0fatagen2026-05-27 15:49 UTC155
            // commonEnv
b449da897c0fatagen2026-05-27 15:49 UTC156
          );
b449da897c0fatagen2026-05-27 15:49 UTC157
b449da897c0fatagen2026-05-27 15:49 UTC158
          # `nix build .#headroom-gui` — optional iced GUI monitor.
b449da897c0fatagen2026-05-27 15:49 UTC159
          # separate package so the default build stays graphics-free. iced/wgpu
b449da897c0fatagen2026-05-27 15:49 UTC160
          # dlopen vulkan/libGL/wayland/xkbcommon at runtime → wrap with LD_LIBRARY_PATH.
b449da897c0fatagen2026-05-27 15:49 UTC161
          # also ships the .desktop entry.
b449da897c0fatagen2026-05-27 15:49 UTC162
          headroom-gui = pkgs.rustPlatform.buildRustPackage (
b449da897c0fatagen2026-05-27 15:49 UTC163
            {
b449da897c0fatagen2026-05-27 15:49 UTC164
              pname = "headroom-gui";
872b0bdcf4abatagen2026-10-17 11:08 UTC165
              version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).workspace.package.version;
872b0bdcf4abatagen2026-10-17 11:08 UTC166
              # + "-"
872b0bdcf4abatagen2026-10-17 11:08 UTC167
              # + (toString self.lastModifiedDate);
b449da897c0fatagen2026-05-27 15:49 UTC168
872b0bdcf4abatagen2026-10-17 11:08 UTC169
              src = cleanSrc ./.;
b449da897c0fatagen2026-05-27 15:49 UTC170
b449da897c0fatagen2026-05-27 15:49 UTC171
              cargoLock = {
b449da897c0fatagen2026-05-27 15:49 UTC172
                lockFile = ./Cargo.lock;
b449da897c0fatagen2026-05-27 15:49 UTC173
              };
b449da897c0fatagen2026-05-27 15:49 UTC174
b449da897c0fatagen2026-05-27 15:49 UTC175
              # makeWrapper for the LD_LIBRARY_PATH wrap. gui doesn't link pipewire
b449da897c0fatagen2026-05-27 15:49 UTC176
              # (talks to the daemon over the socket via headroom-client) → no pipewire/clang
b449da897c0fatagen2026-05-27 15:49 UTC177
              nativeBuildInputs = [
b449da897c0fatagen2026-05-27 15:49 UTC178
                pkgs.pkg-config
b449da897c0fatagen2026-05-27 15:49 UTC179
                pkgs.makeWrapper
b449da897c0fatagen2026-05-27 15:49 UTC180
              ];
b449da897c0fatagen2026-05-27 15:49 UTC181
              buildInputs = guiLibs;
b449da897c0fatagen2026-05-27 15:49 UTC182
b449da897c0fatagen2026-05-27 15:49 UTC183
              cargoBuildFlags = [
b449da897c0fatagen2026-05-27 15:49 UTC184
                "-p"
b449da897c0fatagen2026-05-27 15:49 UTC185
                "headroom-gui"
b449da897c0fatagen2026-05-27 15:49 UTC186
              ];
b449da897c0fatagen2026-05-27 15:49 UTC187
              # gui tests drive iced view/update; no display in the sandbox.
b449da897c0fatagen2026-05-27 15:49 UTC188
              # run them via `cargo test -p headroom-gui` in the dev shell instead
b449da897c0fatagen2026-05-27 15:49 UTC189
              doCheck = false;
b449da897c0fatagen2026-05-27 15:49 UTC190
b449da897c0fatagen2026-05-27 15:49 UTC191
              postInstall = ''
b449da897c0fatagen2026-05-27 15:49 UTC192
                install -Dm644 contrib/desktop/headroom-gui.desktop \
b449da897c0fatagen2026-05-27 15:49 UTC193
                  "$out/share/applications/headroom-gui.desktop"
b449da897c0fatagen2026-05-27 15:49 UTC194
                substituteInPlace "$out/share/applications/headroom-gui.desktop" \
b449da897c0fatagen2026-05-27 15:49 UTC195
                  --replace-fail '@bindir@' "$out/bin"
b449da897c0fatagen2026-05-27 15:49 UTC196
              '';
b449da897c0fatagen2026-05-27 15:49 UTC197
b449da897c0fatagen2026-05-27 15:49 UTC198
              postFixup = ''
b449da897c0fatagen2026-05-27 15:49 UTC199
                wrapProgram "$out/bin/headroom-gui" \
b449da897c0fatagen2026-05-27 15:49 UTC200
                  --prefix LD_LIBRARY_PATH : "${pkgs.lib.makeLibraryPath guiLibs}"
b449da897c0fatagen2026-05-27 15:49 UTC201
              '';
b449da897c0fatagen2026-05-27 15:49 UTC202
b449da897c0fatagen2026-05-27 15:49 UTC203
              meta = with pkgs.lib; {
b449da897c0fatagen2026-05-27 15:49 UTC204
                description = "automatic loudness and per-app volume control (pipewire)";
b449da897c0fatagen2026-05-27 15:49 UTC205
                license = licenses.eupl12;
b449da897c0fatagen2026-05-27 15:49 UTC206
                platforms = platforms.linux;
b449da897c0fatagen2026-05-27 15:49 UTC207
                mainProgram = "headroom-gui";
b449da897c0fatagen2026-05-27 15:49 UTC208
              };
b449da897c0fatagen2026-05-27 15:49 UTC209
            }
b449da897c0fatagen2026-05-27 15:49 UTC210
            // commonEnv
b449da897c0fatagen2026-05-27 15:49 UTC211
          );
b449da897c0fatagen2026-05-27 15:49 UTC212
        };
b449da897c0fatagen2026-05-27 15:49 UTC213
    in
b449da897c0fatagen2026-05-27 15:49 UTC214
    {
b449da897c0fatagen2026-05-27 15:49 UTC215
      devShells = forAllSystems (system: {
b449da897c0fatagen2026-05-27 15:49 UTC216
        default = (perSystem system).devShell;
b449da897c0fatagen2026-05-27 15:49 UTC217
      });
b449da897c0fatagen2026-05-27 15:49 UTC218
b449da897c0fatagen2026-05-27 15:49 UTC219
      packages = forAllSystems (
b449da897c0fatagen2026-05-27 15:49 UTC220
        system:
b449da897c0fatagen2026-05-27 15:49 UTC221
        let
b449da897c0fatagen2026-05-27 15:49 UTC222
          ps = perSystem system;
b449da897c0fatagen2026-05-27 15:49 UTC223
        in
b449da897c0fatagen2026-05-27 15:49 UTC224
        rec {
b449da897c0fatagen2026-05-27 15:49 UTC225
          default = headroom;
b449da897c0fatagen2026-05-27 15:49 UTC226
          headroom = ps.headroom;
b449da897c0fatagen2026-05-27 15:49 UTC227
          headroom-gui = ps.headroom-gui;
b449da897c0fatagen2026-05-27 15:49 UTC228
        }
b449da897c0fatagen2026-05-27 15:49 UTC229
      );
b449da897c0fatagen2026-05-27 15:49 UTC230
b449da897c0fatagen2026-05-27 15:49 UTC231
      formatter = forAllSystems (system: (pkgsFor system).nixpkgs-fmt);
b449da897c0fatagen2026-05-27 15:49 UTC232
b449da897c0fatagen2026-05-27 15:49 UTC233
      # System-independent outputs — modules.
b449da897c0fatagen2026-05-27 15:49 UTC234
      nixosModules.default = import ./nix/nixos-module.nix self;
b449da897c0fatagen2026-05-27 15:49 UTC235
    };
b449da897c0fatagen2026-05-27 15:49 UTC236
}