diff options
author | Dan Williams <dcbw@redhat.com> | 2006-06-12 22:31:26 (GMT) |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2006-06-12 22:31:26 (GMT) |
commit | 17c371119dfff8285775e6cb69af97433595ac55 (patch) | |
tree | 7af4ec838dff1763217b84de26f9fb4129c5fa5d /sugar/presence/Buddy.py | |
parent | d931dca5799ee1e88ce327bf28424f9739f4ad87 (diff) |
More presence service rework
Diffstat (limited to 'sugar/presence/Buddy.py')
-rw-r--r-- | sugar/presence/Buddy.py | 144 |
1 files changed, 82 insertions, 62 deletions
diff --git a/sugar/presence/Buddy.py b/sugar/presence/Buddy.py index 5201a04..9d94b9d 100644 --- a/sugar/presence/Buddy.py +++ b/sugar/presence/Buddy.py @@ -1,46 +1,108 @@ import pwd import os +import base64 import pygtk pygtk.require('2.0') -import gtk +import gtk, gobject +from sugar.p2p import Stream +from sugar.p2p import network -#from sugar import env PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp" -class Buddy(object): +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, + ([])), + 'service-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'service-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) + } + def __init__(self, service): + gobject.GObject.__init__(self) self._services = {} self._nick_name = service.get_name() self._address = service.get_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) + 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) + return False + def add_service(self, service): - """Adds a new service to this buddy's service list.""" + """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 + if service.get_address() != self._address: + return False if service.get_type() in self._services.keys(): - return - self._services.keys[service.get_type()] = service - # FIXME: send out signal for new service found + return False + self._services[service.get_type()] = service + if self._valid: + self.emit("service-added", service) if service.get_type() == PRESENCE_SERVICE_TYPE: # A buddy isn't valid until its official presence # service has been found and resolved self._valid = True + 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_type() in self._services.keys(): + if service.get_address() != self._address: + return + if service.get_name() != self._nick_name: + return + if self._services.has_key(service.get_type()): + if self._valid: + self.emit("service-removed", service) del self._services[service.get_type()] if service.get_type() == PRESENCE_SERVICE_TYPE: self._valid = False + def get_service_of_type(self, stype): + """Return a service of a certain type, or None if the buddy + doesn't provide that 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 @@ -63,65 +125,23 @@ class Buddy(object): def get_address(self): return self._address - def add_service(self, service): - if service.get_name() != self._nick_name: - return False - if service.get_address() != self._address: - return False - if self._services.has_key(service.get_type()): - return False - self._services[service.get_type()] = service - - def remove_service(self, stype): - if self._services.has_key(stype): - del self._services[stype] - - def get_service(self, stype): - if self._services.has_key(stype): - return self._services[stype] - return None - 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.""" - self._icon = icon - # FIXME: do callbacks for icon-changed - + if icon != self._icon: + self._icon = icon + self.emit("icon-changed") -class Owner(Buddy): - """Class representing the owner of this machine/instance.""" - def __init__(self): - nick = env.get_nick_name() - if not nick: - nick = pwd.getpwuid(os.getuid())[0] - if not nick or not len(nick): - nick = "n00b" - - Buddy.__init__(self) - - user_dir = env.get_user_dir() - if not os.path.exists(user_dir): - try: - os.makedirs(user_dir) - except OSError: - print 'Could not create user directory.' - - for fname in os.listdir(user_dir): - if not fname.startswith("buddy-icon."): - continue - fd = open(os.path.join(user_dir, fname), "r") - self._icon = fd.read() - fd.close() - break + def is_owner(self): + return self._owner - def set_icon(self, icon): - """Can only set icon in constructor for now.""" - pass - - def add_service(self, service): - """Do nothing here, since all services we need to know about - are registered with us by our group.""" - pass + +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 |