From 0c3f127c86af818d260966d2292b199757087157 Mon Sep 17 00:00:00 2001 From: Simon Poirier Date: Sat, 11 Jul 2009 21:39:46 +0000 Subject: repackage --- (limited to 'src/sugar/presence/activity.py') diff --git a/src/sugar/presence/activity.py b/src/sugar/presence/activity.py deleted file mode 100644 index dc02aa1..0000000 --- a/src/sugar/presence/activity.py +++ /dev/null @@ -1,410 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -"""UI interface to an activity in the presence service - -STABLE. -""" - -import logging - -import dbus -import gobject -import telepathy - -_logger = logging.getLogger('sugar.presence.activity') - -class Activity(gobject.GObject): - """UI interface for an Activity in the presence service - - Activities in the presence service represent your and other user's - shared activities. - - Properties: - id - color - name - type - joined - """ - __gsignals__ = { - 'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), - } - - __gproperties__ = { - 'id' : (str, None, None, None, gobject.PARAM_READABLE), - 'name' : (str, None, None, None, gobject.PARAM_READWRITE), - 'tags' : (str, None, None, None, gobject.PARAM_READWRITE), - 'color' : (str, None, None, None, gobject.PARAM_READWRITE), - 'type' : (str, None, None, None, gobject.PARAM_READABLE), - 'private' : (bool, None, None, True, gobject.PARAM_READWRITE), - 'joined' : (bool, None, None, False, gobject.PARAM_READABLE), - } - - _PRESENCE_SERVICE = "org.laptop.Sugar.Presence" - _ACTIVITY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Activity" - - def __init__(self, bus, new_obj_cb, del_obj_cb, object_path): - """Initialse the activity interface, connecting to service""" - gobject.GObject.__init__(self) - self._telepathy_room_handle = None - 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._activity = dbus.Interface(bobj, self._ACTIVITY_DBUS_INTERFACE) - self._activity.connect_to_signal('BuddyHandleJoined', - self._buddy_handle_joined_cb) - self._activity.connect_to_signal('BuddyLeft', - self._buddy_left_cb) - self._activity.connect_to_signal('NewChannel', self._new_channel_cb) - self._activity.connect_to_signal('PropertiesChanged', - self._properties_changed_cb, - utf8_strings=True) - # FIXME: this *would* just use a normal proxy call, but I want the - # pending call object so I can block on it, and normal proxy methods - # don't return those as of dbus-python 0.82.1; so do it the hard way - self._get_properties_call = bus.call_async(self._PRESENCE_SERVICE, - object_path, self._ACTIVITY_DBUS_INTERFACE, 'GetProperties', - '', (), self._get_properties_reply_cb, - self._get_properties_error_cb, utf8_strings=True) - - self._id = None - self._color = None - self._name = None - self._type = None - self._tags = None - self._private = True - self._joined = False - # Cache for get_buddy_by_handle, maps handles to buddy object paths - self._handle_to_buddy_path = {} - self._buddy_path_to_handle = {} - - # Set up by set_up_tubes() - self.telepathy_conn = None - self.telepathy_tubes_chan = None - self.telepathy_text_chan = None - self._telepathy_room = None - - def __repr__(self): - return ('' % (self._object_path, id(self))) - - def _get_properties_reply_cb(self, new_props): - self._get_properties_call = None - _logger.debug('%r: initial GetProperties returned', self) - self._properties_changed_cb(new_props) - - def _get_properties_error_cb(self, e): - self._get_properties_call = None - # FIXME: do something with the error - _logger.warning('%r: Error doing initial GetProperties: %s', self, e) - - def _properties_changed_cb(self, new_props): - _logger.debug('%r: Activity properties changed to %r', self, new_props) - val = new_props.get('name', self._name) - if isinstance(val, str) and val != self._name: - self._name = val - self.notify('name') - val = new_props.get('tags', self._tags) - if isinstance(val, str) and val != self._tags: - self._tags = val - self.notify('tags') - val = new_props.get('color', self._color) - if isinstance(val, str) and val != self._color: - self._color = val - self.notify('color') - val = bool(new_props.get('private', self._private)) - if val != self._private: - self._private = val - self.notify('private') - val = new_props.get('id', self._id) - if isinstance(val, str) and self._id is None: - self._id = val - self.notify('id') - val = new_props.get('type', self._type) - if isinstance(val, str) and self._type is None: - self._type = val - self.notify('type') - - def object_path(self): - """Get our dbus object path""" - return self._object_path - - def do_get_property(self, pspec): - """Retrieve a particular property from our property dictionary""" - - if pspec.name == "joined": - return self._joined - - if self._get_properties_call is not None: - _logger.debug('%r: Blocking on GetProperties() because someone ' - 'wants property %s', self, pspec.name) - self._get_properties_call.block() - - if pspec.name == "id": - return self._id - elif pspec.name == "name": - return self._name - elif pspec.name == "color": - return self._color - elif pspec.name == "type": - return self._type - elif pspec.name == "tags": - return self._tags - elif pspec.name == "private": - return self._private - - # FIXME: need an asynchronous API to set these properties, particularly - # 'private' - def do_set_property(self, pspec, val): - """Set a particular property in our property dictionary""" - if pspec.name == "name": - self._activity.SetProperties({'name': val}) - self._name = val - elif pspec.name == "color": - self._activity.SetProperties({'color': val}) - self._color = val - elif pspec.name == "tags": - self._activity.SetProperties({'tags': val}) - self._tags = val - elif pspec.name == "private": - self._activity.SetProperties({'private': val}) - self._private = val - - def set_private(self, val, reply_handler, error_handler): - self._activity.SetProperties({'private': bool(val)}, - reply_handler=reply_handler, - error_handler=error_handler) - - def _emit_buddy_joined_signal(self, object_path): - """Generate buddy-joined GObject signal with presence Buddy object""" - self.emit('buddy-joined', self._ps_new_object(object_path)) - return False - - def _buddy_handle_joined_cb(self, object_path, handle): - _logger.debug('%r: buddy %s joined with handle %u', self, object_path, - handle) - gobject.idle_add(self._emit_buddy_joined_signal, object_path) - self._handle_to_buddy_path[handle] = object_path - self._buddy_path_to_handle[object_path] = handle - - def _emit_buddy_left_signal(self, object_path): - """Generate buddy-left GObject signal with presence Buddy object - - XXX note use of _ps_new_object instead of _ps_del_object here - """ - self.emit('buddy-left', self._ps_new_object(object_path)) - return False - - def _buddy_left_cb(self, object_path): - _logger.debug('%r: buddy %s left', self, object_path) - gobject.idle_add(self._emit_buddy_left_signal, object_path) - handle = self._buddy_path_to_handle.pop(object_path, None) - if handle: - self._handle_to_buddy_path.pop(handle, None) - - def _emit_new_channel_signal(self, object_path): - """Generate new-channel GObject signal with channel object path - - New telepathy-python communications channel has been opened - """ - self.emit('new-channel', object_path) - return False - - def _new_channel_cb(self, object_path): - _logger.debug('%r: new channel created at %s', self, object_path) - gobject.idle_add(self._emit_new_channel_signal, object_path) - - def get_joined_buddies(self): - """Retrieve the set of Buddy objects attached to this activity - - returns list of presence Buddy objects that we can successfully - create from the buddy object paths that PS has for this activity. - """ - resp = self._activity.GetJoinedBuddies() - buddies = [] - for item in resp: - try: - buddies.append(self._ps_new_object(item)) - except dbus.DBusException: - _logger.debug( - 'get_joined_buddies failed to get buddy object for %r', - item) - return buddies - - def get_buddy_by_handle(self, handle): - """Retrieve the Buddy object given a telepathy handle. - - buddy object paths are cached in self._handle_to_buddy_path, - so we can get the buddy without calling PS. - """ - object_path = self._handle_to_buddy_path.get(handle, None) - if object_path: - buddy = self._ps_new_object(object_path) - return buddy - return None - - def invite(self, buddy, message, response_cb): - """Invite the given buddy to join this activity. - - The callback will be called with one parameter: None on success, - or an exception on failure. - """ - op = buddy.object_path() - _logger.debug('%r: inviting %s', self, op) - self._activity.Invite(op, message, - reply_handler=lambda: response_cb(None), - error_handler=response_cb) - - # Joining and sharing (FIXME: sharing is actually done elsewhere) - - def set_up_tubes(self, reply_handler, error_handler): - - chans = [] - - def tubes_ready(): - if self.telepathy_text_chan is None or \ - self.telepathy_tubes_chan is None: - return - - _logger.debug('%r: finished setting up tubes', self) - reply_handler() - - def tubes_chan_ready(chan): - _logger.debug('%r: Tubes channel %r is ready', self, chan) - self.telepathy_tubes_chan = chan - tubes_ready() - - def text_chan_ready(chan): - _logger.debug('%r: Text channel %r is ready', self, chan) - self.telepathy_text_chan = chan - tubes_ready() - - def conn_ready(conn): - _logger.debug('%r: Connection %r is ready', self, conn) - self.telepathy_conn = conn - found_text_channel = False - found_tubes_channel = False - - for chan_path, chan_iface, handle_type, handle_ in chans: - if handle_type != telepathy.HANDLE_TYPE_ROOM: - return - - if chan_iface == telepathy.CHANNEL_TYPE_TEXT: - telepathy.client.Channel( - conn.service_name, chan_path, - ready_handler=text_chan_ready, - error_handler=error_handler) - found_text_channel = True - - elif chan_iface == telepathy.CHANNEL_TYPE_TUBES: - telepathy.client.Channel( - conn.service_name, chan_path, - ready_handler=tubes_chan_ready, - error_handler=error_handler) - found_tubes_channel = True - - if not found_text_channel: - error_handler(AssertionError("Presence Service didn't create " - "a chatroom")) - elif not found_tubes_channel: - error_handler(AssertionError("Presence Service didn't create " - "tubes channel")) - - def channels_listed(bus_name, conn_path, channels): - _logger.debug('%r: Connection on %s at %s, channels: %r', - self, bus_name, conn_path, channels) - - # can't use assignment for this due to Python scoping - chans.extend(channels) - - telepathy.client.Connection(bus_name, conn_path, - ready_handler=conn_ready, - error_handler=error_handler) - - - self._activity.ListChannels(reply_handler=channels_listed, - error_handler=error_handler) - - def _join_cb(self): - _logger.debug('%r: Join finished', self) - self._joined = True - self.emit("joined", True, None) - - def _join_error_cb(self, err): - _logger.debug('%r: Join failed because: %s', self, err) - self.emit("joined", False, str(err)) - - def join(self): - """Join this activity. - - Emits 'joined' and otherwise does nothing if we're already joined. - """ - if self._joined: - self.emit("joined", True, None) - return - - _logger.debug('%r: joining', self) - - def joined(): - self.set_up_tubes(reply_handler=self._join_cb, - error_handler=self._join_error_cb) - - self._activity.Join(reply_handler=joined, - error_handler=self._join_error_cb) - - # GetChannels() wrapper - - def get_channels(self): - """Retrieve communications channel descriptions for the activity - - Returns a tuple containing: - - the D-Bus well-known service name of the connection - (FIXME: this is redundant; in Telepathy it can be derived - from that of the connection) - - the D-Bus object path of the connection - - a list of D-Bus object paths representing the channels - associated with this activity - """ - (bus_name, connection, channels) = self._activity.GetChannels() - _logger.debug('%r: bus name is %s, connection is %s, channels are %r', - self, bus_name, connection, channels) - return bus_name, connection, channels - - # Leaving - - def _leave_cb(self): - """Callback for async action of leaving shared activity.""" - self.emit("joined", False, "left activity") - - def _leave_error_cb(self, err): - """Callback for error in async leaving of shared activity.""" - _logger.debug('Failed to leave activity: %s', err) - - def leave(self): - """Leave this shared activity""" - _logger.debug('%r: leaving', self) - self._joined = False - self._activity.Leave(reply_handler=self._leave_cb, - error_handler=self._leave_error_cb) -- cgit v0.9.1