aethersdr / aethersdr/AetherSDR
DAX: size the published/opened RX device set to radio capacity after connect
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 221
- Forks
- 117
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 299
Description
Corrected — the original body described the post-#4854 branch, not main. Restated against main @ 0bd3c493; thanks to @aethersdr-agent for the catch and the implementation sketch below.
Problem (on main today). The DAX RX wire path publishes/opens a fixed NUM_CHANNELS = 4 devices regardless of the connected radio, while RadioModel::maxSlicesForModel() (src/models/RadioModel.cpp:2197) already knows the per-model slice count (2 for a 6300/6400). So a FLEX-6400 currently gets four AetherSDR DAX N entries in the system audio list, two of which can never carry audio.
Sites on main:
src/core/PipeWireAudioBridge.h:28—NUM_CHANNELS = 4src/core/VirtualAudioBridge.h:37—NUM_CHANNELS = 4- open loops:
src/core/PipeWireAudioBridge.cpp:126,src/core/VirtualAudioBridge.cpp:94 - CoreAudio publish loop:
hal-plugin/AetherSDRDAX.cpp:234(for (int ch = 1; ch <= 4; ++ch))
Relationship to #4854. #4854 raises the wire path to 8 (taking the 6400 case to eight-and-six). This capacity-gating is orthogonal — it can land against main at the current 4→capacity and reduces #4854 stated cost. Either order works.
Proposed approach (design credit: @aethersdr-agent triage on this issue):
Linux/shm bridges run in-process with RadioModel, so they can gate on maxSlices() directly. NUM_CHANNELS sizes std::array/C-array members (PipeWireAudioBridge.h:68/93/101/114), so keep it as the compile-time upper bound and add a runtime m_activeChannels that bounds only the open loops (PipeWireAudioBridge.cpp:126, VirtualAudioBridge.cpp:94). Teardown loops can keep iterating the full bound — closing a never-opened slot is a no-op.
Resize-after-connect hazard: close+reopen yanks a source out from under an app already holding it (a WSJT-X on aethersdr-dax-2 sees its device vanish and return). Prefer grow-freely, shrink-only-when-idle over an unconditional republish on every infoChanged.
CoreAudio HAL plugin (coreaudiod loads it before any radio is known, so it cannot read maxSlices() at load): it already maps the same DaxShmBlock and has a retry timer (AetherSDRDAX.cpp:199). DaxShmBlock.reserved[3] (VirtualAudioBridge.h:23) is unused — writing maxChannels into reserved[0] is ABI-compatible: it zero-inits, an old plugin ignores it, and a new plugin reading 0 means "app too old / not connected -> publish the full set." That sidesteps the plugin/app version-skew hazard. For the device list, prefer hiding already-created devices (kAudioDevicePropertyIsHidden, if libASPL exposes it) over AddDevice/RemoveDevice churn on a device an app may have open; fall back to add/remove (safe post-OnInitialize per AetherSDRDAX.cpp:230-231) if not.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read RadioModel::maxSlicesForModel() in src/models/RadioModel.cpp and the open loops in src/core/PipeWireAudioBridge.cpp and src/core/VirtualAudioBridge.cpp, then inspect the shared-memory and retry logic in hal-plugin/AetherSDRDAX.cpp. Done means published devices follow radio capacity without disrupting active users, while the CoreAudio path handles unknown or older shared-memory data safely.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- audio-video-rtc, desktop
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 39/100