Skip to content

fix: read sink state once per tick instead of three pactl calls per dial - #2

Merged
NyleGarcia merged 1 commit into
mainfrom
fix-pactl-poll-storm
Oct 2, 2026
Merged

NyleGarcia merged 1 commit into
mainfrom
fix-pactl-poll-storm

Conversation

@NyleGarcia

Copy link
Copy Markdown
Owner

Problem

With dials on screen, the plugin spawned ~29 pactl processes per second continuously, loading pipewire-pulse.

Cause

_tick_levels runs at ~8 Hz and, for every encoder, _read called sink_exists (pactl list short sinks), get_volume and get_mute — three subprocesses per dial per tick.

Scope

  • owdeck/graph.py: replace sink_exists/get_volume with sinks() — one pactl -f json list sinks returning {name: (volume, muted)}; failure or bad output returns {} (mix shows unavailable, as before).
  • plugin.py: _sink_states() caches that map for SNAPSHOT_SECONDS (0.9 s), shared by all dials; invalidated after our own set_volume/toggle_mute and on OpenWave pushes, so user turns stay immediate and external changes show within ~1 s.
  • tests/test_plugin.py: fixture stubs graph.sinks; new TestSinkPolling bounds pactl spawns across many ticks with multiple dials.

Verification

  • make test: 121 tests OK; the bound test fails (108 spawns vs limit 4) with the cache disabled. make validate clean.
  • Live: 4 mix dials for 5 s → 6 pactl spawns (~1.2/s, was ~29/s); dials show correct volume/mute.

@NyleGarcia
NyleGarcia merged commit 649d32a into main Oct 2, 2026
3 checks passed
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

🎉 This PR is included in version 0.7.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant