Compare commits

...

3 Commits

5 changed files with 66 additions and 46 deletions

View File

@ -37,7 +37,7 @@ fn handle_signal(data: &Data) {
} }
} }
/// This function contains the default maim loop body of the program. /// This function contains the default main loop body of the program.
/// It updates the active player, updates the output strings based on this, and finally formats and outputs these strings to stdout. /// It updates the active player, updates the output strings based on this, and finally formats and outputs these strings to stdout.
/// ///
/// input: /// input:

View File

@ -1,5 +1,5 @@
//! This file deals with formatting and outputting to stdout. //! This file deals with formatting and outputting to stdout.
use log::{error, info}; use log::error;
use std::collections::HashMap; use std::collections::HashMap;
use string_builder::Builder; use string_builder::Builder;
@ -85,12 +85,25 @@ fn append_prefix(b: &mut Builder, data: &Data) {
/// data: Data struct containing the field-text HashMap. /// data: Data struct containing the field-text HashMap.
fn append_fields(b: &mut Builder, cfg: &Config, data: &Data) { fn append_fields(b: &mut Builder, cfg: &Config, data: &Data) {
let mut idx = 0; let mut idx = 0;
let len = data.field_text.len() as i32;
for field in &cfg.metadata_fields { for field in &cfg.metadata_fields {
if let Some(string) = data.field_text.get(&field.field) { // setup (string, fmt) to contain placeholder or data, if extant.
let f = data.field_text.get(&field.field);
let (string, fmt) = if f.is_some() {
(f.unwrap(), &field.format)
} else if field.placeholder.len() != 0 {
(&field.field, &field.placeholder)
} else {
continue;
};
// insert separator in front of non-empty non-first field.
if idx > 0 {
b.append(cfg.metadata_separator.as_str())
};
idx += 1; idx += 1;
// FIXME: extract to its' own function.
if cfg.escape_chars { if cfg.escape_chars {
let s: &String = &string let s: &String = &string
.chars() .chars()
@ -100,15 +113,9 @@ fn append_fields(b: &mut Builder, cfg: &Config, data: &Data) {
}) })
.collect(); .collect();
b.append(field.format.replace("{}", s.as_str())); b.append(fmt.replace("{}", s.as_str()));
} else { } else {
b.append(field.format.replace("{}", string.as_str())); b.append(fmt.replace("{}", string));
}
if idx < len {
b.append(cfg.metadata_separator.as_str())
};
} else {
info!("failed to get {} value!", field.field);
} }
} }
} }

View File

@ -12,6 +12,8 @@ pub struct Field {
pub num_chars: u32, pub num_chars: u32,
/// Formatting to apply. (the value "{}" is substituted with the actual string) /// Formatting to apply. (the value "{}" is substituted with the actual string)
pub format: String, pub format: String,
/// Placeholder string to insert when the field is empty. (the value "{}" is substituted with the actual string).
pub placeholder: String,
} }
impl Field { impl Field {
@ -20,14 +22,16 @@ impl Field {
/// field: name of the field /// field: name of the field
/// num_chars: maximum length of the field /// num_chars: maximum length of the field
/// format: what formatting to apply to the field /// format: what formatting to apply to the field
/// placeholder: the placeholder string to use
/// ///
/// returns: /// returns:
/// a new Field with the given parameters. /// a new Field with the given parameters.
fn new(field: String, num_chars: u32, format: String) -> Self { fn new(field: String, num_chars: u32, format: String, placeholder: String) -> Self {
Field { Field {
field, field,
num_chars, num_chars,
format, format,
placeholder,
} }
} }
@ -36,15 +40,29 @@ impl Field {
/// field: name of the field /// field: name of the field
/// num_chars: maximum length of the field /// num_chars: maximum length of the field
/// format: (optional), formatting to apply. /// format: (optional), formatting to apply.
/// placeholder: (optional), what placeholder to use.
/// ///
/// returns: /// returns:
/// a new Field with the given parameters. /// a new Field with the given parameters.
pub fn constructor(field: &str, num_chars: u32, format: Option<String>) -> Self { pub fn constructor(
if let Some(format) = format { field: &str,
Self::new(field.to_owned(), num_chars, format) num_chars: u32,
format: Option<String>,
placeholder: Option<String>,
) -> Self {
let fmt = if format.is_some() {
format.unwrap()
} else { } else {
Self::new(field.to_owned(), num_chars, "{}".to_owned()) "{}".to_owned()
} };
let place = if placeholder.is_some() {
placeholder.unwrap()
} else {
"No {}".to_owned()
};
Self::new(field.to_owned(), num_chars, fmt, place)
} }
} }
@ -241,8 +259,8 @@ impl Config {
/// It contains the "title" and "artist" fields, with 40 and 20 maximum characters respectively. /// It contains the "title" and "artist" fields, with 40 and 20 maximum characters respectively.
fn default_metadata_fields() -> Vec<Field> { fn default_metadata_fields() -> Vec<Field> {
vec![ vec![
Field::constructor("xesam:title", 40, None), Field::constructor("xesam:title", 40, None, None),
Field::constructor("xesam:artist", 20, None), Field::constructor("xesam:artist", 20, None, None),
] ]
} }

View File

@ -109,19 +109,14 @@ pub fn update_message(cfg: &Config, data: &mut Data, ratings: &Vec<String>) {
key, key,
value_to_string(value, cfg.array_separator) value_to_string(value, cfg.array_separator)
); );
data.field_text
.insert(key.to_owned(), value_to_string(value, cfg.array_separator))
}
None => {
trace!("update_messages: field {} has no value!", key);
if field.field.eq("bs:isFavorite") {
data.field_text.remove(key);
continue;
}
data.field_text.insert( data.field_text.insert(
key.to_owned(), key.to_owned(),
format!("No {}", key.trim_start_matches("xesam:")), value_to_string(value, cfg.array_separator),
) );
}
None => {
trace!("update_messages: field {} has no value", key);
data.field_text.remove(key);
} }
}; };
} }

View File

@ -38,14 +38,14 @@ pub fn update_players(pf: &PlayerFinder, cfg: &Config, data: &mut Data) {
data.current_player = None; data.current_player = None;
debug!("update_players: no players found!") debug!("update_players: no players found!")
} else { } else {
let mut trees = vec![BTreeMap::new(), BTreeMap::new()]; let mut trees = vec![BTreeMap::new(), BTreeMap::new(), BTreeMap::new()];
for player in players { for player in players {
if let Ok(status) = player.get_playback_status() { if let Ok(status) = player.get_playback_status() {
let idx = cfg.find_player_priorities_idx(player.identity()); let idx = cfg.find_player_priorities_idx(player.identity());
match status { match status {
mpris::PlaybackStatus::Playing => trees[0].insert(idx, player), mpris::PlaybackStatus::Playing => trees[0].insert(idx, player),
mpris::PlaybackStatus::Paused => trees[0].insert(idx, player), mpris::PlaybackStatus::Paused => trees[1].insert(idx, player),
mpris::PlaybackStatus::Stopped => trees[1].insert(idx, player), mpris::PlaybackStatus::Stopped => trees[2].insert(idx, player),
}; };
} }
} }