Milestone 5
This commit is contained in:
parent
420da2d468
commit
4e21039222
9 changed files with 877 additions and 22 deletions
143
README.md
143
README.md
|
|
@ -1,6 +1,16 @@
|
|||
# warppipe
|
||||
|
||||
A C++ libpipewire library for creating virtual sinks/sources and managing links.
|
||||
A C++17 static library wrapping libpipewire for virtual audio node management, link routing, and per-app routing policy.
|
||||
|
||||
## Features
|
||||
|
||||
- **Virtual sinks/sources** — create Audio/Sink and Audio/Source nodes with configurable sample rate and channels
|
||||
- **Link management** — connect and disconnect ports by node+port name or ID, with passive and linger options
|
||||
- **Per-app routing rules** — match applications by name, process binary, or media role and auto-route to target sinks
|
||||
- **Persistence** — JSON config with atomic writes, auto-save on change, auto-load on startup
|
||||
- **Metadata integration** — read and set default audio sink/source via PipeWire metadata
|
||||
- **Policy-only mode** — observe and set metadata without creating links (avoids fighting WirePlumber)
|
||||
- **Thread-safe** — dedicated PipeWire thread loop; all public methods callable from any thread
|
||||
|
||||
## Build
|
||||
|
||||
|
|
@ -10,18 +20,131 @@ Requirements:
|
|||
- libpipewire-0.3 development files
|
||||
- C++17 compiler
|
||||
|
||||
Aurora / Universal Blue (Homebrew):
|
||||
```
|
||||
/home/linuxbrew/.linuxbrew/bin/brew install cmake pkg-config pipewire
|
||||
```
|
||||
|
||||
Build:
|
||||
```
|
||||
```sh
|
||||
cmake -S . -B build
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
Example:
|
||||
Targets: `warppipe` (library), `warppipe_example`, `warppipe_cli`, `warppipe_tests`, `warppipe_perf`
|
||||
|
||||
### Dependencies
|
||||
|
||||
- [libpipewire-0.3](https://pipewire.org/) — system package
|
||||
- [nlohmann/json](https://github.com/nlohmann/json) — fetched automatically via CMake FetchContent
|
||||
- [Catch2 v3](https://github.com/catchorg/Catch2) — fetched automatically via CMake FetchContent
|
||||
|
||||
## Quick Start
|
||||
|
||||
```cpp
|
||||
#include <warppipe/warppipe.hpp>
|
||||
|
||||
warppipe::ConnectionOptions opts;
|
||||
opts.application_name = "my-app";
|
||||
opts.config_path = "/home/user/.config/warppipe/config.json";
|
||||
|
||||
auto result = warppipe::Client::Create(opts);
|
||||
auto& client = result.value;
|
||||
|
||||
// Create a virtual sink
|
||||
auto sink = client->CreateVirtualSink("my-sink");
|
||||
|
||||
// Route Firefox audio to it
|
||||
warppipe::RouteRule rule;
|
||||
rule.match.application_name = "Firefox";
|
||||
rule.target_node = "my-sink";
|
||||
client->AddRouteRule(rule);
|
||||
|
||||
// The policy engine auto-links Firefox when it starts playing
|
||||
```
|
||||
./build/warppipe_example
|
||||
|
||||
## CLI
|
||||
|
||||
`warppipe_cli` provides full access to the library for manual testing and scripting:
|
||||
|
||||
```
|
||||
warppipe_cli list-nodes
|
||||
warppipe_cli list-ports <node-id>
|
||||
warppipe_cli list-links
|
||||
warppipe_cli list-rules
|
||||
warppipe_cli create-sink <name> [--rate N] [--channels N]
|
||||
warppipe_cli create-source <name> [--rate N] [--channels N]
|
||||
warppipe_cli link <out-node> <out-port> <in-node> <in-port> [--passive] [--linger]
|
||||
warppipe_cli unlink <link-id>
|
||||
warppipe_cli add-rule --app <name> --target <node> [--process <bin>] [--role <role>]
|
||||
warppipe_cli remove-rule <rule-id>
|
||||
warppipe_cli save-config <path>
|
||||
warppipe_cli load-config <path>
|
||||
warppipe_cli defaults
|
||||
```
|
||||
|
||||
`create-sink` and `create-source` block until interrupted with Ctrl-C.
|
||||
|
||||
## Configuration
|
||||
|
||||
Config is JSON. Set `ConnectionOptions::config_path` to enable auto-save/load, or use `SaveConfig`/`LoadConfig` manually.
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"virtual_nodes": [
|
||||
{
|
||||
"name": "warppipe-gaming-sink",
|
||||
"is_source": false,
|
||||
"rate": 48000,
|
||||
"channels": 2,
|
||||
"loopback": false,
|
||||
"target_node": ""
|
||||
}
|
||||
],
|
||||
"route_rules": [
|
||||
{
|
||||
"match": {
|
||||
"application_name": "Firefox",
|
||||
"process_binary": "",
|
||||
"media_role": ""
|
||||
},
|
||||
"target_node": "warppipe-gaming-sink"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
See [docs/config-schema.md](docs/config-schema.md) for full schema documentation.
|
||||
|
||||
## Policy-Only Mode
|
||||
|
||||
When running alongside WirePlumber, enable `policy_only` to prevent warppipe from creating links that conflict with the session manager:
|
||||
|
||||
```cpp
|
||||
warppipe::ConnectionOptions opts;
|
||||
opts.policy_only = true;
|
||||
```
|
||||
|
||||
In this mode the policy engine still evaluates rules but does not create links. Metadata defaults can still be read and set.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [API Reference](docs/api.md) — full API, threading model, error model, performance notes
|
||||
- [Config Schema](docs/config-schema.md) — JSON configuration format and persistence behavior
|
||||
|
||||
## Tests
|
||||
|
||||
```sh
|
||||
./build/warppipe_tests
|
||||
```
|
||||
|
||||
31 test cases covering connection, registry, virtual nodes, links, route rules, policy engine, persistence, and metadata.
|
||||
|
||||
## Performance
|
||||
|
||||
```sh
|
||||
./build/warppipe_perf --mode <create-destroy|registry|links|policy|e2e>
|
||||
```
|
||||
|
||||
| Mode | Workload | Typical Result |
|
||||
|------|----------|----------------|
|
||||
| create-destroy | 200 sink create/destroy | < 1s |
|
||||
| registry | 1000 object ingest + 100 events | < 1s |
|
||||
| links | 200 link create/destroy | < 1s |
|
||||
| policy | 200 ephemeral sources routed | ~370ms |
|
||||
| e2e | 200 full iterations (sink + rule + source + teardown) | median ~3ms, p95 ~4ms |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue