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
This commit is contained in:
@@ -207,6 +207,9 @@ pub struct GeneralConfig {
|
|||||||
#[serde(default = "def_toast_topics")]
|
#[serde(default = "def_toast_topics")]
|
||||||
pub notification_topics: IdMap<ToastTopic, DisplayMethod>,
|
pub notification_topics: IdMap<ToastTopic, DisplayMethod>,
|
||||||
|
|
||||||
|
#[serde(default = "def_empty")]
|
||||||
|
pub notification_sound: Arc<str>,
|
||||||
|
|
||||||
#[serde(default = "def_true")]
|
#[serde(default = "def_true")]
|
||||||
pub keyboard_sound_enabled: bool,
|
pub keyboard_sound_enabled: bool,
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ use crate::{
|
|||||||
const FONT_SIZE: isize = 16;
|
const FONT_SIZE: isize = 16;
|
||||||
const PADDING: (f32, f32) = (25., 7.);
|
const PADDING: (f32, f32) = (25., 7.);
|
||||||
const PIXELS_TO_METERS: f32 = 1. / 2000.;
|
const PIXELS_TO_METERS: f32 = 1. / 2000.;
|
||||||
const TOAST_AUDIO_WAV: &[u8] = include_bytes!("../res/557297.wav");
|
|
||||||
static TOAST_NAME: Lazy<Arc<str>> = Lazy::new(|| "toast".into());
|
static TOAST_NAME: Lazy<Arc<str>> = Lazy::new(|| "toast".into());
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[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 destroy_at = instant.add(std::time::Duration::from_secs_f32(self.timeout));
|
||||||
|
|
||||||
let has_sound = self.sound && app.session.config.notifications_sound_enabled;
|
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.
|
// drop any toast that was created before us.
|
||||||
// (DropOverlay only drops overlays that were
|
// (DropOverlay only drops overlays that were
|
||||||
@@ -109,9 +111,6 @@ impl Toast {
|
|||||||
instant,
|
instant,
|
||||||
);
|
);
|
||||||
|
|
||||||
if has_sound {
|
|
||||||
app.audio.play(TOAST_AUDIO_WAV);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
41
src/state.rs
41
src/state.rs
@@ -51,6 +51,7 @@ pub struct AppState {
|
|||||||
pub anchor: Affine3A,
|
pub anchor: Affine3A,
|
||||||
pub sprites: AStrMap<Arc<ImageView>>,
|
pub sprites: AStrMap<Arc<ImageView>>,
|
||||||
pub keyboard_focus: KeyboardFocus,
|
pub keyboard_focus: KeyboardFocus,
|
||||||
|
pub toast_sound: &'static [u8],
|
||||||
|
|
||||||
#[cfg(feature = "osc")]
|
#[cfg(feature = "osc")]
|
||||||
pub osc_sender: Option<OscSender>,
|
pub osc_sender: Option<OscSender>,
|
||||||
@@ -111,6 +112,11 @@ impl AppState {
|
|||||||
#[cfg(feature = "osc")]
|
#[cfg(feature = "osc")]
|
||||||
let osc_sender = crate::backend::osc::OscSender::new(session.config.osc_out_port).ok();
|
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 {
|
Ok(AppState {
|
||||||
fc: FontCache::new(session.config.primary_font.clone())?,
|
fc: FontCache::new(session.config.primary_font.clone())?,
|
||||||
session,
|
session,
|
||||||
@@ -123,6 +129,7 @@ impl AppState {
|
|||||||
anchor: Affine3A::IDENTITY,
|
anchor: Affine3A::IDENTITY,
|
||||||
sprites: AStrMap::new(),
|
sprites: AStrMap::new(),
|
||||||
keyboard_focus: KeyboardFocus::PhysicalScreen,
|
keyboard_focus: KeyboardFocus::PhysicalScreen,
|
||||||
|
toast_sound: toast_sound_wav,
|
||||||
|
|
||||||
#[cfg(feature = "osc")]
|
#[cfg(feature = "osc")]
|
||||||
osc_sender,
|
osc_sender,
|
||||||
@@ -145,6 +152,40 @@ impl AppState {
|
|||||||
Ok(wayvr)
|
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 {
|
pub struct AppSession {
|
||||||
|
|||||||
Reference in New Issue
Block a user