feat(mpris): Emit Seeked signal
* Add Seeked signal to Mpris interface The Mpris2 spec includes a `Seeked` signal which should be fired when the track position changes in an unexpected way i.e. when the user seeks to a different part of the track. This PR implements this signal on seek events and also when a new track begins. The latter is not strictly required but has been observed in other players (e.g. VLC). Closes #1492 * chore: Use `send_mpris()` and `Duration` for conversion * doc: Update CHANGELOG --------- Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
This commit is contained in:
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Emit MPRIS `Seeked` signal
|
||||
|
||||
### Fixed
|
||||
|
||||
- Switch to OAuth2 login mechanism
|
||||
|
||||
12
src/mpris.rs
12
src/mpris.rs
@@ -1,3 +1,5 @@
|
||||
#![allow(clippy::use_self)]
|
||||
|
||||
use log::info;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
@@ -6,6 +8,7 @@ use std::time::Duration;
|
||||
use tokio::sync::mpsc;
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
use tokio_stream::StreamExt;
|
||||
use zbus::object_server::SignalContext;
|
||||
use zbus::zvariant::{ObjectPath, Value};
|
||||
use zbus::{interface, ConnectionBuilder};
|
||||
|
||||
@@ -314,6 +317,9 @@ impl MprisPlayer {
|
||||
self.queue.get_current().is_some()
|
||||
}
|
||||
|
||||
#[zbus(signal)]
|
||||
async fn seeked(context: &SignalContext<'_>, position: &i64) -> zbus::Result<()>;
|
||||
|
||||
fn next(&self) {
|
||||
self.queue.next(true)
|
||||
}
|
||||
@@ -472,6 +478,8 @@ pub enum MprisCommand {
|
||||
EmitVolumeStatus,
|
||||
/// Emit metadata
|
||||
EmitMetadataStatus,
|
||||
/// Emit seeked position
|
||||
EmitSeekedStatus(i64),
|
||||
}
|
||||
|
||||
/// An MPRIS server that internally manager a thread which can be sent commands. This is internally
|
||||
@@ -539,6 +547,10 @@ impl MprisManager {
|
||||
Some(MprisCommand::EmitMetadataStatus) => {
|
||||
player_iface.metadata_changed(ctx).await?;
|
||||
}
|
||||
Some(MprisCommand::EmitSeekedStatus(pos)) => {
|
||||
info!("sending MPRIS seeked signal");
|
||||
MprisPlayer::seeked(ctx, &pos).await?;
|
||||
}
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +313,10 @@ impl Queue {
|
||||
move || send_notification(&summary_txt, &body_txt, cover_url)
|
||||
});
|
||||
}
|
||||
|
||||
// Send a Seeked signal at start of new track
|
||||
#[cfg(feature = "mpris")]
|
||||
self.spotify.notify_seeked(0);
|
||||
}
|
||||
|
||||
if reshuffle && self.get_shuffle() {
|
||||
|
||||
@@ -415,6 +415,8 @@ impl Spotify {
|
||||
/// Seek in the currently played [Playable] played by the [Player].
|
||||
pub fn seek(&self, position_ms: u32) {
|
||||
self.send_worker(WorkerCommand::Seek(position_ms));
|
||||
#[cfg(feature = "mpris")]
|
||||
self.notify_seeked(position_ms);
|
||||
}
|
||||
|
||||
/// Seek relatively to the current playback position of the [Player].
|
||||
@@ -429,6 +431,19 @@ impl Spotify {
|
||||
self.cfg.state().volume
|
||||
}
|
||||
|
||||
/// Send a Seeked signal on Mpris interface
|
||||
#[cfg(feature = "mpris")]
|
||||
pub fn notify_seeked(&self, position_ms: u32) {
|
||||
let new_position = Duration::from_millis(position_ms.into());
|
||||
let command = MprisCommand::EmitSeekedStatus(
|
||||
new_position
|
||||
.as_micros()
|
||||
.try_into()
|
||||
.expect("track position exceeds MPRIS datatype"),
|
||||
);
|
||||
self.send_mpris(command);
|
||||
}
|
||||
|
||||
/// Set the current volume of the [Player]. If `notify` is true, also notify MPRIS clients about
|
||||
/// the update.
|
||||
pub fn set_volume(&self, volume: u16, notify: bool) {
|
||||
|
||||
Reference in New Issue
Block a user