use std::sync::Arc; use mpris_server::{ zbus::{fdo, Result}, LoopStatus, Metadata, PlaybackRate, PlaybackStatus, PlayerInterface, RootInterface, Time, TrackId, Volume, }; use tokio::sync::mpsc::Sender; use super::Messages; const ERROR: fdo::Error = fdo::Error::Failed(String::new()); /// The actual MPRIS server. pub struct Player { pub player: Arc, pub sender: Sender, } impl RootInterface for Player { async fn raise(&self) -> fdo::Result<()> { Err(ERROR) } async fn quit(&self) -> fdo::Result<()> { self.sender.send(Messages::Quit).await.map_err(|_| ERROR) } async fn can_quit(&self) -> fdo::Result { Ok(true) } async fn fullscreen(&self) -> fdo::Result { Ok(false) } async fn set_fullscreen(&self, _: bool) -> Result<()> { Ok(()) } async fn can_set_fullscreen(&self) -> fdo::Result { Ok(false) } async fn can_raise(&self) -> fdo::Result { Ok(false) } async fn has_track_list(&self) -> fdo::Result { Ok(false) } async fn identity(&self) -> fdo::Result { Ok("lowfi".to_string()) } async fn desktop_entry(&self) -> fdo::Result { Ok("dev.talwat.lowfi".to_string()) } async fn supported_uri_schemes(&self) -> fdo::Result> { Ok(vec!["https".to_string()]) } async fn supported_mime_types(&self) -> fdo::Result> { Ok(vec!["audio/mpeg".to_string()]) } } impl PlayerInterface for Player { async fn next(&self) -> fdo::Result<()> { self.sender.send(Messages::Next).await.map_err(|_| ERROR) } async fn previous(&self) -> fdo::Result<()> { Err(ERROR) } async fn pause(&self) -> fdo::Result<()> { self.sender .send(Messages::PlayPause) .await .map_err(|_| ERROR) } async fn play_pause(&self) -> fdo::Result<()> { self.sender .send(Messages::PlayPause) .await .map_err(|_| ERROR) } async fn stop(&self) -> fdo::Result<()> { self.play_pause().await } async fn play(&self) -> fdo::Result<()> { self.play_pause().await } async fn seek(&self, _offset: Time) -> fdo::Result<()> { Err(ERROR) } async fn set_position(&self, _track_id: TrackId, _position: Time) -> fdo::Result<()> { Err(ERROR) } async fn open_uri(&self, _uri: String) -> fdo::Result<()> { Err(ERROR) } async fn playback_status(&self) -> fdo::Result { Ok(if !self.player.current_exists() { PlaybackStatus::Stopped } else if self.player.sink.is_paused() { PlaybackStatus::Paused } else { PlaybackStatus::Playing }) } async fn loop_status(&self) -> fdo::Result { Err(ERROR) } async fn set_loop_status(&self, _loop_status: LoopStatus) -> Result<()> { Ok(()) } async fn rate(&self) -> fdo::Result { Ok(self.player.sink.speed().into()) } async fn set_rate(&self, rate: PlaybackRate) -> Result<()> { self.player.sink.set_speed(rate as f32); Ok(()) } async fn shuffle(&self) -> fdo::Result { Ok(true) } async fn set_shuffle(&self, _shuffle: bool) -> Result<()> { Ok(()) } async fn metadata(&self) -> fdo::Result { let metadata = match self.player.current.load().as_ref() { Some(track) => { let mut metadata = Metadata::builder().title(track.name.clone()).build(); metadata.set_length( track .duration .and_then(|x| Some(Time::from_micros(x.as_micros() as i64))), ); metadata } None => Metadata::new(), }; Ok(metadata) } async fn volume(&self) -> fdo::Result { Ok(self.player.sink.volume().into()) } async fn set_volume(&self, volume: Volume) -> Result<()> { self.player.sink.set_volume(volume as f32); Ok(()) } async fn position(&self) -> fdo::Result