Implement some contact and request interfaces
Empathy still isn't happy, but it's going to take some debugging to work out why. I suspect it requires one of the "optional" interfaces in practice... but which one?
This commit is contained in:
@@ -2,7 +2,7 @@ use crate::telepathy;
|
|||||||
use dbus::blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection};
|
use dbus::blocking::{stdintf::org_freedesktop_dbus::RequestNameReply, LocalConnection};
|
||||||
use dbus::channel::Sender;
|
use dbus::channel::Sender;
|
||||||
use dbus::message::SignalArgs;
|
use dbus::message::SignalArgs;
|
||||||
use dbus::tree;
|
use dbus::{arg, tree};
|
||||||
|
|
||||||
use dc::config::Config;
|
use dc::config::Config;
|
||||||
use dc::context::Context;
|
use dc::context::Context;
|
||||||
@@ -68,7 +68,8 @@ impl Connection {
|
|||||||
let msgq = Arc::new(Mutex::new(VecDeque::<dbus::Message>::new()));
|
let msgq = Arc::new(Mutex::new(VecDeque::<dbus::Message>::new()));
|
||||||
|
|
||||||
let id2 = id.clone();
|
let id2 = id.clone();
|
||||||
let msgq2 = msgq.clone();
|
// Use this if we need to send messages in response to DC events:
|
||||||
|
// let msgq2 = msgq.clone();
|
||||||
let f = move |_c: &Context, e: Event| {
|
let f = move |_c: &Context, e: Event| {
|
||||||
match e {
|
match e {
|
||||||
Event::Info(msg) => println!("Connection<{}>: INFO: {}", id2, msg),
|
Event::Info(msg) => println!("Connection<{}>: INFO: {}", id2, msg),
|
||||||
@@ -144,11 +145,26 @@ impl Connection {
|
|||||||
let c_rc = std::rc::Rc::new(self);
|
let c_rc = std::rc::Rc::new(self);
|
||||||
|
|
||||||
let f = tree::Factory::new_fn::<()>();
|
let f = tree::Factory::new_fn::<()>();
|
||||||
let iface = telepathy::connection_server(&f, (), move |_| c_rc.clone());
|
|
||||||
|
|
||||||
let mut tree = f.tree(());
|
let mut tree = f.tree(());
|
||||||
tree = tree.add(f.object_path(path, ()).introspectable().add(iface));
|
|
||||||
|
|
||||||
|
let c_rc1 = c_rc.clone();
|
||||||
|
let conn_iface = telepathy::connection_server(&f, (), move |_| c_rc1.clone());
|
||||||
|
|
||||||
|
let c_rc2 = c_rc.clone();
|
||||||
|
let contacts_iface =
|
||||||
|
telepathy::connection_interface_contacts_server(&f, (), move |_| c_rc2.clone());
|
||||||
|
|
||||||
|
let c_rc3 = c_rc.clone();
|
||||||
|
let requests_iface =
|
||||||
|
telepathy::connection_interface_requests_server(&f, (), move |_| c_rc3.clone());
|
||||||
|
|
||||||
|
tree = tree.add(
|
||||||
|
f.object_path(path.clone(), ())
|
||||||
|
.introspectable()
|
||||||
|
.add(conn_iface)
|
||||||
|
.add(contacts_iface)
|
||||||
|
.add(requests_iface),
|
||||||
|
);
|
||||||
tree = tree.add(f.object_path("/", ()).introspectable());
|
tree = tree.add(f.object_path("/", ()).introspectable());
|
||||||
|
|
||||||
// Setup DBus connection
|
// Setup DBus connection
|
||||||
@@ -219,6 +235,18 @@ impl AsRef<dyn telepathy::Connection + 'static> for std::rc::Rc<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<dyn telepathy::ConnectionInterfaceContacts + 'static> for std::rc::Rc<Connection> {
|
||||||
|
fn as_ref(&self) -> &(dyn telepathy::ConnectionInterfaceContacts + 'static) {
|
||||||
|
&**self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<dyn telepathy::ConnectionInterfaceRequests + 'static> for std::rc::Rc<Connection> {
|
||||||
|
fn as_ref(&self) -> &(dyn telepathy::ConnectionInterfaceRequests + 'static) {
|
||||||
|
&**self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl telepathy::Connection for Connection {
|
impl telepathy::Connection for Connection {
|
||||||
// In connect(), we start the threads that drive the deltachat context
|
// In connect(), we start the threads that drive the deltachat context
|
||||||
fn connect(&self) -> Result<(), tree::MethodErr> {
|
fn connect(&self) -> Result<(), tree::MethodErr> {
|
||||||
@@ -443,6 +471,128 @@ impl telepathy::Connection for Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl telepathy::ConnectionInterfaceContacts for Connection {
|
||||||
|
fn get_contact_attributes(
|
||||||
|
&self,
|
||||||
|
handles: Vec<u32>,
|
||||||
|
interfaces: Vec<&str>,
|
||||||
|
hold: bool,
|
||||||
|
) -> Result<HashMap<u32, HashMap<String, super::Variant>>, tree::MethodErr> {
|
||||||
|
println!(
|
||||||
|
"Connection<{}>::get_contact_attributes({:?}, {:?}, {})",
|
||||||
|
self.id, handles, interfaces, hold
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut out = HashMap::<u32, HashMap<String, super::Variant>>::new();
|
||||||
|
for id in handles.iter() {
|
||||||
|
// FIXME: work out how to use get_all
|
||||||
|
let contact = match dc::contact::Contact::get_by_id(&self.ctx.read().unwrap(), *id) {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(_e) => continue, // FIXME: Ignore the error. Whatevs.
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut props = HashMap::<String, super::Variant>::new();
|
||||||
|
// This is mandatory
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Connection/contact-id".to_string(),
|
||||||
|
arg::Variant(Box::new(contact.get_display_name().to_string())),
|
||||||
|
);
|
||||||
|
|
||||||
|
// We don't advertise this interface but empathy is being weird.
|
||||||
|
// The empty string means "no avatar"
|
||||||
|
props.insert(
|
||||||
|
"org.freedesktop.Telepathy.Connection.Interface.Avatars/token".to_string(),
|
||||||
|
arg::Variant(Box::new("".to_string())),
|
||||||
|
);
|
||||||
|
|
||||||
|
out.insert(*id, props);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_contact_by_id(
|
||||||
|
&self,
|
||||||
|
identifier: &str,
|
||||||
|
interfaces: Vec<&str>,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
u32,
|
||||||
|
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
|
||||||
|
),
|
||||||
|
tree::MethodErr,
|
||||||
|
> {
|
||||||
|
println!(
|
||||||
|
"Connection<{}>::get_contact_by_id({}, {:?})",
|
||||||
|
self.id, identifier, interfaces
|
||||||
|
);
|
||||||
|
Err(tree::MethodErr::no_arg()) // FIXME: should be NotImplemented?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contact_attribute_interfaces(&self) -> Result<Vec<String>, tree::MethodErr> {
|
||||||
|
println!("Connection<{}>::contact_attribute_interfaces()", self.id);
|
||||||
|
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl telepathy::ConnectionInterfaceRequests for Connection {
|
||||||
|
fn create_channel(
|
||||||
|
&self,
|
||||||
|
request: ::std::collections::HashMap<&str, arg::Variant<Box<dyn arg::RefArg>>>,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
dbus::Path<'static>,
|
||||||
|
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
|
||||||
|
),
|
||||||
|
tree::MethodErr,
|
||||||
|
> {
|
||||||
|
println!("Connection<{}>::create_channel({:?})", self.id, request);
|
||||||
|
Err(tree::MethodErr::no_arg()) // FIXME: should be NotImplemented?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ensure_channel(
|
||||||
|
&self,
|
||||||
|
request: ::std::collections::HashMap<&str, arg::Variant<Box<dyn arg::RefArg>>>,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
bool,
|
||||||
|
dbus::Path<'static>,
|
||||||
|
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
|
||||||
|
),
|
||||||
|
tree::MethodErr,
|
||||||
|
> {
|
||||||
|
println!("Connection<{}>::ensure_channel({:?})", self.id, request);
|
||||||
|
Err(tree::MethodErr::no_arg()) // FIXME: should be NotImplemented?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn channels(
|
||||||
|
&self,
|
||||||
|
) -> Result<
|
||||||
|
Vec<(
|
||||||
|
dbus::Path<'static>,
|
||||||
|
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
|
||||||
|
)>,
|
||||||
|
tree::MethodErr,
|
||||||
|
> {
|
||||||
|
println!("Connection<{}>::channels()", self.id);
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn requestable_channel_classes(
|
||||||
|
&self,
|
||||||
|
) -> Result<
|
||||||
|
Vec<(
|
||||||
|
::std::collections::HashMap<String, arg::Variant<Box<dyn arg::RefArg + 'static>>>,
|
||||||
|
Vec<String>,
|
||||||
|
)>,
|
||||||
|
tree::MethodErr,
|
||||||
|
> {
|
||||||
|
println!("Connection<{}>::requestable_channel_classes()", self.id);
|
||||||
|
Ok(super::requestables())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn escape_one(b: u8) -> String {
|
fn escape_one(b: u8) -> String {
|
||||||
format!("_{:0<2x}", b)
|
format!("_{:0<2x}", b)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user