Spotify URL support for MPRIS OpenUri function (#314)

* Added OpenUri D-BUS MPRIS support.
Removed "user:" from URIType check because Spotify doesn't always provide it.

* Added tags to .gitignore

* Changed mpris metadata to actually return the track's url instead of the Spotify URI so that it matches the functionality of the official Spotify client.

* Changed mpris:trackid and xesam:url to not use static naming so it can support podcasts.

* Changed xesam:url to default to an empty string instead of "0"

* Added possibility to start playing Shows and Episodes via MPRIS.
Added possibility to search for Podcast Episodes.

* Fixed mpris:trackid not returning the id in the correct format.
MPRIS OpenUri function now supports Spotify url links.

* return result directly instead of mut string

* handle artist URLs/URIs

Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
This commit is contained in:
Bettehem
2020-11-10 21:18:22 +02:00
committed by GitHub
parent 0c1297d749
commit a8861fc1aa
3 changed files with 26 additions and 13 deletions

View File

@@ -21,6 +21,7 @@ use crate::show::Show;
use crate::spotify::{PlayerEvent, Spotify, URIType};
use crate::track::Track;
use crate::traits::ListItem;
use regex::Regex;
type Metadata = HashMap<String, Variant<Box<dyn RefArg>>>;
@@ -41,12 +42,7 @@ fn get_metadata(playable: Option<Playable>) -> Metadata {
hm.insert(
"mpris:trackid".to_string(),
Variant(Box::new(Path::from(format!(
"/org/ncspot/{}",
playable
.map(|t| t.uri().replace(':', "/"))
.unwrap_or_else(|| "0".to_string())
)))),
Variant(Box::new(playable.map(|t| t.uri()).unwrap_or_default())),
);
hm.insert(
"mpris:length".to_string(),
@@ -481,11 +477,22 @@ fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<
f.method("OpenUri", (), move |m| {
let uri_data: Option<&str> = m.msg.get1();
let uri = match uri_data {
Some(s) => s,
None => "",
Some(s) => {
let spotify_uri = if s.contains("open.spotify.com") {
let regex = Regex::new(r"https?://open\.spotify\.com(/user)?/(album|track|playlist|show|episode)/(.+)(\?si=\S+)?").unwrap();
let captures = regex.captures(s).unwrap();
let uri_type = &captures[2];
let id = &captures[3];
format!("spotify:{}:{}", uri_type, id)
}else {
s.to_string()
};
spotify_uri
}
None => "".to_string(),
};
let id = &uri[uri.rfind(':').unwrap_or(0) + 1..uri.len()];
let uri_type = URIType::from_uri(uri);
let uri_type = URIType::from_uri(&uri);
match uri_type {
Some(URIType::Album) => {
if let Some(a) = spotify.album(&id) {
@@ -548,7 +555,13 @@ fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<
queue.play(0, false, false)
}
}
Some(URIType::Artist) => {}
Some(URIType::Artist) => {
if let Some(a) = spotify.artist_top_tracks(&id) {
queue.clear();
queue.append_next(a.iter().map(|track| Playable::Track(track.clone())).collect());
queue.play(0, false, false)
}
}
None => {}
}
Ok(vec![m.msg.method_return()])

View File

@@ -822,8 +822,8 @@ impl Spotify {
self.api_with_retry(|api| api.user_playlist_follow_playlist(&owner_id, &id, true))
}
pub fn artist_top_tracks(&self, id: String) -> Option<Vec<Track>> {
self.api_with_retry(|api| api.artist_top_tracks(&id, None))
pub fn artist_top_tracks(&self, id: &str) -> Option<Vec<Track>> {
self.api_with_retry(|api| api.artist_top_tracks(id, None))
.map(|ft| ft.tracks.iter().map(|t| t.into()).collect())
}

View File

@@ -40,7 +40,7 @@ impl ArtistView {
let library = library.clone();
thread::spawn(move || {
if let Some(id) = id {
if let Some(tracks) = spotify.artist_top_tracks(id) {
if let Some(tracks) = spotify.artist_top_tracks(&id) {
top_tracks.write().unwrap().extend(tracks);
library.trigger_redraw();
}