Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Schampijer <simon@schampijer.de>2007-06-30 12:53:15 (GMT)
committer Simon Schampijer <simon@schampijer.de>2007-06-30 12:53:15 (GMT)
commit6b66d6c927518508b3ca6f4aa13cea630790026e (patch)
tree495949e1bbd4bdf4a2445381ea2fb908ff2f2083
parent663a1fc0adb0291c0544500405625bbbf3d9c4c6 (diff)
cleaning the tree
-rw-r--r--game.py240
-rw-r--r--gridtest.py46
-rw-r--r--infopanel.py20
-rwxr-xr-xmemosono.py610
-rwxr-xr-xmemosonoactivity.py28
-rw-r--r--playpoints.py73
-rw-r--r--playview.py25
-rw-r--r--selectentry.py34
-rw-r--r--selectview.py54
-rw-r--r--tubeconn.py107
10 files changed, 420 insertions, 817 deletions
diff --git a/game.py b/game.py
new file mode 100644
index 0000000..f151199
--- /dev/null
+++ b/game.py
@@ -0,0 +1,240 @@
+import logging
+
+import gtk
+
+from dbus import Interface
+from dbus.service import method, signal
+from dbus.gobject_service import ExportedGObject
+
+
+# XXX: I'm not convinced this is in the right namespace
+SERVICE = "org.freedesktop.Telepathy.Tube.Memosono"
+IFACE = SERVICE
+PATH = "/org/freedesktop/Telepathy/Tube/Memosono"
+
+
+_logger = logging.getLogger('memosono-activity.game')
+
+
+class ConnectGame(ExportedGObject):
+
+ def __init__(self, tube, grid, is_initiator, buddies_panel, info_panel,
+ owner, get_buddy, activity):
+ super(ConnectGame, self).__init__(tube, PATH)
+ self.tube = tube
+ self.grid = grid
+ self.is_initiator = is_initiator
+ self.entered = False
+ self.player_id = None
+ self.buddies_panel = buddies_panel
+ self.info_panel = info_panel
+ self.owner = owner
+ self._get_buddy = get_buddy
+ self.activity = activity
+
+ # list indexed by player ID
+ # 0, 1 are players 0, 1
+ # 2+ are the spectator queue, 2 is to play next
+ self.ordered_bus_names = []
+
+ self.tube.watch_participants(self.participant_change_cb)
+ self.grid.connect('insert-requested', self.insert_requested_cb)
+
+ def participant_change_cb(self, added, removed):
+ # Initiator is player 0, other player is player 1.
+
+ _logger.debug('adding participants: %r', added)
+ _logger.debug('removing participants: %r', removed)
+
+ for handle, bus_name in added:
+ buddy = self._get_buddy(handle)
+ _logger.debug('Buddy %r was added', buddy)
+ if buddy is not None:
+ self.buddies_panel.add_watcher(buddy)
+
+ for handle in removed:
+ buddy = self._get_buddy(handle)
+ _logger.debug('Buddy %r was removed', buddy)
+ if buddy is not None:
+ self.buddies_panel.remove_watcher(buddy)
+ try:
+ self.ordered_bus_names.remove(self.tube.participants[handle])
+ except ValueError:
+ # already absent
+ pass
+
+ 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):
+ """Request that this player's Welcome method is called to bring it
+ up to date with the game state.
+ """
+
+ @method(dbus_interface=IFACE, in_signature='aanas', out_signature='')
+ def Welcome(self, grid, bus_names):
+ """To be called on the incoming player by the other players to
+ inform them of the game state.
+
+ FIXME: nominate a "referee" (initially the initiator) responsible
+ for saying Welcome, elect a new referee when the current referee
+ leaves? This could also be used to make the protocol robust against
+ cheating/bugs
+ """
+ if self.player_id is None:
+ _logger.debug('Welcomed to the game. Player bus names are %r',
+ bus_names)
+ self.grid.grid = grid
+ dump_grid(grid)
+ self.ordered_bus_names = bus_names
+ self.player_id = bus_names.index(self.tube.get_unique_name())
+ # OK, now I'm synched with the game, I can welcome others
+ self.add_hello_handler()
+
+ buddy = self._get_buddy(self.tube.bus_name_to_handle[bus_names[0]])
+ self.buddies_panel.add_player(buddy)
+ buddy = self._get_buddy(self.tube.bus_name_to_handle[bus_names[1]])
+ self.buddies_panel.add_player(buddy)
+
+ if self.get_active_player() == self.player_id:
+ _logger.debug("It's my turn already!")
+ self.change_turn()
+
+ redraw(self.grid)
+ 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')
+
+ @signal(dbus_interface=IFACE, signature='n')
+ def Insert(self, column):
+ """Signal that the local player has placed a disc."""
+ assert column >= 0
+ assert column < 7
+
+ def hello_cb(self, sender=None):
+ """Tell the newcomer what's going on."""
+ _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).Welcome(self.grid.grid,
+ self.ordered_bus_names,
+ dbus_interface=IFACE)
+ if (self.player_id == 0 and len(self.ordered_bus_names) == 2):
+ _logger.debug("This is my game and an opponent has joined. "
+ "I go first")
+ self.change_turn()
+
+ def insert_cb(self, column, sender=None):
+ # Someone placed a disc
+ handle = self.tube.bus_name_to_handle[sender]
+ _logger.debug('Insert(%d) from %s', column, sender)
+
+ if self.tube.self_handle == handle:
+ _logger.debug('Ignoring Insert signal from myself: %d', column)
+ return
+
+ try:
+ winner = self.grid.insert(column, self.get_active_player())
+ except ValueError:
+ return
+
+ dump_grid(self.grid.grid)
+
+ if winner is not None:
+ _logger.debug('Player with handle %d wins', handle)
+ self.info_panel.show('The other player wins!')
+ redraw(self.grid)
+ return
+
+ self.change_turn()
+
+ def change_turn(self):
+ try:
+ bus_name = self.ordered_bus_names[self.get_active_player()]
+ buddy = self._get_buddy(self.tube.bus_name_to_handle[bus_name])
+ self.buddies_panel.set_is_playing(buddy)
+ except:
+ _logger.error('argh!', exc_info=1)
+ raise
+
+ if self.get_active_player() == self.player_id:
+ _logger.debug('It\'s my turn now')
+ self.info_panel.show('Your turn')
+ self.grid.selected_column = 3
+ self.activity.grab_focus()
+ else:
+ _logger.debug('It\'s not my turn')
+ self.grid.selected_column = None
+
+ redraw(self.grid)
+
+ def get_active_player(self):
+ count = {}
+
+ for row in self.grid.grid:
+ for player in row:
+ if player > -1:
+ count[player] = count.get(player, 0) + 1
+
+ if count.get(0, 0) > count.get(1, 0):
+ return 1
+ else:
+ return 0
+
+ def key_press_event(self, widget, event):
+ if self.grid.selected_column is None:
+ _logger.debug('Ignoring keypress - not my turn')
+ return
+
+ _logger.debug('Keypress: keyval %s', event.keyval)
+
+ if event.keyval in (gtk.keysyms.Left,):
+ _logger.debug('<--')
+ if self.grid.selected_column > 0:
+ self.grid.selected_column -= 1
+ redraw(self.grid)
+ elif event.keyval in (gtk.keysyms.Right,):
+ _logger.debug('-->')
+ if self.grid.selected_column < 6:
+ self.grid.selected_column += 1
+ redraw(self.grid)
+ elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.space):
+ _logger.debug('v')
+ self.insert_requested_cb(self.grid, self.grid.selected_column)
+
+ def insert_requested_cb(self, grid, col):
+ winner = grid.insert(col, self.player_id)
+ if winner == -1:
+ return
+
+ _logger.debug('Inserting at %d', col)
+ dump_grid(grid.grid)
+ redraw(grid)
+ self.Insert(col)
+
+ self.change_turn()
+
+ if winner is not None:
+ print "I win"
+ self.info_panel.show('You win!')
+ else:
+ self.info_panel.show('Other player\'s turn')
diff --git a/gridtest.py b/gridtest.py
new file mode 100644
index 0000000..9220746
--- /dev/null
+++ b/gridtest.py
@@ -0,0 +1,46 @@
+import gtk
+import os
+
+from playview import PlayView
+from model import Game
+
+
+class Test(object):
+ def __init__(self):
+
+ self.games = {}
+ os.path.walk(os.path.join(os.path.dirname(__file__), 'games'), self._find_games, None)
+
+ gamelist = self.games.keys()
+ gamelist.sort()
+
+ print 'gamelist: %s' %gamelist
+ print 'pairs: %s' %self.games[gamelist[0]].pairs
+
+ self.pv = PlayView(self.games[gamelist[0]].pairs)
+
+ window = gtk.Window()
+ window.connect('destroy', gtk.main_quit)
+ window.connect('key-press-event', self.key_press_cb)
+ window.add(self.pv)
+ window.show_all()
+ try:
+ gtk.main()
+ except KeyboardInterupt:
+ pass
+
+ def key_press_cb(self, window, event):
+ if gtk.gdk.keyval_name(event.keyval) in ('Escape', 'q'):
+ gtk.main_quit()
+
+ def _find_games(self, arg, dirname, names):
+ for name in names:
+ if name.endswith('.mson'):
+ game = Game(dirname, os.path.dirname(__file__))
+ game.read(name)
+ self.games[name.split('.mson')[0]] = game
+
+
+if __name__ == '__main__':
+ Test()
+
diff --git a/infopanel.py b/infopanel.py
new file mode 100644
index 0000000..95defa6
--- /dev/null
+++ b/infopanel.py
@@ -0,0 +1,20 @@
+import hippo
+import pango
+from sugar.graphics import color
+
+class InfoPanel(hippo.CanvasBox):
+ def __init__(self):
+ hippo.CanvasBox.__init__(self, spacing=4, padding=5,
+ orientation=hippo.ORIENTATION_VERTICAL)
+ self.status_box = hippo.CanvasBox(spacing=4, padding=5,
+ orientation=hippo.ORIENTATION_VERTICAL)
+ self.append(self.status_box)
+
+ def show(self, text):
+ textwidget = hippo.CanvasText(text=text,
+ font_desc=pango.FontDescription('Sans 16'),
+ color=color.WHITE.get_int(),
+ xalign=hippo.ALIGNMENT_CENTER)
+ self.status_box.remove_all()
+ self.status_box.append(textwidget)
+
diff --git a/memosono.py b/memosono.py
deleted file mode 100755
index 9912590..0000000
--- a/memosono.py
+++ /dev/null
@@ -1,610 +0,0 @@
-#! /usr/bin/env python
-#
-# Copyright (C) 2006 Simon Schampijer
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-#
-
-
-import gobject
-import gtk, pygtk
-import os
-import socket
-import logging
-import random
-import copy
-import time
-import errno
-import gc
-
-from sugar.activity import activity
-
-from osc.oscapi import OscApi
-from csound.csoundserver import CsoundServer
-
-
-class Server:
- def __init__(self, _MEMO, port):
-
- isserver = 0
- while isserver == 0:
- self.port = port
- self.oscapi = OscApi(self.port)
- isserver = self.oscapi.isserver
- port+=1
-
- logging.debug(" Memosono-Server has port "+str(self.port) )
- gobject.io_add_watch(self.oscapi.iosock, gobject.IO_IN, self._handle_query)
- self.oscapi.addmethod('/MEMO/tile', 'is', self._tile)
- self.oscapi.addmethod('/MEMO/connect', 'i', self._connect)
- self.compkey = ''
- self.key = ''
- self.tile = 0
- self.comtile = 0
- self.match = 0
- self.addresses = {}
- self.addresses['eva'] = []
- self.addresses['simon'] = []
- self.players = ['eva', 'simon']
- self.currentplayer = 0
- self.lastplayer = 0
- self.numplayers = _MEMO['_NUM_PLAYERS']
- self.count = 0
- self.numpairs = _MEMO['_NUM_GRIDPOINTS']/2
-
- def _handle_query(self, source, condition):
- data, address = source.recvfrom(1024)
- self.oscapi.handlemsg(data, address)
- return True
-
-# OSC-METHODS:
- def _connect(self, *msg):
- self.addresses['eva'] = [msg[1][0], int(msg[1][1])]
- self.addresses['simon'] = [msg[1][0], int(msg[1][1])+1]
-
- def _tile(self, *msg):
- self.tile = msg[0][2]
- self.key = msg[0][3]
-
- # send to other machines
- for i in self.addresses:
- if msg[1][0] == self.addresses[i][0]:
- if msg[1][1] != self.addresses[i][1]:
- self.oscapi.send((self.addresses[i][0], self.addresses[i][1]), "/MEMO/tile",
- [self.tile, self.key])
- else:
- ## logging.debug(" Send the stuff ")
- self.oscapi.send((self.addresses[i][0], self.addresses[i][1]), "/MEMO/tile",
- [self.tile, self.key])
- # match
- if self.compkey != '':
- if self.compkey == self.key:
- ## logging.debug(" Key matches ")
- self.match = 1
- self.count += 1
- else:
- ## logging.debug(" Key does NOT match ")
- self.match = 0
- self.lastplayer = self.currentplayer
- if self.match == 0:
- if self.currentplayer == self.numplayers-1 :
- self.currentplayer = 0
- else:
- self.currentplayer+=1
- i = 0
- for i in self.addresses:
- self.oscapi.send((self.addresses[i][0], self.addresses[i][1]),"/MEMO/game/next",
- [self.players[self.currentplayer],
- self.players[self.lastplayer]])
- i = 0
- for i in self.addresses:
- self.oscapi.send((self.addresses[i][0], self.addresses[i][1]), "/MEMO/game/match",
- [self.match, self.players[self.lastplayer],
- self.comtile, self.tile, self.count/self.numpairs])
- self.compkey = ''
- self.comptile = 0
- else:
- self.compkey = self.key
- self.comtile = self.tile
-
-
-
-class Controler(gobject.GObject):
- __gsignals__ = {
- 'fliptile': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
- 'game': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'updatepointsc': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'nextc': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
- 'addplayer': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'gameinit': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
- 'tileflippedc': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
- }
- def __init__(self, _MEMO, port):
- gobject.GObject.__init__(self)
- self._MEMO = _MEMO
- self.sound = 1
- self.replyaddr = (('127.0.0.1', port))
- self.serveraddr = (('127.0.0.1', port))
- port+=1
- # OSC-communication
- isserver = 0
- while isserver == 0:
- self.port = port
- self.oscapi = OscApi(self.port)
- isserver = self.oscapi.isserver
- port+=1
-
- logging.debug(" Memosono-Client has port "+str(self.port) )
- self.oscapi.send((self.serveraddr[0], self.serveraddr[1]), "/MEMO/connect", [self.port])
- gobject.io_add_watch(self.oscapi.iosock, gobject.IO_IN, self._handle_query)
- self.oscapi.addmethod('/MEMO/addplayer', '', self._addplayer)
- self.oscapi.addmethod('/MEMO/init', 'sis', self._game_init)
- self.oscapi.addmethod('/MEMO/tile', 'i', self._tile)
- self.oscapi.addmethod('/MEMO/game/match', 'isiii', self._game_match)
- self.oscapi.addmethod('/MEMO/game/next', 'ss', self._game_next)
- self.oscapi.addmethod('/CSOUND/ping', '', self._ping)
- self.block = 0
- self.count = 0
-
-
- # CSOUND-communication
- self.id = 0 ##FIXME give a significant number
-
- def csconnect(self):
- self.oscapi.send(('127.0.0.1', 6783), "/CSOUND/connect", [])
-
- def init_game(self, playername, numplayers, gamename):
- self.emit('gameinit', playername, numplayers, gamename)
-
- def _handle_query(self, source, condition):
- data, self.replyaddr = source.recvfrom(1024)
- self.oscapi.handlemsg(data, self.replyaddr)
- return True
-
-# SLOTS:
- def _user_input(self, widget, tile_number):
- #if not self.block:
- # self.count+=1
- self.emit('fliptile', tile_number, 0, self.block)
- #if self.count == 2:
- # self.block = 1
- # self.count = 0
- return False
-
- def _tile_flipped(self, model, tile_number, pic, sound, requesttype, chosen_flag):
- if chosen_flag == 1:
- self.emit('game', 'Chosen already!')
- else:
- logging.debug("tile_number: "+str(tile_number)+" pic: "+pic+" sound: "+sound)
- logging.debug("count: "+str(self.count)+" self.block: "+str(self.block))
- if not self.block:
- if requesttype is not 2:
- self.count+=1
-
- if sound is not '-1':
- self.emit('tileflippedc', tile_number, pic, sound)
- if self.sound is 1:
- if os.path.exists(os.path.join(self._MEMO['_DIR_GSOUNDS'],sound)):
- file = os.path.join(self._MEMO['_DIR_GSOUNDS'],sound)
- self.oscapi.send(('127.0.0.1', 6783), '/CSOUND/perform', ['i 108 0.0 3.0 "%s" 1 0.7 0.5 0'%file])
- logging.debug(" Read file: "+os.path.join(self._MEMO['_DIR_GSOUNDS'],sound))
- else:
- logging.error(" Can not read file: "+os.path.join(self._MEMO['_DIR_GSOUNDS'],sound))
-
- if requesttype == 0:
- logging.debug(" send to server ")
- self.oscapi.send((self.serveraddr[0], self.serveraddr[1]), "/MEMO/tile", [tile_number, pic])
- if self.count == 2:
- self.block = 1
- self.count = 0
-
- return False
-
-# OSC-METHODS:
- def _addplayer(self, *msg):
- logging.debug(" Addplayer ")
-
- def _game_init(self, *msg):
- self.init_game(msg[0][2], msg[0][3], msg[0][4])
-
- def _tile(self, *msg):
- self.emit('fliptile', msg[0][2], 1, self.block)
-
- def _game_next(self, *msg):
- logging.debug("next please --- self.block: "+str(self.block))
- gobject.timeout_add(3000, self._game_next_delayed, msg[0][2], msg[0][3])
-
- def _game_next_delayed(self, player, lastplayer):
- self.block = 0
- logging.debug("next-delayed please --- self.block: "+str(self.block))
- self.emit('nextc', player, lastplayer)
- return False
-
- def _game_match(self, *msg):
- # flag_match, playername, tile1, tile2
- logging.debug(msg)
- if msg[0][2] == 1:
- # update points
- self.block = 0
- self.emit('updatepointsc', msg[0][3])
- if msg[0][6] != 1:
- self.emit('game', 'Match!')
- else:
- logging.debug("end")
- self.block = 1
- self.emit('game', 'The end')
- else:
- requesttype = 2 # 0:normal, 1:setback
- self.emit('game', 'Pairs do not match!')
- self.emit('fliptile', int(msg[0][4]), requesttype, self.block)
- self.emit('fliptile', int(msg[0][5]), requesttype, self.block)
-
- def _ping(self, *msg):
- self.oscapi.send(msg[1], '/CSOUND/pong', [])
-
-
-class Model(gobject.GObject):
- __gsignals__ = {
- 'tileflipped': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
- gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
- 'nextm': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
- gobject.TYPE_PYOBJECT])),
- 'updatepointsm': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])),
- }
- def __init__(self, grid):
- gobject.GObject.__init__(self)
- # tile - key=id, pic, sound, flag_flipped
- self.tileg = []
- i = 0
- for elem in grid:
- self.tileg.append(elem)
- i+=1
- # player - key=name, picture, tiles_won, scores
- self.player = {}
- self.player['eva'] = [0, ['player1_0.jpg', 'player1_0b.jpg'],['player1_1.jpg', 'player1_1b.jpg'],
- ['player1_2.jpg', 'player1_2b.jpg'],['player2_3.jpg', 'player2_3b.jpg'],
- ['player1_4.jpg', 'player1_4b.jpg'],['player1_5.jpg', 'player1_5b.jpg'],
- ['player1_6.jpg', 'player1_6b.jpg'],['player1_7.jpg', 'player1_7b.jpg'],
- ['player1_8.jpg', 'player1_8b.jpg'],['player1_9.jpg', 'player1_9b.jpg'],
- ['player1_10.jpg', 'player1_10b.jpg'],['player1_11.jpg', 'player1_11b.jpg'],
- ['player1_12.jpg', 'player1_12b.jpg'],['player1_13.jpg', 'player1_13b.jpg'],
- ['player1_14.jpg', 'player1_14b.jpg'],['player1_15.jpg', 'player1_15b.jpg'],
- ['player1_16.jpg', 'player1_16b.jpg'],['player1_17.jpg', 'player1_17b.jpg'],
- ['player1_18.jpg', 'player1_18b.jpg']]
-
- self.player['simon'] = [0, ['player2_0.jpg', 'player2_0b.jpg'],['player2_1.jpg', 'player2_1b.jpg'],
- ['player2_2.jpg', 'player2_2b.jpg'],['player2_3.jpg', 'player2_3b.jpg'],
- ['player2_4.jpg', 'player2_4b.jpg'],['player2_5.jpg', 'player2_5b.jpg'],
- ['player2_6.jpg', 'player2_6b.jpg'],['player2_7.jpg', 'player2_7b.jpg'],
- ['player2_8.jpg', 'player2_8b.jpg'],['player2_9.jpg', 'player2_9b.jpg'],
- ['player2_10.jpg', 'player2_10b.jpg'],['player2_11.jpg', 'player2_11b.jpg'],
- ['player2_12.jpg', 'player2_12b.jpg'],['player2_13.jpg', 'player2_13b.jpg'],
- ['player2_14.jpg', 'player2_14b.jpg'],['player2_15.jpg', 'player2_15b.jpg'],
- ['player2_16.jpg', 'player2_16b.jpg'],['player2_17.jpg', 'player2_17b.jpg'],
- ['player2_18.jpg', 'player2_18b.jpg']]
- # game
- self.numplayers = 2
-
-# SLOTS:
- def _game_init(self, controler, playername, numplayers, gamename):
- ## logging.debug(" gameinit ")
- return False
- def _add_player():
- ## logging.debug(" addplayer ")
- return False
-
- def _flip_tile(self, controler, tile_number, requesttype, blocked):
- if requesttype == 0 or requesttype == 1:
- if self.tileg[tile_number][2] == 0: # !!FIX - better switch
- if not blocked:
- self.tileg[tile_number][2] = 1
- # --->view: number, pic, sound, requesttype, chosen
- self.emit('tileflipped', tile_number, self.tileg[tile_number][0],
- self.tileg[tile_number][1], requesttype,0)
- else:
- self.emit('tileflipped', tile_number, self.tileg[tile_number][0],
- self.tileg[tile_number][1], requesttype,1)
- else:
- # set tilestate back
- # self.tileg[tile_number][2] = 0
- gobject.timeout_add(3000, self._reset, tile_number, requesttype)
- return False
-
- def _reset(self, tile_number, requesttype):
- self.tileg[tile_number][2] = 0
- self.emit('tileflipped', tile_number, '-1', '-1', requesttype, 0)
- return False
-
- def _next(self, controler, player, lastplayer ):
- count1 = self.player[player][0]
- count2 = self.player[lastplayer][0]
- self.emit('nextm', player, self.player[player][count1+1][1], lastplayer,self.player[lastplayer][count2+1][0])
-
- def _updatepoints(self, controler, player):
- self.player[player][0] += 1
- pic_id = self.player[player][0]
- self.emit('updatepointsm', player, self.player[player][pic_id+1][1])
-
-class View:
- def __init__(self, controler, memosonoactivity, _MEMO):
- self._MEMO = _MEMO
- self.row1 = gtk.HBox(False, 0)
- # create the grid
- self.imageObj = []
- self.buttonObj = []
- # create the players
- self.p_imageObj = {}
- self.p_fixedObj = {}
-
-# SLOTS:
- def _game_init(self, controler, playername, numplayers, gamename):
- # Create a table for the grid
- self.num_elem_x = 6
- self.num_elem_y = 6
- self.table = gtk.Table(self.num_elem_y, self.num_elem_x, True)
- self.row1.pack_start(self.table)
-
- # scale black
- self.scale_x = 120
- self.scale_y = 120
- pixbuf_i = gtk.gdk.pixbuf_new_from_file(os.path.join(self._MEMO['_DIR_IMAGES'],"black80.jpg"))
- self.scaledbuf_i = pixbuf_i.scale_simple(self.scale_x, self.scale_y, gtk.gdk.INTERP_BILINEAR)
-
- ### fix to release the memory allocated by the pixbuf call
- del pixbuf_i
- gc.collect()
-
- self.y = 0
- self.x = 0
- i = 0
- while(self.y < self.num_elem_y):
- while(self.x < self.num_elem_x):
- self.imageObj.append(gtk.Image())
- self.imageObj[i].set_from_pixbuf(self.scaledbuf_i)
- self.imageObj[i].show()
- self.buttonObj.append(gtk.Button())
- self.buttonObj[i].add(self.imageObj[i])
- self.table.attach(self.buttonObj[i], self.x, self.x+1, self.y, self.y+1)
- self.x+=1
- i+=1
- self.x=0
- self.y+=1
-
- # Players
- self.pscale_x = 200
- self.pscale_y = 200
- self.downbox = gtk.HBox(False, 0)
- self.playerbox = gtk.VBox(False, 0)
- self.p1 = 'eva'
- self.p2 = 'simon'
- self.p_imageObj[self.p1] = gtk.Image()
- self.p_imageObj[self.p1].set_from_pixbuf(self.pixbuf("player1_0b.jpg",0, self.pscale_x, self.pscale_y))
- self.p_fixedObj[self.p1] = gtk.Fixed()
- self.p_fixedObj[self.p1].set_size_request(self.pscale_x, self.pscale_y)
- self.p_fixedObj[self.p1].add(self.p_imageObj[self.p1])
- self.playerbox.pack_start(self.p_fixedObj[self.p1])
-
- self.p_imageObj[self.p2] = gtk.Image()
- self.p_imageObj[self.p2].set_from_pixbuf(self.pixbuf("player2_0.jpg",0, self.pscale_x, self.pscale_y))
- self.p_fixedObj[self.p2] = gtk.Fixed()
- self.p_fixedObj[self.p2].set_size_request(self.pscale_x, self.pscale_y)
- self.p_fixedObj[self.p2].add(self.p_imageObj[self.p2])
- self.playerbox.pack_start(self.p_fixedObj[self.p2])
-
- self.downbox.pack_start(self.playerbox)
- self.row1.pack_start(self.downbox)
- self.row1.show_all()
- return False
-
- def pixbuf(self, filename, pictype, pscale_x, pscale_y):
- if pictype is 1:
- ppixbuf_i = gtk.gdk.pixbuf_new_from_file(os.path.join(self._MEMO['_DIR_GIMAGES'],filename))
- if pictype is 0:
- ppixbuf_i = gtk.gdk.pixbuf_new_from_file(os.path.join(self._MEMO['_DIR_IMAGES'],filename))
-
- pscaledbuf_i = ppixbuf_i.scale_simple(pscale_x, pscale_y, gtk.gdk.INTERP_BILINEAR)
-
- ### fix to release the memory allocated by the pixbuf call
- del ppixbuf_i
- gc.collect()
-
- return pscaledbuf_i
-
- def _next(self, controler, playername, filename, lastplayer, lastfilename):
- self.p_imageObj[playername].set_from_pixbuf(self.pixbuf(filename, 0, self.pscale_x, self.pscale_y))
- self.p_imageObj[lastplayer].set_from_pixbuf(self.pixbuf(lastfilename, 0, self.pscale_x, self.pscale_y))
- return False
-
- def _updatepoints(self, controler, playername, pic):
- self.p_imageObj[playername].set_from_pixbuf(self.pixbuf(pic, 0, self.pscale_x, self.pscale_y))
- return False
-
- def _tile_flipped(self, model, tile_number, pic, sound):
- if pic == "-1":
- self.imageObj[tile_number].set_from_pixbuf(self.pixbuf("black80.jpg", 0, self.scale_x, self.scale_y))
- else:
- self.imageObj[tile_number].set_from_pixbuf(self.pixbuf(pic, 1, self.scale_x, self.scale_y))
- return False
-
- def _game(self, controler, string):
- return False
-
-
-def read_config(filename, seed, numelems):
- temp = []
- grid = []
- # set random seed
- random.seed(seed)
- filecheck = filename.split('.')
- if filecheck[2] != 'mson':
- logging.error(' File format of %s'%filename)
- ## sys.exit()
- else:
- fd = open(filename, 'r')
- if fd == None:
- logging.error(' Reading setup file %s'%filename)
- ## sys.exit()
- else:
- logging.info(' Read setup for memosono from file %s'%filename)
- line = fd.readline()
- while line:
- zw = line.split()
- zw.append(0)
- if len(zw) is not 0:
- temp.append(zw)
- line = fd.readline()
- fd.close()
- # select randomly numelems of the list
- grid = random.sample(temp, numelems)
- # make a complete deepcopy of the list
- # and concatenate it at the end grid.extend()
- tm = copy.deepcopy(grid)
- grid.extend(tm)
- # shuffle th grid elements
- random.shuffle(grid)
- return grid
-
-
-def pathes(filename):
- # read config file
- path = []
- gamename = filename
- home = os.path.join(os.path.dirname(os.path.abspath(__file__)), "games")
- gamepath = os.path.join(home, gamename)
- logging.debug(gamepath)
- if not os.path.exists(gamepath):
- logging.error(" Game path does NOT exist in the home folder ")
- else:
- logging.debug(" Game path exist in the home folder ")
- configpath = os.path.join(gamepath, filename+".mson")
- if not os.path.exists(configpath):
- logging.error(" Config file does NOT exist: "+configpath)
- logging.error(" Did you name it correct, ending with .mson? ")
- #sys.exit() ##FIXME
- else:
- path.append(configpath)
- logging.debug(" Config file is placed in the folder ")
- imagespath = os.path.join(gamepath, "images")
- soundspath = os.path.join(gamepath, "sounds")
- if os.path.exists(imagespath):
- logging.debug(" Set path for images: "+imagespath)
- path.append(imagespath)
- else:
- logging.error(" Path to images does NOT exist ")
- #sys.exit() ##FIXME
- if os.path.exists(soundspath):
- logging.debug(" Set path for sounds: "+soundspath)
- path.append(soundspath)
- else:
- logging.error(" Path to images does NOT exist ")
- #sys.exit() ##FIXME
- return path
-
-
-class MemosonoActivity(activity.Activity):
- def __init__(self, handle):
- activity.Activity.__init__(self, handle)
- self.connect('destroy', self._cleanup_cb)
-
- self.gamename = 'drumgit'
- self.set_title("Memosono - "+self.gamename)
- logging.debug(" ---------------------Memosono start-----------------------. ")
-
- # set path
- _MEMO = {}
- _MEMO['_DIR_CSSERVER'] = os.path.join(os.path.dirname(__file__), "csserver")
- _MEMO['_DIR_IMAGES'] = os.path.join(os.path.dirname(__file__), "images")
- logging.error( os.path.dirname('.') )
- _MEMO['_DIR_SOUNDS'] = os.path.join(os.path.dirname(__file__), "sounds")
- path = pathes(self.gamename)
- _MEMO['_DIR_GIMAGES'] = path[1]
- _MEMO['_DIR_GSOUNDS'] = path[2]
- # read config
- seed = random.randint(0, 14567)
- _MEMO['_NUM_GRIDPOINTS'] = 36
- _MEMO['_NUM_ELEMS'] = 18
- grid = read_config(path[0], seed, _MEMO['_NUM_ELEMS'])
-
- _MEMO['_NUM_PLAYERS'] = 2
- name_creator = 'eva'
-
- self.server = Server(_MEMO, 7000)
- self.controler = Controler(_MEMO, self.server.port)
-
- self.model = Model(grid)
- self.view = View(self.controler, self, _MEMO)
- self.set_canvas(self.view.row1)
-
-# SLOTS connections:
- self.model.connect('tileflipped', self.controler._tile_flipped)
- self.controler.connect('tileflippedc', self.view._tile_flipped)
- self.controler.connect('fliptile', self.model._flip_tile)
- self.controler.connect('addplayer', self.model._add_player)
- self.controler.connect('gameinit', self.model._game_init)
- self.controler.connect('gameinit', self.view._game_init)
- self.controler.connect('game', self.view._game)
- self.controler.connect('nextc', self.model._next)
- self.model.connect('nextm', self.view._next)
- self.controler.connect('updatepointsc', self.model._updatepoints)
- self.model.connect('updatepointsm', self.view._updatepoints)
- # connect to the in/out events of the memosono activity
- self.connect('focus_in_event', self._focus_in)
- self.connect('focus_out_event', self._focus_out)
-
-
- self.controler.init_game(name_creator, _MEMO['_NUM_PLAYERS'], self.gamename)
- i = 0
- while(i < _MEMO['_NUM_GRIDPOINTS']):
- self.view.buttonObj[i].connect('clicked', self.controler._user_input, i)
- i+=1
-
- ### start csound server
- self.cs = CsoundServer()
- gtk.gdk.threads_init()
- self.controler.csconnect()
-
- def _cleanup_cb(self, data=None):
- self.controler.oscapi.send(('127.0.0.1', 6783), "/CSOUND/quit", [])
- self.controler.oscapi.iosock.close()
- self.server.oscapi.iosock.close()
- logging.debug(" Closed OSC sockets ")
-
- def _focus_in(self, event, data=None):
- logging.debug(" Memosono is visible: Connect to the Csound-Server. ")
- self.controler.oscapi.send(('127.0.0.1', 6783), "/CSOUND/connect", [])
-
- def _focus_out(self, event, data=None):
- logging.debug(" Memosono is invisible: Close the connection to the Csound-Server. ")
- self.controler.oscapi.send(('127.0.0.1', 6783), "/CSOUND/disconnect", [])
diff --git a/memosonoactivity.py b/memosonoactivity.py
index ffb3610..f02e9b0 100755
--- a/memosonoactivity.py
+++ b/memosonoactivity.py
@@ -31,30 +31,22 @@ from sugar.activity.activity import Activity
from sugar.activity.activity import ActivityToolbox
from sugar.presence import presenceservice
-from osc.oscapi import OscApi
from csound.csoundserver import CsoundServer
-from selectview import SelectView
from playview import PlayView
-from toolbar import PlayToolbar
+#from toolbar import PlayToolbar
from model import Game
-
+from game import ConnectGame
class MemosonoActivity(Activity):
def __init__(self, handle):
Activity.__init__(self, handle)
self.set_title ("Memosono")
- self.sv = None
self.pv = None
toolbox = ActivityToolbox(self)
self.set_toolbox(toolbox)
toolbox.show()
- toolbox._notebook.connect('switch-page', self._switch_page)
-
- self.play_toolbar = PlayToolbar(self)
- toolbox.add_toolbar(_('Play'), self.play_toolbar)
- self.play_toolbar.show()
-
+
self.games = {}
os.path.walk(os.path.join(os.path.dirname(__file__), 'games'), self._find_games, None)
@@ -64,9 +56,6 @@ class MemosonoActivity(Activity):
logging.debug(gamelist)
self.pv = PlayView(None, self.games[gamelist[0]].pairs)
self.pv.show()
- self.sv = SelectView(gamelist)
- self.sv.connect('entry-selected', self._entry_selected_cb)
- self.sv.show()
self.pservice = presenceservice.get_instance()
self.owner = self.pservice.get_owner()
@@ -219,17 +208,6 @@ class MemosonoActivity(Activity):
game.read(name)
self.games[name.split('.mson')[0]] = game
- def _entry_selected_cb(self, list_view, entry):
- self.pv = PlayView(None, self.games[entry.name].pairs)
- self.pv.show()
-
- def _switch_page(self, notebook, page, page_num, user_param1=None):
- if page_num == 1:
- self.set_canvas(self.pv)
- elif page_num == 0:
- if self.sv != None:
- self.set_canvas(self.sv)
-
def _cleanup_cb(self, data=None):
pass
#self.controler.oscapi.send(('127.0.0.1', 6783), "/CSOUND/quit", [])
diff --git a/playpoints.py b/playpoints.py
deleted file mode 100644
index 84f1b3b..0000000
--- a/playpoints.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import gtk
-import hippo
-import math
-import os
-
-from sugar.graphics import font
-from sugar.graphics import units
-
-class PlayPoints(hippo.CanvasBox, hippo.CanvasItem):
- __gtype_name__ = 'PlayPoints'
- _BORDER_DEFAULT = units.points_to_pixels(1.0)
-
- def __init__(self, name, **kargs):
- hippo.CanvasBox.__init__(self, **kargs)
-
- self.image = os.path.join(os.path.dirname(__file__), 'images/black.png')
-
- self._radius = units.points_to_pixels(5)
- self.props.border_color = 3520189183
- self.props.background_color = 3520189183
- self.props.orientation = hippo.ORIENTATION_VERTICAL
- self.props.border = self._BORDER_DEFAULT
- self.props.border_left = self._radius
- self.props.border_right = self._radius
-
- self.append(self._build_title_box())
- playername = hippo.CanvasText(text=name,
- xalign=hippo.ALIGNMENT_START,
- font_desc=font.DEFAULT_BOLD.get_pango_desc(),
- size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END)
- self.append(playername)
-
- def do_paint_background(self, cr, damaged_box):
- [width, height] = self.get_allocation()
-
- x = self._BORDER_DEFAULT / 2
- y = self._BORDER_DEFAULT / 2
- width -= self._BORDER_DEFAULT
- height -= self._BORDER_DEFAULT
-
- cr.move_to(x + self._radius, y);
- cr.arc(x + width - self._radius, y + self._radius,
- self._radius, math.pi * 1.5, math.pi * 2);
- cr.arc(x + width - self._radius, x + height - self._radius,
- self._radius, 0, math.pi * 0.5);
- cr.arc(x + self._radius, y + height - self._radius,
- self._radius, math.pi * 0.5, math.pi);
- cr.arc(x + self._radius, y + self._radius, self._radius,
- math.pi, math.pi * 1.5);
-
- hippo.cairo_set_source_rgba32(cr, self.props.background_color)
- cr.fill()
-
- def _build_title_box(self):
- hbox = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL)
- hbox.props.spacing = units.points_to_pixels(5)
- hbox.props.padding_top = units.points_to_pixels(5)
- hbox.props.padding_bottom = units.points_to_pixels(5)
-
- self.img_widget = gtk.Image()
- img_pixbuf = gtk.gdk.pixbuf_new_from_file(self.image)
- self.pixbuf = img_pixbuf.scale_simple(100, 100, gtk.gdk.INTERP_BILINEAR)
- self.img_widget.set_from_pixbuf(self.pixbuf)
-
- canvas_widget = hippo.CanvasWidget()
- canvas_widget.props.widget = self.img_widget
- self.img_widget.show()
- hbox.append(canvas_widget)
-
- return hbox
-
-
-
diff --git a/playview.py b/playview.py
index ef3cf96..13bfc45 100644
--- a/playview.py
+++ b/playview.py
@@ -7,11 +7,9 @@ from sugar.graphics import color
from sugar.graphics import font
from playtile import PlayTile
-from playpoints import PlayPoints
-from buddiespanel import BuddiesPanel
class PlayView(hippo.Canvas):
- def __init__(self, oscapi, pairs):
+ def __init__(self, pairs):
hippo.Canvas.__init__(self)
root = hippo.CanvasBox()
@@ -20,24 +18,9 @@ class PlayView(hippo.Canvas):
tilebox = hippo.CanvasBox()
tilebox.props.orientation = hippo.ORIENTATION_VERTICAL
root.append(tilebox)
-
- self.buddies_panel = BuddiesPanel()
- root.append(self.buddies_panel)
-
- '''
- pointsbox = hippo.CanvasBox()
- pointsbox.props.orientation = hippo.ORIENTATION_VERTICAL
- root.append(pointsbox)
-
- point = PlayPoints('erwin')
- pointsbox.append(point)
- point = PlayPoints('richard')
- pointsbox.append(point)
- '''
-
- self.oscapi = oscapi
+
self.tiles = []
- self.turn = 0
+ self.turn = 1
tile_num = 0
numtiles = len(pairs)*2
@@ -59,7 +42,7 @@ class PlayView(hippo.Canvas):
def _button_press_cb(self, tile, event, data=None):
if self.turn:
- self.oscapi.send(('127.0.0.1', 40000), "/MEMOSONO/tile/chosen", [data])
+ print data
else:
print 'it is not your turn'
diff --git a/selectentry.py b/selectentry.py
deleted file mode 100644
index 475ae82..0000000
--- a/selectentry.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import logging
-from gettext import gettext as _
-import datetime
-
-import hippo
-import pango
-
-from sugar.graphics.frame import Frame
-from sugar.graphics.xocolor import XoColor
-from sugar.graphics import font
-from sugar.graphics import color
-from sugar.graphics import units
-
-
-class SelectEntry(Frame):
- _DATE_COL_WIDTH = units.points_to_pixels(150)
- _BUDDIES_COL_WIDTH = units.points_to_pixels(60)
-
- def __init__(self, name):
- Frame.__init__(self)
- self.name = name
- self.props.box_height = units.grid_to_pixels(1)
- self.props.spacing = units.points_to_pixels(5)
-
- self.props.border_color = color.FRAME_BORDER.get_int()
- self.props.background_color = color.FRAME_BORDER.get_int()
- logging.debug('FRAME_COLOR %s'%color.FRAME_BORDER.get_int())
-
- title = hippo.CanvasText(text=self.name,
- xalign=hippo.ALIGNMENT_START,
- font_desc=font.DEFAULT_BOLD.get_pango_desc(),
- size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END)
- self.append(title)
-
diff --git a/selectview.py b/selectview.py
deleted file mode 100644
index 3975363..0000000
--- a/selectview.py
+++ /dev/null
@@ -1,54 +0,0 @@
-import hippo
-import os
-import gobject
-import gtk
-
-from sugar.graphics import color
-
-from selectentry import SelectEntry
-
-class SelectView(gtk.ScrolledWindow):
- __gtype_name__ = 'SelectView'
-
- __gsignals__ = {
- 'entry-selected': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([object]))
- }
-
- _SELECTED = 1000000
- _UNSELECTED = 3520189183
- def __init__(self, names):
- gtk.ScrolledWindow.__init__(self)
-
- root = hippo.CanvasBox()
- root.props.orientation = hippo.ORIENTATION_VERTICAL
-
- canvas = hippo.Canvas()
- canvas.set_root(root)
- self.add_with_viewport(canvas)
-
- self.tiles = []
- self.turn = 0
- self.current = 0
-
- for name in names:
- entry = SelectEntry(name)
- entry.connect('button-press-event', self._button_press_cb)
- root.append(entry)
- if name == names[0]:
- self.current = entry
- entry.props.background_color = self._SELECTED
- entry.emit_paint_needed(0, 0, -1, -1)
-
- canvas.show()
-
- def _button_press_cb(self, entry, event, data=None):
- entry.props.background_color = self._SELECTED
- entry.emit_paint_needed(0, 0, -1, -1)
-
- self.current.props.background_color = self._UNSELECTED
- self.current.emit_paint_needed(0, 0, -1, -1)
- self.current = entry
- self.emit('entry-selected', entry)
-
diff --git a/tubeconn.py b/tubeconn.py
new file mode 100644
index 0000000..d1c1403
--- /dev/null
+++ b/tubeconn.py
@@ -0,0 +1,107 @@
+# 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
+
+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.bus_name_to_handle = {}
+ 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
+ match = self._tubes_iface.connect_to_signal('DBusNamesChanged',
+ self._on_dbus_names_changed)
+ self._tubes_iface.GetDBusNames(self.tube_id,
+ reply_handler=self._on_get_dbus_names_reply,
+ error_handler=self._on_get_dbus_names_error)
+ 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()
+ self._on_dbus_names_changed(self.tube_id, (), self.participants.keys())
+ 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
+ self.bus_name_to_handle[bus_name] = handle
+
+ # call the callback while the removed people are still in
+ # participants, so their bus names are available
+ for callback in self._mapping_watches:
+ callback(added, removed)
+
+ for handle in removed:
+ bus_name = self.participants.pop(handle, None)
+ self.bus_name_to_handle.pop(bus_name, None)
+
+ 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, [])