screenreader: Clean up code, memory allocations a bit

This commit is contained in:
Vicki Pfau 2025-07-04 15:27:35 -07:00
parent 98774dea76
commit 4355f90ae9
2 changed files with 36 additions and 35 deletions

View file

@ -308,11 +308,7 @@ impl CpuScaling1 {
let governors = get_available_cpu_scaling_governors() let governors = get_available_cpu_scaling_governors()
.await .await
.map_err(to_zbus_fdo_error)?; .map_err(to_zbus_fdo_error)?;
let mut result = Vec::new(); Ok(governors.into_iter().map(|g| g.to_string()).collect())
for g in governors {
result.push(g.to_string());
}
Ok(result)
} }
#[zbus(property)] #[zbus(property)]
@ -712,7 +708,7 @@ impl ScreenReader0 {
} }
#[zbus(property)] #[zbus(property)]
async fn voice(&self) -> String { async fn voice(&self) -> &str {
self.screen_reader.voice() self.screen_reader.voice()
} }
@ -730,13 +726,13 @@ impl ScreenReader0 {
} }
#[zbus(property)] #[zbus(property)]
async fn voice_locales(&self) -> Vec<String> { async fn voice_locales(&self) -> Vec<&str> {
self.screen_reader.get_voice_locales() self.screen_reader.get_voice_locales()
} }
#[zbus(property)] #[zbus(property)]
async fn voices_for_locale(&self) -> HashMap<String, Vec<String>> { async fn voices_for_locale(&self) -> HashMap<String, Vec<String>> {
self.screen_reader.get_voices() self.screen_reader.get_voices().clone()
} }
async fn trigger_action(&mut self, a: u32, timestamp: u64) -> fdo::Result<()> { async fn trigger_action(&mut self, a: u32, timestamp: u64) -> fdo::Result<()> {

View file

@ -109,6 +109,10 @@ pub(crate) struct OrcaManager<'dbus> {
voices_by_language: HashMap<String, Vec<String>>, voices_by_language: HashMap<String, Vec<String>>,
} }
fn default_map() -> Value {
Value::Object(Map::new())
}
impl<'dbus> OrcaManager<'dbus> { impl<'dbus> OrcaManager<'dbus> {
pub async fn new(connection: &Connection) -> Result<OrcaManager<'dbus>> { pub async fn new(connection: &Connection) -> Result<OrcaManager<'dbus>> {
let mut manager = OrcaManager { let mut manager = OrcaManager {
@ -146,7 +150,7 @@ impl<'dbus> OrcaManager<'dbus> {
match manager.init_voice_list() { match manager.init_voice_list() {
Ok(()) => trace!("Voice list loaded"), Ok(()) => trace!("Voice list loaded"),
Err(e) => error!("Unable to init voice list. {e}"), Err(e) => error!("Unable to init voice list: {e}"),
} }
Ok(manager) Ok(manager)
@ -161,22 +165,20 @@ impl<'dbus> OrcaManager<'dbus> {
.name; .name;
let connection = let connection =
SDConnection::open(CLIENT_NAME, CONNECTION_NAME, &user_name, Mode::Threaded)?; SDConnection::open(CLIENT_NAME, CONNECTION_NAME, &user_name, Mode::Threaded)?;
let voices = connection.list_synthesis_voices()?.to_vec(); let voices = connection.list_synthesis_voices()?;
for v in voices.iter() { for v in voices.into_iter() {
let name = &v.name;
let lang = &v.language;
self.voices.insert(name.clone(), v.clone());
self.voices_by_language self.voices_by_language
.entry(lang.clone()) .entry(v.language.clone())
.or_default() .or_default()
.push(name.clone()); .push(v.name.clone());
self.voices.insert(v.name.clone(), v);
} }
Ok(()) Ok(())
} }
pub fn get_voices(&self) -> HashMap<String, Vec<String>> { pub fn get_voices(&self) -> &HashMap<String, Vec<String>> {
self.voices_by_language.clone() &self.voices_by_language
} }
#[cfg(test)] #[cfg(test)]
@ -194,8 +196,8 @@ impl<'dbus> OrcaManager<'dbus> {
Ok(()) Ok(())
} }
pub fn get_voice_locales(&self) -> Vec<String> { pub fn get_voice_locales(&self) -> Vec<&str> {
self.voices_by_language.keys().cloned().collect() self.voices_by_language.keys().map(String::as_str).collect()
} }
#[cfg(not(test))] #[cfg(not(test))]
@ -241,8 +243,8 @@ impl<'dbus> OrcaManager<'dbus> {
Ok(()) Ok(())
} }
pub fn voice(&self) -> String { pub fn voice(&self) -> &str {
self.voice.clone() self.voice.as_str()
} }
pub async fn set_voice(&mut self, voice: &str) -> Result<()> { pub async fn set_voice(&mut self, voice: &str) -> Result<()> {
@ -423,7 +425,7 @@ impl<'dbus> OrcaManager<'dbus> {
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf json is not an object"))? .ok_or(anyhow!("orca user-settings.conf json is not an object"))?
.entry("general") .entry("general")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
general general
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf general is not an object"))? .ok_or(anyhow!("orca user-settings.conf general is not an object"))?
@ -511,35 +513,38 @@ impl<'dbus> OrcaManager<'dbus> {
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf json is not an object"))? .ok_or(anyhow!("orca user-settings.conf json is not an object"))?
.entry("profiles") .entry("profiles")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
let default_profile = profiles let default_profile = profiles
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf profiles is not an object"))? .ok_or(anyhow!("orca user-settings.conf profiles is not an object"))?
.entry("default") .entry("default")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
let voices = default_profile let voices = default_profile
.as_object_mut() .as_object_mut()
.ok_or(anyhow!( .ok_or(anyhow!(
"orca user-settings.conf default profile is not an object" "orca user-settings.conf default profile is not an object"
))? ))?
.entry("voices") .entry("voices")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
let default_voice = voices let default_voice = voices
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf voices is not an object"))? .ok_or(anyhow!("orca user-settings.conf voices is not an object"))?
.entry("default") .entry("default")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
let family = default_voice let family = default_voice
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf family is not an object"))? .ok_or(anyhow!("orca user-settings.conf family is not an object"))?
.entry("family") .entry("family")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
// If we have a dialect use it, otherwise leave it blank // If we have a dialect use it, otherwise leave it blank
let mut language = voice.language.clone(); let language;
let mut dialect = ""; let dialect;
if let Some((l, d)) = voice.language.split_once("-") { if let Some((l, d)) = voice.language.split_once("-") {
language = l.to_string(); language = l;
dialect = d; dialect = d;
} else {
language = voice.language.as_str();
dialect = "";
} }
let mut_family = family.as_object_mut().ok_or(anyhow!( let mut_family = family.as_object_mut().ok_or(anyhow!(
"orca user-settings.conf default voice family is not an object" "orca user-settings.conf default voice family is not an object"
@ -580,24 +585,24 @@ impl<'dbus> OrcaManager<'dbus> {
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf json is not an object"))? .ok_or(anyhow!("orca user-settings.conf json is not an object"))?
.entry("profiles") .entry("profiles")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
let default_profile = profiles let default_profile = profiles
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf profiles is not an object"))? .ok_or(anyhow!("orca user-settings.conf profiles is not an object"))?
.entry("default") .entry("default")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
let voices = default_profile let voices = default_profile
.as_object_mut() .as_object_mut()
.ok_or(anyhow!( .ok_or(anyhow!(
"orca user-settings.conf default profile is not an object" "orca user-settings.conf default profile is not an object"
))? ))?
.entry("voices") .entry("voices")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
let default_voice = voices let default_voice = voices
.as_object_mut() .as_object_mut()
.ok_or(anyhow!("orca user-settings.conf voices is not an object"))? .ok_or(anyhow!("orca user-settings.conf voices is not an object"))?
.entry("default") .entry("default")
.or_insert(Value::Object(Map::new())); .or_insert_with(default_map);
default_voice default_voice
.as_object_mut() .as_object_mut()
.ok_or(anyhow!( .ok_or(anyhow!(