fix: workaround for a bug where playing players are somtimes incorrectly reported as paused
This commit is contained in:
parent
c074b4279e
commit
d34e842f3e
|
|
@ -17,29 +17,34 @@ use crate::structs::{config::Config, data::Data};
|
||||||
/// Output:
|
/// Output:
|
||||||
/// String representing the input MetadataValue.
|
/// String representing the input MetadataValue.
|
||||||
fn value_to_string(v: &MetadataValue, sep: char) -> String {
|
fn value_to_string(v: &MetadataValue, sep: char) -> String {
|
||||||
match v {
|
match v {
|
||||||
MetadataValue::String(v) => v.to_string(),
|
MetadataValue::String(v) => v.to_string(),
|
||||||
MetadataValue::I16(v) => v.to_string(),
|
MetadataValue::I16(v) => v.to_string(),
|
||||||
MetadataValue::I32(v) => v.to_string(),
|
MetadataValue::I32(v) => v.to_string(),
|
||||||
MetadataValue::I64(v) => v.to_string(),
|
MetadataValue::I64(v) => v.to_string(),
|
||||||
MetadataValue::U8(v) => v.to_string(),
|
MetadataValue::U8(v) => v.to_string(),
|
||||||
MetadataValue::U16(v) => v.to_string(),
|
MetadataValue::U16(v) => v.to_string(),
|
||||||
MetadataValue::U32(v) => v.to_string(),
|
MetadataValue::U32(v) => v.to_string(),
|
||||||
MetadataValue::U64(v) => v.to_string(),
|
MetadataValue::U64(v) => v.to_string(),
|
||||||
MetadataValue::F64(v) => v.to_string(),
|
MetadataValue::F64(v) => v.to_string(),
|
||||||
MetadataValue::Bool(v) => v.to_string(),
|
MetadataValue::Bool(v) => v.to_string(),
|
||||||
MetadataValue::Array(v) => {
|
MetadataValue::Array(v) => {
|
||||||
let mut out = v.iter().map( |val| {
|
let mut out = v
|
||||||
let mut str = value_to_string(val, sep);
|
.iter()
|
||||||
str.push(sep);
|
.map(|val| {
|
||||||
str
|
let mut str = value_to_string(val, sep);
|
||||||
}).collect::<String>();
|
str.push(sep);
|
||||||
out.pop();
|
str
|
||||||
out
|
})
|
||||||
},
|
.collect::<String>();
|
||||||
MetadataValue::Map(_v) => panic!("unimplemented! TBH i have no clue when a metadataValue would even return this?"),
|
out.pop();
|
||||||
MetadataValue::Unsupported => panic!("Unsupported Metadata type detected!"),
|
out
|
||||||
}
|
}
|
||||||
|
MetadataValue::Map(_v) => {
|
||||||
|
panic!("unimplemented! TBH i have no clue when a metadataValue would even return this?")
|
||||||
|
}
|
||||||
|
MetadataValue::Unsupported => panic!("Unsupported Metadata type detected!"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function converts one specific instance of MetadataValue to an appropriate String.
|
/// This function converts one specific instance of MetadataValue to an appropriate String.
|
||||||
|
|
@ -53,24 +58,28 @@ fn value_to_string(v: &MetadataValue, sep: char) -> String {
|
||||||
/// Output:
|
/// Output:
|
||||||
/// Some(String) if a rating exists, None otherwise.
|
/// Some(String) if a rating exists, None otherwise.
|
||||||
fn rating_to_string(r: Option<&MetadataValue>, str: &Vec<String>) -> Option<String> {
|
fn rating_to_string(r: Option<&MetadataValue>, str: &Vec<String>) -> Option<String> {
|
||||||
match r {
|
match r {
|
||||||
Some(rating) => {
|
Some(rating) => {
|
||||||
if let Some(f) = rating.as_f64() {
|
if let Some(f) = rating.as_f64() {
|
||||||
let mut i = (f * 10_f64).round() as i64;
|
let mut i = (f * 10_f64).round() as i64;
|
||||||
if i > 10 {i = 10}
|
if i > 10 {
|
||||||
if i < 0 {i = 0}
|
i = 10
|
||||||
|
}
|
||||||
|
if i < 0 {
|
||||||
|
i = 0
|
||||||
|
}
|
||||||
|
|
||||||
Some(str[i as usize].to_owned()) //TODO: still inefficient. would be better to note the idx and load it in print_text
|
Some(str[i as usize].to_owned()) //TODO: still inefficient. would be better to note the idx and load it in print_text
|
||||||
} else {
|
} else {
|
||||||
debug!("failed to convert MetadataValue to f64!");
|
debug!("failed to convert MetadataValue to f64!");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => {
|
None => {
|
||||||
trace!("no userRating MetadataValue found!");
|
trace!("no userRating MetadataValue found!");
|
||||||
None
|
None
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This higher level function updates the to be output Hashmap of strings.
|
/// This higher level function updates the to be output Hashmap of strings.
|
||||||
|
|
@ -82,23 +91,44 @@ fn rating_to_string(r: Option<&MetadataValue>, str: &Vec<String>) -> Option<Stri
|
||||||
/// data: mutable Data struct for the program. Its' Hashmap containing strings is updated.
|
/// data: mutable Data struct for the program. Its' Hashmap containing strings is updated.
|
||||||
/// ratings: Vec of precomputed rating strings.
|
/// ratings: Vec of precomputed rating strings.
|
||||||
pub fn update_message(cfg: &Config, data: &mut Data, ratings: &Vec<String>) {
|
pub fn update_message(cfg: &Config, data: &mut Data, ratings: &Vec<String>) {
|
||||||
if let Some(player) = &data.current_player {
|
if let Some(player) = &data.current_player {
|
||||||
if let Ok(meta) = player.get_metadata() {
|
if let Ok(meta) = player.get_metadata() {
|
||||||
for field in &cfg.metadata_fields {
|
for field in &cfg.metadata_fields {
|
||||||
let key: &str = field.field.as_ref();
|
let key: &str = field.field.as_ref();
|
||||||
if field.field.eq("xesam:userRating") {
|
if field.field.eq("xesam:userRating") {
|
||||||
if let Some(rating_string) = rating_to_string(meta.get(key), ratings) {
|
if let Some(rating_string) = rating_to_string(meta.get(key), ratings) {
|
||||||
data.field_text.insert(key.to_owned(), rating_string);
|
data.field_text.insert(key.to_owned(), rating_string);
|
||||||
} else {
|
} else {
|
||||||
data.field_text.remove(key);
|
data.field_text.remove(key);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
match meta.get(&key) {
|
||||||
|
Some(value) => {
|
||||||
|
trace!(
|
||||||
|
"update_messages: field {} has value {}",
|
||||||
|
key,
|
||||||
|
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);
|
||||||
|
data.field_text.insert(
|
||||||
|
key.to_owned(),
|
||||||
|
format!("No {}", key.trim_start_matches("xesam:")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
match meta.get(&key) {
|
debug!(
|
||||||
Some(value) => data.field_text.insert(key.to_owned(), value_to_string(value, cfg.array_separator)),
|
"update_messages: Player {} has no metadata!",
|
||||||
None => data.field_text.insert(key.to_owned(), format!("No {}", key.trim_start_matches("xesam:"))),
|
player.unique_name()
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
debug!("update_messages: No player found!");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -2,10 +2,9 @@
|
||||||
//! It also updates the prefix, which kind of breaks seperation of concerns, but this saves me a lot of headache so I'm not changing it.
|
//! It also updates the prefix, which kind of breaks seperation of concerns, but this saves me a lot of headache so I'm not changing it.
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use log::trace;
|
use crate::structs::{config::Config, data::Data};
|
||||||
use mpris::{PlayerFinder, Player};
|
use log::{debug, trace};
|
||||||
use crate::structs::{data::Data, config::Config};
|
use mpris::PlayerFinder;
|
||||||
|
|
||||||
|
|
||||||
/// This function updates the current prefix.
|
/// This function updates the current prefix.
|
||||||
/// If no entry is found in config containing the active player, a default value is used instead ('>').
|
/// If no entry is found in config containing the active player, a default value is used instead ('>').
|
||||||
|
|
@ -15,13 +14,13 @@ use crate::structs::{data::Data, config::Config};
|
||||||
/// data: mutable char containing the active prefix.
|
/// data: mutable char containing the active prefix.
|
||||||
/// name: name of active player, to fetch the appropriate prefix from cfg.
|
/// name: name of active player, to fetch the appropriate prefix from cfg.
|
||||||
fn update_prefix(cfg: &Config, data: &mut char, name: &str) {
|
fn update_prefix(cfg: &Config, data: &mut char, name: &str) {
|
||||||
if let Some(char) = cfg.player_prefixes.get(name) {
|
if let Some(char) = cfg.player_prefixes.get(name) {
|
||||||
*data = *char;
|
*data = *char;
|
||||||
trace!("updated prefix to {}", data);
|
trace!("updated prefix to {}", data);
|
||||||
} else {
|
} else {
|
||||||
*data = *cfg.player_prefixes.get("default").unwrap_or(&'>');
|
*data = *cfg.player_prefixes.get("default").unwrap_or(&'>');
|
||||||
trace!("set prefix to default ({})", data);
|
trace!("set prefix to default ({})", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function updates which player is selected as 'active'.
|
/// This function updates which player is selected as 'active'.
|
||||||
|
|
@ -33,25 +32,35 @@ fn update_prefix(cfg: &Config, data: &mut char, name: &str) {
|
||||||
/// cfg: Config struct of the program, containing the list of acceptable players.
|
/// cfg: Config struct of the program, containing the list of acceptable players.
|
||||||
/// data: mutable Data struct of the program, containing a marker for the currently active player.
|
/// data: mutable Data struct of the program, containing a marker for the currently active player.
|
||||||
pub fn update_players(pf: &PlayerFinder, cfg: &Config, data: &mut Data) {
|
pub fn update_players(pf: &PlayerFinder, cfg: &Config, data: &mut Data) {
|
||||||
// get all acceptable players
|
// get all acceptable players
|
||||||
let players = pf.find_all().unwrap_or(Vec::new());
|
let players = pf.find_all().unwrap_or(Vec::new());
|
||||||
if players.is_empty() {
|
if players.is_empty() {
|
||||||
data.current_player = None;
|
data.current_player = None;
|
||||||
} else {
|
debug!("update_players: no players found!")
|
||||||
let mut active: BTreeMap<u8, Player> = BTreeMap::new();
|
|
||||||
for player in players {
|
|
||||||
if let Ok(mpris::PlaybackStatus::Playing) = player.get_playback_status() {
|
|
||||||
let idx = cfg.find_player_priorities_idx(player.identity());
|
|
||||||
active.insert(idx, player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// select the player with the highest priority.
|
|
||||||
if let Some((_, player)) = active.pop_first() {
|
|
||||||
update_prefix(cfg, &mut data.prefix, player.identity());
|
|
||||||
data.current_player = Some(player);
|
|
||||||
} else {
|
} else {
|
||||||
data.current_player = None;
|
let mut trees = vec![BTreeMap::new(), BTreeMap::new(), BTreeMap::new()];
|
||||||
|
for player in players {
|
||||||
|
if let Ok(status) = player.get_playback_status() {
|
||||||
|
let idx = cfg.find_player_priorities_idx(player.identity());
|
||||||
|
match status {
|
||||||
|
mpris::PlaybackStatus::Playing => trees[0].insert(idx, player),
|
||||||
|
mpris::PlaybackStatus::Paused => trees[1].insert(idx, player),
|
||||||
|
mpris::PlaybackStatus::Stopped => trees[2].insert(idx, player),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// select the player with the highest priority.
|
||||||
|
for mut tree in trees {
|
||||||
|
if let Some((_, player)) = tree.pop_first() {
|
||||||
|
update_prefix(cfg, &mut data.prefix, player.identity());
|
||||||
|
debug!("update_players: updated player to {}!", player.identity());
|
||||||
|
data.current_player = Some(player);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
data.current_player = None;
|
||||||
|
debug!("update_players: No acceptable player found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue