improve error handling

This commit is contained in:
galister
2024-03-17 16:11:05 +01:00
parent 1d1230b1e7
commit 54dfb297ac
6 changed files with 67 additions and 45 deletions

View File

@@ -136,8 +136,8 @@ impl GeneralConfig {
} }
fn post_load(&self) { fn post_load(&self) {
GeneralConfig::sanitize_range("keyboard_scale", self.keyboard_scale, 0.0, 5.0); GeneralConfig::sanitize_range("keyboard_scale", self.keyboard_scale, 0.05, 5.0);
GeneralConfig::sanitize_range("desktop_view_scale", self.desktop_view_scale, 0.0, 5.0); GeneralConfig::sanitize_range("desktop_view_scale", self.desktop_view_scale, 0.05, 5.0);
} }
} }
@@ -192,12 +192,31 @@ pub fn load_general() -> GeneralConfig {
// Add files from conf.d directory // Add files from conf.d directory
let path_conf_d = get_conf_d_path(); let path_conf_d = get_conf_d_path();
if let Ok(paths_unsorted) = std::fs::read_dir(path_conf_d) { if let Ok(paths_unsorted) = std::fs::read_dir(path_conf_d) {
let mut paths: Vec<_> = paths_unsorted
.filter_map(|r| match r {
Ok(entry) => Some(entry),
Err(e) => {
error!("Failed to read conf.d directory: {}", e);
None
}
})
.collect();
// Sort paths alphabetically // Sort paths alphabetically
let mut paths: Vec<_> = paths_unsorted.map(|r| r.unwrap()).collect(); // TODO safe unwrap?
paths.sort_by_key(|dir| dir.path()); paths.sort_by_key(|dir| dir.path());
for path in paths { for path in paths {
if !path.file_type().unwrap().is_file() { let file_type = match path.file_type() {
// TODO safe unwrap? Ok(file_type) => file_type,
Err(e) => {
error!(
"Failed to get file type of {}: {}",
path.path().to_string_lossy(),
e
);
continue;
}
};
if !file_type.is_file() {
continue; continue;
} }

View File

@@ -106,9 +106,7 @@ impl FontCache {
} }
let pattern_str = format!("{PRIMARY_FONT}-{size}:style=bold:charset={cp:04x}"); let pattern_str = format!("{PRIMARY_FONT}-{size}:style=bold:charset={cp:04x}");
let mut pattern = OwnedPattern::from_str(&pattern_str).unwrap(); // safe because PRIMARY_FONT is const
let mut pattern =
OwnedPattern::from_str(&pattern_str).expect("Failed to create fontconfig pattern");
self.fc self.fc
.substitute(&mut pattern, fontconfig::MatchKind::Pattern); .substitute(&mut pattern, fontconfig::MatchKind::Pattern);
pattern.default_substitute(); pattern.default_substitute();

View File

@@ -1,6 +1,5 @@
use std::{ use std::{
f32::consts::PI, f32::consts::PI,
io::Cursor,
ops::Add, ops::Add,
process::{self, Child}, process::{self, Child},
sync::Arc, sync::Arc,
@@ -8,7 +7,6 @@ use std::{
}; };
use glam::{Quat, Vec3A}; use glam::{Quat, Vec3A};
use rodio::{Decoder, Source};
use serde::Deserialize; use serde::Deserialize;
use crate::{ use crate::{
@@ -613,11 +611,8 @@ fn run_window(window: &Arc<str>, action: &WindowAction, app: &mut AppState) {
} }
} }
const THUMP_AUDIO_WAV: &'static [u8] = include_bytes!("../../res/380885.wav");
fn audio_thump(app: &mut AppState) { fn audio_thump(app: &mut AppState) {
if let Some(handle) = app.audio.get_handle() { app.audio.play(THUMP_AUDIO_WAV);
let wav = include_bytes!("../../res/380885.wav");
let cursor = Cursor::new(wav);
let source = Decoder::new_wav(cursor).unwrap();
let _ = handle.play_raw(source.convert_samples());
}
} }

View File

@@ -1,6 +1,5 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
io::Cursor,
process::{Child, Command}, process::{Child, Command},
str::FromStr, str::FromStr,
}; };
@@ -18,7 +17,6 @@ use crate::{
use glam::{vec2, vec3a, Affine2, Vec4}; use glam::{vec2, vec3a, Affine2, Vec4};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use rodio::{Decoder, Source};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
const PIXELS_PER_UNIT: f32 = 80.; const PIXELS_PER_UNIT: f32 = 80.;
@@ -83,10 +81,14 @@ where
verbs: key_events_for_macro(macro_verbs), verbs: key_events_for_macro(macro_verbs),
}); });
} else if let Some(exec_args) = LAYOUT.exec_commands.get(key) { } else if let Some(exec_args) = LAYOUT.exec_commands.get(key) {
if exec_args.is_empty() {
log::error!("Keyboard: EXEC args empty for {}", key);
continue;
}
maybe_state = Some(KeyButtonData::Exec { maybe_state = Some(KeyButtonData::Exec {
program: exec_args program: exec_args
.first() .first()
.expect("Keyboard: Invalid EXEC args") .unwrap() // safe because we checked is_empty
.clone(), .clone(),
args: exec_args.iter().skip(1).cloned().collect(), args: exec_args.iter().skip(1).cloned().collect(),
}); });
@@ -227,18 +229,12 @@ struct KeyboardData {
processes: Vec<Child>, processes: Vec<Child>,
} }
const KEY_AUDIO_WAV: &'static [u8] = include_bytes!("../res/421581.wav");
impl KeyboardData { impl KeyboardData {
fn key_click(&mut self, app: &mut AppState) { fn key_click(&mut self, app: &mut AppState) {
if !app.session.config.keyboard_sound_enabled { if app.session.config.keyboard_sound_enabled {
return; app.audio.play(KEY_AUDIO_WAV);
}
if let Some(handle) = app.audio.get_handle() {
// https://freesound.org/people/UberBosser/sounds/421581/
let wav = include_bytes!("../res/421581.wav");
let cursor = Cursor::new(wav);
let source = Decoder::new_wav(cursor).unwrap();
let _ = handle.play_raw(source.convert_samples());
} }
} }
} }
@@ -253,7 +249,7 @@ enum KeyButtonData {
static LAYOUT: Lazy<Layout> = Lazy::new(Layout::load_from_disk); static LAYOUT: Lazy<Layout> = Lazy::new(Layout::load_from_disk);
static MACRO_REGEX: Lazy<Regex> = static MACRO_REGEX: Lazy<Regex> =
Lazy::new(|| Regex::new(r"^([A-Za-z0-1_-]+)(?: +(UP|DOWN))?$").unwrap()); Lazy::new(|| Regex::new(r"^([A-Za-z0-1_-]+)(?: +(UP|DOWN))?$").unwrap()); // want panic
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct Layout { pub struct Layout {
@@ -314,11 +310,17 @@ impl Layout {
key = &key[3..]; key = &key[3..];
} }
if key.contains('_') { if key.contains('_') {
key = key.split('_').next().unwrap(); key = key.split('_').next().unwrap_or_else(|| {
log::error!(
"keyboard.yaml: Key '{}' must not start or end with '_'!",
key
);
"???"
});
} }
vec![format!( vec![format!(
"{}{}", "{}{}",
key.chars().next().unwrap().to_uppercase(), key.chars().next().unwrap().to_uppercase(), // safe because we checked is_empty
&key[1..].to_lowercase() &key[1..].to_lowercase()
)] )]
} }

