[go: up one dir, main page]

audio renderer probe

tutti

An audio renderer is a device that plays sound when a control point hands it a URL. Sonos, WiiM, Eversolo, Yamaha receivers, smart speakers — most of them speak UPnP / DLNA. They shouldall just work. They don't. tutti asks them why.

Why this exists

A renderer that won't show up in your music client is almost always a parser mismatch, not a network problem. The device announces itself fine; the client's library rejects it because the descriptor doesn't match what the parser expected. Different libraries reject different devices. A device might cast cleanly from Sonos's app but stay invisible to a Subsonic client running on the same LAN.

No tool tells you which library rejected your device and on what grounds. tutti is that tool: it walks the network, runs the device's descriptor through every Go control-point library it knows about, drives a real cast end to end, and writes a paste-ready bundle of evidence to disk. The corpus on this site is what tutti has captured against real devices on real LANs.

How streaming is supposed to work

Five stages, with the control point on the left and the renderer on the right. Solid moss arrows are control-point initiated; dashed grey arrows are the device's response.

CONTROL POINTRENDERERNETWORKyour music applooking for renderers1. M-SEARCH ssdp:discoverUDP multicast 239.255.255.250:19002. HTTP/1.1 responseUSN, LOCATION, SERVER, BOOTID"here I am"describes its services3. GET <LOCATION>fetch the device descriptor XML4. <root>…</root>deviceType, services, control URLsparses the descriptorfinds AVTransport servicemost failures land here5. SOAP: SetAVTransportURI+ DIDL-Lite envelope (title, art, format)6. SOAP: Playdevice transitions: STOPPED → TRANSITIONING → PLAYINGrenderer fetches the URLdecodes, sends to DACHTTP GET, separate TCP connection7. SOAP: GetTransportInfo / GetPositionInfopolls state + position; updates UI

Where it goes wrong

tutti exists because each of these failure modes is invisible from the music app's UI — the device just doesn't show up, or shows up and then doesn't play. The corpus surfaces them explicitly.

stage 4

Parser mismatch

The library walks the descriptor and rejects the device because deviceType isn't the exact string it expected, or the control URL didn't parse, or a UUID-shaped field doesn't match RFC 4122. Different libraries reject different shapes. The user sees: device missing from picker.

tutti shows: per-library decision matrix on each device's page.

stage 5

Format under-announced

Device's GetProtocolInfo Sink list omits a format the device actually plays (DSD on Plutinosoft-derived stacks is the canonical case). Control points that intersect their request format against the Sink list will never offer it. The user sees: format greyed out, even though it works in another app.

tutti shows: announced sinks vs. drive-test outcomes side by side.

stage 5

Metadata surface mismatch

Device renders the artist/title from the file's embedded tags rather than the DIDL-Lite envelope the control point sent — or vice versa. The user sees: wrong song name or missing cover art on the device's display, even though playback is fine.

tutti shows: round-trip status (matched / mismatched / absent) and which surface the device honored.

What tutti's seen so far

Every device profiled, every capture, every drive transcript. Add yours: run the binary against your LAN, paste the bundle as a merge request.