@@ -1087,13 +1087,17 @@ impl SpircTask {
10871087 fn handle_transfer ( & mut self , mut transfer : TransferState ) -> Result < ( ) , Error > {
10881088 let mut ctx_uri = match transfer. current_session . context . uri {
10891089 None => Err ( SpircError :: NoUri ( "transfer context" ) ) ?,
1090- // can apparently happen when a state is transferred stared with "uris" via the api
1091- Some ( ref uri) if uri == "-" => String :: new ( ) ,
1092- Some ( ref uri) => uri. clone ( ) ,
1090+ // can apparently happen when a state is transferred and was started with "uris" via the api
1091+ Some ( ref uri) if uri == "-" || uri . is_empty ( ) => None ,
1092+ Some ( ref uri) => Some ( uri. clone ( ) ) ,
10931093 } ;
10941094
1095- self . connect_state
1096- . reset_context ( ResetContext :: WhenDifferent ( & ctx_uri) ) ;
1095+ self . connect_state . reset_context (
1096+ ctx_uri
1097+ . as_deref ( )
1098+ . map ( ResetContext :: WhenDifferent )
1099+ . unwrap_or ( ResetContext :: Completely ) ,
1100+ ) ;
10971101
10981102 match self . connect_state . current_track_from_transfer ( & transfer) {
10991103 Err ( why) => warn ! ( "didn't find initial track: {why}" ) ,
@@ -1105,44 +1109,47 @@ impl SpircTask {
11051109
11061110 let autoplay = self . connect_state . current_track ( |t| t. is_autoplay ( ) ) ;
11071111 if autoplay {
1108- ctx_uri = ctx_uri. replace ( "station:" , "" ) ;
1112+ ctx_uri = ctx_uri. map ( |c| c . replace ( "station:" , "" ) ) ;
11091113 }
11101114
11111115 let fallback = self . connect_state . current_track ( |t| & t. uri ) . clone ( ) ;
1112- let load_from_context_uri = !ctx_uri. is_empty ( ) ;
1113-
1114- if load_from_context_uri {
1115- self . context_resolver . add ( ResolveContext :: from_uri (
1116- ctx_uri. clone ( ) ,
1117- & fallback,
1118- ContextType :: Default ,
1119- ContextAction :: Replace ,
1120- ) ) ;
1121- } else {
1122- self . load_context_from_tracks (
1123- transfer
1116+ let load_from_context_uri = ctx_uri. is_some ( ) ;
1117+
1118+ match ctx_uri {
1119+ Some ( ref uri) => {
1120+ self . context_resolver . add ( ResolveContext :: from_uri (
1121+ uri. clone ( ) ,
1122+ & fallback,
1123+ ContextType :: Default ,
1124+ ContextAction :: Replace ,
1125+ ) ) ;
1126+ }
1127+ None => {
1128+ let all_tracks = transfer
11241129 . current_session
11251130 . context
11261131 . pages
11271132 . iter ( )
11281133 . cloned ( )
11291134 . flat_map ( |p| p. tracks )
1130- . collect :: < Vec < _ > > ( ) ,
1131- ) ?
1132- }
1135+ . collect :: < Vec < _ > > ( ) ;
11331136
1134- self . context_resolver . add ( ResolveContext :: from_uri (
1135- ctx_uri. clone ( ) ,
1136- & fallback,
1137- ContextType :: Default ,
1138- ContextAction :: Replace ,
1139- ) ) ;
1137+ if !all_tracks. is_empty ( ) {
1138+ self . load_context_from_tracks ( all_tracks) ?;
1139+ } else {
1140+ warn ! (
1141+ "tried to transfer with an invalid state, using fallback as ctx_uri ({fallback})"
1142+ ) ;
1143+ ctx_uri = Some ( fallback. clone ( ) )
1144+ }
1145+ }
1146+ } ;
11401147
11411148 self . handle_activate ( ) ;
11421149
11431150 let timestamp = self . now_ms ( ) ;
11441151 let state = & mut self . connect_state ;
1145- state. handle_initial_transfer ( & mut transfer) ;
1152+ state. handle_initial_transfer ( & mut transfer, ctx_uri . clone ( ) ) ;
11461153
11471154 // adjust active context, so resolve knows for which context it should set up the state
11481155 state. active_context = if autoplay {
@@ -1166,24 +1173,34 @@ impl SpircTask {
11661173 let is_playing = !transfer. playback . is_paused ( ) ;
11671174
11681175 if self . connect_state . current_track ( |t| t. is_autoplay ( ) ) || autoplay {
1169- debug ! ( "currently in autoplay context, async resolving autoplay for {ctx_uri}" ) ;
1170-
1171- self . context_resolver . add ( ResolveContext :: from_uri (
1172- ctx_uri,
1173- fallback,
1174- ContextType :: Autoplay ,
1175- ContextAction :: Replace ,
1176- ) )
1176+ if let Some ( ctx_uri) = ctx_uri {
1177+ debug ! ( "currently in autoplay context, async resolving autoplay for {ctx_uri}" ) ;
1178+ self . context_resolver . add ( ResolveContext :: from_uri (
1179+ ctx_uri,
1180+ fallback,
1181+ ContextType :: Autoplay ,
1182+ ContextAction :: Replace ,
1183+ ) )
1184+ } else {
1185+ warn ! ( "couldn't resolve autoplay context without a context uri" ) ;
1186+ }
11771187 }
11781188
11791189 if load_from_context_uri {
11801190 self . transfer_state = Some ( transfer) ;
11811191 } else {
1182- let ctx = self . connect_state . get_context ( ContextType :: Default ) ?;
1183- let idx = ConnectState :: find_index_in_context ( ctx, |pt| {
1184- self . connect_state . current_track ( |t| pt. uri == t. uri )
1185- } ) ?;
1186- self . connect_state . reset_playback_to_position ( Some ( idx) ) ?;
1192+ match self . connect_state . get_context ( ContextType :: Default ) {
1193+ Err ( why) => {
1194+ warn ! ( "continuing transfer in an unknown state. {why}" ) ;
1195+ self . transfer_state = Some ( transfer) ;
1196+ }
1197+ Ok ( ctx) => {
1198+ let idx = ConnectState :: find_index_in_context ( ctx, |pt| {
1199+ self . connect_state . current_track ( |t| pt. uri == t. uri )
1200+ } ) ?;
1201+ self . connect_state . reset_playback_to_position ( Some ( idx) ) ?;
1202+ }
1203+ }
11871204 }
11881205
11891206 self . load_track ( is_playing, position. try_into ( ) ?)
@@ -1397,7 +1414,11 @@ impl SpircTask {
13971414 }
13981415
13991416 fn load_context_from_tracks ( & mut self , tracks : impl Into < ContextPage > ) -> Result < ( ) , Error > {
1417+ const WEB_API_URI : & str = "spotify:web-api" ;
14001418 let ctx = Context {
1419+ // by providing values for uri/url the player in the official client's isn't frozen
1420+ uri : Some ( WEB_API_URI . into ( ) ) ,
1421+ url : Some ( format ! ( "context://{WEB_API_URI}" ) ) ,
14011422 pages : vec ! [ tracks. into( ) ] ,
14021423 ..Default :: default ( )
14031424 } ;
0 commit comments