Add cancellable Quick Connect pairing and shared connection guards for Jellyfin and Subsonic. Bound connection attempts, validate library access before saving credentials, and report per-provider connection and synchronization status.
cx
Stage 5's first half. Sibling of `qbz-plex` and deliberately shaped like
it, so `qbz-source`'s JellyfinSource will read like PlexSource:
frontend-agnostic, HTTP + DTOs, no cache schema and no settings store.
Three measured facts shape the file, and each one is a comment because
each one is a decision somebody could otherwise undo:
- `?static=true` is bit-perfect. Verified by md5 against the file on the
server's own disk, not inferred from a content type. `is_direct_
response` encodes the tell a transcode leaves — chunked with no
Content-Length — so a server-side policy silently resampling a hi-res
track is caught rather than played.
- Quality costs 45.8 s per 4924 tracks and there is no cheaper path.
`Fields=MediaStreams` trims 29% of the bytes and saves nothing: the
cost is server-side media-info hydration. The scan will own that
knowingly, which is why `track_count` exists to give a progress
denominator.
- Cover urls need no credentials, so unlike a Plex thumb they are STABLE
and their cache key can be the url itself.
`stream_url` / `image_url` are free functions rather than methods. Two
reasons and both are load-bearing: `Source::artwork_token` may not touch
the network by contract, and a `reqwest::Client` cannot even be
CONSTRUCTED without a rustls provider — which a unit test does not have.
The mapper picks the audio stream BY TYPE, not by position: an embedded
cover rides in the same MediaStreams array as an `mjpeg` with BitDepth 8,
and taking [0] would badge a 24-bit FLAC as 8-bit. A lossy row keeps an
absent bit depth rather than defaulting to 16, which would badge every
MP3 as CD quality.
10 unit tests, plus 5 LIVE tests that skip unless QBZ_JELLYFIN_URL names
a server. The unit tests prove the JSON shape is understood; only the
live ones can prove the endpoint still exists, the token still opens it,
and the stream is still direct. Against Jellyfin 10.11.11: 5/5 — 500-row
page with 221 real bit depths of 4924 total, a Range request answered
206 with a `fLaC` bitstream, a tokenless cover, and a future-dated delta
returning zero.
cc