nixcfg/modules/nixos/hardware/audio/default.nix

201 lines
5.3 KiB
Nix
Raw Normal View History

2024-01-11 11:26:46 +01:00
{ options
, config
, pkgs
, lib
, ...
}:
# FIXME: The transition to wireplumber from media-session has completely
# broken my setup. I'll need to invest some time to figure out how to override Alsa things
# again...
with lib;
with lib.plusultra; let
cfg = config.plusultra.hardware.audio;
lua-format = {
type = with lib.types; let
valueType =
nullOr
(oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
])
// {
description = "Lua value";
};
in
valueType;
generate = name: value:
let
toLuaValue = value:
if value == null
then "null"
else if value == true
then "true"
else if value == false
then "false"
else if builtins.isInt value || builtins.isFloat value
then builtins.toString value
else if builtins.isString value
then toLuaString value
else if builtins.isAttrs value
then toLuaTable value
else if builtins.isList value
then toLuaList value
else builtins.abort "Unsupported value used with formats.lua.generate: ${value}";
toLuaString = value: "\"${builtins.toString value}\"";
toLuaTable = value:
let
pairs =
mapAttrsToList
(name: value: "[${toLuaString name}] = ${toLuaValue value}")
value;
content = concatStringsSep ", " pairs;
in
"{ ${content} }";
toLuaList = value:
let
parts = builtins.map toLuaValue value;
content = concatStringsSep ", " parts;
in
"{ ${content} }";
in
toLuaValue value;
};
pipewire-config = {
"context.objects" = cfg.nodes ++ [ ];
"context.modules" =
[
{
name = "libpipewire-module-rtkit";
args = { };
flags = [ "ifexists" "nofail" ];
}
{ name = "libpipewire-module-protocol-native"; }
{ name = "libpipewire-module-profiler"; }
# {
# name = "libpipewire-module-metadata";
# flags = [ "ifexists" "nofail" ];
# }
{ name = "libpipewire-module-spa-device-factory"; }
{ name = "libpipewire-module-spa-node-factory"; }
# {
# name = "libpipewire-module-client-node";
# flags = [ "ifexists" "nofail" ];
# }
# {
# name = "libpipewire-module-client-device";
# flags = [ "ifexists" "nofail" ];
# }
{
name = "libpipewire-module-portal";
flags = [ "ifexists" "nofail" ];
}
{
name = "libpipewire-module-access";
args = { };
}
{ name = "libpipewire-module-adapter"; }
{ name = "libpipewire-module-link-factory"; }
{ name = "libpipewire-module-session-manager"; }
]
++ cfg.modules;
"context.components" = [
{
name = "libwireplumber-module-lua-scripting";
type = "module";
}
{
name = "config.lua";
type = "config/lua";
}
];
};
alsa-config = {
alsa_monitor = cfg.alsa-monitor;
};
in
{
options.plusultra.hardware.audio = with types; {
enable = mkBoolOpt false "Whether or not to enable audio support.";
alsa-monitor = mkOpt attrs { } "Alsa configuration.";
nodes =
mkOpt (listOf attrs) [ ]
"Audio nodes to pass to Pipewire as `context.objects`.";
modules =
mkOpt (listOf attrs) [ ]
"Audio modules to pass to Pipewire as `context.modules`.";
extra-packages = mkOpt (listOf package) [
pkgs.qjackctl
pkgs.easyeffects
] "Additional packages to install.";
};
config = mkIf cfg.enable {
security.rtkit.enable = true;
services.pipewire = {
enable = true;
alsa.enable = true;
pulse.enable = true;
jack.enable = true;
wireplumber.enable = true;
};
environment.etc = {
# "pipewire/pipewire.conf.d/10-pipewire.conf".source =
# pkgs.writeText "pipewire.conf" (builtins.toJSON pipewire-config);
# "pipewire/pipewire.conf.d/21-alsa.conf".source =
# pkgs.writeText "pipewire.conf" (builtins.toJSON alsa-config);
# "wireplumber/wireplumber.conf".source =
# pkgs.writeText "pipewire.conf" (builtins.toJSON pipewire-config);
# "wireplumber/scripts/config.lua.d/alsa.lua".text = ''
# local input = ${lua-format.generate "sample.lua" cfg.alsa-monitor}
# if input.rules == nil then
# input.rules = {}
# end
# local rules = input.rules
# for _, rule in ipairs(input.rules) do
# table.insert(alsa_monitor.rules, rule)
# end
# '';
};
hardware.pulseaudio.enable = mkForce false;
environment.systemPackages = with pkgs;
[
pulsemixer
pavucontrol
]
++ cfg.extra-packages;
plusultra.user.extraGroups = [ "audio" ];
plusultra.home.extraOptions = {
systemd.user.services.mpris-proxy = {
Unit.Description = "Mpris proxy";
Unit.After = [ "network.target" "sound.target" ];
Service.ExecStart = "${pkgs.bluez}/bin/mpris-proxy";
Install.WantedBy = [ "default.target" ];
};
};
};
}