201 lines
5.3 KiB
Nix
201 lines
5.3 KiB
Nix
|
{ 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" ];
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
}
|