From 8de5e558017d7c4ebe09c323e4c5dee925ef8d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dav=C3=AD=C3=B0=20Steinn=20Geirsson?= Date: Fri, 20 Feb 2026 00:30:39 +0000 Subject: [PATCH] Replace sound tri-state with playback/capture booleans Instead of passing raw crosvm attrsets, sound is now configured with two booleans: sound.playback (default true) and sound.capture (default false, implies playback). Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 2 +- README.md | 8 ++++---- example/configuration.nix | 2 +- modules/options.nix | 24 +++++++++++------------- modules/scripts.nix | 25 +++++++++++++++---------- 5 files changed, 32 insertions(+), 29 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index ce58605..473b428 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -94,7 +94,7 @@ See README.md for full usage details and options. ### Key Patterns -- **Option tri-state**: `gpu`, `sound`, and similar options accept `false` (disabled), `true` (default config), or an attrset (custom config). Built into crosvm args via `lib/helpers.nix`. +- **Option tri-state**: `gpu` and similar options accept `false` (disabled), `true` (default config), or an attrset (custom config). Built into crosvm args via `lib/helpers.nix`. Note: `sound` uses a submodule with `playback` and `capture` booleans instead. - **Socket activation chain**: command socket → proxy template service → VM service → crosvm - **Offline-by-default networking**: VMs have no network unless `network.interfaces` is configured with TAP interfaces. - **Root overlay**: qcow2-backed (default) or tmpfs-backed overlayfs upper layer. Ephemeral — created at VM start, deleted at stop. diff --git a/README.md b/README.md index 2f2112e..7f26605 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,8 @@ For mpv, make sure you use `--vo=wlshm`. Other backends probably won't work. | `copyChannel` | bool | `false` | Include NixOS channel in rootfs (same nixpkgs rev used to build the VM) | | `kernelParams` | list of strings | `[]` | Extra kernel command line parameters | | `gpu` | bool or attrset | `true` | GPU config (false=disabled, true=default, attrset=custom) | -| `sound` | bool or attrset | `true` | Sound config (false=disabled, true=default PulseAudio, attrset=custom) | +| `sound.playback` | bool | `true` | Enable sound playback | +| `sound.capture` | bool | `false` | Enable sound capture (implies playback) | | `sharedDirectories` | attrsOf submodule | `{}` | Shared directories via virtiofsd (keys are fs tags, see below) | | `pciDevices` | list of attrsets | `[]` | PCI devices to passthrough (path + optional kv pairs) | | `guestPrograms` | list of packages | `[]` | VM-specific packages | @@ -312,9 +313,8 @@ VMs with `gpu = false` do not connect to the host Wayland socket and are unaffec ### Sound Configuration ```nix -sound = false; # Disabled -sound = true; # Default PulseAudio config -sound = { backend = "pulse"; capture = true; }; # Custom +sound.playback = false; # Disabled +sound.capture = true; # Playback + capture ``` ### PCI Passthrough Configuration diff --git a/example/configuration.nix b/example/configuration.nix index 494313c..3be34fa 100644 --- a/example/configuration.nix +++ b/example/configuration.nix @@ -79,7 +79,7 @@ memory = 512; cpus = 2; gpu = false; - sound = false; + sound.playback = false; sharedHome = false; network = { nameservers = [ "8.8.8.8" ]; diff --git a/modules/options.nix b/modules/options.nix index 367b8b8..e9944c1 100644 --- a/modules/options.nix +++ b/modules/options.nix @@ -347,19 +347,17 @@ let ''; }; - sound = lib.mkOption { - type = lib.types.either lib.types.bool crosvmAttrsetType; - default = true; - description = '' - Sound configuration. Set to false to disable, true for default PulseAudio config, - or an attrset for custom --virtio-snd options. - ''; - example = lib.literalExpression '' - { - backend = "pulse"; - capture = true; - } - ''; + sound = { + playback = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Enable sound playback."; + }; + capture = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Enable sound capture. Implies playback."; + }; }; sharedDirectories = lib.mkOption { diff --git a/modules/scripts.nix b/modules/scripts.nix index 468c496..93e0ee3 100644 --- a/modules/scripts.nix +++ b/modules/scripts.nix @@ -35,13 +35,18 @@ let userGid = config.users.groups.${config.users.users.${cfg.user}.group}.gid; userRuntimeDir = "/run/user/${toString userUid}"; - # Default PulseAudio sound configuration - defaultSoundConfig = { - backend = "pulse"; - capture = false; - pulse_socket_path = "${userRuntimeDir}/pulse/native"; - pulse_cookie_path = "/home/${cfg.user}/.config/pulse/cookie"; - }; + # Build effective sound config from sound options + mkSoundConfig = + sound: + if sound.playback || sound.capture then + { + backend = "pulse"; + capture = sound.capture; + pulse_socket_path = "${userRuntimeDir}/pulse/native"; + pulse_cookie_path = "/home/${cfg.user}/.config/pulse/cookie"; + } + else + null; # Default GPU configuration defaultGpuConfig = { @@ -58,7 +63,7 @@ let vm: let # Enable pipewire in guest when sound is enabled - soundConfig = lib.optionalAttrs (vm.sound != false) { + soundConfig = lib.optionalAttrs (vm.sound.playback || vm.sound.capture) { services.pipewire = { enable = lib.mkDefault true; pulse.enable = lib.mkDefault true; @@ -170,8 +175,8 @@ let # GPU config: false = disabled, true = default config, attrset = custom config effectiveGpu = resolveOptionalConfig defaultGpuConfig vm.gpu; - # Sound config: false = disabled, true = default pulse config, attrset = custom config - effectiveSound = resolveOptionalConfig defaultSoundConfig vm.sound; + # Sound config from playback/capture booleans + effectiveSound = mkSoundConfig vm.sound; # Convert BDF to sysfs path bdfToSysfs = bdf: "/sys/bus/pci/devices/${normalizeBdf bdf}";