diff --git a/src/main.rs b/src/main.rs index 9c7ef7f..256c849 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; use clap::Parser; +use log::error; use mpris::PlayerFinder; use structs::cli::Cli; use structs::{config::Config, data::Data}; @@ -23,9 +24,9 @@ fn handle_signal(data: &Data) { } } -fn default_loop(pf: &PlayerFinder, cfg: &Config, data: &mut Data) { +fn default_loop(pf: &PlayerFinder, cfg: &Config, data: &mut Data, r: &Vec) { update_players(pf, cfg, data); - update_message(cfg, data); + update_message(cfg, data, r); print_text(cfg, data); } @@ -39,6 +40,8 @@ fn main() { match confy::load::("polybar-now-playing", cli.config_file.as_str()) { Ok(cfg) => { let mut data: Data = Data::default(); + let rating_strings = cfg.build_rating_strings(); + let term = Arc::new(AtomicBool::new(false)); let pf: PlayerFinder = PlayerFinder::new() @@ -49,11 +52,10 @@ fn main() { } loop { - // thread::sleep(cfg.update_delay); thread::sleep(time::Duration::from_millis(cfg.update_delay)); match cli.debug { true => print_players(&pf), - false => default_loop(&pf, &cfg, &mut data), + false => default_loop(&pf, &cfg, &mut data, &rating_strings), } if term.load(Ordering::Relaxed) { @@ -62,6 +64,9 @@ fn main() { }; } }, - Err(_) => println!("Failed to read config file {}", cli.config_file), + Err(e) => { + error!("{e}"); + println!("Failed to read config file {}", cli.config_file); + }, }; } diff --git a/src/structs/config.rs b/src/structs/config.rs index 0032351..0b724f6 100644 --- a/src/structs/config.rs +++ b/src/structs/config.rs @@ -28,11 +28,27 @@ pub struct Rating { } impl Rating { - pub fn repeat(c: char, n: usize) -> String { + fn repeat(c: char, n: usize) -> String { let mut s = c.to_string(); s.push(' '); s.repeat(n) } + + fn build_rating_strings(&self) -> Vec { + let mut out = Vec::new(); + out.push(Self::repeat(self.nil, 5)); + out.push(format!("{}{}", Self::repeat(self.half, 1), Self::repeat(self.nil, 4))); + out.push(format!("{}{}", Self::repeat(self.full, 1), Self::repeat(self.nil, 4))); + out.push(format!("{}{}{}", Self::repeat(self.full, 1), Self::repeat(self.half, 1), Self::repeat(self.nil, 3))); + out.push(format!("{}{}", Self::repeat(self.full, 2), Self::repeat(self.nil, 3))); + out.push(format!("{}{}{}", Self::repeat(self.full, 2), Self::repeat(self.half, 1), Self::repeat(self.nil, 2))); + out.push(format!("{}{}", Self::repeat(self.full, 3), Self::repeat(self.nil, 2))); + out.push(format!("{}{}{}", Self::repeat(self.full, 3), Self::repeat(self.half, 1), Self::repeat(self.nil, 1))); + out.push(format!("{}{}", Self::repeat(self.full, 4), Self::repeat(self.nil, 1))); + out.push(format!("{}{}", Self::repeat(self.full, 4), Self::repeat(self.half, 1))); + out.push(Self::repeat(self.full, 5)); + out + } } impl Default for Rating { @@ -87,6 +103,13 @@ impl Config { } } + pub fn build_rating_strings(&self) -> Vec { + match self.rating_icons.as_ref() { + Some(r) => r.build_rating_strings(), + None => Rating::default().build_rating_strings(), + } + } + fn default_player_priorities() -> Vec { vec![ "Clementine".to_owned(), diff --git a/src/structs/data.rs b/src/structs/data.rs index 6d9970f..cdcb040 100644 --- a/src/structs/data.rs +++ b/src/structs/data.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use mpris::Player; pub struct Data { - pub current_player: Option, + pub current_player: Option, pub display_text: HashMap, pub display_prefix: char, } diff --git a/src/update_message.rs b/src/update_message.rs index 830176f..f4b2acb 100644 --- a/src/update_message.rs +++ b/src/update_message.rs @@ -1,4 +1,6 @@ +use log::error; use mpris::{MetadataValue}; +use string_builder::Builder; use crate::structs::{config::{Rating, Config}, data::Data}; @@ -28,32 +30,15 @@ fn value_to_string(v: &MetadataValue, sep: char) -> String { } } -fn rating_to_string(r: Option<&MetadataValue>, opt: Option<&Rating>) -> Option { - let def = Rating::default(); - let map: &Rating; - match opt { - Some(m) => map = m, - None => map = &def, - } - +fn rating_to_string(r: Option<&MetadataValue>, str: &Vec) -> Option { match r { Some(rating) => { if let Some(f) = rating.as_f64() { - let i = (f * 10_f64).round() as i64; - match i { //TODO: refactor this - 0 => Some(Rating::repeat(map.nil, 5)), - 1 => Some(format!("{}{}", Rating::repeat(map.half, 1), Rating::repeat(map.nil, 4))), - 2 => Some(format!("{}{}", Rating::repeat(map.full, 1), Rating::repeat(map.nil, 4))), - 3 => Some(format!("{}{}{}", Rating::repeat(map.full, 1), Rating::repeat(map.half, 1), Rating::repeat(map.nil, 3))), - 4 => Some(format!("{}{}", Rating::repeat(map.full, 2), Rating::repeat(map.nil, 3))), - 5 => Some(format!("{}{}{}", Rating::repeat(map.full, 2), Rating::repeat(map.half, 1), Rating::repeat(map.nil, 2))), - 6 => Some(format!("{}{}", Rating::repeat(map.full, 3), Rating::repeat(map.nil, 2))), - 7 => Some(format!("{}{}{}", Rating::repeat(map.full, 3), Rating::repeat(map.half, 1), Rating::repeat(map.nil, 1))), - 8 => Some(format!("{}{}", Rating::repeat(map.full, 4), Rating::repeat(map.nil, 1))), - 9 => Some(format!("{}{}", Rating::repeat(map.full, 4), Rating::repeat(map.half, 1))), - 10.. => Some(Rating::repeat(map.full, 5)), - _ => Some(format!("Invalid rating!")) - } + let mut i = (f * 10_f64).round() as i64; + if i > 10 {i = 10} + if i < 0 {i = 0} + + Some(str[i as usize].clone()) //TODO: still inefficient. would be better to note the idx and load it in print_text } else { None } @@ -64,13 +49,13 @@ fn rating_to_string(r: Option<&MetadataValue>, opt: Option<&Rating>) -> Option) { if let Some(player) = &data.current_player { if let Ok(meta) = player.get_metadata() { for field in &cfg.metadata_fields { let key = field.field.clone(); if field.field.eq("xesam:userRating") { - if let Some(rating_string) = rating_to_string(meta.get(&key), cfg.rating_icons.as_ref()) { + if let Some(rating_string) = rating_to_string(meta.get(&key), ratings) { data.display_text.insert(key, rating_string); } else { data.display_text.remove(&key);