feat(audio-rooms): M1 listener-only wire-up — Connect button + Connected chip + mute
Wires `connectNestsListener` into the existing NIP-53 audio-room "stage" so
a user can tap Connect, see the live connection state, and hear hosts
speaking. Per the audio-rooms completion plan
(`nestsClient/plans/2026-04-26-audio-rooms-completion.md`) phase M1.
UI (amethyst):
- AudioRoomStage gets a state-chip / Connect / Disconnect / Mute row
above the existing hand-raise. State chip walks ResolvingRoom →
OpeningTransport → MoQ-handshake → Connected; Failed surfaces the
reason inline with a Retry button. The 30312 `service` tag drives
visibility — rooms hosted on non-nests servers show "Audio not
available" and the rest of the stage UI continues to work.
ViewModel (commons):
- New `AudioRoomViewModel` in commons/.../viewmodels/ owns one
`NestsListener` and one `AudioRoomPlayer` per active speaker, exposes
a single `StateFlow<AudioRoomUiState>`, and reconciles subscriptions
whenever the screen pushes a new speaker set via `updateSpeakers`.
Audio-pipeline construction is injected via `decoderFactory` /
`playerFactory` so a future desktop port can reuse the orchestration
once Compose Desktop has WebTransport. Unit-tested with a fake
`NestsListenerConnector` driving state transitions directly.
nestsClient:
- `AudioPlayer.setMuted(Boolean)` joins the interface; `AudioTrackPlayer`
routes it through `AudioTrack.setVolume(0f/1f)`. Mute keeps the
decode + network pipeline running so unmute is sample-accurate.
Build:
- `:commons` commonMain now `implementation(project(":nestsClient"))` so
the shared VM can see `NestsListener` / `AudioRoomPlayer` / interfaces.
Concrete OkHttp / Quic / MediaCodec / AudioTrack actuals stay in
`:nestsClient`'s platform source sets and are bound by an
Android-side `AudioRoomViewModelFactory` co-located with the screen.
Verified: `./gradlew spotlessApply :commons:jvmTest :nestsClient:jvmTest
:quic:jvmTest :amethyst:compilePlayDebugKotlin` all green.
This commit is contained in:
+6
@@ -206,6 +206,8 @@ class AudioRoomPlayerTest {
|
||||
private set
|
||||
val stopped: Boolean get() = stopCount > 0
|
||||
val queued = mutableListOf<ShortArray>()
|
||||
var muted: Boolean = false
|
||||
private set
|
||||
|
||||
override fun start() {
|
||||
started = true
|
||||
@@ -215,6 +217,10 @@ class AudioRoomPlayerTest {
|
||||
queued.add(pcm)
|
||||
}
|
||||
|
||||
override fun setMuted(muted: Boolean) {
|
||||
this.muted = muted
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
stopCount++
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user