diff --git a/src/mpris/player.rs b/src/mpris/player.rs index 3868395..62c9ae7 100644 --- a/src/mpris/player.rs +++ b/src/mpris/player.rs @@ -219,17 +219,24 @@ impl Player { Ok(()) } + + fn playbin(&self) -> zbus::fdo::Result { + match self.playbin.upgrade() { + None => Err(zbus::fdo::Error::Failed("playbin was discarded".into())), + Some(playbin) => Ok(playbin), + } + } } #[zbus::interface(name = "org.mpris.MediaPlayer2.Player")] impl Player { - fn next(&self) { + fn next(&self) -> zbus::fdo::Result<()> { // If CanGoNext is false, attempting to call this method should have no effect. - if !self.can_go_next() { - return; + if !self.can_go_next()? { + return Ok(()); } - let playbin = self.playbin.upgrade().unwrap(); + let playbin = self.playbin()?; if playbin.play_queue_position() + 1 > playbin.play_queue_length() { // If there is no next track (and endless playback and track repeat are both off), stop playback. // (interpret this as something else than what Stop does) @@ -237,14 +244,16 @@ impl Player { } else { playbin.go_to_next_track(); } + + Ok(()) } - fn previous(&self) { - let playbin = self.playbin.upgrade().unwrap(); + fn previous(&self) -> zbus::fdo::Result<()> { + let playbin = self.playbin()?; // If CanGoPrevious is false, attempting to call this method should have no effect. - if !self.can_go_previous() { - return; + if !self.can_go_previous()? { + return Ok(()); } if playbin.play_queue_position() == 0 { @@ -254,74 +263,79 @@ impl Player { } else { playbin.go_to_prev_track(); } + + Ok(()) } - fn pause(&self) { - let playbin = self.playbin.upgrade().unwrap(); + fn pause(&self) -> zbus::fdo::Result<()> { + let playbin = self.playbin()?; // If CanPause is false, attempting to call this method should have no effect. if !self.can_pause() { - return; + return Ok(()); } // If playback is already paused, this has no effect. if playbin.state() != crate::playbin::State::Playing { - return; + return Ok(()); } - self.playbin.upgrade().unwrap().pause(); + playbin.pause(); + Ok(()) } - fn play_pause(&self) { + fn play_pause(&self) -> zbus::fdo::Result<()> { // don't think this is exactly according to spec but it looks more reasonable to me - if self.playbin.upgrade().unwrap().state() == crate::playbin::State::Paused { - self.play(); + if self.playbin()?.state() == crate::playbin::State::Paused { + self.play() } else { - self.pause(); + self.pause() } } - fn stop(&self) { - let playbin = self.playbin.upgrade().unwrap(); + fn stop(&self) -> zbus::fdo::Result<()> { + let playbin = self.playbin()?; // If playback is already stopped, this has no effect. if playbin.state() != crate::playbin::State::Playing { - return; + return Ok(()); } // Calling Play after this should cause playback to start again from the beginning of the track. playbin.pause(); playbin.seek(0.0); + Ok(()) } - fn play(&self) { - let playbin = self.playbin.upgrade().unwrap(); + fn play(&self) -> zbus::fdo::Result<()> { + let playbin = self.playbin()?; // If CanPlay is false, attempting to call this method should have no effect. - if !self.can_play() { - return; + if !self.can_play()? { + return Ok(()); } // If already playing, this has no effect. if playbin.state() == crate::playbin::State::Playing { - return; + return Ok(()); } // If there is no track to play, this has no effect. if playbin.play_queue_length() == 0 { - return; + return Ok(()); } playbin.play(); + Ok(()) } - fn seek(&self, offset: i64) { + fn seek(&self, offset: i64) -> zbus::fdo::Result<()> { // If the CanSeek property is false, this has no effect. if !self.can_seek() { - return; + return Ok(()); } - let playbin = self.playbin.upgrade().unwrap(); + let playbin = self.playbin()?; // Seeks forward in the current track by the specified number of microseconds. let mut new_position = (playbin.position() * MICROSECONDS) as i64 + offset; @@ -336,30 +350,32 @@ impl Player { } playbin.seek(new_position as f64 / MICROSECONDS); + Ok(()) } - fn set_position(&self, track_id: ObjectPath<'_>, position: i64) { - let playbin = self.playbin.upgrade().unwrap(); + fn set_position(&self, track_id: ObjectPath<'_>, position: i64) -> zbus::fdo::Result<()> { + let playbin = self.playbin()?; // If the Position argument is less than 0, do nothing. if position < 0 { - return; + return Ok(()); } // If the Position argument is greater than the track length, do nothing. if position > (playbin.duration() * MICROSECONDS) as i64 { - return; + return Ok(()); } // If the CanSeek property is false, this has no effect. if !self.can_seek() { - return; + return Ok(()); } // check if it's stale if self.metadata.track_id.as_deref() != Some(&track_id) { // TODO: warn of stale seek - return; + return Ok(()); } playbin.seek(position as f64 / MICROSECONDS); + Ok(()) } fn open_uri(&self, _s: &str) -> zbus::fdo::Result<()> { @@ -370,47 +386,50 @@ impl Player { async fn seeked(signal_emitter: &SignalEmitter<'_>, position: i64) -> zbus::Result<()>; #[zbus(property)] - fn playback_status(&self) -> String { - match self.playbin.upgrade().unwrap().state() { - crate::playbin::State::Stopped => "Stopped".into(), - crate::playbin::State::Playing => "Playing".into(), - crate::playbin::State::Paused => "Paused".into(), + fn playback_status(&self) -> zbus::fdo::Result<&str> { + match self.playbin()?.state() { + crate::playbin::State::Stopped => Ok("Stopped"), + crate::playbin::State::Playing => Ok("Playing"), + crate::playbin::State::Paused => Ok("Paused"), } } #[zbus(property)] - fn loop_status(&self) -> String { - "None".into() // TODO + fn loop_status(&self) -> zbus::fdo::Result { + Ok("None".into()) // TODO } #[zbus(property)] fn set_loop_status(&self, _loop_status: &str) -> zbus::Result<()> { - Err(zbus::Error::Unsupported) // TODO + Err(zbus::fdo::Error::NotSupported("setting LoopStatus".into()).into()) // TODO } #[zbus(property)] - fn rate(&self) -> f64 { - 1.0 + fn rate(&self) -> zbus::fdo::Result { + Ok(1.0) } #[zbus(property)] - fn set_rate(&self, rate: f64) { + fn set_rate(&self, rate: f64) -> zbus::Result<()> { // A value of 0.0 should not be set by the client. If it is, the media player should act as though Pause was called. if rate == 0.0 { - self.pause(); + self.pause()?; } // just ignore anything else + Ok(()) } #[zbus(property)] - fn shuffle(&self) -> bool { - false + // FIXME: zbus bug (?): this getter can't be infallible + fn shuffle(&self) -> zbus::fdo::Result { + Ok(false) } #[zbus(property)] + // FIXME: zbus bug (?): this setter can't return zbus::fdo::Result fn set_shuffle(&self, _shuffle: bool) -> zbus::Result<()> { - Err(zbus::Error::Unsupported) + Err(zbus::fdo::Error::NotSupported("setting Shuffle".into()).into()) } #[zbus(property)] @@ -419,24 +438,25 @@ impl Player { } #[zbus(property)] - fn volume(&self) -> f64 { - self.playbin.upgrade().unwrap().volume() as f64 / 100.0 + fn volume(&self) -> zbus::fdo::Result { + Ok(self.playbin()?.volume() as f64 / 100.0) } #[zbus(property)] - fn set_volume(&mut self, mut volume: f64) { + fn set_volume(&mut self, mut volume: f64) -> zbus::fdo::Result<()> { // When setting, if a negative value is passed, the volume should be set to 0.0. if volume < 0.0 { volume = 0.0; } - let playbin = self.playbin.upgrade().unwrap(); + let playbin = self.playbin()?; // FIXME: check if this is set by the notify callback: self.volume = volume; playbin.set_volume((volume * 100.0) as i32); + Ok(()) } #[zbus(property(emits_changed_signal = "false"))] - fn position(&self) -> i64 { - (self.playbin.upgrade().unwrap().position() * MICROSECONDS) as i64 + fn position(&self) -> zbus::fdo::Result { + Ok((self.playbin()?.position() * MICROSECONDS) as i64) } #[zbus(property)] @@ -450,21 +470,21 @@ impl Player { } #[zbus(property)] - fn can_go_next(&self) -> bool { + fn can_go_next(&self) -> zbus::fdo::Result { // same as can_play - self.playbin.upgrade().unwrap().play_queue_length() > 0 + Ok(self.playbin()?.play_queue_length() > 0) } #[zbus(property)] - fn can_go_previous(&self) -> bool { + fn can_go_previous(&self) -> zbus::fdo::Result { // same as can_play - self.playbin.upgrade().unwrap().play_queue_length() > 0 + Ok(self.playbin()?.play_queue_length() > 0) } #[zbus(property)] - fn can_play(&self) -> bool { + fn can_play(&self) -> zbus::fdo::Result { // it only makes sense to disallow "play" when the play queue is empty - self.playbin.upgrade().unwrap().play_queue_length() > 0 + Ok(self.playbin()?.play_queue_length() > 0) } #[zbus(property)]