Skip to main content
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.
Looking to remote-control a running rockboxd over the network instead? That is what the Client SDKs 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

Four surfaces

Every binding exposes the same namespaces with matching method names:

metadata

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

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.

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.

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.
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():

Playback modes

Shuffle (current track stays, the rest are shuffled) and repeat (off / one / all), readable back from status().

Equalizer

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

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).

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.
These are the same controls as Rockbox’s on-device sound menu — see the official Rockbox manual — Sound Settings (and the Equalizer section) for what each one does.

Pick a language

Python

pip install rockbox-ffi — cffi

Go

go get …/bindings/go — purego, no cgo

TypeScript

npm install rockbox-ffi — Bun / Deno / Node

Ruby

gem install rockbox_ffi — fiddle

Erlang

{rockbox_ffi_nif, …} — erl_nif (shared)

Elixir

{:rockbox_ex_ffi, "~> 0.1"} — erl_nif

Gleam

gleam add rockbox_ffi — erl_nif

Swift

SwiftPM — pure-Swift dlopen

Kotlin

io.github.tsirysndr:rockbox-ffi — Java FFM

Clojure

io.github.tsirysndr/rockbox-clj-ffi — Java FFM
On the BEAM, Erlang (rockbox_ffi_nif) is the shared native layer — a raw erl_nif surface over the C ABI. The Elixir and Gleam 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:

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:
The loaders walk up to target/release/ by default. Point them elsewhere with the ROCKBOX_FFI_LIB environment variable:
On Linux the shared library links ALSA — install the system libasound2 package at runtime.