111 lines
3.6 KiB
Rust
111 lines
3.6 KiB
Rust
|
|
pub mod devices;
|
||
|
|
pub mod diagnostics;
|
||
|
|
pub mod state;
|
||
|
|
|
||
|
|
mod ui;
|
||
|
|
|
||
|
|
use std::collections::BTreeMap;
|
||
|
|
|
||
|
|
use anyhow::Result;
|
||
|
|
|
||
|
|
pub use diagnostics::{DiagnosticsLog, PerformanceSample, SnapshotReport, quality_probe_command};
|
||
|
|
pub use state::{DeviceSelection, InputRouting, LauncherState, ViewMode};
|
||
|
|
|
||
|
|
pub fn maybe_run_launcher(args: &[String]) -> Result<bool> {
|
||
|
|
if args.iter().any(|arg| arg == "--launcher") {
|
||
|
|
let server_addr = resolve_server_addr(args);
|
||
|
|
ui::run_gui_launcher(server_addr)?;
|
||
|
|
return Ok(true);
|
||
|
|
}
|
||
|
|
Ok(false)
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn runtime_env_vars(state: &LauncherState) -> BTreeMap<String, String> {
|
||
|
|
let mut envs = BTreeMap::new();
|
||
|
|
envs.insert(
|
||
|
|
"LESAVKA_CAPTURE_REMOTE".to_string(),
|
||
|
|
state.routing.as_env().to_string(),
|
||
|
|
);
|
||
|
|
envs.insert(
|
||
|
|
"LESAVKA_VIEW_MODE".to_string(),
|
||
|
|
state.view_mode.as_env().to_string(),
|
||
|
|
);
|
||
|
|
if let Some(camera) = state.devices.camera.as_ref() {
|
||
|
|
envs.insert("LESAVKA_CAM_SOURCE".to_string(), camera.clone());
|
||
|
|
}
|
||
|
|
if let Some(microphone) = state.devices.microphone.as_ref() {
|
||
|
|
envs.insert("LESAVKA_MIC_SOURCE".to_string(), microphone.clone());
|
||
|
|
}
|
||
|
|
if let Some(speaker) = state.devices.speaker.as_ref() {
|
||
|
|
envs.insert("LESAVKA_AUDIO_SINK".to_string(), speaker.clone());
|
||
|
|
}
|
||
|
|
envs
|
||
|
|
}
|
||
|
|
|
||
|
|
fn resolve_server_addr(args: &[String]) -> String {
|
||
|
|
for window in args.windows(2) {
|
||
|
|
if window[0] == "--server" {
|
||
|
|
return window[1].clone();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
args.iter()
|
||
|
|
.find(|arg| !arg.starts_with("--"))
|
||
|
|
.cloned()
|
||
|
|
.or_else(|| std::env::var("LESAVKA_SERVER_ADDR").ok())
|
||
|
|
.unwrap_or_else(|| "http://127.0.0.1:50051".to_string())
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod tests {
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn resolve_server_addr_prefers_explicit_server_flag() {
|
||
|
|
let args = vec![
|
||
|
|
"--launcher".to_string(),
|
||
|
|
"--server".to_string(),
|
||
|
|
"http://example:50051".to_string(),
|
||
|
|
"http://fallback:50051".to_string(),
|
||
|
|
];
|
||
|
|
assert_eq!(resolve_server_addr(&args), "http://example:50051");
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn resolve_server_addr_uses_first_non_flag_or_default() {
|
||
|
|
let args = vec!["--launcher".to_string(), "http://from-arg:50051".to_string()];
|
||
|
|
assert_eq!(resolve_server_addr(&args), "http://from-arg:50051");
|
||
|
|
|
||
|
|
let args = vec!["--launcher".to_string()];
|
||
|
|
assert!(resolve_server_addr(&args).starts_with("http://"));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn runtime_env_vars_emit_selected_controls() {
|
||
|
|
let mut state = LauncherState::new();
|
||
|
|
state.set_routing(InputRouting::Local);
|
||
|
|
state.set_view_mode(ViewMode::Unified);
|
||
|
|
state.select_camera(Some("/dev/video0".to_string()));
|
||
|
|
state.select_microphone(Some("alsa_input.test".to_string()));
|
||
|
|
state.select_speaker(Some("alsa_output.test".to_string()));
|
||
|
|
|
||
|
|
let envs = runtime_env_vars(&state);
|
||
|
|
assert_eq!(envs.get("LESAVKA_CAPTURE_REMOTE"), Some(&"0".to_string()));
|
||
|
|
assert_eq!(envs.get("LESAVKA_VIEW_MODE"), Some(&"unified".to_string()));
|
||
|
|
assert_eq!(envs.get("LESAVKA_CAM_SOURCE"), Some(&"/dev/video0".to_string()));
|
||
|
|
assert_eq!(
|
||
|
|
envs.get("LESAVKA_MIC_SOURCE"),
|
||
|
|
Some(&"alsa_input.test".to_string())
|
||
|
|
);
|
||
|
|
assert_eq!(
|
||
|
|
envs.get("LESAVKA_AUDIO_SINK"),
|
||
|
|
Some(&"alsa_output.test".to_string())
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn maybe_run_launcher_returns_false_without_launcher_flag() {
|
||
|
|
let args = vec!["http://server:50051".to_string()];
|
||
|
|
assert!(!maybe_run_launcher(&args).expect("launcher check"));
|
||
|
|
}
|
||
|
|
}
|