Improve synchronization of playback times

Take librespot timestamps instead of approximating them in ncspot.
This commit is contained in:
Henrik Friedrichsen
2021-04-11 15:17:10 +02:00
parent 44da16dc0e
commit decf7c2aef
5 changed files with 36 additions and 27 deletions

View File

@@ -30,8 +30,8 @@ struct MprisState(String, Option<Playable>);
fn get_playbackstatus(spotify: Spotify) -> String { fn get_playbackstatus(spotify: Spotify) -> String {
match spotify.get_current_status() { match spotify.get_current_status() {
PlayerEvent::Playing | PlayerEvent::FinishedTrack => "Playing", PlayerEvent::Playing(_) | PlayerEvent::FinishedTrack => "Playing",
PlayerEvent::Paused => "Paused", PlayerEvent::Paused(_) => "Paused",
_ => "Stopped", _ => "Stopped",
} }
.to_string() .to_string()

View File

@@ -273,7 +273,7 @@ impl Queue {
pub fn toggleplayback(&self) { pub fn toggleplayback(&self) {
match self.spotify.get_current_status() { match self.spotify.get_current_status() {
PlayerEvent::Playing | PlayerEvent::Paused => { PlayerEvent::Playing(_) | PlayerEvent::Paused(_) => {
self.spotify.toggleplayback(); self.spotify.toggleplayback();
} }
PlayerEvent::Stopped => match self.next_index() { PlayerEvent::Stopped => match self.next_index() {

View File

@@ -60,8 +60,8 @@ pub const VOLUME_PERCENT: u16 = ((u16::max_value() as f64) * 1.0 / 100.0) as u16
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum PlayerEvent { pub enum PlayerEvent {
Playing, Playing(SystemTime),
Paused, Paused(Duration),
Stopped, Stopped,
FinishedTrack, FinishedTrack,
} }
@@ -746,12 +746,13 @@ impl Spotify {
pub fn update_status(&self, new_status: PlayerEvent) { pub fn update_status(&self, new_status: PlayerEvent) {
match new_status { match new_status {
PlayerEvent::Paused => { PlayerEvent::Paused(position) => {
self.set_elapsed(Some(self.get_current_progress())); self.set_elapsed(Some(position));
self.set_since(None); self.set_since(None);
} }
PlayerEvent::Playing => { PlayerEvent::Playing(playback_start) => {
self.set_since(Some(SystemTime::now())); self.set_since(Some(playback_start));
self.set_elapsed(None);
} }
PlayerEvent::Stopped | PlayerEvent::FinishedTrack => { PlayerEvent::Stopped | PlayerEvent::FinishedTrack => {
self.set_elapsed(None); self.set_elapsed(None);
@@ -778,8 +779,8 @@ impl Spotify {
pub fn toggleplayback(&self) { pub fn toggleplayback(&self) {
match self.get_current_status() { match self.get_current_status() {
PlayerEvent::Playing => self.pause(), PlayerEvent::Playing(_) => self.pause(),
PlayerEvent::Paused => self.play(), PlayerEvent::Paused(_) => self.play(),
_ => (), _ => (),
} }
} }
@@ -805,13 +806,6 @@ impl Spotify {
} }
pub fn seek(&self, position_ms: u32) { pub fn seek(&self, position_ms: u32) {
self.set_elapsed(Some(Duration::from_millis(position_ms.into())));
self.set_since(if self.get_current_status() == PlayerEvent::Playing {
Some(SystemTime::now())
} else {
None
});
self.send_worker(WorkerCommand::Seek(position_ms)); self.send_worker(WorkerCommand::Seek(position_ms));
} }

View File

@@ -14,8 +14,8 @@ use librespot_core::session::Session;
use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId}; use librespot_core::spotify_id::{SpotifyAudioType, SpotifyId};
use librespot_playback::mixer::Mixer; use librespot_playback::mixer::Mixer;
use librespot_playback::player::{Player, PlayerEvent as LibrespotPlayerEvent}; use librespot_playback::player::{Player, PlayerEvent as LibrespotPlayerEvent};
use std::pin::Pin;
use std::time::Duration; use std::time::Duration;
use std::{pin::Pin, time::SystemTime};
pub(crate) enum WorkerCommand { pub(crate) enum WorkerCommand {
Load(Playable, bool, u32), Load(Playable, bool, u32),
@@ -141,13 +141,28 @@ impl futures::Future for Worker {
| LibrespotPlayerEvent::Changed { .. } => { | LibrespotPlayerEvent::Changed { .. } => {
progress = true; progress = true;
} }
LibrespotPlayerEvent::Playing { .. } => { LibrespotPlayerEvent::Playing {
self.events.send(Event::Player(PlayerEvent::Playing)); play_request_id: _,
track_id: _,
position_ms,
duration_ms: _,
} => {
let position = Duration::from_millis(position_ms as u64);
let playback_start = SystemTime::now() - position;
self.events
.send(Event::Player(PlayerEvent::Playing(playback_start)));
self.refresh_task = self.create_refresh(); self.refresh_task = self.create_refresh();
self.active = true; self.active = true;
} }
LibrespotPlayerEvent::Paused { .. } => { LibrespotPlayerEvent::Paused {
self.events.send(Event::Player(PlayerEvent::Paused)); play_request_id: _,
track_id: _,
position_ms,
duration_ms: _,
} => {
let position = Duration::from_millis(position_ms as u64);
self.events
.send(Event::Player(PlayerEvent::Paused(position)));
self.active = false; self.active = false;
} }
LibrespotPlayerEvent::Stopped { .. } => { LibrespotPlayerEvent::Stopped { .. } => {

View File

@@ -72,14 +72,14 @@ impl View for StatusBar {
let state_icon = if self.use_nerdfont { let state_icon = if self.use_nerdfont {
match self.spotify.get_current_status() { match self.spotify.get_current_status() {
PlayerEvent::Playing => "\u{f909} ", PlayerEvent::Playing(_) => "\u{f909} ",
PlayerEvent::Paused => "\u{f8e3} ", PlayerEvent::Paused(_) => "\u{f8e3} ",
PlayerEvent::Stopped | PlayerEvent::FinishedTrack => "\u{f9da} ", PlayerEvent::Stopped | PlayerEvent::FinishedTrack => "\u{f9da} ",
} }
} else { } else {
match self.spotify.get_current_status() { match self.spotify.get_current_status() {
PlayerEvent::Playing => "", PlayerEvent::Playing(_) => "",
PlayerEvent::Paused => "▮▮", PlayerEvent::Paused(_) => "▮▮",
PlayerEvent::Stopped | PlayerEvent::FinishedTrack => "", PlayerEvent::Stopped | PlayerEvent::FinishedTrack => "",
} }
} }