More presence service rework
This commit is contained in:
+82
-62
@@ -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")
|
||||
|
||||
def is_owner(self):
|
||||
return self._owner
|
||||
|
||||
|
||||
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 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 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
|
||||
|
||||
Reference in New Issue
Block a user