diff options
author | Morgan Collett <morgan.collett@collabora.co.uk> | 2007-06-29 13:39:26 (GMT) |
---|---|---|
committer | Morgan Collett <morgan.collett@collabora.co.uk> | 2007-06-29 13:39:26 (GMT) |
commit | 2fd702e4272252ea8cc5cced95c4a88af12ce007 (patch) | |
tree | 4e45738dbf291be54dd48624ed9e8b7ef6994cb9 | |
parent | 33ce6546d7e2dede68e1b20a9dbfcf19eee1972b (diff) |
Implement communication over the Tube with a signal and a method
-rw-r--r-- | activity.py | 113 |
1 files changed, 107 insertions, 6 deletions
diff --git a/activity.py b/activity.py index 6b921dc..3ba6acf 100644 --- a/activity.py +++ b/activity.py @@ -22,10 +22,14 @@ import logging import telepathy import telepathy.client +from dbus import Interface +from dbus.service import method, signal +from dbus.gobject_service import ExportedGObject + from sugar.activity.activity import Activity, ActivityToolbox from sugar.presence import presenceservice -# will eventually be imported from telepathy.tubes or something +# will eventually be imported from sugar from tubeconn import TubeConnection SERVICE = "org.laptop.HelloMesh" @@ -61,13 +65,14 @@ class HelloMeshActivity(Activity): self.set_canvas(canvas) self.show_all() + self.hellotube = None + # get the Presence Service self.pservice = presenceservice.get_instance() name, path = self.pservice.get_preferred_connection() self.tp_conn_name = name self.tp_conn_path = path self.conn = telepathy.client.Connection(name, path) - self.initiating = None self.connect('shared', self._shared_cb) @@ -88,11 +93,11 @@ class HelloMeshActivity(Activity): def _shared_cb(self, activity): logger.debug('My activity was shared') - self.initiating = True self._setup() for buddy in self._shared_activity.get_joined_buddies(): - pass # Can do stuff with newly acquired buddies here + logger.debug('Buddy %s is already in the activity' % + buddy.props.nick) self._shared_activity.connect('buddy-joined', self._buddy_joined_cb) self._shared_activity.connect('buddy-left', self._buddy_left_cb) @@ -160,11 +165,11 @@ class HelloMeshActivity(Activity): if not self._shared_activity: return + # Find out who's already in the shared activity: for buddy in self._shared_activity.get_joined_buddies(): - pass # XXX do stuff with buddy + logger.debug('Buddy %s is already in the activity' % buddy.props.nick) logger.debug('Joined an existing shared activity') - self.initiating = False self._setup() logger.debug('This is not my activity: waiting for a tube...') @@ -185,9 +190,105 @@ class HelloMeshActivity(Activity): tube_conn = TubeConnection(self.conn, self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) + self.hellotube = HelloTube(tube_conn, self._get_buddy) def _buddy_joined_cb (self, activity, buddy): logger.debug('Buddy %s joined' % buddy.props.nick) def _buddy_left_cb (self, activity, buddy): logger.debug('Buddy %s left' % buddy.props.nick) + + def _get_buddy(self, cs_handle): + """Get a Buddy from a channel specific handle.""" + logger.debug('Trying to find owner of handle %u...', cs_handle) + group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP] + my_csh = group.GetSelfHandle() + logger.debug('My handle in that group is %u', my_csh) + if my_csh == cs_handle: + handle = self.conn.GetSelfHandle() + logger.debug('CS handle %u belongs to me, %u', cs_handle, handle) + else: + handle = group.GetHandleOwners([cs_handle])[0] + logger.debug('CS handle %u belongs to %u', cs_handle, handle) + + # XXX: deal with failure to get the handle owner + assert handle != 0 + + # XXX: we're assuming that we have Buddy objects for all contacts - + # this might break when the server becomes scalable. + return self.pservice.get_buddy_by_telepathy_handle(self.tp_conn_name, + self.tp_conn_path, handle) + +class HelloTube(ExportedGObject): + """The bit that talks over the TUBES!!!""" + + def __init__(self, tube, get_buddy): + self.tube = tube + self.entered = False # Have we set up the tube? + self.helloworld = False # Have we said Hello and received World? + self._get_buddy = get_buddy # Converts handle to Buddy object + self.tube.watch_participants(self.participant_change_cb) + + def participant_change_cb(self, added, removed): + logger.debug('Adding participants: %r' % added) + logger.debug('Removing participants: %r' % removed) + + for handle, bus_name in added: + buddy = self._get_buddy(handle) + if buddy is not None: + logger.debug('Buddy %s was added' % buddy.props.nick) + + for handle in removed: + buddy = self._get_buddy(handle) + if buddy is not None: + logger.debug('Buddy %s was removed' % buddy.props.nick) + # Do activity logic with new or removed buddies + + if not self.entered: + self.tube.add_signal_receiver(self.insert_cb, 'Insert', IFACE, + path=PATH, sender_keyword='sender') + if self.is_initiator: + _logger.debug('I am the initiator, so making myself player 0') + self.add_hello_handler() + self.ordered_bus_names = [self.tube.get_unique_name()] + self.player_id = 0 + self.buddies_panel.add_player(self.owner) + else: + _logger.debug('Hello, everyone! What did I miss?') + self.Hello() + self.entered = True + + @signal(dbus_interface=IFACE, signature='') + def Hello(self): + """Say Hello to whoever else is in the tube.""" + _logger.debug('I said Hello.') + + @method(dbus_interface=IFACE, in_signature='as', out_signature='') + def World(self, name): + """To be called on the incoming XO after they Hello.""" + if not self.helloworld: + _logger.debug('%s said World.') + # now I can World others + self.add_hello_handler() + + #buddy = self._get_buddy(self.tube.bus_name_to_handle[bus_names[0]]) + else: + _logger.debug("I've already been welcomed, doing nothing") + + def add_hello_handler(self): + self.tube.add_signal_receiver(self.hello_cb, 'Hello', IFACE, + path=PATH, sender_keyword='sender') + + def hello_cb(self, sender=None): + """Somebody Helloed me. World them.""" + _logger.debug('Newcomer %s has joined', sender) + self.ordered_bus_names.append(sender) + if len(self.ordered_bus_names) == 2: + buddy = self._get_buddy(self.tube.bus_name_to_handle[sender]) + self.buddies_panel.add_player(buddy) + _logger.debug('Bus names are now: %r', self.ordered_bus_names) + _logger.debug('Welcoming newcomer and sending them the game state') + self.tube.get_object(sender, PATH).World(self.ordered_bus_names, + dbus_interface=IFACE) + + |