feat(audio): per-stream mix controls in Windows client + vc_get_remote_stream getter

PerUserTuningDialog previously broadcast one gain/mute/NR set to *all* of a
user's streams, even though the core mixer (AudioEngine::RemoteStream) and
the C ABI (vc_set_remote_stream) were already per-stream. The UI had no
per-mix controls anywhere.

Reworks the dialog to enumerate ListUserStreams on open and render one row
per stream (kind + label + Gain + Mute + NR), each wiring only to its own
stream_id. Adds a read-back ABI counterpart, vc_get_remote_stream, so the
dialog opens at the listener's actual current per-stream settings (defaults
1.0/unmuted/NR-off) rather than always 100%. Additive ABI change only; no
existing symbols touched.

Tests: test_m3_multistream extended with getter round-trip assertions; new
C# smoke test exercises the full P/Invoke marshaling path with two clients.
Docs: voice.md §10 notes the getter. NR checkbox keeps its honest
'passthrough' label (NS DSP still unbuilt per §8).
This commit is contained in:
2026-06-18 02:06:44 +02:00
parent 1dfe3c95ed
commit d397731db9
15 changed files with 402 additions and 82 deletions

View File

@@ -319,6 +319,17 @@ typedef struct vc_stream_summary_list {
size_t count;
} vc_stream_summary_list;
/* Receive-side state the local listener has chosen for a specific remote stream — the
* counterpart to vc_set_remote_stream, so a UI can reopen its per-mix controls at the
* listener's actual current settings. All LOCAL (no protocol traffic) — docs/voice.md §10.
* If (user_id, stream_id) is known but the listener has never called vc_set_remote_stream on
* it, the defaults are gain=1.0, muted=0, noise_reduction=0 (matching a fresh RemoteStream). */
typedef struct vc_remote_stream_state {
float gain; /* 0.0–… ; default 1.0 */
int muted; /* bool */
int noise_reduction; /* bool */
} vc_remote_stream_state;
/* Opaque client handle. */
typedef struct vc_client vc_client;
@@ -365,7 +376,13 @@ VC_API vc_result vc_set_self_mute(vc_client* c, int mic_muted, int deafened);
/* Receive-side, per remote stream, all LOCAL (no protocol traffic) — docs/voice.md §10:
* gain (0..) , mute, and listener-chosen noise reduction on a specific user's stream. */
VC_API vc_result vc_set_remote_stream(vc_client* c, uint32_t user_id, uint32_t stream_id,
float gain, int muted, int noise_reduction);
float gain, int muted, int noise_reduction);
/* Reads back the receive-side state last set on (user_id, stream_id) via
* vc_set_remote_stream (or the defaults if never set). VC_ERR_INVALID_ARG if the user/stream
* isn't known. */
VC_API vc_result vc_get_remote_stream(vc_client* c, uint32_t user_id, uint32_t stream_id,
vc_remote_stream_state* out);
/* Effective Opus config in use for (user_id, stream_id) — your own stream or a peer's.
* VC_ERR_INVALID_ARG if the user/stream isn't known. */