Make joining asynchronous on the activity side

This commit is contained in:
Dan Williams 2007-05-02 23:25:15 -04:00
parent 46d97015e6
commit 7774073276
4 changed files with 76 additions and 40 deletions

View File

@ -42,6 +42,7 @@ class ActivityToolbar(gtk.Toolbar):
self._activity = activity self._activity = activity
activity.connect('shared', self._activity_shared_cb) activity.connect('shared', self._activity_shared_cb)
activity.connect('joined', self._activity_shared_cb)
button = ToolButton('window-close') button = ToolButton('window-close')
button.connect('clicked', self._close_button_clicked_cb) button.connect('clicked', self._close_button_clicked_cb)
@ -105,7 +106,8 @@ class Activity(Window, gtk.Container):
__gtype_name__ = 'SugarActivity' __gtype_name__ = 'SugarActivity'
__gsignals__ = { __gsignals__ = {
'shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) 'shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
} }
def __init__(self, handle): def __init__(self, handle):
@ -133,53 +135,64 @@ class Activity(Window, gtk.Container):
self.connect('destroy', self._destroy_cb) self.connect('destroy', self._destroy_cb)
self._shared = False
self._activity_id = handle.activity_id self._activity_id = handle.activity_id
self._pservice = presenceservice.get_instance() self._pservice = presenceservice.get_instance()
self._service = None self._shared_activity = None
self._share_sigid = None self._share_id = None
self._join_id = None
service = handle.get_presence_service() shared_activity = handle.get_shared_activity()
if service: if shared_activity:
self._join(service) # Join an existing instance of this activity on the network
self._shared_activity = shared_activity
self._join_id = self._shared_activity.connect("joined", self._internal_joined_cb)
if not self._shared_activity.props.joined:
self._shared_activity.join()
else:
self._joined_cb(self._shared_activity, True, None)
self._bus = ActivityService(self) self._bus = ActivityService(self)
def _internal_joined_cb(self, activity, success, err):
"""Callback when join has finished"""
self._shared_activity.disconnect(self._join_id)
self._join_id = None
if not success:
logging.debug("Failed to join activity: %s" % err)
return
self.present()
self.emit('joined')
def get_service_name(self): def get_service_name(self):
"""Gets the activity service name.""" """Gets the activity service name."""
return os.environ['SUGAR_BUNDLE_SERVICE_NAME'] return os.environ['SUGAR_BUNDLE_SERVICE_NAME']
def get_shared(self): def get_shared(self):
"""Returns TRUE if the activity is shared on the mesh.""" """Returns TRUE if the activity is shared on the mesh."""
return self._shared if not self._shared_activity:
return False
return self._shared_activity.props.joined
def get_id(self): def get_id(self):
"""Get the unique activity identifier.""" """Get the unique activity identifier."""
return self._activity_id return self._activity_id
def _join(self, service): def _internal_share_cb(self, ps, success, activity, err):
"""Join an existing instance of this activity on the network.""" self._pservice.disconnect(self._share_id)
self._service = service self._share_id = None
self._shared = True if not success:
self._service.join() logging.debug('Share of activity %s failed: %s.' % (self._activity_id, err))
self.present() return
logging.debug('Share of activity %s successful.' % self._activity_id)
self.shared_activity = activity
self.emit('shared') self.emit('shared')
def _share_cb(self, ps, success, service, err):
self._pservice.disconnect(self._share_sigid)
self._share_sigid = None
if success:
logging.debug('Share of activity %s successful.' % self.get_id())
self._service = service
self._shared = True
self.emit('shared')
else:
logging.debug('Share of activity %s failed: %s.' % (self.get_id(), err))
def share(self): def share(self):
"""Request that the activity be shared on the network.""" """Request that the activity be shared on the network."""
logging.debug('Requesting share of activity %s.' % self.get_id()) if self._shared_activty and self._shared_activity.props.joined:
self._share_sigid = self._pservice.connect("activity-shared", self._share_cb) raise RuntimeError("Activity %s already shared." % self._activity_id)
logging.debug('Requesting share of activity %s.' % self._activity_id)
self._share_id = self._pservice.connect("activity-shared", self._internal_share_cb)
self._pservice.share_activity(self) self._pservice.share_activity(self)
def execute(self, command, args): def execute(self, command, args):
@ -191,8 +204,8 @@ class Activity(Window, gtk.Container):
if self._bus: if self._bus:
del self._bus del self._bus
self._bus = None self._bus = None
if self._service: if self._shared_activity:
self._pservice.unregister_service(self._service) self._shared_activity.leave()
def _handle_close_cb(self, toolbar): def _handle_close_cb(self, toolbar):
self.destroy() self.destroy()

