fn network_spread_ms(samples: &VecDeque<(Instant, f32)>) -> f32 { if samples.len() < 2 { return 0.0; } let mut values = samples.iter().map(|(_, value)| *value).collect::>(); values.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)); let median = values[values.len() / 2]; let mut deviations = values .into_iter() .map(|value| (value - median).abs()) .collect::>(); deviations.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)); deviations[deviations.len() / 2] } #[cfg(not(coverage))] /// Apply a remote-audio gain slider update without unwinding through GTK callbacks. fn apply_audio_gain_change( scale: >k::Scale, state: &Rc>, widgets: &super::ui_components::LauncherWidgets, child_proc: &Rc>>, ) -> bool { let percent = scale .value() .round() .clamp(0.0, MAX_AUDIO_GAIN_PERCENT as f64) as u32; let label = { let Ok(mut state) = state.try_borrow_mut() else { return false; }; if state.audio_gain_percent == percent { widgets.audio_gain_value.set_text(&state.audio_gain_label()); return true; } state.set_audio_gain_percent(percent); state.audio_gain_label() }; widgets.audio_gain_value.set_text(&label); let relay_live = child_proc .try_borrow() .map(|child| child.is_some()) .unwrap_or(false); if relay_live { let path = audio_gain_control_path(); match write_audio_gain_request(&path, percent) { Ok(()) => widgets .status_label .set_text(&format!("Remote audio gain set to {label}.")), Err(err) => widgets.status_label.set_text(&format!( "Remote audio gain set to {label} for the next relay launch, but live gain control could not be written: {err}" )), } } else { widgets.status_label.set_text(&format!( "Remote audio gain set to {label} for the next relay launch." )); } true } #[cfg(not(coverage))] /// Apply a microphone uplink gain slider update without unwinding through GTK callbacks. fn apply_mic_gain_change( scale: >k::Scale, state: &Rc>, widgets: &super::ui_components::LauncherWidgets, child_proc: &Rc>>, ) -> bool { let percent = scale .value() .round() .clamp(0.0, MAX_MIC_GAIN_PERCENT as f64) as u32; let label = { let Ok(mut state) = state.try_borrow_mut() else { return false; }; if state.mic_gain_percent == percent { widgets.mic_gain_value.set_text(&state.mic_gain_label()); return true; } state.set_mic_gain_percent(percent); state.mic_gain_label() }; widgets.mic_gain_value.set_text(&label); let relay_live = child_proc .try_borrow() .map(|child| child.is_some()) .unwrap_or(false); if relay_live { let path = mic_gain_control_path(); match write_mic_gain_request(&path, percent) { Ok(()) => widgets.status_label.set_text(&format!("Mic gain set to {label}.")), Err(err) => widgets.status_label.set_text(&format!( "Mic gain set to {label} for the next relay launch, but live gain control could not be written: {err}" )), } } else { widgets.status_label.set_text(&format!( "Mic gain set to {label} for the next relay launch." )); } true } #[cfg(not(coverage))] /// Apply a live media soft-pause/resume request without restarting USB gadget functions. fn apply_media_control_change( state_snapshot: &LauncherState, widgets: &super::ui_components::LauncherWidgets, child_proc: &Rc>>, feed_label: &str, enabled: bool, ) { let relay_live = child_proc .try_borrow() .map(|child| child.is_some()) .unwrap_or(false); let action = if enabled { "resumed" } else { "soft-paused" }; if relay_live { let path = media_control_path(); match write_media_control_request(&path, state_snapshot) { Ok(()) => widgets .status_label .set_text(&format!("{feed_label} {action} for the live relay.")), Err(err) => widgets.status_label.set_text(&format!( "{feed_label} will be {action} on the next relay launch, but the live soft-pause control could not be written: {err}" )), } } else { widgets.status_label.set_text(&format!( "{feed_label} will start {} on the next relay launch.", if enabled { "enabled" } else { "paused" } )); } } #[cfg(not(coverage))] /// Refresh relay capture-power state in the background so GTK stays responsive. fn request_capture_power_refresh( power_tx: std::sync::mpsc::Sender, server_addr: String, delay: Duration, ) { std::thread::spawn(move || { if !delay.is_zero() { std::thread::sleep(delay); } let result = fetch_capture_power(&server_addr).map_err(|err| err.to_string()); let _ = power_tx.send(PowerMessage::Refresh(result)); }); } #[cfg(not(coverage))] fn request_capture_power_command( power_tx: std::sync::mpsc::Sender, server_addr: String, command: CapturePowerCommand, ) { std::thread::spawn(move || { let result = set_capture_power_mode(&server_addr, command).map_err(|err| err.to_string()); let _ = power_tx.send(PowerMessage::Command(result)); }); } #[cfg(not(coverage))] /// Refresh upstream calibration state in the background so the UI can poll safely. fn request_calibration_refresh( calibration_tx: std::sync::mpsc::Sender, server_addr: String, delay: Duration, ) { std::thread::spawn(move || { if !delay.is_zero() { std::thread::sleep(delay); } let result = fetch_calibration(&server_addr).map_err(|err| err.to_string()); let _ = calibration_tx.send(CalibrationMessage::Refresh(result)); }); } #[cfg(not(coverage))] /// Refresh authoritative upstream sync planner state in the background. fn request_upstream_sync_refresh( upstream_sync_tx: std::sync::mpsc::Sender, server_addr: String, delay: Duration, ) { std::thread::spawn(move || { if !delay.is_zero() { std::thread::sleep(delay); } let result = fetch_upstream_sync(&server_addr).map_err(|err| err.to_string()); let _ = upstream_sync_tx.send(UpstreamSyncMessage::Refresh(result)); }); } #[cfg(not(coverage))] fn request_calibration_command( calibration_tx: std::sync::mpsc::Sender, server_addr: String, action: F, ) where F: FnOnce(&str) -> anyhow::Result + Send + 'static, { std::thread::spawn(move || { let result = action(&server_addr).map_err(|err| err.to_string()); let _ = calibration_tx.send(CalibrationMessage::Command(result)); }); } #[cfg(not(coverage))] /// Probe server capabilities on a short-lived runtime without blocking the UI thread. fn request_handshake_caps( caps_tx: std::sync::mpsc::Sender, server_addr: String, delay: Duration, ) { std::thread::spawn(move || { if !delay.is_zero() { std::thread::sleep(delay); } let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() .build(); let probe = match runtime { Ok(runtime) => runtime.block_on(probe(&server_addr)), Err(_) => HandshakeProbe::default(), }; let _ = caps_tx.send(CapsMessage::Refresh(probe)); }); } #[cfg(not(coverage))] fn unavailable_capture_power(detail: String) -> CapturePowerStatus { CapturePowerStatus { available: false, enabled: false, unit: "relay.service".to_string(), detail, active_leases: 0, mode: "auto".to_string(), detected_devices: 0, } } #[cfg(not(coverage))] fn unavailable_calibration(detail: String) -> CalibrationStatus { CalibrationStatus::unavailable(detail) } #[cfg(not(coverage))] fn unavailable_upstream_sync(detail: String) -> UpstreamSyncStatus { UpstreamSyncStatus::unavailable(detail) } #[cfg(not(coverage))] fn calibration_summary(calibration: &CalibrationStatus) -> String { format!( "Upstream A/V calibration: {} audio {:+.1} ms, video {:+.1} ms ({}, {}).", calibration.profile, calibration.active_audio_offset_us as f64 / 1000.0, calibration.active_video_offset_us as f64 / 1000.0, calibration.source, calibration.confidence ) }