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

# Ruby

> Rockbox DSP, metadata, and playback in Ruby via fiddle — no native extension to compile.

```sh theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
gem install rockbox_ffi
```

Requires **Ruby 2.6+**. The binding uses [`fiddle`](https://docs.ruby-lang.org/en/master/Fiddle.html)
(Ruby stdlib) to `dlopen` the shared library — **no native extension is
compiled**. The published gem bundles a prebuilt `librockbox_ffi`; from a repo
checkout the loader walks up to `target/release/` (override with
`ROCKBOX_FFI_LIB`).

## Quick start

```ruby theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
require "rockbox_ffi"

# --- metadata ---------------------------------------------------------
meta = RockboxFFI::Metadata.read("song.flac")
puts "#{meta[:artist]} — #{meta[:title]} (#{meta[:duration_ms]} ms)"
RockboxFFI::Metadata.probe("track.opus")   # => "Opus"

# --- DSP (interleaved stereo int16) -----------------------------------
RockboxFFI::Dsp.open(44_100) do |dsp|
  dsp.eq_enable(true)
  dsp.set_eq_band(0, 60, 0.7, 3.0)
  dsp.set_replaygain(RockboxFFI::DspReplayGainMode::TRACK, true, 0.0)
  dsp.set_replaygain_gains(track_gain_db: -6.02)  # halves amplitude
  processed = dsp.process(samples)                # Array<Integer>
end

# --- playback (needs an output device) --------------------------------
# Mutating Player setters return self, so calls chain fluently. The queue
# accepts local file paths, http(s):// URLs, and live-radio / streaming URLs.
RockboxFFI::Player.open(volume: 0.8) do |player|
  player
    .set_queue(["a.flac", "https://example.com/b.mp3", "http://stream.example/live"])
    .set_eq_preset(RockboxFFI::EqPreset::BASS_BOOST)
    .set_shuffle(true)
    .set_repeat(RockboxFFI::RepeatMode::ALL)
    .set_balance(0)                     # -100 full left … +100 full right, 0 = centre
    .play

  # --- DSP chain (all setters chainable) ------------------------------
  player
    .set_eq_enabled(true)
    .set_eq_band(0, 60, 0.7, 3.0)       # band, cutoff_hz, q, gain_db
    .set_eq_precut(3.0)
    .set_bass(4).set_treble(2)          # or set_tone(bass, treble, cuts…)
    .set_crossfeed(RockboxFFI::CrossfeedMode::MEIER, 0, 0, 0, 0)
    .set_channel_mode(RockboxFFI::ChannelMode::STEREO)

  player.eq_enabled?      # => true
  player.shuffle_enabled? # => true
  player.repeat           # => 2 (RepeatMode::ALL)
  player.dsp_settings     # => {eq_enabled: true, ...}
  player.status           # => {state: "playing", index: 0, ...}
end

# --- decode a file to PCM (interleaved stereo int16) ------------------
RockboxFFI::Decoder.open("song.flac") do |dec|
  dec.metadata[:title]                # same shape as Metadata.read
  dec.seek_ms(30_000)                 # optional: jump 30 s in

  dec.each_chunk do |samples, sample_rate|
    # samples: Array<Integer> S16LE stereo; sample_rate: Hz
    handle(samples, sample_rate)
  end

  done, code = dec.finished            # code: 0 = clean end, negative = codec error
  warn "codec error #{code}" if done && code.negative?
end
```

<Warning>
  The Rockbox codec engine is **process-wide — only one `Decoder` decodes at a
  time**. A second `Decoder.open` blocks until the first is freed (via `#close`
  or the block form). Drive a decoder from a single thread.
</Warning>

## API

| Namespace              | Contents                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RockboxFFI::Metadata` | `read(path) => Hash`, `probe(filename) => String \| nil`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `RockboxFFI::Dsp`      | EQ / tone / surround / compressor / ReplayGain, `process(samples)`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `RockboxFFI::Player`   | queue (`set_queue` / `enqueue` / `insert` — local paths, `http(s)://` URLs, live-radio / streaming URLs), transport, `set_volume` / `set_balance` / `balance`, `set_shuffle` / `shuffle_enabled?`, `set_repeat` / `repeat`, crossfade, ReplayGain, full DSP chain (`set_eq_enabled` / `eq_enabled?`, `set_eq_preset`, `set_eq_band`, `set_eq_precut`, `set_tone` / `set_bass` / `set_treble` / `set_bass_cutoff` / `set_treble_cutoff`, `set_crossfeed`, `set_surround`, `set_channel_mode` / `set_stereo_width`, `set_bass_enhancement`, `set_fatigue_reduction`, `set_compressor`, `set_dither`, `set_pitch`, `dsp_settings`), m3u/resume, `status => Hash`. Mutating setters return `self` for chaining. |
| `RockboxFFI::Decoder`  | streaming file decoder: `open(path)` / `close`, `metadata => Hash`, `next_chunk` / `each_chunk => [samples, sample_rate]`, `seek_ms`, `elapsed_ms`, `finished => [done, code]`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `RockboxFFI::*Mode`    | `DspReplayGainMode`, `ReplayGainMode`, `RepeatMode`, `CrossfadeMode`, `MixMode`, `CrossfeedMode`, `ChannelMode`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `RockboxFFI::EqPreset` | 21 built-in EQ presets (`FLAT`, `BASS_BOOST`, `ROCK`, `JAZZ`, `VOCAL_BOOST`, …) for `Player#set_eq_preset`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |

* Rich values (metadata, status, `dsp_settings`) come back as **Hashes with
  symbol keys**.
* Sample buffers are `Array<Integer>` of interleaved-stereo signed 16-bit
  samples.
* `Dsp` and `Player` own native resources. Use the block form (`.open`) to
  close them automatically, or call `#close`; a GC finalizer is the backstop.
* The `Player` DSP chain mirrors Rockbox's own sound settings — see the
  [official Rockbox manual](https://download.rockbox.org/daily/manual/rockbox-ipodvideo/rockbox-buildch6.html)
  for what each control does.

<Warning>
  `Dsp#set_replaygain` and `Player#set_replaygain` take **different mode
  integers**. Use the named constants — `DspReplayGainMode` for the DSP,
  `ReplayGainMode` for the player. See [the overview](/bindings/overview#the-one-thing-to-know-two-replaygain-encodings).
</Warning>

## Interactive console

```sh theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
bundle exec rake console        # or: ./bin/console
```

Drops into IRB with `RockboxFFI` loaded and `FIXTURE` pointing at a sample
track — Tab autocompletion and syntax highlighting are on by default:

```ruby theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
RockboxFFI::Metadata.read(FIXTURE)[:title]        # => "Speak"
p = RockboxFFI::Player.new(volume: 0.6)
p.set_queue([FIXTURE]); p.play
p.status[:state]                                  # => "playing"
```
