@@ -13,7 +13,7 @@ use futures::{
1313 future:: { self , Fuse , FusedFuture } ,
1414 stream:: Peekable ,
1515} ;
16- use librespot_connect:: { ConnectConfig , Spirc } ;
16+ use librespot_connect:: { ClusterUpdateInfo , ConnectConfig , Spirc } ;
1717use librespot_core:: {
1818 Error , SessionConfig , SpotifyUri , authentication:: Credentials , cache:: Cache ,
1919 config:: DeviceType , session:: Session ,
@@ -30,6 +30,10 @@ use log::{error, info};
3030use std:: pin:: Pin ;
3131use std:: sync:: Arc ;
3232
33+ const SPECTATOR_CONNECTION_ID : & str = "spectator-remote" ;
34+ const SPECTATOR_USER_NAME : & str = "spectator" ;
35+ const SPECTATOR_PLAY_REQUEST_ID : u64 = 0 ;
36+
3337#[ cfg( not( feature = "dbus_mpris" ) ) ]
3438type DbusServer = Pending < ( ) > ;
3539
@@ -222,16 +226,20 @@ impl MainLoop {
222226 let mut running_event_program = Box :: pin ( Fuse :: terminated ( ) ) ;
223227
224228 let mut event_channel = connection. player . get_player_event_channel ( ) ;
225- let mut state_channel = self
229+ let mut cluster_update_channel = self
226230 . spectator
227- . then ( || shared_spirc. as_ref ( ) . get_state_update_channel ( ) ) ;
231+ . then ( || shared_spirc. as_ref ( ) . get_cluster_update_channel ( ) ) ;
228232
229233 let mut last_track_uri: Option < String > = None ;
230- let mut last_play_request_id: u64 = 0 ;
234+ #[ cfg( feature = "dbus_mpris" ) ]
235+ let mut spectator_connected = false ;
231236
232- let mut emit_spectator_state =
233- |track_uri : String , is_playing : bool , position_ms : u32 , play_request_id : u64 | {
234- let track_changed = if let Some ( ref last_uri) = last_track_uri {
237+ let emit_spectator_state = |last_track_uri : & mut Option < String > ,
238+ track_uri : String ,
239+ is_playing : bool ,
240+ position_ms : u32 ,
241+ play_request_id : u64 | {
242+ let track_changed = if let Some ( ref last_uri) = * last_track_uri {
235243 last_uri != & track_uri && !track_uri. is_empty ( )
236244 } else {
237245 !track_uri. is_empty ( )
@@ -274,7 +282,7 @@ impl MainLoop {
274282 }
275283 }
276284
277- last_track_uri = Some ( track_uri) ;
285+ * last_track_uri = Some ( track_uri) ;
278286 } ;
279287
280288 loop {
@@ -308,30 +316,52 @@ impl MainLoop {
308316 result // unused variable
309317 }
310318 state = async {
311- match state_channel . as_mut( ) {
319+ match cluster_update_channel . as_mut( ) {
312320 Some ( channel) => channel. recv( ) . await ,
313321 None => future:: pending( ) . await
314322 }
315323 } , if self . spectator => {
316- if let Ok ( player_state) = state {
317- let track_uri = player_state. track
318- . as_ref( )
319- . map( |t| t. uri. clone( ) )
320- . unwrap_or_default( ) ;
324+ if let Ok ( ClusterUpdateInfo { active_device_id, track_uri, is_playing, position_ms } ) = state {
325+ let has_active_remote = !active_device_id. is_empty( ) ;
321326
322- let is_playing = player_state. is_playing;
323- let position_ms = player_state. position_as_of_timestamp as u32 ;
327+ #[ cfg( feature = "dbus_mpris" ) ]
328+ if let Some ( ref tx) = mpris_event_tx {
329+ if has_active_remote && !spectator_connected {
330+ let _ = tx. send( PlayerEvent :: SessionConnected {
331+ connection_id: SPECTATOR_CONNECTION_ID . to_string( ) ,
332+ user_name: SPECTATOR_USER_NAME . to_string( ) ,
333+ } ) ;
334+ spectator_connected = true ;
335+ } else if !has_active_remote && spectator_connected {
336+ if let Some ( ref uri) = last_track_uri
337+ && let Ok ( track_id) = SpotifyUri :: from_uri( uri)
338+ {
339+ let _ = tx. send( PlayerEvent :: Stopped {
340+ play_request_id: SPECTATOR_PLAY_REQUEST_ID ,
341+ track_id,
342+ } ) ;
343+ }
344+ let _ = tx. send( PlayerEvent :: SessionDisconnected {
345+ connection_id: SPECTATOR_CONNECTION_ID . to_string( ) ,
346+ user_name: SPECTATOR_USER_NAME . to_string( ) ,
347+ } ) ;
348+ spectator_connected = false ;
349+ }
350+ }
324351
325- if let Ok ( playback_id ) = player_state . playback_id . parse :: < u64 > ( ) {
326- last_play_request_id = playback_id ;
352+ if !has_active_remote {
353+ continue ;
327354 }
328355
329- emit_spectator_state(
330- track_uri,
331- is_playing,
332- position_ms,
333- last_play_request_id,
334- ) ;
356+ if let Some ( track_uri) = track_uri {
357+ emit_spectator_state(
358+ & mut last_track_uri,
359+ track_uri,
360+ is_playing. unwrap_or( false ) ,
361+ position_ms. unwrap_or( 0 ) ,
362+ SPECTATOR_PLAY_REQUEST_ID ,
363+ ) ;
364+ }
335365 }
336366 }
337367 // a new player event is available and no program is running
0 commit comments