[gnome-games/sudoku-tube] Ask receiver before open the network game
- From: Zhang Sen <zhangsen src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-games/sudoku-tube] Ask receiver before open the network game
- Date: Fri, 14 Aug 2009 11:04:04 +0000 (UTC)
commit 5c658a45b785aefe88e6c1212e3667b98381f021
Author: Zhang Sen <zh jesse gmail com>
Date: Fri Aug 14 17:54:45 2009 +0800
Ask receiver before open the network game
* Also ship the puzzle together with the tube offer, instead of querying
afterwards.
* Need to let the initiator be blocked until receiver has agreed.
gnome-sudoku/src/lib/gnome_sudoku.py | 2 +-
gnome-sudoku/src/lib/main.py | 107 ++++++++++++++++++++++------------
gnome-sudoku/src/lib/networking.py | 5 --
gnome-sudoku/src/lib/tp_tube.py | 9 ++-
gnome-sudoku/src/lib/tube_handler.py | 21 +++++--
5 files changed, 91 insertions(+), 53 deletions(-)
---
diff --git a/gnome-sudoku/src/lib/gnome_sudoku.py b/gnome-sudoku/src/lib/gnome_sudoku.py
index 57d16fe..dbf4733 100644
--- a/gnome-sudoku/src/lib/gnome_sudoku.py
+++ b/gnome-sudoku/src/lib/gnome_sudoku.py
@@ -36,7 +36,7 @@ def start_game ():
parser = optparse.OptionParser(
version = defaults.VERSION,
option_list = [
- optparse.make_option("-v", const=True, action="store_const",
+ optparse.make_option("-d", const=True, action="store_const",
dest="debug", help="Print debug information",
default=False),
optparse.make_option("-p", const=True, action="store_const",
diff --git a/gnome-sudoku/src/lib/main.py b/gnome-sudoku/src/lib/main.py
index 3abb0c6..09e23a4 100644
--- a/gnome-sudoku/src/lib/main.py
+++ b/gnome-sudoku/src/lib/main.py
@@ -79,7 +79,7 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
self.setup_gui()
self.tube_handler = tube_handler.TubeHandler(self._tube_service,
- tube_received_cb=self._tube_received_cb)
+ tube_received_cb=self._tube_incoming_cb)
self.timer = timer.ActiveTimer(self.w)
self.won = False
@@ -121,17 +121,24 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
def _auto_load_new(self):
"""Automatically open a new game"""
- # TODO should use preconfigured level
- level = self.gconf['game-level']
- new_puzzle = self.sudoku_maker.get_puzzles(1, [level])
+ new_puzzle = self._generate_new_puzzle()
if new_puzzle:
- # new_puzzle is a list, with the form of (<puzzle>, <difficulty>)
- logger.debug("%s game generated" % level)
- return new_puzzle[0][0]
+ return new_puzzle
else:
- logger.warning("failed to genereate new puzzle")
+ logger.error("failed to genereate new puzzle")
return None
+ def _generate_new_puzzle(self):
+ # TODO should use preconfigured or user-selected level
+ level = self.gconf['game-level']
+ # new_puzzle is a list, with the form of (<puzzle>, <difficulty>)
+ puzzles = self.sudoku_maker.get_puzzles(1, [level])
+ if puzzles:
+ puzzle = puzzles[0][0].replace(" ", "") # delete all spaces
+ logger.debug("%s game generated: %s" % (level, puzzle))
+ return puzzle
+ return None
+
def _open_game(self, game_type, puzzle):
"""Finally enter the puzzle"""
self._puzzle = puzzle
@@ -454,8 +461,15 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
conn, handle, contact = choice
logger.debug("selected: %s\n connection: %s\n handle: %d" % (
contact.alias, conn.service_name, handle))
- self._tube_offer = tp_tube.TubeOffer(conn, handle,
- self._tube_service)
+
+ puzzle = self._generate_new_puzzle()
+ if not puzzle:
+ logger.error("failed to genereate new puzzle")
+ # should popup?
+ return
+
+ self._tube_offer = tp_tube.TubeOffer(
+ conn, handle, self._tube_service, puzzle)
_connecting_label = gtk.Label(_("Connecting..."))
self._wait_dialog = gtk.Dialog("Sending request...",
@@ -466,7 +480,8 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
self._wait_dialog.vbox.pack_start(_connecting_label)
self._wait_dialog.connect("response", self._wait_dialog_response_cb)
- self._tube_offer.connect("offer-succeeded", self._tube_offered_cb)
+ self._tube_offer.connect("offer-succeeded",
+ self._tube_offered_cb, puzzle)
self._tube_offer.connect("offer-failed", self._offer_fail_cb)
self._tube_offer.execute()
@@ -501,15 +516,41 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
self._wait_dialog.vbox.pack_start(fail_label)
self._wait_dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT)
- def _tube_received_cb(self, bus, tube):
+ def _tube_incoming_cb(self, bus, tube, params):
"""Called when we receive a tube"""
- def error_cb(exception):
- logger.error('get puzzle error: %s' % exception)
- self.new_cb()
+ def reply_cb(dialog, response_id):
+ if response_id == gtk.RESPONSE_ACCEPT:
+ self._process_accepted_tube(bus, tube, puzzle)
+ else:
+ print 'do nothing; reply to initiator'
+
+ try:
+ puzzle = params['puzzle']
+ except KeyError:
+ logger.error("expected parameter missing from %s" % params)
+ return # do nothing
+
+ puzzle = str(puzzle)
+ logger.debug('got offer: %s' % puzzle)
+
+ dialog = gtk.Dialog("New game offer",
+ self.w,
+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+ (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,
+ gtk.STOCK_NO, gtk.RESPONSE_REJECT))
+ label = gtk.Label("<get-contact> wants to play with you")
+ label.show()
+ dialog.vbox.pack_start(label)
+ dialog.connect("response", reply_cb)
+ dialog.run()
+ dialog.destroy()
+
+ def _process_accepted_tube(self, bus, tube, puzzle):
+ """User has decided to accept the tube
+ """
assert self._is_initiator is None
- self._close_current_game()
self._is_initiator = False
self._bus = bus
self._tube = tube
@@ -519,34 +560,24 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
if not self._negotiate_peer_proxy(bus):
return
- self._peer.get_puzzle(
- dbus_interface=networking.view_interface,
- reply_handler=self._got_remote_puzzle_cb,
- error_handler=error_cb)
-
- def _got_remote_puzzle_cb(self, puzzle):
- logger.debug("got puzzle: %s; type: %s" % (puzzle, type(puzzle)))
- puzzle = str(puzzle)
- assert len(puzzle) == 81
+ self.do_stop()
self._open_game(game_selector.NewOrSavedGameSelector.NEW_GAME, puzzle)
- self._init_side_view_display()
+ self._init_side_view_display(puzzle)
self._negotiate_sideview_proxy(self._bus)
- def _tube_offered_cb(self, offer, bus, tube):
+ def _tube_offered_cb(self, offer, bus, tube, puzzle):
"""Called when the peer accepts our tube"""
self._wait_dialog.destroy()
- self._close_current_game()
self._tube = tube
self._tube[tp_tube.CHANNEL_INTERFACE].connect_to_signal(
'Closed', self._tube_closed_cb)
- # use this flag to ensure we are in a new game, and self._puzzle is a
- # string. FIXME
- self._auto_open_game(check_saved=False)
+ self.do_stop()
+ self._open_game(game_selector.NewOrSavedGameSelector.NEW_GAME, puzzle)
if not self._negotiate_peer_proxy(bus):
return
- self._init_side_view_display()
+ self._init_side_view_display(puzzle)
self._negotiate_sideview_proxy(bus)
def _negotiate_peer_proxy(self, bus):
@@ -565,10 +596,9 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
return True
def get_puzzle(self):
- return self._puzzle.replace(" ", "") # delete all spaces
+ return self._puzzle.replace(" ", "")
- def _init_side_view_display(self):
- puzzle = self.get_puzzle()
+ def _init_side_view_display(self, puzzle):
for x in range(9):
for y in range(9):
val = int(puzzle[9 * y + x])
@@ -598,7 +628,7 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
self._side_grid_vew.show()
- def _close_current_game (self):
+ def _close_current_game(self):
"""Close current running game
Return True if game is closed, or else return False"""
@@ -642,7 +672,10 @@ class SudokuGame(gconf_wrapper.GConfWrapper):
def _stop_network_game(self, *args):
logger.debug("close tube-channel")
- self._tube[tp_tube.CHANNEL_INTERFACE].Close()
+ try:
+ self._tube[tp_tube.CHANNEL_INTERFACE].Close()
+ except dbus.exceptions.DBusException as err:
+ logger.error("can't close tube: %s" % err)
self._side_grid_vew.reset()
self._side_grid_vew.hide()
self._tube = None
diff --git a/gnome-sudoku/src/lib/networking.py b/gnome-sudoku/src/lib/networking.py
index ce3ad3a..958cab5 100644
--- a/gnome-sudoku/src/lib/networking.py
+++ b/gnome-sudoku/src/lib/networking.py
@@ -17,11 +17,6 @@ class Peer(dbus.service.Object):
self._game = game
@dbus.service.method(dbus_interface=view_interface,
- in_signature="", out_signature="s")
- def get_puzzle(self):
- return self._game.get_puzzle()
-
- @dbus.service.method(dbus_interface=view_interface,
in_signature="", out_signature="b")
def has_won(self):
return self._game.won
diff --git a/gnome-sudoku/src/lib/tp_tube.py b/gnome-sudoku/src/lib/tp_tube.py
index c4bc295..edff6b4 100644
--- a/gnome-sudoku/src/lib/tp_tube.py
+++ b/gnome-sudoku/src/lib/tp_tube.py
@@ -30,7 +30,7 @@ class TubeOffer(gobject.GObject):
(str,)),
}
- def __init__(self, conn, handle, tube_service):
+ def __init__(self, conn, handle, tube_service, puzzle):
logger.debug("create an offer")
gobject.GObject.__init__(self)
self._tube_state = None
@@ -41,6 +41,7 @@ class TubeOffer(gobject.GObject):
self._conn = conn
self._handle = handle
self._tube_service = tube_service
+ self._puzzle = puzzle
def _tube_state_changed_cb(self, state):
self._tube_state = state
@@ -58,7 +59,7 @@ class TubeOffer(gobject.GObject):
if self._tube_state == TUBE_CHANNEL_STATE_REMOTE_PENDING:
# if tube is already open, it's not _offer_ failed (it's other
# problems)
- self.emit("offer-failed", _("Tube is closed by peer"))
+ self.emit("offer-failed", _("Connection closed by peer"))
def cancel(self):
if self._chan:
@@ -92,7 +93,9 @@ class TubeOffer(gobject.GObject):
logger.debug("offering tube")
try:
- self._address = self._chan[CHANNEL_TYPE_DBUS_TUBE].Offer({},
+ data = {'puzzle': self._puzzle}
+ self._address = self._chan[CHANNEL_TYPE_DBUS_TUBE].Offer(
+ data,
SOCKET_ACCESS_CONTROL_CREDENTIALS)
except dbus.exceptions.DBusException as excep:
error_busname = telepathy.errors.NotAvailable().get_dbus_name()
diff --git a/gnome-sudoku/src/lib/tube_handler.py b/gnome-sudoku/src/lib/tube_handler.py
index e2f1794..54683fb 100644
--- a/gnome-sudoku/src/lib/tube_handler.py
+++ b/gnome-sudoku/src/lib/tube_handler.py
@@ -4,6 +4,7 @@ import logging
import dbus
import dbus.service
+from dbus import PROPERTIES_IFACE
from dbus.mainloop.glib import DBusGMainLoop
from telepathy.client.conn import Connection
@@ -50,19 +51,25 @@ class TubeHandler(dbus.service.Object):
def HandleTube(self, bus_name, connection, channel, handle_type, handle):
"""Called when we are offered a tube"""
logger.debug("Tube received on %s" % channel)
- conn = Connection(bus_name, connection)
- self._tube_chan = Channel(bus_name, channel)
+ self._bus_name = bus_name
+ self._channel = channel
+ conn = Connection(bus_name, connection,
+ ready_handler=self._ready_handler)
- self.address = self._tube_chan[CHANNEL_TYPE_DBUS_TUBE].Accept(
- SOCKET_ACCESS_CONTROL_CREDENTIALS)
+ def _ready_handler(self, conn):
+ self._tube_chan = Channel(self._bus_name, self._channel)
self._tube_chan[CHANNEL_INTERFACE_TUBE].connect_to_signal(
'TubeChannelStateChanged', self._tube_state_changed_cb)
+ self._address = self._tube_chan[CHANNEL_TYPE_DBUS_TUBE].Accept(
+ SOCKET_ACCESS_CONTROL_CREDENTIALS)
+
def _tube_state_changed_cb(self, state):
if state == TUBE_STATE_OPEN:
logger.debug("Tube state changed ->open")
- tube_conn = dbus.connection.Connection(self.address)
-
- self._tube_received_cb(tube_conn, self._tube_chan)
+ bus = dbus.connection.Connection(self._address)
+ params = self._tube_chan[PROPERTIES_IFACE].Get(
+ CHANNEL_INTERFACE_TUBE, 'Parameters')
+ self._tube_received_cb(bus, self._tube_chan, params)
else:
logger.debug("Tube state changed ->%s" % state)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]