Some more patches to the Connect activity. These make it a proper shared activity.
From 684f3be93e064d6cd014e41d00df89b8c0092911 Mon Sep 17 00:00:00 2001 From: Simon McVittie <[EMAIL PROTECTED]> Date: Tue, 8 May 2007 15:12:12 +0100 Subject: [PATCH] gtkui.py: take responsibility for linking up the GLib main loop to dbus-python
---
gtkui.py | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/gtkui.py b/gtkui.py
index 8dd6edd..9711099 100644
--- a/gtkui.py
+++ b/gtkui.py
@@ -3,6 +3,7 @@ import sys
import logging
import dbus
+from dbus.mainloop.glib import DBusGMainLoop
import gtk
import telepathy
@@ -92,5 +93,5 @@ def main():
pass
if __name__ == '__main__':
+ dbus_main_loop = DBusGMainLoop(set_as_default=True)
main()
-
--
1.5.1.3
From ff890fe93a52fffc6df3b2d954d1959518c655ba Mon Sep 17 00:00:00 2001
From: Simon McVittie <[EMAIL PROTECTED]>
Date: Tue, 8 May 2007 15:14:51 +0100
Subject: [PATCH] client.py: Clean up some unused code. Move responsibility for participant tracking into ConnectGame
---
client.py | 33 +++------------------------------
1 files changed, 3 insertions(+), 30 deletions(-)
diff --git a/client.py b/client.py
index 8496481..f625e61 100644
--- a/client.py
+++ b/client.py
@@ -25,20 +25,8 @@ PATH = "/org/freedesktop/Telepathy/Tube/Connect"
ROOM = "[EMAIL PROTECTED]"
-dbus_main_loop = DBusGMainLoop(set_as_default=True)
-
-logging.basicConfig()
_logger = logging.getLogger('connect-activity.client')
-def print_dbus_message(msg):
- print 'got %s' % (msg.__class__.__name__)
- print ' sender: %r' % msg.get_sender()
- print ' destination: %r' % msg.get_destination()
- print ' path: %r' % msg.get_path()
- print ' interface %r' % msg.get_interface()
- print ' member %r' % msg.get_member()
- print ' args: %r' % msg.get_args_list()
-
def redraw(grid):
"""Utility function to force a redraw of a Gtk widget."""
grid.window.invalidate_rect(grid.get_allocation(), False)
@@ -56,6 +44,9 @@ class ConnectGame(Object):
def participant_change_cb(self, added, removed):
# Initiator is player 1, other player is player 2.
+ _logger.debug('adding participants: %r', added)
+ _logger.debug('removing participants: %r', removed)
+
if self.player_id is None:
if self.initiator == self.tube.self_handle:
self.player_id = 1
@@ -154,9 +145,6 @@ class ConnectClient:
self.conn = conn
self.grid = grid
self.game = None
- self.tubes_self_handle = 0
- self.pending_calls = {}
- self.player_id = 0
event_widget.connect('key-press-event', self.key_press_cb)
@@ -185,15 +173,11 @@ class ConnectClient:
current, lp, rp = map(lambda x: map(int, x),
text_chan[CHANNEL_INTERFACE_GROUP].GetAllMembers())
print 'activity members: %r, %r, %r' % (current, lp, rp)
- self.tubes_self_handle = text_chan[
- CHANNEL_INTERFACE_GROUP].GetSelfHandle()
tubes_chan = self.conn.request_channel(
CHANNEL_TYPE_TUBES, HANDLE_TYPE_ROOM, handle,
True)
tubes_chan[CHANNEL_TYPE_TUBES].connect_to_signal('NewTube',
self.new_tube_cb)
- tubes_chan[CHANNEL_TYPE_TUBES].connect_to_signal('DBusNamesChanged',
- self.dbus_names_changed_cb)
# XXX: this is racy. When we have the Presence Service's
# initiator/inviter semantics, we won't have this issue though
tube = self.find_tube(tubes_chan)
@@ -213,17 +197,6 @@ class ConnectClient:
SERVICE, {})
print 'found no tube; created tube %d' % id
- def dbus_names_changed_cb(self, tube_id, added, removed):
- print 'names changed:'
-
- if added:
- added = tuple([(int(x[0]), str(x[1])) for x in added])
- print ' added: %r' % added
-
- if removed:
- removed = tuple([int(x) for x in removed])
- print ' removed: %r' % removed
-
def find_tube(self, chan):
"Find a D-Bus tube in a tubes channel that provides our service."
--
1.5.1.3
From 099ca5a15aec89ba439abd44028840eac21dd233 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[EMAIL PROTECTED]>
Date: Tue, 8 May 2007 15:29:51 +0100
Subject: [PATCH] activity.py: Hook into Presence Service rather than using ConnectClient
---
activity.py | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 128 insertions(+), 5 deletions(-)
diff --git a/activity.py b/activity.py
index 57fa836..dc2ca60 100644
--- a/activity.py
+++ b/activity.py
@@ -1,27 +1,150 @@
+import logging
+from gettext import gettext as _
import dbus
+import gtk
import hippo
import telepathy
+import telepathy.client
-from sugar.activity.activity import Activity
+from sugar.activity.activity import Activity, ActivityToolbox
from sugar.presence import presenceservice
+import sugar.logger
import gridwidget
import client
+# will eventually be imported from telepathy.tubes or something
+from tubeconn import TubeConnection
+
+
+logger = logging.getLogger('connect-activity')
+
class ConnectActivity(Activity):
def __init__(self, handle):
Activity.__init__(self, handle)
- widget = gridwidget.GridWidget()
- self.set_canvas(widget)
+ logger.debug('Starting Connect activity...')
+
+ self.set_title(_('Connect Activity'))
+
+ self.grid = gridwidget.GridWidget()
+ self.set_canvas(self.grid)
self.show_all()
pservice = presenceservice.get_instance()
bus = dbus.Bus()
name, path = pservice.get_preferred_connection()
- conn = telepathy.client.Connection(name, path)
+ self.conn = telepathy.client.Connection(name, path)
+
+ self.game = None
+
+ toolbox = ActivityToolbox(self)
+ self.set_toolbox(toolbox)
+ toolbox.show()
+
+ self.connect('shared', self._shared_cb)
+
+ if self._shared_activity:
+ self.connect('joined', self._joined_cb)
+ if self.get_shared():
+ # oh, OK, we've already joined
+ self._joined_cb()
+
+ self.connect('key-press-event', self.key_press_cb)
+
+ def key_press_cb(self, widget, event):
+ if event.keyval in (gtk.keysyms.Escape, gtk.keysyms.q):
+ gtk.main_quit()
+
+ if self.game is not None:
+ self.game.key_press_event(widget, event)
+
+ def _shared_cb(self, activity):
+ logger.debug('My Connect activity was shared')
+ self._setup()
+
+ logger.debug('This is my activity: making a tube...')
+ id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferTube(
+ telepathy.TUBE_TYPE_DBUS, client.SERVICE, {})
+
+ # FIXME: presence service should be tubes-aware and give us more help
+ # with this
+ def _setup(self):
+ pservice = presenceservice.get_instance()
+ # There are too many things called Activity.
+ ps_activity = pservice.get_activity(self.get_id())
+ bus_name, conn_path, channel_paths = ps_activity.get_channels()
+
+ # Work out what our room is called and whether we have Tubes already
+ room = None
+ tubes_chan = None
+ text_chan = None
+ for channel_path in channel_paths:
+ channel = telepathy.client.Channel(bus_name, channel_path)
+ htype, handle = channel.GetHandle()
+ if htype == telepathy.HANDLE_TYPE_ROOM:
+ logger.debug('Found our room: it has handle#%d "%s"',
+ handle, self.conn.InspectHandles(htype, [handle])[0])
+ room = handle
+ ctype = channel.GetChannelType()
+ if ctype == telepathy.CHANNEL_TYPE_TUBES:
+ logger.debug('Found our Tubes channel at %s', channel_path)
+ tubes_chan = channel
+ elif ctype == telepathy.CHANNEL_TYPE_TEXT:
+ logger.debug('Found our Text channel at %s', channel_path)
+ text_chan = channel
+
+ if room is None:
+ logger.error("Presence service didn't create a room")
+ return
+ if text_chan is None:
+ logger.error("Presence service didn't create a text channel")
+ return
+
+ # Make sure we have a Tubes channel - PS doesn't yet provide one
+ if tubes_chan is None:
+ logger.debug("Didn't find our Tubes channel, requesting one...")
+ tubes_chan = self.conn.request_channel(telepathy.CHANNEL_TYPE_TUBES,
+ telepathy.HANDLE_TYPE_ROOM, room, True)
+
+ self.tubes_chan = tubes_chan
+ self.text_chan = text_chan
+
+ tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal('NewTube',
+ self._new_tube_cb)
+
+ def _list_tubes_reply_cb(self, tubes):
+ for tube_info in tubes:
+ self._new_tube_cb(*tube_info)
+
+ def _list_tubes_error_cb(self, e):
+ logger.error('ListTubes() failed: %s', e)
+
+ def _joined_cb(self, activity):
+ if self.game is not None:
+ return
+
+ logger.debug('Joined an existing Connect game')
+ self._setup()
+
+ logger.debug('This is not my activity: waiting for a tube...')
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
+ reply_handler=self._list_tubes_reply_cb,
+ error_handler=self._list_tubes_error_cb)
+
+ def _new_tube_cb(self, id, initiator, type, service, params, state):
+ logger.debug('New tube: ID=%d initator=%d type=%d service=%s '
+ 'params=%r state=%d', id, initiator, type, service,
+ params, state)
- client.ConnectClient(conn, self, widget)
+ if (self.game is None and type == telepathy.TUBE_TYPE_DBUS and
+ service == client.SERVICE):
+ if state == telepathy.TUBE_STATE_LOCAL_PENDING:
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptTube(id)
+ tube_conn = TubeConnection(self.conn,
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES],
+ id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP])
+ self.game = client.ConnectGame(tube_conn, self.grid, initiator)
--
1.5.1.3
From 00d4df40086977506778b7c966ee612d934d71b6 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[EMAIL PROTECTED]>
Date: Tue, 8 May 2007 15:39:50 +0100
Subject: [PATCH] Move ConnectGame to its own file game.py; activity no longer uses client.py
(it's only still here for the benefit of gtkui)
---
activity.py | 8 ++--
client.py | 122 +-------------------------------------------------------
game.py | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 134 insertions(+), 125 deletions(-)
create mode 100644 game.py
diff --git a/activity.py b/activity.py
index dc2ca60..b786dbe 100644
--- a/activity.py
+++ b/activity.py
@@ -12,7 +12,7 @@ from sugar.presence import presenceservice
import sugar.logger
import gridwidget
-import client
+from game import ConnectGame, SERVICE
# will eventually be imported from telepathy.tubes or something
from tubeconn import TubeConnection
@@ -67,7 +67,7 @@ class ConnectActivity(Activity):
logger.debug('This is my activity: making a tube...')
id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferTube(
- telepathy.TUBE_TYPE_DBUS, client.SERVICE, {})
+ telepathy.TUBE_TYPE_DBUS, SERVICE, {})
# FIXME: presence service should be tubes-aware and give us more help
# with this
@@ -140,11 +140,11 @@ class ConnectActivity(Activity):
params, state)
if (self.game is None and type == telepathy.TUBE_TYPE_DBUS and
- service == client.SERVICE):
+ service == SERVICE):
if state == telepathy.TUBE_STATE_LOCAL_PENDING:
self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptTube(id)
tube_conn = TubeConnection(self.conn,
self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES],
id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP])
- self.game = client.ConnectGame(tube_conn, self.grid, initiator)
+ self.game = ConnectGame(tube_conn, self.grid, initiator)
diff --git a/client.py b/client.py
index f625e61..710e078 100644
--- a/client.py
+++ b/client.py
@@ -1,12 +1,8 @@
import logging
-import pprint
import gtk
import telepathy
-from dbus import Interface
-from dbus.mainloop.glib import DBusGMainLoop
-from dbus.service import Object, method, signal
from telepathy.interfaces import CHANNEL_TYPE_TUBES, \
CHANNEL_TYPE_TEXT, CONN_INTERFACE, CHANNEL_INTERFACE_GROUP
@@ -14,131 +10,15 @@ from telepathy.constants import TUBE_TYPE_DBUS, \
TUBE_STATE_LOCAL_PENDING, TUBE_STATE_REMOTE_PENDING, TUBE_STATE_OPEN, \
CONNECTION_STATUS_CONNECTED, HANDLE_TYPE_ROOM
+from game import ConnectGame, SERVICE
# will eventually be imported from telepathy.tubes or something
from tubeconn import TubeConnection
-# XXX: I'm not convinced this is in the right namespace
-SERVICE = "org.freedesktop.Telepathy.Tube.Connect"
-IFACE = SERVICE
-PATH = "/org/freedesktop/Telepathy/Tube/Connect"
-
ROOM = "[EMAIL PROTECTED]"
_logger = logging.getLogger('connect-activity.client')
-def redraw(grid):
- """Utility function to force a redraw of a Gtk widget."""
- grid.window.invalidate_rect(grid.get_allocation(), False)
-
-class ConnectGame(Object):
- def __init__(self, tube, grid, initiator):
- super(ConnectGame, self).__init__(tube, PATH)
- self.tube = tube
- self.grid = grid
- self.initiator = initiator
- self.player_id = None
-
- self.tube.watch_participants(self.participant_change_cb)
-
- def participant_change_cb(self, added, removed):
- # Initiator is player 1, other player is player 2.
-
- _logger.debug('adding participants: %r', added)
- _logger.debug('removing participants: %r', removed)
-
- if self.player_id is None:
- if self.initiator == self.tube.self_handle:
- self.player_id = 1
- else:
- opponent = self.tube.get_object(
- self.tube.participants[self.initiator], PATH)
- self.opponent = Interface(opponent, IFACE)
- self.opponent.Hello(reply_handler=self.hello_cb,
- error_handler=self.error_cb)
- self.player_id = 2
- self.tube.add_signal_receiver(self.insert_cb, 'Insert', IFACE,
- path=PATH, sender_keyword='sender')
-
- print 'intiator: %d' % self.initiator
- print 'self: %d' % self.tube.self_handle
- print 'player ID: %d' % self.player_id
-
- def hello_cb(self, success):
- self.opponent.GetGrid(reply_handler=self.get_grid_cb,
- error_handler=self.error_cb)
-
- def get_grid_cb(self, grid):
- self.grid.grid = grid
- redraw(self.grid)
-
- def error_cb(self, e):
- _logger.error('Error connecting to opponent:\n%s', e)
-
- @method(dbus_interface=IFACE, in_signature='', out_signature='b')
- def Hello(self):
- self.grid.selected_column = 3
- redraw(self.grid)
- # XXX: return player ID too, to allow for swapping who goes first in
- # for second and later games
- return True
-
- @method(dbus_interface=IFACE, in_signature='', out_signature='aan')
- def GetGrid(self):
- return self.grid.grid
-
- @signal(dbus_interface=IFACE, signature='n')
- def Insert(self, column):
- assert column >= 0
- assert column < 7
-
- def insert_cb(self, column, sender=None):
- _logger.debug('Insert(%d) from %s', column, sender)
-
- if sender == self.tube.participants[self.tube.self_handle]:
- _logger.debug('Ignoring Insert signal from myself: %d', column)
- return
-
- if self.grid.insert(column, self.get_active_player()):
- if self.get_active_player() == self.player_id:
- _logger.debug('It\'s my turn now')
- # This should always be the case for 2 players, as we only get
- # this signal when the other player plays.
- self.grid.selected_column = 3
- redraw(self.grid)
-
- def get_active_player(self):
- count = {}
-
- for row in self.grid.grid:
- for player in row:
- if player != 0:
- count[player] = count.get(player, 0) + 1
-
- if count.get(1, 0) > count.get(2, 0):
- return 2
- else:
- return 1
-
- def key_press_event(self, widget, event):
- if self.grid.selected_column is None:
- return
-
- if event.keyval in (gtk.keysyms.Left,):
- if self.grid.selected_column > 0:
- self.grid.selected_column -= 1
- redraw(self.grid)
- elif event.keyval in (gtk.keysyms.Right,):
- if self.grid.selected_column < 6:
- self.grid.selected_column += 1
- redraw(self.grid)
- elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.space):
- if self.grid.insert(self.grid.selected_column, self.player_id):
- _logger.debug('Inserting at %d', self.grid.selected_column)
- redraw(self.grid)
- self.Insert(self.grid.selected_column)
- self.grid.selected_column = None
-
class ConnectClient:
def __init__(self, conn, event_widget, grid):
diff --git a/game.py b/game.py
new file mode 100644
index 0000000..3ed9e36
--- /dev/null
+++ b/game.py
@@ -0,0 +1,129 @@
+import logging
+
+import gtk
+
+from dbus import Interface
+from dbus.service import Object, method, signal
+
+
+# XXX: I'm not convinced this is in the right namespace
+SERVICE = "org.freedesktop.Telepathy.Tube.Connect"
+IFACE = SERVICE
+PATH = "/org/freedesktop/Telepathy/Tube/Connect"
+
+
+_logger = logging.getLogger('connect-activity.game')
+
+
+def redraw(grid):
+ """Utility function to force a redraw of a Gtk widget."""
+ grid.window.invalidate_rect(grid.get_allocation(), False)
+
+
+class ConnectGame(Object):
+ def __init__(self, tube, grid, initiator):
+ super(ConnectGame, self).__init__(tube, PATH)
+ self.tube = tube
+ self.grid = grid
+ self.initiator = initiator
+ self.player_id = None
+
+ self.tube.watch_participants(self.participant_change_cb)
+
+ def participant_change_cb(self, added, removed):
+ # Initiator is player 1, other player is player 2.
+
+ _logger.debug('adding participants: %r', added)
+ _logger.debug('removing participants: %r', removed)
+
+ if self.player_id is None:
+ if self.initiator == self.tube.self_handle:
+ self.player_id = 1
+ else:
+ opponent = self.tube.get_object(
+ self.tube.participants[self.initiator], PATH)
+ self.opponent = Interface(opponent, IFACE)
+ self.opponent.Hello(reply_handler=self.hello_cb,
+ error_handler=self.error_cb)
+ self.player_id = 2
+ self.tube.add_signal_receiver(self.insert_cb, 'Insert', IFACE,
+ path=PATH, sender_keyword='sender')
+
+ print 'intiator: %d' % self.initiator
+ print 'self: %d' % self.tube.self_handle
+ print 'player ID: %d' % self.player_id
+
+ def hello_cb(self, success):
+ self.opponent.GetGrid(reply_handler=self.get_grid_cb,
+ error_handler=self.error_cb)
+
+ def get_grid_cb(self, grid):
+ self.grid.grid = grid
+ redraw(self.grid)
+
+ def error_cb(self, e):
+ _logger.error('Error connecting to opponent:\n%s', e)
+
+ @method(dbus_interface=IFACE, in_signature='', out_signature='b')
+ def Hello(self):
+ self.grid.selected_column = 3
+ redraw(self.grid)
+ # XXX: return player ID too, to allow for swapping who goes first in
+ # for second and later games
+ return True
+
+ @method(dbus_interface=IFACE, in_signature='', out_signature='aan')
+ def GetGrid(self):
+ return self.grid.grid
+
+ @signal(dbus_interface=IFACE, signature='n')
+ def Insert(self, column):
+ assert column >= 0
+ assert column < 7
+
+ def insert_cb(self, column, sender=None):
+ _logger.debug('Insert(%d) from %s', column, sender)
+
+ if sender == self.tube.participants[self.tube.self_handle]:
+ _logger.debug('Ignoring Insert signal from myself: %d', column)
+ return
+
+ if self.grid.insert(column, self.get_active_player()):
+ if self.get_active_player() == self.player_id:
+ _logger.debug('It\'s my turn now')
+ # This should always be the case for 2 players, as we only get
+ # this signal when the other player plays.
+ self.grid.selected_column = 3
+ redraw(self.grid)
+
+ def get_active_player(self):
+ count = {}
+
+ for row in self.grid.grid:
+ for player in row:
+ if player != 0:
+ count[player] = count.get(player, 0) + 1
+
+ if count.get(1, 0) > count.get(2, 0):
+ return 2
+ else:
+ return 1
+
+ def key_press_event(self, widget, event):
+ if self.grid.selected_column is None:
+ return
+
+ if event.keyval in (gtk.keysyms.Left,):
+ if self.grid.selected_column > 0:
+ self.grid.selected_column -= 1
+ redraw(self.grid)
+ elif event.keyval in (gtk.keysyms.Right,):
+ if self.grid.selected_column < 6:
+ self.grid.selected_column += 1
+ redraw(self.grid)
+ elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.space):
+ if self.grid.insert(self.grid.selected_column, self.player_id):
+ _logger.debug('Inserting at %d', self.grid.selected_column)
+ redraw(self.grid)
+ self.Insert(self.grid.selected_column)
+ self.grid.selected_column = None
--
1.5.1.3
signature.asc
Description: Digital signature
_______________________________________________ Sugar mailing list [email protected] http://mailman.laptop.org/mailman/listinfo/sugar
