diff --git a/services/presence2/buddy.py b/services/presence2/buddy.py index acec16a5..63f6da9f 100644 --- a/services/presence2/buddy.py +++ b/services/presence2/buddy.py @@ -170,6 +170,9 @@ class Buddy(dbus.service.Object): def is_owner(self): return False + def set_key(self, key): + self._key = key + def get_key(self): return self._key diff --git a/services/presence2/presenceservice.py b/services/presence2/presenceservice.py index fffb7c52..af709695 100644 --- a/services/presence2/presenceservice.py +++ b/services/presence2/presenceservice.py @@ -20,8 +20,8 @@ from telepathy.client import ManagerRegistry, Connection from telepathy.interfaces import CONN_MGR_INTERFACE import telepathyclient -import buddy -import activity +from buddy import Buddy, Owner +from activity import Activity import buddyiconcache from sugar import profile @@ -42,7 +42,7 @@ class PresenceService(dbus.service.Object): self._next_object_id = 0 self._buddies = {} # key -> Buddy - self._buddies_handle = {} # tp handle -> Buddy + self._handles = {} # tp client -> (handle -> Buddy) self._activities = {} # activity id -> Activity self._icon_cache = buddyiconcache.BuddyIconCache() @@ -52,7 +52,7 @@ class PresenceService(dbus.service.Object): # Create the Owner object objid = self._get_next_object_id() - self._owner = buddy.Owner(self, self._bus_name, objid, self._icon_cache) + self._owner = Owner(self, self._bus_name, objid, self._icon_cache) self._buddies[self._owner.get_key()] = self._owner self._registry = ManagerRegistry() @@ -71,26 +71,42 @@ class PresenceService(dbus.service.Object): conn = Connection(conn_bus_name, conn_object_path) self._server_client = telepathyclient.TelepathyClient(conn) + self._handles[self._server_client] = {} + # Telepathy link local connection self._ll_client = None - self._server_client.connect('contact-appeared', self._contact_appeared) + self._server_client.connect('contact-online', self._contact_online) + self._server_client.connect('contact-offline', self._contact_offline) self._server_client.run() dbus.service.Object.__init__(self, self._bus_name, _PRESENCE_PATH) - def _contact_appeared(self, tp, handle, key): - if self._buddies.has_key(key): - # We already know this buddy - return + def _contact_online(self, tp, handle, key): + buddy = self._buddies.get(key) - objid = self._get_next_object_id() - new_buddy = buddy.Buddy(self._bus_name, objid, self._icon_cache) - self._buddies[key] = new_buddy - self._buddies_handle[handle] = new_buddy + if not buddy: + # we don't know yet this buddy + objid = self._get_next_object_id() + buddy = Buddy(self._bus_name, objid, self._icon_cache) + buddy.set_key(key) + print "create buddy" + self._buddies[key] = buddy - self.BuddyAppeared(new_buddy.object_path()) + buddies = self._handles[tp] + buddies[handle] = buddy + + self.BuddyAppeared(buddy.object_path()) + def _contact_offline(self, tp, handle): + buddy = self._handles[tp].pop(handle) + key = buddy.get_key() + + # TODO: check if we don't see this buddy using the other CM + self._buddies.pop(key) + print "remove buddy" + + self.BuddyDisappeared(buddy.object_path()) def _get_next_object_id(self): """Increment and return the object ID counter.""" diff --git a/services/presence2/telepathyclient.py b/services/presence2/telepathyclient.py index 4ade31e5..aeb2a2d2 100644 --- a/services/presence2/telepathyclient.py +++ b/services/presence2/telepathyclient.py @@ -5,7 +5,7 @@ import gobject from telepathy.client import ConnectionManager, ManagerRegistry, Connection, Channel from telepathy.interfaces import ( CONN_MGR_INTERFACE, CONN_INTERFACE, CHANNEL_TYPE_CONTACT_LIST, CHANNEL_INTERFACE_GROUP, CONN_INTERFACE_ALIASING, - CONN_INTERFACE_AVATARS) + CONN_INTERFACE_AVATARS, CONN_INTERFACE_PRESENCE) from telepathy.constants import ( CONNECTION_HANDLE_TYPE_NONE, CONNECTION_HANDLE_TYPE_CONTACT, CONNECTION_STATUS_CONNECTED, CONNECTION_STATUS_DISCONNECTED, CONNECTION_STATUS_CONNECTING, @@ -17,16 +17,25 @@ import buddy class TelepathyClient(gobject.GObject): __gsignals__ = { - 'contact-appeared':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + 'contact-online':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), + 'contact-offline':(gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), } def __init__(self, conn): gobject.GObject.__init__(self) + self._online_contacts = set() + conn[CONN_INTERFACE].connect_to_signal('StatusChanged', self._status_changed_cb) + # hack + conn._valid_interfaces.add(CONN_INTERFACE_PRESENCE) + conn[CONN_INTERFACE_PRESENCE].connect_to_signal('PresenceUpdate', + self._presence_update_cb) + self.conn = conn def _request_list_channel(self, name): @@ -56,6 +65,7 @@ class TelepathyClient(gobject.GObject): not_subscribed = list(set(publish_handles) - set(subscribe_handles)) self_handle = self.conn[CONN_INTERFACE].GetSelfHandle() + self._online_contacts.add(self_handle) for handle in not_subscribed: # request subscriptions from people subscribed to us if we're not subscribed to them @@ -64,14 +74,10 @@ class TelepathyClient(gobject.GObject): # hack self.conn._valid_interfaces.add(CONN_INTERFACE_ALIASING) - for handle in subscribe_handles: - self._contact_appeared(handle); - if CONN_INTERFACE_ALIASING in self.conn: aliases = self.conn[CONN_INTERFACE_ALIASING].RequestAliases(subscribe_handles) else: aliases = self.conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, subscribe_handles) - print aliases #for handle, alias in zip(subscribe_handles, aliases): # print alias @@ -115,9 +121,36 @@ class TelepathyClient(gobject.GObject): def disconnect(self): self.conn[CONN_INTERFACE].Disconnect() - def _contact_appeared(self, handle): - key = "1111111" - self.emit("contact-appeared", handle, key) + + def _contact_go_offline(self, handle): + name = self.conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] + print name, "offline" + + self._online_contacts.remove(handle) + self.emit("contact-offline", handle) + + def _contact_go_online(self, handle): + name = self.conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] + print name, "online" + + # TODO: use the OLPC interface to get the key + key = handle + + self._online_contacts.add(handle) + self.emit("contact-online", handle, key) + + def _presence_update_cb(self, presence): + for handle in presence: + timestamp, statuses = presence[handle] + + name = self.conn[CONN_INTERFACE].InspectHandles(CONNECTION_HANDLE_TYPE_CONTACT, [handle])[0] + online = handle in self._online_contacts + + for status, params in statuses.items(): + if not online and status in ["available", "away", "brb", "busy", "dnd", "xa"]: + self._contact_go_online(handle) + elif online and status in ["offline", "invisible"]: + self._contact_go_offline(handle) if __name__ == '__main__': import logging