You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The radio-side dax_rx stream map lives in a single PanadapterStream (one per radio), but three independent consumers each hand-roll their own ownership bookkeeping on top of it and coordinate by peeking at each other's state:
PanadapterStream itself only exposes registerDaxStream() / unregisterDaxStream() / daxStreamIdForChannel() — no notion of who holds a channel or how many holders there are. So each consumer reimplements "is anyone else using this channel?" by reaching into the others:
TCI borrows a stream the bridge created and refuses to remove borrowed channels in releaseDaxForTci() (src/core/TciServer.cpp), explicitly to avoid silencing other consumers.
This works but is fragile and O(consumers²): every new consumer has to learn about every existing one, and any missed cross-check silently tears out a stream another consumer needs (the #3270 failure mode, which #2895/#3282 patched from two directions).
Proposed direction
Replace the per-consumer ownership maps with centralized refcounting in PanadapterStream:
// rough shape
quint32 acquireDaxChannel(int channel, DaxConsumer who); // creates stream if refcount 0→1, else reusesvoidreleaseDaxChannel(int channel, DaxConsumer who); // sends `stream remove` only when refcount 1→0
PanadapterStream owns the channel→(streamId, refcount, holders) table and is the single place that emits stream create / stream remove.
Consumers call acquire/release and stop tracking stream IDs and each other entirely.
Removal happens only when the last holder releases — no consumer can stomp another.
These are the contained, per-path predecessors; this issue tracks the structural consolidation we deferred to a later release.
Notes
Architecture change (new ownership model + signal/ownership routing) → maintainer design call before implementation.
Should preserve: slice 0 RX flow, the Broken TCI audio tested on Win11 #1439 re-assert, borrowed-stream semantics (no double stream create → double-speed audio), and clean teardown on disconnect/stopDax/releaseDaxForTci.
Problem
The radio-side
dax_rxstream map lives in a singlePanadapterStream(one per radio), but three independent consumers each hand-roll their own ownership bookkeeping on top of it and coordinate by peeking at each other's state:MainWindow)m_daxSliceLastCh(sliceId→channel), per-slicedaxChannelChangedwiringTciServer)m_tciDaxStreamIds(channel→id),m_tciDaxBorrowedChannels,m_tciDaxSlicesMainWindow)m_radeDaxStreamIdPanadapterStreamitself only exposesregisterDaxStream()/unregisterDaxStream()/daxStreamIdForChannel()— no notion of who holds a channel or how many holders there are. So each consumer reimplements "is anyone else using this channel?" by reaching into the others:releaseDaxForTci()(src/core/TciServer.cpp), explicitly to avoid silencing other consumers.TciServer::ownsDaxChannel()and compares againstm_radeDaxStreamIdbefore removing a stream (added in DAX virtual audio: only slice 0 gets audio client on Linux PipeWire headless (RPi 5, Ubuntu 24.04, FLEX-8600) #2895).This works but is fragile and O(consumers²): every new consumer has to learn about every existing one, and any missed cross-check silently tears out a stream another consumer needs (the #3270 failure mode, which #2895/#3282 patched from two directions).
Proposed direction
Replace the per-consumer ownership maps with centralized refcounting in
PanadapterStream:PanadapterStreamowns the channel→(streamId, refcount, holders) table and is the single place that emitsstream create/stream remove.acquire/releaseand stop tracking stream IDs and each other entirely.slice set <id> dax=<ch>client-registration re-assert (Broken TCI audio tested on Win11 #1439) as a separate concern.Context / predecessors (contained fixes already landed/in-flight)
daxChannelChanged+ reciprocal ownership guard against TCI/RADEThese are the contained, per-path predecessors; this issue tracks the structural consolidation we deferred to a later release.
Notes
stream create→ double-speed audio), and clean teardown on disconnect/stopDax/releaseDaxForTci.