librockbox_ffi at runtime and bind every function
to a MethodHandle downcall.
librockbox_ffi for every OS/arch and extracts the matching one at
load time — no Rust toolchain needed. ROCKBOX_FFI_LIB overrides; a repo
checkout falls back to target/release.
Quick start
Player API
Every mutating player fn takes the handlep first and returns p, so a
full session — queue, DSP chain, shuffle/repeat, transport — threads with ->.
Getters/queries (volume, status, queue, dsp-settings, shuffle-enabled?,
repeat, eq-enabled?, …) return their values as usual.
Sources
set-queue, enqueue, and insert accept local file paths, finite
http(s):// URLs, and live-radio / streaming URLs in the same list —
mix them freely. dsp-settings returns a keywordized snapshot of the whole
chain.
Stereo balance
set-balance / balance pan the output between the channels: the value ranges
from -100 (full left) to +100 (full right), with 0 = centre.
Enums
Every enum arg accepts either the keyword or the raw int (rockbox.ffi.enums):
Decoder API
rockbox.ffi.decoder streams an audio file to interleaved-stereo S16LE PCM
one chunk at a time through the Rockbox codec engine — useful for feeding your
own output sink, resampler, or analysis pipeline.
opentakes a path and returns a handle;free(orwith-decoder) releases it when you’re done.metadatareturns the tags + stream properties as a keyword-keyed map (same shape asmetadata/read).next-chunkyields[samples sample-rate]—samplesis an interleaved stereoshort-array— or nil at end of track.seek-msrequests a seek;elapsed-msis the codec’s last reported position.finishedreturns[done code]:codeis0on a clean end and negative on a codec error (valid only oncedoneis true).
Notes
- Rich values (metadata, player status,
dsp-settings) come back as maps with keyword keys, parsed withclojure.data.json. - Native memory is freed automatically —
with-dsp/with-playerfree their handle, and everychar*/int16*the ABI returns is freed inside the binding. - Enum arguments accept either a keyword or the raw int (see
src/rockbox/ffi/enums.clj).
The FFM downcalls need
--enable-native-access=ALL-UNNAMED, wired into the
project’s deps.edn aliases. This binding lives under rockbox.ffi.* and
coexists cleanly with the separate rockbox-clj gRPC SDK (which owns the bare
rockbox.* namespaces).