Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/collaboration/presenceservice.py
diff options
context:
space:
mode:
Diffstat (limited to 'collaboration/presenceservice.py')
-rw-r--r--collaboration/presenceservice.py266
1 files changed, 266 insertions, 0 deletions
diff --git a/collaboration/presenceservice.py b/collaboration/presenceservice.py
new file mode 100644
index 0000000..b6c581e
--- /dev/null
+++ b/collaboration/presenceservice.py
@@ -0,0 +1,266 @@
+# Copyright (C) 2007, Red Hat, Inc.
+# Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# 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.
+
+"""
+STABLE.
+"""
+
+import logging
+
+import gobject
+import dbus
+import dbus.exceptions
+import dbus.glib
+from dbus import PROPERTIES_IFACE
+
+from sugar.presence.buddy import Buddy, Owner
+from sugar.presence.activity import Activity
+from sugar.presence.connectionmanager import get_connection_manager
+
+from telepathy.interfaces import ACCOUNT, \
+ ACCOUNT_MANAGER, \
+ CONNECTION
+from telepathy.constants import HANDLE_TYPE_CONTACT
+
+
+_logger = logging.getLogger('sugar.presence.presenceservice')
+
+ACCOUNT_MANAGER_SERVICE = 'org.freedesktop.Telepathy.AccountManager'
+ACCOUNT_MANAGER_PATH = '/org/freedesktop/Telepathy/AccountManager'
+
+CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties'
+
+
+class PresenceService(gobject.GObject):
+ """Provides simplified access to the Telepathy framework to activities"""
+ __gsignals__ = {
+ 'activity-shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
+ gobject.TYPE_PYOBJECT])),
+ }
+
+ def __init__(self):
+ """Initialise the service and attempt to connect to events
+ """
+ gobject.GObject.__init__(self)
+
+ self._activity_cache = None
+ self._buddy_cache = {}
+
+ def get_activity(self, activity_id, warn_if_none=True):
+ """Retrieve single Activity object for the given unique id
+
+ activity_id -- unique ID for the activity
+
+ returns single Activity object or None if the activity
+ is not found using GetActivityById on the service
+ """
+ if self._activity_cache is not None:
+ if self._activity_cache.props.id != activity_id:
+ raise RuntimeError('Activities can only access their own'
+ ' shared instance')
+ return self._activity_cache
+ else:
+ connection_manager = get_connection_manager()
+ connections_per_account = \
+ connection_manager.get_connections_per_account()
+ for account_path, connection in connections_per_account.items():
+ if not connection.connected:
+ continue
+ logging.debug('Calling GetActivity on %s', account_path)
+ try:
+ room_handle = connection.connection.GetActivity(
+ activity_id,
+ dbus_interface=CONN_INTERFACE_ACTIVITY_PROPERTIES)
+ except dbus.exceptions.DBusException, e:
+ name = 'org.freedesktop.Telepathy.Error.NotAvailable'
+ if e.get_dbus_name() == name:
+ logging.debug("There's no shared activity with the id "
+ "%s", activity_id)
+ else:
+ raise
+ else:
+ activity = Activity(account_path, connection.connection,
+ room_handle=room_handle)
+ self._activity_cache = activity
+ return activity
+
+ return None
+
+ def get_activity_by_handle(self, connection_path, room_handle):
+ if self._activity_cache is not None:
+ if self._activity_cache.room_handle != room_handle:
+ raise RuntimeError('Activities can only access their own'
+ ' shared instance')
+ return self._activity_cache
+ else:
+ connection_manager = get_connection_manager()
+ account_path = \
+ connection_manager.get_account_for_connection(connection_path)
+
+ connection_name = connection_path.replace('/', '.')[1:]
+ bus = dbus.SessionBus()
+ connection = bus.get_object(connection_name, connection_path)
+ activity = Activity(account_path, connection,
+ room_handle=room_handle)
+ self._activity_cache = activity
+ return activity
+
+ def get_buddy(self, account_path, contact_id):
+ if (account_path, contact_id) in self._buddy_cache:
+ return self._buddy_cache[(account_path, contact_id)]
+
+ buddy = Buddy(account_path, contact_id)
+ self._buddy_cache[(account_path, contact_id)] = buddy
+ return buddy
+
+ # DEPRECATED
+ def get_buddy_by_telepathy_handle(self, tp_conn_name, tp_conn_path,
+ handle):
+ """Retrieve single Buddy object for the given public key
+
+ :Parameters:
+ `tp_conn_name` : str
+ The well-known bus name of a Telepathy connection
+ `tp_conn_path` : dbus.ObjectPath
+ The object path of the Telepathy connection
+ `handle` : int or long
+ The handle of a Telepathy contact on that connection,
+ of type HANDLE_TYPE_CONTACT. This may not be a
+ channel-specific handle.
+ :Returns: the Buddy object, or None if the buddy is not found
+ """
+
+ bus = dbus.Bus()
+ obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, ACCOUNT_MANAGER_PATH)
+ account_manager = dbus.Interface(obj, ACCOUNT_MANAGER)
+ account_paths = account_manager.Get(ACCOUNT_MANAGER, 'ValidAccounts',
+ dbus_interface=PROPERTIES_IFACE)
+ for account_path in account_paths:
+ obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, account_path)
+ connection_path = obj.Get(ACCOUNT, 'Connection')
+ if connection_path == tp_conn_path:
+ connection_name = connection_path.replace('/', '.')[1:]
+ connection = bus.get_object(connection_name, connection_path)
+ contact_ids = connection.InspectHandles(HANDLE_TYPE_CONTACT,
+ [handle],
+ dbus_interface=CONNECTION)
+ return self.get_buddy(account_path, contact_ids[0])
+
+ raise ValueError('Unknown buddy in connection %s with handle %d',
+ tp_conn_path, handle)
+
+ def get_owner(self):
+ """Retrieves the laptop Buddy object."""
+ return Owner()
+
+ def __share_activity_cb(self, activity):
+ """Finish sharing the activity
+ """
+ self.emit('activity-shared', True, activity, None)
+
+ def __share_activity_error_cb(self, activity, error):
+ """Notify with GObject event of unsuccessful sharing of activity
+ """
+ self.emit('activity-shared', False, activity, error)
+
+ def share_activity(self, activity, properties=None, private=True):
+ if properties is None:
+ properties = {}
+
+ if 'id' not in properties:
+ properties['id'] = activity.get_id()
+
+ if 'type' not in properties:
+ properties['type'] = activity.get_bundle_id()
+
+ if 'name' not in properties:
+ properties['name'] = activity.metadata.get('title', None)
+
+ if 'color' not in properties:
+ properties['color'] = activity.metadata.get('icon-color', None)
+
+ properties['private'] = private
+
+ if self._activity_cache is not None:
+ raise ValueError('Activity %s is already tracked',
+ activity.get_id())
+
+ connection_manager = get_connection_manager()
+ account_path, connection = \
+ connection_manager.get_preferred_connection()
+
+ if connection is None:
+ self.emit('activity-shared', False, None,
+ 'No active connection available')
+ return
+
+ shared_activity = Activity(account_path, connection,
+ properties=properties)
+ self._activity_cache = shared_activity
+
+ if shared_activity.props.joined:
+ raise RuntimeError('Activity %s is already shared.' %
+ activity.props.id)
+
+ shared_activity.share(self.__share_activity_cb,
+ self.__share_activity_error_cb)
+
+ def get_preferred_connection(self):
+ """Gets the preferred telepathy connection object that an activity
+ should use when talking directly to telepathy
+
+ returns the bus name and the object path of the Telepathy connection
+ """
+ manager = get_connection_manager()
+ account_path, connection = manager.get_preferred_connection()
+ if connection is None:
+ return None
+ else:
+ return connection.requested_bus_name, connection.object_path
+
+ # DEPRECATED
+ def get(self, object_path):
+ raise NotImplementedError()
+
+ # DEPRECATED
+ def get_activities(self):
+ raise NotImplementedError()
+
+ # DEPRECATED
+ def get_activities_async(self, reply_handler=None, error_handler=None):
+ raise NotImplementedError()
+
+ # DEPRECATED
+ def get_buddies(self):
+ raise NotImplementedError()
+
+ # DEPRECATED
+ def get_buddies_async(self, reply_handler=None, error_handler=None):
+ raise NotImplementedError()
+
+
+_ps = None
+
+
+def get_instance(allow_offline_iface=False):
+ """Retrieve this process' view of the PresenceService"""
+ global _ps
+ if not _ps:
+ _ps = PresenceService()
+ return _ps