1- use std:: { collections:: HashMap , process, sync:: Arc } ;
1+ use std:: { collections:: HashMap , process, sync:: Arc , time :: Instant } ;
22
33use librespot_connect:: Spirc ;
44use log:: { debug, warn} ;
@@ -557,12 +557,27 @@ impl TryInto<HashMap<String, zbus::zvariant::OwnedValue>> for Metadata {
557557 }
558558}
559559
560+ struct Position {
561+ ms : u32 ,
562+ last_update : Instant ,
563+ }
564+
565+ impl From < u32 > for Position {
566+ fn from ( value : u32 ) -> Self {
567+ Self {
568+ ms : value,
569+ last_update : Instant :: now ( ) ,
570+ }
571+ }
572+ }
573+
560574struct MprisPlayerService {
561575 spirc : Option < Spirc > ,
562576 repeat : LoopStatus ,
563577 shuffle : bool ,
564578 playback_status : PlaybackStatus ,
565579 volume : u16 ,
580+ position : Option < Position > ,
566581 metadata : Metadata ,
567582}
568583
@@ -904,8 +919,15 @@ impl MprisPlayerService {
904919 #[ zbus( property( emits_changed_signal = "false" ) ) ]
905920 async fn position ( & self ) -> zbus:: fdo:: Result < TimeInUs > {
906921 debug ! ( "org.mpris.MediaPlayer2.Player::Position" ) ;
907- // todo!("fetch up-to-date position from player")
908- Ok ( 0 )
922+
923+ self . position
924+ . as_ref ( )
925+ . map ( |position| {
926+ let corrected = ( position. ms as u128 )
927+ . saturating_add ( position. last_update . elapsed ( ) . as_millis ( ) ) ;
928+ corrected as i64 * 1000
929+ } )
930+ . ok_or ( zbus:: fdo:: Error :: Failed ( String :: from ( "Got no position" ) ) )
909931 }
910932
911933 // The minimum value which the `Rate` property can take. Clients should not attempt to set the
@@ -1104,6 +1126,7 @@ impl MprisEventHandler {
11041126 shuffle : false ,
11051127 playback_status : PlaybackStatus :: Stopped ,
11061128 volume : u16:: MAX ,
1129+ position : None ,
11071130 metadata : Metadata :: default ( ) ,
11081131 } ;
11091132
@@ -1261,12 +1284,14 @@ impl MprisTask {
12611284 }
12621285 PlayerEvent :: Playing {
12631286 track_id,
1264- // position_ms,
1287+ position_ms,
12651288 ..
12661289 } => {
1267- // TODO: update position
12681290 let iface_ref = self . mpris_player_iface ( ) . await ;
12691291 let mut iface = iface_ref. get_mut ( ) . await ;
1292+
1293+ iface. position = Some ( Position :: from ( position_ms) ) ;
1294+
12701295 let meta = & mut iface. metadata ;
12711296
12721297 if meta. mpris . track_id . as_ref ( ) != Some ( & track_id) {
@@ -1283,12 +1308,14 @@ impl MprisTask {
12831308 }
12841309 PlayerEvent :: Paused {
12851310 track_id,
1286- // position_ms,
1311+ position_ms,
12871312 ..
12881313 } => {
1289- // TODO: update position
12901314 let iface_ref = self . mpris_player_iface ( ) . await ;
12911315 let mut iface = iface_ref. get_mut ( ) . await ;
1316+
1317+ iface. position = Some ( Position :: from ( position_ms) ) ;
1318+
12921319 let meta = & mut iface. metadata ;
12931320
12941321 if meta. mpris . track_id . as_ref ( ) != Some ( & track_id) {
@@ -1307,15 +1334,20 @@ impl MprisTask {
13071334 PlayerEvent :: Preloading { .. } => { }
13081335 PlayerEvent :: TimeToPreloadNextTrack { .. } => { }
13091336 PlayerEvent :: EndOfTrack { track_id, .. } => {
1310- // TODO: Update position
13111337 let iface_ref = self . mpris_player_iface ( ) . await ;
13121338 let mut iface = iface_ref. get_mut ( ) . await ;
13131339 let meta = & mut iface. metadata ;
13141340
1315- if meta. mpris . track_id . as_ref ( ) != Some ( & track_id) {
1341+ if meta. mpris . track_id . as_ref ( ) == Some ( & track_id) {
1342+ iface. position = meta
1343+ . mpris
1344+ . length
1345+ . map ( |length| Position :: from ( ( length as f64 / 1000. ) as u32 ) ) ;
1346+ } else {
13161347 * meta = Metadata :: default ( ) ;
13171348 meta. mpris . track_id = Some ( track_id) ;
13181349 warn ! ( "Missed TrackChanged event, metadata missing" ) ;
1350+ iface. position = None ;
13191351 iface. metadata_changed ( iface_ref. signal_context ( ) ) . await ?;
13201352 }
13211353 }
@@ -1330,12 +1362,14 @@ impl MprisTask {
13301362 }
13311363 PlayerEvent :: Seeked {
13321364 track_id,
1333- // position_ms,
1365+ position_ms,
13341366 ..
13351367 } => {
1336- // TODO: Update position
13371368 let iface_ref = self . mpris_player_iface ( ) . await ;
13381369 let mut iface = iface_ref. get_mut ( ) . await ;
1370+
1371+ iface. position = Some ( Position :: from ( position_ms) ) ;
1372+
13391373 let meta = & mut iface. metadata ;
13401374
13411375 if meta. mpris . track_id . as_ref ( ) != Some ( & track_id) {
@@ -1347,11 +1381,14 @@ impl MprisTask {
13471381 }
13481382 PlayerEvent :: PositionCorrection {
13491383 track_id,
1350- // position_ms,
1384+ position_ms,
13511385 ..
13521386 } => {
13531387 let iface_ref = self . mpris_player_iface ( ) . await ;
13541388 let mut iface = iface_ref. get_mut ( ) . await ;
1389+
1390+ iface. position = Some ( Position :: from ( position_ms) ) ;
1391+
13551392 let meta = & mut iface. metadata ;
13561393
13571394 if meta. mpris . track_id . as_ref ( ) != Some ( & track_id) {
@@ -1361,9 +1398,16 @@ impl MprisTask {
13611398 iface. metadata_changed ( iface_ref. signal_context ( ) ) . await ?;
13621399 }
13631400 }
1364- PlayerEvent :: PositionChanged { track_id, .. } => {
1401+ PlayerEvent :: PositionChanged {
1402+ track_id,
1403+ position_ms,
1404+ ..
1405+ } => {
13651406 let iface_ref = self . mpris_player_iface ( ) . await ;
13661407 let mut iface = iface_ref. get_mut ( ) . await ;
1408+
1409+ iface. position = Some ( Position :: from ( position_ms) ) ;
1410+
13671411 let meta = & mut iface. metadata ;
13681412
13691413 if meta. mpris . track_id . as_ref ( ) != Some ( & track_id) {
0 commit comments