> ## Documentation Index
> Fetch the complete documentation index at: https://rockboxzig.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Native engine bindings

> Call the Rockbox DSP, metadata, decoding, and playback engine in-process from ten languages, all over one shared C ABI.

The **bindings** embed the Rockbox audio engine directly in your process. They
wrap `rockbox-ffi` — a flat **C ABI** (`crates/rockbox-ffi`) — so you can parse
tags, decode files to PCM, run PCM through the DSP pipeline, and drive a
queue-based player without running a daemon or talking to any network port.

> [!NOTE]
>
> Looking to **remote-control a running `rockboxd`** over the network instead?
> That is what the [Client SDKs](https://rockboxzig.mintlify.site/sdks/overview.md) are for — they speak GraphQL on
> port 6062. The bindings on this page are the opposite: no daemon, no sockets,
> the engine runs **inside your program**.

## SDKs vs. bindings

|   | [Client SDKs](https://rockboxzig.mintlify.site/sdks/overview.md) | Bindings (this section) |
| - | - | - |
| Talks to | A running `rockboxd` over GraphQL | The engine, linked in-process |
| Transport | HTTP / WebSocket on port 6062 | Native `dlopen` / FFI — no network |
| Best for | Apps that control a music server | Embedding DSP / metadata / playback |
| Package family | `rockbox-sdk`, `@rockbox-zig/sdk`, … | `rockbox-ffi` and friends |

## Four surfaces

Every binding exposes the same namespaces with matching method names:

> [card] metadata
>
> `read(path)` returns parsed tags, duration, ReplayGain, album-art and
> cuesheet offsets. `probe(filename)` guesses the codec from the extension —
> no I/O.

> [card] Decoder
>
> Open a file and pull decoded **interleaved-stereo int16 PCM** one chunk at
> a time through the Rockbox codec engine — `metadata()`, `next_chunk()`,
> `seek_ms()`, `elapsed_ms()`, `finished()`. No audio device needed.

> [card] Dsp
>
> Construct with a sample rate, then the whole pipeline — EQ, tone,
> crossfeed, surround, channel mixing, bass enhancement, compressor,
> ReplayGain, … — and `process(samples)` over interleaved stereo int16.

> [card] Player
>
> Queue + transport, **shuffle / repeat**, crossfade, ReplayGain, **stereo
> balance**, the full **DSP chain** (EQ + presets, tone, crossfeed, surround,
> compressor, …), and `status()`. Needs an audio output device.

> [!NOTE]
>
> The codec state is **process-wide** — only one `Decoder` can decode at a time.
> Opening a second one blocks until the first is freed (closed explicitly, or
> by GC / a context manager).

## What the Player exposes

Beyond queue and transport, the player mirrors Rockbox's own sound engine —
every setter is live and reflected back by `dsp_settings()` / `status()`:

> [card] Playback modes
>
> **Shuffle** (current track stays, the rest are shuffled) and **repeat**
> (`off` / `one` / `all`), readable back from `status()`.

> [card] Equalizer
>
> 10-band parametric EQ with **21 ready-to-use presets** (Rock, Jazz, Bass
> Boost, …), per-band control, and a pre-cut.

> [card] Tone & spatial
>
> Bass/treble (with cutoffs), **crossfeed**, Haas **surround**, channel
> mixing (mono / karaoke / swap), custom stereo width and **stereo balance**
> (−100 full-left … +100 full-right).

> [card] Enhancement & output
>
> **Perceptual bass enhancement**, **auditory fatigue reduction**, a
> dynamic-range **compressor**, **dither** and **pitch**/speed.

Queue entries can be **local file paths**, **`http(s)://` URLs** (finite
remote files, streamed on demand), or **live-radio / streaming URLs**.

> [!NOTE]
>
> These are the same controls as Rockbox's on-device sound menu — see the
> official [Rockbox manual — Sound Settings](https://download.rockbox.org/daily/manual/rockbox-ipodvideo/rockbox-buildch6.html)
> (and the [Equalizer](https://download.rockbox.org/daily/manual/rockbox-ipodvideo/rockbox-buildch6.html#x11-1200006.11)
> section) for what each one does.

## Pick a language

> [card] [Python](https://rockboxzig.mintlify.site/bindings/python.md)
>
> `pip install rockbox-ffi` — cffi

> [card] [Go](https://rockboxzig.mintlify.site/bindings/go.md)
>
> `go get …/bindings/go` — purego, no cgo

> [card] [TypeScript](https://rockboxzig.mintlify.site/bindings/typescript.md)
>
> `npm install rockbox-ffi` — Bun / Deno / Node

> [card] [Ruby](https://rockboxzig.mintlify.site/bindings/ruby.md)
>
> `gem install rockbox_ffi` — fiddle

> [card] [Erlang](https://rockboxzig.mintlify.site/bindings/erlang.md)
>
> `{rockbox_ffi_nif, …}` — erl\_nif (shared)

> [card] [Elixir](https://rockboxzig.mintlify.site/bindings/elixir.md)
>
> `{:rockbox_ex_ffi, "~> 0.1"}` — erl\_nif

> [card] [Gleam](https://rockboxzig.mintlify.site/bindings/gleam.md)
>
> `gleam add rockbox_ffi` — erl\_nif

> [card] [Swift](https://rockboxzig.mintlify.site/bindings/swift.md)
>
> SwiftPM — pure-Swift dlopen

> [card] [Kotlin](https://rockboxzig.mintlify.site/bindings/kotlin.md)
>
> `io.github.tsirysndr:rockbox-ffi` — Java FFM

> [card] [Clojure](https://rockboxzig.mintlify.site/bindings/clojure.md)
>
> `io.github.tsirysndr/rockbox-clj-ffi` — Java FFM

> [!NOTE]
>
> On the BEAM, [Erlang](https://rockboxzig.mintlify.site/bindings/erlang.md) (`rockbox_ffi_nif`) is the shared
> native layer — a raw `erl_nif` surface over the C ABI. The
> [Elixir](https://rockboxzig.mintlify.site/bindings/elixir.md) and [Gleam](https://rockboxzig.mintlify.site/bindings/gleam.md) packages depend on it
> for their native code and add the ergonomic wrappers on top.

## The one thing to know: two ReplayGain encodings

The DSP and the player use **different integers** for the same ReplayGain
modes — a quirk of the underlying C ABI. Every binding ships named
enums/constants so you never have to remember which is which:

| Mode | `Dsp` (`DspReplayGainMode`) | `Player` (`ReplayGainMode`) |
| - | - | - |
| Off | 3 | 0 |
| Track | 0 | 1 |
| Album | 1 | 2 |
| Shuffle | 2 | — |

## How values cross the boundary

* **Rich values** (metadata, player status) cross as **JSON** and land as a
  native map/dict/struct in your language.
* **Sample buffers** are raw interleaved-stereo **signed 16-bit** integers
  (`Int16Array`, `array('h')`, `ShortArray`, a BEAM binary, …).
* **Memory is managed for you.** Every allocation the ABI hands out has a
  matching free called *inside* the binding — you never call a `*_free`
  yourself. Handles close via context managers, `use`/`with`, or GC finalizers.

## Build the native library

Published packages bundle a prebuilt `librockbox_ffi` for your platform, so
`pip install` / `npm install` / `gem install` need no Rust toolchain. From a
repo checkout, build it once and every binding finds it automatically:

```sh theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
cargo build --release -p rockbox-ffi
#  target/release/librockbox_ffi.dylib   (macOS)
#  target/release/librockbox_ffi.so      (Linux)
#  target/release/librockbox_ffi.a       (static, for the BEAM NIFs)
```

The loaders walk up to `target/release/` by default. Point them elsewhere with
the `ROCKBOX_FFI_LIB` environment variable:

```sh theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
export ROCKBOX_FFI_LIB=/path/to/librockbox_ffi.dylib
```

> [!NOTE]
>
> On **Linux** the shared library links ALSA — install the system
> `libasound2` package at runtime.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.