stage 3: daemon core
Phase 3 — bring up the daemon end-to-end through six checkpoints:
3a Module skeleton (error, profile, routing, runtime, pw/*)
3b Pure routing engine + 13 tests (no PipeWire dep)
3c PwContext: main loop, sigprocmask-block SIGTERM/SIGINT before
add_signal_local so signalfd actually picks them up
3d headroom-processed virtual sink via the adapter factory with
factory.name=support.null-audio-sink
3e Filter: two pw_streams (capture from monitor / playback to real
sink) with an rtrb SPSC ring between them. DSP chain
(Compressor → two-tier Limiter) runs in the playback callback.
Allocation-free; #![forbid(unsafe_code)] preserved via
bytemuck::try_cast_slice for the byte↔f32 reinterpretation.
3f Registry watcher binds the default metadata, evaluates new
Stream/Output/Audio nodes against profile rules, writes
target.object for processed routes. Self-stream guard skips
anything whose node.name starts with 'headroom-filter'.
Workspace deps added: pipewire = { features = ["v0_3_44"] } for the
modern TARGET_OBJECT key, libspa, rtrb, nix (sigprocmask), bytemuck.
Tests: 65 passing (28 dsp, 20 ipc, 4 client, 13 core). Clippy clean
at default level under -D warnings.
PLAN.md §5 renumbered to fix stale subsection labels (was 4.1–4.4
from before the per-app insertion).
Known limitations punted to Phase 4 (documented in commit history
and team memory):
- WirePlumber doesn't always honor late target.object writes once
a stream is already linked (timing race).
- preferred_real_sink dynamic tracking stubbed.
- No auto-promote of headroom-processed to system default.
- application.process.binary occasionally arrives in late metadata
updates after the global registers; routing logs show '?' until
we add a re-read.
This commit is contained in:
parent
ca1910de60
commit
ae83310772
14 changed files with 2280 additions and 39 deletions
15
PLAN.md
15
PLAN.md
|
|
@ -517,7 +517,7 @@ At realistic stream counts (2–5 managed apps): **<0.5% CPU total,
|
|||
|
||||
## 5. PipeWire integration
|
||||
|
||||
### 4.1 Sinks
|
||||
### 5.1 Sinks
|
||||
|
||||
Created on daemon startup by emitting a `pipewire.conf.d` fragment into
|
||||
`$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/headroom.conf` (if not already
|
||||
|
|
@ -537,7 +537,7 @@ There is no second sink. Bypassed streams are routed directly at the
|
|||
current `preferred_real_sink` via `target.object` metadata writes
|
||||
(see §4.3).
|
||||
|
||||
### 4.2 The filter
|
||||
### 5.2 The filter
|
||||
|
||||
Two `pw_stream`s:
|
||||
|
||||
|
|
@ -551,8 +551,12 @@ Two `pw_stream`s:
|
|||
compressor → limiter → push to playback. Allocation-free. Parameter
|
||||
updates arrive over an `rtrb` SPSC queue from the control thread.
|
||||
|
||||
### 4.3 Routing
|
||||
### 5.3 Routing
|
||||
|
||||
- On startup, write `default.audio.sink` in the `default` metadata to
|
||||
point at `headroom-processed` so new streams default to the
|
||||
processor. The previous value (the user's hardware sink) is
|
||||
captured as the initial `preferred_real_sink`.
|
||||
- Subscribe to `pw_registry` global-added events.
|
||||
- On any new node with `media.class == "Stream/Output/Audio"` and
|
||||
`node.dont-move != true`:
|
||||
|
|
@ -560,7 +564,8 @@ updates arrive over an `rtrb` SPSC queue from the control thread.
|
|||
`pipewire.access.portal.app_id`, `media.role`.
|
||||
- Evaluate routing rules from the active profile to decide
|
||||
`processed` vs. `bypass`.
|
||||
- Write `target.object` into the `default` metadata:
|
||||
- Write `target.object` into the `default` metadata for the new
|
||||
stream:
|
||||
- `processed` → `headroom-processed`'s `object.serial`.
|
||||
- `bypass` → `preferred_real_sink`'s `object.serial`.
|
||||
WirePlumber honours this for any movable stream.
|
||||
|
|
@ -574,7 +579,7 @@ updates arrive over an `rtrb` SPSC queue from the control thread.
|
|||
(so subsequent app launches still land in the processor).
|
||||
- Hotplug (sink appears/disappears) goes through the same code path.
|
||||
|
||||
### 4.4 Stream identification
|
||||
### 5.4 Stream identification
|
||||
|
||||
| Property | Reliability | Use |
|
||||
|---|---|---|
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue