More patches for review: these add a TubesConnection helper, which I'll eventually move into telepathy-python.
Simon
From 3aba4b1d28757591795f07284474082acddde242 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[EMAIL PROTECTED]>
Date: Mon, 7 May 2007 14:54:57 +0100
Subject: [PATCH] gtkui.py: Configure logging to show all messages
---
gtkui.py | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/gtkui.py b/gtkui.py
index 27e950a..8dd6edd 100644
--- a/gtkui.py
+++ b/gtkui.py
@@ -1,5 +1,6 @@
import sys
+import logging
import dbus
import gtk
@@ -8,6 +9,11 @@ import telepathy
import gridwidget
import client
+
+logging.basicConfig()
+logging.getLogger().setLevel(1)
+
+
def decode(x, sig):
# XXX: dbus-python ought to do most of the work for this
if sig == 'b':
--
1.5.1.3
From 56c8ceeb2c9e0d4ab938d57df30c4b814fb490f6 Mon Sep 17 00:00:00 2001 From: Simon McVittie <[EMAIL PROTECTED]> Date: Mon, 7 May 2007 14:56:01 +0100 Subject: [PATCH] tubeconn.py: Add a prototype Tubes connection helper, for eventual inclusion in telepathy-python --- tubeconn.py | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 104 insertions(+), 0 deletions(-) create mode 100644 tubeconn.py diff --git a/tubeconn.py b/tubeconn.py new file mode 100644 index 0000000..0b65056 --- /dev/null +++ b/tubeconn.py @@ -0,0 +1,104 @@ +# This should eventually land in telepathy-python, so has the same license: + +# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This program 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.1 of the License, or +# (at your option) any later version. +# +# This program 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 program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +__all__ = ('TubeConnection',) +__docformat__ = 'reStructuredText' + + +import logging +try: + set() +except NameError: + from sets import Set as set + +from dbus import Array +from dbus.connection import Connection + + +logger = logging.getLogger('telepathy.tubeconn') + + +class TubeConnection(Connection): + + def __new__(cls, conn, tubes_iface, tube_id, address=None, + group_iface=None, mainloop=None): + if address is None: + address = tubes_iface.GetDBusServerAddress(tube_id) + self = super(TubeConnection, cls).__new__(cls, address, + mainloop=mainloop) + + self._tubes_iface = tubes_iface + self.tube_id = tube_id + self.participants = {} + self._mapping_watches = [] + + if group_iface is None: + method = conn.GetSelfHandle + else: + method = group_iface.GetSelfHandle + method(reply_handler=self._on_get_self_handle_reply, + error_handler=self._on_get_self_handle_error) + + return self + + def _on_get_self_handle_reply(self, handle): + self.self_handle = handle + self._tubes_iface.GetDBusNames(self.tube_id, + reply_handler=self._on_get_dbus_names_reply, + error_handler=self._on_get_dbus_names_error) + match = self._tubes_iface.connect_to_signal('DBusNamesChanged', + self._on_dbus_names_changed) + self._dbus_names_changed_match = match + + def _on_get_self_handle_error(self, e): + logging.basicConfig() + logger.error('GetSelfHandle failed: %s', e) + + def close(self): + self._dbus_names_changed_match.remove() + super(TubeConnection, self).close() + + def _on_get_dbus_names_reply(self, names): + self._on_dbus_names_changed(self.tube_id, names, ()) + + def _on_get_dbus_names_error(self, e): + logging.basicConfig() + logger.error('GetDBusNames failed: %s', e) + + def _on_dbus_names_changed(self, tube_id, added, removed): + if tube_id == self.tube_id: + for handle, bus_name in added: + if handle == self.self_handle: + # I've just joined - set my unique name + self.set_unique_name(bus_name) + self.participants[handle] = bus_name + for handle in removed: + self.participants.pop(handle, None) + for callback in self._mapping_watches: + callback(added, removed) + + def watch_participants(self, callback): + self._mapping_watches.append(callback) + if self.participants: + # GetDBusNames already returned: fake a participant add event + # immediately + added = [] + for k, v in self.participants.iteritems(): + added.append((k, v)) + callback(added, []) -- 1.5.1.3
From 38ef3e74e2ad624507f7a767e523bfe802b302e5 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[EMAIL PROTECTED]>
Date: Mon, 7 May 2007 14:57:19 +0100
Subject: [PATCH] client.py: Use TubeConnection. Move all game code to ConnectGame
---
client.py | 106 +++++++++++++++++++++++++++++++++----------------------------
1 files changed, 57 insertions(+), 49 deletions(-)
diff --git a/client.py b/client.py
index 9f9cfa0..8496481 100644
--- a/client.py
+++ b/client.py
@@ -5,7 +5,6 @@ import gtk
import telepathy
from dbus import Interface
-from dbus.connection import Connection
from dbus.mainloop.glib import DBusGMainLoop
from dbus.service import Object, method, signal
@@ -15,6 +14,9 @@ from telepathy.constants import TUBE_TYPE_DBUS, \
TUBE_STATE_LOCAL_PENDING, TUBE_STATE_REMOTE_PENDING, TUBE_STATE_OPEN, \
CONNECTION_STATUS_CONNECTED, HANDLE_TYPE_ROOM
+# 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"
@@ -42,31 +44,33 @@ def redraw(grid):
grid.window.invalidate_rect(grid.get_allocation(), False)
class ConnectGame(Object):
- def __init__(self, tube, grid, self_handle, initiator, dbus_names):
+ 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
- # Initiator is player 1, other player is player 2.
+ self.tube.watch_participants(self.participant_change_cb)
- self.self_handle = self_handle
- self.initiator = initiator
+ def participant_change_cb(self, added, removed):
+ # Initiator is player 1, other player is player 2.
- if initiator == self_handle:
- self.player_id = 1
- else:
- opponent = self.tube.get_object(dbus_names[initiator], PATH)
- self.opponent = Interface(opponent, IFACE)
- self.opponent.Hello(reply_handler=self.hello_cb,
- error_handler=self.error_cb)
- self.player_id = 2
-
- # XXX: care about signal sender
- self.tube.add_signal_receiver(self.insert_cb, 'Insert', IFACE,
- path=PATH)
-
- print 'intiator: %d' % initiator
- print 'self: %d' % self.self_handle
+ 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):
@@ -97,11 +101,16 @@ class ConnectGame(Object):
assert column >= 0
assert column < 7
- def insert_cb(self, column):
- #print 'Insert: %r' % args
+ 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
@@ -120,6 +129,25 @@ class ConnectGame(Object):
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):
@@ -142,22 +170,8 @@ class ConnectClient:
if event.keyval in (gtk.keysyms.Escape, gtk.keysyms.q):
gtk.main_quit()
- 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):
- redraw(self.grid)
- self.game.Insert(self.grid.selected_column)
- self.grid.selected_column = None
+ if self.game is not None:
+ self.game.key_press_event(widget, event)
def status_changed_cb(self, status, reason):
if status == CONNECTION_STATUS_CONNECTED:
@@ -180,8 +194,8 @@ class ConnectClient:
self.new_tube_cb)
tubes_chan[CHANNEL_TYPE_TUBES].connect_to_signal('DBusNamesChanged',
self.dbus_names_changed_cb)
- # XXX: this is racy
- # XXX: try all tubes and use the first one where Hello () -> True
+ # 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)
self.text_chan = text_chan
self.tubes_chan = tubes_chan
@@ -222,17 +236,11 @@ class ConnectClient:
def use_tube(self, id, initiator):
print 'using tube %d' % id
- addr = self.tubes_chan[CHANNEL_TYPE_TUBES].GetDBusServerAddress(id)
- assert addr
- self.dbus_names = dict(
- self.tubes_chan[CHANNEL_TYPE_TUBES].GetDBusNames(id))
- print 'names:', pprint.pformat(list(self.dbus_names))
- assert self.tubes_self_handle in self.dbus_names
- conn = Connection(addr)
+ conn = TubeConnection(self.conn, self.tubes_chan[CHANNEL_TYPE_TUBES],
+ id, group_iface=self.text_chan[CHANNEL_INTERFACE_GROUP])
- self.game = ConnectGame(conn, self.grid, self.tubes_self_handle,
- initiator, self.dbus_names)
+ self.game = ConnectGame(conn, self.grid, initiator)
def new_tube_cb(self, id, initiator, type, service, parameters, state):
print 'new tube: %r' % (
--
1.5.1.3
signature.asc
Description: Digital signature
_______________________________________________ Sugar mailing list [email protected] http://mailman.laptop.org/mailman/listinfo/sugar
