diff --git a/dash-frontend/assets/dashboard/wivrn_head_symbolic.svg b/dash-frontend/assets/dashboard/wivrn_head_symbolic.svg new file mode 100644 index 0000000..8b16978 --- /dev/null +++ b/dash-frontend/assets/dashboard/wivrn_head_symbolic.svg @@ -0,0 +1,169 @@ + + + +WiVRn Wyvern yippeWiVRn Wyvern yippe1/25/25Yaya, y.a.y.a on Discord. diff --git a/dash-frontend/assets/lang/de.json b/dash-frontend/assets/lang/de.json index 3ca23fa..1292979 100644 --- a/dash-frontend/assets/lang/de.json +++ b/dash-frontend/assets/lang/de.json @@ -40,8 +40,7 @@ "NO_VR_MICROPHONE_SWITCH_MANUALLY": "Kein VR-Mikrofon gefunden. Schalten Sie es manuell um.", "FAILED_TO_SWITCH_MICROPHONE": "Fehler beim Wechseln des Mikrofons", "MICROPHONE_SET_SUCCESSFULLY": "Mikrofon erfolgreich umgeschaltet", - "SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich umgeschaltet", - "DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Gerät gefunden und initialisiert, aber nicht umgeschaltet" + "SPEAKERS_SET_SUCCESSFULLY": "Lautsprecher erfolgreich umgeschaltet" }, "ACTIONS": { "RECENTER_PLAYSPACE": "Playspace neu zentrieren" diff --git a/dash-frontend/assets/lang/en.json b/dash-frontend/assets/lang/en.json index 858bdf5..c25f8ae 100644 --- a/dash-frontend/assets/lang/en.json +++ b/dash-frontend/assets/lang/en.json @@ -27,7 +27,6 @@ "AUDIO": { "AUTO_SWITCH_TO_VR_AUDIO": "Auto-switch to VR audio", "CARDS": "Cards", - "DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Device found and initialized, but not switched", "FAILED_TO_SWITCH_MICROPHONE": "Failed to switch microphone", "MICROPHONE_SET_SUCCESSFULLY": "Microphone set successfully", "MICROPHONES": "Microphones", diff --git a/dash-frontend/assets/lang/es.json b/dash-frontend/assets/lang/es.json index 497fc6b..661f90a 100644 --- a/dash-frontend/assets/lang/es.json +++ b/dash-frontend/assets/lang/es.json @@ -40,8 +40,7 @@ "NO_VR_MICROPHONE_SWITCH_MANUALLY": "No se encontró micrófono VR. Actívelo manualmente.", "FAILED_TO_SWITCH_MICROPHONE": "No se pudo cambiar el micrófono", "MICROPHONE_SET_SUCCESSFULLY": "Micrófono configurado correctamente", - "SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente", - "DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Dispositivo encontrado e inicializado, pero no cambiado" + "SPEAKERS_SET_SUCCESSFULLY": "Altavoces configurados correctamente" }, "ACTIONS": { "RECENTER_PLAYSPACE": "Re-centrar espacio de juego" diff --git a/dash-frontend/assets/lang/ja.json b/dash-frontend/assets/lang/ja.json index 9be1c93..4f9d387 100644 --- a/dash-frontend/assets/lang/ja.json +++ b/dash-frontend/assets/lang/ja.json @@ -40,8 +40,7 @@ "NO_VR_MICROPHONE_SWITCH_MANUALLY": "VRマイクが見つかりませんでした。手動で切り替えてください。", "FAILED_TO_SWITCH_MICROPHONE": "マイクの切り替えに失敗しました", "MICROPHONE_SET_SUCCESSFULLY": "マイクの設定が完了しました", - "SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定しました", - "DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "デバイスが見つかり、初期化されましたが、切り替えられていません" + "SPEAKERS_SET_SUCCESSFULLY": "スピーカーを設定しました" }, "ACTIONS": { "RECENTER_PLAYSPACE": "プレイスペースを再中央" diff --git a/dash-frontend/assets/lang/pl.json b/dash-frontend/assets/lang/pl.json index 304d832..29ad660 100644 --- a/dash-frontend/assets/lang/pl.json +++ b/dash-frontend/assets/lang/pl.json @@ -26,7 +26,6 @@ "AUDIO": { "AUTO_SWITCH_TO_VR_AUDIO": "Automatyczne przełączanie na dźwięk VR", "CARDS": "Karty", - "DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED": "Urządzenie znalezione i zainicjalizowane, ale nie przełączone", "FAILED_TO_SWITCH_MICROPHONE": "Nie udało się przełączyć mikrofon", "MICROPHONE_SET_SUCCESSFULLY": "Mikrofon ustawiono pomyślnie", "MICROPHONES": "Mikrofony", diff --git a/dash-frontend/src/views/audio_settings.rs b/dash-frontend/src/views/audio_settings.rs index 909743c..3116e73 100644 --- a/dash-frontend/src/views/audio_settings.rs +++ b/dash-frontend/src/views/audio_settings.rs @@ -18,7 +18,7 @@ use wgui::{ use crate::{ frontend::{FrontendTask, FrontendTasks}, - util::pactl_wrapper, + util::pactl_wrapper::{self}, }; #[derive(Clone)] @@ -172,7 +172,8 @@ fn does_string_mention_hmd_sink(input: &str) -> bool { lwr.contains("index") || // Valve hardware lwr.contains("oculus") || // Oculus lwr.contains("rift") || // Also Oculus - lwr.contains("beyond") // Bigscreen Beyond + lwr.contains("beyond") || // Bigscreen Beyond + lwr.contains("wivrn") // WiVRn } fn does_string_mention_hmd_source(input: &str) -> bool { @@ -180,7 +181,8 @@ fn does_string_mention_hmd_source(input: &str) -> bool { lwr.contains("hmd") || // generic hmd name detected lwr.contains("valve") || // Valve hardware lwr.contains("oculus") || // Oculus - lwr.contains("beyond") // Bigscreen Beyond + lwr.contains("beyond") || // Bigscreen Beyond + lwr.contains("wivrn") // WiVRn } fn is_card_mentioning_hmd(card: &pactl_wrapper::Card) -> bool { @@ -401,7 +403,30 @@ struct MountDeviceSliderParams<'a> { alt_desc: String, } +fn push_popup_speakers_set_successfully(globals: &WguiGlobals, frontend_tasks: &FrontendTasks, name: &str) { + frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key( + format!( + "{}: {}", + globals.i18n().translate("AUDIO.SPEAKERS_SET_SUCCESSFULLY"), + name + ) + .as_str(), + ))); +} + +fn push_popup_microphone_set_successfully(globals: &WguiGlobals, frontend_tasks: &FrontendTasks, name: &str) { + frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key( + format!( + "{}: {}", + globals.i18n().translate("AUDIO.MICROPHONE_SET_SUCCESSFULLY"), + name + ) + .as_str(), + ))); +} + fn switch_sink_card( + globals: &WguiGlobals, frontend_tasks: &FrontendTasks, card: &pactl_wrapper::Card, profile_name: &str, @@ -424,32 +449,32 @@ fn switch_sink_card( } if sink_found { - frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key( - format!("[AUDIO.SPEAKERS_SET_SUCCESSFULLY]: {}", name.name).as_str(), - ))); + push_popup_speakers_set_successfully(globals, frontend_tasks, &name.name); } else { frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key( - format!("[AUDIO.DEVICE_FOUND_AND_INITIALIZED_BUT_NOT_SWITCHED]: {}", name.name).as_str(), + format!("Card found ({}), but no matching speakers found", name.name).as_str(), ))); } Ok(()) } -fn switch_source(frontend_tasks: &FrontendTasks, source: &pactl_wrapper::Source) -> anyhow::Result<()> { +fn switch_source( + globals: &WguiGlobals, + frontend_tasks: &FrontendTasks, + source: &pactl_wrapper::Source, +) -> anyhow::Result<()> { match pactl_wrapper::set_default_source(source.index) { Ok(()) => { - frontend_tasks.push(FrontendTask::PushToast(Translation::from_translation_key( - format!( - "[AUDIO.MICROPHONE_SET_SUCCESSFULLY]: {}", - if let Some(card_name) = &source.properties.card_name { - card_name - } else { - &source.description - } - ) - .as_str(), - ))); + push_popup_microphone_set_successfully( + globals, + frontend_tasks, + if let Some(card_name) = &source.properties.card_name { + card_name + } else { + &source.description + }, + ); Ok(()) } Err(e) => { @@ -459,13 +484,13 @@ fn switch_source(frontend_tasks: &FrontendTasks, source: &pactl_wrapper::Source) } } -fn switch_to_vr_microphone(frontend_tasks: &FrontendTasks) -> anyhow::Result<()> { +fn switch_to_vr_microphone(globals: &WguiGlobals, frontend_tasks: &FrontendTasks) -> anyhow::Result<()> { let sources = pactl_wrapper::list_sources()?; let mut switched = false; for source in &sources { if is_source_mentioning_hmd(source) { - switch_source(frontend_tasks, source)?; + switch_source(globals, frontend_tasks, source)?; switched = true; break; } @@ -529,10 +554,20 @@ fn get_best_profile_from_array<'a>(arr: &[CardPriorityResult<'a>]) -> Option anyhow::Result<()> { +fn switch_to_vr_speakers(globals: &WguiGlobals, frontend_tasks: &FrontendTasks) -> anyhow::Result<()> { let cards = pactl_wrapper::list_cards()?; + let sinks = pactl_wrapper::list_sinks()?; let mut best_profiles = Vec::new(); + // Check for WiVRn presence + for sink in sinks { + if sink.name.contains("wivrn") { + pactl_wrapper::set_default_sink(sink.index)?; + push_popup_speakers_set_successfully(globals, frontend_tasks, "WiVRn"); + return Ok(()); + } + } + for card in &cards { if !is_card_mentioning_hmd(card) { continue; @@ -545,7 +580,7 @@ fn switch_to_vr_speakers(frontend_tasks: &FrontendTasks) -> anyhow::Result<()> { if !best_profiles.is_empty() { let best_profile = get_best_profile_from_array(&best_profiles).unwrap(); let name = get_profile_display_name(&best_profile.name, best_profile.card); - switch_sink_card(frontend_tasks, best_profile.card, &best_profile.name, &name)?; + switch_sink_card(globals, frontend_tasks, best_profile.card, &best_profile.name, &name)?; return Ok(()); } @@ -556,7 +591,7 @@ fn switch_to_vr_speakers(frontend_tasks: &FrontendTasks) -> anyhow::Result<()> { if !name.is_vr { continue; } - switch_sink_card(frontend_tasks, card, profile_name, &name)?; + switch_sink_card(globals, frontend_tasks, card, profile_name, &name)?; return Ok(()); } } @@ -684,8 +719,8 @@ impl View { pactl_wrapper::set_card_profile(c.card.index, &c.profile_name)?; } ViewTask::AutoSwitch => { - switch_to_vr_microphone(&self.frontend_tasks)?; - switch_to_vr_speakers(&self.frontend_tasks)?; + switch_to_vr_speakers(&self.globals, &self.frontend_tasks)?; + switch_to_vr_microphone(&self.globals, &self.frontend_tasks)?; self.tasks.push(ViewTask::Remount); } } @@ -745,8 +780,14 @@ impl View { par.insert("device_name".into(), disp.name.as_str().into()); par.insert("device_icon".into(), disp.icon_path.into()); } else { + let icon_path = if params.alt_desc.contains("WiVRn") { + "dashboard/wivrn_head_symbolic.svg" + } else { + "dashboard/binary.svg" + }; + par.insert("device_name".into(), params.alt_desc.into()); - par.insert("device_icon".into(), "dashboard/binary.svg".into()); + par.insert("device_icon".into(), icon_path.into()); } par.insert(