View File

@ -52,8 +52,8 @@ class ActivityHandle(object):
self.object_id = object_id self.object_id = object_id
self.uri = uri self.uri = uri
def get_presence_service(self): def get_shared_activity(self):
"""Retrieve the "sharing service" for this activity """Retrieve the shared instance of this activity
Uses the PresenceService to find any existing dbus Uses the PresenceService to find any existing dbus
service which provides sharing mechanisms for this service which provides sharing mechanisms for this

View File

@ -36,10 +36,12 @@ class Activity(gobject.GObject):
__gsignals__ = { __gsignals__ = {
'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT])),
'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])) ([gobject.TYPE_PYOBJECT])),
'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT]))
} }
__gproperties__ = { __gproperties__ = {
@ -137,15 +139,22 @@ class Activity(gobject.GObject):
buddies.append(self._ps_new_object(item)) buddies.append(self._ps_new_object(item))
return buddies return buddies
def _join_cb(self):
self._joined = True
self.emit("joined", True, None)
def _join_error_cb(self, err):
self.emit("joined", False, str(err))
def join(self): def join(self):
"""Join this activity """Join this activity
XXX if these are all activities, can I join my own activity? XXX if these are all activities, can I join my own activity?
""" """
if self._joined: if self._joined:
self.emit("joined", True, None)
return return
self._activity.Join() self._activity.Join(reply_handler=self._join_cb, error_handler=self._join_error_cb)
self._joined = True
def get_channels(self): def get_channels(self):
"""Retrieve communications channel descriptions for the activity """Retrieve communications channel descriptions for the activity
@ -157,7 +166,6 @@ class Activity(gobject.GObject):
(bus_name, connection, channels) = self._activity.GetChannels() (bus_name, connection, channels) = self._activity.GetChannels()
return bus_name, connection, channels return bus_name, connection, channels
def owner_has_joined(self): def leave(self):
"""Retrieve whether the owner of the activity is active within it"""
# FIXME # FIXME
return False self._joined = False

View File

@ -160,6 +160,11 @@ class PresenceService(gobject.GObject):
elif object_path.startswith(self._PS_ACTIVITY_OP): elif object_path.startswith(self._PS_ACTIVITY_OP):
obj = activity.Activity(self._bus, self._new_object, obj = activity.Activity(self._bus, self._new_object,
self._del_object, object_path) self._del_object, object_path)
try:
# Pre-fill the activity's ID
foo = obj.props.id
except dbus.exceptions.DBusException, err:
pass
else: else:
raise RuntimeError("Unknown object type") raise RuntimeError("Unknown object type")
self._objcache[object_path] = obj self._objcache[object_path] = obj
@ -322,7 +327,9 @@ class PresenceService(gobject.GObject):
def _share_activity_cb(self, activity, op): def _share_activity_cb(self, activity, op):
"""Notify with GObject event of successful sharing of activity""" """Notify with GObject event of successful sharing of activity"""
self.emit("activity-shared", True, self._new_object(op), None) psact = self._new_object(op)
psact._joined = True
self.emit("activity-shared", True, psact, None)
def _share_activity_error_cb(self, activity, err): def _share_activity_error_cb(self, activity, err):
"""Notify with GObject event of unsuccessful sharing of activity""" """Notify with GObject event of unsuccessful sharing of activity"""
@ -343,6 +350,14 @@ class PresenceService(gobject.GObject):
returns None returns None
""" """
actid = activity.get_id() actid = activity.get_id()
# Ensure the activity is not already shared/joined
for obj in self._objcache.values():
if not isinstance(object, activity.Activity):
continue
if obj.props.id == actid or obj.props.joined:
raise RuntimeError("Activity %s is already shared." % actid)
atype = activity.get_service_name() atype = activity.get_service_name()
name = activity.props.title name = activity.props.title
self._ps.ShareActivity(actid, atype, name, properties, self._ps.ShareActivity(actid, atype, name, properties,