Repository navigation
Releases: sonn-audio/node-upnp
Release list
v0.4.2
Opens the toolkit up to UPnP services beyond DLNA, and fixes a DIDL parsing bug that reached the media renderer.
GENA subscriber — start() now takes extraServices, so a caller can subscribe to a service the toolkit has no typed parser for, and onRaw reports every NOTIFY with its body and unescaped LastChange. Typed parsing is unchanged, but now only runs for AVTransport and RenderingControl instead of treating anything that isn't AVTransport as RenderingControl.
buildSoapRequest — instanceId: null omits the InstanceID argument, for services that take none (ZoneGroupTopology, DeviceProperties, ContentDirectory). The default is unchanged.
DIDL fix — <upnp:album[^>]*> also matched <upnp:albumArtURI>. Where a DIDL item lists the art before the album, reading upnp:album started at the wrong element and returned the art URI plus everything in between. This reaches UpnpMediaRenderer.onSetUri, so a control point using that field order handed us a garbage album name.
Also includes v0.4.1, which was tagged but never released: seek in ABS_TIME as well, and stop offering TRACK_NR.
v0.4.0
feat(controlpoint): ask a renderer which formats it accepts (v0.4.0) A UPnP renderer publishes what it can decode as protocolInfo entries in its ConnectionManager's Sink list, and asking is the only way to know whether a stream will play before sending it: a renderer handed something it cannot decode does not complain, it plays silence. Without this, a caller can only guess or be configured. - discovery now resolves the ConnectionManager control URL alongside AVTransport and RenderingControl; the service parsing was already generic, so this is one more lookup. - DlnaControlPoint.getSinkContentTypes() invokes GetProtocolInfo and returns the MIME types, cached — the sink list is a property of the device, not of a session. - parseSinkContentTypes() is exported and takes the *third colon-separated field* of each entry rather than searching the raw string, so `audio/flac` cannot be found inside some other token, and it keeps parameterised types (`audio/L16;rate=44100`) intact. Returns null — not an empty array — when the device has no ConnectionManager, does not answer, or answers unparseably. "It told us nothing" and "it accepts nothing" must not read the same to a caller deciding what to send.
v0.3.1
fix(ssdp): don't hang startup when the :1900 bind fails SsdpAdvertiser.start() awaited only the bind success callback, so when binding UDP :1900 errored — most often EADDRINUSE, when another UPnP/DLNA process on the host already holds the port — the promise never settled and start() hung forever. A caller that awaits start() during its own boot then stalls indefinitely instead of finishing. Treat a failed bind as best-effort: log a warning, leave the advertiser disabled, and resolve so the caller's startup continues without UPnP.
v0.3.0
feat(didl): carry performer and genre on containers DidlContainer could only express a title, art and a child count, so an album container had no way to say whose album it is. Controllers use dc:creator and upnp:artist to label and group album tiles, and browse-by-genre keys on upnp:genre — all three were unreachable for hosts using this module. Add artist, creator (falling back to artist) and genre, emitted in the DIDL document. Existing callers are unaffected: every field is optional and the element order for a container without them is unchanged.
v0.2.0
feat: UPnP Search action (v0.2.0) Add optional Search to the MediaServer: a ContentProvider.search() hook, the Search SOAP action + SCPD declaration, real GetSearchCapabilities (advertised only when the provider implements search — empty otherwise, the spec signal that stops control points from searching), and a parseSearchCriteria helper that extracts free-text terms + a coarse item/container class filter from the raw UPnP SearchCriteria grammar. Browse/Search share one response builder. Verified end-to-end over SOAP: SCPD declares Search, GetSearchCapabilities returns the fields, and a Search request reaches provider.search with the container id and unescaped criteria.
v0.1.0
feat: initial @sonn-audio/node-upnp module UPnP AV toolkit with zero runtime deps. Three app-agnostic frameworks: - UpnpMediaServer (inject a ContentProvider) - UpnpMediaRenderer (inject a RendererHandler) - DlnaControlPoint (push to an external renderer, with device-quirk handling) plus a shared SsdpAdvertiser and the underlying SSDP/SOAP/DIDL-Lite/GENA/ description/SCPD/ID3 primitives. Dual CJS+ESM build, typed. Includes a runnable demo consumer and a release workflow (npm publish --provenance on release).