121 lines
3.6 KiB
Markdown
121 lines
3.6 KiB
Markdown
# 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`
|