Skip to main content

doobs_mpris/binding/
track_list.rs

1// SPDX-License-Identifier: MPL-2.0
2use zbus::interface;
3use zbus::object_server::SignalEmitter;
4
5use crate::types::{Metadata, TrackId};
6
7/// Implement this trait to provide the main functionality for a [TrackList].
8#[allow(unused_variables)]
9pub trait TrackListProvider {
10    /// Gets all the metadata available for a set of tracks.
11    ///
12    /// Each set of metadata must have a `mpris:trackid` entry at the very least, which contains a string that uniquely identifies this track within the scope of the tracklist.
13    fn get_tracks_metadata(
14        &self,
15        track_ids: Vec<TrackId>,
16    ) -> impl Future<Output = zbus::fdo::Result<Vec<Metadata>>> + Send;
17
18    /// Adds a URI in the TrackList.
19    ///
20    /// If the *CanEditTracks* property is false, this has no effect.
21    ///
22    /// Note: Clients should not assume that the track has been added at the time when this method returns.
23    /// They should wait for a *TrackAdded* (or *TrackListReplaced*) signal.
24    fn add_track(
25        &self,
26        uri: &str,
27        after_track: TrackId,
28        set_as_current: bool,
29    ) -> impl Future<Output = zbus::fdo::Result<()>> + Send;
30
31    /// Removes an item from the TrackList.
32    ///
33    /// If the track is not part of this tracklist, this has no effect.
34    ///
35    /// If the *CanEditTracks* property is false, this has no effect.
36    ///
37    /// Note: Clients should not assume that the track has been removed at the time when this method returns.
38    /// They should wait for a *TrackRemoved* (or *TrackListReplaced*) signal.
39    fn remove_track(&self, track_id: TrackId)
40    -> impl Future<Output = zbus::fdo::Result<()>> + Send;
41
42    /// Skip to the specified TrackId.
43    ///
44    /// If the track is not part of this tracklist, this has no effect.
45    ///
46    /// If this object is not `/org/mpris/MediaPlayer2`, the current TrackList's tracks should be replaced with the contents of this TrackList, and the *TrackListReplaced* signal should be fired from `/org/mpris/MediaPlayer2`.
47    fn go_to(&self, track_id: TrackId) -> impl Future<Output = zbus::fdo::Result<()>> + Send;
48
49    /// An array which contains the identifier of each track in the tracklist, in order.
50    ///
51    /// The *org.freedesktop.DBus.Properties.PropertiesChanged* signal is emitted every time this property changes, but the signal message does not contain the new value.
52    /// Client implementations should rather rely on the *TrackAdded*, *TrackRemoved* and *TrackListReplaced* signals to keep their representation of the tracklist up to date.
53    fn tracks(&self) -> impl Future<Output = zbus::fdo::Result<Vec<TrackId>>> + Send;
54
55    /// Whether the client can edit the track list.
56    ///
57    /// If `false`, calling *AddTrack* or *RemoveTrack* will have no effect, and may raise a [zbus::fdo::Error::NotSupported] error.
58    fn can_edit_tracks(&self) -> impl Future<Output = zbus::fdo::Result<bool>> + Send;
59}
60
61/// Provides access to a short list of tracks which were recently played or will be played shortly.
62///
63/// This is intended to provide context to the currently-playing track, rather than giving complete access to the media player's playlist.
64///
65/// It delegates the D-Bus calls to its provider.
66pub struct TrackList<P>(P);
67
68impl<P> TrackList<P>
69where
70    P: TrackListProvider + Send + Sync + 'static,
71{
72    /// Creates a new MPRIS player that delegates to the given [TrackListProvider].
73    pub fn new(provider: P) -> Self {
74        Self(provider)
75    }
76
77    /// The reference to the underlying [TrackListProvider].
78    pub fn inner(&self) -> &P {
79        &self.0
80    }
81
82    /// The mutable reference to the underlying [TrackListProvider].
83    pub fn inner_mut(&mut self) -> &mut P {
84        &mut self.0
85    }
86}
87
88#[interface(
89    interface = "org.mpris.MediaPlayer2.TrackList",
90    proxy(default_path = "/org/mpris/MediaPlayer2")
91)]
92impl<P> TrackList<P>
93where
94    P: TrackListProvider + Send + Sync + 'static,
95{
96    /// GetTracksMetadata method
97    async fn get_tracks_metadata(
98        &self,
99        track_ids: Vec<TrackId>,
100    ) -> zbus::fdo::Result<Vec<Metadata>> {
101        self.0.get_tracks_metadata(track_ids).await
102    }
103
104    /// AddTrack method
105    async fn add_track(
106        &self,
107        uri: &str,
108        after_track: TrackId,
109        set_as_current: bool,
110    ) -> zbus::fdo::Result<()> {
111        self.0.add_track(uri, after_track, set_as_current).await
112    }
113
114    /// RemoveTrack method
115    async fn remove_track(&self, track_id: TrackId) -> zbus::fdo::Result<()> {
116        self.0.remove_track(track_id).await
117    }
118
119    /// GoTo method
120    async fn go_to(&self, track_id: TrackId) -> zbus::fdo::Result<()> {
121        self.0.go_to(track_id).await
122    }
123
124    /// TrackListReplaced signal
125    ///
126    /// Indicates that the entire tracklist has been replaced.
127    ///
128    /// It is left up to the implementation to decide when a change to the track list is invasive enough that this signal should be emitted instead of a series of *TrackAdded* and *TrackRemoved* signals.
129    ///
130    /// `/org/mpris/MediaPlayer2/TrackList/NoTrack` indicates that there is no current track.
131    #[zbus(signal)]
132    async fn track_list_replaced(
133        emitter: &SignalEmitter<'_>,
134        tracks: Vec<TrackId>,
135        current_track: TrackId,
136    ) -> zbus::Result<()>;
137
138    /// TrackAdded signal
139    ///
140    /// Indicates that a track has been added to the track list.
141    #[zbus(signal)]
142    async fn track_added(
143        emitter: &SignalEmitter<'_>,
144        metadata: Metadata,
145        after_track: TrackId,
146    ) -> zbus::Result<()>;
147
148    /// TrackRemoved signal
149    ///
150    /// Indicates that a track has been removed from the track list.
151    #[zbus(signal)]
152    async fn track_removed(emitter: &SignalEmitter<'_>, track: TrackId) -> zbus::Result<()>;
153
154    /// TrackMetadataChanged signal
155    ///
156    /// Indicates that the metadata of a track in the tracklist has changed.
157    ///
158    /// This may indicate that a track has been replaced, in which case the `mpris:trackid` metadata entry is different from the `track` argument.
159    #[zbus(signal)]
160    async fn track_metadata_changed(
161        emitter: &SignalEmitter<'_>,
162        track: TrackId,
163        metadata: Metadata,
164    ) -> zbus::Result<()>;
165
166    /// Tracks property
167    #[zbus(property)]
168    async fn tracks(&self) -> zbus::fdo::Result<Vec<TrackId>> {
169        self.0.tracks().await
170    }
171
172    /// CanEditTracks property
173    #[zbus(property)]
174    async fn can_edit_tracks(&self) -> zbus::fdo::Result<bool> {
175        self.0.can_edit_tracks().await
176    }
177}