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
use super::INTERFACE;
use crate::{Player, Result};
use dbus::nonblock::stdintf::org_freedesktop_dbus::Properties;
use dbus::{
    arg::{Append, Arg, Get, PropMap},
    strings::Path,
};
use std::time::Duration;

/// Retrieves track metadata from a `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(player: &mut Player<'_>) -> Result<PropMap> {
    let proxy = player.get_proxy()?;
    let metadata: PropMap = proxy.get(INTERFACE, "Metadata").await?;
    Ok(metadata)
}

/// 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>(player: &mut Player<'_>, property: &str) -> Result<T>
where
    T: for<'a> Get<'a> + 'static,
{
    let proxy = player.get_proxy()?;
    let value: T = proxy.get(INTERFACE, property).await?;

    Ok(value)
}

/// 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>(player: &mut Player<'_>, property: &str, value: T) -> Result<()>
where
    T: Arg + Append,
{
    let proxy = player.get_proxy()?;
    proxy.set(INTERFACE, property, value).await?;

    Ok(())
}

/// Seeks the position of the active track.
pub async fn seek(player: &mut Player<'_>, offset: Duration) -> Result<()> {
    let proxy = player.get_proxy()?;
    let offset = offset.as_micros() as i64;
    proxy.method_call(INTERFACE, "Seek", (offset,)).await?;

    Ok(())
}

/// Same as `seek`, but in reverse.
pub async fn seek_reverse(player: &mut Player<'_>, offset: Duration) -> Result<()> {
    let proxy = player.get_proxy()?;
    let offset = offset.as_micros() as i64;
    proxy.method_call(INTERFACE, "Seek", (-offset,)).await?;

    Ok(())
}

/// Sets the position of the current track, by microseconds.
pub async fn set_position(player: &mut Player<'_>, position: i64) -> Result<()> {
    let mut player_clone = player.clone();

    let proxy = player.get_proxy()?;
    let metadata = get_metadata(&mut player_clone).await?;
    let track_id: &Path = crate::prop_cast(&metadata, "mpris:trackid").unwrap();

    proxy
        .method_call(INTERFACE, "SetPosition", (track_id, position))
        .await?;

    Ok(())
}

/// Opens a track by its URI.
///
/// # Errors
/// May return an `Err` variant if the provided URI is invalid.
pub async fn open_uri(player: &mut Player<'_>, uri: &str) -> Result<()> {
    let proxy = player.get_proxy()?;
    proxy.method_call(INTERFACE, "OpenUri", (uri,)).await?;

    Ok(())
}