diff options
Diffstat (limited to 'gtk2/StoryActivity.py')
-rw-r--r-- | gtk2/StoryActivity.py | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/gtk2/StoryActivity.py b/gtk2/StoryActivity.py deleted file mode 100644 index ef5e37d..0000000 --- a/gtk2/StoryActivity.py +++ /dev/null @@ -1,404 +0,0 @@ -#Copyright (c) 2012 Walter Bender - -# 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 3 of the License, or -# (at your option) any later version. -# -# You should have received a copy of the GNU General Public License -# along with this library; if not, write to the Free Software -# Foundation, 51 Franklin Street, Suite 500 Boston, MA 02110-1335 USA - - -import gtk -import gobject -import subprocess -import cairo -import os -import time - -from sugar.activity import activity -from sugar import profile -from sugar.datastore import datastore -try: - from sugar.graphics.toolbarbox import ToolbarBox - _have_toolbox = True -except ImportError: - _have_toolbox = False - -if _have_toolbox: - from sugar.activity.widgets import ActivityToolbarButton - from sugar.activity.widgets import StopButton - -from sugar.graphics.alert import Alert - -from toolbar_utils import button_factory, label_factory, separator_factory -from utils import json_load, json_dump, play_audio_from_file -from grecord import Grecord - -import telepathy -import dbus -from dbus.service import signal -from dbus.gobject_service import ExportedGObject -from sugar.presence import presenceservice -from sugar.presence.tubeconn import TubeConnection - -from gettext import gettext as _ - -from game import Game - -import logging -_logger = logging.getLogger('story-activity') - - -SERVICE = 'org.sugarlabs.StoryActivity' -IFACE = SERVICE - - -class StoryActivity(activity.Activity): - """ Storytelling game """ - - def __init__(self, handle): - """ Initialize the toolbars and the game board """ - try: - super(StoryActivity, self).__init__(handle) - except dbus.exceptions.DBusException, e: - _logger.error(str(e)) - - self.path = activity.get_bundle_path() - - self.nick = profile.get_nick_name() - if profile.get_color() is not None: - self.colors = profile.get_color().to_string().split(',') - else: - self.colors = ['#A0FFA0', '#FF8080'] - - self._recording = False - self._grecord = None - self._alert = None - - self._setup_toolbars(_have_toolbox) - self._setup_dispatch_table() - - # Create a canvas - canvas = gtk.DrawingArea() - canvas.set_size_request(gtk.gdk.screen_width(), \ - gtk.gdk.screen_height()) - self.set_canvas(canvas) - canvas.show() - self.show_all() - - self._game = Game(canvas, parent=self, path=self.path, - colors=self.colors) - self._setup_presence_service() - - if 'dotlist' in self.metadata: - self._restore() - else: - self._game.new_game() - - def _setup_toolbars(self, have_toolbox): - """ Setup the toolbars. """ - - self.max_participants = 9 - - if have_toolbox: - toolbox = ToolbarBox() - - # Activity toolbar - activity_button = ActivityToolbarButton(self) - - toolbox.toolbar.insert(activity_button, 0) - activity_button.show() - - self.set_toolbar_box(toolbox) - toolbox.show() - self.toolbar = toolbox.toolbar - - else: - # Use pre-0.86 toolbar design - games_toolbar = gtk.Toolbar() - toolbox = activity.ActivityToolbox(self) - self.set_toolbox(toolbox) - toolbox.add_toolbar(_('Game'), games_toolbar) - toolbox.show() - toolbox.set_current_toolbar(1) - self.toolbar = games_toolbar - - self._new_game_button_h = button_factory( - 'view-refresh', self.toolbar, self._new_game_cb, - tooltip=_('Load new images.')) - - separator_factory(self.toolbar) - - self.save_as_image = button_factory( - 'image-saveoff', self.toolbar, self._do_save_as_image_cb, - tooltip=_('Save as image')) - - separator_factory(self.toolbar) - - self._record_button = button_factory( - 'media-record', self.toolbar, - self._record_cb, tooltip=_('Start recording')) - - self._playback_button = button_factory( - 'media-playback-start-insensitive', self.toolbar, - self._playback_recording_cb, tooltip=_('Nothing to play')) - - if _have_toolbox: - separator_factory(toolbox.toolbar, True, False) - - if _have_toolbox: - stop_button = StopButton(self) - stop_button.props.accelerator = '<Ctrl>q' - toolbox.toolbar.insert(stop_button, -1) - stop_button.show() - - def _new_game_cb(self, button=None): - ''' Start a new game. ''' - self._game.new_game() - - def write_file(self, file_path): - """ Write the grid status to the Journal """ - dot_list = self._game.save_game() - self.metadata['dotlist'] = '' - for dot in dot_list: - self.metadata['dotlist'] += str(dot) - if dot_list.index(dot) < len(dot_list) - 1: - self.metadata['dotlist'] += ' ' - - def _restore(self): - """ Restore the game state from metadata """ - dot_list = [] - dots = self.metadata['dotlist'].split() - for dot in dots: - dot_list.append(int(dot)) - self._game.restore_game(dot_list) - - def _do_save_as_image_cb(self, button=None): - """ Grab the current canvas and save it to the Journal. """ - self._notify_successful_save(title=_('Save as image')) - file_path = os.path.join(activity.get_activity_root(), - 'instance', 'story.png') - png_surface = self._game.export() - png_surface.write_to_png(file_path) - - dsobject = datastore.create() - dsobject.metadata['title'] = "%s %s" % \ - (self.metadata['title'], _("image")) - dsobject.metadata['icon-color'] = profile.get_color().to_string() - dsobject.metadata['mime_type'] = 'image/png' - dsobject.set_file_path(file_path) - datastore.write(dsobject) - dsobject.destroy() - os.remove(file_path) - if self._alert is not None: - self.remove_alert(self._alert) - self._alert = None - - def _record_cb(self, button=None): - ''' Start/stop audio recording ''' - if self._grecord is None: - _logger.debug('setting up grecord') - self._grecord = Grecord(self) - if self._recording: # Was recording, so stop (and save?) - _logger.debug('recording...True. Preparing to save.') - self._grecord.stop_recording_audio() - self._recording = False - self._record_button.set_icon('media-record') - self._record_button.set_tooltip(_('Start recording')) - self._playback_button.set_icon('media-playback-start') - self._playback_button.set_tooltip(_('Play recording')) - self._notify_successful_save(title=_('Save recording')) - gobject.timeout_add(100, self._wait_for_transcoding_to_finish) - else: # Wasn't recording, so start - _logger.debug('recording...False. Start recording.') - self._grecord.record_audio() - self._recording = True - self._record_button.set_icon('media-recording') - self._record_button.set_tooltip(_('Stop recording')) - - def _wait_for_transcoding_to_finish(self, button=None): - while not self._grecord.transcoding_complete(): - time.sleep(1) - if self._alert is not None: - self.remove_alert(self._alert) - self._alert = None - self._save_recording() - - def _playback_recording_cb(self, button=None): - ''' Play back current recording ''' - _logger.debug('Playback current recording from output.ogg...') - play_audio_from_file(os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg')) - return - - def _save_recording(self): - if os.path.exists(os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg')): - _logger.debug('Saving recording to Journal...') - dsobject = datastore.create() - dsobject.metadata['title'] = _('audio note for %s') % \ - (self.metadata['title']) - dsobject.metadata['icon-color'] = profile.get_color().to_string() - dsobject.metadata['mime_type'] = 'audio/ogg' - _logger.debug('setting file path to %s' % ( - os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg'))) - dsobject.set_file_path(os.path.join(activity.get_activity_root(), - 'instance', 'output.ogg')) - datastore.write(dsobject) - dsobject.destroy() - # Always save an image with the recording. - self._do_save_as_image_cb() - else: - _logger.debug('Nothing to save...') - return - - def _notify_successful_save(self, title='', msg=''): - ''' Notify user when saves are completed ''' - self._alert = Alert() - self._alert.props.title = title - self._alert.props.msg = msg - self.add_alert(self._alert) - self._alert.show() - - # Collaboration-related methods - - def _setup_presence_service(self): - """ Setup the Presence Service. """ - self.pservice = presenceservice.get_instance() - self.initiating = None # sharing (True) or joining (False) - - owner = self.pservice.get_owner() - self.owner = owner - self._share = "" - self.connect('shared', self._shared_cb) - self.connect('joined', self._joined_cb) - - def _shared_cb(self, activity): - """ Either set up initial share...""" - self._new_tube_common(True) - - def _joined_cb(self, activity): - """ ...or join an exisiting share. """ - self._new_tube_common(False) - - def _new_tube_common(self, sharer): - """ Joining and sharing are mostly the same... """ - if self._shared_activity is None: - _logger.debug("Error: Failed to share or join activity ... \ - _shared_activity is null in _shared_cb()") - return - - self.initiating = sharer - self.waiting_for_hand = not sharer - - self.conn = self._shared_activity.telepathy_conn - self.tubes_chan = self._shared_activity.telepathy_tubes_chan - self.text_chan = self._shared_activity.telepathy_text_chan - - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( - 'NewTube', self._new_tube_cb) - - if sharer: - _logger.debug('This is my activity: making a tube...') - id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( - SERVICE, {}) - else: - _logger.debug('I am joining an activity: waiting for a tube...') - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( - reply_handler=self._list_tubes_reply_cb, - error_handler=self._list_tubes_error_cb) - self._game.set_sharing(True) - - def _list_tubes_reply_cb(self, tubes): - """ Reply to a list request. """ - for tube_info in tubes: - self._new_tube_cb(*tube_info) - - def _list_tubes_error_cb(self, e): - """ Log errors. """ - _logger.debug('Error: ListTubes() failed: %s' % (e)) - - def _new_tube_cb(self, id, initiator, type, service, params, state): - """ Create a new tube. """ - _logger.debug('New tube: ID=%d initator=%d type=%d service=%s \ -params=%r state=%d' % (id, initiator, type, service, params, state)) - - if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE): - if state == telepathy.TUBE_STATE_LOCAL_PENDING: - self.tubes_chan[ \ - telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) - - tube_conn = TubeConnection(self.conn, - self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, \ - group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) - - self.chattube = ChatTube(tube_conn, self.initiating, \ - self.event_received_cb) - - def _setup_dispatch_table(self): - ''' Associate tokens with commands. ''' - self._processing_methods = { - 'n': [self._receive_new_game, 'get a new game grid'], - 'p': [self._receive_dot_click, 'get a dot click'], - } - - def event_received_cb(self, event_message): - ''' Data from a tube has arrived. ''' - if len(event_message) == 0: - return - try: - command, payload = event_message.split('|', 2) - except ValueError: - _logger.debug('Could not split event message %s' % (event_message)) - return - self._processing_methods[command][0](payload) - - def send_new_game(self): - ''' Send a new grid to all players ''' - self.send_event('n|%s' % (json_dump(self._game.save_game()))) - - def _receive_new_game(self, payload): - ''' Sharer can start a new game. ''' - dot_list = json_load(payload) - self._game.restore_game(dot_list) - - def send_dot_click(self, dot, color): - ''' Send a dot click to all the players ''' - self.send_event('p|%s' % (json_dump([dot, color]))) - - def _receive_dot_click(self, payload): - ''' When a dot is clicked, everyone should change its color. ''' - (dot, color) = json_load(payload) - self._game.remote_button_press(dot, color) - - def send_event(self, entry): - """ Send event through the tube. """ - if hasattr(self, 'chattube') and self.chattube is not None: - self.chattube.SendText(entry) - - -class ChatTube(ExportedGObject): - """ Class for setting up tube for sharing """ - - def __init__(self, tube, is_initiator, stack_received_cb): - super(ChatTube, self).__init__(tube, PATH) - self.tube = tube - self.is_initiator = is_initiator # Are we sharing or joining activity? - self.stack_received_cb = stack_received_cb - self.stack = '' - - self.tube.add_signal_receiver(self.send_stack_cb, 'SendText', IFACE, - path=PATH, sender_keyword='sender') - - def send_stack_cb(self, text, sender=None): - if sender == self.tube.get_unique_name(): - return - self.stack = text - self.stack_received_cb(text) - - @signal(dbus_interface=IFACE, signature='s') - def SendText(self, text): - self.stack = text |