pub fn voice_for_lang(lang: &str) -> String { match lang { "zh_TW" => "Meijia", "zh_CN" => "Ting-Ting", "en_US" => "Samantha", "en_GB" => "Daniel", "ja_JP" => "Kyoko", "ko_KR" => "Yuna", "fr_FR" => "Amelie", "de_DE" => "Anna", _ => "Meijia", } .to_string() } pub fn phrase_for_lang(lang: &str) -> String { match lang { "zh_TW" | "zh_CN" => "語音測試一二三", "en_US" | "en_GB" => "Test one two three", "ja_JP" => "これはテストです", "ko_KR" => "테스트입니다", "fr_FR" => "Ceci est un test", "de_DE" => "Das ist ein Test", _ => "Test", } .to_string() } pub fn audio_devices() -> (Vec, Vec, String, String) { let run = |t: &str| -> Vec { if let Ok(r) = std::process::Command::new("SwitchAudioSource") .args(["-a", "-t", t, "-f", "json"]) .output() { String::from_utf8_lossy(&r.stdout) .lines() .filter_map(|l| { serde_json::from_str::(l) .ok() .and_then(|v| v["name"].as_str().map(|s| s.to_string())) }) .collect() } else { vec![] } }; let current = |t: &str| -> String { std::process::Command::new("SwitchAudioSource") .args(["-c", "-t", t]) .output() .map(|r| String::from_utf8_lossy(&r.stdout).trim().to_string()) .unwrap_or_default() }; let out = run("output"); let inp = run("input"); let co = current("output"); let ci = current("input"); (out, inp, co, ci) } pub fn inject_audio_devices( html: &str, out: &[String], inp: &[String], cur_out: &str, cur_in: &str, ) -> String { let mut out_opts = String::from(""); for d in out { let sel = if d == cur_out { " selected" } else { "" }; out_opts.push_str(&format!("")); } let mut inp_opts = String::from(""); for d in inp { let sel = if d == cur_in { " selected" } else { "" }; inp_opts.push_str(&format!("")); } html.replace("{out_devs}", &out_opts) .replace("{in_devs}", &inp_opts) }