--audio-format refuses a pin the advertisement does not carry with a message that blames the device:
E audio: --audio-format asked for FLAC 1ch 16-bit @ 48000 Hz, which output device 'null' does
not take -- refusing to start rather than play something else. Run with -l to see what the
device accepts.
The device takes it. What does not carry it is the advertisement, and the two are not the same set on the channels axis.
advertised_channels() (src/supported_formats.cpp:71-80) collapses the whole channels axis to a single value — 2 where the device lists 2, otherwise the narrowest count it reported. Rate and depth are different: supported_formats() crosses every value the device reported. So the advertisement carries one channel count and only one, and any pin naming another is refused, whether or not the device reports it.
Reproducing it needs no hardware — the null sink's capabilities are SinkCapabilities::permissive(), which is PROBE_CHANNELS{1, 2, 4, 6, 8} in full:
$ sendspin-cli -o null --audio-format flac:48000:16:1 --no-mdns --no-control
I audio: Advertising 65 formats for 'null': FLAC 2ch ...; OPUS 2ch ...; PCM 2ch ...
E audio: --audio-format asked for FLAC 1ch 16-bit @ 48000 Hz, which output device 'null' does not take ...
The Advertising line directly above states the real reason — 2ch, and nothing else. Confirmed for flac:48000:16:6, pcm:44100:24:1 and opus:48000:16:1 too; all three codecs, since all three take their channel count from the same function. flac:48000:16:2 pins fine.
The advice at the end of the message compounds it: -l reports the device's own channel count (out ch in the PortAudio table), so an operator who follows it is shown a number that confirms their pin and told the opposite.
Two shapes a fix could take, and they are not equivalent:
- Reword the refusal. Say the pin is not in the advertisement and print what was advertised, rather than asserting what the device does or does not take. Cheap, honest, and leaves current behaviour alone.
- Stop narrowing the axis. Advertise each channel count the device reported instead of one. That is a real behaviour change and wants its own argument —
advertised_channels()'s docstring is about not promising a width the device cannot take, which is the opposite direction from this, but it says nothing about why the narrower widths it can take are dropped.
The first is the one that makes the message true. The second is the one that makes the pin work, and is worth deciding on separately.
Same wrong-blame shape as the parse-time OPUS bug fixed in #31 — an error naming the device for something that was never the device's doing. Found reviewing that PR; the refusal message lands with it, while the advertised_channels() narrowing it collides with is already on main.
--audio-formatrefuses a pin the advertisement does not carry with a message that blames the device:The device takes it. What does not carry it is the advertisement, and the two are not the same set on the channels axis.
advertised_channels()(src/supported_formats.cpp:71-80) collapses the whole channels axis to a single value — 2 where the device lists 2, otherwise the narrowest count it reported. Rate and depth are different:supported_formats()crosses every value the device reported. So the advertisement carries one channel count and only one, and any pin naming another is refused, whether or not the device reports it.Reproducing it needs no hardware — the
nullsink's capabilities areSinkCapabilities::permissive(), which isPROBE_CHANNELS{1, 2, 4, 6, 8}in full:The
Advertisingline directly above states the real reason —2ch, and nothing else. Confirmed forflac:48000:16:6,pcm:44100:24:1andopus:48000:16:1too; all three codecs, since all three take their channel count from the same function.flac:48000:16:2pins fine.The advice at the end of the message compounds it:
-lreports the device's own channel count (out chin the PortAudio table), so an operator who follows it is shown a number that confirms their pin and told the opposite.Two shapes a fix could take, and they are not equivalent:
advertised_channels()'s docstring is about not promising a width the device cannot take, which is the opposite direction from this, but it says nothing about why the narrower widths it can take are dropped.The first is the one that makes the message true. The second is the one that makes the pin work, and is worth deciding on separately.
Same wrong-blame shape as the parse-time OPUS bug fixed in #31 — an error naming the device for something that was never the device's doing. Found reviewing that PR; the refusal message lands with it, while the
advertised_channels()narrowing it collides with is already onmain.