use log::info; use std::sync::Arc; use dbus::{ channel::{MatchingReceiver, Sender}, message::MatchRule, nonblock::SyncConnection, Path, }; use dbus_crossroads::Crossroads; #[derive(Clone)] pub struct Endpoint { connection: Arc, implementation: T, } impl Endpoint { pub fn new(connection: Arc, implementation: T) -> Self { Self { connection, implementation, } } pub async fn register_object(&self, path: &str, register_fn: F) where F: Fn(&mut Crossroads) -> R, R: IntoIterator>, { let dbus_path = String::from(path); // Enable async support for the crossroads instance. // (Currently irrelevant since dbus generates sync code) let mut cr = Crossroads::new(); cr.set_async_support(Some(( self.connection.clone(), Box::new(|x| { tokio::spawn(x); }), ))); // Register the daemon as a D-Bus object with multiple interfaces let tokens: Vec<_> = register_fn(&mut cr).into_iter().collect(); cr.insert(dbus_path, &tokens, self.implementation.clone()); // Start receiving messages. self.connection.start_receive( MatchRule::new_method_call(), Box::new(move |msg, conn| cr.handle_message(msg, conn).is_ok()), ); info!(target: "dbus", "Registered endpoint at {} with {} interfaces", path, tokens.len()); } pub fn send_signal(&self, path: &str, signal: S) -> Result where S: dbus::message::SignalArgs + dbus::arg::AppendAll, { let message = signal.to_emit_message(&Path::new(path).unwrap()); self.connection.send(message) } }