# Warp Pipe Configuration Schema Warp Pipe uses JSON for configuration persistence. The config file stores virtual nodes, routing rules, saved links, and per-node volume/mute using stable identifiers (names, not serial IDs). ## Schema Version 1 ```json { "version": 1, "virtual_nodes": [ { "name": "warppipe-gaming-sink", "is_source": false, "rate": 48000, "channels": 2, "loopback": false, "target_node": "", "volume": 1.0, "mute": false }, { "name": "warppipe-mic-source", "is_source": true, "rate": 48000, "channels": 2, "loopback": false, "target_node": "" }, { "name": "warppipe-loopback", "is_source": false, "rate": 48000, "channels": 2, "loopback": true, "target_node": "alsa_output.pci-0000_00_1f.3.analog-stereo" } ], "route_rules": [ { "match": { "application_name": "Firefox", "process_binary": "firefox", "media_role": "" }, "target_node": "warppipe-gaming-sink" }, { "match": { "application_name": "discord", "process_binary": "", "media_role": "Communication" }, "target_node": "alsa_output.usb-headset" } ], "links": [ { "out_node": "Firefox", "out_port": "output_FL", "in_node": "warppipe-gaming-sink", "in_port": "input_FL" } ] } ``` ## Field Descriptions ### virtual_nodes - `name` (string, required): Unique node name (PW_KEY_NODE_NAME) - `is_source` (boolean, required): true for Audio/Source, false for Audio/Sink - `rate` (integer, default 48000): Sample rate in Hz - `channels` (integer, default 2): Channel count - `loopback` (boolean, default false): Whether node forwards to a target - `target_node` (string, optional): Required when loopback is true - `volume` (number, default 1.0): Stored node volume (0.0 - 1.5) - `mute` (boolean, default false): Stored node mute state ### route_rules Rules match ephemeral audio sources to target sinks by stable application metadata. - `match.application_name` (string): Match PW_KEY_APP_NAME - `match.process_binary` (string): Match PW_KEY_APP_PROCESS_BINARY - `match.media_role` (string): Match PW_KEY_MEDIA_ROLE - `id` (integer, optional): Auto-saved rule id (ignored on load) - `target_node` (string, required): Destination node name All non-empty match fields must match (AND logic). At least one match field must be non-empty. ### links Saved links are recreated by matching node and port names when both endpoints appear. - `out_node` (string, required): Output node name - `out_port` (string, required): Output port name - `in_node` (string, required): Input node name - `in_port` (string, required): Input port name ## Persistence Behavior - **Auto-save**: When `ConnectionOptions::config_path` is set, config is saved after: - Virtual node created/removed - Routing rule added/removed - `SetNodeVolume` updates - `CreateLink`/`RemoveLink` updates - **Load on startup**: When `config_path` is set and the file exists, it is loaded during `Client::Create()` after connection is established. - **Manual**: `SaveConfig(path)` and `LoadConfig(path)` work independently of auto-save. - **Atomic writes**: Saves write to a `.tmp` file first, then rename for crash safety. ## Error Handling - Missing config file on auto-load: Silently ignored (fresh start) - Invalid JSON syntax: `StatusCode::kInvalidArgument` with parse error details - Missing version field: `StatusCode::kInvalidArgument` - Empty path: `StatusCode::kInvalidArgument` - File not found on manual load: `StatusCode::kNotFound`