mpris/
lib.rs

1#![warn(missing_docs)]
2#![deny(
3    missing_debug_implementations,
4    missing_copy_implementations,
5    trivial_casts,
6    trivial_numeric_casts,
7    unsafe_code,
8    unreachable_pub,
9    unstable_features,
10    unused_import_braces,
11    unused_qualifications
12)]
13
14//!
15//! # mpris
16//!
17//! `mpris` is an idiomatic library for dealing with [MPRIS2][spec]-compatible media players over D-Bus.
18//!
19//! This would mostly apply to the Linux-ecosystem which is a heavy user of D-Bus.
20//!
21//! ## Getting started
22//!
23//! Some hints on how to use this library:
24//!
25//! 1. Look at the examples under `examples/`.
26//! 2. Look at the [`PlayerFinder`] struct.
27//!
28//! [spec]: https://specifications.freedesktop.org/mpris-spec/latest/
29
30use thiserror::Error;
31
32mod extensions;
33
34#[allow(unreachable_pub)]
35mod generated;
36
37mod event;
38mod find;
39mod metadata;
40mod player;
41mod pooled_connection;
42mod progress;
43mod track_list;
44
45pub use crate::event::{Event, EventError, PlayerEvents};
46pub use crate::find::{FindingError, PlayerFinder, PlayerIter};
47pub use crate::metadata::Metadata;
48pub use crate::metadata::Value as MetadataValue;
49pub use crate::metadata::ValueKind as MetadataValueKind;
50pub use crate::player::Player;
51pub use crate::progress::{Progress, ProgressError, ProgressTick, ProgressTracker};
52pub use crate::track_list::{TrackID, TrackList, TrackListError};
53
54#[derive(Debug, PartialEq, Eq, Copy, Clone)]
55#[allow(missing_docs)]
56/// The [`Player`]'s playback status
57///
58/// See: [MPRIS2 specification about `PlaybackStatus`][playback_status]
59///
60/// [playback_status]: https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html#Enum:Playback_Status
61pub enum PlaybackStatus {
62    /// A track is currently playing.
63    Playing,
64    /// A track is currently paused.
65    Paused,
66    /// There is no track currently playing.
67    Stopped,
68}
69
70#[derive(Debug, PartialEq, Eq, Copy, Clone)]
71/// A [`Player`]'s looping status.
72///
73/// See: [MPRIS2 specification about `Loop_Status`][loop_status]
74///
75/// [loop_status]: https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html#Enum:Loop_Status
76pub enum LoopStatus {
77    /// The playback will stop when there are no more tracks to play
78    None,
79
80    /// The current track will start again from the begining once it has finished playing
81    Track,
82
83    /// The playback loops through a list of tracks
84    Playlist,
85}
86
87/// [`PlaybackStatus`] had an invalid string value.
88#[derive(Debug, Error)]
89#[error("PlaybackStatus must be one of Playing, Paused, Stopped, but was {0}")]
90pub struct InvalidPlaybackStatus(String);
91
92impl ::std::str::FromStr for PlaybackStatus {
93    type Err = InvalidPlaybackStatus;
94
95    fn from_str(string: &str) -> Result<Self, Self::Err> {
96        use crate::PlaybackStatus::*;
97
98        match string {
99            "Playing" => Ok(Playing),
100            "Paused" => Ok(Paused),
101            "Stopped" => Ok(Stopped),
102            other => Err(InvalidPlaybackStatus(other.to_string())),
103        }
104    }
105}
106
107/// [`LoopStatus`] had an invalid string value.
108#[derive(Debug, Error)]
109#[error("LoopStatus must be one of None, Track, Playlist, but was {0}")]
110pub struct InvalidLoopStatus(String);
111
112impl ::std::str::FromStr for LoopStatus {
113    type Err = InvalidLoopStatus;
114
115    fn from_str(string: &str) -> Result<Self, Self::Err> {
116        match string {
117            "None" => Ok(LoopStatus::None),
118            "Track" => Ok(LoopStatus::Track),
119            "Playlist" => Ok(LoopStatus::Playlist),
120            other => Err(InvalidLoopStatus(other.to_string())),
121        }
122    }
123}
124
125impl LoopStatus {
126    fn dbus_value(self) -> String {
127        String::from(match self {
128            LoopStatus::None => "None",
129            LoopStatus::Track => "Track",
130            LoopStatus::Playlist => "Playlist",
131        })
132    }
133}
134
135/// Something went wrong when communicating with the D-Bus. This could either be an underlying
136/// D-Bus library problem, or that the other side did not conform to the expected protocols.
137#[derive(Debug, Error)]
138pub enum DBusError {
139    /// An error occurred while talking to the D-Bus.
140    #[error("D-Bus call failed: {0}")]
141    TransportError(#[from] dbus::Error),
142
143    /// Failed to parse an enum from a string value received from the [`Player`]. This means that the
144    /// [`Player`] replied with unexpected data.
145    #[error("Failed to parse enum value: {0}")]
146    EnumParseError(String),
147
148    /// A D-Bus method call did not pass arguments of the correct type. This means that the [`Player`]
149    /// replied with unexpected data.
150    #[error("D-Bus call failed: {0}")]
151    TypeMismatchError(#[from] dbus::arg::TypeMismatchError),
152
153    /// Some other unexpected error occurred.
154    #[error("Unexpected error: {0}")]
155    Miscellaneous(String),
156}
157
158impl From<InvalidPlaybackStatus> for DBusError {
159    fn from(error: InvalidPlaybackStatus) -> Self {
160        DBusError::EnumParseError(error.to_string())
161    }
162}
163
164impl From<InvalidLoopStatus> for DBusError {
165    fn from(error: InvalidLoopStatus) -> Self {
166        DBusError::EnumParseError(error.to_string())
167    }
168}