@@ -444,7 +444,7 @@ the five files that log, and `tests/daemon_test.cpp`:
444444 process acquires * any* resource — rather than as a list of three current call sites. All
445445 three are live: ` make_audio_sink() ` already probes the device
446446 (` src/audio_sink.cpp:258,267 ` ) and ` PortAudioSink ` then holds a ` PortAudioGuard ` that
447- brings up the CoreAudio HAL's mach ports and helper threads, ` start_server ()` starts the
447+ brings up the CoreAudio HAL's mach ports and helper threads, ` start ()` starts the
448448 sync task's ` std::thread ` , and a ` DNSServiceRef ` is a per-process connection to
449449 ` mDNSResponder ` /` avahi-daemon ` . Only the forking thread survives a fork, so an item 7
450450 control socket or an item 8 config file cannot quietly land above the line without
@@ -494,7 +494,7 @@ the five files that log, and `tests/daemon_test.cpp`:
494494 mDNS daemon.
495495
496496** Three asks removed from this item rather than deferred** , all for one reason worth
497- writing down: sendspin-cpp v0.7 .0 logs through ` src/platform/logging.h ` 's bare
497+ writing down: sendspin-cpp v0.8 .0 logs through ` src/platform/logging.h ` 's bare
498498` fprintf(stderr, "E %s: " fmt "\n", tag, ...) ` macros, gated on a single global
499499` int ss_host_log_level ` , with ** no callback or sink hook** . Library lines cannot be
500500reformatted, redirected or filtered per tag by any API call this layer can make.
@@ -614,7 +614,7 @@ stops the worse failure this item only documents: an operator running a player t
614614authenticated. It is a breaking change for anyone passing such a URL today, which is why it is
615615owed here rather than done here. Masking is what this item ships; refusing is the fix.
616616
617- ** A third thing this item does not claim: the library's own dial lines.** sendspin-cpp v0.7 .0
617+ ** A third thing this item does not claim: the library's own dial lines.** sendspin-cpp v0.8 .0
618618logs the URL it is dialling at ` info ` from ` ConnectionManager::connect_to() ` and again at
619619` error ` from ` SendspinClientConnection ` , through the same sink-less ` SS_LOG* ` macros that put
620620timestamps and per-tag filtering out of reach above — so those lines still carry whatever the
@@ -942,9 +942,9 @@ advertised an adjustable delay with nothing behind it, leaving a spec requiremen
942942 ` ConnectionManager::fnv1_hash() ` , which lives in the library's uninstalled ` src/ ` — so we store
943943 the number we are handed and hand it back, and never compute it. Discovery's own tie-break
944944 needs the raw id, which the hash cannot be turned back into.
945- - ** ` CliPersistenceProvider ` is installed before ` add_player() ` and ` start_server ()` ** , and
945+ - ** ` CliPersistenceProvider ` is installed before ` add_player() ` and ` start ()` ** , and
946946 neither is negotiable: the pointer is copied into ` PlayerRole ` at construction, and
947- ` start_server ()` is what loads the remembered hash. Installed after either, it is a provider
947+ ` start ()` is what loads the remembered hash. Installed after either, it is a provider
948948 the library never asks.
949949- ** Volume and mute are the CLI's own half** , since the provider has no hook for either.
950950 ` PlayerListener ` writes through on every server change, and startup seeds the sink, the
@@ -1663,9 +1663,9 @@ locally settable, and volume changes are ramped. Split out of item 4.
16631663** This item's opening premise was wrong, and correcting it is part of what shipped.** It claimed
16641664` set_static_delay_adjustable(true) ` was advertised with no ` on_static_delay_changed() ` override,
16651665so "a controller can offer the user a static delay this player then applies to nothing". Against
1666- sendspin-cpp v0.7 .0 that is not true, and it never was: ` SyncTask::decode_chunk() ` subtracts
1666+ sendspin-cpp v0.8 .0 that is not true, and it never was: ` SyncTask::decode_chunk() ` subtracts
16671667` get_effective_static_delay_ms() ` from every chunk's client timestamp
1668- (` _deps/sendspin-src/src/sync_task.cpp:593 ` ), and that value becomes ` decoded_timestamp ` , which
1668+ (` _deps/sendspin-src/src/sync_task.cpp:597 ` ), and that value becomes ` decoded_timestamp ` , which
16691669is what ` raw_error ` is measured against — the drift correction itself. ` get_effective_static_delay_ms() `
16701670returns the stored delay precisely * because* adjustability is on. So the delay was already being
16711671obeyed; the override was never the thing standing between the value and the audio path. A future
@@ -1681,7 +1681,7 @@ landed:
16811681- ** ` status ` reports it** , as ` static delay: <n> ms ` , read from ` PlayerRole::get_static_delay_ms() `
16821682 rather than from a listener-held shadow. That is not a style choice: ` update_static_delay() ` does
16831683 not invoke the listener (only a server's ` set_static_delay ` does,
1684- ` _deps/sendspin-src/src/player_role.cpp:396-400 ` ), so a shadow would be stale the moment the
1684+ ` _deps/sendspin-src/src/player_role.cpp:403-408 ` ), so a shadow would be stale the moment the
16851685 local knob below was used.
16861686- ** ` sendspin-cli delay <0-5000> ` ** sets it locally. The first * mutating* request answered without
16871687 a server — ` status ` was previously the only locally answered one at all — which the spec
@@ -1736,7 +1736,7 @@ stdout sink stays a jump. Not an oversight.
17361736
17371737** The ` DEFAULT_SINK_VOLUME ` mismatch was already closed, so it was re-documented rather than
17381738fixed.** Item 8 made startup call ` player.update_volume() ` /` update_muted() ` unconditionally, with
1739- the volume falling back to ` DEFAULT_SINK_VOLUME ` , before ` start_server ()` — so the role and the
1739+ the volume falling back to ` DEFAULT_SINK_VOLUME ` , before ` start ()` — so the role and the
17401740sink agree from before the first ` client/state ` , and the disagreement four comments still
17411741described was no longer observable. Those four (` src/audio_sink.h ` , ` src/player_listener.h ` ,
17421742` src/control.h ` , ` src/main.cpp ` 's ` status() ` ) now describe the current arrangement, keeping the
@@ -1758,7 +1758,7 @@ reasons those members exist: `PlayerListener` is still the only thing that knows
17581758** One gap found while scoping this belongs upstream, not here.** ` required_lead_time_ms ` and
17591759` min_buffer_ms ` are ** REQUIRED** in ` client/state ` per ` roles/player/v1.md ` — the server uses them
17601760to decide how far ahead to send audio, scheduling the first chunk at least
1761- ` min_buffer_ms + static_delay_ms ` out — and sendspin-cpp v0.7 .0 implements neither anywhere. A
1761+ ` min_buffer_ms + static_delay_ms ` out — and sendspin-cpp v0.8 .0 implements neither anywhere. A
17621762grep of the whole library, headers and sources, matches neither name. Nothing in this repo can
17631763supply them: ` ClientPlayerStateObject ` , which ` PlayerRole::Impl::build_state_fields() ` fills, has
17641764no field for either. It needs a library change, not a change here.
@@ -1877,7 +1877,7 @@ a backoff and a bounded retry, for the backends whose version of it is a server
18771877than a device-list rebuild; PortAudio's remains the one attempt described here.
18781878
18791879No re-advertising of formats mid-session: ` capabilities() ` is answered once
1880- before ` start_server ()` , so a rescan does not change what the server was told, and the refusal
1880+ before ` start ()` , so a rescan does not change what the server was told, and the refusal
18811881path that already names the device and the format it would not take stays the mitigation, as the
18821882comment on ` capabilities() ` has said since item 3. ` NullAudioSink ` is untouched, having no
18831883device to lose.
@@ -1996,14 +1996,14 @@ item, but it should not be lost.** The spec has moved inbound arbitration to an
19961996first ` server/activate ` , with "higher or equal is accepted, lower is rejected", plus a
19971997persisted last-* playback* server.
19981998
1999- Pinned ` sendspin-cpp ` v0.7 .0 has ** no ` activities ` and no ` server/activate ` at all** , and
1999+ Pinned ` sendspin-cpp ` v0.8 .0 has ** no ` activities ` and no ` server/activate ` at all** , and
20002000still implements the older ` connection_reason ` DISCOVERY/PLAYBACK handoff. So this item is
20012001gated on a library that speaks the newer shape, and is likely to arrive with a
20022002` SENDSPIN_GIT_TAG ` bump rather than on its own.
20032003
20042004Item 5's ` src/last_server.{h,cpp} ` is the nearest thing that exists today and is
20052005deliberately named for what it observes — the last server whose * handshake* completed, not
2006- its last * playback* server, which v0.7 .0 gives no way to know.
2006+ its last * playback* server, which v0.8 .0 gives no way to know.
20072007
20082008### 18. Native PulseAudio backend — * shipped (audible slice)*
20092009
@@ -2260,11 +2260,10 @@ no workaround either — the control socket answers questions, it does not annou
22602260 polled from the main loop, next to mDNS and the control socket. A non-zero exit or a
22612261 signal death is one ` W hook: ` line; a hook still running at shutdown is left to
22622262 finish, because an amplifier half-switched is worse than an orphan.
2263- - ** The stream's end is waited for on the way out.** ` disconnect() ` only enqueues it, and
2264- it is ` client.loop() ` that delivers it, so without this a player killed mid-stream reaches
2265- ` return 0 ` with its stop hook unrun and the amplifier still on. The loop is pumped after
2266- the disconnect until the listener reports the stream over, bounded by
2267- ` SHUTDOWN_DRAIN_MS ` against a wait of about fifty, and says so and goes if that passes.
2263+ - ** The stream's end is waited for on the way out.** ` client.stop() ` goodbyes every peer and
2264+ delivers ` on_stream_end() ` before it returns, so the hook is queued by the time control comes
2265+ back and the ` hooks.flush() ` below runs it. Without that wait a player killed mid-stream would
2266+ reach ` return 0 ` with its stop hook unrun and the amplifier still on.
22682267 The stop hook it spawns is by definition the orphan case above: nothing waits on it.
22692268- ** Fired on the stream lifecycle, not on the format being accepted** , through a
22702269 ` PlayerListener::on_stream_event ` seam shaped like ` AudioSink::on_frames_played ` . A
@@ -2376,17 +2375,16 @@ detection may pick the wrong interface" — the same scenario, so it is worth sa
23762375is not the same lever. That value goes into ` client/hello ` 's ` device_info ` : it is identity,
23772376and it moves no socket.
23782377
2379- ** Why this is more than "it listens broadly".** Pinned v0.7.2 has ** no inbound
2378+ ** Why this is more than "it listens broadly".** Pinned v0.8.0 has ** no inbound
23802379authentication of any kind** : no PSK, no pairing gate on the inbound path, and — per item
2381- 17, whose text still cites v0.7.0, re-checked here at v0.7.2 — no ` activities ` /
2382- ` server/activate ` either, since it still runs the older ` connection_reason ` handoff.
2380+ 17 — no ` activities ` / ` server/activate ` either, since it still runs the older ` connection_reason ` handoff.
23832381` server_max_connections ` is the only inbound limit, and it counts sockets rather than
23842382judging them. Reachability is therefore authorization: whatever reaches the listen port
23852383completes the handshake and drives the player, and a bind address would be the only such
23862384control the player itself offers.
23872385
23882386** That is a statement about the pinned library, not about Sendspin.** The spec
2389- authenticates in the handshake — pairing and a PSK, as item 6 records — and v0.7.2 does
2387+ authenticates in the handshake — pairing and a PSK, as item 6 records — and v0.8.0 does
23902388not implement that half yet. This item's premise expires when it does.
23912389
23922390** In proportion.** Most installs sit behind NAT, where no interface holds a routable
0 commit comments