61 lines
6.7 KiB
Markdown
61 lines
6.7 KiB
Markdown
# Warppipe Plan (C++ libpipewire library)
|
||
|
||
- [x] Milestone 0 - Groundwork and constraints
|
||
- [x] Choose build system: CMake (confirmed). Define minimal library target and example app target.
|
||
- [x] Define public API surface (namespaces, class/struct layout, error model, threading model).
|
||
- [x] Define performance budget and metrics (e.g., 200 create/modify/delete ops in < 1s on typical desktop).
|
||
- [x] Choose identity strategy for ephemeral sources (match rules on application.name, application.process.binary, media.role, node.name, fallback to client properties; avoid serial IDs).
|
||
- [x] Tests to add (non-happy path/edge cases): instructions: create unit tests that fail on missing PipeWire daemon, missing libpipewire-module-link-factory, missing libpipewire-module-metadata, and misconfigured runtime properties (e.g., invalid PW_KEY_MEDIA_CLASS).
|
||
- [x] Performance tests: instructions: add a microbenchmark harness that measures connect->create->destroy of N no-op objects (no links) and asserts subsecond N=200 on a warm PipeWire connection.
|
||
|
||
- [ ] Milestone 1 - Core runtime and registry model
|
||
- [x] Implement a WarpContext (pw_main_loop/pw_thread_loop + pw_context + pw_core) with lifecycle and reconnect handling.
|
||
- [x] Implement registry cache for nodes/ports/links with event listeners, and a stable "object identity" resolver (node name, application properties).
|
||
- [x] Expose a query API to list nodes, ports, and identify sinks/sources.
|
||
- [x] Add Catch2 test harness with smoke coverage for connection modes.
|
||
- [x] Add warppipe_cli for list-nodes, list-ports, list-links.
|
||
- [x] Tests to add (non-happy path/edge cases): instructions: simulate registry events where nodes/ports disappear mid-iteration; ensure safe iteration and cleanup; verify reconnection logic after daemon restart.
|
||
- [x] Performance tests: instructions: measure time to ingest registry snapshot of 1000 objects and process 100 add/remove events; assert latency per event and total under subsecond.
|
||
|
||
- [ ] Milestone 2 - Virtual sinks and sources
|
||
- [x] Implement virtual sink/source creation via pw_stream_new with PW_KEY_MEDIA_CLASS set to Audio/Sink or Audio/Source and autoconnect flags as needed (see src/pipewire/stream.h).
|
||
- [x] Support "null" behavior (discard) and "loopback" behavior (sink that forwards to target) using stream properties and explicit links.
|
||
- [x] Provide a naming scheme and metadata tags for virtual nodes to ensure stable identification.
|
||
- [x] Tests to add (non-happy path/edge cases): instructions: create sink/source with missing media class and expect validation error; create duplicate node name; attempt to connect when target node is absent.
|
||
- [x] Performance tests: instructions: create/destroy 100 virtual sinks and 100 virtual sources in a tight loop; measure wall time and ensure it stays within the target budget.
|
||
|
||
- [ ] Milestone 3 - Link management API
|
||
- [ ] Implement link creation via link-factory (load libpipewire-module-link-factory and call pw_core_create_object with link.input.* and link.output.* props; see src/modules/module-link-factory.c, src/examples/internal.c, src/tools/pw-link.c).
|
||
- [ ] Support linking by node+port names and by object IDs; add object.linger and link.passive options.
|
||
- [ ] Add link deletion and link reconciliation (auto-remove stale links when endpoints vanish).
|
||
- [ ] Tests to add (non-happy path/edge cases): instructions: link to non-existent port; link output-to-output or input-to-input; remove node while link is initializing; create two links to same port and validate policy behavior.
|
||
- [ ] Performance tests: instructions: create 200 links between existing ports; measure create+destroy time and verify subsecond target where possible.
|
||
|
||
- [ ] Milestone 4 - Persistence and "ephemeral source" policy
|
||
- [ ] Implement persistence (JSON or TOML) for: virtual nodes, links, and per-app routing rules. Persist on change; load on startup.
|
||
- [ ] Implement policy engine:
|
||
- [ ] Watch for node/port appearance; apply stored rules to auto-link ephemeral sources to preferred sinks.
|
||
- [ ] Store mapping by rule (app identity -> target sink/source). Avoid serial IDs; use stable metadata (app/process/role).
|
||
- [ ] Allow user override to update rule and persist.
|
||
- [ ] Integrate metadata store for defaults and routing hints using libpipewire-module-metadata (see src/modules/module-metadata.c). Track default.audio.sink/source and default.configured.audio.sink/source for stable defaults; use a dedicated warppipe.* metadata namespace to avoid conflicts.
|
||
- [ ] Tests to add (non-happy path/edge cases): instructions: rule for app that disappears and reappears under a different PID; verify re-routing; conflicting rules (two matches) resolved deterministically; persistence file corrupted; metadata module not available.
|
||
- [ ] Performance tests: instructions: simulate 200 ephemeral sources (connect/disconnect) and measure time to apply routing rules and create links; ensure rule lookup is O(1) or O(log n).
|
||
|
||
- [ ] Milestone 5 - Stability, compatibility, and tooling
|
||
- [ ] Provide a simple CLI (optional) to inspect nodes, create virtual nodes, link/unlink, and export/import config (useful for manual testing).
|
||
- [ ] Add documentation: API usage patterns, threading model, and performance notes.
|
||
- [ ] Validate behavior with PipeWire session manager present (WirePlumber) to avoid fighting policy; allow “policy-only” mode (observes and sets metadata without forcing links).
|
||
- [ ] Tests to add (non-happy path/edge cases): instructions: run with session manager disabled/enabled and verify no infinite re-link loops; ensure policy mode doesn’t override user defaults unexpectedly.
|
||
- [ ] Performance tests: instructions: end-to-end scenario (virtual sink + app connect + reroute + disconnect + reconnect) repeated 200 times; measure median/95th percentile latency.
|
||
|
||
## Design notes grounded in PipeWire code/docs
|
||
|
||
- Virtual sinks/sources via pw_stream_new and PW_KEY_MEDIA_CLASS (Audio/Sink, Audio/Source): src/pipewire/stream.h.
|
||
- Explicit link creation via link-factory and link.input.*/link.output.* properties: src/modules/module-link-factory.c, src/examples/internal.c, src/tools/pw-link.c.
|
||
- Metadata store creation and defaults (default.audio.sink/source and configured defaults): src/modules/module-metadata.c; metadata tools in src/tools/pw-metadata.c; pulse-related defaults/metadata in src/modules/module-protocol-pulse/*.
|
||
- Official concepts: nodes/ports/links and session manager policy: https://docs.pipewire.org/page_objects_design.html and https://docs.pipewire.org/page_session_manager.html
|
||
|
||
## Key behavior for ephemeral sources
|
||
|
||
- Store per-app routing rules keyed by stable application metadata (name/process/role) and apply on node appearance.
|
||
- When an app reappears, re-link its output port(s) to the saved target sink (instead of default speakers).
|