@@ -20,6 +20,7 @@ use crate::{
2020 connect:: { Cluster , ClusterUpdate , LogoutCommand , SetVolumeCommand } ,
2121 context:: Context ,
2222 explicit_content_pubsub:: UserAttributesUpdate ,
23+ player:: ProvidedTrack ,
2324 playlist4_external:: PlaylistModificationInfo ,
2425 social_connect_v2:: SessionUpdate ,
2526 transfer_state:: TransferState ,
@@ -132,6 +133,7 @@ enum SpircCommand {
132133 Activate ,
133134 Transfer ( Option < TransferRequest > ) ,
134135 Load ( LoadRequest ) ,
136+ AddToQueue ( SpotifyUri ) ,
135137}
136138
137139const CONTEXT_FETCH_THRESHOLD : usize = 2 ;
@@ -388,6 +390,24 @@ impl Spirc {
388390 Ok ( self . commands . send ( SpircCommand :: Load ( command) ) ?)
389391 }
390392
393+ /// Adds a track, episode, album or playlist to the queue.
394+ ///
395+ /// Does nothing if we are not the active device.
396+ ///
397+ /// For albums and playlists, all tracks/episodes are resolved and added to the queue.
398+ pub fn add_to_queue ( & self , uri : SpotifyUri ) -> Result < ( ) , Error > {
399+ if !matches ! (
400+ uri,
401+ SpotifyUri :: Track { .. }
402+ | SpotifyUri :: Episode { .. }
403+ | SpotifyUri :: Album { .. }
404+ | SpotifyUri :: Playlist { .. }
405+ ) {
406+ return Err ( Error :: invalid_argument ( "uri" ) ) ;
407+ }
408+ Ok ( self . commands . send ( SpircCommand :: AddToQueue ( uri) ) ?)
409+ }
410+
391411 /// Disconnects the current device and pauses the playback according the value.
392412 ///
393413 /// Does nothing if we are not the active device.
@@ -679,6 +699,7 @@ impl SpircTask {
679699 SpircCommand :: SetPosition ( position) => self . handle_seek ( position) ,
680700 SpircCommand :: SetVolume ( volume) => self . set_volume ( volume) ,
681701 SpircCommand :: Load ( command) => self . handle_load ( command, None , None ) . await ?,
702+ SpircCommand :: AddToQueue ( uri) => self . handle_add_to_queue ( uri) . await ,
682703 } ;
683704
684705 self . notify ( ) . await
@@ -1062,7 +1083,13 @@ impl SpircTask {
10621083 self . handle_repeat_context ( repeat_context. value ) ?
10631084 }
10641085 SetRepeatingTrack ( repeat_track) => self . handle_repeat_track ( repeat_track. value ) ,
1065- AddToQueue ( add_to_queue) => self . connect_state . add_to_queue ( add_to_queue. track , true ) ,
1086+ AddToQueue ( add_to_queue) => {
1087+ let track = add_to_queue. track . clone ( ) ;
1088+ self . connect_state . add_to_queue ( add_to_queue. track , true ) ;
1089+ if let Ok ( uri) = SpotifyUri :: from_uri ( & track. uri ) {
1090+ self . player . emit_added_to_queue_event ( uri) ;
1091+ }
1092+ }
10661093 SetQueue ( set_queue) => self . connect_state . handle_set_queue ( set_queue) ,
10671094 SetOptions ( set_options) => {
10681095 if let Some ( repeat_context) = set_options. repeating_context {
@@ -1545,6 +1572,39 @@ impl SpircTask {
15451572 self . connect_state . set_repeat_track ( repeat) ;
15461573 }
15471574
1575+ async fn handle_add_to_queue ( & mut self , uri : SpotifyUri ) {
1576+ let track_uris: Vec < String > = match uri {
1577+ SpotifyUri :: Track { .. } | SpotifyUri :: Episode { .. } => vec ! [ uri. to_uri( ) ] ,
1578+ SpotifyUri :: Album { .. } | SpotifyUri :: Playlist { .. } => {
1579+ match self . session . spclient ( ) . get_context ( & uri. to_uri ( ) ) . await {
1580+ Ok ( context) => context
1581+ . pages
1582+ . iter ( )
1583+ . flat_map ( |page| page. tracks . iter ( ) )
1584+ . filter_map ( |track| track. uri . clone ( ) )
1585+ . collect ( ) ,
1586+ Err ( e) => {
1587+ error ! ( "failed to resolve context for {}: {e}" , uri. item_type( ) ) ;
1588+ return ;
1589+ }
1590+ }
1591+ }
1592+ _ => return ,
1593+ } ;
1594+
1595+ for track_uri in track_uris {
1596+ let track = ProvidedTrack {
1597+ uri : track_uri. clone ( ) ,
1598+ ..Default :: default ( )
1599+ } ;
1600+ self . connect_state . add_to_queue ( track, true ) ;
1601+
1602+ if let Ok ( uri) = SpotifyUri :: from_uri ( & track_uri) {
1603+ self . player . emit_added_to_queue_event ( uri) ;
1604+ }
1605+ }
1606+ }
1607+
15481608 fn handle_preload_next_track ( & mut self ) {
15491609 // Requests the player thread to preload the next track
15501610 match self . play_status {
0 commit comments