View File

@@ -1,12 +1,9 @@
use std::{ use std::{
io::Cursor,
ops::Add, ops::Add,
sync::{atomic::AtomicUsize, Arc}, sync::{atomic::AtomicUsize, Arc},
time::Instant, time::Instant,
}; };
use rodio::{Decoder, Source};
use glam::vec3a; use glam::vec3a;
use crate::{ use crate::{
@@ -21,6 +18,7 @@ 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: &'static [u8] = include_bytes!("../res/557297.wav");
static AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(0); static AUTO_INCREMENT: AtomicUsize = AtomicUsize::new(0);
@@ -79,12 +77,7 @@ impl Toast {
.enqueue_at(TaskType::DropOverlay(selector), destroy_at); .enqueue_at(TaskType::DropOverlay(selector), destroy_at);
if has_sound { if has_sound {
if let Some(handle) = app.audio.get_handle() { app.audio.play(TOAST_AUDIO_WAV);
let wav = include_bytes!("../res/557297.wav");
let cursor = Cursor::new(wav);
let source = Decoder::new_wav(cursor).unwrap();
let _ = handle.play_raw(source.convert_samples());
}
} }
} }
} }

View File

@@ -1,8 +1,8 @@
use std::{path::PathBuf, sync::Arc}; use std::{io::Cursor, path::PathBuf, sync::Arc};
use anyhow::bail; use anyhow::bail;
use glam::Vec3; use glam::Vec3;
use rodio::{OutputStream, OutputStreamHandle}; use rodio::{Decoder, OutputStream, OutputStreamHandle, Source};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use vulkano::format::Format; use vulkano::format::Format;
@@ -126,18 +126,33 @@ impl AudioOutput {
} }
} }
pub fn get_handle(&mut self) -> Option<&OutputStreamHandle> { fn get_handle(&mut self) -> Option<&OutputStreamHandle> {
if self.audio_stream.is_none() && self.first_try { if self.audio_stream.is_none() && self.first_try {
self.first_try = false; self.first_try = false;
if let Ok((stream, handle)) = OutputStream::try_default() { if let Ok((stream, handle)) = OutputStream::try_default() {
self.audio_stream = Some((stream, handle)); self.audio_stream = Some((stream, handle));
} else { } else {
log::error!("Failed to open audio stream"); log::error!("Failed to open audio stream. Audio will not work.");
return None; return None;
} }
} }
self.audio_stream.as_ref().map(|(_, h)| h) self.audio_stream.as_ref().map(|(_, h)| h)
} }
pub fn play(&mut self, wav_bytes: &'static [u8]) {
let Some(handle) = self.get_handle() else {
return;
};
let cursor = Cursor::new(wav_bytes);
let source = match Decoder::new_wav(cursor) {
Ok(source) => source,
Err(e) => {
log::error!("Failed to play sound: {:?}", e);
return;
}
};
let _ = handle.play_raw(source.convert_samples());
}
} }
pub struct ScreenMeta { pub struct ScreenMeta {