Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu.vizoso@collabora.co.uk>2010-06-22 14:31:21 (GMT)
committer Tomeu Vizoso <tomeu.vizoso@collabora.co.uk>2010-08-20 13:33:52 (GMT)
commit98cc77f1fb35ae0c0e44a27dc389248b8024bba7 (patch)
treee91674e18a1f142069f51453a4708f7f6b2c687a
parentd6da506dfdd8dbfa2e6baf145d4bb62dbb5b73cc (diff)
Replace enough of the old PS so we can join an activity instance on the network.
* src/sugar/activity/activity.py: Get the shared activity wrapper from sugar.presence. * src/sugar/activity/activityfactory.py: Disable checking in the PS for activity_id duplicates. * src/sugar/presence/activity.py: Remove the PS dependency and query Telepathy directly. Implemented enough to join an activity. * src/sugar/presence/buddy.py: Remove the PS dependency and query Telepathy directly. Implemented enough to join an activity. Added an Owner subclass of Buddy() * src/sugar/presence/presenceservice.py: Remove the PS dependency and query Telepathy directly. Implemented enough to join an activity. * src/sugar/presence/util.py: Add ConnectionManager for discovering and tracking connections.
-rw-r--r--src/sugar/activity/activity.py7
-rw-r--r--src/sugar/activity/activityfactory.py3
-rw-r--r--src/sugar/presence/activity.py176
-rw-r--r--src/sugar/presence/buddy.py257
-rw-r--r--src/sugar/presence/presenceservice.py167
5 files changed, 279 insertions, 331 deletions
diff --git a/src/sugar/activity/activity.py b/src/sugar/activity/activity.py
index 0e2ecc5..20c9c7d 100644
--- a/src/sugar/activity/activity.py
+++ b/src/sugar/activity/activity.py
@@ -70,6 +70,7 @@ from sugar.graphics.alert import Alert
from sugar.graphics.icon import Icon
from sugar.datastore import datastore
from sugar.session import XSMPClient
+from sugar.presence import presenceservice
from sugar import wm
# support deprecated imports
@@ -266,7 +267,6 @@ class Activity(Window, gtk.Container):
self._active = False
self._activity_id = handle.activity_id
- self._pservice = presenceservice.get_instance()
self.shared_activity = None
self._share_id = None
self._join_id = None
@@ -302,8 +302,9 @@ class Activity(Window, gtk.Container):
share_scope = self._jobject.metadata['share-scope']
# handle activity share/join
- mesh_instance = self._pservice.get_activity(self._activity_id,
- warn_if_none=False)
+ pservice = presenceservice.get_instance()
+ mesh_instance = pservice.get_activity(self._activity_id,
+ warn_if_none=False)
logging.debug("*** Act %s, mesh instance %r, scope %s",
self._activity_id, mesh_instance, share_scope)
if mesh_instance is not None:
diff --git a/src/sugar/activity/activityfactory.py b/src/sugar/activity/activityfactory.py
index 6b4ba32..0dd3793 100644
--- a/src/sugar/activity/activityfactory.py
+++ b/src/sugar/activity/activityfactory.py
@@ -75,11 +75,14 @@ def create_activity_id():
# check through network activities
found = False
+ logging.info('KILL_PS check the activity_id is not used in the network')
+ """
activities = pservice.get_activities()
for act in activities:
if act_id == act.props.id:
found = True
break
+ """
if not found:
return act_id
raise RuntimeError("Cannot generate unique activity id.")
diff --git a/src/sugar/presence/activity.py b/src/sugar/presence/activity.py
index 1d4a9c9..617409f 100644
--- a/src/sugar/presence/activity.py
+++ b/src/sugar/presence/activity.py
@@ -25,7 +25,14 @@ import logging
import dbus
import gobject
import telepathy
+from telepathy.client import Channel
+from telepathy.interfaces import CHANNEL, \
+ CHANNEL_TYPE_TUBES, \
+ CHANNEL_TYPE_TEXT, \
+ CONNECTION
+from telepathy.constants import HANDLE_TYPE_ROOM
+CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties'
_logger = logging.getLogger('sugar.presence.activity')
@@ -64,34 +71,14 @@ class Activity(gobject.GObject):
'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"""
+ def __init__(self, connection, room_handle):
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.telepathy_conn = connection
+ self.telepathy_text_chan = None
+ self.telepathy_tubes_chan = None
+
+ self._room_handle = room_handle
self._id = None
self._color = None
self._name = None
@@ -99,31 +86,32 @@ class Activity(gobject.GObject):
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 ('<proxy for %s at %x>' % (self._object_path, id(self)))
- def _get_properties_reply_cb(self, new_props):
+ bus = dbus.SessionBus()
+ self._get_properties_call = bus.call_async(
+ connection.requested_bus_name,
+ connection.object_path,
+ CONN_INTERFACE_ACTIVITY_PROPERTIES,
+ 'GetProperties',
+ 'u',
+ (self._room_handle,),
+ reply_handler=self._got_properties_cb,
+ error_handler=self._error_handler_cb,
+ utf8_strings=True)
+
+ def _got_properties_cb(self, properties):
+ _logger.debug('_got_properties_cb', properties)
self._get_properties_call = None
- _logger.debug('%r: initial GetProperties returned', self)
- self._properties_changed_cb(new_props)
+ self._update_properties(properties)
- 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 _error_handler_cb(self, error):
+ _logger.debug('_error_handler_cb', error)
def _properties_changed_cb(self, new_props):
_logger.debug('%r: Activity properties changed to %r', self, new_props)
+ self._update_properties(new_props)
+
+ def _update_properties(self, new_props):
val = new_props.get('name', self._name)
if isinstance(val, str) and val != self._name:
self._name = val
@@ -244,16 +232,8 @@ class Activity(gobject.GObject):
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
+ logging.info('KILL_PS return joined buddies')
+ return []
def get_buddy_by_handle(self, handle):
"""Retrieve the Buddy object given a telepathy handle.
@@ -293,62 +273,38 @@ class Activity(gobject.GObject):
_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
+ def tubes_channel_ready_cb(channel):
+ _logger.debug('%r: Tubes channel %r is ready', self, channel)
+ self.telepathy_tubes_chan = channel
tubes_ready()
- def text_chan_ready(chan):
- _logger.debug('%r: Text channel %r is ready', self, chan)
- self.telepathy_text_chan = chan
+ def text_channel_ready_cb(channel):
+ _logger.debug('%r: Text channel %r is ready', self, channel)
+ self.telepathy_text_chan = channel
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
- self.telepathy_room_handle = handle
-
- 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 create_text_channel_cb(channel_path):
+ Channel(self.telepathy_conn.requested_bus_name, channel_path,
+ ready_handler=text_channel_ready_cb)
+
+ def create_tubes_channel_cb(channel_path):
+ Channel(self.telepathy_conn.requested_bus_name, channel_path,
+ ready_handler=tubes_channel_ready_cb)
+
+ def error_handler_cb(error):
+ raise RuntimeError(error)
+
+ self.telepathy_conn.RequestChannel(CHANNEL_TYPE_TEXT,
+ HANDLE_TYPE_ROOM, self._room_handle, True,
+ reply_handler=create_text_channel_cb,
+ error_handler=error_handler_cb,
+ dbus_interface=CONNECTION)
+
+ self.telepathy_conn.RequestChannel(CHANNEL_TYPE_TUBES,
+ HANDLE_TYPE_ROOM, self._room_handle, True,
+ reply_handler=create_tubes_channel_cb,
+ error_handler=error_handler_cb,
+ dbus_interface=CONNECTION)
def _join_cb(self):
_logger.debug('%r: Join finished', self)
@@ -370,11 +326,7 @@ class Activity(gobject.GObject):
_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,
+ self.set_up_tubes(reply_handler=self._join_cb,
error_handler=self._join_error_cb)
# GetChannels() wrapper
diff --git a/src/sugar/presence/buddy.py b/src/sugar/presence/buddy.py
index 2978e4d..4722485 100644
--- a/src/sugar/presence/buddy.py
+++ b/src/sugar/presence/buddy.py
@@ -20,12 +20,21 @@
STABLE.
"""
+import logging
+
import gobject
import gtk
import dbus
+import gconf
+from telepathy.interfaces import CONNECTION_INTERFACE_ALIASING, \
+ CONNECTION_INTERFACE_CONTACTS
+
+CONN_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo'
+
+_logger = logging.getLogger('sugar.presence.buddy')
-class Buddy(gobject.GObject):
+class BaseBuddy(gobject.GObject):
"""UI interface for a Buddy in the presence service
Each buddy interface tracks a set of activities and properties
@@ -42,6 +51,8 @@ class Buddy(gobject.GObject):
See __gproperties__
"""
+ __gtype_name__ = 'PresenceBaseBuddy'
+
__gsignals__ = {
'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])),
'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
@@ -52,53 +63,17 @@ class Buddy(gobject.GObject):
([gobject.TYPE_PYOBJECT])),
}
- __gproperties__ = {
- 'key': (str, None, None, None, gobject.PARAM_READABLE),
- 'icon': (str, None, None, None, gobject.PARAM_READABLE),
- 'nick': (str, None, None, None, gobject.PARAM_READABLE),
- 'color': (str, None, None, None, gobject.PARAM_READABLE),
- 'current-activity': (object, None, None, gobject.PARAM_READABLE),
- 'owner': (bool, None, None, False, gobject.PARAM_READABLE),
- 'ip4-address': (str, None, None, None, gobject.PARAM_READABLE),
- 'tags': (str, None, None, None, gobject.PARAM_READABLE),
- }
-
- _PRESENCE_SERVICE = "org.laptop.Sugar.Presence"
- _BUDDY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Buddy"
-
- def __init__(self, bus, new_obj_cb, del_obj_cb, object_path):
- """Initialise the reference to the buddy
-
- bus -- dbus bus object
- new_obj_cb -- callback to call when this buddy joins an activity
- del_obj_cb -- callback to call when this buddy leaves an activity
- object_path -- path to the buddy object
- """
+ def __init__(self):
gobject.GObject.__init__(self)
- self._object_path = object_path
- self._ps_new_object = new_obj_cb
- self._ps_del_object = del_obj_cb
- self._properties = {}
- self._activities = {}
-
- bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
- self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE)
-
- self._icon_changed_signal = self._buddy.connect_to_signal(
- 'IconChanged', self._icon_changed_cb, byte_arrays=True)
- self._joined_activity_signal = self._buddy.connect_to_signal(
- 'JoinedActivity', self._joined_activity_cb)
- self._left_activity_signal = self._buddy.connect_to_signal(
- 'LeftActivity', self._left_activity_cb)
- self._property_changed_signal = self._buddy.connect_to_signal(
- 'PropertyChanged', self._property_changed_cb)
-
- self._properties = self._get_properties_helper()
- activities = self._buddy.GetJoinedActivities()
- for op in activities:
- self._activities[op] = self._ps_new_object(op)
+ self._key = None
self._icon = None
+ self._nick = None
+ self._color = None
+ self._current_activity = None
+ self._owner = False
+ self._ip4_address = None
+ self._tags = None
def destroy(self):
self._icon_changed_signal.remove()
@@ -114,41 +89,68 @@ class Buddy(gobject.GObject):
return {}
return props
- def do_get_property(self, pspec):
- """Retrieve a particular property from our property dictionary
+ def get_key(self):
+ return self._key
- pspec -- XXX some sort of GTK specifier object with attributes
- including 'name', 'active' and 'icon-name'
- """
- if pspec.name == "key":
- return self._properties["key"]
- elif pspec.name == "nick":
- return self._properties["nick"]
- elif pspec.name == "color":
- return self._properties["color"]
- elif pspec.name == "tags":
- return self._properties["tags"]
- elif pspec.name == "current-activity":
- if not self._properties.has_key("current-activity"):
- return None
- curact = self._properties["current-activity"]
- if not len(curact):
- return None
- for activity in self._activities.values():
- if activity.props.id == curact:
- return activity
+ def set_key(self, key):
+ self._key = key
+
+ key = gobject.property(type=str, getter=get_key, setter=set_key)
+
+ def get_icon(self):
+ raise NotImplementedError()
+
+ icon = gobject.property(type=str, getter=get_icon)
+
+ def get_nick(self):
+ return self._nick
+
+ def set_nick(self, nick):
+ self._nick = nick
+
+ nick = gobject.property(type=str, getter=get_nick, setter=set_nick)
+
+ def get_color(self):
+ return self._color
+
+ def set_color(self, color):
+ self._color = color
+
+ color = gobject.property(type=str, getter=get_color, setter=set_color)
+
+ def get_current_activity(self):
+ if self._current_activity is None:
return None
- elif pspec.name == "owner":
- return self._properties["owner"]
- elif pspec.name == "icon":
- if not self._icon:
- self._icon = str(self._buddy.GetIcon(byte_arrays=True))
- return self._icon
- elif pspec.name == "ip4-address":
- # IPv4 address will go away quite soon
- if not self._properties.has_key("ip4-address"):
- return None
- return self._properties["ip4-address"]
+ for activity in self._activities.values():
+ if activity.props.id == self._current_activity:
+ return activity
+ return None
+
+ current_activity = gobject.property(type=object, getter=get_current_activity)
+
+ def get_owner(self):
+ return self._owner
+
+ def set_owner(self, owner):
+ self._owner = owner
+
+ owner = gobject.property(type=bool, getter=get_owner, setter=set_owner, default=False)
+
+ def get_ip4_address(self):
+ return self._ip4_address
+
+ def set_ip4_address(self, ip4_address):
+ self._ip4_address = ip4_address
+
+ ip4_address = gobject.property(type=str, getter=get_ip4_address, setter=set_ip4_address)
+
+ def get_tags(self):
+ return self._tags
+
+ def set_tags(self, tags):
+ self._tags = tags
+
+ tags = gobject.property(type=str, getter=get_tags, setter=set_tags)
def object_path(self):
"""Retrieve our dbus object path"""
@@ -160,16 +162,16 @@ class Buddy(gobject.GObject):
self.emit('icon-changed')
return False
- def _icon_changed_cb(self, icon_data):
+ def __icon_changed_cb(self, icon_data):
"""Handle dbus signal by emitting a GObject signal"""
gobject.idle_add(self._emit_icon_changed_signal, icon_data)
- def _emit_joined_activity_signal(self, object_path):
+ def __emit_joined_activity_signal(self, object_path):
"""Emit activity joined signal with Activity object"""
self.emit('joined-activity', self._ps_new_object(object_path))
return False
- def _joined_activity_cb(self, object_path):
+ def __joined_activity_cb(self, object_path):
"""Handle dbus signal by emitting a GObject signal
Stores the activity in activities dictionary as well
@@ -187,7 +189,7 @@ class Buddy(gobject.GObject):
self.emit('left-activity', self._ps_new_object(object_path))
return False
- def _left_activity_cb(self, object_path):
+ def __left_activity_cb(self, object_path):
"""Handle dbus signal by emitting a GObject signal
Also removes from the activities dictionary
@@ -207,7 +209,7 @@ class Buddy(gobject.GObject):
self.emit('property-changed', prop_list)
return False
- def _property_changed_cb(self, prop_list):
+ def __property_changed_cb(self, prop_list):
"""Handle dbus signal by emitting a GObject signal"""
gobject.idle_add(self._handle_property_changed_signal, prop_list)
@@ -241,3 +243,92 @@ class Buddy(gobject.GObject):
for item in resp:
acts.append(self._ps_new_object(item))
return acts
+
+
+class Buddy(BaseBuddy):
+ __gtype_name__ = 'PresenceBuddy'
+ def __init__(self, connection, contact_handle):
+ BaseBuddy.__init__(self)
+
+ self._contact_handle = contact_handle
+
+ bus = dbus.SessionBus()
+ self._get_properties_call = bus.call_async(
+ connection.requested_bus_name,
+ connection.object_path,
+ CONN_INTERFACE_BUDDY_INFO,
+ 'GetProperties',
+ 'u',
+ (self._contact_handle,),
+ reply_handler=self.__got_properties_cb,
+ error_handler=self.__error_handler_cb,
+ utf8_strings=True,
+ byte_arrays=True)
+
+ self._get_attributes_call = bus.call_async(
+ connection.requested_bus_name,
+ connection.object_path,
+ CONNECTION_INTERFACE_CONTACTS,
+ 'GetContactAttributes',
+ 'auasb',
+ ([self._contact_handle], [CONNECTION_INTERFACE_ALIASING], False),
+ reply_handler=self.__got_attributes_cb,
+ error_handler=self.__error_handler_cb)
+
+ def __got_properties_cb(self, properties):
+ _logger.debug('__got_properties_cb', properties)
+ self._get_properties_call = None
+ self._update_properties(properties)
+
+ def __got_attributes_cb(self, attributes):
+ _logger.debug('__got_attributes_cb', attributes)
+ self._get_attributes_call = None
+ self._update_attributes(attributes[self._contact_handle])
+
+ def __error_handler_cb(self, error):
+ _logger.debug('__error_handler_cb', error)
+
+ def __properties_changed_cb(self, new_props):
+ _logger.debug('%r: Buddy properties changed to %r', self, new_props)
+ self._update_properties(new_props)
+
+ def _update_properties(self, properties):
+ if 'key' in properties:
+ self.props.key = properties['key']
+ if 'icon' in properties:
+ self.props.icon = properties['icon']
+ if 'color' in properties:
+ self.props.color = properties['color']
+ if 'current-activity' in properties:
+ self.props.current_activity = properties['current-activity']
+ if 'owner' in properties:
+ self.props.owner = properties['owner']
+ if 'ip4-address' in properties:
+ self.props.ip4_address = properties['ip4-address']
+ if 'tags' in properties:
+ self.props.tags = properties['tags']
+
+ def _update_attributes(self, attributes):
+ nick_key = CONNECTION_INTERFACE_ALIASING + '/alias'
+ if nick_key in attributes:
+ self.props.nick = attributes[nick_key]
+
+ def do_get_property(self, pspec):
+ 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()
+
+ return BaseBuddy.do_get_property(self, pspec)
+
+
+class Owner(BaseBuddy):
+
+ __gtype_name__ = 'PresenceOwner'
+
+ def __init__(self):
+ BaseBuddy.__init__(self)
+
+ client = gconf.client_get_default()
+ self.props.nick = client.get_string("/desktop/sugar/user/nick")
+ self.props.color = client.get_string("/desktop/sugar/user/color")
diff --git a/src/sugar/presence/presenceservice.py b/src/sugar/presence/presenceservice.py
index f4aa6df..0b94924 100644
--- a/src/sugar/presence/presenceservice.py
+++ b/src/sugar/presence/presenceservice.py
@@ -23,19 +23,16 @@ STABLE.
import logging
import traceback
+import gobject
import dbus
import dbus.exceptions
import dbus.glib
-import gobject
-from sugar.presence.buddy import Buddy
+from sugar.presence.buddy import Buddy, Owner
from sugar.presence.activity import Activity
+from sugar.presence.util import get_connection_manager
-DBUS_SERVICE = "org.laptop.Sugar.Presence"
-DBUS_INTERFACE = "org.laptop.Sugar.Presence"
-DBUS_PATH = "/org/laptop/Sugar/Presence"
-
_logger = logging.getLogger('sugar.presence.presenceservice')
@@ -66,92 +63,12 @@ class PresenceService(gobject.GObject):
gobject.TYPE_PYOBJECT])),
}
- _PS_BUDDY_OP = DBUS_PATH + "/Buddies/"
- _PS_ACTIVITY_OP = DBUS_PATH + "/Activities/"
-
- def __init__(self, allow_offline_iface=True):
+ def __init__(self):
"""Initialise the service and attempt to connect to events
"""
gobject.GObject.__init__(self)
- self._objcache = {}
- self._joined = None
-
- # Get a connection to the session bus
- self._bus = dbus.SessionBus()
- self._bus.add_signal_receiver(self._name_owner_changed_cb,
- signal_name="NameOwnerChanged",
- dbus_interface="org.freedesktop.DBus")
-
- # attempt to load the interface to the service...
- self._allow_offline_iface = allow_offline_iface
- self._get_ps()
-
- def _name_owner_changed_cb(self, name, old, new):
- if name != DBUS_SERVICE:
- return
- if (old and len(old)) and (not new and not len(new)):
- # PS went away, clear out PS dbus service wrapper
- self._ps_ = None
- elif (not old and not len(old)) and (new and len(new)):
- # PS started up
- self._get_ps()
-
- _ps_ = None
- def _get_ps(self):
- """Retrieve dbus interface to PresenceService
-
- Also registers for updates from various dbus events on the
- interface.
-
- If unable to retrieve the interface, we will temporarily
- return an _OfflineInterface object to allow the calling
- code to continue functioning as though it had accessed a
- real presence service.
-
- If successful, caches the presence service interface
- for use by other methods and returns that interface
- """
- if not self._ps_:
- try:
- # NOTE: We need to follow_name_owner_changes here
- # because we can not connect to a signal unless
- # we follow the changes or we start the service
- # before we connect. Starting the service here
- # causes a major bottleneck during startup
- ps = dbus.Interface(
- self._bus.get_object(DBUS_SERVICE,
- DBUS_PATH,
- follow_name_owner_changes=True),
- DBUS_INTERFACE)
- except dbus.exceptions.DBusException, err:
- _logger.error(
- """Failure retrieving %r interface from
- the D-BUS service %r %r: %s""",
- DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err)
- if self._allow_offline_iface:
- return _OfflineInterface()
- raise RuntimeError('Failed to connect to the presence '
- 'service.')
- else:
- self._ps_ = ps
- ps.connect_to_signal('BuddyAppeared',
- self._buddy_appeared_cb)
- ps.connect_to_signal('BuddyDisappeared',
- self._buddy_disappeared_cb)
- ps.connect_to_signal('ActivityAppeared',
- self._activity_appeared_cb)
- ps.connect_to_signal('ActivityDisappeared',
- self._activity_disappeared_cb)
- ps.connect_to_signal('ActivityInvitation',
- self._activity_invitation_cb)
- ps.connect_to_signal('PrivateInvitation',
- self._private_invitation_cb)
- return self._ps_
-
- _ps = property(_get_ps, None, None,
- """DBUS interface to the PresenceService
- (services/presence/presenceservice)""")
+ self._buddy_cache = {}
def _new_object(self, object_path):
"""Turn new object path into (cached) Buddy/Activity instance
@@ -289,17 +206,11 @@ class PresenceService(gobject.GObject):
returns list of Activity objects for all object paths
the service reports exist (using GetActivities)
"""
- try:
- resp = self._ps.GetActivities()
- except dbus.exceptions.DBusException:
- _logger.exception('Unable to retrieve activity list from '
- 'presence service')
- return []
- else:
- acts = []
- for item in resp:
- acts.append(self._new_object(item))
- return acts
+ resp = self._ps.GetActivities()
+ acts = []
+ for item in resp:
+ acts.append(self._new_object(item))
+ return acts
def _get_activities_cb(self, reply_handler, resp):
acts = []
@@ -338,14 +249,14 @@ class PresenceService(gobject.GObject):
returns single Activity object or None if the activity
is not found using GetActivityById on the service
"""
- try:
- act_op = self._ps.GetActivityById(activity_id)
- except dbus.exceptions.DBusException, err:
- if warn_if_none:
- _logger.warn("Unable to retrieve activity handle for %r from "
- "presence service: %s", activity_id, err)
- return None
- return self._new_object(act_op)
+ for connection in get_connection_manager().connections:
+ try:
+ room_handle = connection.GetActivity(activity_id)
+ return Activity(connection, room_handle)
+ except:
+ pass
+
+ return None
def get_buddies(self):
"""Retrieve set of all buddies from service
@@ -426,26 +337,19 @@ class PresenceService(gobject.GObject):
channel-specific handle.
:Returns: the Buddy object, or None if the buddy is not found
"""
- try:
- buddy_op = self._ps.GetBuddyByTelepathyHandle(tp_conn_name,
- tp_conn_path,
- handle)
- except dbus.exceptions.DBusException, err:
- _logger.warn('Unable to retrieve buddy handle for handle %u at '
- 'conn %s:%s from presence service: %s',
- handle, tp_conn_name, tp_conn_path, err)
- return None
- return self._new_object(buddy_op)
+ logging.info('KILL_PS decide how to invalidate this cache')
+ if (tp_conn_path, handle) in self._buddy_cache:
+ return self._buddy_cache[(tp_conn_path, handle)]
+ else:
+ bus = dbus.SessionBus()
+ connection = bus.get_object(tp_conn_name, tp_conn_path)
+ buddy = Buddy(connection, handle)
+ self._buddy_cache[(tp_conn_path, handle)] = buddy
+ return buddy
def get_owner(self):
- """Retrieves the laptop "owner" Buddy object."""
- try:
- owner_op = self._ps.GetOwner()
- except dbus.exceptions.DBusException:
- _logger.exception('Unable to retrieve local user/owner from '
- 'presence service')
- raise RuntimeError("Could not get owner object.")
- return self._new_object(owner_op)
+ """Retrieves the laptop Buddy object."""
+ return Owner()
def _share_activity_cb(self, activity, op):
"""Finish sharing the activity
@@ -505,14 +409,11 @@ class PresenceService(gobject.GObject):
should use when talking directly to telepathy
returns the bus name and the object path of the Telepathy connection"""
-
- try:
- bus_name, object_path = self._ps.GetPreferredConnection()
- except dbus.exceptions.DBusException:
- logging.error(traceback.format_exc())
+ connection = get_connection_manager().get_preferred_connection()
+ if connection is None:
return None
-
- return bus_name, object_path
+ else:
+ return connection.requested_bus_name, connection.object_path
class _OfflineInterface(object):
@@ -596,5 +497,5 @@ def get_instance(allow_offline_iface=False):
"""Retrieve this process' view of the PresenceService"""
global _ps
if not _ps:
- _ps = PresenceService(allow_offline_iface)
+ _ps = PresenceService()
return _ps