warp-pipe/PLAN.md
2026-01-29 21:01:56 -07:00

61 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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
- [x] 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).
- [x] Support linking by node+port names and by object IDs; add object.linger and link.passive options.
- [x] Add link deletion and link reconciliation (auto-remove stale links when endpoints vanish).
- [x] 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.
- [x] Performance tests: instructions: create 200 links between existing ports; measure create+destroy time and verify subsecond target where possible.
- [x] Milestone 4 - Persistence and "ephemeral source" policy
- [x] Implement persistence (JSON or TOML) for: virtual nodes, links, and per-app routing rules. Persist on change; load on startup.
- [x] Implement policy engine:
- [x] Watch for node/port appearance; apply stored rules to auto-link ephemeral sources to preferred sinks.
- [x] Store mapping by rule (app identity -> target sink/source). Avoid serial IDs; use stable metadata (app/process/role).
- [x] Allow user override to update rule and persist.
- [x] 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.
- [x] 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.
- [x] 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 doesnt 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).