add support for getting genre from mpris (experimental)

master
Ondřej Hruška 6 years ago
parent ef78943940
commit 170b6ebc7b
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 1
      Cargo.lock
  2. 1
      Cargo.toml
  3. 63
      src/brainz.rs
  4. 50
      src/main.rs

1
Cargo.lock generated

@ -956,6 +956,7 @@ dependencies = [
name = "rapblock" name = "rapblock"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dbus 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",

@ -17,3 +17,4 @@ log = "0.4"
env_logger = "0.6" env_logger = "0.6"
regex = "1.1.0" regex = "1.1.0"
inotify = "0.7.0" inotify = "0.7.0"
dbus = "0.6.4"

@ -30,6 +30,38 @@ struct MBArtist {
const VERSION: &'static str = env!("CARGO_PKG_VERSION"); const VERSION: &'static str = env!("CARGO_PKG_VERSION");
/// Check genre; returns true if it's OK
pub fn check_genre(config: &crate::Config, genre: &String) -> bool {
if config.whitelist.tag.contains(genre) {
info!("+ Whitelisted tag \"{}\"", genre);
return true;
}
if config.blacklist.tag.contains(genre) {
info!("- Blacklisted tag \"{}\"", genre);
return false;
} else {
for substr in config.blacklist.tag_partial.iter() {
let re = Regex::new(&format!(r"\b{}\b", regex::escape(substr)));
let matches = match re {
Ok(re) => re.is_match(genre),
Err(_) => genre.contains(substr),
};
if matches {
info!(
"- Blacklisted tag \"{}\" - due to substring \"{}\"",
genre, substr
);
return false;
}
}
}
true
}
pub fn check_artist(config: &crate::Config, artist: &str) -> Result<bool, Error> { pub fn check_artist(config: &crate::Config, artist: &str) -> Result<bool, Error> {
let query = utf8_percent_encode(&format!("\"{}\"", artist), DEFAULT_ENCODE_SET).to_string(); let query = utf8_percent_encode(&format!("\"{}\"", artist), DEFAULT_ENCODE_SET).to_string();
let url = format!( let url = format!(
@ -89,36 +121,7 @@ pub fn check_artist(config: &crate::Config, artist: &str) -> Result<bool, Error>
info!("Artist #{} - \"{}\" has tags: {:?}", an + 1, a.name, as_vec); info!("Artist #{} - \"{}\" has tags: {:?}", an + 1, a.name, as_vec);
'tags: for tag in as_vec { 'tags: for tag in as_vec {
if config.whitelist.tag.contains(tag) { if !check_genre(config, tag) {
info!("+ Whitelisted tag \"{}\"", tag);
continue 'tags;
}
let mut blacklisted = false;
if config.blacklist.tag.contains(&tag) {
info!("- Blacklisted tag \"{}\"", tag);
blacklisted = true;
} else {
'blacklist: for t in config.blacklist.tag_partial.iter() {
let re = Regex::new(&format!(r"\b{}\b", regex::escape(t)));
let matches = match re {
Ok(re) => re.is_match(tag),
Err(_) => tag.contains(t),
};
if matches {
info!(
"- Blacklisted tag \"{}\" - due to substring \"{}\"",
tag, t
);
blacklisted = true;
break 'blacklist;
}
}
}
if blacklisted {
confidence = true; confidence = true;
passed = false; passed = false;
break 'artists; break 'artists;

@ -11,6 +11,8 @@ use std::time::Duration;
use mpris::Event; use mpris::Event;
use std::collections::HashSet; use std::collections::HashSet;
use failure::Error; use failure::Error;
use dbus::arg::Variant;
use dbus::arg::RefArg;
mod brainz; mod brainz;
mod config_file; mod config_file;
@ -167,6 +169,9 @@ fn main() -> Result<(), Error> {
break 'event_loop; break 'event_loop;
} }
Event::TrackChanged(mut metadata) => { Event::TrackChanged(mut metadata) => {
::std::thread::sleep(Duration::from_millis(250));
metadata = player.get_metadata().unwrap_or(metadata);
let mut title = metadata.title().unwrap_or(""); let mut title = metadata.title().unwrap_or("");
info!("--- new track : {} ---", title); info!("--- new track : {} ---", title);
@ -185,6 +190,39 @@ fn main() -> Result<(), Error> {
} }
} }
let mut skip = !config.allow_by_default;
let mut confidence = false;
debug!("MPRIS meta: {:#?}", metadata);
// try to get genre from the 'rest' map in the metadata struct
#[allow(deprecated)] // 2.0.0 will provide some nicer API, hopefully
let rest = metadata.rest();
let meta_genre : Option<&Variant<Box<RefArg>>> = rest.get("xesam:genre");
match meta_genre {
Some(variant) => {
let b : &RefArg = variant.0.as_ref();
if let Some(s) = b.as_str() {
info!("Using genre from MPRIS metadata: {}", s);
skip = !brainz::check_genre(&config, &s.to_string().to_lowercase());
confidence = true;
} else if let Some(list) = b.as_iter() {
debug!("MPRIS contains array of genres");
for item in list {
if let Some(s) = item.as_str() {
info!("Using genre from MPRIS metadata: {}", s);
skip = !brainz::check_genre(&config, &s.to_string().to_lowercase());
confidence = true;
}
}
}
},
None => {
debug!("No MPRIS genre");
}
};
if !confidence {
let mut artists = HashSet::new(); let mut artists = HashSet::new();
if let Some(aa) = metadata.artists() { if let Some(aa) = metadata.artists() {
@ -198,15 +236,14 @@ fn main() -> Result<(), Error> {
} }
} }
let mut skip = false; let artists_e = artists
let mut confidence = false;
'artists_loop: for (an, a) in artists
.iter() .iter()
.take(config.max_artists_per_track as usize) .take(config.max_artists_per_track as usize)
.enumerate() .enumerate();
{
'artists_loop: for (an, a) in artists_e {
info!("Checking artist #{}: {}", an + 1, a); info!("Checking artist #{}: {}", an + 1, a);
if let Some(resolution) = artist_cache.get(a.as_str()) { if let Some(resolution) = artist_cache.get(*a) {
confidence = true; confidence = true;
if !resolution { if !resolution {
info!("~ result cached: BAD"); info!("~ result cached: BAD");
@ -253,6 +290,7 @@ fn main() -> Result<(), Error> {
} }
} }
} }
}
if skip || (!confidence && !config.allow_by_default) { if skip || (!confidence && !config.allow_by_default) {
info!(">>>>>> SKIP : {} >>>>>>\n", title); info!(">>>>>> SKIP : {} >>>>>>\n", title);

Loading…
Cancel
Save