diff options
Diffstat (limited to 'messenger.py')
-rw-r--r-- | messenger.py | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/messenger.py b/messenger.py new file mode 100644 index 0000000..658ee08 --- /dev/null +++ b/messenger.py @@ -0,0 +1,232 @@ +# Copyright (C) 2006, 2007, 2008 One Laptop Per Child +# +# 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 logging +_logger = logging.getLogger('memorize-activity') + +import tempfile +from os import environ, chmod +from os.path import join, getsize, dirname, basename +from dbus.service import method, signal +from dbus.gobject_service import ExportedGObject +from sugar.datastore import datastore +from gettext import gettext as _ + +SERVICE = 'org.laptop.Memorize' +IFACE = SERVICE +PATH = '/org/laptop/Memorize' + +class Messenger(ExportedGObject): + + def __init__(self, tube, is_initiator, get_buddy, game): + ExportedGObject.__init__(self, tube, PATH) + self._tube = tube + self.is_initiator = is_initiator + self._get_buddy = get_buddy + self.game = game + self.ordered_bus_names = [] + self.entered = False + self._tube.watch_participants(self.participant_change_cb) + self.files = {} + + def participant_change_cb(self, added, removed): + if not self.entered: + if self.is_initiator: + self._flip_handler() + self._change_game_handler() + self._file_part_handler() + + self.player_id = self._tube.get_unique_name() + self.ordered_bus_names = [self.player_id] + self._hello_handler() + else: + self._hello_signal() + self.entered = True + + # hello methods + + @signal(IFACE, signature='') + def _hello_signal(self): + pass + + def _hello_handler(self): + self._tube.add_signal_receiver(self._hello_receiver, + '_hello_signal', + IFACE, + path=PATH, + sender_keyword='sender') + + def _hello_receiver(self, sender=None): + self.ordered_bus_names.append(sender) + data = self.game.model.data + path = data['game_file'] + if self.game.model.data['mode'] == 'file': + title = data.get('title', 'Received game') + color = data.get('color', '#ff00ff,#00ff00') + self.file_sender(sender, path, title, color) + + remote_object = self._tube.get_object(sender, PATH) + remote_object.load_game(self.ordered_bus_names, + self.game.get_grid(), + self.game.collect_data(), + self.game.players.index(self.game.current_player), + #self.game.waiting_players, + path) + + @method(dbus_interface=IFACE, in_signature='asaa{ss}a{ss}ns', + out_signature='', byte_arrays=True) + def load_game(self, bus_names, grid, data, current_player, path): + self.ordered_bus_names = bus_names + self.player_id = bus_names.index(self._tube.get_unique_name()) + #self.game.load_waiting_list(list) + self._change_game_receiver(data['mode'], grid, data, path) + + for i in range(len(self.game.players)): + self.game.increase_point(self.game.players[i], + int(data.get(str(i), '0'))) + + self.game.current_player = self.game.players[current_player] + self.game.update_turn() + + self._flip_handler() + self._change_game_handler() + self._file_part_handler() + + def change_game(self, sender, mode, grid, data, waiting_list, zip): + path = self.game.model.data['game_file'] + + if mode == 'file': + title = data.get('title', 'Received game') + color = data.get('color', '') + self.file_sender('all', path, title, color) + + self._change_game_signal(mode, grid, data, path) + + def _change_game_handler(self): + self._tube.add_signal_receiver(self._change_game_receiver, + '_change_game_signal', + IFACE, path=PATH, + sender_keyword='sender', + byte_arrays=True) + + @signal(IFACE, signature='saa{ss}a{ss}s') + def _change_game_signal(self, mode, grid, data, path): + pass + + def _change_game_receiver(self, mode, grid, data, path, sender=None): + # ignore my own signal + if sender == self._tube.get_unique_name(): + return + if mode == 'demo': + game_name = basename(data.get('game_file', 'debug-demo')) + game_file = join(dirname(__file__), 'demos', + game_name).encode('ascii') + self.game.model.read(game_file) + if mode == 'file': + self.game.model.read(self.files[path]) + + if self.game.model.data.has_key('path'): + data['path'] = self.game.model.data['path'] + data['pathimg'] = self.game.model.data['pathimg'] + data['pathsnd'] = self.game.model.data['pathsnd'] + self.game.load_remote(grid, data, mode, True) + + # File transfer methods + + def file_sender(self, target, filename, title, color): + size = getsize(filename) + f = open(filename, 'rb') + part_size = 8192 + num_parts = (size / part_size) + 1 + for part in range(num_parts): + bytes = f.read(part_size) + self._file_part_signal(target, filename, part + 1, + num_parts, bytes, title, color) + f.close() + + @signal(dbus_interface=IFACE, signature='ssuuayss') + def _file_part_signal(self, target, filename, part, numparts, + bytes, title, color): + pass + + def _file_part_handler(self): + self._tube.add_signal_receiver(self._file_part_receiver, + '_file_part_signal', + IFACE, + path=PATH, + sender_keyword='sender', + byte_arrays=True) + + def _file_part_receiver(self, target, filename, part, numparts, + bytes, title=None, color=None, sender=None): + # ignore my own signal + if sender == self._tube.get_unique_name(): + return + + if not (target == 'all' or target == self._tube.get_unique_name()): + return + + # first chunk + if part == 1: + tmp_root = join(environ['SUGAR_ACTIVITY_ROOT'], 'instance') + temp_dir = tempfile.mkdtemp(dir=tmp_root) + chmod(temp_dir, 0777) + self.temp_file = join(temp_dir, 'game.zip') + self.files[filename] = self.temp_file + self.f = open(self.temp_file, 'a+b') + + self.f.write(bytes) + + percentage = int(float(part) / float(numparts) * 100.0) + self.game.set_load_mode(_('Receiving game') + ': ' + + str(percentage) + '% ' + _('done') + '.') + + # last chunk + if part == numparts: + self.f.close() + #file = self.files[filename] + # Saves the zip in datastore + gameObject = datastore.create() + gameObject.metadata['title'] = title + gameObject.metadata['mime_type'] = 'application/x-memorize-project' + gameObject.metadata['icon-color'] = color + gameObject.file_path = self.temp_file + datastore.write(gameObject) + #gameObject.destroy() + + + # flip card methods + + def flip_sender(self, widget, id): + self._flip_signal(id) + + def _flip_handler(self): + self._tube.add_signal_receiver(self._flip_receiver, + '_flip_signal', + IFACE, + path=PATH, + sender_keyword='sender') + + @signal(IFACE, signature='n') + def _flip_signal(self, card_number): + pass + + def _flip_receiver(self, card_number, sender=None): + # ignore my own signal + if sender == self._tube.get_unique_name(): + return + self.game.card_flipped(None, card_number, True) |