Skip to content

CopperlineOS/sdk-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 

sdk-rs

Official Rust SDK for CopperlineOS (Phase‑0).
Typed clients and utilities for talking to CopperlineOS services over message ports (Unix domain sockets). Includes high‑level APIs for copperd (timeline), compositord (Vulkan/KMS compositor), blitterd (2D ops), and audiomixerd (audio graph), plus helpers for DMABUFs, events, and errors.

TL;DR: add one crate, get typed clients for copperd, compositord, blitterd, and audiomixerd—async or blocking—so you can script timelines, move pixels, and wire audio with minimal code.


Status

  • Targets Phase‑0 (Linux‑hosted) JSON protocol v0.
  • Async and blocking clients available.
  • License: MIT OR Apache‑2.0.

Crate layout

sdk-rs/
├─ copperline-sdk/            # main umbrella crate (re-exports sub-crates)
├─ crates/
│  ├─ ports/                  # low-level port client (framing, JSON, FD passing)
│  ├─ copper/                 # copperd client (load/start/stop, events)
│  ├─ compositor/             # compositord client (layers, regs, dmabuf bind)
│  ├─ blitter/                # blitterd client (rect_fill/copy/convert/batch)
│  └─ audio/                  # audiomixerd client (nodes, connect, start/stop)
└─ examples/
   ├─ overlay_sprite.rs       # layer + moving sprite via copper
   ├─ rect_fill.rs            # use blitter to fill/copy
   └─ tone_to_device.rs       # audio tone → device graph

The copperline-sdk crate re‑exports the most common types so users typically depend on just one crate.


Install

Until published on crates.io, use a path dependency:

# Cargo.toml
[dependencies]
copperline-sdk = { path = "../sdk-rs/copperline-sdk", features = ["async"] }
# or for blocking clients:
# copperline-sdk = { path = "../sdk-rs/copperline-sdk", default-features = false, features = ["blocking"] }

When published on crates.io:

[dependencies]
copperline-sdk = { version = "0.1", features = ["async"] }

Runtime: async uses tokio. blocking has no async requirement.


Features

  • async (default) — async clients built on tokio.
  • blocking — blocking clients (no async runtime).
  • dmabuf — helpers for DMABUF FDs (format/stride/modifier helpers via nix/libdrm bindings).
  • serde — derive helpers for message payloads (enabled by default).

(async and blocking are mutually exclusive.)


Quick start (async)

Create a layer, bind an image, then animate it using Copper:

use copperline_sdk::{
    compositor::AsyncCompositorClient,
    copper::AsyncCopperClient,
};
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Connect to services
    let mut comp = AsyncCompositorClient::connect("/run/copperline/compositord.sock").await?;
    let mut cop  = AsyncCopperClient::connect("/run/copperline/copperd.sock").await?;

    // Create a layer and bind a debug image (raw RGBA8 128x128)
    let layer = comp.create_layer().await?.id;
    comp.bind_image(layer, "/tmp/sprite.rgba", 128, 128, "RGBA8").await?;
    comp.set(layer)
        .x(100).y(360).alpha(1.0).z(10).visible(true)
        .apply().await?;

    // Minimal Copper program: move right 4 px per vsync
    let program = json!({
        "version": 1,
        "program": [
            { "op":"MOVE", "reg":"layer[1].x", "value":100 },
            { "op":"MOVE", "reg":"layer[1].y", "value":360 },
            { "op":"LOOP", "count":-1, "label":"loop" },
            { "label":"loop" },
            { "op":"WAIT", "vsync":true },
            { "op":"ADD",  "reg":"layer[1].x", "delta":4 },
            { "op":"IRQ",  "tag":"tick" },
            { "op":"JUMP", "label":"loop" }
        ]
    });

    let id = cop.load(program).await?.id;
    cop.start(id).await?;

    // Subscribe to IRQ events (optional)
    let mut sub = cop.subscribe(&["irq"]).await?;
    while let Some(ev) = sub.next().await {
        println!("event: {:?}", ev?);
        // break if you want to exit after N frames
        break;
    }
    Ok(())
}

Run:

cargo run --example overlay_sprite

Quick start (blocking)

use copperline_sdk::compositor::BlockingCompositorClient as Compositor;
use copperline_sdk::copper::BlockingCopperClient as Copper;
use serde_json::json;

fn main() -> anyhow::Result<()> {
    let mut comp = Compositor::connect("/run/copperline/compositord.sock")?;
    let mut cop  = Copper::connect("/run/copperline/copperd.sock")?;

    let layer = comp.create_layer()?.id;
    comp.bind_image(layer, "/tmp/sprite.rgba", 128, 128, "RGBA8")?;
    comp.set(layer).x(100).y(360).alpha(1.0).z(10).visible(true).apply()?;

    let program = json!({
        "version":1,
        "program":[ {"op":"WAIT","vsync":true} ]
    });
    let id = cop.load(program)?.id;
    cop.start(id)?;
    Ok(())
}

Build with:

cargo run --no-default-features --features blocking --example overlay_sprite

DMABUF helpers (optional)

If you enable the dmabuf feature, the SDK exposes small helpers to work with DMABUFs:

use copperline_sdk::dmabuf::{Format, SurfaceDesc};
let desc = SurfaceDesc::rgba8(1920, 1080).linear(); // stride, modifier helpers

You can pass the FD + SurfaceDesc to compositor/blitter calls.


Error handling & retries

  • All clients return Result<T, Error> where Error wraps protocol errors and IO.
  • Idempotent calls (e.g., ping, status) may be retried by the helper methods with jittered backoff.
  • Subscriptions yield Stream<Item=Result<Event>> in async mode; read continuously to avoid backpressure drops.

Protocol compatibility

The SDK enforces a protocol matrix at compile time:

SDK crate Protocol
copperline-sdk 0.1.x ports protocol 0 (JSON/NDJSON)
copperline-sdk 0.2.x planned: binary framing + JSON fallback

Services report their protocol via {"cmd":"ping"}; the SDK warns on mismatches.


Building from source

rustup default stable
rustup component add rustfmt clippy
cargo fmt --all
cargo clippy --all-targets -- -D warnings
cargo test

Minimum Rust: 1.78+.


Examples

  • overlay_sprite.rs – create a layer, move a sprite via copper.
  • rect_fill.rs – allocate/bind a buffer and fill/copy via blitter.
  • tone_to_device.rs – build a tiny audio graph and start playback.

Run all examples:

for e in overlay_sprite rect_fill tone_to_device; do
  cargo run --example $e
done

Contributing

  • Open issues for API ergonomics or protocol coverage gaps.
  • Keep examples compiling with both async and blocking.
  • Public APIs use semver; avoid breaking changes in 0.x without a deprecation path.

See CONTRIBUTING.md and CODE_OF_CONDUCT.md.


License

Dual-licensed under Apache‑2.0 OR MIT.


See also

About

Rust SDK

Resources

License

Unknown and 2 other licenses found

Licenses found

Unknown
LICENSE
Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published