Rename client state to a boolean available - #115
Merged
Conversation
This was referenced Jul 2, 2026
kahrendt
pushed a commit
that referenced
this pull request
Jul 6, 2026
This PR and one more (the `state` to `available` rename in #115) are the last client-breaking changes to the spec. There *might* be more if we hit issues with the newly added encryption support, but apart from that these two *should* cover everything I found. There are also some breaking changes I'm still working out, but those are strictly server-implementation breaking. Clients will not have to adjust anything. Specifically, this PR addresses the following gaps: - `client/goodbye`: a client switching servers MUST send reason `another_server`, and clients SHOULD default to `shutdown` when the device is powering off or otherwise not coming back. - Discovery: the `path` TXT key is now REQUIRED (value still recommends `/sendspin`). - Pairing: the initial static PIN MUST be device-specific (e.g. randomly generated and printed), never a fixed shared default. - Custom roles: `_`-prefixed role names SHOULD carry a vendor-specific prefix to avoid collisions. - Player state: persisting `volume`/`muted` across reboots is RECOMMENDED, and a server MUST NOT assume they are unchanged after a reconnect. - Streaming: `codec_header` is specified as standard Base64 (the rest of the spec uses base64url), clarifying the existing encoding rather than changing the wire format. - `external_source`: a client whose output is taken by a non-Sendspin activity reports `external_source` only when it will not yield (the server then cannot stream to it, since `stream/start` is gated on `synchronized`); a client that can be interrupted instead stays `synchronized` so the server can take over at any time. - Source role: dropped `source@v1_support.supported_formats`; a source declares its format per stream in `client_stream/start` and the server accepts any format. - Forward compatibility: clients MUST ignore unrecognized `payload` fields, and MUST NOT send fields the spec doesn't define for a message (beyond the `_`-prefixed application-specific role objects a message already permits). Undefined field names stay reserved to the spec, so a client can't squat on a name a later version might claim. - `stream/request-format`: a player MUST only request a format listed in its `supported_formats`, so a format request can never name something the client cannot decode.
maximmaxim345
force-pushed
the
fix/available-state
branch
from
July 7, 2026 06:58
5b517e1 to
feec536
Compare
maximmaxim345
marked this pull request as ready for review
July 7, 2026 06:59
maximmaxim345
added a commit
to Sendspin/aiosendspin
that referenced
this pull request
Jul 14, 2026
A batch of protocol-conformance and correctness fixes. This PR doesn't include changes to encryption/authentication, that will follow in a later PR. ## Changes - **Adopt client/state `available` boolean.** Replace the client state enum with the spec's `available` boolean end to end: the SDK sends only `available`, the server tracks a boolean and notifies roles via `on_availability_changed`. A legacy `state` enum on the wire normalizes to `available`, with only `external_source` treated as unavailable so a client reporting an error is not ejected from its group. Spec: [#115](Sendspin/spec#115), [#113](Sendspin/spec#113). - **Stamp `server_transmitted` on stream lifecycle messages.** Add `server_transmitted` to `stream/start`, `stream/clear`, and `stream/end`, stamped at actual send time, matching `server/time`. Spec: [#106](Sendspin/spec#106). - **Floor send-ahead at `min_buffer`.** Live streams floor at `min_buffer + static` instead of extending to `required_lead` (which added latency a realtime queue cannot recover); buffered streams keep the `min_buffer` floor instead of dropping to `required_lead + static`. Spec: [#107](Sendspin/spec#107). - **Document `seek_relative` clamping** as the application's responsibility. Spec: [#103](Sendspin/spec#103). - **Track all unimplemented client roles**, not just spec-support families (controller/metadata/color and wholly-unknown families), still excluding `_`-prefixed custom roles. Spec: [#113](Sendspin/spec#113). - **Make server reconnect per-goodbye-reason and activity-aware.** Retry a server-initiated connection only on restart or concurrent_attempt; on a drop with no goodbye, assume restart when the connection was idle or carried playback, else treat it as a session end. Spec: [#113](Sendspin/spec#113), [#116](Sendspin/spec#116). - **Default the visualizer pitch feature off** (rides reserved binary type 21; kept as an opt-in extension). Spec: [#86](Sendspin/spec#86). - **Mask the beat downbeat bit** unless the role tracks downbeats. Spec: [#86](Sendspin/spec#86). - **Remember visualizer request-format when no stream is active** instead of starting a stream in response (which the spec forbids). Mirrors player/artwork. Spec: [#112](Sendspin/spec#112). - **Note peak-cadence deviation from spec** with a TODO (peak onset detection currently runs only at the periodic `rate_max` hop). Spec: [#86](Sendspin/spec#86). - **Hoist binary-type sets out of the per-frame dispatch path** (reuse module-level frozensets instead of rebuilding per binary frame). - **Reset `_stream_started` after the artwork deactivate stream/end**, matching the other stream roles.
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The remaining client-breaking change after #113: it replaces the
client/statestateenum (synchronized|external_source) with a booleanavailable.available: true- operational and ready to participate; for a player or source this means its clock has converged. Formerlysynchronized.available: false- the client's output is in use by an external system. Formerlyexternal_source.Pure terminology rename with no behavioral change. The group-leave behavior it builds on (the
available: falsethenavailable: trueflip, and the no-auto-rejoin rule) already landed in #113.