Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 2ef67be5 rédigé par Kubat's avatar Kubat
Parcourir les fichiers

MPRIS: Add the default implementations for the MPRIS server

parent 2e4c79d0
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
use zbus::DBusError;
#[derive(DBusError, Debug)]
#[dbus_error(prefix = "org.mpris.MediaPlayer2")]
pub enum Error {
#[dbus_error(zbus_error)]
ZBus(zbus::Error),
NoFile(String),
}
pub type MPRISResult<T> = std::result::Result<T, Error>;
pub mod error;
pub mod server; pub mod server;
pub mod types; pub mod types;
//! # DBus interface for: `org.mpris.MediaPlayer2`, `org.mpris.MediaPlayer2.Player` //! # DBus interface for: `org.mpris.MediaPlayer2`, `org.mpris.MediaPlayer2.Player`
// use crate::types::*; // use crate::types::*;
use crate::types::*;
use commons::log;
use zbus::dbus_interface; use zbus::dbus_interface;
/// Should be served at "/org/mpris/MediaPlayer2"
pub struct MediaPlayer2 { pub struct MediaPlayer2 {
identity: String, identity: String,
} }
/// Should be served at "/org/mpris/MediaPlayer2"
pub struct MediaPlayer2Player {}
#[dbus_interface(name = "org.mpris.MediaPlayer2")] #[dbus_interface(name = "org.mpris.MediaPlayer2")]
impl MediaPlayer2 { impl MediaPlayer2 {
/// Quit method /// Quit method
#[dbus_interface(name = "Quit")]
fn quit(&self) {} fn quit(&self) {}
/// Raise method /// Raise method
#[dbus_interface(name = "Raise")]
fn raise(&self) {} fn raise(&self) {}
/// CanQuit property /// CanQuit property
...@@ -45,7 +53,7 @@ impl MediaPlayer2 { ...@@ -45,7 +53,7 @@ impl MediaPlayer2 {
false false
} }
#[dbus_interface(property, name = "Fullscreen")] #[dbus_interface(property, name = "Fullscreen")]
fn set_fullscreen(&mut self, _value: bool) {} fn set_fullscreen(&self, _value: bool) {}
/// HasTrackList property /// HasTrackList property
#[dbus_interface(property, name = "HasTrackList")] #[dbus_interface(property, name = "HasTrackList")]
...@@ -75,110 +83,128 @@ impl MediaPlayer2 { ...@@ -75,110 +83,128 @@ impl MediaPlayer2 {
} }
} }
// #[dbus_interface( #[dbus_interface(name = "org.mpris.MediaPlayer2.Player")]
// interface = "org.mpris.MediaPlayer2.Player", impl MediaPlayer2Player {
// default_path = "/org/mpris/MediaPlayer2", /// Next method
// assume_defaults = true fn next(&self) {}
// )]
// trait Player { /// Pause method
// /// Next method fn pause(&self) {
// fn next(&self) -> zbus::Result<()>; todo!()
// }
// /// OpenUri method
// fn open_uri(&self, id_uri: &str) -> zbus::Result<()>; /// Play method
// fn play(&self) {
// /// Pause method todo!()
// fn pause(&self) -> zbus::Result<()>; }
//
// /// Play method /// OpenUri method
// fn play(&self) -> zbus::Result<()>; fn open_uri(&self, uri: &str) {
// todo!("handle open uri {uri}")
// /// PlayPause method }
// fn play_pause(&self) -> zbus::Result<()>;
// fn play_pause(&self) {
// /// Previous method todo!()
// fn previous(&self) -> zbus::Result<()>; }
//
// /// Seek method /// Previous method
// fn seek(&self, time: TimeMicroSec) -> zbus::Result<()>; fn previous(&self) {
// todo!()
// /// SetPosition method }
// fn set_position(
// &self, /// Seek method
// track_id: &MediaPlayerObjectPath, fn seek(&self, offset: TimeMicroSec) {
// time: TimeMicroSec, todo!("handle seek offset {offset:?}")
// ) -> zbus::Result<()>; }
//
// /// Stop method /// SetPosition method
// fn stop(&self) -> zbus::Result<()>; fn set_position(&self, track_id: MediaPlayerObjectPath, position: TimeMicroSec) {
// todo!("handle set position {track_id:?} {position:?}")
// /// CanControl property }
// #[dbus_interface(property)]
// fn can_control(&self) -> zbus::Result<bool>; /// Stop method
// fn stop(&self) {
// /// CanPause property todo!()
// #[dbus_interface(property)] }
// fn can_pause(&self) -> zbus::Result<bool>;
// /// CanControl property
// /// CanPlay property #[dbus_interface(property)]
// #[dbus_interface(property)] fn can_control(&self) -> bool {
// fn can_play(&self) -> zbus::Result<bool>; true
// }
// /// CanSeek property
// #[dbus_interface(property)] /// CanPause property
// fn can_seek(&self) -> zbus::Result<bool>; #[dbus_interface(property)]
// fn can_pause(&self) -> bool {
// /// LoopStatus property todo!()
// #[dbus_interface(property)] }
// fn loop_status(&self) -> zbus::Result<MediaPlayerObjectPath>;
// fn set_loop_status(&self, value: &MediaPlayerObjectPath) -> zbus::Result<()>; /// CanPlay property
// #[dbus_interface(property)]
// /// MaximumRate property. We will only set it to `1.0` here... fn can_play(&self) -> bool {
// #[dbus_interface(property)] todo!()
// fn maximum_rate(&self) -> zbus::Result<f64> { }
// Ok(1.0)
// } /// CanSeek property
// fn set_maximum_rate(&self, _: f64) -> zbus::Result<()> { #[dbus_interface(property)]
// Ok(()) fn can_seek(&self) -> bool {
// } false
// }
// /// Metadata property. If there is a current kara playing, there must be at
// /// least a `mpris:trackid` value of type `o` which is the object path of /// LoopStatus property
// /// the current kara id. #[dbus_interface(property, name = "LoopStatus")]
// #[dbus_interface(property)] fn loop_status(&self) -> MediaPlayerObjectPath {
// fn metadata( todo!()
// &self, }
// ) -> zbus::Result<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>; #[dbus_interface(property, name = "LoopStatus")]
// fn set_loop_status(&self, loop_status: MediaPlayerObjectPath) {
// /// MinimumRate property. We will only set it to `1.0` here... todo!("handle loop status {loop_status:?}")
// #[dbus_interface(property)] }
// fn minimum_rate(&self) -> zbus::Result<f64> {
// Ok(1.0) #[rustfmt::skip] #[dbus_interface(property, name = "MaximumRate")] fn maximum_rate(&self) -> f64 { 1.0 }
// } #[rustfmt::skip] #[dbus_interface(property, name = "MinimumRate")] fn minimum_rate(&self) -> f64 { 1.0 }
// fn set_minimum_rate(&self, _: f64) -> zbus::Result<()> { #[rustfmt::skip] #[dbus_interface(property, name = "MaximumRate")] fn set_maximum_rate(&self, rate: f64) { log::warn!("ignore rate {rate}") }
// Ok(()) #[rustfmt::skip] #[dbus_interface(property, name = "MinimumRate")] fn set_minimum_rate(&self, rate: f64) { log::warn!("ignore rate {rate}") }
// } #[rustfmt::skip] #[dbus_interface(property, name = "Rate" )] fn rate(&self) -> f64 { 1.0 }
// #[rustfmt::skip] #[dbus_interface(property, name = "Rate" )] fn set_rate(&self, rate: f64) { log::warn!("ignore rate {rate}") }
// /// PlaybackStatus property
// #[dbus_interface(property)] /// Shuffle property
// fn playback_status(&self) -> zbus::Result<MediaPlayerPlaybackStatus>; #[dbus_interface(property, name = "Shuffle")]
// fn shuffle(&self) -> bool {
// /// Position property todo!()
// #[dbus_interface(property)] }
// fn position(&self) -> zbus::Result<TimeMicroSec>; #[dbus_interface(property, name = "Shuffle")]
// fn set_shuffle(&self, shuffle: bool) {
// /// Rate property todo!("handle shuffle {shuffle}")
// #[dbus_interface(property)] }
// fn rate(&self) -> zbus::Result<f64>;
// fn set_rate(&self, value: f64) -> zbus::Result<()>; /// Volume property
// #[dbus_interface(property, name = "Volume")]
// /// Shuffle property fn volume(&self) -> f64 {
// #[dbus_interface(property)] todo!()
// fn shuffle(&self) -> zbus::Result<bool>; }
// fn set_shuffle(&self, value: bool) -> zbus::Result<()>; #[dbus_interface(property, name = "Volume")]
// fn set_volume(&self, volume: f64) {
// /// Volume property todo!("handle volume {volume}")
// #[dbus_interface(property)] }
// fn volume(&self) -> zbus::Result<f64>;
// fn set_volume(&self, value: f64) -> zbus::Result<()>; /// PlaybackStatus property
// } #[dbus_interface(property, name = "PlaybackStatus")]
fn playback_status(&self) -> MediaPlayerPlaybackStatus {
todo!()
}
/// Position property
#[dbus_interface(property, name = "Position")]
fn position(&self) -> TimeMicroSec {
todo!()
}
/// Metadata property. If there is a current kara playing, there must be at
/// least a `mpris:trackid` value of type `o` which is the object path of
/// the current kara id.
#[dbus_interface(property, name = "Metadata")]
fn metadata(&self) -> MediaPlayerMetadata {
todo!()
}
}
use hashbrown::HashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use zbus::zvariant::{ObjectPath as ZObjectPath, OwnedValue as ZOwnedValue, Type as ZType}; use zbus::zvariant::{Dict as ZDict, ObjectPath as ZObjectPath, Type as ZType, Value as ZValue};
/// The loop status. /// The loop status.
#[derive(Debug, Deserialize, Serialize, ZType, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Deserialize, Serialize, ZType, Clone, Copy, PartialEq, Eq)]
...@@ -25,6 +26,10 @@ pub enum MediaPlayerPlaybackStatus { ...@@ -25,6 +26,10 @@ pub enum MediaPlayerPlaybackStatus {
#[zvariant(signature = "x")] #[zvariant(signature = "x")]
pub struct TimeMicroSec(i64); pub struct TimeMicroSec(i64);
#[derive(Debug, Serialize, Deserialize, ZType, Clone, PartialEq, Eq)]
#[zvariant(signature = "a{sv}")]
pub struct MediaPlayerMetadata(HashMap<String, String>);
/// A valid path must be prefiexed by `/org/mpris/MediaPlayer2`. After that we /// A valid path must be prefiexed by `/org/mpris/MediaPlayer2`. After that we
/// have the variant name, then a `/`, then the ascii only value. For example /// have the variant name, then a `/`, then the ascii only value. For example
/// we can have: /// we can have:
...@@ -53,15 +58,15 @@ impl From<i64> for TimeMicroSec { ...@@ -53,15 +58,15 @@ impl From<i64> for TimeMicroSec {
} }
} }
impl From<ZOwnedValue> for TimeMicroSec { impl From<ZValue<'_>> for TimeMicroSec {
fn from(value: ZOwnedValue) -> Self { fn from(value: ZValue<'_>) -> Self {
let value: i64 = value.try_into().unwrap_or_default(); let value: i64 = value.try_into().unwrap_or_default();
Self(value) Self(value)
} }
} }
impl From<ZOwnedValue> for MediaPlayerLoopStatus { impl From<ZValue<'_>> for MediaPlayerLoopStatus {
fn from(value: ZOwnedValue) -> Self { fn from(value: ZValue<'_>) -> Self {
let value: String = value.try_into().unwrap_or_default(); let value: String = value.try_into().unwrap_or_default();
match &value[..] { match &value[..] {
"None" => Self::None, "None" => Self::None,
...@@ -72,8 +77,8 @@ impl From<ZOwnedValue> for MediaPlayerLoopStatus { ...@@ -72,8 +77,8 @@ impl From<ZOwnedValue> for MediaPlayerLoopStatus {
} }
} }
impl From<ZOwnedValue> for MediaPlayerPlaybackStatus { impl From<ZValue<'_>> for MediaPlayerPlaybackStatus {
fn from(value: ZOwnedValue) -> Self { fn from(value: ZValue<'_>) -> Self {
let value: String = value.try_into().unwrap_or_default(); let value: String = value.try_into().unwrap_or_default();
match &value[..] { match &value[..] {
"Paused" => Self::Paused, "Paused" => Self::Paused,
...@@ -84,8 +89,8 @@ impl From<ZOwnedValue> for MediaPlayerPlaybackStatus { ...@@ -84,8 +89,8 @@ impl From<ZOwnedValue> for MediaPlayerPlaybackStatus {
} }
} }
impl<'a> From<ZOwnedValue> for MediaPlayerObjectPath { impl From<ZValue<'_>> for MediaPlayerObjectPath {
fn from(value: ZOwnedValue) -> Self { fn from(value: ZValue<'_>) -> Self {
let value: ZObjectPath = value.try_into().unwrap_or_default(); let value: ZObjectPath = value.try_into().unwrap_or_default();
let value = value.trim_start_matches('/'); let value = value.trim_start_matches('/');
match value.split('/').collect::<Vec<_>>()[..] { match value.split('/').collect::<Vec<_>>()[..] {
...@@ -98,3 +103,61 @@ impl<'a> From<ZOwnedValue> for MediaPlayerObjectPath { ...@@ -98,3 +103,61 @@ impl<'a> From<ZOwnedValue> for MediaPlayerObjectPath {
} }
} }
} }
impl From<MediaPlayerObjectPath> for ZValue<'_> {
fn from(value: MediaPlayerObjectPath) -> Self {
use MediaPlayerObjectPath::*;
ZValue::ObjectPath(
match value {
None => ZObjectPath::try_from("/org/mpris/MediaPlayer2/None"),
NoTrack => ZObjectPath::try_from("/org/mpris/MediaPlayer2/TrackList/NoTrack"),
Id(id) => ZObjectPath::try_from(format!("/org/mpris/MediaPlayer2/Id/{id}")),
}
.expect("incorrect serialization"),
)
}
}
impl From<MediaPlayerLoopStatus> for ZValue<'_> {
fn from(value: MediaPlayerLoopStatus) -> Self {
use MediaPlayerLoopStatus::*;
match value {
None => "None",
Track => "Track",
Playlist => "Playlist",
}
.into()
}
}
impl From<MediaPlayerPlaybackStatus> for ZValue<'_> {
fn from(value: MediaPlayerPlaybackStatus) -> Self {
use MediaPlayerPlaybackStatus::*;
match value {
Paused => "Paused",
Playing => "Playing",
Stopped => "Stopped",
}
.into()
}
}
impl From<TimeMicroSec> for ZValue<'_> {
fn from(TimeMicroSec(value): TimeMicroSec) -> Self {
value.into()
}
}
impl From<MediaPlayerMetadata> for ZValue<'_> {
fn from(MediaPlayerMetadata(value): MediaPlayerMetadata) -> Self {
let mut dict = ZDict::new(
"s".try_into().expect("invalid signature"),
"v".try_into().expect("invalid signature"),
);
for (key, value) in value {
dict.append(key.into(), value.into())
.expect("invalid entry found")
}
todo!()
}
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter