Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ Optional feature enablers:
- [`experimental/net-user-v2`](./experimental/net-user-v2.yaml): [experimental] user-v2 network
to enable VM-to-VM communication without root privilege
- [`experimental/vnc`](./experimental/vnc.yaml): [experimental] use vnc display and xorg server
- [`experimental/alsa`](./experimental/alsa.yaml): [experimental] use alsa and default audio device

Lost+found:
- ~`centos`~: Removed in Lima v0.8.0, as CentOS 8 reached [EOL](https://www.centos.org/centos-linux-eol/).
Expand Down
3 changes: 3 additions & 0 deletions examples/default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ audio:
# QEMU audiodev, e.g., "none", "coreaudio", "pa", "alsa", "oss".
# VZ driver, use "vz" as device name
# Choosing "none" will mute the audio output, and not play any sound.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is not part of this PR, but reading the docs here makes me wonder what the difference is between "" and "none" beyond that "none" doesn't work with VZ. Why would you use "none" instead of just leaving off the audio device?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually some distributions don't work properly without an audio card, so the default ("") is to add one but leave it disconnected to any speakers. It can be explicitly removed ("none"), if you know that the OS will still boot...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the comment is actually wrong. It is "" that is muting the audio, and "none" that removes the driver.

And I still think it needs to be clarified that "default" doesn't apply to VZ. This could be as simple as moving the VZ line all the way to the bottom (on top of the "Builtin default" line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically, "" omits the qemu flag

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but this is end-user documentation. We should not punt by telling them to read the qemu docs and the Lima sources, but explain what each valid choice does, and why they would want to pick "" over "none" or vice versa. Or just drop "none" from our comments if there is no reason a user would ever want that.

Copy link
Member Author

@afbjorklund afbjorklund Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The defaults changed again in QEMU 8.2, so if we want to document what the default drivers are - it needs some more research and testing.

# Choosing "default" will pick a suitable of: coreudio, pa, dsound, oss.
# As of QEMU v6.2 the default is to create a disconnected sound device
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still ambiguous if "the default" means when it is set to "default" or to "the builtin default" "".

But maybe it doesn't really matter, practically speaking.

# that is still visible in the guest but not connected to the host.
# 🟢 Builtin default: ""
device: null

Expand Down
55 changes: 55 additions & 0 deletions examples/experimental/alsa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# A template to run ubuntu using device: default
# This template requires Lima v0.23.0 or later.
images:
# Try to use release-yyyyMMdd image if available. Note that release-yyyyMMdd will be removed after several months.
- location: "https://cloud-images.ubuntu.com/releases/24.04/release-20240423/ubuntu-24.04-server-cloudimg-amd64.img"
arch: "x86_64"
digest: "sha256:32a9d30d18803da72f5936cf2b7b9efcb4d0bb63c67933f17e3bdfd1751de3f3"
- location: "https://cloud-images.ubuntu.com/releases/24.04/release-20240423/ubuntu-24.04-server-cloudimg-arm64.img"
arch: "aarch64"
digest: "sha256:c841bac00925d3e6892d979798103a867931f255f28fefd9d5e07e3e22d0ef22"
# Fallback to the latest release image.
# Hint: run `limactl prune` to invalidate the cache
- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img"
arch: "x86_64"
- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img"
arch: "aarch64"

mounts:
- location: "~"
- location: "/tmp/lima"
writable: true

vmType: "qemu"
audio:
device: "default"

provision:
- mode: system
script: |
#!/bin/bash
set -eux -o pipefail
test -e /lib/modules/$(uname -r)/kernel/sound/pci/hda/snd-hda-intel.ko* && exit 0
apt-get install -y linux-modules-extra-$(uname -r)
modprobe snd-hda-intel
- mode: system
script: |
#!/bin/bash
set -eux -o pipefail
command -v aplay >/dev/null 2>&1 && exit 0
apt-get install -y --no-install-recommends alsa-utils
probes:
- description: "alsa to be installed"
script: |
#!/bin/bash
set -eux -o pipefail
if ! timeout 30s bash -c "until command -v aplay >/dev/null 2>&1; do sleep 3; done"; then
echo >&2 "alsa is not installed yet"
exit 1
fi
hint: See "/var/log/cloud-init-output.log" in the guest
message: |
To get a list of all available audio devices:
$ sudo aplay -L
To test the audio device, use something like:
$ sudo speaker-test -c2 -twav
16 changes: 16 additions & 0 deletions pkg/qemu/qemu.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,19 @@ func qemuMachine(arch limayaml.Arch) string {
return "virt"
}

// audioDevice returns the default audio device.
func audioDevice() string {
switch runtime.GOOS {
case "darwin":
return "coreaudio"
case "linux":
return "pa" // pulseaudio
case "windows":
return "dsound"
}
return "oss"
}

func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err error) {
y := cfg.LimaYAML
exe, args, err = Exe(*y.Arch)
Expand Down Expand Up @@ -762,6 +775,9 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
id := "default"
// audio device
audiodev := *y.Audio.Device
if audiodev == "default" {
audiodev = audioDevice()
}
audiodev += fmt.Sprintf(",id=%s", id)
args = append(args, "-audiodev", audiodev)
// audio controller
Expand Down
9 changes: 7 additions & 2 deletions pkg/vz/vm_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,8 @@ func attachFolderMounts(driver *driver.BaseDriver, vmConfig *vz.VirtualMachineCo
}

func attachAudio(driver *driver.BaseDriver, config *vz.VirtualMachineConfiguration) error {
if *driver.Yaml.Audio.Device == "vz" {
switch *driver.Yaml.Audio.Device {
case "vz", "default":
outputStream, err := vz.NewVirtioSoundDeviceHostOutputStreamConfiguration()
if err != nil {
return err
Expand All @@ -587,8 +588,12 @@ func attachAudio(driver *driver.BaseDriver, config *vz.VirtualMachineConfigurati
config.SetAudioDevicesVirtualMachineConfiguration([]vz.AudioDeviceConfiguration{
soundDeviceConfiguration,
})
return nil
case "", "none":
return nil
default:
return fmt.Errorf("unexpected audio device %q", *driver.Yaml.Audio.Device)
}
return nil
}

func attachOtherDevices(_ *driver.BaseDriver, vmConfig *vz.VirtualMachineConfiguration) error {
Expand Down
8 changes: 5 additions & 3 deletions pkg/vz/vz_driver_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,11 @@ func (l *LimaVzDriver) Validate() error {
}
}

audioDevice := *l.Yaml.Audio.Device
if audioDevice != "" && audioDevice != "vz" {
logrus.Warnf("field `audio.device` must be %q for VZ driver , got %q", "vz", audioDevice)
switch audioDevice := *l.Yaml.Audio.Device; audioDevice {
case "":
case "vz", "default", "none":
default:
logrus.Warnf("field `audio.device` must be \"vz\", \"default\", or \"none\" for VZ driver, got %q", audioDevice)
}

switch videoDisplay := *l.Yaml.Video.Display; videoDisplay {
Expand Down