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

# Go

> Rockbox DSP, metadata, and playback in Go via purego over the librockbox_ffi C ABI — no cgo.

```sh theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
go get github.com/tsirysndr/rockboxd/bindings/go
```

Requires **Go 1.22+**. Calls the native engine through
[`purego`](https://github.com/ebitengine/purego) — **no cgo and no C
toolchain**; the package `dlopen`s a prebuilt `librockbox_ffi` at process
start. From a repo checkout the loader walks up to `target/release/`; override
with `ROCKBOX_FFI_LIB`.

## Quick start

```go theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
package main

import (
	"fmt"

	rockbox "github.com/tsirysndr/rockboxd/bindings/go"
)

func main() {
	// --- metadata -----------------------------------------------------
	meta, _ := rockbox.Metadata.Read("song.flac")
	fmt.Println(meta.Artist, "—", meta.Title, meta.DurationMs, "ms")
	label, _ := rockbox.Metadata.Probe("track.opus") // "Opus" (no I/O, extension guess)
	fmt.Println(label)

	// --- DSP: process interleaved stereo int16 ------------------------
	dsp, _ := rockbox.NewDsp(44_100)
	defer dsp.Close()
	dsp.EqEnable(true)
	dsp.SetEqBand(0, 60, 0.7, 3.0)
	dsp.SetReplaygain(rockbox.DspReplayGainTrack, true, 0.0)
	dsp.SetReplaygainGains(rockbox.Opt(-6.02), nil, nil, nil) // −6 dB ≈ half amplitude
	processed, _ := dsp.Process(samples)                      // []int16
	_ = processed

	// --- playback (needs an output device) ----------------------------
	// Functional-options constructor (or use NewPlayer(Config) directly):
	player, _ := rockbox.New(
		rockbox.WithVolume(0.8),
		rockbox.WithReplayGain(rockbox.ReplayGainTrack, 0.0, true),
		rockbox.WithCrossfade(rockbox.CrossfadeAlways, 0, 2000, 0, 2000, rockbox.MixCrossfade),
		rockbox.WithResumeFile("state.m3u8"),
	)
	defer player.Close()

	// DSP chain — EQ presets, tone, crossfeed, compressor, … (setters return nothing)
	player.SetEqEnabled(true)
	player.SetEqPreset(rockbox.EqPresetBassBoost)

	// Shuffle & repeat
	player.SetShuffle(true)
	player.SetRepeat(rockbox.RepeatAll)

	// Queue entries may be local paths, http(s):// URLs, or live-radio / streaming URLs.
	player.SetQueue([]string{"a.flac", "https://example.com/b.mp3", "https://stream.example/radio"})
	player.Play()
	st, _ := player.Status() // &Status{State: "playing", Index: 0, Shuffle: true, Repeat: "all", ...}
	fmt.Println(st.State, st.Shuffle, st.Repeat)
}
```

## Decode a file to PCM

`OpenDecoder` runs a file through the Rockbox codec engine and hands back
interleaved-stereo S16LE PCM one chunk at a time — decode without an output
device.

```go theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
dec, err := rockbox.OpenDecoder("song.flac")
if err != nil {
	log.Fatal(err)
}
defer dec.Close() // safe to call twice

meta, _ := dec.Metadata() // map[string]any, same shape as Metadata.Read
fmt.Println(meta["title"])

for {
	samples, rate, ok := dec.NextChunk() // []int16, sample rate, ok=false at EOF
	if !ok {
		break
	}
	_ = samples
	_ = rate
	// dec.SeekMs(30_000); dec.ElapsedMs()
}

if done, code := dec.Finished(); done && code < 0 {
	log.Printf("codec error: %d", code) // 0 = clean end, negative = codec error
}
```

<Warning>
  The codec engine is **process-wide**: only one `Decoder` may decode at a
  time, and always from a single goroutine. A second `OpenDecoder` blocks until
  the first is closed.
</Warning>

## API

| Symbol                                          | Contents                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rockbox.Metadata`                              | `Read(path) (*Meta, error)`, `Probe(name) (string, bool)`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `rockbox.NewDsp` → `*Dsp`                       | EQ / tone / surround / compressor / ReplayGain, `Process([]int16)`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| `rockbox.New` / `rockbox.NewPlayer` → `*Player` | **Construct:** `New(WithVolume, WithReplayGain, WithCrossfade, WithResumeFile, …)` (functional options) or `NewPlayer(Config)`. **Transport:** `Play` / `Pause` / `Toggle` / `Stop` / `Next` / `Previous` / `SkipTo` / `SeekMs`. **Queue:** `SetQueue` / `Enqueue` / `Insert` / `Queue` (local paths, `http(s)://`, live-radio / streaming URLs). **Shuffle & repeat:** `SetShuffle` / `IsShuffleEnabled`, `SetRepeat` / `Repeat`. **DSP chain:** `SetEqEnabled` / `IsEqEnabled` / `SetEqPreset` / `SetEqBand` / `SetEqPrecut`, `SetTone` / `SetBass` / `SetTreble` / `SetBassCutoff` / `SetTrebleCutoff`, `SetCrossfeed`, `SetSurround`, `SetChannelMode` / `SetStereoWidth`, `SetBassEnhancement`, `SetFatigueReduction`, `SetCompressor`, `SetDither`, `SetPitch`, `DSPSettings()`. **Volume/balance/ReplayGain/crossfade:** `SetVolume` / `Volume`, `SetBalance` / `Balance`, `SetReplaygain`, `SetCrossfade`. **Resume / m3u:** `Resume` / `SaveResume` / `ClearResume`, `LoadM3u` / `ImportM3u` / `ExportM3u`. **State:** `Status()`. |
| `rockbox.OpenDecoder` → `*Decoder`              | Stream-decode a file to interleaved-stereo S16LE PCM via the Rockbox codec engine: `Metadata()`, `NextChunk() ([]int16, uint32, bool)`, `SeekMs` / `ElapsedMs`, `Finished() (bool, int32)`. **Codec state is process-wide** — only one Decoder decodes at a time, from one goroutine.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `rockbox.*` consts                              | `DspReplayGainMode`, `ReplayGainMode`, `RepeatMode` (Off/One/All), `EqPreset` (21 presets), `CrossfeedMode`, `ChannelMode`, `CrossfadeMode`, `MixMode`, `InsertPosition`, `ChannelConfig`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

* **Handles** own native resources — `defer dsp.Close()` / `defer player.Close()`
  frees them.
* **Rich values** (metadata, status) decode into typed structs (`Meta`,
  `Status`); optional tags are `nil`-able pointer fields.
* **Sample buffers** are `[]int16` of interleaved-stereo signed 16-bit samples.
* **DSP semantics** (EQ bands, tone, crossfeed, compressor, …) mirror Rockbox's own settings — see the [official Rockbox manual](https://download.rockbox.org/daily/manual/rockbox-ipodvideo/rockbox-buildch6.html) for what each control does.

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

## Smoke test

```sh theme={"theme":{"light":"catppuccin-latte","dark":"min-dark"}}
cd bindings/go
go run ./examples/smoke   # metadata + DSP + player checks
go test ./...
```
