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}