mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Make SpotifyId
understand more URI formats
This commit is contained in:
parent
6786c093ad
commit
b96405af82
3 changed files with 42 additions and 19 deletions
|
@ -13,14 +13,14 @@ use context::StationContext;
|
||||||
use librespot_core::config::ConnectConfig;
|
use librespot_core::config::ConnectConfig;
|
||||||
use librespot_core::mercury::MercuryError;
|
use librespot_core::mercury::MercuryError;
|
||||||
use librespot_core::session::Session;
|
use librespot_core::session::Session;
|
||||||
use librespot_core::spotify_id::SpotifyId;
|
use librespot_core::spotify_id::{SpotifyId, SpotifyIdError};
|
||||||
use librespot_core::util::SeqGenerator;
|
use librespot_core::util::SeqGenerator;
|
||||||
use librespot_core::version;
|
use librespot_core::version;
|
||||||
use librespot_core::volume::Volume;
|
use librespot_core::volume::Volume;
|
||||||
use playback::mixer::Mixer;
|
use playback::mixer::Mixer;
|
||||||
use playback::player::Player;
|
use playback::player::Player;
|
||||||
use protocol;
|
use protocol;
|
||||||
use protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State};
|
use protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State, TrackRef};
|
||||||
|
|
||||||
pub struct SpircTask {
|
pub struct SpircTask {
|
||||||
player: Player,
|
player: Player,
|
||||||
|
@ -797,7 +797,7 @@ impl SpircTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_tracks(&mut self, frame: &protocol::spirc::Frame) {
|
fn update_tracks(&mut self, frame: &protocol::spirc::Frame) {
|
||||||
// debug!("State: {:?}", frame.get_state());
|
debug!("State: {:?}", frame.get_state());
|
||||||
let index = frame.get_state().get_playing_track_index();
|
let index = frame.get_state().get_playing_track_index();
|
||||||
let context_uri = frame.get_state().get_context_uri().to_owned();
|
let context_uri = frame.get_state().get_context_uri().to_owned();
|
||||||
let tracks = frame.get_state().get_track();
|
let tracks = frame.get_state().get_track();
|
||||||
|
@ -813,31 +813,43 @@ impl SpircTask {
|
||||||
self.state.set_shuffle(frame.get_state().get_shuffle());
|
self.state.set_shuffle(frame.get_state().get_shuffle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// should this be a method of SpotifyId directly?
|
||||||
|
fn get_spotify_id_for_track(&self, track_ref: &TrackRef) -> Result<SpotifyId, SpotifyIdError> {
|
||||||
|
SpotifyId::from_raw(track_ref.get_gid()).or_else(|_| {
|
||||||
|
let uri = track_ref.get_uri();
|
||||||
|
debug!("Malformed or no gid, attempting to parse URI <{}>", uri);
|
||||||
|
SpotifyId::from_uri(uri)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn load_track(&mut self, play: bool) {
|
fn load_track(&mut self, play: bool) {
|
||||||
let context_uri = self.state.get_context_uri().to_owned();
|
let context_uri = self.state.get_context_uri().to_owned();
|
||||||
let index = self.state.get_playing_track_index();
|
let mut index = self.state.get_playing_track_index();
|
||||||
info!("context: {}", context_uri);
|
let tracks_len = self.state.get_track().len() as u32;
|
||||||
// Redundant check here
|
debug!(
|
||||||
let track = if context_uri.contains(":show:") || context_uri.contains(":episode:") {
|
"Loading context: {} index: [{}] of {}",
|
||||||
let uri = self.state.get_track()[index as usize].get_uri();
|
context_uri, index, tracks_len
|
||||||
SpotifyId::from_uri(uri).expect("Unable to parse uri")
|
);
|
||||||
} else {
|
// Tracks either have a gid or uri.
|
||||||
let mut index = self.state.get_playing_track_index();
|
// Context based frames sometimes use spotify:meta:page: that needs to be ignored.
|
||||||
// Check for malformed gid
|
let track = {
|
||||||
let tracks_len = self.state.get_track().len() as u32;
|
|
||||||
let mut track_ref = &self.state.get_track()[index as usize];
|
let mut track_ref = &self.state.get_track()[index as usize];
|
||||||
while track_ref.get_gid().len() != 16 {
|
let mut track_id = self.get_spotify_id_for_track(track_ref);
|
||||||
|
while track_id.is_err() {
|
||||||
warn!(
|
warn!(
|
||||||
"Skipping track {:?} at position [{}] of {}",
|
"Skipping track {:?} at position [{}] of {}",
|
||||||
track_ref.get_uri(),
|
track_ref.get_uri(),
|
||||||
index,
|
index,
|
||||||
tracks_len
|
tracks_len
|
||||||
);
|
);
|
||||||
|
// This will keep looping over, instead we should cylce tracks only once
|
||||||
index = if index + 1 < tracks_len { index + 1 } else { 0 };
|
index = if index + 1 < tracks_len { index + 1 } else { 0 };
|
||||||
track_ref = &self.state.get_track()[index as usize];
|
track_ref = &self.state.get_track()[index as usize];
|
||||||
|
track_id = self.get_spotify_id_for_track(track_ref);
|
||||||
}
|
}
|
||||||
SpotifyId::from_raw(track_ref.get_gid()).unwrap()
|
track_id
|
||||||
};
|
}
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let position = self.state.get_position_ms();
|
let position = self.state.get_position_ms();
|
||||||
let end_of_track = self.player.load(track, play, position);
|
let end_of_track = self.player.load(track, play, position);
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::fmt;
|
||||||
pub enum SpotifyAudioType {
|
pub enum SpotifyAudioType {
|
||||||
Track,
|
Track,
|
||||||
Podcast,
|
Podcast,
|
||||||
|
NonPlayable,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -71,12 +72,18 @@ impl SpotifyId {
|
||||||
|
|
||||||
pub fn from_uri(uri: &str) -> Result<SpotifyId, SpotifyIdError> {
|
pub fn from_uri(uri: &str) -> Result<SpotifyId, SpotifyIdError> {
|
||||||
let parts = uri.split(":").collect::<Vec<&str>>();
|
let parts = uri.split(":").collect::<Vec<&str>>();
|
||||||
if uri.contains(":show:") || uri.contains(":episode:") {
|
let gid = parts.last().unwrap();
|
||||||
let mut spotify_id = SpotifyId::from_base62(parts[2]).unwrap();
|
if uri.contains(":episode:") {
|
||||||
|
let mut spotify_id = SpotifyId::from_base62(gid).unwrap();
|
||||||
let _ = std::mem::replace(&mut spotify_id.audio_type, SpotifyAudioType::Podcast);
|
let _ = std::mem::replace(&mut spotify_id.audio_type, SpotifyAudioType::Podcast);
|
||||||
Ok(spotify_id)
|
Ok(spotify_id)
|
||||||
|
} else if uri.contains(":track:") {
|
||||||
|
SpotifyId::from_base62(gid)
|
||||||
} else {
|
} else {
|
||||||
SpotifyId::from_base62(parts[2])
|
// show/playlist/artist/album/??
|
||||||
|
let mut spotify_id = SpotifyId::from_base62(gid).unwrap();
|
||||||
|
let _ = std::mem::replace(&mut spotify_id.audio_type, SpotifyAudioType::NonPlayable);
|
||||||
|
Ok(spotify_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ extern crate librespot_protocol as protocol;
|
||||||
|
|
||||||
pub mod cover;
|
pub mod cover;
|
||||||
|
|
||||||
|
use futures::future;
|
||||||
use futures::Future;
|
use futures::Future;
|
||||||
use linear_map::LinearMap;
|
use linear_map::LinearMap;
|
||||||
|
|
||||||
|
@ -71,6 +72,9 @@ impl AudioItem {
|
||||||
match id.audio_type {
|
match id.audio_type {
|
||||||
SpotifyAudioType::Track => Track::get_audio_item(session, id),
|
SpotifyAudioType::Track => Track::get_audio_item(session, id),
|
||||||
SpotifyAudioType::Podcast => Episode::get_audio_item(session, id),
|
SpotifyAudioType::Podcast => Episode::get_audio_item(session, id),
|
||||||
|
SpotifyAudioType::NonPlayable => {
|
||||||
|
Box::new(future::err::<AudioItem, MercuryError>(MercuryError))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue