From 5f93bc9cac499196629ceff61d3c08fa8aff77a1 Mon Sep 17 00:00:00 2001 From: Jay <157681441+cubee-cb@users.noreply.github.com> Date: Mon, 24 Mar 2025 22:32:29 +1100 Subject: [PATCH] Config notification/toast sound (#179) * try adding config to load different sound looks like include_bytes!() doesn't take a variable parameter, so will need a different solution lol. * no errors in loading, but toast.rs now has a lifetime issue * hey, config toast sound works now! the sound is loaded in AppState now, since Toast are created in several different places at different times, and i don't want to load the sound every time a toast is made. also put back the original sound since i accidentally commited my custom one. * clean up * change custom toast sound leak to happen on load rather than every play * move toast sound loading into a function so it can be reused in the future, for example if we want to load arbitrary keypress sounds or other [u8] data. * remove label from try_load_bytes, return early when failing --- src/config.rs | 3 +++ src/overlays/toast.rs | 7 +++---- src/state.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/config.rs b/src/config.rs index 84ba31f..9915ee0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -207,6 +207,9 @@ pub struct GeneralConfig { #[serde(default = "def_toast_topics")] pub notification_topics: IdMap, + #[serde(default = "def_empty")] + pub notification_sound: Arc, + #[serde(default = "def_true")] pub keyboard_sound_enabled: bool, diff --git a/src/overlays/toast.rs b/src/overlays/toast.rs index 7e856f3..474cb2b 100644 --- a/src/overlays/toast.rs +++ b/src/overlays/toast.rs @@ -18,7 +18,6 @@ use crate::{ const FONT_SIZE: isize = 16; const PADDING: (f32, f32) = (25., 7.); const PIXELS_TO_METERS: f32 = 1. / 2000.; -const TOAST_AUDIO_WAV: &[u8] = include_bytes!("../res/557297.wav"); static TOAST_NAME: Lazy> = Lazy::new(|| "toast".into()); #[derive(Debug, Clone, Copy, Serialize, Deserialize)] @@ -78,6 +77,9 @@ impl Toast { let destroy_at = instant.add(std::time::Duration::from_secs_f32(self.timeout)); let has_sound = self.sound && app.session.config.notifications_sound_enabled; + if has_sound { + app.audio.play(app.toast_sound); + } // drop any toast that was created before us. // (DropOverlay only drops overlays that were @@ -109,9 +111,6 @@ impl Toast { instant, ); - if has_sound { - app.audio.play(TOAST_AUDIO_WAV); - } } } diff --git a/src/state.rs b/src/state.rs index 1cab906..314a2df 100644 --- a/src/state.rs +++ b/src/state.rs @@ -51,6 +51,7 @@ pub struct AppState { pub anchor: Affine3A, pub sprites: AStrMap>, pub keyboard_focus: KeyboardFocus, + pub toast_sound: &'static [u8], #[cfg(feature = "osc")] pub osc_sender: Option, @@ -111,6 +112,11 @@ impl AppState { #[cfg(feature = "osc")] let osc_sender = crate::backend::osc::OscSender::new(session.config.osc_out_port).ok(); + let toast_sound_wav = AppState::try_load_bytes( + &session.config.notification_sound, + include_bytes!("res/557297.wav") + ); + Ok(AppState { fc: FontCache::new(session.config.primary_font.clone())?, session, @@ -123,6 +129,7 @@ impl AppState { anchor: Affine3A::IDENTITY, sprites: AStrMap::new(), keyboard_focus: KeyboardFocus::PhysicalScreen, + toast_sound: toast_sound_wav, #[cfg(feature = "osc")] osc_sender, @@ -145,6 +152,40 @@ impl AppState { Ok(wayvr) } } + + pub fn try_load_bytes(path: &str, fallback_data: &'static [u8]) -> &'static [u8] + { + if path.is_empty() { + return fallback_data; + } + + let real_path = config_io::get_config_root().join(&*path); + + if std::fs::File::open(real_path.clone()).is_err() { + log::warn!( + "Could not open file at: {}", + path + ); + return fallback_data; + }; + + return match std::fs::read(real_path.clone()){ + // Box is used here to work around `f`'s limited lifetime + Ok(f) => { + Box::leak(Box::new(f)).as_slice() + }, + Err(e) => { + log::warn!( + "Failed to read file at: {}", + path + ); + log::warn!("{:?}", e); + fallback_data + } + }; + + } + } pub struct AppSession {