# 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. - [x] 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. - [x] 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. - [x] 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). - [x] Milestone 5 - Stability, compatibility, and tooling - [x] Provide a simple CLI (optional) to inspect nodes, create virtual nodes, link/unlink, and export/import config (useful for manual testing). - [x] Add documentation: API usage patterns, threading model, and performance notes. - [x] Validate behavior with PipeWire session manager present (WirePlumber) to avoid fighting policy; allow "policy-only" mode (observes and sets metadata without forcing links). - [x] 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. - [x] 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).