1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use crate::{methods, util, Result};
use dbus::{
    arg::{Append, Arg, Get, PropMap},
    nonblock::{Proxy, SyncConnection},
};
use std::{fmt::Display, time::Duration};

/// A struct used to control an MPRIS player.
#[derive(Clone)]
pub struct Player<'a> {
    pub name: String,
    conn: &'a SyncConnection,
}

impl<'a> Player<'a> {
    /// Tries to create a new `Player` instance from a given name.
    ///
    /// # Errors
    /// Returns an `Err` if the provided player is invalid.
    pub async fn try_new<T>(name: T, conn: &'a SyncConnection) -> Result<Player<'a>>
    where
        T: AsRef<str> + Display,
    {
        if !util::validate(name.as_ref(), conn).await? {
            return Err(Box::from("The provided player was invalid."));
        }

        let player = Player {
            name: name.to_string(),
            conn,
        };
        Ok(player)
    }

    #[doc(hidden)]
    pub fn get_proxy(&mut self) -> Result<Proxy<&'a SyncConnection>> {
        let proxy = Proxy::new(
            format!("org.mpris.MediaPlayer2.{}", self.name),
            "/org/mpris/MediaPlayer2",
            Duration::from_millis(5000),
            self.conn,
        );

        Ok(proxy)
    }

    /// Skips to the next track
    ///
    /// # Errors
    /// Will `Err` if the `Player` has closed.
    pub async fn next(&mut self) -> Result<()> {
        Ok(methods::next(self).await?)
    }

    /// Skips to the previous track
    ///
    /// # Errors
    /// Will `Err` if the `Player` has closed.
    pub async fn previous(&mut self) -> Result<()> {
        Ok(methods::previous(self).await?)
    }

    /// Pauses the current track
    ///
    /// # Errors
    /// Will `Err` if the `Player` has closed.
    pub async fn pause(&mut self) -> Result<()> {
        Ok(methods::pause(self).await?)
    }

    /// Starts or resumes the current track
    ///
    /// # Errors
    /// Will `Err` if the `Player` has closed.
    pub async fn play(&mut self) -> Result<()> {
        Ok(methods::play(self).await?)
    }

    /// Resumes/starts or pauses the current track
    ///
    /// # Errors
    /// Will `Err` if the `Player` has closed.
    pub async fn play_pause(&mut self) -> Result<()> {
        Ok(methods::play_pause(self).await?)
    }

    /// Stops playback
    ///
    /// # Errors
    /// Will `Err` if the `Player` has closed.
    pub async fn stop(&mut self) -> Result<()> {
        Ok(methods::stop(self).await?)
    }

    /// Retrieves track metadata from the `Player`.
    /// The [`prop_cast`](crate::prop_cast) function may be used
    /// to get specific values out of the resulting metadata.
    ///
    /// # Errors
    /// May `Err` if there is a failure in getting the metadata.
    pub async fn get_metadata(&mut self) -> Result<PropMap> {
        Ok(methods::get_metadata(self).await?)
    }

    /// Retrieves the value of an MPRIS property.
    /// Available properties can be found [here].
    ///
    /// [here]: https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html#Property:PlaybackStatus
    ///
    /// # Errors
    /// May return an `Err` variant if:
    /// * An invalid type was provided for the property
    /// * An invalid property was provided
    pub async fn get_property<T>(&mut self, property: &str) -> Result<T>
    where
        T: for<'c> Get<'c> + 'static,
    {
        Ok(methods::get_property(self, property).await?)
    }

    /// Sets the value of a writable MPRIS property.
    /// Available properties can be found [here].
    ///
    /// [here]: https://specifications.freedesktop.org/mpris-spec/latest/Player_Interface.html#Property:PlaybackStatus
    ///
    /// # Errors
    /// May return an `Err` variant if:
    /// * An invalid type was provided for the property
    /// * An invalid property was provided
    pub async fn set_property<T>(&mut self, property: &str, value: T) -> Result<()>
    where
        T: Arg + Append,
    {
        Ok(methods::set_property(self, property, value).await?)
    }

    /// Seeks the position of the active track.
    pub async fn seek(&mut self, offset: Duration) -> Result<()> {
        Ok(methods::seek(self, offset).await?)
    }

    /// Same as `seek`, but in reverse.
    pub async fn seek_reverse(&mut self, offset: Duration) -> Result<()> {
        Ok(methods::seek_reverse(self, offset).await?)
    }

    /// Sets the position of the current track, by microseconds.
    pub async fn set_position(&mut self, position: i64) -> Result<()> {
        Ok(methods::set_position(self, position).await?)
    }

    /// Opens a track by its URI.
    ///
    /// # Errors
    /// May return an `Err` variant if the provided URI is invalid.
    pub async fn open_uri(&mut self, uri: &str) -> Result<()> {
        Ok(methods::open_uri(self, uri).await?)
    }
}