Skip to content

Fix ALSA hardware volume detection for CARD=<name> and bare sysdefault devices - #279

Open
OnFreund wants to merge 1 commit into
mainfrom
claude/jolly-taussig-3e6f5a
Open

Fix ALSA hardware volume detection for CARD=<name> and bare sysdefault devices#279
OnFreund wants to merge 1 commit into
mainfrom
claude/jolly-taussig-3e6f5a

Conversation

@OnFreund

@OnFreund OnFreund commented Sep 7, 2026

Copy link
Copy Markdown

Summary

  • parse_alsa_card() in sendspin/alsa_volume.py only recognized PortAudio's numeric hw:N,M card annotation. Devices selected via --audio-device using the plughw:CARD=<name>,DEV=<n> / dmix:CARD=<name>,DEV=<n> convention — often needed because raw hw:N,M bypasses ALSA's plug/dmix conversion layer and fails to open for playback at all — weren't recognized, so hardware volume control silently fell back to software volume even when a real mixer element existed.
  • parse_alsa_card() now also extracts the card's string name from a CARD=<name> pattern, and find_mixer_element()/AlsaVolumeController/async_check_alsa_available() were generalized to accept int | str card identifiers. Confirmed via the amixer source that -c resolves either a numeric index or a card name through snd_card_get_index() internally, so passing the name straight through works.
  • Also handles PortAudio's bare sysdefault/default device enumeration (no card info at all in the name), which turned up in real-world testing on an ODROID-N2. Since the string carries no card identity, this cross-references aplay -L's fully-qualified hints (e.g. sysdefault:CARD=ODROIDN2) to recover the card, and only resolves when exactly one hint matches — on a system with multiple cards each exposing their own default hint, it backs off to software volume rather than guessing which one is meant.

Test plan

  • uv run ruff check --fix .
  • uv run ruff format .
  • uv run mypy sendspin — no issues
  • uv run pytest tests/ -q — 150 passed (11 new tests covering CARD=<name> parsing, the plughw/dmix discovery flow, and the bare-sysdefault resolution including the ambiguous multi-card and no-hint cases)

🤖 Generated with Claude Code

parse_alsa_card() only matched PortAudio's hw:N,M numeric card form,
so devices selected via --audio-device using the plughw:/dmix:
CARD=<name> convention (needed to reach ALSA's plug/dmix conversion
layer, since raw hw:N,M often fails to open for playback) silently
fell back to software volume even when a real hardware mixer existed.

Also handle PortAudio's bare "sysdefault"/"default" enumeration, which
carries no card info at all: cross-reference aplay -L's fully-qualified
hints (e.g. sysdefault:CARD=vc4hdmi) to recover the card, backing off
to software volume only when the match is ambiguous (multiple cards
each exposing their own default hint) rather than guessing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

1 participant