Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
This commit is contained in:
commit
fc000346e4
@ -10,6 +10,9 @@ PRESENCE_SERVICE_TYPE = "_presence_olpc._tcp"
|
|||||||
BUDDY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Buddies/"
|
BUDDY_DBUS_OBJECT_PATH = "/org/laptop/Presence/Buddies/"
|
||||||
BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy"
|
BUDDY_DBUS_INTERFACE = "org.laptop.Presence.Buddy"
|
||||||
|
|
||||||
|
_BUDDY_KEY_COLOR = 'color'
|
||||||
|
_BUDDY_KEY_CURACT = 'curact'
|
||||||
|
|
||||||
class NotFoundError(Exception):
|
class NotFoundError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -85,7 +88,10 @@ class BuddyDBusHelper(dbus.service.Object):
|
|||||||
props['owner'] = self._parent.is_owner()
|
props['owner'] = self._parent.is_owner()
|
||||||
color = self._parent.get_color()
|
color = self._parent.get_color()
|
||||||
if color:
|
if color:
|
||||||
props['color'] = self._parent.get_color()
|
props[_BUDDY_KEY_COLOR] = self._parent.get_color()
|
||||||
|
curact = self._parent.get_current_activity()
|
||||||
|
if curact:
|
||||||
|
props[_BUDDY_KEY_CURACT] = self._parent.get_current_activity()
|
||||||
return props
|
return props
|
||||||
|
|
||||||
|
|
||||||
@ -113,6 +119,7 @@ class Buddy(object):
|
|||||||
self._nick_name = service.get_name()
|
self._nick_name = service.get_name()
|
||||||
self._address = service.get_source_address()
|
self._address = service.get_source_address()
|
||||||
self._color = None
|
self._color = None
|
||||||
|
self._current_activity = None
|
||||||
self._valid = False
|
self._valid = False
|
||||||
self._icon = None
|
self._icon = None
|
||||||
self._icon_tries = 0
|
self._icon_tries = 0
|
||||||
@ -121,6 +128,7 @@ class Buddy(object):
|
|||||||
self._object_path = BUDDY_DBUS_OBJECT_PATH + str(self._object_id)
|
self._object_path = BUDDY_DBUS_OBJECT_PATH + str(self._object_id)
|
||||||
self._dbus_helper = BuddyDBusHelper(self, bus_name, self._object_path)
|
self._dbus_helper = BuddyDBusHelper(self, bus_name, self._object_path)
|
||||||
|
|
||||||
|
self._buddy_presence_service = None
|
||||||
if service is not None:
|
if service is not None:
|
||||||
self.add_service(service)
|
self.add_service(service)
|
||||||
|
|
||||||
@ -181,25 +189,48 @@ class Buddy(object):
|
|||||||
service_key[1]))
|
service_key[1]))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
if service.get_type() == PRESENCE_SERVICE_TYPE and self._buddy_presence_service:
|
||||||
|
# already have a presence service for this buddy
|
||||||
|
logging.debug("!!! Tried to add a buddy presence service when " \
|
||||||
|
"one already existed.")
|
||||||
|
return False
|
||||||
|
|
||||||
logging.debug("Buddy %s added service type %s id %s" % (self._nick_name,
|
logging.debug("Buddy %s added service type %s id %s" % (self._nick_name,
|
||||||
service.get_type(), service.get_activity_id()))
|
service.get_type(), service.get_activity_id()))
|
||||||
self._services[service_key] = service
|
self._services[service_key] = service
|
||||||
service.set_owner(self)
|
service.set_owner(self)
|
||||||
|
|
||||||
if service.get_type() == PRESENCE_SERVICE_TYPE:
|
if service.get_type() == PRESENCE_SERVICE_TYPE:
|
||||||
|
self._buddy_presence_service = service
|
||||||
# A buddy isn't valid until its official presence
|
# A buddy isn't valid until its official presence
|
||||||
# service has been found and resolved
|
# service has been found and resolved
|
||||||
self._valid = True
|
self._valid = True
|
||||||
print 'Requesting buddy icon %s' % self._nick_name
|
logging.debug('Requesting buddy icon %s' % self._nick_name)
|
||||||
self._request_buddy_icon(service)
|
self._request_buddy_icon(service)
|
||||||
self._color = service.get_one_property('color')
|
self._color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||||
if self._color:
|
if self._color:
|
||||||
self._dbus_helper.PropertyChanged(['color'])
|
self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
|
||||||
|
# Monitor further buddy property changes, like current activity
|
||||||
|
# and color
|
||||||
|
service.connect('property-changed',
|
||||||
|
self.__buddy_presence_service_property_changed_cb)
|
||||||
|
|
||||||
if self._valid:
|
if self._valid:
|
||||||
self._dbus_helper.ServiceAppeared(service.object_path())
|
self._dbus_helper.ServiceAppeared(service.object_path())
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def __buddy_presence_service_property_changed_cb(self, service, keys):
|
||||||
|
if _BUDDY_KEY_COLOR in keys:
|
||||||
|
new_color = service.get_one_property(_BUDDY_KEY_COLOR)
|
||||||
|
if new_color and self._color != new_color:
|
||||||
|
self._color = new_color
|
||||||
|
self._dbus_helper.PropertyChanged([_BUDDY_KEY_COLOR])
|
||||||
|
if _BUDDY_KEY_CURACT in keys:
|
||||||
|
new_curact = service.get_one_property(_BUDDY_KEY_CURACT)
|
||||||
|
if new_curact and self._current_activity != new_curact:
|
||||||
|
self._current_activity = new_curact
|
||||||
|
self._dbus_helper.PropertyChanged([_BUDDY_KEY_CURACT])
|
||||||
|
|
||||||
def add_activity(self, activity):
|
def add_activity(self, activity):
|
||||||
actid = activity.get_id()
|
actid = activity.get_id()
|
||||||
if activity in self._activities.values():
|
if activity in self._activities.values():
|
||||||
@ -222,6 +253,13 @@ class Buddy(object):
|
|||||||
return
|
return
|
||||||
if service.get_name() != self._nick_name:
|
if service.get_name() != self._nick_name:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if service.get_type() == PRESENCE_SERVICE_TYPE \
|
||||||
|
and self._buddy_presence_service \
|
||||||
|
and service != self._buddy_presence_service:
|
||||||
|
logging.debug("!!! Tried to remove a spurious buddy presence service.")
|
||||||
|
return
|
||||||
|
|
||||||
service_key = self._get_service_key(service)
|
service_key = self._get_service_key(service)
|
||||||
if self._services.has_key(service_key):
|
if self._services.has_key(service_key):
|
||||||
if self._valid:
|
if self._valid:
|
||||||
@ -282,6 +320,9 @@ class Buddy(object):
|
|||||||
def get_color(self):
|
def get_color(self):
|
||||||
return self._color
|
return self._color
|
||||||
|
|
||||||
|
def get_current_activity(self):
|
||||||
|
return self._current_activity
|
||||||
|
|
||||||
def _set_icon(self, icon):
|
def _set_icon(self, icon):
|
||||||
"""Can only set icon for other buddies. The Owner
|
"""Can only set icon for other buddies. The Owner
|
||||||
takes care of setting it's own icon."""
|
takes care of setting it's own icon."""
|
||||||
|
@ -5,6 +5,7 @@ from sugar import util
|
|||||||
import dbus, dbus.service
|
import dbus, dbus.service
|
||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
|
import gobject
|
||||||
|
|
||||||
def compose_service_name(name, activity_id):
|
def compose_service_name(name, activity_id):
|
||||||
if type(name) == type(""):
|
if type(name) == type(""):
|
||||||
@ -135,13 +136,19 @@ class ServiceDBusHelper(dbus.service.Object):
|
|||||||
self._parent.set_properties(values, sender)
|
self._parent.set_properties(values, sender)
|
||||||
|
|
||||||
|
|
||||||
class Service(object):
|
class Service(gobject.GObject):
|
||||||
"""Encapsulates information about a specific ZeroConf/mDNS
|
"""Encapsulates information about a specific ZeroConf/mDNS
|
||||||
service as advertised on the network."""
|
service as advertised on the network."""
|
||||||
|
|
||||||
|
__gsignals__ = {
|
||||||
|
'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||||
|
([gobject.TYPE_PYOBJECT]))
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, bus_name, object_id, name, stype, domain=u"local",
|
def __init__(self, bus_name, object_id, name, stype, domain=u"local",
|
||||||
address=None, port=-1, properties=None, source_address=None,
|
address=None, port=-1, properties=None, source_address=None,
|
||||||
local_publisher=None):
|
local_publisher=None):
|
||||||
|
gobject.GObject.__init__(self)
|
||||||
if not bus_name:
|
if not bus_name:
|
||||||
raise ValueError("DBus bus name must be valid")
|
raise ValueError("DBus bus name must be valid")
|
||||||
if not object_id or type(object_id) != type(1):
|
if not object_id or type(object_id) != type(1):
|
||||||
@ -178,7 +185,7 @@ class Service(object):
|
|||||||
self._domain = domain
|
self._domain = domain
|
||||||
self._port = -1
|
self._port = -1
|
||||||
self.set_port(port)
|
self.set_port(port)
|
||||||
self._properties = None
|
self._properties = {}
|
||||||
self._dbus_helper = None
|
self._dbus_helper = None
|
||||||
self._internal_set_properties(properties)
|
self._internal_set_properties(properties)
|
||||||
|
|
||||||
@ -252,6 +259,11 @@ class Service(object):
|
|||||||
properties."""
|
properties."""
|
||||||
return self._properties
|
return self._properties
|
||||||
|
|
||||||
|
def __emit_properties_changed_signal(self, keys):
|
||||||
|
if self._dbus_helper:
|
||||||
|
self._dbus_helper.PublishedValueChanged(keys)
|
||||||
|
self.emit('property-changed', keys)
|
||||||
|
|
||||||
def set_property(self, key, value, sender=None):
|
def set_property(self, key, value, sender=None):
|
||||||
"""Set one service property"""
|
"""Set one service property"""
|
||||||
if not self._local_publisher:
|
if not self._local_publisher:
|
||||||
@ -290,8 +302,7 @@ class Service(object):
|
|||||||
if self._local_publisher and self._avahi_entry_group:
|
if self._local_publisher and self._avahi_entry_group:
|
||||||
self.__internal_update_avahi_properties()
|
self.__internal_update_avahi_properties()
|
||||||
|
|
||||||
if self._dbus_helper:
|
self.__emit_properties_changed_signal([key])
|
||||||
self._dbus_helper.PublishedValueChanged([key])
|
|
||||||
|
|
||||||
def set_properties(self, properties, sender=None, from_network=False):
|
def set_properties(self, properties, sender=None, from_network=False):
|
||||||
"""Set all service properties in one call"""
|
"""Set all service properties in one call"""
|
||||||
@ -306,13 +317,13 @@ class Service(object):
|
|||||||
python dictionary."""
|
python dictionary."""
|
||||||
if type(properties) != type({}):
|
if type(properties) != type({}):
|
||||||
raise ValueError("Properties must be a dictionary.")
|
raise ValueError("Properties must be a dictionary.")
|
||||||
self._properties = {}
|
|
||||||
|
|
||||||
# Make sure the properties are actually different
|
# Make sure the properties are actually different
|
||||||
diff_keys = _dicts_differ(self._properties, properties)
|
diff_keys = _dicts_differ(self._properties, properties)
|
||||||
if len(diff_keys) == 0:
|
if len(diff_keys) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
self._properties = {}
|
||||||
# Set key/value pairs on internal property list
|
# Set key/value pairs on internal property list
|
||||||
for key, value in properties.items():
|
for key, value in properties.items():
|
||||||
if len(key) == 0:
|
if len(key) == 0:
|
||||||
@ -329,8 +340,7 @@ class Service(object):
|
|||||||
if self._local_publisher and self._avahi_entry_group and not from_network:
|
if self._local_publisher and self._avahi_entry_group and not from_network:
|
||||||
self.__internal_update_avahi_properties()
|
self.__internal_update_avahi_properties()
|
||||||
|
|
||||||
if self._dbus_helper:
|
self.__emit_properties_changed_signal(diff_keys)
|
||||||
self._dbus_helper.PublishedValueChanged(diff_keys)
|
|
||||||
|
|
||||||
def __internal_update_avahi_properties(self):
|
def __internal_update_avahi_properties(self):
|
||||||
info = _convert_properties_to_dbus_byte_array(self._properties)
|
info = _convert_properties_to_dbus_byte_array(self._properties)
|
||||||
|
@ -3,12 +3,18 @@ from sugar.canvas.IconColor import IconColor
|
|||||||
|
|
||||||
class BuddyModel:
|
class BuddyModel:
|
||||||
def __init__(self, buddy=None):
|
def __init__(self, buddy=None):
|
||||||
if buddy:
|
|
||||||
self.set_name(buddy.get_name())
|
|
||||||
self.set_color(buddy.get_color())
|
|
||||||
self._buddy = buddy
|
|
||||||
self._cur_activity = None
|
self._cur_activity = None
|
||||||
self._pservice = PresenceService.get_instance()
|
self._pservice = PresenceService.get_instance()
|
||||||
|
|
||||||
|
self._buddy = buddy
|
||||||
|
if self._buddy:
|
||||||
|
self.set_name(self._buddy.get_name())
|
||||||
|
self.set_color(self._buddy.get_color())
|
||||||
|
self._buddy.connect('property-changed',
|
||||||
|
self.__buddy_property_changed_cb)
|
||||||
|
else:
|
||||||
|
# if we don't have a buddy yet, connect to the PS
|
||||||
|
# and wait until the buddy pops up on the network
|
||||||
self._pservice.connect('buddy-appeared', self.__buddy_appeared_cb)
|
self._pservice.connect('buddy-appeared', self.__buddy_appeared_cb)
|
||||||
|
|
||||||
def set_name(self, name):
|
def set_name(self, name):
|
||||||
@ -24,7 +30,11 @@ class BuddyModel:
|
|||||||
return self._color
|
return self._color
|
||||||
|
|
||||||
def get_buddy(self):
|
def get_buddy(self):
|
||||||
if not self._buddy:
|
# If we have a buddy already, just return
|
||||||
|
if self._buddy:
|
||||||
|
return self._buddy
|
||||||
|
|
||||||
|
# Otherwise try to get the buddy from the PS
|
||||||
self._buddy = self._pservice.get_buddy_by_name(self._name)
|
self._buddy = self._pservice.get_buddy_by_name(self._name)
|
||||||
if self._buddy:
|
if self._buddy:
|
||||||
self._buddy.connect('property-changed',
|
self._buddy.connect('property-changed',
|
||||||
@ -32,10 +42,12 @@ class BuddyModel:
|
|||||||
return self._buddy
|
return self._buddy
|
||||||
|
|
||||||
def __buddy_appeared_cb(self, pservice, buddy):
|
def __buddy_appeared_cb(self, pservice, buddy):
|
||||||
|
# FIXME: use public key rather than buddy name
|
||||||
if not self._buddy and buddy.get_name() == self._name:
|
if not self._buddy and buddy.get_name() == self._name:
|
||||||
self.get_buddy()
|
self.get_buddy()
|
||||||
|
|
||||||
def __buddy_property_changed_cb(self, buddy, keys):
|
def __buddy_property_changed_cb(self, buddy, keys):
|
||||||
|
# all we care about right now is current activity
|
||||||
curact = self._buddy.get_current_activity()
|
curact = self._buddy.get_current_activity()
|
||||||
self._cur_activity = self._pservice.get_activity(curact)
|
self._cur_activity = self._pservice.get_activity(curact)
|
||||||
|
|
||||||
|
@ -36,7 +36,13 @@ class Buddy(gobject.GObject):
|
|||||||
self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb)
|
self._buddy.connect_to_signal('JoinedActivity', self._joined_activity_cb)
|
||||||
self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb)
|
self._buddy.connect_to_signal('LeftActivity', self._left_activity_cb)
|
||||||
self._buddy.connect_to_signal('PropertyChanged', self._property_changed_cb)
|
self._buddy.connect_to_signal('PropertyChanged', self._property_changed_cb)
|
||||||
self._properties = self._buddy.getProperties()
|
self._properties = self._get_properties_helper()
|
||||||
|
|
||||||
|
def _get_properties_helper(self):
|
||||||
|
props = self._buddy.getProperties()
|
||||||
|
if not props:
|
||||||
|
return {}
|
||||||
|
return props
|
||||||
|
|
||||||
def object_path(self):
|
def object_path(self):
|
||||||
return self._object_path
|
return self._object_path
|
||||||
@ -77,7 +83,7 @@ class Buddy(gobject.GObject):
|
|||||||
gobject.idle_add(self._emit_left_activity_signal, object_path)
|
gobject.idle_add(self._emit_left_activity_signal, object_path)
|
||||||
|
|
||||||
def _handle_property_changed_signal(self, prop_list):
|
def _handle_property_changed_signal(self, prop_list):
|
||||||
self._properties = self._buddy.getProperties()
|
self._properties = self._get_properties_helper()
|
||||||
self.emit('property-changed', prop_list)
|
self.emit('property-changed', prop_list)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user