doobs_mpris/
enumerator.rs1use futures_util::Stream;
4use futures_util::stream::{self, StreamExt};
5use zbus::Connection;
6use zbus::fdo::DBusProxy;
7use zbus::names::OwnedBusName;
8
9use crate::binding::MPRIS_BUS_NAME_PREFIX;
10
11#[derive(Clone, Debug)]
13pub enum EnumeratorEvent {
14 Add(OwnedBusName),
16 Remove(OwnedBusName),
18}
19
20pub struct Enumerator {
25 proxy: DBusProxy<'static>,
26}
27
28impl Enumerator {
29 pub async fn new(connection: &Connection) -> zbus::Result<Self> {
30 Ok(Self {
31 proxy: DBusProxy::builder(connection)
32 .path("/org/freedesktop/DBus")?
33 .build()
34 .await?,
35 })
36 }
37
38 pub async fn receive_changes(
40 &self,
41 ) -> zbus::Result<impl Stream<Item = zbus::Result<EnumeratorEvent>> + Unpin + use<>> {
42 let stream = self.proxy.receive_name_owner_changed().await?;
43 Ok(stream
44 .filter_map(|signal| {
45 Box::pin(async move {
46 let args = match signal.args() {
47 Ok(args) => args,
48 Err(err) => {
49 return Some(stream::iter(Some(Err(err)).into_iter().chain(None)));
50 }
51 };
52 if args.name().starts_with(MPRIS_BUS_NAME_PREFIX) {
53 let remove = args
54 .old_owner
55 .as_ref()
56 .map(|_| Ok(EnumeratorEvent::Remove(args.name().to_owned().into())));
57 let add = args
58 .new_owner
59 .as_ref()
60 .map(|_| Ok(EnumeratorEvent::Add(args.name().to_owned().into())));
61 Some(stream::iter(remove.into_iter().chain(add)))
62 } else {
63 None
64 }
65 })
66 })
67 .flatten())
68 }
69
70 pub async fn players(&self) -> zbus::Result<Vec<OwnedBusName>> {
72 let mut players = self.proxy.list_names().await?;
73 players.retain(|name| name.starts_with(MPRIS_BUS_NAME_PREFIX));
74 Ok(players)
75 }
76}