Skip to main content
The Swift package ships the engine two ways, from one shared implementation (RockboxFFICore — the public API plus a dlsym loader). Pick the product that fits how you want to distribute: Both drive the same typed @convention(c) closures; the loader resolves the rb_* symbols from the process image (static) or from a dlopened library (dynamic — the same approach as the Ruby and Python bindings), decided at runtime. Build the native artifacts once from the repo root — this produces both librockbox_ffi.a (bundled by RockboxFFI) and librockbox_ffi.dylib (loaded by RockboxFFIDynamic, which honours ROCKBOX_FFI_LIB, else walks up to target/release):

Distribution

The bindings-release workflow publishes reproducible, prebuilt Swift artifacts to each GitHub Release:

RockboxFFI.xcframework.zip

Static library + header for macOS (universal), iOS (arm64 device), and the iOS simulator (arm64 + x86_64). Drop it into Xcode or reference it as a SwiftPM binaryTarget.

rockbox-ffi-swift-macos.tar.gz

The SwiftPM package with the universal macOS archive vendored under Libs/, so swift build works turnkey off the monorepo (macOS only; iOS consumers use the xcframework).
The static RockboxFFI product force-references each rb_* entry point with a -u <symbol> linker flag (it reaches them via dlsym, so -dead_strip would otherwise drop them). If you consume the xcframework through this loader on iOS, keep those flags. iOS apps must also link AudioToolbox / AVFoundation and set up an AVAudioSession before using Player.

Quick start

setQueue / enqueue / insert accept local file paths, finite http(s):// URLs, and live-radio / streaming URLs interchangeably.

Player DSP chain

The Player exposes the full Rockbox DSP pipeline. Every setter is @discardableResult and returns Self, so they compose in one fluent chain (the statement-style calls still compile unchanged). Read the live state back with dspSettings() (a [String: Any] snapshot).

Player API

setBalance(_:) / balance take a stereo balance of -100 (full left) to +100 (full right), with 0 = centre. Relevant enums: RepeatMode (off/one/all), EqPreset (21 cases, flatvocalBoost), CrossfeedMode (off/meier/custom), ChannelMode (stereo/mono/custom/monoLeft/monoRight/karaoke/swap), CrossfadeMode, and MixMode.
The DSP controls mirror Rockbox’s own Sound Settings. For what each parameter does, see the official Rockbox manual.

Decoder

Decoder is a streaming decoder: it decodes one local audio file to interleaved-stereo S16LE PCM, one chunk at a time, through the Rockbox codec engine. Open it with a path; the native handle is freed on close() or deinit.
The Rockbox codec state is process-wide — only one Decoder decodes at a time. Constructing a second Decoder blocks until the first is freed (via close() or deinit).

Notes

  • Rich values (metadata, player status) come back as [String: Any], parsed from the ABI’s JSON with JSONSerialization.
  • Native memory is freed inside the binding — close() / deinit for handles; every char* / int16* return is freed after copying.
Two ReplayGain encodings — use DspReplayGainMode (track 0, album 1, shuffle 2, off 3) for Dsp, and ReplayGainMode (off 0, track 1, album 2) for Player. See the overview.
Keep Sources/RockboxFFICore/Loader.swift — and the ffiSymbols list in Package.swift — in sync with include/rockbox_ffi.h. The loader declares each function signature by hand, and the static product force-links each symbol by name.