mpris: Add helper for enumerating players, watching for new players (#12)
This commit is contained in:
parent
8b9767f6ce
commit
c81f428ace
6 changed files with 93 additions and 12 deletions
|
|
@ -13,6 +13,7 @@ members = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
futures-util = "0.3.30"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
time = { version = "0.3", features = ["parsing"] }
|
time = { version = "0.3", features = ["parsing"] }
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ edition = "2021"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
futures-util.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
time.workspace = true
|
time.workspace = true
|
||||||
|
|
|
||||||
16
mpris2/examples/enumerate.rs
Normal file
16
mpris2/examples/enumerate.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use futures_util::stream::StreamExt;
|
||||||
|
use mpris2_zbus::enumerator::Enumerator;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> zbus::Result<()> {
|
||||||
|
let connection = zbus::Connection::session().await?;
|
||||||
|
let enumerator = Enumerator::new(&connection).await?;
|
||||||
|
let mut stream = enumerator.receive_changes().await?;
|
||||||
|
println!("players: {:?}", enumerator.players().await?);
|
||||||
|
while let Some(event) = stream.next().await {
|
||||||
|
println!("change: {:?}", event?);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
71
mpris2/src/enumerator.rs
Normal file
71
mpris2/src/enumerator.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use futures_util::{
|
||||||
|
stream::{self, StreamExt},
|
||||||
|
Stream,
|
||||||
|
};
|
||||||
|
use zbus::{fdo::DBusProxy, names::OwnedBusName, Connection};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Event {
|
||||||
|
Remove(OwnedBusName),
|
||||||
|
Add(OwnedBusName),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to list mpris players on DBus bus, and watch for addition/removal.
|
||||||
|
///
|
||||||
|
/// Uses `org.freedesktop.DBus` to watch for clients that claim names starting with
|
||||||
|
/// `org.mpris.MediaPlayer2.`
|
||||||
|
pub struct Enumerator {
|
||||||
|
proxy: DBusProxy<'static>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Enumerator {
|
||||||
|
pub async fn new(connection: &Connection) -> zbus::Result<Self> {
|
||||||
|
Ok(Self {
|
||||||
|
proxy: DBusProxy::builder(connection)
|
||||||
|
.path("/org/freedesktop/DBus")?
|
||||||
|
.build()
|
||||||
|
.await?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a stream that is signalled when an mpris client is added or removed
|
||||||
|
pub async fn receive_changes(
|
||||||
|
&self,
|
||||||
|
) -> zbus::Result<impl Stream<Item = zbus::Result<Event>> + Unpin> {
|
||||||
|
let stream = self.proxy.receive_name_owner_changed().await?;
|
||||||
|
Ok(stream
|
||||||
|
.filter_map(|signal| {
|
||||||
|
Box::pin(async move {
|
||||||
|
let args = match signal.args() {
|
||||||
|
Ok(args) => args,
|
||||||
|
Err(err) => {
|
||||||
|
return Some(stream::iter(Some(Err(err)).into_iter().chain(None)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if args.name().contains("org.mpris.MediaPlayer2.") {
|
||||||
|
let remove = args
|
||||||
|
.old_owner
|
||||||
|
.as_ref()
|
||||||
|
.map(|_| Ok(Event::Remove(args.name().to_owned().into())));
|
||||||
|
let add = args
|
||||||
|
.new_owner
|
||||||
|
.as_ref()
|
||||||
|
.map(|_| Ok(Event::Add(args.name().to_owned().into())));
|
||||||
|
Some(stream::iter(remove.into_iter().chain(add)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.flatten())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get names of all mpris players currently on the bus
|
||||||
|
pub async fn players(&self) -> zbus::Result<Vec<OwnedBusName>> {
|
||||||
|
let mut players = self.proxy.list_names().await?;
|
||||||
|
players.retain(|name| name.starts_with("org.mpris.MediaPlayer2."));
|
||||||
|
Ok(players)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
pub mod bindings;
|
pub mod bindings;
|
||||||
|
pub mod enumerator;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod media_player;
|
pub mod media_player;
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@ use crate::{
|
||||||
media_player::MediaPlayer2Proxy, player::PlayerProxy, playlist::PlaylistsProxy,
|
media_player::MediaPlayer2Proxy, player::PlayerProxy, playlist::PlaylistsProxy,
|
||||||
track_list::TrackListProxy,
|
track_list::TrackListProxy,
|
||||||
},
|
},
|
||||||
|
enumerator::Enumerator,
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
player::Player,
|
player::Player,
|
||||||
playlists::Playlists,
|
playlists::Playlists,
|
||||||
track_list::TrackList,
|
track_list::TrackList,
|
||||||
};
|
};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use zbus::{fdo::DBusProxy, names::OwnedBusName, Connection};
|
use zbus::{names::OwnedBusName, Connection};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MediaPlayer {
|
pub struct MediaPlayer {
|
||||||
|
|
@ -30,17 +31,7 @@ impl MediaPlayer {
|
||||||
|
|
||||||
/// Gets the names of all the MPRIS players that are available on the current session.
|
/// Gets the names of all the MPRIS players that are available on the current session.
|
||||||
pub async fn available_players(connection: &Connection) -> Result<Vec<OwnedBusName>> {
|
pub async fn available_players(connection: &Connection) -> Result<Vec<OwnedBusName>> {
|
||||||
let dbus = DBusProxy::builder(connection)
|
Ok(Enumerator::new(connection).await?.players().await?)
|
||||||
.path("/org/freedesktop/DBus")?
|
|
||||||
.build()
|
|
||||||
.await?;
|
|
||||||
let mut players = Vec::new();
|
|
||||||
for name in dbus.list_names().await? {
|
|
||||||
if name.starts_with("org.mpris.MediaPlayer2.") {
|
|
||||||
players.push(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(players)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a new instance of all the MPRIS players that are available on the current session.
|
/// Gets a new instance of all the MPRIS players that are available on the current session.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue