sonn docs GitHub

using it

Zones & outputs

A zone is a single device you play music on. Zones are optional: skip them entirely if you only want to serve your content to other apps and devices — that is what Access does. Loxone is the exception: it drives zones by design, so with the Loxone integration on, zones are always active and come from the Miniserver.

Adding zones gets you:

  • Central control: every zone in one place — web player, Admin UI, or a Loxone app
  • Grouping: several zones in perfect sync, regrouped on the fly
  • Receivers: features on a device that it doesn't support natively (below)

Each zone plays to exactly one device, with a per-zone equalizer, volume limits, recents and favourites, and optional power management. You can add up to 24 zones — the same ceiling a Loxone Audio Server has.

Arrangements

Under Zones you pick one of three arrangements, and can change it later:

  • Disabled — no zones. The server shares your content through Access only. This is how a fresh install starts.
  • Set up here — you add zones yourself: the speakers and rooms you name, group and cast to.
  • Loxone integrated — your Miniserver pushes which zones exist and their names; you still configure each one's output and receivers here. See Loxone.

Outputs

Sendspin, Google Cast (Chromecast), Sonos, AirPlay, DLNA/UPnP renderers, Snapcast, Squeezelite, and Music Assistant players.

Sendspin, and the signal path

sonn is built around one idea: the audio that leaves your library should reach the player exactly as it was recorded. Every step in between — resampling, changing bit depth, re-encoding, gain — can only lose something or alter it, so the server's job is to do none of them unless something makes that impossible.

Sendspin is the output where that can be guaranteed, because its format is negotiated per track. A Sendspin client tells the server which sample rates and bit depths it accepts, and the server then follows the source: a 24-bit/192 kHz FLAC is streamed as 24-bit/192 kHz, a 16-bit CD rip as 16-bit/44.1 kHz, with no resampler in the path at all. Sendspin with a USB DAC is therefore the perfect audio path: the file's own samples travel over the network, the client hands them to the DAC untouched, and the DAC clocks them at the rate they were recorded at.

The other outputs take a fixed format, so playing anything that does not match it means a conversion. That is not a defect — it is what those protocols are — and the conversion is a good one (SoX resampler, 28-bit precision). It is simply not the same as not converting.

Two things deliberately stay out of the audio path either way:

  • Volume is applied by the device, not by the server, so turning it down costs no resolution.
  • The equalizer and crossfade are per zone and off by default. Switching either on is a choice to process the audio, and the player says so while it is on.

The web player's technical view shows all of this per zone, live: the source format, every stage that touched the audio, and the verdict — bit-perfect, untouched, or altered, with the reason. If it says "resampled — this output is fixed at 48 kHz", that is the output's ceiling talking, not a setting you missed.

And if you just want music: use whatever output you already have. A Chromecast in the kitchen, an old Sonos, a pair of Snapcast speakers on a Raspberry Pi — all of it works, all of it sounds good, and none of it needs a thought about sample rates.

Receivers

A receiver lets a phone or app play to a zone. The stream lands on the server, which sends it on to that zone's output — the device itself needs no support for the protocol. Point AirPlay or Spotify Connect at a pair of Snapcast speakers or an old amplifier on a line-out, and it works.

Available receivers: Spotify Connect, AirPlay, DLNA, line-in, Music Assistant — and one zone can offer them all at once.

Grouping

Any rooms play in sync, regrouped on the fly — from the app, the wall panel, or a Loxone scene. The kitchen joins the terrace for dinner and leaves again after.

Power management

A zone can switch an amplifier or power supply on when it starts and off after it stops, over either a GPIO line (using libgpiod's gpioset) or a USB HID relay board (CRelay). Configure it per zone under Zones.

From Docker, the container needs access to the host devices, or calls that work on a host shell will still fail inside the container. Expose the relevant /dev/gpiochip* and/or /dev/hidraw* entries, or run the container with elevated device access.

GPIO line offsets are the most common source of trouble: configure the chip plus the line offset within that chip. On a Raspberry Pi 4, header GPIO22 is typically line 22 on /dev/gpiochip0. The old sysfs-style global number such as 534 is not what gpioset expects, and a correctly wired relay will do nothing.

Shared amps and PSUs

When several zones share one amplifier, switch it as a group instead of per zone. Configure the group under groups.powerGroups[], set each zone's powerManager.powerGroupId to that group id, and give the group its own powerManager.gpio or powerManager.crelay. The shared output turns on while any member is active and off after the last one stops.

Timing

  • activeModes sets which states count as active (default ['play'], so pause switches off)
  • playbackPreDelayMs inserts a pre-delay so an amp can wake before the first sound
  • offDelayMs delays switching off so short gaps don't cycle the amplifier (default 5 minutes; set offDelayEnabled: false for immediate)

HTTP power control

For devices that need more than a simple GET, url.offMethod and url.offBody can be used. The method defaults to GET; a configured body is sent as JSON. The ON side is optional — for example for an autosensing amplifier:

{
  "url": {
    "enabled": true,
    "offUrl": "http://192.168.1.43:8080/BeoDevice/powerManagement/standby",
    "offMethod": "PUT",
    "offBody": { "standby": { "powerState": "standby" } }
  }
}

Bang & Olufsen remotes

A zone can be controlled with a Beoremote One — bidirectionally. The server builds the menu the remote shows: radio stations and room favourites appear directly as playable items on the remote's screen, and any line-in device such as a turntable or CD player is listed too. Each of the coloured and dot buttons starts something in that room, and play, pause and skip route to whatever the room is playing, including a line-in device that can be driven.

Volume stays on the device itself, so it keeps working even if the server is briefly unreachable. Like line-in, this needs a separate helper — the remote pairs with it over Bluetooth, and it forwards the keypresses to this server. It registers itself the same way, so once it is running you only pick which remote belongs to which zone in the Admin UI.