Follow-up to the alignment question in #177: stream/request-format carries dynamically changing values, which per the CONTRIBUTING rule belong in client/state. Looking closer, the whole message should go, because it is a request in name only.
A decline is invisible: when the server cannot honor a request, the stream continues and the request MUST NOT be treated as an error, so no message ever tells the client it was declined. The client learns the operative configuration exclusively from stream/start, which is exactly how state assertions would work. With no stream active the server SHOULD already remember the requested format for the next stream, so the request is de facto state, stored on the wrong side with a weaker guarantee. And no role lets a client request a format it cannot accept (player requests MUST come from supported_formats), so the fields always describe the client's current wishes.
Proposed shape: player gains an optional format preference in its state object (absent means the server picks per supported_formats); artwork moves the per-channel source/format/width/height into a state channels array, with client/hello shrinking to a channel count; visualizer moves types, rate_max and spectrum into state, with hello keeping only buffer_capacity. stream/start derives each role's configuration from the hello constants plus the role's current state, and answers a state change on an active stream with a new stream/start when the configuration changed.
This also collapses the last message that applied as a patch outside of management: after it, client self-description is always full state, and only management requests apply as patches with explicit outcomes.
After #182 even the management requests will be consistent (since no management messages will exist), making the protocol fully consistent in this area.
Follow-up to the alignment question in #177:
stream/request-formatcarries dynamically changing values, which per the CONTRIBUTING rule belong inclient/state. Looking closer, the whole message should go, because it is a request in name only.A decline is invisible: when the server cannot honor a request, the stream continues and the request MUST NOT be treated as an error, so no message ever tells the client it was declined. The client learns the operative configuration exclusively from
stream/start, which is exactly how state assertions would work. With no stream active the server SHOULD already remember the requested format for the next stream, so the request is de facto state, stored on the wrong side with a weaker guarantee. And no role lets a client request a format it cannot accept (player requests MUST come fromsupported_formats), so the fields always describe the client's current wishes.Proposed shape:
playergains an optionalformatpreference in its state object (absent means the server picks persupported_formats);artworkmoves the per-channelsource/format/width/heightinto a statechannelsarray, withclient/helloshrinking to a channel count;visualizermovestypes,rate_maxandspectruminto state, with hello keeping onlybuffer_capacity.stream/startderives each role's configuration from the hello constants plus the role's current state, and answers a state change on an active stream with a newstream/startwhen the configuration changed.This also collapses the last message that applied as a patch outside of management: after it, client self-description is always full state, and only management requests apply as patches with explicit outcomes.
After #182 even the management requests will be consistent (since no management messages will exist), making the protocol fully consistent in this area.