From 6b66d6c927518508b3ca6f4aa13cea630790026e Mon Sep 17 00:00:00 2001 From: Simon Schampijer Date: Sat, 30 Jun 2007 12:53:15 +0000 Subject: cleaning the tree --- 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. +# +# 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, []) -- cgit v0.9.1