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 <noreply@anthropic.com>
This commit is contained in:
Davíð Steinn Geirsson 2026-02-20 00:30:39 +00:00
parent c2e054171b
commit 8de5e55801
5 changed files with 32 additions and 29 deletions

View file

@ -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.

View file

@ -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

View file

@ -79,7 +79,7 @@
memory = 512;
cpus = 2;
gpu = false;
sound = false;
sound.playback = false;
sharedHome = false;
network = {
nameservers = [ "8.8.8.8" ];

View file

@ -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 {

View file

@ -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}";