From 80ed1155f5feb8fa762b9ef310f2b54dacb1cf9c Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Tue, 24 Mar 2026 07:29:57 +0100 Subject: [PATCH] [fix](trx-frontend-http): scope channel audio by remote Send the selected remote together with virtual-channel audio requests and use per-rig stream info when /audio is opened with channel_id. This keeps browser channel audio aligned with the requested remote after the recent multi-rig client changes. Add coverage for parsing channel_id together with remote. Co-authored-by: OpenAI Codex Signed-off-by: Stan Grams --- .../trx-frontend-http/assets/web/app.js | 5 ++++- .../trx-frontend-http/src/audio.rs | 21 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js index 7dd26bb..365e9ca 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js @@ -7672,7 +7672,10 @@ function startRxAudio() { const proto = location.protocol === "https:" ? "wss:" : "ws:"; let audioPath; if (_audioChannelOverride) { - audioPath = `/audio?channel_id=${encodeURIComponent(_audioChannelOverride)}`; + const remoteParam = lastActiveRigId + ? `&remote=${encodeURIComponent(lastActiveRigId)}` + : ""; + audioPath = `/audio?channel_id=${encodeURIComponent(_audioChannelOverride)}${remoteParam}`; } else if (lastActiveRigId) { audioPath = `/audio?remote=${encodeURIComponent(lastActiveRigId)}`; } else { diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/audio.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/audio.rs index ee36c69..e8f6306 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/src/audio.rs +++ b/src/trx-client/trx-frontend/trx-frontend-http/src/audio.rs @@ -502,7 +502,14 @@ pub async fn audio_ws( broadcast::Receiver, tokio::sync::watch::Receiver>, ) = if let Some(ch_id) = query.channel_id { - let Some(info_rx) = context.audio_info.as_ref().cloned() else { + let info_rx = if let Some(ref remote) = query.remote { + context + .rig_audio_info_rx(remote) + .or_else(|| context.audio_info.as_ref().cloned()) + } else { + context.audio_info.as_ref().cloned() + }; + let Some(info_rx) = info_rx else { return Ok(HttpResponse::NotFound().body("audio not enabled")); }; let deadline = Instant::now() + Duration::from_secs(2); @@ -636,6 +643,7 @@ pub async fn audio_ws( #[cfg(test)] mod tests { use super::AudioQuery; + use uuid::Uuid; #[test] fn audio_query_accepts_remote() { @@ -643,4 +651,15 @@ mod tests { serde_json::from_str(r#"{"remote":"lidzbark-vhf"}"#).expect("query parse"); assert_eq!(query.remote.as_deref(), Some("lidzbark-vhf")); } + + #[test] + fn audio_query_accepts_channel_id_with_remote() { + let channel_id = Uuid::new_v4(); + let query: AudioQuery = serde_json::from_str(&format!( + r#"{{"channel_id":"{channel_id}","remote":"lidzbark-vhf"}}"# + )) + .expect("query parse"); + assert_eq!(query.channel_id, Some(channel_id)); + assert_eq!(query.remote.as_deref(), Some("lidzbark-vhf")); + } }