rework mpris notification of PropertiesChanged

as sending out PropertiesChanged events was triggered asynchronously by a
message queue, retrieving the metadata during message formatting is too late.

this resulted in two PropertiesChanged messages announcing the new track as
playing.

this should prevent such a scenario.

as discussed in #89
This commit is contained in:
Henrik Friedrichsen
2019-09-01 01:10:35 +02:00
parent cd80ace4a8
commit 9a38eaa535

View File

@@ -10,6 +10,10 @@ use dbus::{Path, SignalArgs};
use queue::{Queue, RepeatSetting}; use queue::{Queue, RepeatSetting};
use spotify::{PlayerEvent, Spotify}; use spotify::{PlayerEvent, Spotify};
use track::Track;
type Metadata = HashMap<String, Variant<Box<RefArg>>>;
struct MprisState(String, Option<Track>);
fn get_playbackstatus(spotify: Arc<Spotify>) -> String { fn get_playbackstatus(spotify: Arc<Spotify>) -> String {
match spotify.get_current_status() { match spotify.get_current_status() {
@@ -20,11 +24,9 @@ fn get_playbackstatus(spotify: Arc<Spotify>) -> String {
.to_string() .to_string()
} }
fn get_metadata(queue: Arc<Queue>) -> HashMap<String, Variant<Box<RefArg>>> { fn get_metadata(track: Option<Track>) -> Metadata {
let mut hm: HashMap<String, Variant<Box<RefArg>>> = HashMap::new(); let mut hm: Metadata = HashMap::new();
let track = track.as_ref();
let t = queue.get_current();
let track = t.as_ref(); // TODO
hm.insert( hm.insert(
"mpris:trackid".to_string(), "mpris:trackid".to_string(),
@@ -81,7 +83,7 @@ fn get_metadata(queue: Arc<Queue>) -> HashMap<String, Variant<Box<RefArg>>> {
hm hm
} }
fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<()>) { fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<MprisState>) {
let conn = Rc::new( let conn = Rc::new(
dbus::Connection::get_private(dbus::BusType::Session).expect("Failed to connect to dbus"), dbus::Connection::get_private(dbus::BusType::Session).expect("Failed to connect to dbus"),
); );
@@ -193,7 +195,7 @@ fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<
f.property::<HashMap<String, Variant<Box<RefArg>>>, _>("Metadata", ()) f.property::<HashMap<String, Variant<Box<RefArg>>>, _>("Metadata", ())
.access(Access::Read) .access(Access::Read)
.on_get(move |iter, _| { .on_get(move |iter, _| {
let hm = get_metadata(queue.clone()); let hm = get_metadata(queue.clone().get_current());
iter.append(hm); iter.append(hm);
Ok(()) Ok(())
@@ -397,43 +399,54 @@ fn run_dbus_server(spotify: Arc<Spotify>, queue: Arc<Queue>, rx: mpsc::Receiver<
warn!("Unhandled dbus message: {:?}", m); warn!("Unhandled dbus message: {:?}", m);
} }
if rx.try_recv().is_ok() { if let Ok(state) = rx.try_recv() {
let mut changed: PropertiesPropertiesChanged = Default::default(); let mut changed: PropertiesPropertiesChanged = Default::default();
debug!("mpris PropertiesChanged: status {}, track: {:?}", state.0, state.1);
changed.interface_name = "org.mpris.MediaPlayer2.Player".to_string(); changed.interface_name = "org.mpris.MediaPlayer2.Player".to_string();
changed.changed_properties.insert( changed.changed_properties.insert(
"Metadata".to_string(), "Metadata".to_string(),
Variant(Box::new(get_metadata(queue.clone()))), Variant(Box::new(get_metadata(state.1))),
); );
changed.changed_properties.insert( changed.changed_properties.insert(
"PlaybackStatus".to_string(), "PlaybackStatus".to_string(),
Variant(Box::new(get_playbackstatus(spotify.clone()))), Variant(Box::new(state.0)),
); );
conn.send( conn.send(
changed.to_emit_message(&Path::new("/org/mpris/MediaPlayer2".to_string()).unwrap()), changed.to_emit_message(&Path::new("/org/mpris/MediaPlayer2".to_string()).unwrap()),
) )
.unwrap(); .unwrap();
} }
} }
} }
#[derive(Clone)] #[derive(Clone)]
pub struct MprisManager { pub struct MprisManager {
tx: mpsc::Sender<()>, tx: mpsc::Sender<MprisState>,
queue: Arc<Queue>,
spotify: Arc<Spotify>
} }
impl MprisManager { impl MprisManager {
pub fn new(spotify: Arc<Spotify>, queue: Arc<Queue>) -> Self { pub fn new(spotify: Arc<Spotify>, queue: Arc<Queue>) -> Self {
let (tx, rx) = mpsc::channel::<()>(); let (tx, rx) = mpsc::channel::<MprisState>();
std::thread::spawn(move || { {
run_dbus_server(spotify, queue, rx); let spotify = spotify.clone();
}); let queue = queue.clone();
std::thread::spawn(move || {
run_dbus_server(spotify.clone(), queue.clone(), rx);
});
}
MprisManager { tx } MprisManager { tx, queue, spotify }
} }
pub fn update(&self) { pub fn update(&self) {
self.tx.send(()).unwrap(); let status = get_playbackstatus(self.spotify.clone());
let track = self.queue.get_current();
self.tx.send(MprisState(status, track)).unwrap();
} }
} }