Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/messenger.py
diff options
context:
space:
mode:
Diffstat (limited to 'messenger.py')
-rw-r--r--messenger.py232
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)