@@ -17,10 +17,11 @@ use crate::{
1717 protocol:: {
1818 autoplay_context_request:: AutoplayContextRequest ,
1919 connect:: { Cluster , ClusterUpdate , LogoutCommand , SetVolumeCommand } ,
20+ context:: Context ,
2021 explicit_content_pubsub:: UserAttributesUpdate ,
21- player:: { Context , TransferState } ,
2222 playlist4_external:: PlaylistModificationInfo ,
23- social_connect_v2:: { session:: _host_active_device_id, SessionUpdate } ,
23+ social_connect_v2:: SessionUpdate ,
24+ transfer_state:: TransferState ,
2425 user_attributes:: UserAttributesMutation ,
2526 } ,
2627} ;
@@ -49,6 +50,8 @@ use tokio::{sync::mpsc, time::sleep};
4950pub enum SpircError {
5051 #[ error( "response payload empty" ) ]
5152 NoData ,
53+ #[ error( "{0} had no uri" ) ]
54+ NoUri ( & ' static str ) ,
5255 #[ error( "message pushed for another URI" ) ]
5356 InvalidUri ( String ) ,
5457 #[ error( "tried resolving not allowed context: {0:?}" ) ]
@@ -63,7 +66,7 @@ impl From<SpircError> for Error {
6366 fn from ( err : SpircError ) -> Self {
6467 use SpircError :: * ;
6568 match err {
66- NoData | NotAllowedContext ( _) => Error :: unavailable ( err) ,
69+ NoData | NoUri ( _ ) | NotAllowedContext ( _) => Error :: unavailable ( err) ,
6770 InvalidUri ( _) | FailedDealerSetup => Error :: aborted ( err) ,
6871 UnknownEndpoint ( _) => Error :: unimplemented ( err) ,
6972 }
@@ -522,14 +525,14 @@ impl SpircTask {
522525 let mut ctx = self . session . spclient ( ) . get_context ( resolve_uri) . await ?;
523526
524527 if update {
525- ctx. uri = context_uri. to_string ( ) ;
526- ctx. url = format ! ( "context://{context_uri}" ) ;
528+ ctx. uri = Some ( context_uri. to_string ( ) ) ;
529+ ctx. url = Some ( format ! ( "context://{context_uri}" ) ) ;
527530
528531 self . connect_state
529532 . update_context ( ctx, UpdateContext :: Default ) ?
530533 } else if matches ! ( ctx. pages. first( ) , Some ( p) if !p. tracks. is_empty( ) ) {
531534 debug ! (
532- "update context from single page, context {} had {} pages" ,
535+ "update context from single page, context {:? } had {} pages" ,
533536 ctx. uri,
534537 ctx. pages. len( )
535538 ) ;
@@ -883,7 +886,7 @@ impl SpircTask {
883886 let attributes: UserAttributes = update
884887 . pairs
885888 . iter ( )
886- . map ( |pair | ( pair . key ( ) . to_owned ( ) , pair . value ( ) . to_owned ( ) ) )
889+ . map ( |( key , value ) | ( key. to_owned ( ) , value. to_owned ( ) ) )
887890 . collect ( ) ;
888891 self . session . set_user_attributes ( attributes)
889892 }
@@ -998,9 +1001,10 @@ impl SpircTask {
9981001 Unknown ( unknown) => Err ( SpircError :: UnknownEndpoint ( unknown) ) ?,
9991002 // implicit update of the connect_state
10001003 UpdateContext ( update_context) => {
1001- if & update_context. context . uri != self . connect_state . context_uri ( ) {
1004+ if matches ! ( update_context. context. uri, Some ( ref uri) if uri != self . connect_state. context_uri( ) )
1005+ {
10021006 debug ! (
1003- "ignoring context update for <{}>, because it isn't the current context <{}>" ,
1007+ "ignoring context update for <{:? }>, because it isn't the current context <{}>" ,
10041008 update_context. context. uri, self . connect_state. context_uri( )
10051009 )
10061010 } else {
@@ -1020,24 +1024,30 @@ impl SpircTask {
10201024 . options
10211025 . player_options_override
10221026 . as_ref ( )
1023- . map ( |o| o. shuffling_context )
1027+ . map ( |o| o. shuffling_context . unwrap_or_default ( ) )
10241028 . unwrap_or_else ( || self . connect_state . shuffling_context ( ) ) ;
10251029 let repeat = play
10261030 . options
10271031 . player_options_override
10281032 . as_ref ( )
1029- . map ( |o| o. repeating_context )
1033+ . map ( |o| o. repeating_context . unwrap_or_default ( ) )
10301034 . unwrap_or_else ( || self . connect_state . repeat_context ( ) ) ;
10311035 let repeat_track = play
10321036 . options
10331037 . player_options_override
10341038 . as_ref ( )
1035- . map ( |o| o. repeating_track )
1039+ . map ( |o| o. repeating_track . unwrap_or_default ( ) )
10361040 . unwrap_or_else ( || self . connect_state . repeat_track ( ) ) ;
10371041
1042+ let context_uri = play
1043+ . context
1044+ . uri
1045+ . clone ( )
1046+ . ok_or ( SpircError :: NoUri ( "context" ) ) ?;
1047+
10381048 self . handle_load (
10391049 SpircLoadCommand {
1040- context_uri : play . context . uri . clone ( ) ,
1050+ context_uri,
10411051 start_playing : true ,
10421052 seek_to : play. options . seek_to . unwrap_or_default ( ) ,
10431053 playing_track : play. options . skip_to . unwrap_or_default ( ) . into ( ) ,
@@ -1088,12 +1098,13 @@ impl SpircTask {
10881098 }
10891099
10901100 fn handle_transfer ( & mut self , mut transfer : TransferState ) -> Result < ( ) , Error > {
1091- self . connect_state
1092- . reset_context ( ResetContext :: WhenDifferent (
1093- & transfer . current_session . context . uri ,
1094- ) ) ;
1101+ let mut ctx_uri = match transfer . current_session . context . uri {
1102+ None => Err ( SpircError :: NoUri ( "transfer context" ) ) ? ,
1103+ Some ( ref uri ) => uri. clone ( ) ,
1104+ } ;
10951105
1096- let mut ctx_uri = transfer. current_session . context . uri . clone ( ) ;
1106+ self . connect_state
1107+ . reset_context ( ResetContext :: WhenDifferent ( & ctx_uri) ) ;
10971108
10981109 match self . connect_state . current_track_from_transfer ( & transfer) {
10991110 Err ( why) => warn ! ( "didn't find initial track: {why}" ) ,
@@ -1118,17 +1129,18 @@ impl SpircTask {
11181129 state. set_active ( true ) ;
11191130 state. handle_initial_transfer ( & mut transfer) ;
11201131
1121- // update position if the track continued playing
1122- let position = if transfer. playback . is_paused {
1123- transfer. playback . position_as_of_timestamp . into ( )
1124- } else if transfer. playback . position_as_of_timestamp > 0 {
1125- let time_since_position_update = timestamp - transfer. playback . timestamp ;
1126- i64:: from ( transfer. playback . position_as_of_timestamp ) + time_since_position_update
1127- } else {
1128- 0
1132+ let transfer_timestamp = transfer. playback . timestamp . unwrap_or_default ( ) ;
1133+ let position = match transfer. playback . position_as_of_timestamp {
1134+ Some ( position) if transfer. playback . is_paused . unwrap_or_default ( ) => position. into ( ) ,
1135+ // update position if the track continued playing
1136+ Some ( position) if position > 0 => {
1137+ let time_since_position_update = timestamp - transfer_timestamp;
1138+ i64:: from ( position) + time_since_position_update
1139+ }
1140+ _ => 0 ,
11291141 } ;
11301142
1131- let is_playing = ! transfer. playback . is_paused ;
1143+ let is_playing = matches ! ( transfer. playback. is_paused, Some ( is_playing ) if is_playing ) ;
11321144
11331145 if self . connect_state . current_track ( |t| t. is_autoplay ( ) ) || autoplay {
11341146 debug ! ( "currently in autoplay context, async resolving autoplay for {ctx_uri}" ) ;
@@ -1514,7 +1526,9 @@ impl SpircTask {
15141526 & mut self ,
15151527 playlist_modification_info : PlaylistModificationInfo ,
15161528 ) -> Result < ( ) , Error > {
1517- let uri = playlist_modification_info. uri . ok_or ( SpircError :: NoData ) ?;
1529+ let uri = playlist_modification_info
1530+ . uri
1531+ . ok_or ( SpircError :: NoUri ( "playlist modification" ) ) ?;
15181532 let uri = String :: from_utf8 ( uri) ?;
15191533
15201534 if self . connect_state . context_uri ( ) != & uri {
@@ -1540,14 +1554,7 @@ impl SpircTask {
15401554 Some ( session) => session,
15411555 } ;
15421556
1543- let active_device = session. _host_active_device_id . take ( ) . map ( |id| match id {
1544- _host_active_device_id:: HostActiveDeviceId ( id) => id,
1545- other => {
1546- warn ! ( "unexpected active device id {other:?}" ) ;
1547- String :: new ( )
1548- }
1549- } ) ;
1550-
1557+ let active_device = session. host_active_device_id . take ( ) ;
15511558 if matches ! ( active_device, Some ( ref device) if device == self . session. device_id( ) ) {
15521559 info ! (
15531560 "session update: <{:?}> for self, current session_id {}, new session_id {}" ,
0 commit comments