[feat](trx-rs): show audio bitrate and active stream count on About page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -224,6 +224,8 @@ pub struct FrontendRuntimeContext {
|
||||
pub sse_clients: Arc<AtomicUsize>,
|
||||
/// Active rigctl TCP clients.
|
||||
pub rigctl_clients: Arc<AtomicUsize>,
|
||||
/// Active audio WebSocket streams.
|
||||
pub audio_clients: Arc<AtomicUsize>,
|
||||
/// rigctl listen endpoint, if enabled.
|
||||
pub rigctl_listen_addr: Arc<Mutex<Option<SocketAddr>>>,
|
||||
/// Guard to avoid spawning duplicate decode collectors.
|
||||
@@ -367,6 +369,7 @@ impl FrontendRuntimeContext {
|
||||
auth_tokens: HashSet::new(),
|
||||
sse_clients: Arc::new(AtomicUsize::new(0)),
|
||||
rigctl_clients: Arc::new(AtomicUsize::new(0)),
|
||||
audio_clients: Arc::new(AtomicUsize::new(0)),
|
||||
rigctl_listen_addr: Arc::new(Mutex::new(None)),
|
||||
decode_collector_started: AtomicBool::new(false),
|
||||
http_auth_enabled: false,
|
||||
|
||||
@@ -3268,11 +3268,18 @@ function render(update) {
|
||||
document.getElementById("about-audio-codec").textContent = "Opus";
|
||||
document.getElementById("about-audio-samplerate").textContent = `${(streamInfo.sample_rate || 48000).toLocaleString()} Hz`;
|
||||
document.getElementById("about-audio-channels").textContent = (streamInfo.channels || 1) === 1 ? "Mono" : "Stereo";
|
||||
if (streamInfo.bitrate_bps) {
|
||||
const kbps = (streamInfo.bitrate_bps / 1000).toFixed(0);
|
||||
document.getElementById("about-audio-bitrate").textContent = `${kbps} kbps`;
|
||||
}
|
||||
if (streamInfo.frame_duration_ms) {
|
||||
document.getElementById("about-audio-frame").textContent = `${streamInfo.frame_duration_ms} ms`;
|
||||
}
|
||||
}
|
||||
document.getElementById("about-audio-rx").textContent = rxActive ? "Active" : "Off";
|
||||
if (typeof update.audio_clients === "number") {
|
||||
document.getElementById("about-audio-streams").textContent = update.audio_clients;
|
||||
}
|
||||
|
||||
// About — Decoders card
|
||||
const decMap = [
|
||||
|
||||
@@ -1056,8 +1056,10 @@
|
||||
<tr><td>Codec</td><td id="about-audio-codec">--</td></tr>
|
||||
<tr><td>Sample rate</td><td id="about-audio-samplerate">--</td></tr>
|
||||
<tr><td>Channels</td><td id="about-audio-channels">--</td></tr>
|
||||
<tr><td>Bitrate</td><td id="about-audio-bitrate">--</td></tr>
|
||||
<tr><td>Frame duration</td><td id="about-audio-frame">--</td></tr>
|
||||
<tr><td>RX status</td><td id="about-audio-rx">Off</td></tr>
|
||||
<tr><td>Active streams</td><td id="about-audio-streams">--</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- Decoders -->
|
||||
|
||||
@@ -94,6 +94,7 @@ struct FrontendMeta {
|
||||
#[serde(rename = "clients")]
|
||||
http_clients: usize,
|
||||
rigctl_clients: usize,
|
||||
audio_clients: usize,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
rigctl_addr: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -217,6 +218,7 @@ fn frontend_meta_from_context(
|
||||
FrontendMeta {
|
||||
http_clients,
|
||||
rigctl_clients: context.rigctl_clients.load(Ordering::Relaxed),
|
||||
audio_clients: context.audio_clients.load(Ordering::Relaxed),
|
||||
rigctl_addr: rigctl_addr_from_context(context),
|
||||
active_remote: active_rig_id_from_context(context),
|
||||
remotes: rig_ids_from_context(context),
|
||||
|
||||
@@ -650,6 +650,9 @@ pub async fn audio_ws(
|
||||
|
||||
let (response, mut session, mut msg_stream) = actix_ws::handle(&req, body)?;
|
||||
|
||||
let audio_clients = context.audio_clients.clone();
|
||||
audio_clients.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
actix_web::rt::spawn(async move {
|
||||
let mut current_info = loop {
|
||||
if let Some(info) = info_rx.borrow().clone() {
|
||||
@@ -682,7 +685,8 @@ pub async fn audio_ws(
|
||||
};
|
||||
let changed = next_info.sample_rate != current_info.sample_rate
|
||||
|| next_info.channels != current_info.channels
|
||||
|| next_info.frame_duration_ms != current_info.frame_duration_ms;
|
||||
|| next_info.frame_duration_ms != current_info.frame_duration_ms
|
||||
|| next_info.bitrate_bps != current_info.bitrate_bps;
|
||||
if changed {
|
||||
current_info = next_info;
|
||||
let info_json = match serde_json::to_string(¤t_info) {
|
||||
@@ -723,6 +727,7 @@ pub async fn audio_ws(
|
||||
}
|
||||
}
|
||||
let _ = session.close(None).await;
|
||||
audio_clients.fetch_sub(1, std::sync::atomic::Ordering::Relaxed);
|
||||
});
|
||||
|
||||
Ok(response)
|
||||
|
||||
Reference in New Issue
Block a user