fix: emit MPRIS Seeked, so an already-open widget stops extrapolating
The owner's observation is what separated the two halves of this: "el contador del seekbar del widget solo empieza a contar hasta que lo abro." A client reads Position ONCE, when it opens, and extrapolates from there — it does not poll. So two different things were broken and only one was fixed by keeping the stored position fresh. Fresh storage fixes what a client sees when it OPENS. `Seeked` is the only thing that reaches one that is ALREADY open: it tells the client to stop extrapolating and re-read. Without it, a seek moved the music and the widget kept counting from where it had been. So the seek path emits Seeked instead of re-asserting the playback state, which was the previous commit's guess at a cure inside an API that had no signal. `mpris_server::Signal::Seeked` was there all along. Defaulted on the trait to `set_position`, so a backend without the signal still gets the value right on the next read and no other consumer changes: cargo check passes for qbz-app and qbzd. cc
This commit is contained in:
4 files changed
+48
-15
No files matched your search
@@ -20,7 +20,7 @@ use std::sync::{
|
||||
use mpris_server::zbus::{self, fdo};
|
||||
use mpris_server::{
|
||||
LoopStatus, Metadata, PlaybackRate, PlaybackStatus as MprisStatus, PlayerInterface, Property,
|
||||
RootInterface, Server, Time, TrackId, Volume,
|
||||
RootInterface, Server, Signal, Time, TrackId, Volume,
|
||||
};
|
||||
|
||||
use crate::inhibit::SleepInhibitor;
|
||||
@@ -58,6 +58,11 @@ enum Update {
|
||||
/// `PropertiesChanged` by design, so there is no signal to send; the point
|
||||
/// is purely that the next on-demand read is not stale.
|
||||
Position(Time),
|
||||
/// A DISCONTINUOUS jump. Stores like `Position` and additionally emits the
|
||||
/// `Seeked` signal, which is the ONE thing that tells an already-open
|
||||
/// client to stop extrapolating and re-read. Without it a widget keeps
|
||||
/// counting from wherever it was until it happens to poll again.
|
||||
Seeked(Time),
|
||||
}
|
||||
|
||||
/// The cloneable handle returned to the app. Pushing state is a non-blocking
|
||||
@@ -87,6 +92,12 @@ impl MediaIntegration for LinuxHandle {
|
||||
.tx
|
||||
.try_send(Update::Position(Time::from_micros(position.as_micros() as i64)));
|
||||
}
|
||||
|
||||
fn seeked(&self, position: std::time::Duration) {
|
||||
let _ = self
|
||||
.tx
|
||||
.try_send(Update::Seeked(Time::from_micros(position.as_micros() as i64)));
|
||||
}
|
||||
}
|
||||
|
||||
fn map_status(s: PlaybackStatus) -> MprisStatus {
|
||||
@@ -297,6 +308,10 @@ async fn apply(server: &Server<QbzMpris>, state: &Arc<Mutex<State>>, update: Upd
|
||||
Update::Position(p) => {
|
||||
state.lock().unwrap().position = p;
|
||||
}
|
||||
Update::Seeked(p) => {
|
||||
state.lock().unwrap().position = p;
|
||||
let _ = server.emit(Signal::Seeked { position: p }).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -91,4 +91,18 @@ pub trait MediaIntegration: Send + Sync {
|
||||
fn set_position(&self, position: Duration) {
|
||||
let _ = position;
|
||||
}
|
||||
|
||||
/// Report a DISCONTINUOUS jump — a user seek, not the ordinary advance of
|
||||
/// playback.
|
||||
///
|
||||
/// This is the one thing that reaches a client which is already open and
|
||||
/// extrapolating: `Seeked` tells it to stop and re-read. Keeping the
|
||||
/// stored position fresh (above) fixes what a client sees when it OPENS;
|
||||
/// this fixes what it sees while it is already watching.
|
||||
///
|
||||
/// Defaulted to `set_position`, so a backend without the signal still gets
|
||||
/// the value right on the next read.
|
||||
fn seeked(&self, position: Duration) {
|
||||
self.set_position(position);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user