diff --git a/nixos/modules/services/audio/alsa.nix b/nixos/modules/services/audio/alsa.nix index c1ee7023aa1f..7bd0200e3c02 100644 --- a/nixos/modules/services/audio/alsa.nix +++ b/nixos/modules/services/audio/alsa.nix @@ -44,9 +44,15 @@ let in lib.forEach options (i: "options ${i.driver} index=${toList i.ids} id=${toList i.names}"); - defaultDeviceVars = { + pluginsPath = pkgs.symlinkJoin { + name = "alsa-with-plugins"; + paths = cfg.plugins; + }; + + alsaVariables = { "ALSA_AUDIO_OUT" = cfg.defaultDevice.playback; "ALSA_AUDIO_IN" = cfg.defaultDevice.capture; + "ALSA_PLUGIN_DIR" = lib.mkIf (cfg.plugins != [ ]) "${pluginsPath}/lib/alsa-lib"; }; in @@ -106,6 +112,8 @@ in enableOSSEmulation = lib.mkEnableOption "the OSS emulation"; + enableBluetooth = lib.mkEnableOption "Bluetooth audio support via BlueALSA"; + enableRecorder = lib.mkOption { type = lib.types.bool; default = false; @@ -125,6 +133,15 @@ in ''; }; + plugins = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = [ ]; + example = lib.literalExpression "[ pkgs.bluez-alsa ]"; + description = '' + List of ALSA plugins to be added to the search path. + ''; + }; + defaultDevice.playback = lib.mkOption { type = lib.types.str; default = ""; @@ -392,8 +409,8 @@ in }; # Set default PCM devices - environment.sessionVariables = defaultDeviceVars; - systemd.globalEnvironment = defaultDeviceVars; + environment.sessionVariables = alsaVariables; + systemd.globalEnvironment = alsaVariables; environment.etc."asound.conf".text = cfg.config; @@ -412,6 +429,33 @@ in environment.systemPackages = [ pkgs.alsa-utils ]; }) + (lib.mkIf (cfg.enable && cfg.enableBluetooth) { + + users.users.bluealsa = { + description = "BlueALSA daemons user"; + isSystemUser = true; + group = "audio"; + }; + + # Link ALSA configuration + environment.etc."alsa/conf.d/20-bluealsa.conf".source = + "${pkgs.bluez-alsa}/etc/alsa/conf.d/20-bluealsa.conf"; + + # Install plugin + hardware.alsa.plugins = [ pkgs.bluez-alsa ]; + + # Install CLI tools and systemd units + environment.systemPackages = [ pkgs.bluez-alsa ]; + systemd.packages = [ pkgs.bluez-alsa ]; + + # See Nixpkgs issue #81138 + systemd.services."bluealsa".wantedBy = [ "bluetooth.target" ]; + + # Note: bluealsa-aplay is available but we don't start it + # by default, it's only needed to make the machine act as + # bluetooth speaker + }) + (lib.mkIf config.hardware.alsa.enablePersistence { # Install udev rules for restoring card settings on boot diff --git a/pkgs/by-name/bl/bluez-alsa/package.nix b/pkgs/by-name/bl/bluez-alsa/package.nix index bc7500df3b5b..3bdce7e545e1 100644 --- a/pkgs/by-name/bl/bluez-alsa/package.nix +++ b/pkgs/by-name/bl/bluez-alsa/package.nix @@ -16,6 +16,8 @@ readline, sbc, python3, + systemdSupport ? true, + systemdLibs, }: stdenv.mkDerivation (finalAttrs: { @@ -37,7 +39,8 @@ stdenv.mkDerivation (finalAttrs: { autoreconfHook pkg-config python3 - ]; + ] + ++ lib.optional systemdSupport systemdLibs; buildInputs = [ alsa-lib @@ -49,9 +52,7 @@ stdenv.mkDerivation (finalAttrs: { libbsd ncurses ] - ++ lib.optionals aacSupport [ - fdk_aac - ]; + ++ lib.optional aacSupport fdk_aac; configureFlags = [ (lib.enableFeature aacSupport "aac") @@ -59,6 +60,10 @@ stdenv.mkDerivation (finalAttrs: { (lib.enableFeature true "rfcomm") (lib.withFeatureAs true "alsaplugindir" "${placeholder "out"}/lib/alsa-lib") (lib.withFeatureAs true "dbusconfdir" "${placeholder "out"}/share/dbus-1/system.d") + (lib.enableFeature systemdSupport "systemd") + (lib.withFeatureAs systemdSupport "systemdsystemunitdir" "${placeholder "out"}/lib/systemd/system") + (lib.withFeatureAs systemdSupport "bluealsauser" "bluealsa") + (lib.withFeatureAs systemdSupport "bluealsaaplayuser" "bluealsa") ]; passthru.updateScript = gitUpdater { };