Skip to content

oto: add a non-cgo ALSA fallback for the PulseAudio driver#283

Open
hajimehoshi wants to merge 1 commit into
mainfrom
claude/hopeful-shannon-4bd66e
Open

oto: add a non-cgo ALSA fallback for the PulseAudio driver#283
hajimehoshi wants to merge 1 commit into
mainfrom
claude/hopeful-shannon-4bd66e

Conversation

@hajimehoshi
Copy link
Copy Markdown
Member

What

When no PulseAudio server is reachable, the Unix backend now falls back to ALSA instead of failing context creation. The fallback is Cgo-free: it loads libasound.so.2 dynamically (via purego) only when the fallback is actually needed.

Why

e3a524c replaced the cgo ALSA driver with a pure-Go PulseAudio driver, which made a running PulseAudio (or PipeWire pulse-shim) server mandatory. That breaks minimal installs, containers, kiosk/embedded setups, and removed the backend FreeBSD historically used. This restores ALSA as a fallback while staying Cgo-free.

Closes #282.

How

  • driver_unix.go becomes a thin dispatcher: it owns the shared mux, and in a goroutine tries PulseAudio, then ALSA — the same shape as the Windows driver choosing between WASAPI and WinMM. Both backends satisfy a small unixBackend interface.
  • driver_pulseaudio_unix.go (new): the existing PulseAudio code, moved into a pulseContext backend. It now returns its error (the fallback trigger) and closes the client if NewPlayback fails.
  • driver_alsa_unix.go (new): a faithful purego port of the pre-e3a524c cgo ALSA driver — same device enumeration (snd_device_name_hint, default/plug:default prepended, Input/null filtered), FLOAT_LE setup, and the blocking snd_pcm_writei / snd_pcm_recover loop. libasound is Dlopen'd lazily, only when PulseAudio fails.

Platform / build notes

  • The ALSA file is tagged ((linux && !android) || freebsd || netbsd) && !nintendosdk && !playstation5 — purego's supported platforms, excluding the Linux-based console targets that have their own driver. OpenBSD (no purego) keeps PulseAudio only, via a nil dispatcher hook.
  • On FreeBSD, native builds (Cgo enabled by default) work as-is. Building with CGO_ENABLED=0 (e.g. cross-compiling) needs -gcflags="github.com/ebitengine/purego/internal/fakecgo=-std" (documented in the README).
  • Dropped the now-unused libasound2-dev apt install from CI in a separate commit already on main.

Testing

  • gofmt, go build, and go vet clean.
  • Cross-compiles: linux amd64/arm64/386/arm, freebsd (with the gcflags above), netbsd, openbsd, darwin, windows 386/amd64/arm64.
  • go test ./... passes on macOS.
  • ⚠️ The ALSA runtime path could not be exercised from CI or the dev machine (macOS). It should be verified on Linux/FreeBSD by running example/ with PulseAudio stopped (and libasound.so.2 present).

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 31, 2026 05:10
@hajimehoshi
Copy link
Copy Markdown
Member Author

@mcuadros Please try this

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a cgo-free ALSA backend as a runtime fallback when the Unix PulseAudio backend can’t connect to a server, improving support for minimal/containerized Unix installs while keeping the default PulseAudio path.

Changes:

  • Refactors the Unix driver into an asynchronous dispatcher that tries PulseAudio first, then ALSA (when available).
  • Introduces a dedicated PulseAudio backend implementation extracted from the prior Unix driver.
  • Adds a purego-based ALSA backend that dlopens libasound only when needed, and documents the fallback/build notes in the README.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
README.md Documents the new ALSA fallback behavior and FreeBSD CGO-free build note.
driver_unix.go Reworks Unix context initialization into an async dispatcher selecting PulseAudio or ALSA.
driver_pulseaudio_unix.go New PulseAudio backend extracted from the previous Unix driver code.
driver_alsa_unix.go New purego-based ALSA fallback backend with runtime libasound loading and device enumeration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread driver_alsa_unix.go
Comment thread driver_alsa_unix.go
Comment thread driver_alsa_unix.go
Comment thread driver_alsa_unix.go
Comment thread driver_alsa_unix.go
Comment thread driver_alsa_unix.go
@hajimehoshi hajimehoshi force-pushed the claude/hopeful-shannon-4bd66e branch from ca48c9c to ba7a19f Compare May 31, 2026 05:14
The PulseAudio driver requires a running PulseAudio server, which is
absent on many minimal, container, kiosk, and embedded systems. When no
server is reachable, fall back to ALSA by loading libasound dynamically
through purego, keeping the fallback Cgo-free and preserving FreeBSD and
NetBSD support.

The context now picks a backend at startup much like the Windows driver
chooses between WASAPI and WinMM.

Closes #282

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hajimehoshi hajimehoshi force-pushed the claude/hopeful-shannon-4bd66e branch from ba7a19f to edec6a1 Compare May 31, 2026 05:20
@TotallyGamerJet
Copy link
Copy Markdown
Contributor

TotallyGamerJet commented May 31, 2026

I think it would be nice to have a no_alsa_fallback (or nolibasound) build tag so that if someone wants to have a static binary with just pulse audio then they can do that

@hajimehoshi
Copy link
Copy Markdown
Member Author

hajimehoshi commented May 31, 2026

I think it would be nice to have a no_alsa_fallback (or nolibasound) build tag so that if someone wants to have a static binary with just pulse audio then they can do that

I'd add this feature if someone has an issue in the real world and requests it. Windows also has two drivers and nobody requested a flag to choose a driver so far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PulseAudio requirement is a breaking change

3 participants