mpris_server/
playlist.rs

1use serde::Serialize;
2use zbus::zvariant::{ObjectPath, Type, Value};
3
4use crate::{PlaylistId, Uri};
5
6/// A data structure describing a playlist.
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Type)]
8pub struct Playlist {
9    /// A unique identifier for the playlist.
10    ///
11    /// This should remain the same if the playlist is renamed.
12    pub id: PlaylistId,
13    /// The name of the playlist, typically given by the user.
14    pub name: String,
15    /// The URI of an (optional) icon.
16    pub icon: Uri,
17}
18
19impl From<Playlist> for Value<'_> {
20    fn from(p: Playlist) -> Self {
21        Value::from((p.id, p.name, p.icon))
22    }
23}
24
25/// A data structure describing a playlist, or nothing.
26///
27/// <details><summary>Rationale</summary>
28///
29/// D-Bus does not (at the time of writing) support a MAYBE type, so we are
30/// forced to invent our own.
31///
32/// </details>
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Type)]
34#[doc(alias = "Maybe_Playlist")]
35pub(crate) struct MaybePlaylist {
36    /// Whether this structure refers to a valid playlist.
37    valid: bool,
38    /// The playlist, providing `valid` is true, otherwise undefined.
39    ///
40    /// When constructing this type, it should be noted that the playlist ID
41    /// must be a valid object path, or D-Bus implementations may reject it.
42    /// This is true even when Valid is false. It is suggested that "/" is
43    /// used as the playlist ID in this case.
44    playlist: Playlist,
45}
46
47impl From<Option<Playlist>> for MaybePlaylist {
48    fn from(playlist: Option<Playlist>) -> Self {
49        match playlist {
50            Some(playlist) => Self {
51                valid: true,
52                playlist,
53            },
54            None => Self {
55                valid: false,
56                playlist: Playlist {
57                    id: ObjectPath::from_static_str_unchecked("/").into(),
58                    name: String::new(),
59                    icon: Uri::new(),
60                },
61            },
62        }
63    }
64}
65
66impl From<MaybePlaylist> for Value<'_> {
67    fn from(mp: MaybePlaylist) -> Self {
68        Value::from((mp.valid, mp.playlist))
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn valid_signatures() {
78        assert_eq!(Playlist::SIGNATURE, "(oss)");
79        assert_eq!(MaybePlaylist::SIGNATURE, "(b(oss))");
80    }
81}