From 8483653cdedc7fb8c2b905a35e7060ff61dd9b5a Mon Sep 17 00:00:00 2001 From: Henrik Friedrichsen Date: Sat, 3 Apr 2021 21:38:42 +0200 Subject: [PATCH] Refactor: extract Spotify Worker to separate file --- src/main.rs | 1 + src/mpris.rs | 16 +-- src/spotify.rs | 203 +++------------------------------------ src/spotify_url.rs | 48 ++++----- src/spotify_worker.rs | 188 ++++++++++++++++++++++++++++++++++++ src/ui/listview.rs | 16 +-- src/ui/search.rs | 2 +- src/ui/search_results.rs | 32 +++--- 8 files changed, 258 insertions(+), 248 deletions(-) create mode 100644 src/spotify_worker.rs diff --git a/src/main.rs b/src/main.rs index d658e89..7868dbd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,6 +64,7 @@ mod sharing; mod show; mod spotify; mod spotify_url; +mod spotify_worker; mod theme; mod track; mod traits; diff --git a/src/mpris.rs b/src/mpris.rs index 9cb0149..be0650a 100644 --- a/src/mpris.rs +++ b/src/mpris.rs @@ -19,7 +19,7 @@ use crate::playable::Playable; use crate::playlist::Playlist; use crate::queue::{Queue, RepeatSetting}; use crate::show::Show; -use crate::spotify::{PlayerEvent, Spotify, URIType, VOLUME_PERCENT}; +use crate::spotify::{PlayerEvent, Spotify, UriType, VOLUME_PERCENT}; use crate::track::Track; use crate::traits::ListItem; use regex::Regex; @@ -538,9 +538,9 @@ fn run_dbus_server( 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) => { + Some(UriType::Album) => { if let Some(a) = spotify.album(&id) { if let Some(t) = &Album::from(&a).tracks { queue.clear(); @@ -553,14 +553,14 @@ fn run_dbus_server( } } } - Some(URIType::Track) => { + Some(UriType::Track) => { if let Some(t) = spotify.track(&id) { queue.clear(); queue.append(Playable::Track(Track::from(&t))); queue.play(0, false, false) } } - Some(URIType::Playlist) => { + Some(UriType::Playlist) => { if let Some(p) = spotify.playlist(&id) { let mut playlist = Playlist::from(&p); let spotify = spotify.clone(); @@ -576,7 +576,7 @@ fn run_dbus_server( } } } - Some(URIType::Show) => { + Some(UriType::Show) => { if let Some(s) = spotify.get_show(&id) { let mut show = Show::from(&s); let spotify = spotify.clone(); @@ -594,14 +594,14 @@ fn run_dbus_server( } } } - Some(URIType::Episode) => { + Some(UriType::Episode) => { if let Some(e) = spotify.episode(&id) { queue.clear(); queue.append(Playable::Episode(Episode::from(&e))); 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()); diff --git a/src/spotify.rs b/src/spotify.rs index 9a31175..c679871 100644 --- a/src/spotify.rs +++ b/src/spotify.rs @@ -4,13 +4,11 @@ use librespot_core::config::SessionConfig; use librespot_core::keymaster::Token; use librespot_core::mercury::MercuryError; use librespot_core::session::Session; -use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId}; use librespot_playback::config::PlayerConfig; use librespot_playback::audio_backend; use librespot_playback::config::Bitrate; -use librespot_playback::mixer::Mixer; -use librespot_playback::player::{Player, PlayerEvent as LibrespotPlayerEvent}; +use librespot_playback::player::Player; use rspotify::blocking::client::Spotify as SpotifyAPI; use rspotify::model::album::{FullAlbum, SavedAlbum, SimplifiedAlbum}; @@ -28,23 +26,15 @@ use serde_json::{json, Map}; use failure::Error; use futures_01::future::Future as v01_Future; -use futures_01::stream::Stream as v01_Stream; -use futures_01::sync::mpsc::UnboundedReceiver; -use futures_01::Async as v01_Async; use futures::channel::mpsc; use futures::channel::oneshot; use futures::compat::Future01CompatExt; -use futures::compat::Stream01CompatExt; -use futures::task::Context; use futures::Future; -use futures::Stream; use tokio_core::reactor::Core; use url::Url; -use core::task::Poll; - use std::pin::Pin; use std::str::FromStr; use std::sync::{Arc, RwLock}; @@ -56,6 +46,7 @@ use crate::artist::Artist; use crate::config; use crate::events::{Event, EventManager}; use crate::playable::Playable; +use crate::spotify_worker::{Worker, WorkerCommand}; use crate::track::Track; use rspotify::model::recommend::Recommendations; @@ -63,17 +54,6 @@ use rspotify::model::show::{FullEpisode, FullShow, Show, SimplifiedEpisode}; pub const VOLUME_PERCENT: u16 = ((u16::max_value() as f64) * 1.0 / 100.0) as u16; -enum WorkerCommand { - Load(Playable), - Play, - Pause, - Stop, - Seek(u32), - SetVolume(u16), - RequestToken(oneshot::Sender), - Shutdown, -} - #[derive(Clone, Debug, PartialEq)] pub enum PlayerEvent { Playing, @@ -96,165 +76,6 @@ pub struct Spotify { country: Option, } -struct Worker { - events: EventManager, - player_events: UnboundedReceiver, - commands: Pin>>, - session: Session, - player: Player, - refresh_task: Pin>>>, - token_task: Pin>>>, - active: bool, - mixer: Box, -} - -impl Worker { - fn new( - events: EventManager, - player_events: UnboundedReceiver, - commands: Pin>>, - session: Session, - player: Player, - mixer: Box, - ) -> Worker { - Worker { - events, - player_events, - commands, - player, - session, - refresh_task: Box::pin(futures::stream::empty()), - token_task: Box::pin(futures::future::pending()), - active: false, - mixer, - } - } -} - -impl Worker { - fn create_refresh(&self) -> Pin>>> { - let ev = self.events.clone(); - let future = - tokio_timer::Interval::new_interval(Duration::from_millis(400)).map(move |_| { - ev.trigger(); - }); - Box::pin(future.compat()) - } -} - -impl futures::Future for Worker { - type Output = Result<(), ()>; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> futures::task::Poll { - loop { - let mut progress = false; - - if self.session.is_invalid() { - self.events.send(Event::Player(PlayerEvent::Stopped)); - return Poll::Ready(Result::Err(())); - } - - if let Poll::Ready(Some(cmd)) = self.commands.as_mut().poll_next(cx) { - progress = true; - debug!("message received!"); - match cmd { - WorkerCommand::Load(playable) => match SpotifyId::from_uri(&playable.uri()) { - Ok(id) => { - info!("player loading track: {:?}", id); - if id.audio_type == SpotifyAudioType::NonPlayable { - warn!("track is not playable"); - self.events.send(Event::Player(PlayerEvent::FinishedTrack)); - } else { - self.player.load(id, true, 0); - } - } - Err(e) => { - error!("error parsing uri: {:?}", e); - self.events.send(Event::Player(PlayerEvent::FinishedTrack)); - } - }, - WorkerCommand::Play => { - self.player.play(); - } - WorkerCommand::Pause => { - self.player.pause(); - } - WorkerCommand::Stop => { - self.player.stop(); - } - WorkerCommand::Seek(pos) => { - self.player.seek(pos); - } - WorkerCommand::SetVolume(volume) => { - self.mixer.set_volume(volume); - } - WorkerCommand::RequestToken(sender) => { - self.token_task = Spotify::get_token(&self.session, sender); - progress = true; - } - WorkerCommand::Shutdown => { - self.player.stop(); - self.session.shutdown(); - } - } - } - - if let Ok(v01_Async::Ready(Some(event))) = self.player_events.poll() { - debug!("librespot player event: {:?}", event); - match event { - LibrespotPlayerEvent::Started { .. } - | LibrespotPlayerEvent::Loading { .. } - | LibrespotPlayerEvent::Changed { .. } => { - progress = true; - } - LibrespotPlayerEvent::Playing { .. } => { - self.events.send(Event::Player(PlayerEvent::Playing)); - self.refresh_task = self.create_refresh(); - self.active = true; - } - LibrespotPlayerEvent::Paused { .. } => { - self.events.send(Event::Player(PlayerEvent::Paused)); - self.active = false; - } - LibrespotPlayerEvent::Stopped { .. } => { - self.events.send(Event::Player(PlayerEvent::Stopped)); - self.active = false; - } - LibrespotPlayerEvent::EndOfTrack { .. } => { - self.events.send(Event::Player(PlayerEvent::FinishedTrack)); - progress = true; - } - _ => {} - } - } - - if let Poll::Ready(Some(Ok(_))) = self.refresh_task.as_mut().poll_next(cx) { - self.refresh_task = if self.active { - progress = true; - self.create_refresh() - } else { - Box::pin(futures::stream::empty()) - }; - } - - match self.token_task.as_mut().poll(cx) { - Poll::Ready(Ok(_)) => { - info!("token updated!"); - self.token_task = Box::pin(futures::future::pending()) - } - Poll::Ready(Err(e)) => { - error!("could not generate token: {:?}", e); - } - _ => (), - } - - if !progress { - return Poll::Pending; - } - } - } -} - impl Spotify { pub fn new( events: EventManager, @@ -365,7 +186,7 @@ impl Spotify { .expect("could not open spotify session") } - fn get_token( + pub(crate) fn get_token( session: &Session, sender: oneshot::Sender, ) -> Pin>>> { @@ -955,7 +776,7 @@ impl Spotify { } #[derive(Debug, PartialEq)] -pub enum URIType { +pub enum UriType { Album, Artist, Track, @@ -964,20 +785,20 @@ pub enum URIType { Episode, } -impl URIType { - pub fn from_uri(s: &str) -> Option { +impl UriType { + pub fn from_uri(s: &str) -> Option { if s.starts_with("spotify:album:") { - Some(URIType::Album) + Some(UriType::Album) } else if s.starts_with("spotify:artist:") { - Some(URIType::Artist) + Some(UriType::Artist) } else if s.starts_with("spotify:track:") { - Some(URIType::Track) + Some(UriType::Track) } else if s.starts_with("spotify:") && s.contains(":playlist:") { - Some(URIType::Playlist) + Some(UriType::Playlist) } else if s.starts_with("spotify:show:") { - Some(URIType::Show) + Some(UriType::Show) } else if s.starts_with("spotify:episode:") { - Some(URIType::Episode) + Some(UriType::Episode) } else { None } diff --git a/src/spotify_url.rs b/src/spotify_url.rs index 6f25f23..266ce39 100644 --- a/src/spotify_url.rs +++ b/src/spotify_url.rs @@ -1,15 +1,15 @@ -use crate::spotify::URIType; +use crate::spotify::UriType; use url::{Host, Url}; -pub struct SpotifyURL { +pub struct SpotifyUrl { pub id: String, - pub uri_type: URIType, + pub uri_type: UriType, } -impl SpotifyURL { - fn new(id: &str, uri_type: URIType) -> SpotifyURL { - SpotifyURL { +impl SpotifyUrl { + fn new(id: &str, uri_type: UriType) -> SpotifyUrl { + SpotifyUrl { id: id.to_string(), uri_type, } @@ -22,7 +22,7 @@ impl SpotifyURL { /// assert_eq!(result.id, "4uLU6hMCjMI75M1A2tKUQC"); /// assert_eq!(result.uri_type, URIType::Track); /// ``` - pub fn from_url(s: &str) -> Option { + pub fn from_url(s: &str) -> Option { let url = Url::parse(s).ok()?; if url.host() != Some(Host::Domain("open.spotify.com")) { return None; @@ -33,12 +33,12 @@ impl SpotifyURL { let entity = path_segments.next()?; let uri_type = match entity.to_lowercase().as_str() { - "album" => Some(URIType::Album), - "artist" => Some(URIType::Artist), - "episode" => Some(URIType::Episode), - "playlist" => Some(URIType::Playlist), - "show" => Some(URIType::Show), - "track" => Some(URIType::Track), + "album" => Some(UriType::Album), + "artist" => Some(UriType::Artist), + "episode" => Some(UriType::Episode), + "playlist" => Some(UriType::Playlist), + "show" => Some(UriType::Show), + "track" => Some(UriType::Track), "user" => { let _user_id = path_segments.next()?; let entity = path_segments.next()?; @@ -47,14 +47,14 @@ impl SpotifyURL { return None; } - Some(URIType::Playlist) + Some(UriType::Playlist) } _ => None, }?; let id = path_segments.next()?; - Some(SpotifyURL::new(id, uri_type)) + Some(SpotifyUrl::new(id, uri_type)) } } @@ -62,39 +62,39 @@ impl SpotifyURL { mod tests { use std::collections::HashMap; - use super::SpotifyURL; - use crate::spotify::URIType; + use super::SpotifyUrl; + use crate::spotify::UriType; #[test] fn test_urls() { let mut test_cases = HashMap::new(); test_cases.insert( "https://open.spotify.com/playlist/1XFxe8bkTryTODn0lk4CNa?si=FfSpZ6KPQdieClZbwHakOQ", - SpotifyURL::new("1XFxe8bkTryTODn0lk4CNa", URIType::Playlist), + SpotifyUrl::new("1XFxe8bkTryTODn0lk4CNa", UriType::Playlist), ); test_cases.insert( "https://open.spotify.com/track/6fRJg3R90w0juYoCJXxj2d", - SpotifyURL::new("6fRJg3R90w0juYoCJXxj2d", URIType::Track), + SpotifyUrl::new("6fRJg3R90w0juYoCJXxj2d", UriType::Track), ); test_cases.insert( "https://open.spotify.com/user/~villainy~/playlist/0OgoSs65CLDPn6AF6tsZVg", - SpotifyURL::new("0OgoSs65CLDPn6AF6tsZVg", URIType::Playlist), + SpotifyUrl::new("0OgoSs65CLDPn6AF6tsZVg", UriType::Playlist), ); test_cases.insert( "https://open.spotify.com/show/4MZfJbM2MXzZdPbv6gi5lJ", - SpotifyURL::new("4MZfJbM2MXzZdPbv6gi5lJ", URIType::Show), + SpotifyUrl::new("4MZfJbM2MXzZdPbv6gi5lJ", UriType::Show), ); test_cases.insert( "https://open.spotify.com/episode/3QE6rfmjRaeqXSqeWcIWF6", - SpotifyURL::new("3QE6rfmjRaeqXSqeWcIWF6", URIType::Episode), + SpotifyUrl::new("3QE6rfmjRaeqXSqeWcIWF6", UriType::Episode), ); test_cases.insert( "https://open.spotify.com/artist/6LEeAFiJF8OuPx747e1wxR", - SpotifyURL::new("6LEeAFiJF8OuPx747e1wxR", URIType::Artist), + SpotifyUrl::new("6LEeAFiJF8OuPx747e1wxR", UriType::Artist), ); for case in test_cases { - let result = SpotifyURL::from_url(case.0).unwrap(); + let result = SpotifyUrl::from_url(case.0).unwrap(); assert_eq!(result.id, case.1.id); assert_eq!(result.uri_type, case.1.uri_type); } diff --git a/src/spotify_worker.rs b/src/spotify_worker.rs new file mode 100644 index 0000000..ad34906 --- /dev/null +++ b/src/spotify_worker.rs @@ -0,0 +1,188 @@ +use crate::events::{Event, EventManager}; +use crate::playable::Playable; +use crate::spotify::{PlayerEvent, Spotify}; +use futures::channel::{mpsc, oneshot}; +use futures::compat::Stream01CompatExt; +use futures::task::{Context, Poll}; +use futures::{Future, Stream}; +use futures_01::stream::Stream as v01_Stream; +use futures_01::sync::mpsc::UnboundedReceiver; +use futures_01::Async as v01_Async; +use librespot_core::keymaster::Token; +use librespot_core::mercury::MercuryError; +use librespot_core::session::Session; +use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId}; +use librespot_playback::mixer::Mixer; +use librespot_playback::player::{Player, PlayerEvent as LibrespotPlayerEvent}; +use std::pin::Pin; +use std::time::Duration; + +pub(crate) enum WorkerCommand { + Load(Playable), + Play, + Pause, + Stop, + Seek(u32), + SetVolume(u16), + RequestToken(oneshot::Sender), + Shutdown, +} + +pub struct Worker { + events: EventManager, + player_events: UnboundedReceiver, + commands: Pin>>, + session: Session, + player: Player, + refresh_task: Pin>>>, + token_task: Pin>>>, + active: bool, + mixer: Box, +} + +impl Worker { + pub(crate) fn new( + events: EventManager, + player_events: UnboundedReceiver, + commands: Pin>>, + session: Session, + player: Player, + mixer: Box, + ) -> Worker { + Worker { + events, + player_events, + commands, + player, + session, + refresh_task: Box::pin(futures::stream::empty()), + token_task: Box::pin(futures::future::pending()), + active: false, + mixer, + } + } +} + +impl Worker { + fn create_refresh(&self) -> Pin>>> { + let ev = self.events.clone(); + let future = + tokio_timer::Interval::new_interval(Duration::from_millis(400)).map(move |_| { + ev.trigger(); + }); + Box::pin(future.compat()) + } +} + +impl futures::Future for Worker { + type Output = Result<(), ()>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> futures::task::Poll { + loop { + let mut progress = false; + + if self.session.is_invalid() { + self.events.send(Event::Player(PlayerEvent::Stopped)); + return Poll::Ready(Result::Err(())); + } + + if let Poll::Ready(Some(cmd)) = self.commands.as_mut().poll_next(cx) { + progress = true; + debug!("message received!"); + match cmd { + WorkerCommand::Load(playable) => match SpotifyId::from_uri(&playable.uri()) { + Ok(id) => { + info!("player loading track: {:?}", id); + if id.audio_type == SpotifyAudioType::NonPlayable { + warn!("track is not playable"); + self.events.send(Event::Player(PlayerEvent::FinishedTrack)); + } else { + self.player.load(id, true, 0); + } + } + Err(e) => { + error!("error parsing uri: {:?}", e); + self.events.send(Event::Player(PlayerEvent::FinishedTrack)); + } + }, + WorkerCommand::Play => { + self.player.play(); + } + WorkerCommand::Pause => { + self.player.pause(); + } + WorkerCommand::Stop => { + self.player.stop(); + } + WorkerCommand::Seek(pos) => { + self.player.seek(pos); + } + WorkerCommand::SetVolume(volume) => { + self.mixer.set_volume(volume); + } + WorkerCommand::RequestToken(sender) => { + self.token_task = Spotify::get_token(&self.session, sender); + progress = true; + } + WorkerCommand::Shutdown => { + self.player.stop(); + self.session.shutdown(); + } + } + } + + if let Ok(v01_Async::Ready(Some(event))) = self.player_events.poll() { + debug!("librespot player event: {:?}", event); + match event { + LibrespotPlayerEvent::Started { .. } + | LibrespotPlayerEvent::Loading { .. } + | LibrespotPlayerEvent::Changed { .. } => { + progress = true; + } + LibrespotPlayerEvent::Playing { .. } => { + self.events.send(Event::Player(PlayerEvent::Playing)); + self.refresh_task = self.create_refresh(); + self.active = true; + } + LibrespotPlayerEvent::Paused { .. } => { + self.events.send(Event::Player(PlayerEvent::Paused)); + self.active = false; + } + LibrespotPlayerEvent::Stopped { .. } => { + self.events.send(Event::Player(PlayerEvent::Stopped)); + self.active = false; + } + LibrespotPlayerEvent::EndOfTrack { .. } => { + self.events.send(Event::Player(PlayerEvent::FinishedTrack)); + progress = true; + } + _ => {} + } + } + + if let Poll::Ready(Some(Ok(_))) = self.refresh_task.as_mut().poll_next(cx) { + self.refresh_task = if self.active { + progress = true; + self.create_refresh() + } else { + Box::pin(futures::stream::empty()) + }; + } + + match self.token_task.as_mut().poll(cx) { + Poll::Ready(Ok(_)) => { + info!("token updated!"); + self.token_task = Box::pin(futures::future::pending()) + } + Poll::Ready(Err(e)) => { + error!("could not generate token: {:?}", e); + } + _ => (), + } + + if !progress { + return Poll::Pending; + } + } + } +} diff --git a/src/ui/listview.rs b/src/ui/listview.rs index 636d13c..0eecb9d 100644 --- a/src/ui/listview.rs +++ b/src/ui/listview.rs @@ -26,7 +26,7 @@ use crate::ui::album::AlbumView; use crate::ui::artist::ArtistView; use crate::ui::contextmenu::ContextMenu; use crate::ui::pagination::Pagination; -use crate::{album::Album, spotify::URIType, spotify_url::SpotifyURL}; +use crate::{album::Album, spotify::UriType, spotify_url::SpotifyUrl}; pub struct ListView { content: Arc>>, @@ -535,26 +535,26 @@ impl ViewExt for ListView { let spotify = self.queue.get_spotify(); - let url = SpotifyURL::from_url(&url); + let url = SpotifyUrl::from_url(&url); if let Some(url) = url { let target: Option> = match url.uri_type { - URIType::Track => spotify + UriType::Track => spotify .track(&url.id) .map(|track| Track::from(&track).as_listitem()), - URIType::Album => spotify + UriType::Album => spotify .album(&url.id) .map(|album| Album::from(&album).as_listitem()), - URIType::Playlist => spotify + UriType::Playlist => spotify .playlist(&url.id) .map(|playlist| Playlist::from(&playlist).as_listitem()), - URIType::Artist => spotify + UriType::Artist => spotify .artist(&url.id) .map(|artist| Artist::from(&artist).as_listitem()), - URIType::Episode => spotify + UriType::Episode => spotify .episode(&url.id) .map(|episode| Episode::from(&episode).as_listitem()), - URIType::Show => spotify + UriType::Show => spotify .get_show(&url.id) .map(|show| Show::from(&show).as_listitem()), }; diff --git a/src/ui/search.rs b/src/ui/search.rs index 9e7bf90..2879748 100644 --- a/src/ui/search.rs +++ b/src/ui/search.rs @@ -19,7 +19,7 @@ use crate::library::Library; use crate::playlist::Playlist; use crate::queue::Queue; use crate::show::Show; -use crate::spotify::{Spotify, URIType}; +use crate::spotify::{Spotify, UriType}; use crate::track::Track; use crate::traits::{ListItem, ViewExt}; use crate::ui::layout::Layout; diff --git a/src/ui/search_results.rs b/src/ui/search_results.rs index 4b2e1a6..9bbf5a8 100644 --- a/src/ui/search_results.rs +++ b/src/ui/search_results.rs @@ -8,8 +8,8 @@ use crate::library::Library; use crate::playlist::Playlist; use crate::queue::Queue; use crate::show::Show; -use crate::spotify::{Spotify, URIType}; -use crate::spotify_url::SpotifyURL; +use crate::spotify::{Spotify, UriType}; +use crate::spotify_url::SpotifyUrl; use crate::track::Track; use crate::traits::{ListItem, ViewExt}; use crate::ui::listview::ListView; @@ -381,9 +381,9 @@ impl SearchResultsView { self.spotify.refresh_token(); // is the query a Spotify URI? - if let Some(uritype) = URIType::from_uri(&query) { + if let Some(uritype) = UriType::from_uri(&query) { match uritype { - URIType::Track => { + UriType::Track => { self.perform_search( Box::new(Self::get_track), &self.results_tracks, @@ -392,7 +392,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(0); } - URIType::Album => { + UriType::Album => { self.perform_search( Box::new(Self::get_album), &self.results_albums, @@ -401,7 +401,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(1); } - URIType::Artist => { + UriType::Artist => { self.perform_search( Box::new(Self::get_artist), &self.results_artists, @@ -410,7 +410,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(2); } - URIType::Playlist => { + UriType::Playlist => { self.perform_search( Box::new(Self::get_playlist), &self.results_playlists, @@ -419,7 +419,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(3); } - URIType::Show => { + UriType::Show => { self.perform_search( Box::new(Self::get_show), &self.results_shows, @@ -428,7 +428,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(4); } - URIType::Episode => { + UriType::Episode => { self.perform_search( Box::new(Self::get_episode), &self.results_episodes, @@ -440,9 +440,9 @@ impl SearchResultsView { } // Is the query a spotify URL? // https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC - } else if let Some(url) = SpotifyURL::from_url(&query) { + } else if let Some(url) = SpotifyUrl::from_url(&query) { match url.uri_type { - URIType::Track => { + UriType::Track => { self.perform_search( Box::new(Self::get_track), &self.results_tracks, @@ -451,7 +451,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(0); } - URIType::Album => { + UriType::Album => { self.perform_search( Box::new(Self::get_album), &self.results_albums, @@ -460,7 +460,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(1); } - URIType::Artist => { + UriType::Artist => { self.perform_search( Box::new(Self::get_artist), &self.results_artists, @@ -469,7 +469,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(2); } - URIType::Playlist => { + UriType::Playlist => { self.perform_search( Box::new(Self::get_playlist), &self.results_playlists, @@ -478,7 +478,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(3); } - URIType::Show => { + UriType::Show => { self.perform_search( Box::new(Self::get_show), &self.results_shows, @@ -487,7 +487,7 @@ impl SearchResultsView { ); self.tabs.move_focus_to(4); } - URIType::Episode => { + UriType::Episode => { self.perform_search( Box::new(Self::get_episode), &self.results_episodes,