Skip to content

Commit afd6e8c

Browse files
committed
feat(mpris): Get position from player and provide it to MPRIS
1 parent 8e15bef commit afd6e8c

File tree

1 file changed

+57
-13
lines changed

1 file changed

+57
-13
lines changed

src/mpris_event_handler.rs

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{collections::HashMap, process, sync::Arc};
1+
use std::{collections::HashMap, process, sync::Arc, time::Instant};
22

33
use librespot_connect::Spirc;
44
use 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+
560574
struct 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

Comments
 (0)