Skip to content

Advertise the formats in preference order - #22

Merged
chrisuthe merged 1 commit into
mainfrom
chrisuthe/task/order-the-advertised-formats-by-preference
Aug 24, 2026
Merged

chrisuthe merged 1 commit into
mainfrom
chrisuthe/task/order-the-advertised-formats-by-preference

Conversation

@chrisuthe

Copy link
Copy Markdown
Member

Why

supported_formats() built the advertisement in the order the device is probed
in — PROBE_RATES and PROBE_BIT_DEPTHS both run ascending — so the list went
out with 22050 Hz / 8-bit at the front.

That order is load-bearing. The spec has supported_formats in priority order,
first preferred, and servers read it that way: aiosendspin's
PlayerRole._ensure_preferred_format() takes filter_encodable_formats(...)[0]
and never looks further. So on any device permissive enough to accept the whole
ladder — the ALSA default PCM in particular, which on a PipeWire or PulseAudio
host converts rather than refuses — Music Assistant settled on FLAC 2 ch
16-bit @ 22050 Hz
and stayed there. (16-bit rather than 8-bit only because the
server drops the 8-bit entries itself: FLAC_BIT_DEPTHS = {16, 24, 32}.)

The set was never the problem. The order was.

What changed

supported_formats() returns exactly the same entries, permuted, ranked on
three named ladders:

axis order why
codec FLAC, OPUS, PCM lossless first; Opus is the fallback worth having where bandwidth is the constraint; PCM costs the most bytes for no gain over FLAC
rate 48000, 44100, 96000, 88200, 192000, 176400, 32000, 22050 48 kHz leads so the preferred rate is also the one rate Opus can be carried at, and the ladder stays in that family; the two rates below CD go last
depth 16, 24, 32, 8 16-bit is what most streams are mastered at; 8-bit can never lead

A permissive device now leads with FLAC 2 ch 16-bit @ 48 kHz, and one that takes
neither 48 nor 44.1 kHz falls through to its best remaining rate rather than
its lowest.

The startup digest reads as the ranking it describes:

I audio: Advertising 65 formats for 'null': FLAC 2ch 16/24/32/8-bit @ 48000/44100/96000/88200/192000/176400/32000/22050 Hz; OPUS 2ch 16-bit @ 48000 Hz; PCM 2ch 16/24/32/8-bit @ 48000/44100/96000/88200/192000/176400/32000/22050 Hz

Ordering only, never narrowing

Dropping entries would be the easy way to force a default, and it would be
wrong: the same advertised list is what Music Assistant builds its per-player
Preferred format menu from, so narrowing it takes choices away from anyone
picking by hand.

The ranking is a std::stable_sort keyed on ladder position, which is a
permutation by construction — it cannot add or drop an entry — and a rate or
depth outside PROBE_RATES/PROBE_BIT_DEPTHS sorts to the back rather than
disappearing. SupportedFormats.RankingOnlyPermutesWhatIsAdvertised holds that
against a spelled-out copy of the old ascending crossing, over ten capability
sets including the degenerate ones.

Tests

New, alongside that permutation test:

  • ThePermissiveSetLeadsWithFlacStereo48kHz16Bit
  • ADeviceWithNeitherPreferredRateLeadsWithItsBestRemaining ({22050, 96000})
  • RatesAndDepthsGoOutRanked
  • OpusSitsAfterEveryFlacEntryAndBeforeEveryPcmEntry
  • ARateTheLaddersDoNotNameIsAdvertisedLastRatherThanDropped

DescribeFormats.GroupsTheAxesPerCodec followed the old positional order and is
updated — it now also asserts the codec groups appear in ranked order, which it
did not check before.

ctest is 354/354 green with -DSENDSPIN_CLI_BUILD_TESTS=ON -DSENDSPIN_CLI_WERROR=ON, the same configure line CI uses.

The protocol has `supported_formats` in priority order, first preferred, and
servers read it that way -- Music Assistant's `aiosendspin` takes the first
entry it can encode and never looks further. supported_formats() emitted the
probe ladders in the ascending order they are probed in, so it nominated the
worst format the device would take: FLAC at 22050 Hz on ALSA `default`, whose
plugin accepts the whole ladder.

Rank the same entries on three named ladders instead -- codec, rate, depth.
A permissive device now leads with FLAC 2 ch 16-bit @ 48 kHz, and one taking
neither 48 nor 44.1 kHz falls to its best remaining rate rather than its lowest.

Ordering only: a stable sort keyed on ladder position is a permutation by
construction, so nothing is dropped and a rate outside PROBE_RATES sorts to the
back rather than disappearing. The advertisement is also the menu a user picks
a format from by hand, which is why it must not be narrowed.
@chrisuthe
chrisuthe merged commit 28c2fe5 into main Aug 24, 2026
10 checks passed
@chrisuthe
chrisuthe deleted the chrisuthe/task/order-the-advertised-formats-by-preference branch August 24, 2026 15:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant