diff options
author | Dan Williams <dcbw@localhost.localdomain> | 2006-07-19 19:27:37 (GMT) |
---|---|---|
committer | Dan Williams <dcbw@localhost.localdomain> | 2006-07-19 19:27:37 (GMT) |
commit | 766b82d46706c0a9f4e32635e27db8aa55a1b820 (patch) | |
tree | 4e02886931de5a0d37fd57216fe47641f2337173 /sugar/presence/Buddy.py | |
parent | d2fdd6400348b2adc08b99e69e67c64aa092ac65 (diff) |
Switch sugar/presence module over to a thin API wrapper around the PresenceService dbus API
Diffstat (limited to 'sugar/presence/Buddy.py')
-rw-r--r-- | sugar/presence/Buddy.py | 253 |
1 files changed, 79 insertions, 174 deletions
diff --git a/sugar/presence/Buddy.py b/sugar/presence/Buddy.py index b91cb7d..ca26946 100644 --- a/sugar/presence/Buddy.py +++ b/sugar/presence/Buddy.py @@ -1,189 +1,94 @@ -import base64 -import logging - -import gtk import gobject - -from sugar.p2p import Stream -from sugar.p2p import network -from sugar.presence import Service - -PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" +import dbus, dbus_bindings class Buddy(gobject.GObject): - """Represents another person on the network and keeps track of the - activities and resources they make available for sharing.""" + __gsignals__ = { - 'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + 'IconChanged': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'service-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + 'ServiceAppeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'ServiceDisappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), - 'service-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + 'JoinedActivity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), - 'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_STRING])), - 'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_STRING])) + 'LeftActivity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) } - def __init__(self, service): + _PRESENCE_SERVICE = "org.laptop.Presence" + _BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy" + + def __init__(self, bus, new_obj_cb, del_obj_cb, object_path): gobject.GObject.__init__(self) - self._services = {} - self._nick_name = service.get_name() - self._address = service.get_publisher_address() - self._valid = False - self._icon = None - self._icon_tries = 0 - self._owner = False - self.add_service(service) - - def _request_buddy_icon_cb(self, result_status, response, user_data): - """Callback when icon request has completed.""" - icon = response - service = user_data - if result_status == network.RESULT_SUCCESS: - if icon and len(icon): - icon = base64.b64decode(icon) - print "Buddy icon for '%s' is size %d" % (self._nick_name, len(icon)) - self.set_icon(icon) - - if (result_status == network.RESULT_FAILED or not icon) and self._icon_tries < 3: - self._icon_tries = self._icon_tries + 1 - print "Failed to retrieve buddy icon for '%s' on try %d of %d" % (self._nick_name, \ - self._icon_tries, 3) - gobject.timeout_add(1000, self._request_buddy_icon, service) + self._object_path = object_path + self._ps_new_object = new_obj_cb + self._ps_del_object = del_obj_cb + bobj = bus.get_object(self._PRESENCE_SERVICE, object_path) + self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE) + self._buddy.connect_to_signal('IconChanged', self._icon_changed_cb) + self._buddy.connect_to_signal('ServiceAppeared', self._service_appeared_cb) + self._buddy.connect_to_signal('ServiceDisappeared', self._service_disappeared_cb) + self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb) + self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb) + + def object_path(self): + return self._object_path + + def _emit_icon_changed_signal(self): + self.emit('IconChanged') return False - def _request_buddy_icon(self, service): - """Contact the buddy to retrieve the buddy icon.""" - buddy_stream = Stream.Stream.new_from_service(service, start_reader=False) - writer = buddy_stream.new_writer(service) - success = writer.custom_request("get_buddy_icon", self._request_buddy_icon_cb, service) - if not success: - del writer, buddy_stream - gobject.timeout_add(1000, self._request_buddy_icon, service) + def _icon_changed_cb(self): + gobject.idle_add(self._emit_icon_changed_signal) + + def _emit_service_appeared_signal(self, object_path): + self.emit('ServiceAppeared', self._ps_new_object(object_path)) return False - def add_service(self, service): - """Adds a new service to this buddy's service list, returning - True if the service was successfully added, and False if it was not.""" - if service.get_name() != self._nick_name: - return False - publisher_addr = service.get_publisher_address() - if publisher_addr != self._address: - logging.error('Service publisher and buddy address doesnt match: %s %s' % (publisher_addr, self._address)) - return False - stype = service.get_type() - if stype in self._services.keys(): - return False - self._services[stype] = service - if self._valid: - self.emit("service-added", service) - - # If this is the first service we've seen that's owned by - # a particular activity, send out the 'joined-activity' signal - actid = service.get_activity_id() - if actid is not None: - found = False - for serv in self._services.values(): - if serv.get_activity_id() == actid and serv.get_type() != stype: - found = True - break - if not found: - print "Buddy (%s) joined activity %s." % (self._nick_name, actid) - self.emit("joined-activity", service) - - if stype == PRESENCE_SERVICE_TYPE: - # A buddy isn't valid until its official presence - # service has been found and resolved - self._valid = True - print 'Requesting buddy icon %s' % self._nick_name - self._request_buddy_icon(service) - return True - - def remove_service(self, service): - """Remove a service from a buddy; ie, the activity was closed - or the buddy went away.""" - if service.get_publisher_address() != self._address: - return - if service.get_name() != self._nick_name: - return - stype = service.get_type() - if self._services.has_key(stype): - if self._valid: - self.emit("service-removed", service) - del self._services[stype] - - # If this is the lase service owned by a particular activity, - # and it's just been removed, send out the 'left-actvity' signal - actid = service.get_activity_id() - if actid is not None: - found = False - for serv in self._services.values(): - if serv.get_activity_id() == actid: - found = True - break - if not found: - print "Buddy (%s) left activity %s." % (self._nick_name, actid) - self.emit("left-activity", service) - - if stype == PRESENCE_SERVICE_TYPE: - self._valid = False - - def get_service_of_type(self, stype=None, activity=None): - """Return a service of a certain type, or None if the buddy - doesn't provide that service.""" - if not stype: - raise RuntimeError("Need to specify a service type.") - - if activity: - actid = activity.get_id() - for service in self._services.values(): - if service.get_type() == stype and service.get_activity_id() == actid: - return service - if self._services.has_key(stype): - return self._services[stype] - return None - - def is_valid(self): - """Return whether the buddy is valid or not. A buddy is - not valid until its official presence service has been found - and successfully resolved.""" - return self._valid - - def get_icon_pixbuf(self): - if self._icon: - pbl = gtk.gdk.PixbufLoader() - pbl.write(self._icon) - pbl.close() - return pbl.get_pixbuf() - else: - return None + def _service_appeared_cb(self, object_path): + gobject.idle_add(self._emit_service_appeared_signal, object_path) + + def _emit_service_disappeared_signal(self, object_path): + self.emit('ServiceDisappeared', self._ps_new_object(object_path)) + return False - def get_icon(self): - """Return the buddies icon, if any.""" - return self._icon - - def get_address(self): - return self._address - - def get_nick_name(self): - return self._nick_name - - def set_icon(self, icon): - """Can only set icon for other buddies. The Owner - takes care of setting it's own icon.""" - if icon != self._icon: - self._icon = icon - self.emit("icon-changed") - - def is_owner(self): - return self._owner - - -class Owner(Buddy): - """Class representing the owner of the machine. This is the client - portion of the Owner, paired with the server portion in Owner.py.""" - def __init__(self, service): - Buddy.__init__(self, service) - self._owner = True + def _service_disappeared_cb(self, object_path): + gobject.idle_add(self._emit_service_disappeared_signal, object_path) + + def _emit_joined_activity_signal(self, object_path): + self.emit('JoinedActivity', self._ps_new_object(object_path)) + return False + + def _joined_activity_cb(self, object_path): + gobject.idle_add(self._emit_joined_activity_signal, object_path) + + def _emit_left_activity_signal(self, object_path): + self.emit('LeftActivity', self._ps_new_object(object_path)) + return False + + def _left_activity_cb(self, object_path): + gobject.idle_add(self._emit_left_activity_signal, object_path) + + def getProperties(self): + return self._buddy.getProperties() + + def getIcon(self): + return self._buddy.getIcon() + + def getServiceOfType(self, stype): + try: + object_path = self._buddy.getServiceOfType(stype) + except dbus_bindings.DBusException: + return None + return self._ps_new_object(object_path) + + def getJoinedActivities(self): + try: + resp = self._buddy.getJoinedActivities() + except dbus_bindings.DBusException: + return [] + acts = [] + for item in resp: + acts.append(self._ps_new_object(item)) + return acts |