use crate::{Player, Result};
use dbus::{
arg::PropMap,
nonblock::{Proxy, SyncConnection},
};
use dbus_tokio::connection;
use std::{sync::Arc, time::Duration};
const MPRIS_PREFIX: &str = "org.mpris.MediaPlayer2.";
pub async fn validate(player_name: &str, conn: &SyncConnection) -> Result<bool> {
Ok(get_all_names(&conn)
.await?
.contains(&player_name.to_string()))
}
async fn get_all_names(conn: &SyncConnection) -> Result<Vec<String>> {
let proxy = Proxy::new("org.freedesktop.DBus", "/", Duration::from_secs(1), conn);
let (services,): (Vec<String>,) = proxy
.method_call("org.freedesktop.DBus", "ListNames", ())
.await?;
let active_players: Vec<String> = services
.into_iter()
.filter_map(|name| {
name.strip_prefix(&MPRIS_PREFIX)
.map_or_else(|| None, |s| Some(s.to_string()))
})
.collect();
Ok(active_players)
}
pub fn get_connection() -> Arc<SyncConnection> {
let (resource, conn) = connection::new_session_sync().unwrap();
tokio::spawn(async {
let err = resource.await;
panic!("Lost connection to D-Bus: {}", err);
});
conn
}
pub async fn get_all_players(conn: &SyncConnection) -> Result<Vec<Player<'_>>> {
let mut players: Vec<Player<'_>> = Vec::new();
for name in get_all_names(&conn).await? {
match Player::try_new(name, &conn).await {
Ok(player) => players.push(player),
Err(_) => continue,
};
}
Ok(players)
}
pub fn prop_cast<'a, T>(map: &'a PropMap, key: &str) -> Option<&'a T>
where
T: 'static,
{
map.get(key).and_then(|v| v.0.as_any().downcast_ref())
}